From 16f2816e812b492df8181fc4fc595b6d760df13a Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Fri, 4 Sep 2020 09:08:17 -0300 Subject: [PATCH] Make 'arg' semantics more Lua like --- lib/allocators/gc.nelua | 9 +++------ lib/arg.nelua | 40 ++++++++++++++++++++----------------- lib/string.nelua | 1 - nelua/cgenerator.lua | 6 +++--- spec/05-cgenerator_spec.lua | 14 ++++++------- spec/08-runner_spec.lua | 10 ++++++++++ 6 files changed, 45 insertions(+), 35 deletions(-) diff --git a/lib/allocators/gc.nelua b/lib/allocators/gc.nelua index 6e4177b3..32b25468 100644 --- a/lib/allocators/gc.nelua +++ b/lib/allocators/gc.nelua @@ -531,15 +531,12 @@ function GC:_mark_statics() ]] end -local function nelua_main(): cint end +local function nelua_main(argc: cint, argv: cstring*): cint end -global arg: span(cstring) - -local function main(argc: cint, argv: cchar**): cint +local function main(argc: cint, argv: cstring*): cint gc:start(&argc) gc:_mark_statics() - arg = {data=argv, size=argc} - local ret: cint = nelua_main() + local ret: cint = nelua_main(argc, argv) gc:stop() return ret end diff --git a/lib/arg.nelua b/lib/arg.nelua index 34724210..f8e99903 100644 --- a/lib/arg.nelua +++ b/lib/arg.nelua @@ -1,21 +1,25 @@ -- Include this file to get have the global "arg" --- with your program command line arguments. - -## if pragmas.nogc then - -require 'span' - -global arg: span(cstring) - -local function nelua_main(): cint end - -local function main(argc: cint, argv: cchar**): cint - arg = {data=argv, size=argc} - return nelua_main() +-- filled with your program command line arguments. + +require 'sequence' +require 'allocators.general' + +-- Import argc and argv from C 'nelua_main' +local nelua_argc: cint +local nelua_argv: cstring[0]* + +-- List of command line arguments. +-- The index 0 usually is filled with the program executable. +-- The arguments goes from 1 up to #arg (like in Lua). +global arg: sequence(stringview, GeneralAllocator) + +do -- setup args + local narg: usize = (@usize)(nelua_argc-1) + arg:reserve(narg) + for i:usize=0,narg do + arg[i] = nelua_argv[i] + end end -## else - -require 'allocators.gc' - -## end +-- NOTE: the memory of 'arg' is never freed, +-- but this is fine, is not a leak for global variables. diff --git a/lib/string.nelua b/lib/string.nelua index ae1fc1f4..c9394e47 100644 --- a/lib/string.nelua +++ b/lib/string.nelua @@ -50,7 +50,6 @@ function string._create(size: usize): string self.data = (@byte[0]*)(string_allocator:alloc(size+1)) check(self.data ~= nilptr, 'string._create: out of memory') self.data[size] = 0 - --self.refs = 1 return self end diff --git a/nelua/cgenerator.lua b/nelua/cgenerator.lua index 6bd32d0e..94080120 100644 --- a/nelua/cgenerator.lua +++ b/nelua/cgenerator.lua @@ -1400,7 +1400,7 @@ local function emit_main(ast, context) if not context.entrypoint or context.hookmain then mainemitter:inc_indent() - mainemitter:add_ln("int nelua_main() {") + mainemitter:add_ln("int nelua_main(int nelua_argc, char** nelua_argv) {") mainemitter:add_traversal(ast) if not context.rootscope.has_return then -- main() must always return an integer @@ -1411,7 +1411,7 @@ local function emit_main(ast, context) mainemitter:add_ln("}") mainemitter:dec_indent() - context:add_declaration('int nelua_main();\n') + context:add_declaration('int nelua_main(int nelua_argc, char** nelua_argv);\n') else mainemitter:inc_indent() mainemitter:add_traversal(ast) @@ -1421,7 +1421,7 @@ local function emit_main(ast, context) if not context.entrypoint then mainemitter:add_indent_ln('int main(int argc, char **argv) {') mainemitter:inc_indent(2) - mainemitter:add_indent_ln('return nelua_main();') + mainemitter:add_indent_ln('return nelua_main(argc, argv);') mainemitter:dec_indent(2) mainemitter:add_indent_ln('}') end diff --git a/spec/05-cgenerator_spec.lua b/spec/05-cgenerator_spec.lua index e90b6ed5..a7034f19 100644 --- a/spec/05-cgenerator_spec.lua +++ b/spec/05-cgenerator_spec.lua @@ -8,18 +8,18 @@ describe("Nelua should parse and generate C", function() it("empty file", function() assert.generate_c("", [[ -int nelua_main() { +int nelua_main(int nelua_argc, char** nelua_argv) { return 0; }]]) end) it("return", function() assert.generate_c("return", [[ -int nelua_main() { +int nelua_main(int nelua_argc, char** nelua_argv) { return 0; }]]) assert.generate_c("return 1", [[ -int nelua_main() { +int nelua_main(int nelua_argc, char** nelua_argv) { return 1; }]]) assert.generate_c("return 1") @@ -2061,11 +2061,11 @@ end) it("hook main", function() assert.run_c([[ - local function nelua_main(): cint end - local function main(argc: cint, argv: cchar**): cint + local function nelua_main(argc: cint, nelua_argv: cstring*): cint end + local function main(argc: cint, argv: cstring*): cint print 'before' - local ret = nelua_main() - print('after') + local ret = nelua_main(argc, argv) + print 'after' return ret end print 'inside' diff --git a/spec/08-runner_spec.lua b/spec/08-runner_spec.lua index 487fd2dd..b9bcdf8e 100644 --- a/spec/08-runner_spec.lua +++ b/spec/08-runner_spec.lua @@ -126,4 +126,14 @@ it("debug options", function() ]]}, "scope resolved 1 symbols") end) +it("program arguments", function() + assert.run({'--eval',[[ + require 'arg' + assert(arg[1] == 'a') + assert(arg[2] == 'b') + assert(arg[3] == 'c') + assert(#arg == 3) + ]], 'a', 'b', 'c'}) +end) + end)