aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2017-09-18 22:41:50 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2017-09-18 22:41:50 -0700
commit2c4acdfe67e05fba88d4c48509c8767d2dce358b (patch)
treed72f52122d4b372d832c69bd9a21d0da34323de5
parent15886aa57978cbd236ff6ac3bc16adf0941ca299 (diff)
More major overhaulage.
-rw-r--r--core.nom363
-rw-r--r--examples/parser_tests.nom12
-rw-r--r--examples/sample_code.nom48
-rw-r--r--examples/sample_game.nom151
-rw-r--r--examples/tutorial.nom191
-rw-r--r--nomsu.lua50
-rwxr-xr-xnomsu.moon32
7 files changed, 621 insertions, 226 deletions
diff --git a/core.nom b/core.nom
index ae4c22a..0b0193b 100644
--- a/core.nom
+++ b/core.nom
@@ -1,10 +1,14 @@
# Rule for making rules
lua block ".."
- |compiler:def("rule %spec = %body", function(compiler, vars)
- | return compiler:def(vars.spec, vars.body)
+ |compiler:defmacro("rule %spec = %body", function(compiler, vars, kind)
+ | if kind == "Expression" then
+ | compiler:error("Cannot use rule definitions as an expression.")
+ | end
+ | local spec = compiler:get_invocations_from_definition(vars.spec.value, vars)
+ | return ("compiler:def("..compiler.utils.repr(spec,true)..", "..compiler:tree_to_lua(vars.body, vars)..")"), true
|end)
-rule "help %invocation" =:
+rule: help %invocation ..=:
lua block ".."
|local fn_info = compiler.defs[vars.invocation]
|if not fn_info then
@@ -16,7 +20,7 @@ rule "help %invocation" =:
# Macros
lua block ".."
|local add_macro = function(compiler, vars, kind)
- | local spec = compiler:tree_to_value(vars.spec, vars)
+ | local spec = compiler:get_invocations_from_definition(vars.spec.value, vars)
| local fn = compiler:tree_to_value(vars.body, vars)
| compiler:defmacro(spec, fn, vars.body.src)
| return "", true
@@ -24,7 +28,7 @@ lua block ".."
|compiler:defmacro("macro %spec = %body", add_macro)
|
|local add_macro_block = function(compiler, vars, kind)
- | local spec = compiler:tree_to_value(vars.spec, vars)
+ | local spec = compiler:get_invocations_from_definition(vars.spec.value, vars)
| local fn = compiler:tree_to_value(vars.body, vars)
| local wrapper = function(compiler, vars, kind)
| if kind == "Expression" then
@@ -38,53 +42,56 @@ lua block ".."
|compiler:defmacro("macro block %spec = %body", add_macro_block)
# Compiler tools
-rule ["eval %code", "run %code"] =:
+rule:
+ eval %code
+ run %code
+..=:
lua expr "compiler:run(vars.code)"
-macro "source code %code" =:
+macro: source code %code ..=:
lua block ".."
|if vars.code.value.type ~= "Thunk" then
| compiler:error("'source code %' only takes code blocks, not "..vars.code.value.type)
|end
lua expr "compiler.utils.repr(vars.code.value.value.src, true)"
-rule "run file %filename" =:
+rule: run file %filename ..=:
lua block ".."
|local file = io.open(vars.filename)
|return compiler:run(file:read("*a"))
# Error functions
-rule "error!" =:
+rule: error! ..=:
lua block ".."
|table.remove(compiler.callstack)
|compiler:error()
-rule "error %msg" =:
+rule: error %msg ..=:
lua block ".."
|table.remove(compiler.callstack)
|compiler:error(vars.msg)
-macro "as lua %block" =:
+macro: as lua %block ..=:
lua expr "compiler.utils.repr(compiler:tree_to_lua(vars.block.value.value, vars), true)"
-macro block "show generated lua %block" =:
+macro block: show generated lua %block ..=:
".."|compiler:writeln(\lua expr "compiler.utils.repr(compiler:tree_to_lua(vars.block.value.value, vars), true)"\)
# Macro helper functions
-rule "%tree as value" =:
+rule: %tree as value ..=:
lua expr ".."
|compiler:tree_to_value(vars.tree, vars)
-rule "%tree as lua block" =:
+rule: %tree as lua block ..=:
lua block ".."
|return compiler:tree_to_lua(vars.tree, 'Statement'), true
-rule "%tree as lua expr" =:
+rule: %tree as lua expr ..=:
lua expr ".."
|compiler:tree_to_lua(vars.tree, 'Expression')
# Moonscript!
-macro block "moonscript block %moonscript_code" =:
+macro block: moonscript block %moonscript_code ..=:
lua block ".."
|local parse, compile = require('moonscript.parse'), require('moonscript.compile')
|local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
@@ -98,7 +105,7 @@ macro block "moonscript block %moonscript_code" =:
|end
|return "do\\n"..lua_code.."\\nend"
-macro "moonscript %moonscript_code" =:
+macro: moonscript %moonscript_code ..=:
lua block ".."
|local parse, compile = require('moonscript.parse'), require('moonscript.compile')
|local moon_code = compiler:tree_to_value(vars.moonscript_code, vars)
@@ -113,24 +120,27 @@ macro "moonscript %moonscript_code" =:
|return "(function(compiler, vars)\\n"..lua_code.."\\nend)(compiler, vars)"
# String functions
-rule "join %strs" =:
+rule: join %strs ..=:
lua block ".."
|local str_bits = {}
|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" =:
+rule: join %strs with glue %glue ..=:
lua block ".."
|local str_bits = {}
|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"] =:
+rule:
+ capitalize %str
+ %str capitalized
+..=:
lua expr ".."|vars.str:gsub("%l", string.upper, 1)
# Variable assignment
#..
- macro block "%var = %value" =:
+ macro block: %var = %value ..=:
lua block ".."
|if vars.var.value.type ~= "Var" then
| compiler:error("Assignment operation has the wrong type for the left hand side. "
@@ -138,81 +148,107 @@ rule ["capitalize %str", "%str capitalized"] =:
|end
".."|\%var as lua expr\ = \%value as lua expr\
-macro block "%var = %value" =:
- lua block ".."
- |if vars.var.value.type ~= "Var" then
- | compiler:error("Assignment operation has the wrong type for the left hand side. "
- | .."Expected Var, but got: "..vars.var.value.type)
- |end
- lua block ".."
- |if vars.value.value.type ~= "Thunk" then
- | compiler:error("Assignment operation has the wrong type for the right hand side. "
- | .."Expected Thunk, but got: "..vars.value.value.type.."\\nMaybe you used '=' instead of '=:'?")
- |end
- ".."|do
- | local ret
- | \lua expr "compiler:tree_to_lua(vars.value.value.value, 'Statement')"\
- | \%var as lua expr\ = ret
- |end
+lua block ".."
+ |local function helper(callback)
+ | return function(compiler, vars, kind)
+ | if kind == "Expression" then
+ | compiler:error("Cannot use an assignment operation as an expression value.")
+ | end
+ | if vars.var.value.type ~= "Var" then
+ | compiler:error("Assignment operation has the wrong type for the left hand side. "
+ | .."Expected Var, but got: "..vars.var.value.type)
+ | end
+ | if vars.value.value.type ~= "Thunk" then
+ | compiler:error("Assignment operation has the wrong type for the right hand side. "
+ | .."Expected Thunk, but got: "..vars.value.value.type.."\\nMaybe you used '=' instead of '=:'?")
+ | end
+ | local ret = "do\\n local ret"
+ | ret = ret .. "\\n "..compiler:tree_to_lua(vars.value.value.value, "Statement")
+ | ret = ret .. "\\n "..callback(compiler:tree_to_lua(vars.var, "Expression"))
+ | return (ret.."\\nend"), true
+ | end
+ |end
+ |compiler:defmacro("%var = %value", helper(function(var) return var.." = ret" end))
+ |compiler:defmacro("%var += %value", helper(function(var) return var.." = "..var.." + ret" end))
+ |compiler:defmacro("%var -= %value", helper(function(var) return var.." = "..var.." - ret" end))
+ |compiler:defmacro("%var *= %value", helper(function(var) return var.." = "..var.." * ret" end))
+ |compiler:defmacro("%var /= %value", helper(function(var) return var.." = "..var.." / ret" end))
+ |compiler:defmacro("%var ^= %value", helper(function(var) return var.." = "..var.." ^ ret" end))
+ |compiler:defmacro("%var and= %value", helper(function(var) return var.." = "..var.." and ret" end))
+ |compiler:defmacro("%var or= %value", helper(function(var) return var.." = "..var.." or ret" end))
+ |compiler:defmacro("%var concat= %value", helper(function(var) return var.." = "..var.." .. ret" end))
+ |compiler:defmacro("%var mod= %value", helper(function(var) return var.." = "..var.." % ret" end))
# Operators
-macro ["true","yes"] =: "true"
-macro ["false","no"] =: "false"
-macro ["nil","null"] =: "nil"
-macro block ["nop", "pass"] =: ""
-macro "%a + %b" =: ".."|(\%a as lua expr\ + \%b as lua expr\)
-macro "%a + %b + %c" =: ".."|(\%a as lua expr\ + \%b as lua expr\ + \%c as lua expr\)
-macro "%a + %b + %c + %d" =: ".."|(\%a as lua expr\ + \%b as lua expr\ + \%c as lua expr\ + \%d as lua expr\)
-macro "%a - %b" =: ".."|(\%a as lua expr\ - \%b as lua expr\)
-macro "%a * %b" =: ".."|(\%a as lua expr\ * \%b as lua expr\)
-macro "%a * %b * %c" =: ".."|(\%a as lua expr\ * \%b as lua expr\ * \%c as lua expr\)
-macro "%a * %b * %c * %d" =: ".."|(\%a as lua expr\ * \%b as lua expr\ * \%c as lua expr\ * \%d as lua expr\)
-macro "%a / %b" =: ".."|(\%a as lua expr\ / \%b as lua expr\)
-macro "%a === %b" =: ".."|(\%a as lua expr\ == \%b as lua expr\)
-macro "%a !== %b" =: ".."|(\%a as lua expr\ ~= \%b as lua expr\)
-macro "%a < %b" =: ".."|(\%a as lua expr\ < \%b as lua expr\)
-macro "%a < %b < %c" =: ".."|((\%a as lua expr\ < \%b as lua expr\) and (\%b as lua expr\ < \%c as lua expr\))
-macro "%a <= %b < %c" =: ".."|((\%a as lua expr\ <= \%b as lua expr\) and (\%b as lua expr\ < \%c as lua expr\))
-macro "%a <= %b <= %c" =: ".."|((\%a as lua expr\ <= \%b as lua expr\) and (\%b as lua expr\ <= \%c as lua expr\))
-macro "%a < %b <= %c" =: ".."|((\%a as lua expr\ < \%b as lua expr\) and (\%b as lua expr\ <= \%c as lua expr\))
-macro "%a > %b > %c" =: ".."|((\%a as lua expr\ > \%b as lua expr\) and (\%b as lua expr\ > \%c as lua expr\))
-macro "%a >= %b > %c" =: ".."|((\%a as lua expr\ >= \%b as lua expr\) and (\%b as lua expr\ > \%c as lua expr\))
-macro "%a >= %b >= %c" =: ".."|((\%a as lua expr\ >= \%b as lua expr\) and (\%b as lua expr\ >= \%c as lua expr\))
-macro "%a > %b >= %c" =: ".."|((\%a as lua expr\ > \%b as lua expr\) and (\%b as lua expr\ >= \%c as lua expr\))
-macro "%a <= %b" =: ".."|(\%a as lua expr\ <= \%b as lua expr\)
-macro "%a > %b" =: ".."|(\%a as lua expr\ > \%b as lua expr\)
-macro "%a >= %b" =: ".."|(\%a as lua expr\ >= \%b as lua expr\)
-macro "%a ^ %b" =: ".."|(\%a as lua expr\ ^ \%b as lua expr\)
-macro "%a and %b" =: ".."|(\%a as lua expr\ and \%b as lua expr\)
-macro "%a and %b and %c" =:
+macro:
+ true
+ yes
+..=: "true"
+macro:
+ false
+ no
+..=: "false"
+macro:
+ nil
+ null
+..=: "nil"
+macro block:
+ nop
+ pass
+..=: ""
+macro: %a + %b ..=: ".."|(\%a as lua expr\ + \%b as lua expr\)
+macro: %a + %b + %c ..=: ".."|(\%a as lua expr\ + \%b as lua expr\ + \%c as lua expr\)
+macro: %a + %b + %c + %d ..=: ".."|(\%a as lua expr\ + \%b as lua expr\ + \%c as lua expr\ + \%d as lua expr\)
+macro: %a - %b ..=: ".."|(\%a as lua expr\ - \%b as lua expr\)
+macro: %a * %b ..=: ".."|(\%a as lua expr\ * \%b as lua expr\)
+macro: %a * %b * %c ..=: ".."|(\%a as lua expr\ * \%b as lua expr\ * \%c as lua expr\)
+macro: %a * %b * %c * %d ..=: ".."|(\%a as lua expr\ * \%b as lua expr\ * \%c as lua expr\ * \%d as lua expr\)
+macro: %a / %b ..=: ".."|(\%a as lua expr\ / \%b as lua expr\)
+macro: %a === %b ..=: ".."|(\%a as lua expr\ == \%b as lua expr\)
+macro: %a !== %b ..=: ".."|(\%a as lua expr\ ~= \%b as lua expr\)
+macro: %a < %b ..=: ".."|(\%a as lua expr\ < \%b as lua expr\)
+macro: %a < %b < %c ..=: ".."|((\%a as lua expr\ < \%b as lua expr\) and (\%b as lua expr\ < \%c as lua expr\))
+macro: %a <= %b < %c ..=: ".."|((\%a as lua expr\ <= \%b as lua expr\) and (\%b as lua expr\ < \%c as lua expr\))
+macro: %a <= %b <= %c ..=: ".."|((\%a as lua expr\ <= \%b as lua expr\) and (\%b as lua expr\ <= \%c as lua expr\))
+macro: %a < %b <= %c ..=: ".."|((\%a as lua expr\ < \%b as lua expr\) and (\%b as lua expr\ <= \%c as lua expr\))
+macro: %a > %b > %c ..=: ".."|((\%a as lua expr\ > \%b as lua expr\) and (\%b as lua expr\ > \%c as lua expr\))
+macro: %a >= %b > %c ..=: ".."|((\%a as lua expr\ >= \%b as lua expr\) and (\%b as lua expr\ > \%c as lua expr\))
+macro: %a >= %b >= %c ..=: ".."|((\%a as lua expr\ >= \%b as lua expr\) and (\%b as lua expr\ >= \%c as lua expr\))
+macro: %a > %b >= %c ..=: ".."|((\%a as lua expr\ > \%b as lua expr\) and (\%b as lua expr\ >= \%c as lua expr\))
+macro: %a <= %b ..=: ".."|(\%a as lua expr\ <= \%b as lua expr\)
+macro: %a > %b ..=: ".."|(\%a as lua expr\ > \%b as lua expr\)
+macro: %a >= %b ..=: ".."|(\%a as lua expr\ >= \%b as lua expr\)
+macro: %a ^ %b ..=: ".."|(\%a as lua expr\ ^ \%b as lua expr\)
+macro: %a and %b ..=: ".."|(\%a as lua expr\ and \%b as lua expr\)
+macro: %a and %b and %c ..=:
".."|(\%a as lua expr\ and \%b as lua expr\ and \%c as lua expr\)
-macro "%a and %b and %c and %d" =:
+macro: %a and %b and %c and %d ..=:
".."|(\%a as lua expr\ and \%b as lua expr\ and \%c as lua expr\ and \%d as lua expr\)
-macro "%a or %b" =: ".."|(\%a as lua expr\ or \%b as lua expr\)
-macro "%a or %b or %c" =:
+macro: %a or %b ..=: ".."|(\%a as lua expr\ or \%b as lua expr\)
+macro: %a or %b or %c ..=:
".."|(\%a as lua expr\ or \%b as lua expr\ or \%c as lua expr\)
-macro "%a or %b or %c or %d" =:
+macro: %a or %b or %c or %d ..=:
".."|(\%a as lua expr\ or \%b as lua expr\ or \%c as lua expr\ or \%d as lua expr\)
-macro "%a mod %b" =: ".."|(\%a as lua expr\ mod \%b as lua expr\)
-macro "- %a" =: ".."|-(\%a as lua expr\)
-macro "not %a" =: ".."|not (\%a as lua expr\)
+macro: %a mod %b ..=: ".."|(\%a as lua expr\ mod \%b as lua expr\)
+macro: - %a ..=: ".."|-(\%a as lua expr\)
+macro: not %a ..=: ".."|not (\%a as lua expr\)
-rule "%a == %b" =:
+rule: %a == %b ..=:
lua expr "((vars.a == vars.b) or compiler.utils.equivalent(vars.a, vars.b))"
-rule "%a != %b" =:
+rule: %a != %b ..=:
lua expr "((vars.a ~= vars.b) or not compiler.utils.equivalent(vars.a, vars.b))"
-macro "repr %obj" =:
+macro: repr %obj ..=:
".."|compiler.utils.repr(\%obj as lua expr\, true)
-macro "say %str" =:
+macro: say %str ..=:
".."|compiler:writeln(compiler.utils.repr(\%str as lua expr\))
# Control flow
-rule "do %action" =:
+rule: do %action ..=:
lua expr "vars.action(compiler, setmetatable({}, {__index=vars}))"
-macro block "return %return_value" =:
+macro block: return %return_value ..=:
lua block ".."
|if vars.return_value.value.type ~= "Thunk" then
| compiler:error("Assignment operation has the wrong type for the right hand side. "
@@ -224,16 +260,16 @@ macro block "return %return_value" =:
| return ret
|end
-macro block "return" =:
+macro block: return ..=:
"return nil"
# Conditionals
-macro block "if %condition %if_body" =:
+macro block: if %condition %if_body ..=:
".."|if \%condition as lua expr\ then
| \(lua expr "vars.if_body.value.value") as lua block\
|end
-macro block "if %condition %if_body else %else_body" =:
+macro block: if %condition %if_body else %else_body ..=:
".."|if \%condition as lua expr\ then
| \(lua expr "vars.if_body.value.value") as lua block\
|else
@@ -241,7 +277,7 @@ macro block "if %condition %if_body else %else_body" =:
|end
# Ternary operator
-macro "%if_expr if %condition else %else_expr" =:
+macro: %if_expr if %condition else %else_expr ..=:
".."|(function(compiler, vars)
| if \%condition as lua expr\ then
| return \%if_expr as lua expr\
@@ -250,8 +286,51 @@ macro "%if_expr if %condition else %else_expr" =:
| end
|end)(compiler, vars)
-# For loop
-macro block "for %var in %iterable %body" =:
+# Loop control flow
+macro block: break ..=: "break"
+macro block: continue ..=: "continue"
+# TODO: add labeled break/continue?
+
+# GOTOs
+lua block ".."
+ |local function lua_label(label)
+ | if label.type ~= "Var" then
+ | compiler:error("Goto label has the wrong type for the label. Expected Var, but got: "..label.type)
+ | end
+ | local bits = "abcdefghijklmnop"
+ | local lua_identifier = "label_"
+ | for i=1,#label.value do
+ | local byte = string.byte(label.value, i)
+ | local low = byte % 16
+ | local high = (byte - low) / 16
+ | lua_identifier = lua_identifier .. bits:sub(low+1,low+1) .. bits:sub(high+1,high+1)
+ | end
+ | return lua_identifier
+ |end
+ |
+ |compiler:defmacro("-> %label", function(compiler, vars, kind)
+ | return "::"..lua_label(vars.label.value).."::", true
+ |end)
+ |compiler:defmacro("go to %label", function(compiler, vars, kind)
+ | return "goto "..lua_label(vars.label.value), true
+ |end)
+
+# While loops
+macro block: repeat %body ..=:
+ ".."|while true do
+ | \(lua expr "vars.body.value.value") as lua block\
+ |end
+macro block: repeat while %condition %body ..=:
+ ".."|while \%condition as lua expr\ do
+ | \(lua expr "vars.body.value.value") as lua block\
+ |end
+macro block: repeat until %condition %body ..=:
+ ".."|while not (\%condition as lua expr\) do
+ | \(lua expr "vars.body.value.value") as lua block\
+ |end
+
+# For loops
+macro block: for %var in %iterable %body ..=:
%var-type =: lua expr "vars.var.value.type"
if (%var-type != "Var"):
error ".."
@@ -264,7 +343,7 @@ macro block "for %var in %iterable %body" =:
|end
|\%var-code\ = old_loopval
-macro block "for all %iterable %body" =:
+macro block: for all %iterable %body ..=:
".."|local old_loopval = vars.it
|for i,value in ipairs(\%iterable as lua expr\) do
| vars.it = value
@@ -274,7 +353,7 @@ macro block "for all %iterable %body" =:
# List Comprehension
# TODO: maybe make this lazy, or a lazy version?
-macro "%expression for %var in %iterable" =:
+macro: %expression for %var in %iterable ..=:
%var-type =: lua expr "vars.var.value.type"
if (%var-type != "Var"):
error ".."
@@ -289,7 +368,7 @@ macro "%expression for %var in %iterable" =:
| return comprehension
|end)(game, setmetatable({}, {__index=vars}))
-macro "%expression for all %iterable" =:
+macro: %expression for all %iterable ..=:
".."|(function(game, vars)
| local comprehension = {}
| for i,value in ipairs(\%iterable as lua expr\) do
@@ -300,7 +379,7 @@ macro "%expression for all %iterable" =:
|end)(game, setmetatable({}, {__index=vars}))
# Dict comprehension
-macro "%key -> %value for %var in %iterable" =:
+macro: %key -> %value for %var in %iterable ..=:
%var-type =: lua expr "vars.var.value.type"
if (%var-type != "Var"):
error ".."
@@ -315,7 +394,7 @@ macro "%key -> %value for %var in %iterable" =:
| return comprehension
|end)(game, setmetatable({}, {__index=vars}))
-macro "%key -> %value for all %iterable" =:
+macro: %key -> %value for all %iterable ..=:
".."|(function(game, vars)
| local comprehension = {}
| for i,value in ipairs(\%iterable as lua expr\) do
@@ -326,58 +405,91 @@ macro "%key -> %value for all %iterable" =:
|end)(game, setmetatable({}, {__index=vars}))
# Number ranges
-rule "%start up to %stop" =:
+rule: %start up to %stop ..=:
lua expr "compiler.utils.range(vars.start,vars.stop-1)"
-rule ["%start thru %stop", "%start through %stop"] =:
+rule:
+ %start thru %stop
+ %start through %stop
+..=:
lua expr "compiler.utils.range(vars.start,vars.stop)"
-rule "%start down to %stop" =:
+rule: %start down to %stop ..=:
lua expr "compiler.utils.range(vars.start,vars.stop+1,-1)"
-rule ["%start down thru %stop", "%start down through %stop"] =:
+rule:
+ %start down thru %stop
+ %start down through %stop
+..=:
lua expr "compiler.utils.range(vars.start,vars.stop,-1)"
-rule "%start up to %stop via %step" =:
+rule: %start up to %stop via %step ..=:
lua expr "compiler.utils.range(vars.start,vars.stop-1,vars.step)"
-rule ["%start thru %stop via %step", "%start through %stop via %step"] =:
+rule:
+ %start thru %stop via %step
+ %start through %stop via %step
+..=:
lua expr "compiler.utils.range(vars.start,vars.stop,vars.step)"
-rule "%start down to %stop via %step" =:
+rule: %start down to %stop via %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"] =:
+rule:
+ %start down thru %stop via %step
+ %start down through %stop via %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 "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"] =:
+rule: random number ..=: lua expr "math.random()"
+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 "compiler.utils.min(vars.items)"
-rule ["max of %items", "biggest of %items", "largest of %items", "highest of %items"] =:
+rule:
+ max of %items
+ biggest of %items
+ largest of %items
+ highest of %items
+..=:
lua expr "compiler.utils.min(vars.items)"
-rule ["min of %items with respect to %keys"] =:
+rule: min of %items with respect to %keys ..=:
lua expr "compiler.utils.min(vars.items, vars.keys)"
-rule ["max of %items with respect to %keys"] =:
+rule: max of %items with respect to %keys ..=:
lua expr "compiler.utils.max(vars.items, vars.keys)"
# List/dict functions
-macro [..]
- "%list 's %index", "%index st in %list", "%index nd in %list", "%index rd in %list"
- "%index th in %list", "%index in %list", "%list -> %index"
+macro:
+ %list's %index
+ %index st in %list
+ %index nd in %list
+ %index rd in %list
+ %index th in %list
+ %index in %list
+ %list -> %index
..=:
".."|\%list as lua expr\[\%index as lua expr\]
-macro block [..]
- "%list 's %index = %value", "%index st in %list = %value", "%index nd in %list = %value"
- "%index rd in %list = %value", "%index th in %list = %value", "%index in %list = %value"
- "%index = %value in %list", "%list -> %index = %value"
+macro block:
+ %list's %index = %value
+ %index st in %list = %value
+ %index nd in %list = %value
+ %index rd in %list = %value
+ %index th in %list = %value
+ %index in %list = %value
+ %list -> %index = %value
..=:
lua block ".."
|if vars.value.value.type ~= "Thunk" then
@@ -390,20 +502,27 @@ macro block [..]
| \%list as lua expr\[\%index as lua expr\] = ret
|end
-macro ["%item is in %list", "%list contains %item"] =:
+macro:
+ %item is in %list
+ %list contains %item
+..=:
".."|(\%list as lua expr\[\%index as lua expr\] ~= nil)
-macro ["length of %list", "size of %list", "number of %list"] =:
+macro:
+ length of %list
+ size of %list
+ number of %list
+..=:
".."|#(\%list as lua expr\)
-rule "dict %items" =:
+rule: dict %items ..=:
%dict =: []
for %pair in %items:
lua block "vars.dict[vars.pair[1]] = vars.pair[2]"
return: %dict
# Permission functions
-rule "restrict %fn to within %whitelist" =:
+rule: restrict %fn to within %whitelist ..=:
lua block ".."
|local fns = compiler:get_invocations(vars.fn)
|local whitelist = compiler:get_invocations(vars.whitelist)
@@ -425,7 +544,7 @@ rule "restrict %fn to within %whitelist" =:
| end
|end
-rule "allow %whitelist to use %fn" =:
+rule: allow %whitelist to use %fn ..=:
lua block ".."
|local fns = compiler:get_invocations(vars.fn)
|local whitelist = compiler:get_invocations(vars.whitelist)
@@ -449,7 +568,7 @@ rule "allow %whitelist to use %fn" =:
| end
|end
-rule "forbid %blacklist to use %fn" =:
+rule: forbid %blacklist to use %fn ..=:
lua block ".."
|local fns = compiler:get_invocations(vars.fn)
|local blacklist = compiler:get_invocations(vars.blacklist)
@@ -472,7 +591,7 @@ rule "forbid %blacklist to use %fn" =:
|end
# For unit testing
-macro block "test %code yields %expected" =:
+macro block: test %code yields %expected ..=:
%generated =: lua expr "compiler.utils.repr(compiler:stringify_tree(vars.code.value.value), true)"
%expected =: %expected as lua expr
if (%generated != %expected):
diff --git a/examples/parser_tests.nom b/examples/parser_tests.nom
index 000b8de..81608b7 100644
--- a/examples/parser_tests.nom
+++ b/examples/parser_tests.nom
@@ -9,21 +9,23 @@ test: say (4) ..yields ".."
| 4
test:
- rule "fart" =: say "poot"
+ rule: fart ..=: say "poot"
..yields ".."
|Call [rule % = %]:
- | "fart"
+ | Thunk:
+ | Call [fart]!
| Thunk:
| Call [say %]:
| "poot"
test:
- rule "doublefart":
+ rule: doublefart ..=:
say "poot"
say "poot"
..yields ".."
- |Call [rule % %]:
- | "doublefart"
+ |Call [rule % = %]:
+ | Thunk:
+ | Call [doublefart]!
| Thunk:
| Call [say %]:
| "poot"
diff --git a/examples/sample_code.nom b/examples/sample_code.nom
index 2917be1..4f4d2dd 100644
--- a/examples/sample_code.nom
+++ b/examples/sample_code.nom
@@ -11,7 +11,7 @@ say (4)
#.. "rule" is just a function that takes a function call spec and a block of code to run,
and stores the function definition
-rule "fart": say "poot"
+rule: fart ..=: say "poot"
fart
@@ -33,13 +33,13 @@ say ".."
|(done)
|
-rule "doublefart": # this farts twice
+rule: doublefart ..=: # this farts twice
say "poot"
say "poot"
doublefart
-rule "subex work": return "subexpressions work"
+rule: subex work ..=: "subexpressions work"
say (subex work)
@@ -54,7 +54,7 @@ say [..]
1, 2
3
-rule "say both %one and %two":
+rule: say both %one and %two ..=:
say %one
say %two
@@ -68,7 +68,7 @@ say both..
"hello"
and "world"
-rule "three": return 3
+rule: three ..=: 3
say both ..
"a list:"
and [..]
@@ -79,16 +79,16 @@ if 1: yes
if 1: yes ..else: no
-say (do: return 5)
+say (do: return: 5)
-rule "do %one also %two":
+rule: do %one also %two ..=:
do %one
do %two
do: say "one liner"
..also: say "another one liner"
-say (do: return "wow")
+say (do: return: "wow")
say (1 + (-(2 * 3)))
@@ -110,27 +110,23 @@ say ".."
| with multiple lines
| and an interpolated expression: \2 + 5\
-rule "%n bottles":
- lua block [..]
- ".."
- |do
- | print("running raw lua code...")
- | local n =
- .., %n, ".."
- |
- | for i=n,1,-1 do
- | print(tostring(i).." bottles of beer on the wall. Take one down, pass it around,")
- | end
- | print("no more bottles of beer on the wall.")
- |end
+rule: %n bottles ..=:
+ lua block ".."
+ |do
+ | print("running raw lua code...")
+ | for i=\%n\,1,-1 do
+ | print(tostring(i).." bottles of beer on the wall. Take one down, pass it around,")
+ | end
+ | print("no more bottles of beer on the wall.")
+ |end
nil
9 bottles
-rule "dumsum %nums":
- let "sum" = 0
- for "n" in %nums:
- let "sum" = (%sum + %n)
- return %sum
+rule: dumsum %nums ..=:
+ %sum =: 0
+ for %n in %nums:
+ %sum +=: %n
+ return: %sum
say (dumsum [1,2,3])
diff --git a/examples/sample_game.nom b/examples/sample_game.nom
index a316b77..87f2c60 100644
--- a/examples/sample_game.nom
+++ b/examples/sample_game.nom
@@ -1,4 +1,155 @@
run file "core.nom"
+run file "lib/secrets.nom"
+
+
+with secrets:
+ rule: pending proposal ..=:
+ secret %pending
+
+ rule: propose source %src ..=:
+ secret %pending =: %src
+ say ".."
+ |Proposal\%src\
+
+ macro block: propose %action ..=: ".."
+ |compiler:call("propose source %", \repr (%action's "src")\)
+
+ rule: approve ..=:
+ if (pending proposal):
+ say ".."
+ |Running\pending proposal\
+ do (..)
+ eval ".."
+ |return: \pending proposal\
+ ..else:
+ say "No action pending"
+
+propose:
+ say "motion passed."
+ rule: fart ..=:
+ say "poot"
+
+approve
+fart
+
+# Users:
+with secrets:
+ secret %users =: lua expr "require('users')"
+ rule: find user %name ..=:
+ lua expr "secrets.users.by_name(vars.name) or compiler:error('Failed to find user: '..tostring(vars.name))"
+ rule: add user %name ..=:
+ lua expr "secrets.users.add(vars.name)"
+ macro: @ %name_block ..=:
+ %name_str =: lua expr "vars.name_block.value.value.src"
+ ".."|compiler:call("find user %", \repr %name_str\)
+
+say ".."|A user looks like: \@:spill\
+say ".."|A user looks like: \@:spill\
+add user "dave"
+say ".."|A user looks like: \@:dave\
+add user "moloch"
+say ".."|A user looks like: \@:moloch\
+add user "bruce"
+
+# Inventory:
+with secrets:
+ secret %inventory =: lua expr ".."
+ |setmetatable({}, {__index=function(self,key)
+ | local t = {}
+ | self[key] = t
+ | return t
+ |end})
+ with secrets:
+ lua block ".."
+ |local endings = setmetatable({x="es",c="es",s="es"}, {__index=function() return "s" end})
+ |secrets.plurals = setmetatable({}, {__index=function(self,key)
+ | return key..endings[key:sub(-1)]
+ |end})
+ |secrets.singulars = setmetatable({}, {__index=function(self,key)
+ | if key:sub(-2) == "es" and rawget(endings, key:sub(-3,-3)) then return key:sub(1,-3) end
+ | if key:sub(-1) == "s" then return key:sub(1,-2) end
+ | return key
+ |end})
+ |secrets.canonicals = setmetatable({}, {__index=function(self,key)
+ | if key:sub(-1) == "s" then return secrets.singulars[key] end
+ | return key
+ |end})
+
+ rule: the plural of %singular is %plural ..=:
+ (secret %plurals)->%singular =: %plural
+ (secret %singulars)->%plural =: %singular
+ (secret %canonicals)->%plural =: %singular
+
+ rule: singular %plural ..=:
+ %plural in (secret %singulars)
+
+ rule: plural %singular ..=:
+ %singular in (secret %plurals)
+
+ rule: canonicalize %item-name ..=:
+ %item-name in (secret %canonicals)
+
+ rule: %person's inventory ..=:
+ (secret %inventory)->%person
+
+ rule: %person's stock of %item ..=:
+ %item =: canonicalize %item
+ ((%person's inventory)->%item) or 0
+
+ rule: %person's stock of %item as str ..=:
+ %item =: canonicalize %item
+ %count =: %person's stock of %item
+ ".."
+ |\%count\ \(singular %item) if (%count == 1) else (plural %item)\
+
+ rule: give %person %count %item ..=:
+ %item =: canonicalize %item
+ (%person's inventory)-> %item =: (%person's stock of %item) + %count
+
+ rule: give %person %count %item from %donor ..=:
+ %item =: canonicalize %item
+ if ((%donor's stock of %item) < %count):
+ say ".."
+ |\%donor\ does not have enough \%item\ to transfer
+ ..else:
+ (%person's inventory)->%item =: (%person's stock of %item) + %count
+ (%donor's inventory)->%item =: (%donor's stock of %item) - %count
+
+ rule:
+ %person has %item
+ %person has a %item
+ %person has an %item
+ ..=:
+ (%person's stock of %item) > 0
+
+give (@:bruce) 3 "hats"
+give (@:bruce) 3 "hats"
+give (@:dave) 1 "hat" from (@:bruce)
+say ".."|Bruce has \(@:bruce)'s stock of "hats" as str\
+say ".."|Dave has \(@:dave)'s stock of "hats" as str\
+give (@:dave) 1 "box"
+say ".."|Dave has \(@:dave)'s stock of "boxes" as str\
+the plural of "goose" is "geese"
+give (@:dave) 1 "goose"
+say ".."|Dave has \(@:dave)'s stock of "geese" as str\
+give (@:dave) 1 "goose"
+say ".."|Dave has \(@:dave)'s stock of "geese" as str\
+
+do:
+ lua block "math.randomseed(os.time())"
+ repeat until ((random number) < 0.01):
+ say "tick"
+ say "tock"
+
+
+
+
+
+
+
+
+
+
# A basic key-value store that's only accessible through these functions:
lua block ".."
|do -- Use a closure to hide this behind the accessor rules
diff --git a/examples/tutorial.nom b/examples/tutorial.nom
index 7106f94..5f0acb3 100644
--- a/examples/tutorial.nom
+++ b/examples/tutorial.nom
@@ -25,7 +25,7 @@ run file "core.nom"
5
6,7,8
-# Dicts:
+# Dictionaries (AKA hash maps):
dict [["x", 99], ["y", 101]]
dict [..]
["z", 222]
@@ -34,22 +34,105 @@ dict [..]
# Function calls:
say "Hello world!"
+# Variables use the % sign:
+%str =: "Hello again"
+say %str
+
+# There are +=:, -=:, *=:, /=:, ^=:, and=:, or=:, and mod=: operators for updating variables
+%x =: 1
+%x +=: 100
+say %x
+
+# Conditionals look like this:
+if (1 < 10):
+ say "1 is indeed < 10"
+
+if (1 > 10):
+ say "this won't print"
+..else:
+ say "this will print"
+
+if (1 > 3):
+ say "this won't print"
+..else: if (1 < 2):
+ say "this won't print"
+..else:
+ say "this will print"
+
+# Loops look like this:
+for %x in [1,2,3]:
+ say ".."|for loop over list #\%x\
+
+# If you want to iterate over a numeric range, you can use some built in functions like this:
+for %x in (1 through 3):
+ say ".."|for loop over number range #\%x\
+
+# While loops:
+%x =: 1
+repeat while (%x <= 3):
+ say ".."|repeat while loop #\%x\
+ %x +=: 1
+
+%x =: 1
+repeat until (%x > 3):
+ say ".."|repeat until loop #\%x\
+ %x +=: 1
+
+# Infinite loop:
+%x =: 1
+repeat:
+ say ".."|repeat loop #\%x\
+ %x +=: 1
+ if (%x > 3):
+ break
+
+# GOTOs:
+do:
+ %x =: 1
+ -> %again
+ say ".."|go to loop #\%x\
+ %x +=: 1
+ if (%x <= 3):
+ go to %again
+ say "finished going to"
+
+
# Function definition:
-rule "say both %first and also %second":
- # Variables use the "%" sign:
+rule:
+ say both %first and also %second
+..=:
+ # Function arguments are accessed just like variables
say %first
say %second
-rule "get x from %dict":
- #.. Functions can return values explicitly, but if not, the last line in the function
- is the return value.
- return (%dict's "x")
+# The last line of a function is the return value
+rule:
+ add %x and %y
+..=:
+ %result =: %x + %y
+ %result
+
+# Functions can use "return" to return a value early
+rule:
+ first fibonacci above %n
+..=:
+ %f1 =: 0
+ %f2 =: 1
+ repeat:
+ %tmp =: %f1 + %f2
+ %f1 =: %f2
+ %f2 =: %tmp
+ if (%f2 > %n):
+ return: %f2
+
+say (first fibonacci above 10)
# Functions can have aliases, which may or may not have the arguments in different order
-rule [..]
- "I hate %worse-things more than %better-things", "I think %worse-things are worse than %better-things"
- "I like %better-things more than %worse-things"
-..:
+rule:
+ I hate %worse-things more than %better-things
+ I think %worse-things are worse than %better-things
+ I like %better-things more than %worse-things
+..=:
say ".."|\%better-things capitalized\ rule and \%worse-things\ drool!
I like "dogs" more than "cats"
@@ -61,24 +144,33 @@ I think "chihuahuas" are worse than "corgis"
say both "Hello" and also "again!"
# Functions can even have their name at the end:
-rule "%what-she-said is what she said":
+rule:
+ %what-she-said is what she said
+..=:
say %what-she-said
say "-- she said"
+
"Howdy pardner" is what she said
#.. The language only reserves []{}().,:;% as special characters, so functions and variables
can have really funky names!
-rule ">> %foo-bar$$$^ --> %@@& _~-^-~_~-^ %1 !":
+rule:
+ >> %foo-bar$$$^ --> %@@& _~-^-~_~-^ %1 !
+..=:
say %foo-bar$$$^
say %@@&
say %1
+
>> "wow" --> "so flexible!" _~-^-~_~-^ "even numbers can be variables!" !
-# Though literals can't be used in function names
# Math and logic operations are just treated the same as function calls in the syntax
say (2 + 3)
# So it's easy to define your own operators
-rule "%a ++ %b": 2 * (%a + %b)
+rule:
+ %a ++ %b
+..=:
+ 2 * (%a + %b)
+
say (2 ++ 3)
@@ -121,7 +213,7 @@ say both ".."
..and also..
"-- Abraham Lincoln"
-rule "my favorite number": return 23
+rule: my favorite number ..=: 21 + 2
# Subexpressions are wrapped in parentheses:
say (my favorite number)
@@ -139,48 +231,10 @@ say ".."
number
..\, but this time it uses an indented subexpression!
-#.. There's a few macros in the language for things like conditional branches and logic/math
- operations, but they can be thought of as basically the same as functions.
- There are no keywords in the language!
-if (1 < 10):
- say "One is less than ten"
-..else:
- say "One is not less than ten"
-
-#.. Breakdown of the above:
- Function call (actually a macro) to "if % % else %"
- First argument is a subexpression that is a function call (also a macro) to "% < %"
- that performs a comparison on its arguments, 1 and 10
- Second argument is a block of code that includes a function call to "say %", the "if" body
- Third argument is a block of code that includes a different function call to "say %", the "else" body
-
-# Line continuations can be used for "elseif"
-if (1 > 10):
- say "First condition"
-..else: if (1 > 5):
- say "Second condition"
-..else:
- say "Last condition"
-
-# ^that's the same as:
-if (1 > 10):
- say "First condition"
-..else:
- if (1 > 5):
- say "Second condition"
- ..else:
- say "Last condition"
-
-# Variables are modified with a macro, "let % = %"
-let "numbers" = [5,6,7]
-
-# Looping:
-say ".."|Looping over \%numbers\:
-for "number" in %numbers:
- say (%number + 100)
-
-rule "sing %starting-bottles bottles of beer":
- for "n" in (%starting-bottles down through 0):
+rule:
+ sing %starting-bottles bottles of beer
+..=:
+ for %n in (%starting-bottles down through 0):
say ".."
|\%n if (%n > 0) else "No more"\ \"bottle" if (%n == 1) else "bottles"\ of beer on the wall.
|\"" if (%n == 0) else " Take one down, pass it around..."\
@@ -206,7 +260,7 @@ any of [0,0,0,0,1,0,0]
# Macros:
# The "lua block %" and "lua expr %" macros can be used to write raw lua code:
-rule "say the time":
+rule: say the time ..=:
lua block ".."
|io.write("The OS time is: ")
|io.write(tostring(os.time()).."\\n")
@@ -215,24 +269,23 @@ say ".."|Math expression result is: \lua expr "(1 + 2*3 + 3*4)^2"\
#.. In the lua environment, "vars" can be used to get local variables/function args, and
"compiler" can be used to access the compiler, function defs, and other things
-rule "square root of %n":
- return (lua expr "math.sqrt(vars.n)")
+rule: square root of %n ..=:
+ lua expr "math.sqrt(vars.n)"
say ".."|The square root of 2 is \square root of 2\
# Macros can be defined as functions that take unprocessed syntax trees and return lua code
# "macro block %" is for defining macros that produce blocks of code, not values
-macro block "unless %condition %body":
- ".."
- |if not (\%condition as lua expr\) then
- | \(lua expr "vars.body.value.value") as lua block\
- |end
+macro block: unless %condition %body ..=: ".."
+ |if not (\%condition as lua expr\) then
+ | \(lua expr "vars.body.value.value") as lua block\
+ |end
unless (1 > 10):
say "Macros work!"
say "It looks like a keyword, but there's no magic here!"
# and "macro %" is for defining macros that produce an expression
-macro "%value as a boolean":
- ".."|(not not (\%value as lua expr\))
-macro "yep": "true"
+macro: %value as a boolean ..=: ".."
+ |(not not (\%value as lua expr\))
+macro: yep ..=: "true"
diff --git a/nomsu.lua b/nomsu.lua
index 443b663..6a4793d 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -203,7 +203,43 @@ do
self.defs[invocation] = fn_info
end
end,
+ get_invocations_from_definition = function(self, def, vars)
+ if def.type == "String" or def.type == "List" then
+ return self:tree_to_value(def, vars)
+ end
+ if def.type ~= "Thunk" then
+ self:error("Trying to get invocations from " .. tostring(def.type) .. ", but expected Thunk.")
+ end
+ local invocations = { }
+ local _list_0 = def.value.value
+ for _index_0 = 1, #_list_0 do
+ local statement = _list_0[_index_0]
+ if statement.value.type ~= "FunctionCall" then
+ self:error("Invalid statement type: " .. tostring(statement.value.type) .. ", expected FunctionCall")
+ end
+ local name_bits = { }
+ local _list_1 = statement.value.value
+ for _index_1 = 1, #_list_1 do
+ local token = _list_1[_index_1]
+ if token.type == "Word" then
+ table.insert(name_bits, token.value)
+ elseif token.value.type == "Var" then
+ table.insert(name_bits, token.value.src)
+ else
+ self:error("Unexpected token type in definition: " .. tostring(token.value.type) .. " (expected Word or Var)")
+ end
+ end
+ table.insert(invocations, table.concat(name_bits, " "))
+ end
+ return invocations
+ end,
get_invocations = function(self, text)
+ if not text then
+ self:error("No text provided!")
+ end
+ if type(text) == 'function' then
+ error("Function passed to get_invocations")
+ end
if type(text) == 'string' then
text = {
text
@@ -764,11 +800,21 @@ do
if kind == "Expression" then
error("Expected to be in statement.")
end
- return "do\n" .. self:tree_to_value(vars.lua_code, vars) .. "\nend", true
+ local inner_vars = setmetatable({ }, {
+ __index = function(_, key)
+ return "vars[" .. tostring(utils.repr(key, true)) .. "]"
+ end
+ })
+ return "do\n" .. self:tree_to_value(vars.lua_code, inner_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)
+ local inner_vars = setmetatable({ }, {
+ __index = function(_, key)
+ return "vars[" .. tostring(utils.repr(key, true)) .. "]"
+ end
+ })
+ return self:tree_to_value(vars.lua_code, inner_vars)
end)
return self:def("run file %filename", function(self, vars)
local file = io.open(vars.filename)
diff --git a/nomsu.moon b/nomsu.moon
index 1a0b370..c8e339e 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -9,6 +9,7 @@ utils = require 'utils'
-- better scoping?
-- first-class functions
-- better error reporting
+-- versions of rules with auto-supplied arguments
-- type checking?
INDENT = " "
@@ -137,8 +138,33 @@ class NomsuCompiler
fn_info = {:fn, :arg_names, :invocations, :src, is_macro:false}
for invocation in *invocations
@defs[invocation] = fn_info
+
+ get_invocations_from_definition:(def, vars)=>
+ if def.type == "String" or def.type == "List"
+ return @tree_to_value(def, vars)
+
+ if def.type != "Thunk"
+ @error "Trying to get invocations from #{def.type}, but expected Thunk."
+ invocations = {}
+ for statement in *def.value.value
+ if statement.value.type != "FunctionCall"
+ @error "Invalid statement type: #{statement.value.type}, expected FunctionCall"
+ name_bits = {}
+ for token in *statement.value.value
+ if token.type == "Word"
+ table.insert name_bits, token.value
+ elseif token.value.type == "Var"
+ table.insert name_bits, token.value.src
+ else
+ @error "Unexpected token type in definition: #{token.value.type} (expected Word or Var)"
+ table.insert invocations, table.concat(name_bits, " ")
+ return invocations
get_invocations:(text)=>
+ if not text
+ @error "No text provided!"
+ if type(text) == 'function'
+ error "Function passed to get_invocations"
if type(text) == 'string' then text = {text}
invocations = {}
arg_names = {}
@@ -559,11 +585,13 @@ class NomsuCompiler
@defmacro [[lua block %lua_code]], (vars, kind)=>
if kind == "Expression" then error("Expected to be in statement.")
- return "do\n"..@tree_to_value(vars.lua_code, vars).."\nend", true
+ inner_vars = setmetatable({}, {__index:(_,key)-> "vars[#{utils.repr(key,true)}]"})
+ return "do\n"..@tree_to_value(vars.lua_code, inner_vars).."\nend", true
@defmacro [[lua expr %lua_code]], (vars, kind)=>
lua_code = vars.lua_code.value
- return @tree_to_value(vars.lua_code, vars)
+ inner_vars = setmetatable({}, {__index:(_,key)-> "vars[#{utils.repr(key,true)}]"})
+ return @tree_to_value(vars.lua_code, inner_vars)
@def "run file %filename", (vars)=>
file = io.open(vars.filename)