aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--code_obj.lua59
-rw-r--r--code_obj.moon29
-rw-r--r--compatibility/compatibility.nom4
-rw-r--r--containers.lua20
-rw-r--r--containers.moon6
-rw-r--r--core/control_flow.nom1
-rw-r--r--core/io.nom8
-rw-r--r--core/math.nom8
-rw-r--r--core/metaprogramming.nom33
-rw-r--r--core/operators.nom11
-rw-r--r--core/text.nom22
-rw-r--r--lib/consolecolor.nom2
-rw-r--r--lib/object.nom2
-rw-r--r--lib/things.nom2
-rw-r--r--nomsu.lua6
-rwxr-xr-xnomsu.moon6
-rw-r--r--nomsu_compiler.lua140
-rw-r--r--nomsu_compiler.moon110
-rw-r--r--nomsu_decompiler.lua34
-rw-r--r--nomsu_decompiler.moon34
-rw-r--r--nomsu_environment.lua18
-rw-r--r--nomsu_environment.moon17
22 files changed, 286 insertions, 286 deletions
diff --git a/code_obj.lua b/code_obj.lua
index 4fd01d6..376ee0c 100644
--- a/code_obj.lua
+++ b/code_obj.lua
@@ -110,9 +110,23 @@ do
return self:text()
end,
as_lua = function(self)
- return tostring(self.__class.__name) .. "(" .. tostring(concat({
- tostring(self.source):as_lua(),
- unpack((function()
+ if self.source then
+ return tostring(self.__class.__name) .. ":from(" .. tostring(concat({
+ tostring(self.source):as_lua(),
+ unpack((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ local _list_0 = self.bits
+ for _index_0 = 1, #_list_0 do
+ local b = _list_0[_index_0]
+ _accum_0[_len_0] = b:as_lua()
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)())
+ }, ", ")) .. ")"
+ else
+ return tostring(self.__class.__name) .. "(" .. tostring(concat((function()
local _accum_0 = { }
local _len_0 = 1
local _list_0 = self.bits
@@ -122,8 +136,8 @@ do
_len_0 = _len_0 + 1
end
return _accum_0
- end)())
- }, ", ")) .. ")"
+ end)(), ", ")) .. ")"
+ end
end,
__len = function(self)
return #self:text()
@@ -246,12 +260,8 @@ do
}
_base_0.__index = _base_0
_class_0 = setmetatable({
- __init = function(self, source, ...)
- self.source = source
+ __init = function(self, ...)
self.bits = { }
- if type(self.source) == 'string' then
- self.source = Source:from_string(self.source)
- end
return self:append(...)
end,
__base = _base_0,
@@ -266,6 +276,14 @@ do
})
_base_0.__class = _class_0
local self = _class_0
+ self.from = function(self, source, ...)
+ local inst = self(...)
+ if type(source) == 'string' then
+ source = Source:from_string(source)
+ end
+ inst.source = source
+ return inst
+ end
self.is_instance = function(self, x)
return type(x) == 'table' and x.__class == self
end
@@ -370,27 +388,8 @@ do
end
return to_declare
end,
- as_statements = function(self, prefix, suffix)
- if prefix == nil then
- prefix = ""
- end
- if suffix == nil then
- suffix = ";"
- end
- if self:text():matches(";$") or self:text() == "" then
- return self
- end
- local statements = LuaCode(self.source)
- if prefix ~= "" then
- statements:append(prefix)
- end
- statements:append(self)
- if suffix ~= "" then
- statements:append(suffix)
- end
- return statements
- end,
make_offset_table = function(self)
+ assert(self.source, "This code doesn't have a source")
local lua_to_nomsu, nomsu_to_lua = { }, { }
local walk
walk = function(lua, pos)
diff --git a/code_obj.moon b/code_obj.moon
index fcf2217..e7fb5f3 100644
--- a/code_obj.moon
+++ b/code_obj.moon
@@ -43,13 +43,17 @@ class Source
class Code
is_code: true
- new: (@source, ...)=>
+ new: (...)=>
@bits = {}
- if type(@source) == 'string'
- @source = Source\from_string(@source)
- --assert(@source and Source\is_instance(@source), "Source has the wrong type")
@append(...)
+ @from: (source, ...)=>
+ inst = self(...)
+ if type(source) == 'string'
+ source = Source\from_string(source)
+ inst.source = source
+ return inst
+
@is_instance: (x)=> type(x) == 'table' and x.__class == @
text: =>
@@ -71,7 +75,10 @@ class Code
__tostring: => @text!
as_lua: =>
- "#{@__class.__name}(#{concat {tostring(@source)\as_lua!, unpack([b\as_lua! for b in *@bits])}, ", "})"
+ if @source
+ "#{@__class.__name}:from(#{concat {tostring(@source)\as_lua!, unpack([b\as_lua! for b in *@bits])}, ", "})"
+ else
+ "#{@__class.__name}(#{concat [b\as_lua! for b in *@bits], ", "})"
__len: => #@text!
@@ -214,18 +221,8 @@ class LuaCode extends Code
@prepend "local #{concat to_declare, ", "};\n"
return to_declare
- as_statements: (prefix="", suffix=";")=>
- if @text!\matches(";$") or @text! == ""
- return self
- statements = LuaCode(@source)
- if prefix != ""
- statements\append prefix
- statements\append self
- if suffix != ""
- statements\append suffix
- return statements
-
make_offset_table: =>
+ assert @source, "This code doesn't have a source"
-- Return a mapping from output (lua) character number to input (nomsu) character number
lua_to_nomsu, nomsu_to_lua = {}, {}
walk = (lua, pos)->
diff --git a/compatibility/compatibility.nom b/compatibility/compatibility.nom
index 184ca56..4e22dbc 100644
--- a/compatibility/compatibility.nom
+++ b/compatibility/compatibility.nom
@@ -79,13 +79,13 @@ externally [..]
if ((%ver as list) > (%end_version as list)): stop %ver
if %ACTION_UPGRADES.%ver:
%tree = (..)
- %tree with % -> (..)
+ %tree with % ->:
if ((% is "Action" syntax tree) and %ACTION_UPGRADES.%ver.(%.stub)):
%with_upgraded_args = (..)
%k = (%v upgraded from %start_version to %end_version) for %k = %v in %
set %with_upgraded_args 's metatable to (% 's metatable)
return (..)
- call %ACTION_UPGRADES.%ver.(%.stub) with [%with_upgraded_args, %end_version]
+ %ACTION_UPGRADES.%ver.(%.stub) %with_upgraded_args %end_version
if %UPGRADES.%ver:
%with_upgraded_args = (..)
diff --git a/containers.lua b/containers.lua
index 17d37a2..f33c2ff 100644
--- a/containers.lua
+++ b/containers.lua
@@ -210,19 +210,21 @@ local _list_mt = {
end,
from_1_to = function(self, start, stop)
local n = #self
- if n < 0 then
+ if start < 0 then
start = (n + 1 - start)
end
- if n < 0 then
+ if stop < 0 then
stop = (n + 1 - stop)
end
- local _accum_0 = { }
- local _len_0 = 1
- for i = start, stop do
- _accum_0[_len_0] = self[i]
- _len_0 = _len_0 + 1
- end
- return _accum_0
+ return List((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for i = start, stop do
+ _accum_0[_len_0] = self[i]
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)())
end
},
__newindex = function(self, k, v)
diff --git a/containers.moon b/containers.moon
index 4cafdaf..990a741 100644
--- a/containers.moon
+++ b/containers.moon
@@ -85,9 +85,9 @@ _list_mt =
return nil
from_1_to: (start, stop)=>
n = #@
- start = (n+1-start) if n < 0
- stop = (n+1-stop) if n < 0
- return [@[i] for i=start,stop]
+ start = (n+1-start) if start < 0
+ stop = (n+1-stop) if stop < 0
+ return List[@[i] for i=start,stop]
-- TODO: remove this safety check to get better performance?
__newindex: (k,v)=>
assert type(k) == 'number', "List indices must be numbers"
diff --git a/core/control_flow.nom b/core/control_flow.nom
index cba0777..ff1a7c1 100644
--- a/core/control_flow.nom
+++ b/core/control_flow.nom
@@ -4,7 +4,6 @@
like "if" statements and loops.
use "core/metaprogramming.nom"
-use "core/text.nom"
use "core/operators.nom"
use "core/errors.nom"
diff --git a/core/io.nom b/core/io.nom
index edeeab4..2df0999 100644
--- a/core/io.nom
+++ b/core/io.nom
@@ -9,17 +9,17 @@ use "core/metaprogramming.nom"
(say %message) compiles to:
lua> "\
..if \%message.type == "Text" then
- return LuaCode(tree.source, "print(", \(%message as lua expr), ");");
+ return LuaCode("print(", \(%message as lua expr), ");");
else
- return LuaCode(tree.source, "print(tostring(", \(%message as lua expr), "));");
+ return LuaCode("print(tostring(", \(%message as lua expr), "));");
end"
(ask %prompt) compiles to:
lua> "\
..if \%prompt.type == "Text" then
- return LuaCode(tree.source, "(io.write(", \(%prompt as lua expr), ") and io.read())");
+ return LuaCode("(io.write(", \(%prompt as lua expr), ") and io.read())");
else
- return LuaCode(tree.source, "(io.write(tostring(", \(..)
+ return LuaCode("(io.write(tostring(", \(..)
%prompt as lua expr
.., ")) and io.read())");
end"
diff --git a/core/math.nom b/core/math.nom
index 1c7306e..8951721 100644
--- a/core/math.nom
+++ b/core/math.nom
@@ -85,7 +85,7 @@ externally [all of %items, all %items] all mean:
return (yes)
[all of %items, all %items] all compile to:
unless (%items.type is "List"):
- return %tree
+ return \(all of %items)
if ((size of %items) == 0): return (Lua "true")
%lua = (Lua "(")
%lua::add ((% as lua expr) for % in %items) joined with " and "
@@ -99,7 +99,7 @@ externally [any of %items, any %items] all mean:
return (no)
[any of %items, any %items] all compile to:
unless (%items.type is "List"):
- return %tree
+ return \(any of %items)
if ((size of %items) == 0): return (Lua "false")
%lua = (Lua "(")
%lua::add ((% as lua expr) for % in %items) joined with " or "
@@ -114,7 +114,7 @@ externally [sum of %items, sum %items] all mean:
return %total
[sum of %items, sum %items] all compile to:
unless (%items.type is "List"):
- return %tree
+ return \(sum of %items)
if ((size of %items) == 0): return (Lua "0")
%lua = (Lua "(")
%lua::add ((% as lua expr) for % in %items) joined with " + "
@@ -127,7 +127,7 @@ externally [product of %items, product %items] all mean:
return %prod
[product of %items, product %items] all compile to:
unless (%items.type is "List"):
- return %tree
+ return \(product of %items)
if ((size of %items) == 0): return (Lua "1")
%lua = (Lua "(")
%lua::add ((% as lua expr) for % in %items) joined with " * "
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index 1f787c2..fc81e15 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -17,13 +17,13 @@ lua> "\
end
end
end
- compile.action["define mangler"] = function(compile, tree)
- return LuaCode(tree.source, "local mangle = mangler()")
+ compile.action["define mangler"] = function(compile)
+ return LuaCode("local mangle = mangler()")
end"
lua> "\
- ..compile.action["1 ->"] = function(compile, tree, \%args, \%body)
- local lua = LuaCode(tree.source, "(function(")
+ ..compile.action["1 ->"] = function(compile, \%args, \%body)
+ local lua = LuaCode("(function(")
if SyntaxTree:is_instance(\%args) and \%args.type == "Action" then \%args = \%args:get_args() end
local lua_args = table.map(\%args, function(a) return SyntaxTree:is_instance(a) and compile(a):text() or a end)
lua:concat_append(lua_args, ", ")
@@ -36,11 +36,10 @@ lua> "\
end"
lua> "\
- ..compile.action["what 1 compiles to"] = function(compile, tree, \%action)
- local lua = LuaCode(tree.source, "compile.action[", \%action.stub:as_lua(), "](")
+ ..compile.action["what 1 compiles to"] = function(compile, \%action)
+ local lua = LuaCode("compile.action[", \%action.stub:as_lua(), "](")
local lua_args = table.map(\%action:get_args(), function(a) return compile(a) end)
table.insert(lua_args, 1, "compile")
- table.insert(lua_args, 2, "tree")
lua:concat_append(lua_args, ", ")
lua:append(")")
return lua
@@ -66,12 +65,12 @@ test:
asdf
assume (%tmp is (nil)) or barf "compile to is leaking variables"
lua> "\
- ..compile.action["1 compiles to"] = function(compile, tree, \%action, \%body)
- local \%args = List{\(\%compile), \(\%tree), unpack(\%action:get_args())}
+ ..compile.action["1 compiles to"] = function(compile, \%action, \%body)
+ local \%args = List{\(\%compile), unpack(\%action:get_args())}
if \%body.type == "Text" then
\%body = SyntaxTree{source=\%body.source, type="Action", "Lua", \%body}
end
- return LuaCode(tree.source, "compile.action[", \%action.stub:as_lua(),
+ return LuaCode("compile.action[", \%action.stub:as_lua(),
"] = ", \(what (%args -> %body) compiles to))
end"
@@ -82,11 +81,11 @@ lua> "\
..if \%actions.type ~= "List" then
compile_error(\%actions, "This should be a list of actions.")
end
- local lua = LuaCode(tree.source, \(what (%actions.1 compiles to %body) compiles to))
- local \%args = List{\(\%compile), \(\%tree), unpack(\%actions[1]:get_args())}
+ local lua = \(what (%actions.1 compiles to %body) compiles to)
+ local \%args = List{\(\%compile), unpack(\%actions[1]:get_args())}
for i=2,#\%actions do
local alias = \%actions[i]
- local \%alias_args = List{\(\%compile), \(\%tree), unpack(alias:get_args())}
+ local \%alias_args = List{\(\%compile), unpack(alias:get_args())}
lua:append("\\ncompile.action[", alias.stub:as_lua(), "] = ")
if \%alias_args == \%args then
lua:append("compile.action[", \%actions[1].stub:as_lua(), "]")
@@ -100,7 +99,7 @@ lua> "\
(call %fn with %args) compiles to:
lua> "\
- ..local lua = LuaCode(tree.source, compile(\%fn), "(")
+ ..local lua = LuaCode(compile(\%fn), "(")
if \%args.type == 'List' then
lua:concat_append(table.map(\%args, function(a) return compile(a) end), ", ")
else
@@ -126,14 +125,14 @@ test:
lua> "\
..local fn_name = \%action.stub:as_lua_id()
local \%args = \%action:get_args()
- local lua = LuaCode(tree.source, fn_name, " = ", \(what (%args -> %body) compiles to))
+ local lua = LuaCode(fn_name, " = ", \(what (%args -> %body) compiles to))
lua:add_free_vars({fn_name})
return lua"
(%actions all mean %body) compiles to:
lua> "\
..local fn_name = \%actions[1].stub:as_lua_id()
local \%args = List(\%actions[1]:get_args())
- local lua = LuaCode(tree.source, \(what (%actions.1 means %body) compiles to))
+ local lua = \(what (%actions.1 means %body) compiles to)
for i=2,#\%actions do
local alias = \%actions[i]
local alias_name = alias.stub:as_lua_id()
@@ -222,7 +221,7 @@ test:
return t:as_lua()
end
end
- local \%new_body = LuaCode(\%body.source,
+ local \%new_body = LuaCode:from(\%body.source,
"local mangle = mangler()",
"\\nreturn ", make_tree(\%body))
local ret = \(what (%actions all compile to %new_body) compiles to)
diff --git a/core/operators.nom b/core/operators.nom
index 38fc9a8..19a61d7 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -31,7 +31,7 @@ test:
lua> "\
..local \%var_lua = \(%var as lua expr)
local \%value_lua = \(%value as lua expr)
- local lua = LuaCode(tree.source, \%var_lua, ' = ', \%value_lua, ';')
+ local lua = LuaCode(\%var_lua, ' = ', \%value_lua, ';')
if \%var.type == 'Var' then
lua:add_free_vars({compile(\%var):text()})
end
@@ -49,7 +49,7 @@ test:
assume (%assignments.type is "Dict") or barf "\
..Expected a Dict for the assignments part of '<- %' statement, not \%assignments"
lua> "\
- ..local lhs, rhs = LuaCode(tree.source), LuaCode(tree.source)
+ ..local lhs, rhs = LuaCode(), LuaCode()
for i, item in ipairs(\%assignments) do
local \%target, \%value = item[1], item[2]
\%value = \%value:map(function(t)
@@ -69,7 +69,7 @@ test:
lhs:append(target_lua)
rhs:append(value_lua)
end
- return LuaCode(tree.source, lhs, " = ", rhs, ";")"
+ return LuaCode(lhs, " = ", rhs, ";")"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -111,7 +111,7 @@ test:
(with %assignments %body) compiles to:
%lua = (%body as lua)
lua> "\
- ..local lhs, rhs = LuaCode(tree.source), LuaCode(tree.source)
+ ..local lhs, rhs = LuaCode(), LuaCode()
local vars = {}
for i, item in ipairs(\%assignments) do
local \%target, \%value = item[1], item[2]
@@ -233,8 +233,7 @@ test:
test:
assume ((size of [1, 2, 3]) == 3)
-[size of %list, size of %list, size of %list, size of %list] all compile to (..)
- "(#\(%list as lua expr))"
+(size of %list) compiles to "(#\(%list as lua expr))"
(%list is empty) compiles to "(#\(%list as lua expr) == 0)"
diff --git a/core/text.nom b/core/text.nom
index 2d72f01..d4cd227 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -4,6 +4,8 @@
color codes.
use "core/metaprogramming.nom"
+use "core/operators.nom"
+use "core/control_flow.nom"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -47,17 +49,9 @@ test:
assume "\n" == (newline)
# Text literals
-lua> "\
- ..do
- local escapes = {
- nl="\\\\n", newline="\\\\n", tab="\\\\t", bell="\\\\a", cr="\\\\r",
- ["carriage return"]="\\\\r", backspace="\\\\b", ["form feed"]="\\\\f",
- formfeed="\\\\f", ["vertical tab"]="\\\\v",
- };
- for name, e in pairs(escapes) do
- local lua = "'"..e.."'"
- compile.action[name] = function(compile, tree)
- return LuaCode(tree.source, lua)
- end
- end
- end"
+%escapes = {..}
+ nl:"\n", newline:"\n", tab:"\t", bell:"\a", cr:"\r", "carriage return":"\r",
+ backspace:"\b", "form feed":"\f", formfeed:"\f", "vertical tab":"\v"
+for %name = %str in %escapes:
+ with {%lua: Lua (quote %str)}:
+ %compile.action.%name = ([]-> %lua)
diff --git a/lib/consolecolor.nom b/lib/consolecolor.nom
index d8b078f..1016c0b 100644
--- a/lib/consolecolor.nom
+++ b/lib/consolecolor.nom
@@ -17,7 +17,7 @@ for %name = %colornum in %colors:
#(=lua "COMPILE_ACTIONS").%name = (..)
[%nomsu, %tree] -> (Lua "'\\027[\(%colornum)m'")
%compile.action.%name = (..)
- [%nomsu, %tree, %text] ->:
+ [%nomsu, %text] ->:
if %text:
return (Lua "('\\027[\(%colornum)m'..\(%text as lua expr)..'\\027[0m')")
..else: return (Lua "'\\027[\(%colornum)m'")
diff --git a/lib/object.nom b/lib/object.nom
index 2af5412..bb2de3a 100644
--- a/lib/object.nom
+++ b/lib/object.nom
@@ -56,7 +56,7 @@ test:
..local fn_name = \%actions[1].stub:as_lua_id()
local \%args = List(\%actions[1]:get_args())
table.insert(\%args, 1, \(\%me))
- local lua = LuaCode(tree.source, "class.", fn_name, " = ", \(..)
+ local lua = LuaCode("class.", fn_name, " = ", \(..)
what (%args -> %body) compiles to
..)
for i=2,#\%actions do
diff --git a/lib/things.nom b/lib/things.nom
index 4f15e68..50c7aaa 100644
--- a/lib/things.nom
+++ b/lib/things.nom
@@ -60,7 +60,7 @@ test:
lua> "\
..local fn_name = \%actions[1].stub:as_lua_id()
local \%args = List{\(\%its), unpack(\%actions[1]:get_args())}
- local lua = LuaCode(tree.source, "class.", fn_name, " = ", \(..)
+ local lua = LuaCode("class.", fn_name, " = ", \(..)
what (%args -> %body) compiles to
..)
for i=2,#\%actions do
diff --git a/nomsu.lua b/nomsu.lua
index 82c0d02..9010227 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -181,7 +181,7 @@ run = function()
if args.check_syntax then
local code = Files.read(filename)
local source = Source(filename, 1, #code)
- nomsu_environment._1_parsed(NomsuCode(source, code))
+ nomsu_environment._1_parsed(NomsuCode:from(source, code))
print("Parse succeeded: " .. tostring(filename))
elseif args.compile then
local output
@@ -192,7 +192,7 @@ run = function()
end
local code = Files.read(filename)
local source = Source(filename, 1, #code)
- code = NomsuCode(source, code)
+ code = NomsuCode:from(source, code)
local tree = nomsu_environment._1_parsed(code)
if not (tree.type == 'FileChunks') then
tree = {
@@ -214,7 +214,7 @@ run = function()
elseif args.verbose then
local code = Files.read(filename)
local source = Source(filename, 1, #code)
- code = NomsuCode(source, code)
+ code = NomsuCode:from(source, code)
local tree = nomsu_environment._1_parsed(code)
if not (tree.type == 'FileChunks') then
tree = {
diff --git a/nomsu.moon b/nomsu.moon
index 8825ba5..35726e7 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -117,7 +117,7 @@ run = ->
-- Check syntax
code = Files.read(filename)
source = Source(filename, 1, #code)
- nomsu_environment._1_parsed(NomsuCode(source, code))
+ nomsu_environment._1_parsed(NomsuCode\from(source, code))
print("Parse succeeded: #{filename}")
elseif args.compile
-- Compile .nom files into .lua
@@ -125,7 +125,7 @@ run = ->
else io.open(filename\gsub("%.nom$", ".lua"), "w")
code = Files.read(filename)
source = Source(filename, 1, #code)
- code = NomsuCode(source, code)
+ code = NomsuCode\from(source, code)
tree = nomsu_environment._1_parsed(code)
tree = {tree} unless tree.type == 'FileChunks'
for chunk in *tree
@@ -139,7 +139,7 @@ run = ->
elseif args.verbose
code = Files.read(filename)
source = Source(filename, 1, #code)
- code = NomsuCode(source, code)
+ code = NomsuCode\from(source, code)
tree = nomsu_environment._1_parsed(code)
tree = {tree} unless tree.type == 'FileChunks'
for chunk in *tree
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index d293d99..f262dd8 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -63,30 +63,11 @@ do
tree_to_nomsu, tree_to_inline_nomsu = _obj_0.tree_to_nomsu, _obj_0.tree_to_inline_nomsu
end
local math_expression = re.compile([[ (([*/^+-] / [0-9]+) " ")* [*/^+-] !. ]])
-local compile_math_expression
-compile_math_expression = function(compile, tree, ...)
- local lua = LuaCode(tree.source)
- for i, tok in ipairs(tree) do
- if type(tok) == 'string' then
- lua:append(tok)
- else
- local tok_lua = compile(tok)
- if tok.type == "Action" then
- tok_lua:parenthesize()
- end
- lua:append(tok_lua)
- end
- if i < #tree then
- lua:append(" ")
- end
- end
- return lua
-end
local MAX_LINE = 80
local compile = setmetatable({
action = Importer({
- [""] = function(compile, tree, fn, ...)
- local lua = LuaCode(tree.source)
+ [""] = function(compile, fn, ...)
+ local lua = LuaCode()
local fn_lua = compile(fn)
lua:append(fn_lua)
if not (fn_lua:text():match("^%(.*%)$") or fn_lua:text():match("^[_a-zA-Z][_a-zA-Z0-9.]*$")) then
@@ -102,9 +83,9 @@ local compile = setmetatable({
lua:append(")")
return lua
end,
- ["Lua"] = function(compile, tree, code)
+ ["Lua"] = function(compile, code)
if code.type ~= "Text" then
- return LuaCode(code.source, "LuaCode(", tostring(code.source):as_lua(), ", ", compile(code), ")")
+ return LuaCode("LuaCode:from(", tostring(code.source):as_lua(), ", ", compile(code), ")")
end
local add_bit_lua
add_bit_lua = function(lua, bit_lua)
@@ -114,7 +95,7 @@ local compile = setmetatable({
end
local operate_on_text
operate_on_text = function(text)
- local lua = LuaCode(text.source, "LuaCode(", tostring(text.source):as_lua())
+ local lua = LuaCode:from(text.source, "LuaCode:from(", tostring(text.source):as_lua())
for _index_0 = 1, #text do
local bit = text[_index_0]
if type(bit) == "string" then
@@ -130,13 +111,13 @@ local compile = setmetatable({
end
return operate_on_text(code)
end,
- ["lua >"] = function(compile, tree, code)
+ ["lua >"] = function(compile, code)
if code.type ~= "Text" then
- return tree
+ return code
end
local operate_on_text
operate_on_text = function(text)
- local lua = LuaCode(text.source)
+ local lua = LuaCode:from(text.source)
for _index_0 = 1, #text do
local bit = text[_index_0]
if type(bit) == "string" then
@@ -151,18 +132,18 @@ local compile = setmetatable({
end
return operate_on_text(code)
end,
- ["= lua"] = function(compile, tree, code)
- return compile.action["lua >"](compile, tree, code)
+ ["= lua"] = function(compile, code)
+ return compile.action["lua >"](compile, code)
end,
- ["use"] = function(compile, tree, path)
- return LuaCode(tree.source, "run_file_1_in(" .. tostring(compile(path)) .. ", _ENV)")
+ ["use"] = function(compile, path)
+ return LuaCode("run_file_1_in(" .. tostring(compile(path)) .. ", _ENV)")
end,
- ["tests"] = function(compile, tree)
- return LuaCode(tree.source, "TESTS")
+ ["tests"] = function(compile)
+ return LuaCode("TESTS")
end,
- ["test"] = function(compile, tree, body)
+ ["test"] = function(compile, body)
if not (body.type == 'Block') then
- compile_error(tree, "This should be a Block")
+ compile_error(body, "This should be a Block")
end
local test_nomsu = body:get_source_code():match(":[ ]*(.*)")
do
@@ -171,16 +152,16 @@ local compile = setmetatable({
test_nomsu = test_nomsu:gsub("\n" .. indent, "\n")
end
end
- return LuaCode(tree.source, "TESTS[" .. tostring(tostring(tree.source):as_lua()) .. "] = ", test_nomsu:as_lua())
+ return LuaCode("TESTS[" .. tostring(tostring(body.source):as_lua()) .. "] = ", test_nomsu:as_lua())
end,
- ["is jit"] = function(compile, tree, code)
- return LuaCode(tree.source, "jit")
+ ["is jit"] = function(compile, code)
+ return LuaCode("jit")
end,
- ["Lua version"] = function(compile, tree, code)
- return LuaCode(tree.source, "_VERSION")
+ ["Lua version"] = function(compile, code)
+ return LuaCode("_VERSION")
end,
- ["nomsu environment"] = function(compile, tree)
- return LuaCode(tree.source, "_ENV")
+ ["nomsu environment"] = function(compile)
+ return LuaCode("_ENV")
end
})
}, {
@@ -191,25 +172,27 @@ local compile = setmetatable({
if force_value == nil then
force_value = false
end
- if tree.version then
- do
- local get_version = compile.action[("Nomsu version"):as_lua_id()]
- if get_version then
- do
- local upgrade = compile.action[("1 upgraded from 2 to"):as_lua_id()]
- if upgrade then
- tree = upgrade(tree, tree.version, get_version())
- end
- end
- end
- end
- end
local _exp_0 = tree.type
if "Action" == _exp_0 then
local stub = tree.stub
local compile_action = compile.action[stub]
if not compile_action and math_expression:match(stub) then
- compile_action = compile_math_expression
+ local lua = LuaCode:from(tree.source)
+ for i, tok in ipairs(tree) do
+ if type(tok) == 'string' then
+ lua:append(tok)
+ else
+ local tok_lua = compile(tok)
+ if tok.type == "Action" then
+ tok_lua:parenthesize()
+ end
+ lua:append(tok_lua)
+ end
+ if i < #tree then
+ lua:append(" ")
+ end
+ end
+ return lua
end
if compile_action and not tree.target then
local args
@@ -225,20 +208,21 @@ local compile = setmetatable({
end
args = _accum_0
end
- local ret = compile_action(compile, tree, unpack(args))
+ local ret = compile_action(compile, unpack(args))
if ret == nil then
local info = debug.getinfo(compile_action, "S")
local filename = Source:from_string(info.source).filename
compile_error(tree, "The compile-time action here (" .. tostring(stub) .. ") failed to return any value.", "Look at the implementation of (" .. tostring(stub) .. ") in " .. tostring(filename) .. ":" .. tostring(info.linedefined) .. " and make sure it's returning something.")
end
if not (SyntaxTree:is_instance(ret)) then
+ ret.source = ret.source or tree.source
return ret
end
if ret ~= tree then
return compile(ret)
end
end
- local lua = LuaCode(tree.source)
+ local lua = LuaCode:from(tree.source)
if tree.target then
local target_lua = compile(tree.target)
local target_text = target_lua:text()
@@ -269,7 +253,7 @@ local compile = setmetatable({
lua:append(")")
return lua
elseif "EscapedNomsu" == _exp_0 then
- local lua = LuaCode(tree.source, "SyntaxTree{")
+ local lua = LuaCode:from(tree.source, "SyntaxTree{")
local needs_comma, i = false, 1
local as_lua
as_lua = function(x)
@@ -304,7 +288,7 @@ local compile = setmetatable({
return lua
elseif "Block" == _exp_0 then
if not force_value then
- local lua = LuaCode(tree.source)
+ local lua = LuaCode:from(tree.source)
lua:concat_append((function()
local _accum_0 = { }
local _len_0 = 1
@@ -317,7 +301,7 @@ local compile = setmetatable({
end)(), "\n")
return lua
else
- local lua = LuaCode(tree.source)
+ local lua = LuaCode:from(tree.source)
lua:append("((function()")
for i, line in ipairs(tree) do
lua:append("\n ", compile(line))
@@ -326,7 +310,7 @@ local compile = setmetatable({
return lua
end
elseif "Text" == _exp_0 then
- local lua = LuaCode(tree.source)
+ local lua = LuaCode:from(tree.source)
local string_buffer = ""
for i, bit in ipairs(tree) do
local _continue_0 = false
@@ -348,7 +332,7 @@ local compile = setmetatable({
lua:append("..")
end
if bit.type ~= "Text" then
- bit_lua = LuaCode(bit.source, "tostring(", bit_lua, ")")
+ bit_lua = LuaCode:from(bit.source, "tostring(", bit_lua, ")")
end
lua:append(bit_lua)
_continue_0 = true
@@ -368,7 +352,7 @@ local compile = setmetatable({
end
return lua
elseif "List" == _exp_0 or "Dict" == _exp_0 then
- local lua = LuaCode(tree.source, tostring(tree.type) .. "{")
+ local lua = LuaCode:from(tree.source, tostring(tree.type) .. "{")
local i = 1
local sep = ''
while i <= #tree do
@@ -389,32 +373,38 @@ local compile = setmetatable({
end
lua:append("}")
if i <= #tree then
- lua = LuaCode(tree.source, "(function()\n local it = ", lua)
+ lua = LuaCode:from(tree.source, "(function()\n local comprehension = ", lua)
+ if tree.type == "List" then
+ lua:append("\n local function add(x) comprehension[#comprehension+1] = x end")
+ else
+ lua:append("\n local function " .. tostring(("add 1 ="):as_lua_id()) .. "(k, v) comprehension[k] = v end")
+ end
while i <= #tree do
lua:append("\n ")
if tree[i].type == 'Block' or tree[i].type == 'Comment' then
lua:append(compile(tree[i]))
elseif tree[i].type == "DictEntry" then
- lua:append("it[ ", compile(tree[i][1]), "] = ", (tree[i][2] and compile(tree[i][2]) or "true"))
+ local entry_lua = compile(tree[i])
+ lua:append((entry_lua:text():sub(1, 1) == '[' and "comprehension" or "comprehension."), entry_lua)
else
- lua:append("it:add(", compile(tree[i]), ")")
+ lua:append("comprehension[#comprehension+1] = ", compile(tree[i]))
end
i = i + 1
end
- lua:append("\n return it\nend)()")
+ lua:append("\n return comprehension\nend)()")
end
return lua
elseif "DictEntry" == _exp_0 then
local key, value = tree[1], tree[2]
local key_lua = compile(key)
- local value_lua = value and compile(value) or LuaCode(key.source, "true")
+ local value_lua = value and compile(value) or LuaCode:from(key.source, "true")
local key_str = match(key_lua:text(), [=[^["']([a-zA-Z_][a-zA-Z0-9_]*)['"]$]=])
if key_str and key_str:is_lua_id() then
- return LuaCode(tree.source, key_str, "=", value_lua)
+ return LuaCode:from(tree.source, key_str, "=", value_lua)
elseif sub(key_lua:text(), 1, 1) == "[" then
- return LuaCode(tree.source, "[ ", key_lua, "]=", value_lua)
+ return LuaCode:from(tree.source, "[ ", key_lua, "]=", value_lua)
else
- return LuaCode(tree.source, "[", key_lua, "]=", value_lua)
+ return LuaCode:from(tree.source, "[", key_lua, "]=", value_lua)
end
elseif "IndexChain" == _exp_0 then
local lua = compile(tree[1])
@@ -437,13 +427,13 @@ local compile = setmetatable({
end
return lua
elseif "Number" == _exp_0 then
- return LuaCode(tree.source, tostring(tree[1]))
+ return LuaCode:from(tree.source, tostring(tree[1]))
elseif "Var" == _exp_0 then
- return LuaCode(tree.source, (tree[1]):as_lua_id())
+ return LuaCode:from(tree.source, (tree[1]):as_lua_id())
elseif "FileChunks" == _exp_0 then
return error("Can't convert FileChunks to a single block of lua, since each chunk's " .. "compilation depends on the earlier chunks")
elseif "Comment" == _exp_0 then
- return LuaCode(tree.source, "")
+ return LuaCode:from(tree.source, "")
elseif "Error" == _exp_0 then
return error("Can't compile errors")
else
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index 847da21..97cb0a7 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -40,23 +40,12 @@ compile_error = (tree, err_msg, hint=nil)->
-- math expressions like 2*x + 3^2 without having to define a single
-- action for every possibility.
math_expression = re.compile [[ (([*/^+-] / [0-9]+) " ")* [*/^+-] !. ]]
-compile_math_expression = (compile, tree, ...)->
- lua = LuaCode(tree.source)
- for i,tok in ipairs tree
- if type(tok) == 'string'
- lua\append tok
- else
- tok_lua = compile(tok)
- tok_lua\parenthesize! if tok.type == "Action"
- lua\append tok_lua
- lua\append " " if i < #tree
- return lua
MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
compile = setmetatable({
action: Importer{
- [""]: (compile, tree, fn, ...)->
- lua = LuaCode(tree.source)
+ [""]: (compile, fn, ...)->
+ lua = LuaCode!
fn_lua = compile(fn)
lua\append fn_lua
unless fn_lua\text!\match("^%(.*%)$") or fn_lua\text!\match("^[_a-zA-Z][_a-zA-Z0-9.]*$")
@@ -68,15 +57,15 @@ compile = setmetatable({
lua\append ")"
return lua
- ["Lua"]: (compile, tree, code)->
+ ["Lua"]: (compile, code)->
if code.type != "Text"
- return LuaCode(code.source, "LuaCode(", tostring(code.source)\as_lua!, ", ", compile(code), ")")
+ return LuaCode("LuaCode:from(", tostring(code.source)\as_lua!, ", ", compile(code), ")")
add_bit_lua = (lua, bit_lua)->
bit_leading_len = #(bit_lua\match("^[^\n]*"))
lua\append(lua\trailing_line_len! + bit_leading_len > MAX_LINE and ",\n " or ", ")
lua\append(bit_lua)
operate_on_text = (text)->
- lua = LuaCode(text.source, "LuaCode(", tostring(text.source)\as_lua!)
+ lua = LuaCode\from(text.source, "LuaCode:from(", tostring(text.source)\as_lua!)
for bit in *text
if type(bit) == "string"
add_bit_lua(lua, bit\as_lua!)
@@ -88,11 +77,11 @@ compile = setmetatable({
return lua
return operate_on_text code
- ["lua >"]: (compile, tree, code)->
+ ["lua >"]: (compile, code)->
if code.type != "Text"
- return tree
+ return code
operate_on_text = (text)->
- lua = LuaCode(text.source)
+ lua = LuaCode\from(text.source)
for bit in *text
if type(bit) == "string"
lua\append bit
@@ -103,47 +92,53 @@ compile = setmetatable({
return lua
return operate_on_text code
- ["= lua"]: (compile, tree, code)-> compile.action["lua >"](compile, tree, code)
+ ["= lua"]: (compile, code)-> compile.action["lua >"](compile, code)
- ["use"]: (compile, tree, path)->
+ ["use"]: (compile, path)->
--if path.type == 'Text' and #path == 1 and type(path[1]) == 'string'
-- unless import_to_1_from(compile, path[1])
-- compile_error tree, "Could not find anything to import for #{path}"
- return LuaCode(tree.source, "run_file_1_in(#{compile(path)}, _ENV)")
+ return LuaCode("run_file_1_in(#{compile(path)}, _ENV)")
- ["tests"]: (compile, tree)-> LuaCode(tree.source, "TESTS")
- ["test"]: (compile, tree, body)->
+ ["tests"]: (compile)-> LuaCode("TESTS")
+ ["test"]: (compile, body)->
unless body.type == 'Block'
- compile_error(tree, "This should be a Block")
+ compile_error(body, "This should be a Block")
test_nomsu = body\get_source_code!\match(":[ ]*(.*)")
if indent = test_nomsu\match("\n([ ]*)")
test_nomsu = test_nomsu\gsub("\n"..indent, "\n")
- LuaCode tree.source, "TESTS[#{tostring(tree.source)\as_lua!}] = ", test_nomsu\as_lua!
+ return LuaCode "TESTS[#{tostring(body.source)\as_lua!}] = ", test_nomsu\as_lua!
- ["is jit"]: (compile, tree, code)-> LuaCode(tree.source, "jit")
- ["Lua version"]: (compile, tree, code)-> LuaCode(tree.source, "_VERSION")
- ["nomsu environment"]: (compile, tree)-> LuaCode(tree.source, "_ENV")
+ ["is jit"]: (compile, code)-> LuaCode("jit")
+ ["Lua version"]: (compile, code)-> LuaCode("_VERSION")
+ ["nomsu environment"]: (compile)-> LuaCode("_ENV")
}
}, {
__import: (other)=>
import_to_1_from(@action, other.action)
return
__call: (compile, tree, force_value=false)->
- if tree.version
- if get_version = compile.action[("Nomsu version")\as_lua_id!]
- if upgrade = compile.action[("1 upgraded from 2 to")\as_lua_id!]
- tree = upgrade(tree, tree.version, get_version!)
switch tree.type
when "Action"
stub = tree.stub
compile_action = compile.action[stub]
if not compile_action and math_expression\match(stub)
- compile_action = compile_math_expression
+ lua = LuaCode\from(tree.source)
+ for i,tok in ipairs tree
+ if type(tok) == 'string'
+ lua\append tok
+ else
+ tok_lua = compile(tok)
+ tok_lua\parenthesize! if tok.type == "Action"
+ lua\append tok_lua
+ lua\append " " if i < #tree
+ return lua
+
if compile_action and not tree.target
args = [arg for arg in *tree when type(arg) != "string"]
-- Force Lua to avoid tail call optimization for debugging purposes
-- TODO: use tail call?
- ret = compile_action(compile, tree, unpack(args))
+ ret = compile_action(compile, unpack(args))
if ret == nil
info = debug.getinfo(compile_action, "S")
filename = Source\from_string(info.source).filename
@@ -151,11 +146,12 @@ compile = setmetatable({
"The compile-time action here (#{stub}) failed to return any value.",
"Look at the implementation of (#{stub}) in #{filename}:#{info.linedefined} and make sure it's returning something."
unless SyntaxTree\is_instance(ret)
+ ret.source or= tree.source
return ret
if ret != tree
return compile(ret)
- lua = LuaCode(tree.source)
+ lua = LuaCode\from(tree.source)
if tree.target -- Method call
target_lua = compile tree.target
target_text = target_lua\text!
@@ -174,7 +170,7 @@ compile = setmetatable({
return lua
when "EscapedNomsu"
- lua = LuaCode tree.source, "SyntaxTree{"
+ lua = LuaCode\from tree.source, "SyntaxTree{"
needs_comma, i = false, 1
as_lua = (x)->
if type(x) == 'number'
@@ -201,11 +197,11 @@ compile = setmetatable({
when "Block"
if not force_value
- lua = LuaCode(tree.source)
+ lua = LuaCode\from(tree.source)
lua\concat_append([compile(line) for line in *tree], "\n")
return lua
else
- lua = LuaCode(tree.source)
+ lua = LuaCode\from(tree.source)
lua\append("((function()")
for i, line in ipairs(tree)
lua\append "\n ", compile(line)
@@ -213,7 +209,7 @@ compile = setmetatable({
return lua
when "Text"
- lua = LuaCode(tree.source)
+ lua = LuaCode\from(tree.source)
string_buffer = ""
for i, bit in ipairs tree
if type(bit) == "string"
@@ -226,7 +222,7 @@ compile = setmetatable({
bit_lua = compile(bit)
if #lua.bits > 0 then lua\append ".."
if bit.type != "Text"
- bit_lua = LuaCode(bit.source, "tostring(",bit_lua,")")
+ bit_lua = LuaCode\from(bit.source, "tostring(",bit_lua,")")
lua\append bit_lua
if string_buffer ~= "" or #lua.bits == 0
@@ -238,7 +234,7 @@ compile = setmetatable({
return lua
when "List", "Dict"
- lua = LuaCode tree.source, "#{tree.type}{"
+ lua = LuaCode\from tree.source, "#{tree.type}{"
i = 1
sep = ''
while i <= #tree
@@ -255,20 +251,26 @@ compile = setmetatable({
sep = ', '
i += 1
lua\append "}"
+ -- List/dict comprehenstion
if i <= #tree
- lua = LuaCode tree.source, "(function()\n local it = ", lua
+ lua = LuaCode\from tree.source, "(function()\n local comprehension = ", lua
+ if tree.type == "List"
+ lua\append "\n local function add(x) comprehension[#comprehension+1] = x end"
+ else
+ lua\append "\n local function #{("add 1 =")\as_lua_id!}(k, v) comprehension[k] = v end"
while i <= #tree
lua\append "\n "
if tree[i].type == 'Block' or tree[i].type == 'Comment'
lua\append compile(tree[i])
elseif tree[i].type == "DictEntry"
- lua\append "it[ ", compile(tree[i][1]), "] = ", (tree[i][2] and compile(tree[i][2]) or "true")
+ entry_lua = compile(tree[i])
+ lua\append (entry_lua\text!\sub(1,1) == '[' and "comprehension" or "comprehension."), entry_lua
else
- lua\append "it:add(", compile(tree[i]), ")"
+ lua\append "comprehension[#comprehension+1] = ", compile(tree[i])
i += 1
- lua\append "\n return it\nend)()"
+ lua\append "\n return comprehension\nend)()"
return lua
- --lua = LuaCode tree.source, "#{tree.type}{"
+ --lua = LuaCode\from tree.source, "#{tree.type}{"
--lua\concat_append([compile(e) for e in *tree when e.type != 'Comment'], ", ", ",\n ")
--lua\append "}"
--return lua
@@ -276,17 +278,17 @@ compile = setmetatable({
when "DictEntry"
key, value = tree[1], tree[2]
key_lua = compile(key)
- value_lua = value and compile(value) or LuaCode(key.source, "true")
+ value_lua = value and compile(value) or LuaCode\from(key.source, "true")
key_str = match(key_lua\text!, [=[^["']([a-zA-Z_][a-zA-Z0-9_]*)['"]$]=])
return if key_str and key_str\is_lua_id!
- LuaCode tree.source, key_str,"=",value_lua
+ LuaCode\from tree.source, key_str,"=",value_lua
elseif sub(key_lua\text!,1,1) == "["
-- NOTE: this *must* use a space after the [ to avoid freaking out
-- Lua's parser if the inner expression is a long string. Lua
-- parses x[[[y]]] as x("[y]"), not as x["y"]
- LuaCode tree.source, "[ ",key_lua,"]=",value_lua
+ LuaCode\from tree.source, "[ ",key_lua,"]=",value_lua
else
- LuaCode tree.source, "[",key_lua,"]=",value_lua
+ LuaCode\from tree.source, "[",key_lua,"]=",value_lua
when "IndexChain"
lua = compile(tree[1])
@@ -311,10 +313,10 @@ compile = setmetatable({
return lua
when "Number"
- return LuaCode(tree.source, tostring(tree[1]))
+ return LuaCode\from(tree.source, tostring(tree[1]))
when "Var"
- return LuaCode(tree.source, (tree[1])\as_lua_id!)
+ return LuaCode\from(tree.source, (tree[1])\as_lua_id!)
when "FileChunks"
error("Can't convert FileChunks to a single block of lua, since each chunk's "..
@@ -322,7 +324,7 @@ compile = setmetatable({
when "Comment"
-- TODO: implement?
- return LuaCode(tree.source, "")
+ return LuaCode\from(tree.source, "")
when "Error"
error("Can't compile errors")
diff --git a/nomsu_decompiler.lua b/nomsu_decompiler.lua
index 8d0aa7c..a3d7f41 100644
--- a/nomsu_decompiler.lua
+++ b/nomsu_decompiler.lua
@@ -47,7 +47,7 @@ local tree_to_inline_nomsu
tree_to_inline_nomsu = function(tree)
local _exp_0 = tree.type
if "Action" == _exp_0 then
- local nomsu = NomsuCode(tree.source)
+ local nomsu = NomsuCode:from(tree.source)
if tree.target then
local inline_target = tree_to_inline_nomsu(tree.target)
if tree.target.type == "Action" then
@@ -88,9 +88,9 @@ tree_to_inline_nomsu = function(tree)
if not (tree[1].type == "List" or tree[1].type == "Dict" or tree[1].type == "Var") then
inner_nomsu:parenthesize()
end
- return NomsuCode(tree.source, "\\", inner_nomsu)
+ return NomsuCode:from(tree.source, "\\", inner_nomsu)
elseif "Block" == _exp_0 then
- local nomsu = NomsuCode(tree.source, ":")
+ local nomsu = NomsuCode:from(tree.source, ":")
for i, line in ipairs(tree) do
nomsu:append(i == 1 and " " or "; ")
nomsu:append(tree_to_inline_nomsu(line))
@@ -119,11 +119,11 @@ tree_to_inline_nomsu = function(tree)
end
end
end
- local nomsu = NomsuCode(tree.source)
+ local nomsu = NomsuCode:from(tree.source)
add_text(nomsu, tree)
- return NomsuCode(tree.source, '"', nomsu, '"')
+ return NomsuCode:from(tree.source, '"', nomsu, '"')
elseif "List" == _exp_0 or "Dict" == _exp_0 then
- local nomsu = NomsuCode(tree.source, (tree.type == "List" and "[" or "{"))
+ local nomsu = NomsuCode:from(tree.source, (tree.type == "List" and "[" or "{"))
for i, item in ipairs(tree) do
if i > 1 then
nomsu:append(", ")
@@ -136,7 +136,7 @@ tree_to_inline_nomsu = function(tree)
local key, value = tree[1], tree[2]
local nomsu
if key.type == "Text" and #key == 1 and is_identifier(key[1]) then
- nomsu = NomsuCode(key.source, key[1])
+ nomsu = NomsuCode:from(key.source, key[1])
else
nomsu = tree_to_inline_nomsu(key)
end
@@ -154,7 +154,7 @@ tree_to_inline_nomsu = function(tree)
end
return nomsu
elseif "IndexChain" == _exp_0 then
- local nomsu = NomsuCode(tree.source)
+ local nomsu = NomsuCode:from(tree.source)
for i, bit in ipairs(tree) do
if i > 1 then
nomsu:append(".")
@@ -173,9 +173,9 @@ tree_to_inline_nomsu = function(tree)
end
return nomsu
elseif "Number" == _exp_0 then
- return NomsuCode(tree.source, tostring(tree[1]))
+ return NomsuCode:from(tree.source, tostring(tree[1]))
elseif "Var" == _exp_0 then
- return NomsuCode(tree.source, "%", tree[1])
+ return NomsuCode:from(tree.source, "%", tree[1])
elseif "FileChunks" == _exp_0 then
return error("Can't inline a FileChunks")
elseif "Comment" == _exp_0 then
@@ -188,7 +188,7 @@ tree_to_inline_nomsu = function(tree)
end
local tree_to_nomsu
tree_to_nomsu = function(tree)
- local nomsu = NomsuCode(tree.source)
+ local nomsu = NomsuCode:from(tree.source)
local recurse
recurse = function(t)
local space = MAX_LINE - nomsu:trailing_line_len()
@@ -214,7 +214,7 @@ tree_to_nomsu = function(tree)
local indented = tree_to_nomsu(t)
if t.type == "Action" then
if indented:is_multiline() then
- return NomsuCode(t.source, "(..)\n ", indented)
+ return NomsuCode:from(t.source, "(..)\n ", indented)
else
indented:parenthesize()
end
@@ -304,7 +304,7 @@ tree_to_nomsu = function(tree)
nomsu:append(line_nomsu:match('\n[^\n]*\n') and "\n\n" or "\n")
end
end
- return NomsuCode(tree.source, ":\n ", nomsu)
+ return NomsuCode:from(tree.source, ":\n ", nomsu)
elseif "Text" == _exp_0 then
local max_line = math.floor(1.25 * MAX_LINE)
local add_text
@@ -357,7 +357,7 @@ tree_to_nomsu = function(tree)
end
end
add_text(tree)
- return NomsuCode(tree.source, '"\\\n ..', nomsu, '"')
+ return NomsuCode:from(tree.source, '"\\\n ..', nomsu, '"')
elseif "List" == _exp_0 or "Dict" == _exp_0 then
if #tree == 0 then
nomsu:append(tree.type == "List" and "[]" or "{}")
@@ -376,14 +376,14 @@ tree_to_nomsu = function(tree)
end
end
if tree.type == "List" then
- return NomsuCode(tree.source, "[..]\n ", nomsu)
+ return NomsuCode:from(tree.source, "[..]\n ", nomsu)
else
- return NomsuCode(tree.source, "{..}\n ", nomsu)
+ return NomsuCode:from(tree.source, "{..}\n ", nomsu)
end
elseif "DictEntry" == _exp_0 then
local key, value = tree[1], tree[2]
if key.type == "Text" and #key == 1 and is_identifier(key[1]) then
- nomsu = NomsuCode(key.source, key[1])
+ nomsu = NomsuCode:from(key.source, key[1])
else
nomsu = tree_to_inline_nomsu(key)
end
diff --git a/nomsu_decompiler.moon b/nomsu_decompiler.moon
index df1c4d6..828df06 100644
--- a/nomsu_decompiler.moon
+++ b/nomsu_decompiler.moon
@@ -31,7 +31,7 @@ escape = (s)->
tree_to_inline_nomsu = (tree)->
switch tree.type
when "Action"
- nomsu = NomsuCode(tree.source)
+ nomsu = NomsuCode\from(tree.source)
if tree.target
inline_target = tree_to_inline_nomsu(tree.target)
if tree.target.type == "Action"
@@ -61,10 +61,10 @@ tree_to_inline_nomsu = (tree)->
inner_nomsu = tree_to_inline_nomsu(tree[1])
unless tree[1].type == "List" or tree[1].type == "Dict" or tree[1].type == "Var"
inner_nomsu\parenthesize!
- return NomsuCode(tree.source, "\\", inner_nomsu)
+ return NomsuCode\from(tree.source, "\\", inner_nomsu)
when "Block"
- nomsu = NomsuCode(tree.source, ":")
+ nomsu = NomsuCode\from(tree.source, ":")
for i,line in ipairs tree
nomsu\append(i == 1 and " " or "; ")
nomsu\append tree_to_inline_nomsu(line)
@@ -86,12 +86,12 @@ tree_to_inline_nomsu = (tree)->
elseif bit.type == "Var" and type(tree[i+1]) == 'string' and not match(tree[i+1], "^[ \n\t,.:;#(){}[%]]")
interp_nomsu\parenthesize!
nomsu\append "\\", interp_nomsu
- nomsu = NomsuCode(tree.source)
+ nomsu = NomsuCode\from(tree.source)
add_text(nomsu, tree)
- return NomsuCode(tree.source, '"', nomsu, '"')
+ return NomsuCode\from(tree.source, '"', nomsu, '"')
when "List", "Dict"
- nomsu = NomsuCode(tree.source, (tree.type == "List" and "[" or "{"))
+ nomsu = NomsuCode\from(tree.source, (tree.type == "List" and "[" or "{"))
for i, item in ipairs tree
nomsu\append ", " if i > 1
nomsu\append tree_to_inline_nomsu(item)
@@ -101,7 +101,7 @@ tree_to_inline_nomsu = (tree)->
when "DictEntry"
key, value = tree[1], tree[2]
nomsu = if key.type == "Text" and #key == 1 and is_identifier(key[1])
- NomsuCode(key.source, key[1])
+ NomsuCode\from(key.source, key[1])
else tree_to_inline_nomsu(key)
nomsu\parenthesize! if key.type == "Action" or key.type == "Block"
assert(value.type != "Block", "Didn't expect to find a Block as a value in a dict")
@@ -113,7 +113,7 @@ tree_to_inline_nomsu = (tree)->
return nomsu
when "IndexChain"
- nomsu = NomsuCode(tree.source)
+ nomsu = NomsuCode\from(tree.source)
for i, bit in ipairs tree
nomsu\append "." if i > 1
local bit_nomsu
@@ -127,10 +127,10 @@ tree_to_inline_nomsu = (tree)->
return nomsu
when "Number"
- return NomsuCode(tree.source, tostring(tree[1]))
+ return NomsuCode\from(tree.source, tostring(tree[1]))
when "Var"
- return NomsuCode(tree.source, "%", tree[1])
+ return NomsuCode\from(tree.source, "%", tree[1])
when "FileChunks"
error("Can't inline a FileChunks")
@@ -146,7 +146,7 @@ tree_to_inline_nomsu = (tree)->
error("Unknown type: #{tree.type}")
tree_to_nomsu = (tree)->
- nomsu = NomsuCode(tree.source)
+ nomsu = NomsuCode\from(tree.source)
-- For concision:
recurse = (t)->
@@ -166,7 +166,7 @@ tree_to_nomsu = (tree)->
indented = tree_to_nomsu(t)
if t.type == "Action"
if indented\is_multiline!
- return NomsuCode(t.source, "(..)\n ", indented)
+ return NomsuCode\from(t.source, "(..)\n ", indented)
else indented\parenthesize!
return indented
@@ -234,7 +234,7 @@ tree_to_nomsu = (tree)->
if i < #tree
-- number of lines > 2 (TODO: improve this)
nomsu\append(line_nomsu\match('\n[^\n]*\n') and "\n\n" or "\n")
- return NomsuCode(tree.source, ":\n ", nomsu)
+ return NomsuCode\from(tree.source, ":\n ", nomsu)
when "Text"
-- Multi-line text has more generous wrap margins
@@ -274,7 +274,7 @@ tree_to_nomsu = (tree)->
if interp_nomsu\is_multiline!
nomsu\append "\n.."
add_text(tree)
- return NomsuCode(tree.source, '"\\\n ..', nomsu, '"')
+ return NomsuCode\from(tree.source, '"\\\n ..', nomsu, '"')
when "List", "Dict"
if #tree == 0
@@ -290,14 +290,14 @@ tree_to_nomsu = (tree)->
if i < #tree
nomsu\append((item_nomsu\is_multiline! or nomsu\trailing_line_len! + #tostring(item_nomsu) >= MAX_LINE) and '\n' or ', ')
return if tree.type == "List" then
- NomsuCode(tree.source, "[..]\n ", nomsu)
+ NomsuCode\from(tree.source, "[..]\n ", nomsu)
else
- NomsuCode(tree.source, "{..}\n ", nomsu)
+ NomsuCode\from(tree.source, "{..}\n ", nomsu)
when "DictEntry"
key, value = tree[1], tree[2]
nomsu = if key.type == "Text" and #key == 1 and is_identifier(key[1])
- NomsuCode(key.source, key[1])
+ NomsuCode\from(key.source, key[1])
else tree_to_inline_nomsu(key)
nomsu\parenthesize! if key.type == "Block"
value_nomsu = tree_to_nomsu(value)
diff --git a/nomsu_environment.lua b/nomsu_environment.lua
index e72eb20..dd8b3ec 100644
--- a/nomsu_environment.lua
+++ b/nomsu_environment.lua
@@ -52,6 +52,7 @@ do
tree_to_nomsu, tree_to_inline_nomsu = _obj_0.tree_to_nomsu, _obj_0.tree_to_inline_nomsu
end
local compile = require('nomsu_compiler')
+local _currently_running_files = List({ })
local nomsu_environment = Importer({
NOMSU_COMPILER_VERSION = 12,
NOMSU_SYNTAX_VERSION = max_parser_version,
@@ -113,7 +114,7 @@ local nomsu_environment = Importer({
_1_parsed = function(nomsu_code)
if type(nomsu_code) == 'string' then
local filename = Files.spoof(nomsu_code)
- nomsu_code = NomsuCode(Source(filename, 1, #nomsu_code), nomsu_code)
+ nomsu_code = NomsuCode:from(Source(filename, 1, #nomsu_code), nomsu_code)
end
local source = nomsu_code.source
nomsu_code = tostring(nomsu_code)
@@ -186,7 +187,7 @@ local nomsu_environment = Importer({
run_1_in = function(to_run, environment)
if type(to_run) == 'string' then
local filename = Files.spoof(to_run)
- to_run = NomsuCode(Source(filename, 1, #to_run), to_run)
+ to_run = NomsuCode:from(Source(filename, 1, #to_run), to_run)
local ret = environment.run_1_in(to_run, environment)
return ret
elseif NomsuCode:is_instance(to_run) then
@@ -277,6 +278,14 @@ local nomsu_environment = Importer({
import_to_1_from(environment, environment.FILE_CACHE[path])
return
end
+ if _currently_running_files:has(path) then
+ local i = _currently_running_files:index_of(path)
+ _currently_running_files:add(path)
+ local circle = _currently_running_files:from_1_to(i, -1)
+ print(_currently_running_files, path)
+ error("Circular import detected:\n " .. circle:joined_with("\n..imports "))
+ end
+ _currently_running_files:add(path)
local mod = _1_forked(environment)
assert(mod._1_parsed)
mod._ENV = mod
@@ -291,10 +300,10 @@ local nomsu_environment = Importer({
local code
if optimization ~= 0 and Files.read(lua_filename) then
local file = Files.read(lua_filename)
- code = LuaCode(Source(filename, 1, #file), file)
+ code = LuaCode:from(Source(filename, 1, #file), file)
else
local file = Files.read(filename)
- code = NomsuCode(Source(filename, 1, #file), file)
+ code = NomsuCode:from(Source(filename, 1, #file), file)
end
environment.run_1_in(code, mod)
_continue_0 = true
@@ -305,6 +314,7 @@ local nomsu_environment = Importer({
end
import_to_1_from(environment, mod)
environment.FILE_CACHE[path] = mod
+ return _currently_running_files:remove()
end,
compile_error_at = function(tree, err_msg, hint)
if hint == nil then
diff --git a/nomsu_environment.moon b/nomsu_environment.moon
index b216242..bfc5edc 100644
--- a/nomsu_environment.moon
+++ b/nomsu_environment.moon
@@ -32,6 +32,7 @@ for version=1,999
{:tree_to_nomsu, :tree_to_inline_nomsu} = require "nomsu_decompiler"
compile = require('nomsu_compiler')
+_currently_running_files = List{} -- Used to check for circular imports in run_file_1_in
nomsu_environment = Importer{
NOMSU_COMPILER_VERSION: 12, NOMSU_SYNTAX_VERSION: max_parser_version
-- Lua stuff:
@@ -57,7 +58,7 @@ nomsu_environment = Importer{
_1_parsed: (nomsu_code)->
if type(nomsu_code) == 'string'
filename = Files.spoof(nomsu_code)
- nomsu_code = NomsuCode(Source(filename, 1, #nomsu_code), nomsu_code)
+ nomsu_code = NomsuCode\from(Source(filename, 1, #nomsu_code), nomsu_code)
source = nomsu_code.source
nomsu_code = tostring(nomsu_code)
version = nomsu_code\match("^#![^\n]*nomsu[ ]+-V[ ]*([0-9.]+)")
@@ -88,7 +89,7 @@ nomsu_environment = Importer{
run_1_in: (to_run, environment)->
if type(to_run) == 'string'
filename = Files.spoof(to_run)
- to_run = NomsuCode(Source(filename, 1, #to_run), to_run)
+ to_run = NomsuCode\from(Source(filename, 1, #to_run), to_run)
ret = environment.run_1_in(to_run, environment)
return ret
elseif NomsuCode\is_instance(to_run)
@@ -151,6 +152,13 @@ nomsu_environment = Importer{
if environment.FILE_CACHE[path]
import_to_1_from(environment, environment.FILE_CACHE[path])
return
+ if _currently_running_files\has(path)
+ i = _currently_running_files\index_of(path)
+ _currently_running_files\add path
+ circle = _currently_running_files\from_1_to(i, -1)
+ print(_currently_running_files, path)
+ error("Circular import detected:\n "..circle\joined_with("\n..imports "))
+ _currently_running_files\add path
mod = _1_forked(environment)
assert mod._1_parsed
mod._ENV = mod
@@ -160,13 +168,14 @@ nomsu_environment = Importer{
-- TODO: don't automatically use precompiled version?
code = if optimization != 0 and Files.read(lua_filename)
file = Files.read(lua_filename)
- LuaCode(Source(filename, 1, #file), file)
+ LuaCode\from(Source(filename, 1, #file), file)
else
file = Files.read(filename)
- NomsuCode(Source(filename, 1, #file), file)
+ NomsuCode\from(Source(filename, 1, #file), file)
environment.run_1_in(code, mod)
import_to_1_from(environment, mod)
environment.FILE_CACHE[path] = mod
+ _currently_running_files\remove!
compile_error_at: (tree, err_msg, hint=nil)->
err_str = pretty_error{