aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core.nom148
-rw-r--r--nomsu.lua83
-rwxr-xr-xnomsu.moon59
3 files changed, 147 insertions, 143 deletions
diff --git a/core.nom b/core.nom
index 1376990..ced3873 100644
--- a/core.nom
+++ b/core.nom
@@ -11,36 +11,32 @@ rule "macro %spec %body":
rule "macro block %spec %body":
lua block ".."
- |do
- | local spec, body = vars.spec, vars.body
- | local wrapper = function(compiler, vars, kind)
- | if kind == "Expression" then
- | compiler:error("Macro: "..spec.." was defined to be a block, but is being used as an expression.")
- | end
- | return body(compiler, vars, kind), true
+ |local spec, body = vars.spec, vars.body
+ |local wrapper = function(compiler, vars, kind)
+ | if kind == "Expression" then
+ | compiler:error("Macro: "..spec.." was defined to be a block, but is being used as an expression.")
| end
- | compiler:defmacro(spec, wrapper)
- | return nil
+ | return ("do\\n"..body(compiler, vars, kind).."\\nend"), true
|end
+ |compiler:defmacro(spec, wrapper)
+ |return nil
# Compiler tools
rule ["eval %code", "run %code"]:
lua expr "compiler:run(vars.code)"
macro "source code %code":
- lua expr "utils.repr(vars.code.src, true)"
+ lua expr "compiler.utils.repr(vars.code.src, true)"
rule "run file %filename":
lua block ".."
- |do
- | local file = io.open(vars.filename)
- | return compiler:run(file:read("*a"))
- |end
+ |local file = io.open(vars.filename)
+ |return compiler:run(file:read("*a"))
# Macro helper functions
rule "%tree as lua block":
lua block ".."
- |do return compiler:tree_to_lua(vars.tree, 'Statement'), true end
+ |return compiler:tree_to_lua(vars.tree, 'Statement'), true
rule "%tree as lua expr":
lua expr ".."
@@ -49,48 +45,44 @@ rule "%tree as lua expr":
# Moonscript!
macro block "moonscript block %moonscript_code":
lua block ".."
- |do
- | local parse, compile = require('moonscript.parse'), require('moonscript.compile')
- | local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
- | local tree, err = parse.string(moon_code)
- | if not tree then
- | compiler:error("Failed to parse moonscript: "..err)
- | end
- | local lua_code, err, pos = compile.tree(tree)
- | if not lua_code then
- | compiler:error(compile.format_error(err, pos, moon_code))
- | end
- | return "do\\n"..lua_code.."\\nend"
+ |local parse, compile = require('moonscript.parse'), require('moonscript.compile')
+ |local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
+ |local tree, err = parse.string(moon_code)
+ |if not tree then
+ | compiler:error("Failed to parse moonscript: "..err)
|end
+ |local lua_code, err, pos = compile.tree(tree)
+ |if not lua_code then
+ | compiler:error(compile.format_error(err, pos, moon_code))
+ |end
+ |return "do\\n"..lua_code.."\\nend"
macro "moonscript %moonscript_code":
lua block ".."
- |do
- | local parse, compile = require('moonscript.parse'), require('moonscript.compile')
- | local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
- | local tree, err = parse.string(moon_code)
- | if not tree then
- | compiler:error("Failed to parse moonscript: "..err)
- | end
- | local lua_code, err, pos = compile.tree(tree)
- | if not lua_code then
- | compiler:error(compile.format_error(err, pos, moon_code))
- | end
- | return "(function(compiler, vars)\\n"..lua_code.."\\nend)(compiler, vars)"
+ |local parse, compile = require('moonscript.parse'), require('moonscript.compile')
+ |local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
+ |local tree, err = parse.string(moon_code)
+ |if not tree then
+ | compiler:error("Failed to parse moonscript: "..err)
|end
+ |local lua_code, err, pos = compile.tree(tree)
+ |if not lua_code then
+ | compiler:error(compile.format_error(err, pos, moon_code))
+ |end
+ |return "(function(compiler, vars)\\n"..lua_code.."\\nend)(compiler, vars)"
# String functions
rule "join %strs":
lua block ".."
|local str_bits = {}
- |for i,bit in ipairs(vars.strs) do str_bits[i] = utils.repr(bit) end
- |do return table.concat(str_bits) end
+ |for i,bit in ipairs(vars.strs) do str_bits[i] = compiler.utils.repr(bit) end
+ |return table.concat(str_bits)
rule "join %strs with glue %glue":
lua block ".."
|local str_bits = {}
- |for i,bit in ipairs(vars.strs) do str_bits[i] = utils.repr(bit) end
- |do return table.concat(str_bits, vars.glue) end
+ |for i,bit in ipairs(vars.strs) do str_bits[i] = compiler.utils.repr(bit) end
+ |return table.concat(str_bits, vars.glue)
rule ["capitalize %str", "%str capitalized"]:
lua expr ".."|vars.str:gsub("%l", string.upper, 1)
@@ -142,22 +134,22 @@ macro "- %a": ".."|-(\%a as lua expr\)
macro "not %a": ".."|not (\%a as lua expr\)
rule "%a == %b":
- lua expr "((vars.a == vars.b) or utils.equivalent(vars.a, vars.b))"
+ lua expr "((vars.a == vars.b) or compiler.utils.equivalent(vars.a, vars.b))"
rule "%a != %b":
- lua expr "((vars.a ~= vars.b) or not utils.equivalent(vars.a, vars.b))"
+ lua expr "((vars.a ~= vars.b) or not compiler.utils.equivalent(vars.a, vars.b))"
macro "say %str":
- ".."|compiler:writeln(utils.repr(\%str as lua expr\))
+ ".."|compiler:writeln(compiler.utils.repr(\%str as lua expr\))
# Control flow
rule "do %action":
lua expr "vars.action(compiler, setmetatable({}, {__index=vars}))"
macro block "return %return-value":
- ".."|do return \%return-value as lua expr\ end
+ ".."|return \%return-value as lua expr\
macro block "return":
- "do return nil end"
+ "return nil"
# Conditionals
macro block "if %condition %if_body":
@@ -185,24 +177,20 @@ macro "%if_expr if %condition else %else_expr":
# For loop
macro block "for %varname in %iterable %body":
let "varname" = (%varname as lua expr)
- ".."|do
- | local old_loopval = vars[\%varname\]
- | for i,value in ipairs(\%iterable as lua expr\) do
- | vars[\%varname\] = value
- | \(lua expr "vars.body.value.value") as lua block\
- | end
- | vars[\%varname\] = old_loopval
+ ".."|local old_loopval = vars[\%varname\]
+ |for i,value in ipairs(\%iterable as lua expr\) do
+ | vars[\%varname\] = value
+ | \(lua expr "vars.body.value.value") as lua block\
|end
+ |vars[\%varname\] = old_loopval
macro block "for all %iterable %body":
- ".."|do
- | local old_loopval = vars.it
- | for i,value in ipairs(\%iterable as lua expr\) do
- | vars.it = value
- | \(lua expr "vars.body.value.value") as lua block\
- | end
- | vars.it = old_loopval
+ ".."|local old_loopval = vars.it
+ |for i,value in ipairs(\%iterable as lua expr\) do
+ | vars.it = value
+ | \(lua expr "vars.body.value.value") as lua block\
|end
+ |vars.it = old_loopval
# List Comprehension
# TODO: maybe make this lazy, or a lazy version?
@@ -249,45 +237,45 @@ macro "%key = %value for all %iterable":
# Number ranges
rule "%start up to %stop":
- lua expr "utils.range(vars.start,vars.stop-1)"
+ lua expr "compiler.utils.range(vars.start,vars.stop-1)"
rule ["%start thru %stop", "%start through %stop"]:
- lua expr "utils.range(vars.start,vars.stop)"
+ lua expr "compiler.utils.range(vars.start,vars.stop)"
rule "%start down to %stop":
- lua expr "utils.range(vars.start,vars.stop+1,-1)"
+ lua expr "compiler.utils.range(vars.start,vars.stop+1,-1)"
rule ["%start down thru %stop", "%start down through %stop"]:
- lua expr "utils.range(vars.start,vars.stop,-1)"
+ lua expr "compiler.utils.range(vars.start,vars.stop,-1)"
rule "%start up to %stop via %step":
- lua expr "utils.range(vars.start,vars.stop-1,vars.step)"
+ lua expr "compiler.utils.range(vars.start,vars.stop-1,vars.step)"
rule ["%start thru %stop via %step", "%start through %stop via %step"]:
- lua expr "utils.range(vars.start,vars.stop,vars.step)"
+ lua expr "compiler.utils.range(vars.start,vars.stop,vars.step)"
rule "%start down to %stop via %step":
- lua expr "utils.range(vars.start,vars.stop+1,-vars.step)"
+ lua expr "compiler.utils.range(vars.start,vars.stop+1,-vars.step)"
rule ["%start down thru %stop via %step", "%start down through %stop via %step"]:
- lua expr "utils.range(vars.start,vars.stop,-vars.step)"
+ lua expr "compiler.utils.range(vars.start,vars.stop,-vars.step)"
# Common utility functions
rule ["random number"]: lua expr "math.random()"
-rule ["sum of %items"]: lua expr "utils.sum(vars.items)"
-rule ["product of %items"]: lua expr "utils.product(vars.items)"
-rule ["all of %items"]: lua expr "utils.all(vars.items)"
-rule ["any of %items"]: lua expr "utils.any(vars.items)"
-rule ["avg of %items", "average of %items"]: lua expr "(utils.sum(vars.items)/#vars.items)"
+rule ["sum of %items"]: lua expr "compiler.utils.sum(vars.items)"
+rule ["product of %items"]: lua expr "compiler.utils.product(vars.items)"
+rule ["all of %items"]: lua expr "compiler.utils.all(vars.items)"
+rule ["any of %items"]: lua expr "compiler.utils.any(vars.items)"
+rule ["avg of %items", "average of %items"]: lua expr "(compiler.utils.sum(vars.items)/#vars.items)"
rule ["min of %items", "smallest of %items", "lowest of %items"]:
- lua expr "utils.min(vars.items)"
+ lua expr "compiler.utils.min(vars.items)"
rule ["max of %items", "biggest of %items", "largest of %items", "highest of %items"]:
- lua expr "utils.min(vars.items)"
+ lua expr "compiler.utils.min(vars.items)"
rule ["min of %items with respect to %keys"]:
- lua expr "utils.min(vars.items, vars.keys)"
+ lua expr "compiler.utils.min(vars.items, vars.keys)"
rule ["max of %items with respect to %keys"]:
- lua expr "utils.max(vars.items, vars.keys)"
+ lua expr "compiler.utils.max(vars.items, vars.keys)"
# List/dict functions
macro [..]
@@ -395,7 +383,7 @@ rule "error %msg":
|compiler:error(vars.msg)
macro block "test %code yields %expected":
- let "generated" = (lua expr "utils.repr(compiler:stringify_tree(vars.code.value.value), true)")
+ let "generated" = (lua expr "compiler.utils.repr(compiler:stringify_tree(vars.code.value.value), true)")
let "expected" = (%expected as lua expr)
if (%generated != %expected):
say "Test failed!"
diff --git a/nomsu.lua b/nomsu.lua
index 4dc8b51..c8e12f7 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -259,6 +259,48 @@ do
end
return retval
end,
+ serialize = function(self, obj)
+ local _exp_0 = type(obj)
+ if "function" == _exp_0 then
+ return "assert(load(" .. utils.repr(string.dump(obj), true) .. "))"
+ elseif "table" == _exp_0 then
+ if utils.is_list(obj) then
+ return "{" .. tostring(table.concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #obj do
+ local i = obj[_index_0]
+ _accum_0[_len_0] = self:serialize(i)
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ", ")) .. "}"
+ else
+ return "{" .. tostring(table.concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for k, v in pairs(obj) do
+ _accum_0[_len_0] = "[" .. tostring(self:serialize(k)) .. "]= " .. tostring(self:serialize(v))
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ", ")) .. "}"
+ end
+ elseif "number" == _exp_0 then
+ return utils.repr(obj, true)
+ elseif "string" == _exp_0 then
+ return utils.repr(obj, true)
+ else
+ return error("Serialization not implemented for: " .. tostring(type(obj)))
+ end
+ end,
+ deserialize = function(self, str)
+ local lua_thunk, err = load("return (function(compiler,vars)\n return " .. str .. "\n end)")
+ if not lua_thunk then
+ error("Failed to compile generated code:\n" .. tostring(str) .. "\n\n" .. tostring(err))
+ end
+ return (lua_thunk())(self, { })
+ end,
parse = function(self, str)
if self.debug then
self:writeln("PARSING:\n" .. tostring(str))
@@ -331,7 +373,7 @@ do
return tree
end,
tree_to_value = function(self, tree, vars)
- local code = "\n local utils = require('utils')\n return (function(compiler, vars)\nreturn " .. tostring(self:tree_to_lua(tree)) .. "\nend)"
+ local code = "\n return (function(compiler, vars)\nreturn " .. tostring(self:tree_to_lua(tree)) .. "\nend)"
local lua_thunk, err = load(code)
if not lua_thunk then
error("Failed to compile generated code:\n" .. tostring(code) .. "\n\n" .. tostring(err))
@@ -364,7 +406,7 @@ do
for _index_0 = 1, #_list_0 do
local statement = _list_0[_index_0]
local code = to_lua(statement, "Statement")
- local lua_code = "\n local utils = require('utils')\n return (function(compiler, vars)\n" .. tostring(code) .. "\nend)"
+ local lua_code = "\n return (function(compiler, vars)\n" .. tostring(code) .. "\nend)"
local lua_thunk, err = load(lua_code)
if not lua_thunk then
error("Failed to compile generated code:\n" .. tostring(code) .. "\n\n" .. tostring(err) .. "\n\nProduced by statement:\n" .. tostring(utils.repr(statement)))
@@ -385,9 +427,8 @@ do
elseif "Thunk" == _exp_0 then
assert(tree.value.type == "Block", "Non-block value in Thunk")
add([[ (function(compiler, vars)
- local ret]])
- add(to_lua(tree.value))
- add([[ return ret
+ local ret
+ ]] .. to_lua(tree.value) .. "\n" .. [[ return ret
end)
]])
elseif "Statement" == _exp_0 then
@@ -455,7 +496,7 @@ do
table.insert(concat_parts, utils.repr(string_buffer, true))
string_buffer = ""
end
- table.insert(concat_parts, "utils.repr(" .. tostring(to_lua(bit)) .. ")")
+ table.insert(concat_parts, "compiler.utils.repr(" .. tostring(to_lua(bit)) .. ")")
end
end
end
@@ -716,36 +757,12 @@ do
if kind == "Expression" then
error("Expected to be in statement.")
end
- return self:tree_to_value(vars.lua_code, vars), true
+ return "do\n" .. self:tree_to_value(vars.lua_code, vars) .. "\nend", true
end)
self:defmacro([[lua expr %lua_code]], function(self, vars, kind)
local lua_code = vars.lua_code.value
return self:tree_to_value(vars.lua_code, vars)
end)
- self:def("rule %spec %body", function(self, vars)
- return self:def(vars.spec, vars.body)
- end)
- self:defmacro([[macro %spec %body]], function(self, vars, kind)
- if kind == "Expression" then
- error("Macro definitions cannot be used as expressions.")
- end
- self:defmacro(self:tree_to_value(vars.spec, vars), self:tree_to_value(vars.body, vars))
- return "", true
- end)
- self:defmacro([[macro block %spec %body]], function(self, vars, kind)
- if kind == "Expression" then
- error("Macro definitions cannot be used as expressions.")
- end
- local invocation = self:tree_to_value(vars.spec, vars)
- local fn = self:tree_to_value(vars.body, vars)
- self:defmacro(invocation, (function(self, vars, kind)
- if kind == "Expression" then
- error("Macro: " .. tostring(invocation) .. " was defined to be a block, not an expression.")
- end
- return fn(self, vars, kind), true
- end))
- return "", true
- end)
return self:def("run file %filename", function(self, vars)
local file = io.open(vars.filename)
return self:run(file:read('*a'))
@@ -764,6 +781,7 @@ do
self.write = function(self, ...)
return io.write(...)
end
+ self.utils = utils
end,
__base = _base_0,
__name = "NomsuCompiler"
@@ -816,8 +834,7 @@ if arg and arg[1] then
else
output = io.open(arg[2], 'w')
end
- output:write([[ local utils = require('utils')
- local load = function()
+ output:write([[ local load = function()
]])
output:write(code)
output:write([[
diff --git a/nomsu.moon b/nomsu.moon
index 513f8e8..64d16b0 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -97,6 +97,7 @@ class NomsuCompiler
@debug = false
@initialize_core!
@write = (...)=> io.write(...)
+ @utils = utils
writeln:(...)=>
@write(...)
@@ -167,6 +168,30 @@ class NomsuCompiler
if @debug
@writeln "\nGENERATED LUA CODE:\n#{code}"
return retval
+
+ serialize: (obj)=>
+ switch type(obj)
+ when "function"
+ "assert(load("..utils.repr(string.dump(obj), true).."))"
+ when "table"
+ if utils.is_list obj
+ "{#{table.concat([@serialize(i) for i in *obj], ", ")}}"
+ else
+ "{#{table.concat(["[#{@serialize(k)}]= #{@serialize(v)}" for k,v in pairs(obj)], ", ")}}"
+ when "number"
+ utils.repr(obj, true)
+ when "string"
+ utils.repr(obj, true)
+ else
+ error "Serialization not implemented for: #{type(obj)}"
+
+ deserialize: (str)=>
+ lua_thunk, err = load("return (function(compiler,vars)
+ return "..str.."
+ end)")
+ if not lua_thunk
+ error("Failed to compile generated code:\n#{str}\n\n#{err}")
+ return (lua_thunk!)(self, {})
parse: (str)=>
if @debug
@@ -240,9 +265,7 @@ class NomsuCompiler
return tree
tree_to_value: (tree, vars)=>
- -- TODO: clean up require utils
code = "
- local utils = require('utils')
return (function(compiler, vars)\nreturn #{@tree_to_lua(tree)}\nend)"
lua_thunk, err = load(code)
if not lua_thunk
@@ -269,9 +292,7 @@ class NomsuCompiler
for statement in *tree.value.body.value
code = to_lua(statement, "Statement")
-- Run the fuckers as we go
- -- TODO: clean up repeated loading of utils?
lua_code = "
- local utils = require('utils')
return (function(compiler, vars)\n#{code}\nend)"
lua_thunk, err = load(lua_code)
if not lua_thunk
@@ -292,9 +313,8 @@ class NomsuCompiler
assert tree.value.type == "Block", "Non-block value in Thunk"
add [[
(function(compiler, vars)
- local ret]]
- add to_lua(tree.value)
- add [[
+ local ret
+ ]]..to_lua(tree.value).."\n"..[[
return ret
end)
]]
@@ -339,7 +359,7 @@ class NomsuCompiler
if string_buffer ~= ""
table.insert concat_parts, utils.repr(string_buffer, true)
string_buffer = ""
- table.insert concat_parts, "utils.repr(#{to_lua(bit)})"
+ table.insert concat_parts, "compiler.utils.repr(#{to_lua(bit)})"
if string_buffer ~= ""
table.insert concat_parts, utils.repr(string_buffer, true)
@@ -535,32 +555,12 @@ class NomsuCompiler
@defmacro [[lua block %lua_code]], (vars, kind)=>
if kind == "Expression" then error("Expected to be in statement.")
- return @tree_to_value(vars.lua_code, vars), true
+ return "do\n"..@tree_to_value(vars.lua_code, vars).."\nend", true
@defmacro [[lua expr %lua_code]], (vars, kind)=>
lua_code = vars.lua_code.value
return @tree_to_value(vars.lua_code, vars)
- @def "rule %spec %body", (vars)=>
- @def vars.spec, vars.body
-
- @defmacro [[macro %spec %body]], (vars, kind)=>
- if kind == "Expression"
- error("Macro definitions cannot be used as expressions.")
- @defmacro @tree_to_value(vars.spec, vars), @tree_to_value(vars.body, vars)
- return "", true
-
- @defmacro [[macro block %spec %body]], (vars, kind)=>
- if kind == "Expression"
- error("Macro definitions cannot be used as expressions.")
- invocation = @tree_to_value(vars.spec, vars)
- fn = @tree_to_value(vars.body, vars)
- @defmacro invocation, ((vars,kind)=>
- if kind == "Expression"
- error("Macro: #{invocation} was defined to be a block, not an expression.")
- return fn(@,vars,kind), true)
- return "", true
-
@def "run file %filename", (vars)=>
file = io.open(vars.filename)
return @run(file\read('*a'))
@@ -585,7 +585,6 @@ if arg and arg[1]
else io.open(arg[2], 'w')
output\write [[
- local utils = require('utils')
local load = function()
]]
output\write(code)