From 3fd5687370c3ef28c1878a79f0b4173e7212795f Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 10 Jul 2018 17:10:37 -0700 Subject: [PATCH] Fixed up line numbers for generated code. --- code_obj.lua | 4 +- code_obj.moon | 4 +- core/collections.nom | 2 - nomsu.lua | 35 ++++++++++++------ nomsu.moon | 21 ++++++----- nomsu.peg | 22 +++++------ nomsu_compiler.lua | 87 +++++++++++++++++++++++++------------------- nomsu_compiler.moon | 75 +++++++++++++++++++++----------------- tests/text.nom | 2 +- 9 files changed, 143 insertions(+), 109 deletions(-) diff --git a/code_obj.lua b/code_obj.lua index 7fa91fc..cc2fb69 100644 --- a/code_obj.lua +++ b/code_obj.lua @@ -85,7 +85,7 @@ do local _continue_0 = false repeat local b = select(i, ...) - assert(b) + assert(b, "bit is nil") if b == '' then _continue_0 = true break @@ -176,7 +176,7 @@ do if type(self.source) == 'string' then self.source = Source:from_string(self.source) end - assert(self.source and Source:is_instance(self.source)) + assert(self.source and Source:is_instance(self.source), "Source has the wrong type") return self:append(...) end, __base = _base_0, diff --git a/code_obj.moon b/code_obj.moon index 74e9a15..8ac7146 100644 --- a/code_obj.moon +++ b/code_obj.moon @@ -48,7 +48,7 @@ class Code @bits, @indents, @current_indent = {}, {}, 0 if type(@source) == 'string' @source = Source\from_string(@source) - assert(@source and Source\is_instance(@source)) + assert(@source and Source\is_instance(@source), "Source has the wrong type") @append(...) append: (...)=> @@ -57,7 +57,7 @@ class Code match = string.match for i=1,n b = select(i, ...) - assert(b) + assert(b, "bit is nil") if b == '' then continue bits[#bits+1] = b if type(b) == 'string' diff --git a/core/collections.nom b/core/collections.nom index 48a4330..367356b 100644 --- a/core/collections.nom +++ b/core/collections.nom @@ -181,8 +181,6 @@ compile [%dict with fallback %key -> %value] to return value end}) -test: assume: 1 is 2 - # Sorting compile [sort %items] to: Lua "table.sort(\(%items as lua expr));" parse [..] diff --git a/nomsu.lua b/nomsu.lua index ad41446..6080637 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -160,7 +160,10 @@ run = function() local tests = { } if args.run_tests then nomsu.COMPILE_ACTIONS["test %"] = function(self, tree, _body) - table.insert(tests, _body) + if not (tests[tree.source.filename]) then + tests[tree.source.filename] = { } + end + table.insert(tests[tree.source.filename], _body) return LuaCode("") end end @@ -190,7 +193,7 @@ run = function() end local file, source = get_file_and_source(filename) if not (file) then - return nil + return end local tree = nomsu:parse(file, source) if tree then @@ -199,25 +202,25 @@ run = function() tree } end - tests = { } for _index_0 = 1, #tree do local chunk = tree[_index_0] local lua = nomsu:compile(chunk):as_statements("return ") lua:declare_locals() lua:prepend("-- File: " .. tostring(source.filename:gsub("\n.*", "...")) .. "\n") - if lua_handler then + if lua_handler and input_files[filename] then lua_handler(tostring(lua)) end nomsu:run_lua(lua) end - if args.run_tests and #tests > 0 then - for _index_0 = 1, #tests do - local t = tests[_index_0] + if args.run_tests and tests[filename] and input_files[filename] then + local _list_0 = tests[filename] + for _index_0 = 1, #_list_0 do + local t = _list_0[_index_0] local lua = nomsu:compile(t) if lua_handler then lua_handler(tostring(lua)) end - nomsu:run_lua(lua) + nomsu:run_lua(lua, t.source) end end end @@ -228,6 +231,10 @@ run = function() for filename in files.walk(f) do local _continue_0 = false repeat + if not (filename == "stdin" or filename:match("%.nom$")) then + _continue_0 = true + break + end if args.check_syntax then local file, source = get_file_and_source(filename) if not (file) then @@ -276,7 +283,6 @@ action [help] say ".." \(bright)\(underscore)Welcome to the Nomsu v\(Nomsu version) interactive console!\(reset color) - press 'enter' twice to run a command \("")]]) for repl_line = 1, math.huge do @@ -316,11 +322,18 @@ say ".." end end end -local debugger = require(args.debugger or 'error_handling') +local debugger +if args.debugger == "nil" then + debugger = { } +else + debugger = require(args.debugger or 'error_handling') +end local guard if type(debugger) == 'function' then guard = debugger else - guard = debugger.guard or debugger.call or debugger.wrap or debugger.run + guard = debugger.guard or debugger.call or debugger.wrap or debugger.run or (function(fn) + return fn() + end) end return guard(run) diff --git a/nomsu.moon b/nomsu.moon index 2aaf058..cba9eee 100755 --- a/nomsu.moon +++ b/nomsu.moon @@ -106,7 +106,8 @@ run = -> tests = {} if args.run_tests nomsu.COMPILE_ACTIONS["test %"] = (tree, _body)=> - table.insert tests, _body + unless tests[tree.source.filename] then tests[tree.source.filename] = {} + table.insert tests[tree.source.filename], _body return LuaCode "" get_file_and_source = (filename)-> @@ -126,7 +127,7 @@ run = -> run_file = (filename, lua_handler=nil)-> file, source = get_file_and_source(filename) - return nil unless file + return unless file tree = nomsu\parse(file, source) if tree if tree.type != "FileChunks" @@ -134,22 +135,22 @@ run = -> -- Each chunk's compilation is affected by the code in the previous chunks -- (typically), so each chunk needs to compile and run before the next one -- compiles. - tests = {} for chunk in *tree lua = nomsu\compile(chunk)\as_statements("return ") lua\declare_locals! lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n" - if lua_handler then lua_handler(tostring(lua)) + if lua_handler and input_files[filename] then lua_handler(tostring(lua)) nomsu\run_lua(lua) - if args.run_tests and #tests > 0 - for t in *tests + if args.run_tests and tests[filename] and input_files[filename] + for t in *tests[filename] lua = nomsu\compile(t) if lua_handler then lua_handler(tostring(lua)) - nomsu\run_lua(lua) + nomsu\run_lua(lua, t.source) parse_errs = {} for f in *file_queue for filename in files.walk(f) + continue unless filename == "stdin" or filename\match("%.nom$") if args.check_syntax -- Check syntax file, source = get_file_and_source(filename) @@ -186,7 +187,6 @@ action [help] say ".." \(bright)\(underscore)Welcome to the Nomsu v\(Nomsu version) interactive console!\(reset color) - press 'enter' twice to run a command \("")]] for repl_line=1,math.huge @@ -217,7 +217,8 @@ say ".." elseif not ok Errhand.print_error ret -debugger = require(args.debugger or 'error_handling') +debugger = if args.debugger == "nil" then {} +else require(args.debugger or 'error_handling') guard = if type(debugger) == 'function' then debugger -else debugger.guard or debugger.call or debugger.wrap or debugger.run +else debugger.guard or debugger.call or debugger.wrap or debugger.run or ((fn)->fn()) guard(run) diff --git a/nomsu.peg b/nomsu.peg index 2497e7c..8b4d9ec 100644 --- a/nomsu.peg +++ b/nomsu.peg @@ -85,15 +85,6 @@ inline_text (Text): (({} (eol->'Line ended before finding a closing double quotation mark') %userdata) => error) /(({} ([^%nl]*->'Unexpected character while parsing Text') %userdata) => error) )) - --- Have to use "%indent" instead of "indent" etc. to avoid messing up text lines that start with "#" -indented_text (Text): - '".."' eol %nl {| - {~ (%nl*) (%indent -> "") ~} - ({~ - (("\\" -> "\") / (("\" nodent "..") -> "")/ (%nl+ {~ %nodent -> "" ~}) / [^%nl\] / (!text_interpolation "\"))+ - ~} / text_interpolation)* - |} (((!.) %dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Unexpected character while parsing Text") %userdata) => error)) inline_text_interpolation: "\" ( variable / inline_list / inline_dict / inline_text @@ -105,9 +96,18 @@ inline_text_interpolation: / (({} ([^%nl]* -> 'Unexpected character while parsing Text interpolation') %userdata) => error)) ) ) + +-- Have to use "%indent" instead of "indent" etc. to avoid messing up text lines that start with "#" +indented_text (Text): + '".."' eol %nl {| + {~ (%nl*) (%indent -> "") ~} + (indented_plain_text / text_interpolation / {~ ("\" nodent "..") -> "" ~} / {~ %nl+ (%nodent -> "") ~})* + |} (((!.) %dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Unexpected character while parsing Text") %userdata) => error)) +indented_plain_text (Text): + {| ({~ "\\" -> "\" ~} / {[^%nl\]+} / {!(text_interpolation / "\" nodent "..") "\"})+ + {~ (%nl+ (%nodent -> "")) / (("\" nodent "..") -> "") ~}* |} text_interpolation: - inline_text_interpolation / - ("\" indented_expression nodent "..") + inline_text_interpolation / ("\" indented_expression nodent "..") number (Number): {| (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonumber) |} diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua index b2c034a..ca4b760 100644 --- a/nomsu_compiler.lua +++ b/nomsu_compiler.lua @@ -234,40 +234,38 @@ do end local math_expression = re.compile([[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]]) local add_lua_bits - add_lua_bits = function(self, lua, code) - for _index_0 = 1, #code do - local bit = code[_index_0] - if type(bit) == "string" then - lua:append(bit) - else - local bit_lua = self:compile(bit) - if not (bit_lua.is_value) then - self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.") + add_lua_bits = function(self, val_or_stmt, code) + local cls = val_or_stmt == "value" and LuaCode.Value or LuaCode + local operate_on_text + operate_on_text = function(text) + local lua = cls(text.source) + for _index_0 = 1, #text do + local bit = text[_index_0] + if type(bit) == "string" then + lua:append(bit) + elseif bit.type == "Text" then + lua:append(operate_on_text(bit)) + else + local bit_lua = self:compile(bit) + if not (bit_lua.is_value) then + self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.") + end + lua:append(bit_lua) end - lua:append(bit_lua) end + return lua end - return lua + return operate_on_text(code) end local add_lua_string_bits - add_lua_string_bits = function(self, lua, code) + add_lua_string_bits = function(self, val_or_stmt, code) local line_len = 0 + local cls_str = val_or_stmt == "value" and "LuaCode.Value(" or "LuaCode(" if code.type ~= "Text" then - lua:append(", ", self:compile(code)) - return + return LuaCode(code.source, cls_str, repr(tostring(code.source)), ", ", self:compile(code), ")") end - for _index_0 = 1, #code do - local bit = code[_index_0] - local bit_lua - if type(bit) == "string" then - bit_lua = repr(bit) - else - bit_lua = self:compile(bit) - if not (bit_lua.is_value) then - self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.") - end - bit_lua = bit_lua - end + local add_bit_lua + add_bit_lua = function(lua, bit_lua) line_len = line_len + #tostring(bit_lua) if line_len > MAX_LINE then lua:append(",\n ") @@ -275,8 +273,29 @@ do else lua:append(", ") end - lua:append(bit_lua) + return lua:append(bit_lua) end + local operate_on_text + operate_on_text = function(text) + local lua = LuaCode.Value(text.source, cls_str, repr(tostring(text.source))) + for _index_0 = 1, #text do + local bit = text[_index_0] + if type(bit) == "string" then + add_bit_lua(lua, repr(bit)) + elseif bit.type == "Text" then + add_bit_lua(lua, operate_on_text(bit)) + else + local bit_lua = self:compile(bit) + if not (bit_lua.is_value) then + self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.") + end + add_bit_lua(lua, bit_lua) + end + end + lua:append(")") + return lua + end + return operate_on_text(code) end NomsuCompiler.COMPILE_ACTIONS = setmetatable({ ["# compile math expr #"] = function(self, tree, ...) @@ -301,28 +320,22 @@ do return lua end, ["Lua %"] = function(self, tree, _code) - local lua = LuaCode.Value(tree.source, "LuaCode(", repr(tostring(_code.source))) - add_lua_string_bits(self, lua, _code) - lua:append(")") - return lua + return add_lua_string_bits(self, 'statements', _code) end, ["Lua value %"] = function(self, tree, _code) - local lua = LuaCode.Value(tree.source, "LuaCode.Value(", repr(tostring(_code.source))) - add_lua_string_bits(self, lua, _code) - lua:append(")") - return lua + return add_lua_string_bits(self, 'value', _code) end, ["lua > %"] = function(self, tree, _code) if _code.type ~= "Text" then return LuaCode(tree.source, "nomsu:run_lua(", self:compile(_code), ");") end - return add_lua_bits(self, LuaCode(tree.source), _code) + return add_lua_bits(self, "statements", _code) end, ["= lua %"] = function(self, tree, _code) if _code.type ~= "Text" then return LuaCode.Value(tree.source, "nomsu:run_lua(", self:compile(_code), ":as_statements('return '))") end - return add_lua_bits(self, LuaCode.Value(tree.source), _code) + return add_lua_bits(self, "value", _code) end, ["use %"] = function(self, tree, _path) if _path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string' then diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon index 83c864c..080e3d7 100644 --- a/nomsu_compiler.moon +++ b/nomsu_compiler.moon @@ -137,32 +137,31 @@ with NomsuCompiler -- math expressions like 2*x + 3^2 without having to define a single -- action for every possibility. math_expression = re.compile [[ ([+-] " ")* "%" (" " [*/^+-] (" " [+-])* " %")+ !. ]] - add_lua_bits = (lua, code)=> - for bit in *code - if type(bit) == "string" - lua\append bit - else - bit_lua = @compile(bit) - unless bit_lua.is_value - @compile_error bit, - "Cannot use:\n%s\nas a string interpolation value, since it's not an expression." - lua\append bit_lua - return lua - add_lua_string_bits = (lua, code)=> + add_lua_bits = (val_or_stmt, code)=> + cls = val_or_stmt == "value" and LuaCode.Value or LuaCode + operate_on_text = (text)-> + lua = cls(text.source) + for bit in *text + if type(bit) == "string" + lua\append bit + elseif bit.type == "Text" + lua\append(operate_on_text(bit)) + else + bit_lua = @compile(bit) + unless bit_lua.is_value + @compile_error bit, + "Cannot use:\n%s\nas a string interpolation value, since it's not an expression." + lua\append bit_lua + return lua + return operate_on_text code + + add_lua_string_bits = (val_or_stmt, code)=> line_len = 0 + cls_str = val_or_stmt == "value" and "LuaCode.Value(" or "LuaCode(" if code.type != "Text" - lua\append ", ", @compile(code) - return - for bit in *code - bit_lua = if type(bit) == "string" - repr(bit) - else - bit_lua = @compile(bit) - unless bit_lua.is_value - @compile_error bit, - "Cannot use:\n%s\nas a string interpolation value, since it's not an expression." - bit_lua + return LuaCode(code.source, cls_str, repr(tostring(code.source)), ", ", @compile(code), ")") + add_bit_lua = (lua, bit_lua)-> line_len += #tostring(bit_lua) if line_len > MAX_LINE lua\append ",\n " @@ -170,6 +169,22 @@ with NomsuCompiler else lua\append ", " lua\append bit_lua + operate_on_text = (text)-> + lua = LuaCode.Value(text.source, cls_str, repr(tostring(text.source))) + for bit in *text + if type(bit) == "string" + add_bit_lua(lua, repr(bit)) + elseif bit.type == "Text" + add_bit_lua(lua, operate_on_text(bit)) + else + bit_lua = @compile(bit) + unless bit_lua.is_value + @compile_error bit, + "Cannot use:\n%s\nas a string interpolation value, since it's not an expression." + add_bit_lua(lua, bit_lua) + lua\append ")" + return lua + return operate_on_text code .COMPILE_ACTIONS = setmetatable { ["# compile math expr #"]: (tree, ...)=> @@ -189,26 +204,20 @@ with NomsuCompiler return lua ["Lua %"]: (tree, _code)=> - lua = LuaCode.Value(tree.source, "LuaCode(", repr(tostring _code.source)) - add_lua_string_bits(@, lua, _code) - lua\append ")" - return lua + return add_lua_string_bits(@, 'statements', _code) ["Lua value %"]: (tree, _code)=> - lua = LuaCode.Value(tree.source, "LuaCode.Value(", repr(tostring _code.source)) - add_lua_string_bits(@, lua, _code) - lua\append ")" - return lua + return add_lua_string_bits(@, 'value', _code) ["lua > %"]: (tree, _code)=> if _code.type != "Text" return LuaCode tree.source, "nomsu:run_lua(", @compile(_code), ");" - return add_lua_bits(@, LuaCode(tree.source), _code) + return add_lua_bits(@, "statements", _code) ["= lua %"]: (tree, _code)=> if _code.type != "Text" return LuaCode.Value tree.source, "nomsu:run_lua(", @compile(_code), ":as_statements('return '))" - return add_lua_bits(@, LuaCode.Value(tree.source), _code) + return add_lua_bits(@, "value", _code) ["use %"]: (tree, _path)=> if _path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string' diff --git a/tests/text.nom b/tests/text.nom index 4b7f952..39ee496 100644 --- a/tests/text.nom +++ b/tests/text.nom @@ -24,7 +24,7 @@ assume ((%こんにちは と言う) = "こんにちは世界") or barf "Unicode %s <- ".." one two\nthree\ ..four -assume (%s = "one two\\nthreefour") +assume (%s = "one two\\nthreefour") or barf "%s = \(quote %s), not \(quote "one two\\nthreefour")" %s <- ".." list:\[..] 1,2,3