aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code_obj.lua51
-rw-r--r--code_obj.moon28
-rw-r--r--containers.lua63
-rw-r--r--containers.moon28
-rw-r--r--core/collections.nom1
-rw-r--r--core/control_flow.nom27
-rw-r--r--core/errors.nom123
-rw-r--r--core/metaprogramming.nom10
-rw-r--r--core/operators.nom1
-rw-r--r--nomsu.6.peg6
-rw-r--r--nomsu_compiler.lua4
-rw-r--r--nomsu_compiler.moon4
-rw-r--r--parser.lua7
-rw-r--r--parser.moon7
-rwxr-xr-xtools/repl.nom57
15 files changed, 213 insertions, 204 deletions
diff --git a/code_obj.lua b/code_obj.lua
index 5afca1d..a09608f 100644
--- a/code_obj.lua
+++ b/code_obj.lua
@@ -320,6 +320,10 @@ do
return self:dirty()
end,
remove_free_vars = function(self, vars)
+ if vars == nil then
+ vars = nil
+ end
+ vars = vars or self:get_free_vars()
if not (#vars > 0) then
return
end
@@ -351,33 +355,34 @@ do
end
return self:dirty()
end,
- declare_locals = function(self, to_declare)
- if to_declare == nil then
- to_declare = nil
- end
- if to_declare == nil then
- local seen
- to_declare, seen = { }, { }
- local gather_from
- gather_from = function(self)
- local _list_0 = self.free_vars
- for _index_0 = 1, #_list_0 do
- local var = _list_0[_index_0]
- if not (seen[var]) then
- seen[var] = true
- to_declare[#to_declare + 1] = var
- end
+ get_free_vars = function(self)
+ local vars, seen = { }, { }
+ local gather_from
+ gather_from = function(self)
+ local _list_0 = self.free_vars
+ for _index_0 = 1, #_list_0 do
+ local var = _list_0[_index_0]
+ if not (seen[var]) then
+ seen[var] = true
+ vars[#vars + 1] = var
end
- local _list_1 = self.bits
- for _index_0 = 1, #_list_1 do
- local bit = _list_1[_index_0]
- if not (type(bit) == 'string') then
- gather_from(bit)
- end
+ end
+ local _list_1 = self.bits
+ for _index_0 = 1, #_list_1 do
+ local bit = _list_1[_index_0]
+ if not (type(bit) == 'string') then
+ gather_from(bit)
end
end
- gather_from(self)
end
+ gather_from(self)
+ return vars
+ end,
+ declare_locals = function(self, to_declare)
+ if to_declare == nil then
+ to_declare = nil
+ end
+ to_declare = to_declare or self:get_free_vars()
if #to_declare > 0 then
self:remove_free_vars(to_declare)
self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n")
diff --git a/code_obj.moon b/code_obj.moon
index bdce010..9315264 100644
--- a/code_obj.moon
+++ b/code_obj.moon
@@ -179,7 +179,8 @@ class LuaCode extends Code
seen[var] = true
@dirty!
- remove_free_vars: (vars)=>
+ remove_free_vars: (vars=nil)=>
+ vars or= @get_free_vars!
return unless #vars > 0
removals = {}
for var in *vars
@@ -198,18 +199,21 @@ class LuaCode extends Code
stack[#stack+1] = b
@dirty!
+ get_free_vars: =>
+ vars, seen = {}, {}
+ gather_from = =>
+ for var in *@free_vars
+ unless seen[var]
+ seen[var] = true
+ vars[#vars+1] = var
+ for bit in *@bits
+ unless type(bit) == 'string'
+ gather_from bit
+ gather_from self
+ return vars
+
declare_locals: (to_declare=nil)=>
- if to_declare == nil
- to_declare, seen = {}, {}
- gather_from = =>
- for var in *@free_vars
- unless seen[var]
- seen[var] = true
- to_declare[#to_declare+1] = var
- for bit in *@bits
- unless type(bit) == 'string'
- gather_from bit
- gather_from self
+ to_declare or= @get_free_vars!
if #to_declare > 0
@remove_free_vars to_declare
@prepend "local #{concat to_declare, ", "};\n"
diff --git a/containers.lua b/containers.lua
index d4514af..418a819 100644
--- a/containers.lua
+++ b/containers.lua
@@ -251,18 +251,6 @@ List = function(t)
return error("Unsupported List type: " .. type(t))
end
end
-local walk_items
-walk_items = function(self, i)
- i = i + 1
- local k, v = next(self.table, self.key)
- if k ~= nil then
- self.key = k
- return i, Dict({
- key = k,
- value = v
- })
- end
-end
local _dict_mt = {
__type = "Dict",
__eq = function(self, other)
@@ -321,12 +309,6 @@ local _dict_mt = {
return _accum_0
end)(), ", ") .. "}"
end,
- __ipairs = function(self)
- return walk_items, {
- table = self,
- key = nil
- }, 0
- end,
__band = function(self, other)
return Dict((function()
local _tbl_0 = { }
@@ -339,30 +321,28 @@ local _dict_mt = {
end)())
end,
__bor = function(self, other)
- local ret
- do
+ local ret = Dict((function()
local _tbl_0 = { }
for k, v in pairs(self) do
_tbl_0[k] = v
end
- ret = _tbl_0
- end
+ return _tbl_0
+ end)())
for k, v in pairs(other) do
if ret[k] == nil then
ret[k] = v
end
end
- return Dict(ret)
+ return ret
end,
__bxor = function(self, other)
- local ret
- do
+ local ret = Dict((function()
local _tbl_0 = { }
for k, v in pairs(self) do
_tbl_0[k] = v
end
- ret = _tbl_0
- end
+ return _tbl_0
+ end)())
for k, v in pairs(other) do
if ret[k] == nil then
ret[k] = v
@@ -370,17 +350,16 @@ local _dict_mt = {
ret[k] = nil
end
end
- return Dict(ret)
+ return ret
end,
__add = function(self, other)
- local ret
- do
+ local ret = Dict((function()
local _tbl_0 = { }
for k, v in pairs(self) do
_tbl_0[k] = v
end
- ret = _tbl_0
- end
+ return _tbl_0
+ end)())
for k, v in pairs(other) do
if ret[k] == nil then
ret[k] = v
@@ -388,17 +367,16 @@ local _dict_mt = {
ret[k] = ret[k] + v
end
end
- return Dict(ret)
+ return ret
end,
__sub = function(self, other)
- local ret
- do
+ local ret = Dict((function()
local _tbl_0 = { }
for k, v in pairs(self) do
_tbl_0[k] = v
end
- ret = _tbl_0
- end
+ return _tbl_0
+ end)())
for k, v in pairs(other) do
if ret[k] == nil then
ret[k] = -v
@@ -406,7 +384,7 @@ local _dict_mt = {
ret[k] = ret[k] - v
end
end
- return Dict(ret)
+ return ret
end
}
Dict = function(t)
@@ -430,11 +408,6 @@ Dict = function(t)
return error("Unsupported Dict type: " .. type(t))
end
end
-for i, entry in ipairs(Dict({
- x = 99
-})) do
- assert(i == 1 and entry.key == "x" and entry.value == 99, "ipairs compatibility issue")
-end
do
local reverse, upper, lower, find, byte, match, gmatch, gsub, sub, format, rep
do
@@ -502,9 +475,9 @@ do
return (match(self, patt))
end,
matching_groups = function(self, patt)
- return {
+ return List({
match(self, patt)
- }
+ })
end,
[as_lua_id("* 1")] = function(self, n)
return rep(self, n)
diff --git a/containers.moon b/containers.moon
index 26c1032..be0925b 100644
--- a/containers.moon
+++ b/containers.moon
@@ -106,13 +106,6 @@ List = (t)->
return l
else error("Unsupported List type: "..type(t))
-walk_items = (i)=>
- i = i + 1
- k, v = next(@table, @key)
- if k != nil
- @key = k
- return i, Dict{key:k, value:v}
-
_dict_mt =
__type: "Dict"
__eq: (other)=>
@@ -133,32 +126,31 @@ _dict_mt =
"{"..concat(["#{as_nomsu(k)}: #{as_nomsu(v)}" for k,v in pairs @], ", ").."}"
as_lua: =>
"Dict{"..concat(["[ #{as_lua(k)}]= #{as_lua(v)}" for k,v in pairs @], ", ").."}"
- __ipairs: => walk_items, {table:@, key:nil}, 0
__band: (other)=>
Dict{k,v for k,v in pairs(@) when other[k] != nil}
__bor: (other)=>
- ret = {k,v for k,v in pairs(@)}
+ ret = Dict{k,v for k,v in pairs(@)}
for k,v in pairs(other)
if ret[k] == nil then ret[k] = v
- return Dict(ret)
+ return ret
__bxor: (other)=>
- ret = {k,v for k,v in pairs(@)}
+ ret = Dict{k,v for k,v in pairs(@)}
for k,v in pairs(other)
if ret[k] == nil then ret[k] = v
else ret[k] = nil
- return Dict(ret)
+ return ret
__add: (other)=>
- ret = {k,v for k,v in pairs(@)}
+ ret = Dict{k,v for k,v in pairs(@)}
for k,v in pairs(other)
if ret[k] == nil then ret[k] = v
else ret[k] += v
- return Dict(ret)
+ return ret
__sub: (other)=>
- ret = {k,v for k,v in pairs(@)}
+ ret = Dict{k,v for k,v in pairs(@)}
for k,v in pairs(other)
if ret[k] == nil then ret[k] = -v
else ret[k] -= v
- return Dict(ret)
+ return ret
Dict = (t)->
if type(t) == 'table'
return setmetatable(t, _dict_mt)
@@ -171,8 +163,6 @@ Dict = (t)->
return d
else error("Unsupported Dict type: "..type(t))
-for i,entry in ipairs(Dict({x:99}))
- assert(i == 1 and entry.key == "x" and entry.value == 99, "ipairs compatibility issue")
do
{:reverse, :upper, :lower, :find, :byte, :match, :gmatch, :gsub, :sub, :format, :rep} = string
@@ -204,7 +194,7 @@ do
line_position_at: (i)=> select(3, line_at(@, i))
matches: (patt)=> match(@, patt) and true or false
matching: (patt)=> (match(@, patt))
- matching_groups: (patt)=> {match(@, patt)}
+ matching_groups: (patt)=> List{match(@, patt)}
[as_lua_id "* 1"]: (n)=> rep(@, n)
all_matches_of: (patt)=>
result = {}
diff --git a/core/collections.nom b/core/collections.nom
index 69685b8..6aac861 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -37,7 +37,6 @@ test:
test:
$dict = {.x = 1, .y = 2, .z = 3}
assume (size of $dict) == 3
- assume [: for $ in {.x = 1}: add $] == [{.key = "x", .value = 1}]
assume [: for $k = $v in {.x = 1}: add {.key = $k, .value = $v}] ==
[{.key = "x", .value = 1}]
assume ({.x = 1, .y = 1} + {.y = 10, .z = 10}) == {.x = 1, .y = 11, .z = 10}
diff --git a/core/control_flow.nom b/core/control_flow.nom
index 16f8537..f066767 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -5,7 +5,6 @@
use "core/metaprogramming.nom"
use "core/operators.nom"
-use "core/errors.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -449,32 +448,6 @@ test:
")
test:
- $d = {}
- try:
- do:
- $d.x = "bad"
- barf
- ..then always:
- $d.x = "good"
- assume ($d.x == "good")
-
-(do $action then always $final_action) compiles to:
- define mangler
- return
- Lua ("
- do
- local \(mangle "fell_through") = false
- local \(mangle "ok"), \(mangle "ret") = pcall(function()
- \($action as lua)
- \(mangle "fell_through") = true
- end)
- \($final_action as lua)
- if not \(mangle "ok") then error(ret, 0) end
- if not \(mangle "fell_through") then return ret end
- end
- ")
-
-test:
assume ((result of: return 99) == 99)
# Inline thunk:
diff --git a/core/errors.nom b/core/errors.nom
index 6779922..0b63b5b 100644
--- a/core/errors.nom
+++ b/core/errors.nom
@@ -3,11 +3,12 @@
This file contains basic error reporting code
use "core/metaprogramming.nom"
+use "core/operators.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(barf $msg) compiles to
- "error(\(=lua "\$msg and \($msg as lua expr) or 'nil'"), 0);"
+(fail $msg) compiles to
+ "error(\(($msg as lua expr) if $msg else "nil"), 0);"
(assume $condition) compiles to:
lua> ("
@@ -37,62 +38,86 @@ use "core/metaprogramming.nom"
end
")
-(assume $condition or barf $message) compiles to ("
- if not \($condition as lua expr) then
- error(\($message as lua expr), 0)
- end
-")
-
test:
- try (barf) and if it succeeds:
- barf "try failed."
+ try: fail
$worked = (no)
- try (barf) and if it barfs:
+ try: fail
+ ..if it fails:
$worked = (yes)
- assume $worked or barf "try/catch failed"
- $x = 1
- try:
- $x = 2
- do (barf) then always: $x = 3
- ..and if it barfs:
- do nothing
- assume ($x == 3) or barf "do/then always failed"
-
+ ..if it succeeds:
+ fail "'try' incorrectly ran success case."
+
+ unless $worked:
+ fail "'try' failed to recover from failure"
# Try/except
[
- try $action and if it succeeds $success or if it barfs $msg $fallback
- try $action and if it barfs $msg $fallback or if it succeeds $success
-] all compile to ("
- do
- local fell_through = false
- local err, erred = nil, false
- local ok, ret = xpcall(function()
- \($action as lua)
- fell_through = true
- end, function(\(=lua "\$fallback and \($msg as lua expr) or ''"))
- local ok, ret = pcall(function()
- \((=lua "\$fallback or \$msg") as lua)
- end)
- if not ok then err, erred = ret, true end
- end)
- if ok then
- \($success as lua)
- if not fell_through then
- return ret
+ try $action if it succeeds $success if it fails $fallback
+ try $action if it fails $fallback if it succeeds $success
+] all compile to:
+ $success_lua = ($success as lua)
+ if ((#"\$success_lua") > 0): $success_lua, add "\n"
+ $success_lua, prepend "-- Success:\n"
+ $success_lua, add "if not _fell_through then return table.unpack(_result, 2) end"
+ $fallback_lua = ($fallback as lua)
+ if ((#"\$fallback_lua") > 0):
+ $fallback_lua, prepend "\nlocal function failure() return _result[2] end\n"
+ $fallback_lua, prepend "-- Failure:"
+ return
+ Lua ("
+ do
+ local _fell_through = false
+ local _result = {pcall(function()
+ \($action as lua)
+ _fell_through = true
+ end)}
+ if _result[1] then
+ \$success_lua
+ else
+ \$fallback_lua
+ end
end
- elseif erred then
- error(err, 0)
- end
- end
-")
+ ")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(try $action) parses as
- try $action and if it succeeds (do nothing) or if it barfs (do nothing)
+ try $action if it succeeds (do nothing) if it fails (do nothing)
+
+(try $action if it fails $msg $fallback) parses as
+ try $action if it succeeds (do nothing) if it fails $msg $fallback
+
+(try $action if it succeeds $success) parses as
+ try $action if it succeeds $success if it fails (do nothing)
+
+(try $action if it fails $fallback if it succeeds $success) parses as
+ try $action if it succeeds $success if it fails $fallback
+
+test:
+ $success = (no)
+ try:
+ do: fail
+ ..then always:
+ $success = (yes)
+ ..if it succeeds:
+ fail "'try ... then always ...' didn't propagate failure"
+
+ unless $success:
+ fail "'try ... then always ...' didn't execute the 'always' code"
+
+(do $action then always $final_action) compiles to ("
+ do -- do/then always
+ local _fell_through = false
+ local _results = {pcall(function()
+ \($action as lua)
+ _fell_through = true
+ end)}
+ \($final_action as lua)
+ if not _results[1] then error(_results[2], 0) end
+ if not _fell_through then return table.unpack(_results, 2) end
+ end
+")
-(try $action and if it barfs $msg $fallback) parses as
- try $action and if it succeeds (do nothing) or if it barfs $msg $fallback
+~~~
-(try $action and if it succeeds $success) parses as
- try $action and if it succeeds $success or if it barfs (do nothing)
+(barf $) parses as (fail $)
+(assume $1 or barf $2) parses as (unless $1: fail $2)
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 2e1bf6b..b4297dd 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -308,11 +308,11 @@ externally ($ is $kind syntax tree) means
($tree with $t -> $replacement) compiles to ("
\($tree as lua expr):map(function(\($t as lua expr))
\(
- =lua ("
- \$replacement.type == 'Block' and \($replacement as lua) or 'return '..\
- ..\($replacement as lua expr)
- ")
- )
+ =lua ("
+ \$replacement.type == 'Block' and \($replacement as lua) or 'return '..\
+ ..\($replacement as lua expr)
+ ")
+ )
end)
")
diff --git a/core/operators.nom b/core/operators.nom
index 8d646e9..6c089a6 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -3,7 +3,6 @@
This file contains definitions of operators like "+" and "and".
use "core/metaprogramming.nom"
-use "core/errors.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/nomsu.6.peg b/nomsu.6.peg
index 6b4686d..6a1725a 100644
--- a/nomsu.6.peg
+++ b/nomsu.6.peg
@@ -168,7 +168,11 @@ blank_text_lines <-
{~ (%nl ((ws* -> '') (&%nl / !.) / (=curr_indent -> '') &[^%nl]))+ ~}
text_interpolation <-
- ("\" (indented_block (blank_lines =curr_indent "..")? / indented_expression))
+ ({|
+ -- %indentation will backtrack and match the actual indentation of the current line
+ "\" {:curr_indent: %indentation :}
+ (indented_block (blank_lines =curr_indent "..")? / indented_expression)
+ |} -> unpack)
/ inline_text_interpolation
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index 9b8fc87..2b49112 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -304,7 +304,7 @@ local compile = setmetatable({
lua:add(",")
end
if lua:trailing_line_len() + #(entry_lua:text():match("^[\n]*")) > MAX_LINE then
- lua:add("\n")
+ lua:add("\n ")
elseif needs_comma then
lua:add(" ")
end
@@ -417,6 +417,8 @@ local compile = setmetatable({
if tree[i].type == "Comment" then
items_lua:add("\n")
sep = ''
+ elseif items_lua:trailing_line_len() > MAX_LINE then
+ sep = ',\n '
else
sep = ', '
end
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index 12a7529..45e863d 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -234,7 +234,7 @@ compile = setmetatable({
entry_lua\add as_lua(v)
if needs_comma then lua\add ","
if lua\trailing_line_len! + #(entry_lua\text!\match("^[\n]*")) > MAX_LINE
- lua\add "\n"
+ lua\add "\n "
elseif needs_comma
lua\add " "
lua\add entry_lua
@@ -322,6 +322,8 @@ compile = setmetatable({
if tree[i].type == "Comment"
items_lua\add "\n"
sep = ''
+ elseif items_lua\trailing_line_len! > MAX_LINE
+ sep = ',\n '
else
sep = ', '
i += 1
diff --git a/parser.lua b/parser.lua
index 523e223..09386fa 100644
--- a/parser.lua
+++ b/parser.lua
@@ -26,6 +26,13 @@ do
_with_0.unpack = unpack or table.unpack
_with_0["nil"] = Cc(nil)
_with_0.userdata = Carg(1)
+ _with_0.indentation = lpeg.Cmt(P(0), function(s, i)
+ local sub = string.sub
+ while i > 1 and sub(s, i - 1, i - 1) ~= '\n' do
+ i = i - 1
+ end
+ return true, (s:match("^ *", i))
+ end)
_with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191"))
_with_0.Tree = function(t, userdata)
return userdata.make_tree(t, userdata)
diff --git a/parser.moon b/parser.moon
index 122b58c..3f36953 100644
--- a/parser.moon
+++ b/parser.moon
@@ -25,6 +25,13 @@ DEFS = with {}
.unpack = unpack or table.unpack
.nil = Cc(nil)
.userdata = Carg(1)
+ -- Always match and capture the indentation (spaces only) of the current line
+ -- i.e. the leading space of the chunk of non-newline characters leading up to s[i]
+ .indentation = lpeg.Cmt P(0),
+ (s, i)->
+ sub = string.sub
+ while i > 1 and sub(s,i-1,i-1) != '\n' do i -= 1
+ return true, (s\match("^ *", i))
.utf8_char = (
R("\194\223")*R("\128\191") +
R("\224\239")*R("\128\191")*R("\128\191") +
diff --git a/tools/repl.nom b/tools/repl.nom
index 983de5f..4240ddc 100755
--- a/tools/repl.nom
+++ b/tools/repl.nom
@@ -42,25 +42,44 @@ repeat:
if ((size of $buff) == 0): stop
$buff = ($buff, joined)
-
- # TODO: support local variables
spoof file $buff
try:
- $ret = (run $buff)
- ..and if it barfs $err: say $err
- ..or if it succeeds:
- if (type of $ret) is:
- "nil":
- do nothing
-
- "boolean":
- say "= \("yes" if $ret else "no")"
-
- "table":
- if $ret.as_nomsu:
- say "= \($ret, as nomsu)"
- ..else:
+ $tree = ($buff parsed)
+ ..and if it barfs $err:
+ say $err
+ do next
+
+ unless $tree:
+ do next
+
+ for $chunk in $tree:
+ try:
+ $lua = ($chunk as lua)
+ ..and if it barfs $err: say $err
+
+ unless $lua:
+ do next
+
+ # TODO: this is a bit hacky, it just defaults variables to global
+ so that stuff mostly works across multiple lines. It would be
+ nicer if local variables actually worked.
+ $lua, remove free vars
+ try:
+ $ret = (run $lua)
+ ..and if it barfs $err: say $err
+ ..or if it succeeds:
+ if (type of $ret) is:
+ "nil":
+ do nothing
+
+ "boolean":
+ say "= \("yes" if $ret else "no")"
+
+ "table":
+ if $ret.as_nomsu:
+ say "= \($ret, as nomsu)"
+ ..else:
+ say "= \$ret"
+
+ else:
say "= \$ret"
-
- else:
- say "= \$ret"