aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code_obj.lua4
-rw-r--r--code_obj.moon2
-rw-r--r--core/collections.nom49
-rw-r--r--core/errors.nom6
-rw-r--r--core/metaprogramming.nom9
-rw-r--r--core/operators.nom1
-rw-r--r--error_handling.lua77
-rw-r--r--error_handling.moon48
-rw-r--r--nomsu.lua33
-rwxr-xr-xnomsu.moon26
-rw-r--r--nomsu_compiler.lua30
-rw-r--r--nomsu_compiler.moon29
12 files changed, 212 insertions, 102 deletions
diff --git a/code_obj.lua b/code_obj.lua
index d3b9260..7fa91fc 100644
--- a/code_obj.lua
+++ b/code_obj.lua
@@ -173,11 +173,11 @@ do
__init = function(self, source, ...)
self.source = source
self.bits, self.indents, self.current_indent = { }, { }, 0
- self:append(...)
if type(self.source) == 'string' then
self.source = Source:from_string(self.source)
end
- return assert(self.source and Source:is_instance(self.source))
+ assert(self.source and Source:is_instance(self.source))
+ return self:append(...)
end,
__base = _base_0,
__name = "Code"
diff --git a/code_obj.moon b/code_obj.moon
index ef19ed4..74e9a15 100644
--- a/code_obj.moon
+++ b/code_obj.moon
@@ -46,10 +46,10 @@ class Source
class Code
new: (@source, ...)=>
@bits, @indents, @current_indent = {}, {}, 0
- @append(...)
if type(@source) == 'string'
@source = Source\from_string(@source)
assert(@source and Source\is_instance(@source))
+ @append(...)
append: (...)=>
n = select("#",...)
diff --git a/core/collections.nom b/core/collections.nom
index 0f53679..48a4330 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -9,6 +9,7 @@ use "core/operators.nom"
# List/dict functions:
# Indexing
+test: assume: (2nd to last in [1,2,3,4,5]) is 4
compile [..]
%index st to last in %list, %index nd to last in %list, %index rd to last in %list
%index th to last in %list
@@ -20,11 +21,13 @@ parse [last in %list] as: 1st to last in %list
parse [first in %list] as: %list.1
# Membership testing
+test: assume: 3 is in [1,2,3,4,5]
action [%item is in %list, %list contains %item, %list has %item]
for %key = %value in %list
if (%key is %item): return (yes)
return (no)
+test: assume: 99 isn't in [1,2,3]
action [..]
%item isn't in %list, %item is not in %list
%list doesn't contain %item, %list does not contain %item
@@ -34,9 +37,13 @@ action [..]
if (%key is %item): return (no)
return (yes)
+test: assume: {x:no} has key "x"
parse [%list has key %index, %list has index %index] as
%list.%index != (nil)
+test
+ assume: {x:no} doesn't have key "y"
+ assume: not: {x:no} doesn't have key "x"
parse [..]
%list doesn't have key %index, %list does not have key %index
%list doesn't have index %index, %list does not have index %index
@@ -46,6 +53,15 @@ parse [..]
compile [number of keys in %list] to
Lua value "utils.size(\(%list as lua expr))"
+test
+ %list <- [1,2,3,4,5]
+ append 6 to %list
+ assume: (last in %list) is 6
+ pop from %list
+ assume: (last in %list) is 5
+ remove index 1 from %list
+ assume: (first in %list) is 2
+
compile [append %item to %list, add %item to %list, to %list add %item, to %list append %item] to
Lua "table.insert(\(%list as lua expr), \(%item as lua expr))"
@@ -58,6 +74,7 @@ compile [remove index %index from %list] to
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# List Comprehension
+test: assume: ((% * %) for % in [1,2,3]) = [1,4,9]
parse [%expression for %item in %iterable] as
result of
%comprehension <- []
@@ -76,9 +93,11 @@ parse [..]
return %comprehension
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+test: assume: ((% * %) for % in 1 to 3) = [1,4,9]
parse [%expression for %var in %start to %stop] as
%expression for %var in %start to %stop via 1
+test: assume: ("\%k,\%v" for %k = %v in {x:1}) = ["x,1"]
parse [..]
%expression for %key = %value in %iterable
%expression for (%key,%value) in %iterable
@@ -90,6 +109,7 @@ parse [..]
return %comprehension
# Dict comprehensions
+test: assume: ((% * %) = % for % in [1,2,3]) = {1:1,4:2,9:3}
parse [..]
%key = %value for %item in %iterable
(%key,%value) for %item in %iterable
@@ -100,6 +120,7 @@ parse [..]
%comprehension.%key <- %value
return %comprehension
+test: assume: (%k = (%v * %v) for %k = %v in {x:1,y:2,z:3}) = {x:1,y:4,z:9}
parse [..]
%key = %value for %src_key = %src_value in %iterable
(%key,%value) for (%src_key,%src_value) in %iterable
@@ -110,7 +131,23 @@ parse [..]
%comprehension.%key <- %value
return %comprehension
+parse [..]
+ %key = %value for %item in %start to %stop via %step
+ (%key,%value) for %item in %start to %stop via %step
+..as
+ result of
+ %comprehension <- {}
+ for %item in %start to %stop via %step
+ %comprehension.%key <- %value
+ return %comprehension
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+test: assume: ((% * %) = % for % in 1 to 3) = {1:1,4:2,9:3}
+parse [..]
+ %key = %value for %item in %start to %stop
+ (%key,%value) for %item in %start to %stop
+..as: %key = %value for %item in %start to %stop via 1
+
+test: assume: ([[1,2],[3,4]] flattened) = [1,2,3,4]
action [%lists flattened]
%flat <- []
for %list in %lists
@@ -118,14 +155,24 @@ action [%lists flattened]
add %item to %flat
return %flat
+test: assume: (entries in {x:1}) = [{key:"x",value:1}]
parse [entries in %dict] as: {key:%k, value:%v} for %k = %v in %dict
+
+test: assume: (keys in {x:1}) = ["x"]
parse [keys in %dict, keys of %dict] as: %k for %k = %v in %dict
+
+test: assume: (values in {x:1}) = [1]
parse [values in %dict, values of %dict] as: %v for %k = %v in %dict
# Metatable stuff
+test
+ %t <- {}
+ set %t's metatable to {__tostring:[%]->"XXX"}
+ assume: "\%t" = "XXX"
compile [set %dict's metatable to %metatable] to
Lua "setmetatable(\(%dict as lua expr), \(%metatable as lua expr));"
+test: assume: ({} with fallback % -> (% + 1)).10 = 11
compile [%dict with fallback %key -> %value] to
Lua value ".."
setmetatable(\(%dict as lua expr), {__index=function(self, \(%key as lua expr))
@@ -134,6 +181,8 @@ 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/core/errors.nom b/core/errors.nom
index 812052e..91f9b4f 100644
--- a/core/errors.nom
+++ b/core/errors.nom
@@ -8,17 +8,17 @@ compile [traceback %] to: Lua value "debug.traceback('', \(% as lua expr))"
compile [barf] to: Lua "error(nil, 0);"
compile [barf %msg] to: Lua "error(\(%msg as lua expr), 0);"
compile [assume %condition] to
- lua> "local \%assumption = 'Assumption failed: '..tostring(nomsu:tree_to_nomsu(\%condition));"
+ lua> "local \%assumption = 'Assumption failed: '..tostring(nomsu:tree_to_nomsu(\%condition))"
return
Lua ".."
if not \(%condition as lua expr) then
- error(\(quote "\%assumption"), 0);
+ error(\(quote "\%assumption"), 0)
end
compile [assume %condition or barf %message] to
Lua ".."
if not \(%condition as lua expr) then
- error(\(%message as lua expr), 0);
+ error(\(%message as lua expr), 0)
end
# Try/except
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 242db04..5a80c64 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -124,8 +124,13 @@ compile [parse %actions as %body] to
return ret
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-compile [%tree as lua expr] to
- Lua value "nomsu:compile(\(=lua "nomsu:compile(\%tree):as_expr()")):as_expr()"
+lua> ".."
+ COMPILE_ACTIONS["% as lua expr"] = function(nomsu, tree, _t)
+ return LuaCode.Value(tree.source, "nomsu:compile(", nomsu:compile(_t):as_expr(), "):as_expr()")
+ end
+#
+ compile [%tree as lua expr] to
+ Lua value "nomsu:compile(\(=lua "nomsu:compile(\%tree):as_expr()")):as_expr()"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compile [%tree as lua] to
diff --git a/core/operators.nom b/core/operators.nom
index d434ea7..0712ada 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -163,6 +163,7 @@ compile [%x ARSHIFT %shift, %x >> %shift] to: Lua value "(\(%x as lua expr) >> \
# Unary operators
compile [- %] to: Lua value "(- \(% as lua expr))"
compile [not %] to: Lua value "(not \(% as lua expr))"
+test: assume: (length of [1,2,3]) = 3
compile [length of %list, || %list ||] to: Lua value "(#\(%list as lua expr))"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/error_handling.lua b/error_handling.lua
index b0e6dde..d88cfeb 100644
--- a/error_handling.lua
+++ b/error_handling.lua
@@ -45,25 +45,31 @@ debug.getinfo = function(thread, f, what)
info.lastlinedefined = assert(map[info.lastlinedefined])
end
info.short_src = info.source:match('@([^[]*)') or info.short_src
+ if info.name then
+ do
+ local tmp = info.name:match("^A_([a-zA-Z0-9_]*)$")
+ if tmp then
+ info.name = tmp:gsub("_", " "):gsub("x([0-9A-F][0-9A-F])", function(self)
+ return string.char(tonumber(self, 16))
+ end)
+ else
+ info.name = info.name
+ end
+ end
+ else
+ info.name = "main chunk"
+ end
end
end
end
return info
end
local print_error
-print_error = function(error_message, stack_offset)
- if stack_offset == nil then
- stack_offset = 3
- end
+print_error = function(error_message, start_fn, stop_fn)
io.stderr:write(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.red((error_message or "")))) .. "\n")
io.stderr:write("stack traceback:\n")
- local get_line
- get_line = function(file, line_no)
- local start = LINE_STARTS[file][line_no] or 1
- local stop = (LINE_STARTS[file][line_no + 1] or 0) - 1
- return file:sub(start, stop)
- end
- local level = stack_offset
+ local level = 1
+ local found_start = false
while true do
local _continue_0 = false
repeat
@@ -71,10 +77,14 @@ print_error = function(error_message, stack_offset)
if not calling_fn then
break
end
- if calling_fn.func == run then
+ level = level + 1
+ if not (found_start) then
+ if calling_fn.func == start_fn then
+ found_start = true
+ end
+ _continue_0 = true
break
end
- level = level + 1
local name = calling_fn.name and "function '" .. tostring(calling_fn.name) .. "'" or nil
if calling_fn.linedefined == 0 then
name = "main chunk"
@@ -98,8 +108,8 @@ print_error = function(error_message, stack_offset)
end
local filename, start, stop = calling_fn.source:match('@([^[]*)%[([0-9]+):([0-9]+)]')
assert(filename)
- local file = read_file(filename):sub(tonumber(start), tonumber(stop))
- local err_line = get_line(file, calling_fn.currentline):sub(1, -2)
+ local file = files.read(filename)
+ local err_line = files.get_line(file, calling_fn.currentline)
local offending_statement = colored.bright(colored.red(err_line:match("^[ ]*(.*)")))
if calling_fn.name then
do
@@ -119,7 +129,7 @@ print_error = function(error_message, stack_offset)
else
local file
ok, file = pcall(function()
- return read_file(calling_fn.short_src)
+ return files.read(calling_fn.short_src)
end)
if not ok then
file = nil
@@ -128,11 +138,12 @@ print_error = function(error_message, stack_offset)
if name == nil then
local search_level = level
local _info = debug.getinfo(search_level)
- while _info and (_info.func == pcall or _info.func == xpcall) do
+ while true do
search_level = search_level + 1
_info = debug.getinfo(search_level)
- end
- if _info then
+ if not (_info) then
+ break
+ end
for i = 1, 999 do
local varname, val = debug.getlocal(search_level, i)
if not varname then
@@ -177,16 +188,19 @@ print_error = function(error_message, stack_offset)
end
end
if file then
- local err_line = get_line(file, line_num):sub(1, -2)
+ local err_line = files.get_line(file, line_num)
local offending_statement = colored.bright(colored.red(err_line:match("^[ ]*(.*)$")))
line = line .. ("\n " .. offending_statement)
end
end
end
- io.stderr:write(" " .. tostring(line) .. "\n")
+ io.stderr:write(line, "\n")
if calling_fn.istailcall then
io.stderr:write(" " .. tostring(colored.dim(colored.white(" (...tail calls...)"))) .. "\n")
end
+ if calling_fn.func == stop_fn then
+ break
+ end
_continue_0 = true
until true
if not _continue_0 then
@@ -195,18 +209,17 @@ print_error = function(error_message, stack_offset)
end
return io.stderr:flush()
end
-local error_handler
-error_handler = function(error_message)
- print_error(error_message)
- local EXIT_FAILURE = 1
- return os.exit(EXIT_FAILURE)
-end
-local run_safely
-run_safely = function(fn)
+local guard
+guard = function(fn)
+ local error_handler
+ error_handler = function(error_message)
+ print_error(error_message, error_handler, fn)
+ local EXIT_FAILURE = 1
+ return os.exit(EXIT_FAILURE)
+ end
return xpcall(fn, error_handler)
end
return {
- run_safely = run_safely,
- print_error = print_error,
- error_handler = error_handler
+ guard = guard,
+ print_error = print_error
}
diff --git a/error_handling.moon b/error_handling.moon
index 5341348..f28a8c8 100644
--- a/error_handling.moon
+++ b/error_handling.moon
@@ -31,24 +31,28 @@ debug.getinfo = (thread,f,what)->
if info.lastlinedefined
info.lastlinedefined = assert(map[info.lastlinedefined])
info.short_src = info.source\match('@([^[]*)') or info.short_src
+ -- TODO: get name properly
+ info.name = if info.name
+ if tmp = info.name\match("^A_([a-zA-Z0-9_]*)$")
+ tmp\gsub("_"," ")\gsub("x([0-9A-F][0-9A-F])", => string.char(tonumber(@, 16)))
+ else info.name
+ else "main chunk"
return info
-print_error = (error_message, stack_offset=3)->
+print_error = (error_message, start_fn, stop_fn)->
io.stderr\write("#{colored.red "ERROR:"} #{colored.bright colored.red (error_message or "")}\n")
io.stderr\write("stack traceback:\n")
- get_line = (file, line_no)->
- start = LINE_STARTS[file][line_no] or 1
- stop = (LINE_STARTS[file][line_no+1] or 0) - 1
- return file\sub(start, stop)
-
- level = stack_offset
+ level = 1
+ found_start = false
while true
-- TODO: reduce duplicate code
calling_fn = debug_getinfo(level)
if not calling_fn then break
- if calling_fn.func == run then break
level += 1
+ unless found_start
+ if calling_fn.func == start_fn then found_start = true
+ continue
name = calling_fn.name and "function '#{calling_fn.name}'" or nil
if calling_fn.linedefined == 0 then name = "main chunk"
if name == "run_lua_fn" then continue
@@ -63,8 +67,8 @@ print_error = (error_message, stack_offset=3)->
--calling_fn.short_src = calling_fn.source\match('"([^[]*)')
filename,start,stop = calling_fn.source\match('@([^[]*)%[([0-9]+):([0-9]+)]')
assert(filename)
- file = read_file(filename)\sub(tonumber(start),tonumber(stop))
- err_line = get_line(file, calling_fn.currentline)\sub(1,-2)
+ file = files.read(filename)
+ err_line = files.get_line(file, calling_fn.currentline)
offending_statement = colored.bright(colored.red(err_line\match("^[ ]*(.*)")))
-- TODO: get name properly
name = if calling_fn.name
@@ -74,16 +78,16 @@ print_error = (error_message, stack_offset=3)->
else "main chunk"
line = colored.yellow("#{filename}:#{calling_fn.currentline} in #{name}\n #{offending_statement}")
else
- ok, file = pcall ->read_file(calling_fn.short_src)
+ ok, file = pcall ->files.read(calling_fn.short_src)
if not ok then file = nil
local line_num
if name == nil
search_level = level
_info = debug.getinfo(search_level)
- while _info and (_info.func == pcall or _info.func == xpcall)
+ while true
search_level += 1
_info = debug.getinfo(search_level)
- if _info
+ break unless _info
for i=1,999
varname, val = debug.getlocal(search_level, i)
if not varname then break
@@ -113,21 +117,21 @@ print_error = (error_message, stack_offset=3)->
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.currentline} in #{name or '?'}")
if file
- err_line = get_line(file, line_num)\sub(1,-2)
+ err_line = files.get_line(file, line_num)
offending_statement = colored.bright(colored.red(err_line\match("^[ ]*(.*)$")))
line ..= "\n "..offending_statement
- io.stderr\write(" #{line}\n")
+ io.stderr\write(line,"\n")
if calling_fn.istailcall
io.stderr\write(" #{colored.dim colored.white " (...tail calls...)"}\n")
+ if calling_fn.func == stop_fn then break
io.stderr\flush!
-error_handler = (error_message)->
- print_error error_message
- EXIT_FAILURE = 1
- os.exit(EXIT_FAILURE)
-
-run_safely = (fn)->
+guard = (fn)->
+ error_handler = (error_message)->
+ print_error error_message, error_handler, fn
+ EXIT_FAILURE = 1
+ os.exit(EXIT_FAILURE)
xpcall(fn, error_handler)
-return {:run_safely, :print_error, :error_handler}
+return {:guard, :print_error}
diff --git a/nomsu.lua b/nomsu.lua
index 3bc8fb8..939dda1 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -53,13 +53,14 @@ end
local EXIT_SUCCESS, EXIT_FAILURE = 0, 1
local usage = [=[Nomsu Compiler
-Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-I file] [--help | -h] [--version] [file [nomsu args...]]
+Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-t] [-I file] [--help | -h] [--version] [file [nomsu args...]]
OPTIONS
-O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available).
-v Verbose: print compiled lua code.
-c Compile the input files into a .lua files.
-s Check the input files for syntax errors.
+ -t Run tests.
-I <file> Add an additional input file or directory.
-h/--help Print this message.
--version Print the version number and exit.
@@ -93,9 +94,11 @@ local parser = re.compile([[ args <- {| (flag ";")* (({~ file ~} -> add_file)
/ ("-I" (";")? ({~ file ~} -> add_file))
/ ({:check_syntax: ("-s" -> true):})
/ ({:compile: ("-c" -> true):})
+ / {:run_tests: ("-t" -> true) :}
/ {:verbose: ("-v" -> true) :}
/ {:help: (("-h" / "--help") -> true) :}
/ {:version: ("--version" -> true) :}
+ / {:debugger: ("-d" (";")? {([^;])*}) :}
/ {:requested_version: "-V" ((";")? {([0-9.])+})? :}
file <- ("-" -> "stdin") / {[^;]+}
]], {
@@ -153,6 +156,13 @@ run = function()
end
return true
end
+ local tests = { }
+ if args.run_tests then
+ nomsu.COMPILE_ACTIONS["test %"] = function(self, tree, _body)
+ table.insert(tests, _body)
+ return LuaCode("")
+ end
+ end
local get_file_and_source
get_file_and_source = function(filename)
local file, source
@@ -188,6 +198,7 @@ run = function()
tree
}
end
+ tests = { }
for _index_0 = 1, #tree do
local chunk = tree[_index_0]
local lua = nomsu:compile(chunk):as_statements("return ")
@@ -198,6 +209,16 @@ run = function()
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]
+ local lua = nomsu:compile(t)
+ if lua_handler then
+ lua_handler(tostring(lua))
+ end
+ nomsu:run_lua(lua)
+ end
+ end
end
end
local parse_errs = { }
@@ -294,9 +315,11 @@ say ".."
end
end
end
-local has_ldt, ldt = pcall(require, 'ldt')
-if has_ldt then
- return ldt.guard(run)
+local debugger = require(args.debugger or 'error_handling')
+local guard
+if type(debugger) == 'function' then
+ guard = debugger
else
- return Errhand.run_safely(run)
+ guard = debugger.guard or debugger.call or debugger.wrap or debugger.run
end
+return guard(run)
diff --git a/nomsu.moon b/nomsu.moon
index 09ee2bd..0bb4752 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -11,13 +11,14 @@ EXIT_SUCCESS, EXIT_FAILURE = 0, 1
usage = [=[
Nomsu Compiler
-Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-I file] [--help | -h] [--version] [file [nomsu args...]]
+Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-t] [-I file] [--help | -h] [--version] [file [nomsu args...]]
OPTIONS
-O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available).
-v Verbose: print compiled lua code.
-c Compile the input files into a .lua files.
-s Check the input files for syntax errors.
+ -t Run tests.
-I <file> Add an additional input file or directory.
-h/--help Print this message.
--version Print the version number and exit.
@@ -49,9 +50,11 @@ parser = re.compile([[
/ ("-I" (";")? ({~ file ~} -> add_file))
/ ({:check_syntax: ("-s" -> true):})
/ ({:compile: ("-c" -> true):})
+ / {:run_tests: ("-t" -> true) :}
/ {:verbose: ("-v" -> true) :}
/ {:help: (("-h" / "--help") -> true) :}
/ {:version: ("--version" -> true) :}
+ / {:debugger: ("-d" (";")? {([^;])*}) :}
/ {:requested_version: "-V" ((";")? {([0-9.])+})? :}
file <- ("-" -> "stdin") / {[^;]+}
]], {
@@ -99,6 +102,12 @@ run = ->
return false if args.compile and input_files[f]
return true
+ tests = {}
+ if args.run_tests
+ nomsu.COMPILE_ACTIONS["test %"] = (tree, _body)=>
+ table.insert tests, _body
+ return LuaCode ""
+
get_file_and_source = (filename)->
local file, source
if filename == 'stdin'
@@ -124,12 +133,18 @@ 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))
nomsu\run_lua(lua)
+ if args.run_tests and #tests > 0
+ for t in *tests
+ lua = nomsu\compile(t)
+ if lua_handler then lua_handler(tostring(lua))
+ nomsu\run_lua(lua)
parse_errs = {}
for f in *file_queue
@@ -201,8 +216,7 @@ say ".."
elseif not ok
Errhand.print_error ret
-has_ldt, ldt = pcall(require,'ldt')
-if has_ldt
- ldt.guard(run)
-else
- Errhand.run_safely(run)
+debugger = 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
+guard(run)
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index 8c01860..b2c034a 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -301,13 +301,13 @@ do
return lua
end,
["Lua %"] = function(self, tree, _code)
- local lua = LuaCode.Value(_code.source, "LuaCode(", repr(tostring(_code.source)))
+ local lua = LuaCode.Value(tree.source, "LuaCode(", repr(tostring(_code.source)))
add_lua_string_bits(self, lua, _code)
lua:append(")")
return lua
end,
["Lua value %"] = function(self, tree, _code)
- local lua = LuaCode.Value(_code.source, "LuaCode.Value(", repr(tostring(_code.source)))
+ local lua = LuaCode.Value(tree.source, "LuaCode.Value(", repr(tostring(_code.source)))
add_lua_string_bits(self, lua, _code)
lua:append(")")
return lua
@@ -332,6 +332,9 @@ do
end
end
return LuaCode(tree.source, "for f in files.walk(", self:compile(_path), ") do nomsu:run_file(f) end")
+ end,
+ ["test %"] = function(self, tree, _body)
+ return LuaCode("")
end
}, {
__index = function(self, stub)
@@ -434,7 +437,7 @@ do
source = nil
end
local lua_string = tostring(lua)
- local run_lua_fn, err = load(lua_string, nil and tostring(source or lua.source), "t", self)
+ local run_lua_fn, err = load(lua_string, tostring(source or lua.source), "t", self)
if not run_lua_fn then
local line_numbered_lua = concat((function()
local _accum_0 = { }
@@ -447,39 +450,36 @@ do
end)(), "\n")
error("Failed to compile generated code:\n" .. tostring(colored.bright(colored.blue(colored.onblack(line_numbered_lua)))) .. "\n\n" .. tostring(err), 0)
end
- local source_key = tostring(source or lua.source)
+ source = source or lua.source
+ local source_key = tostring(source)
if not (SOURCE_MAP[source_key]) then
local map = { }
- local offset = 1
- source = source or lua.source
local file = files.read(source.filename)
if not file then
error("Failed to find file: " .. tostring(source.filename))
end
local nomsu_str = tostring(file:sub(source.start, source.stop))
local lua_line = 1
- local nomsu_line = files.get_line_number(nomsu_str, source.start)
- local fn
- fn = function(s)
+ local nomsu_line = files.get_line_number(file, source.start)
+ local map_sources
+ map_sources = function(s)
if type(s) == 'string' then
for nl in s:gmatch("\n") do
map[lua_line] = map[lua_line] or nomsu_line
lua_line = lua_line + 1
end
else
- local old_line = nomsu_line
- if s.source then
- nomsu_line = files.get_line_number(nomsu_str, s.source.start)
+ if s.source and s.source.filename == source.filename then
+ nomsu_line = files.get_line_number(file, s.source.start)
end
local _list_0 = s.bits
for _index_0 = 1, #_list_0 do
local b = _list_0[_index_0]
- fn(b)
+ map_sources(b)
end
end
end
- fn(lua)
- map[lua_line] = map[lua_line] or nomsu_line
+ map_sources(lua)
map[0] = 0
SOURCE_MAP[source_key] = map
end
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index 1a7a6e7..83c864c 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -189,13 +189,13 @@ with NomsuCompiler
return lua
["Lua %"]: (tree, _code)=>
- lua = LuaCode.Value(_code.source, "LuaCode(", repr(tostring _code.source))
+ lua = LuaCode.Value(tree.source, "LuaCode(", repr(tostring _code.source))
add_lua_string_bits(@, lua, _code)
lua\append ")"
return lua
["Lua value %"]: (tree, _code)=>
- lua = LuaCode.Value(_code.source, "LuaCode.Value(", repr(tostring _code.source))
+ lua = LuaCode.Value(tree.source, "LuaCode.Value(", repr(tostring _code.source))
add_lua_string_bits(@, lua, _code)
lua\append ")"
return lua
@@ -216,6 +216,9 @@ with NomsuCompiler
for f in files.walk(path)
@run_file(f)
return LuaCode(tree.source, "for f in files.walk(", @compile(_path), ") do nomsu:run_file(f) end")
+
+ ["test %"]: (tree, _body)=>
+ return LuaCode ""
}, {
__index: (stub)=>
if math_expression\match(stub)
@@ -285,35 +288,33 @@ with NomsuCompiler
.run_lua = (lua, source=nil)=>
lua_string = tostring(lua)
- run_lua_fn, err = load(lua_string, nil and tostring(source or lua.source), "t", self)
+ run_lua_fn, err = load(lua_string, tostring(source or lua.source), "t", self)
if not run_lua_fn
line_numbered_lua = concat(
[format("%3d|%s",i,line) for i, line in ipairs files.get_lines(lua_string)],
"\n")
error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack line_numbered_lua}\n\n#{err}", 0)
- source_key = tostring(source or lua.source)
+ source or= lua.source
+ source_key = tostring(source)
unless SOURCE_MAP[source_key]
map = {}
- offset = 1
- source or= lua.source
file = files.read(source.filename)
if not file
error "Failed to find file: #{source.filename}"
nomsu_str = tostring(file\sub(source.start, source.stop))
lua_line = 1
- nomsu_line = files.get_line_number(nomsu_str, source.start)
- fn = (s)->
+ nomsu_line = files.get_line_number(file, source.start)
+ map_sources = (s)->
if type(s) == 'string'
for nl in s\gmatch("\n")
map[lua_line] or= nomsu_line
lua_line += 1
else
- old_line = nomsu_line
- if s.source
- nomsu_line = files.get_line_number(nomsu_str, s.source.start)
- for b in *s.bits do fn(b)
- fn(lua)
- map[lua_line] or= nomsu_line
+ if s.source and s.source.filename == source.filename
+ nomsu_line = files.get_line_number(file, s.source.start)
+ for b in *s.bits do map_sources(b)
+ map_sources(lua)
+ --map[lua_line] or= nomsu_line
map[0] = 0
-- Mapping from lua line number to nomsu line numbers
SOURCE_MAP[source_key] = map