aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--examples/parser_tests.nom7
-rw-r--r--examples/sample_code.nom6
-rw-r--r--examples/sample_game.nom3
-rw-r--r--examples/tutorial.nom9
-rw-r--r--lib/collections.nom57
-rw-r--r--lib/control_flow.nom139
-rw-r--r--lib/metaprogramming.nom53
-rw-r--r--lib/operators.nom36
-rw-r--r--lib/permissions.nom21
-rw-r--r--lib/secrets.nom6
-rw-r--r--lib/testing.nom2
-rw-r--r--lib/utils.nom52
-rwxr-xr-xnomsu.moon12
14 files changed, 206 insertions, 201 deletions
diff --git a/README.md b/README.md
index 9cd2ba0..d0e7b1d 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,8 @@ which produces an output file which can be run with the command `lua output_file
Example code can be found in the examples folder.
-core.nom contains some *extremely* helpful and basic core functionality for the language,
-written in the language itself, so I recommend adding `run file "core.nom"` to the top of
+lib/core.nom contains some *extremely* helpful and basic core functionality for the language,
+written in the language itself, so I recommend adding `require "lib/core.nom"` to the top of
your files.
There is a vim plugin for the language available in the [Vim Nomsu repository](https://bitbucket.org/squidarms/vim-nomsu/src).
diff --git a/examples/parser_tests.nom b/examples/parser_tests.nom
index b1eb23b..b91266e 100644
--- a/examples/parser_tests.nom
+++ b/examples/parser_tests.nom
@@ -1,4 +1,5 @@
require "lib/core.nom"
+require "lib/testing.nom"
test: say "foo"
..yields ".."
@@ -148,12 +149,12 @@ test:
z
..yields ".."
|Call [if % % else %]:
- | Var[x]
+ | Var["x"]
| Thunk:
| Call [x]!
| Thunk:
| Call [if % % else %]:
- | Var[y]
+ | Var["y"]
| Thunk:
| Call [y]!
| Thunk:
@@ -169,6 +170,6 @@ test:
%Brian's hat
..yields ".."
|Call [% 's hat]:
- | Var[Brian]
+ | Var["Brian"]
say "All tests passed!"
diff --git a/examples/sample_code.nom b/examples/sample_code.nom
index e2b3a62..fe73ec7 100644
--- a/examples/sample_code.nom
+++ b/examples/sample_code.nom
@@ -78,7 +78,7 @@ if 1: yes
if 1 (:yes) else (:no)
-say (do: return: 5)
+say (do: return 5)
# Some variables
rule [do %one also %two] =:
@@ -88,7 +88,7 @@ rule [do %one also %two] =:
do: say "one liner"
..also: say "another one liner"
-say (do: return: "wow")
+say (do: return "wow")
say (1 + (-(2 * 3)))
@@ -146,7 +146,7 @@ rule [dumsum %nums] =:
%sum =: 0
for %n in %nums:
%sum +=: %n
- return: %sum
+ return %sum
say (dumsum [1,2,3])
diff --git a/examples/sample_game.nom b/examples/sample_game.nom
index 44b9d35..1f526e3 100644
--- a/examples/sample_game.nom
+++ b/examples/sample_game.nom
@@ -1,4 +1,5 @@
require "lib/core.nom"
+require "lib/permissions.nom"
require "lib/secrets.nom"
require "lib/plurals.nom"
@@ -101,8 +102,6 @@ with secrets:
say ".."
|Proposal:
|\%src\
- say "foo"
-
macro block [propose %action] =:
%source =: source code from tree %action
diff --git a/examples/tutorial.nom b/examples/tutorial.nom
index 306a0af..8739348 100644
--- a/examples/tutorial.nom
+++ b/examples/tutorial.nom
@@ -234,6 +234,7 @@ sing 9 bottles of beer
say (5 + (4 * (- (1 + (6 + 2)))))
# For convenience, +,*,"and", and "or" have been hand defined to work with up to 4 operands:
1 + 2 + 3 + 4
+say "Done with math."
1 * 2 * 3 * 4
1 and 2 and 3 and 4
1 or 2 or 3 or 4
@@ -245,6 +246,8 @@ any of [0,0,0,0,1,0,0]
# And 3-operand chained inequality comparisons have been defined:
1 < 2 <= 3
+say "Done with math."
+
# Macros:
# The "lua block %" and "lua expr %" macros can be used to write raw lua code:
@@ -264,8 +267,8 @@ 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") as lua block\
+ |if not (\%condition as lua\) then
+ | \(lua expr "vars.body.value") as lua\
|end
unless (1 > 10):
@@ -274,6 +277,6 @@ unless (1 > 10):
# and "macro %" is for defining macros that produce an expression
macro [%value as a boolean] =: ".."
- |(not not (\%value as lua expr\))
+ |(not not (\%value as lua\))
macro [yep] =: "true"
diff --git a/lib/collections.nom b/lib/collections.nom
index 3751d27..dbe2afa 100644
--- a/lib/collections.nom
+++ b/lib/collections.nom
@@ -9,18 +9,18 @@ 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\]
- ".."|\%list as lua expr\[\%index as lua expr\]
+ ".."|\%list as lua\[\%index as lua\]
+ ".."|\%list as lua\[\%index as lua\]
macro [..]
%index st to last in %list, %index nd to last in %list, %index rd to last in %list
%index th to last in %list
..=:
- ".."|compiler.utils.nth_to_last(\%list as lua expr\, \%index as lua expr\)
+ ".."|compiler.utils.nth_to_last(\%list as lua\, \%index as lua\)
macro [first in %list, first %list] =:
- ".."|\%list as lua expr\[1]
+ ".."|\%list as lua\[1]
macro [last in %list, last %list] =:
- ".."|compiler.utils.nth_to_last(\%list as lua expr\, 1)
+ ".."|compiler.utils.nth_to_last(\%list as lua\, 1)
# Dict iteration convenience function. This could also be accomplished with: for all (entries in %dict): ...
macro block [for %key -> %value in %dict %body] =:
@@ -31,9 +31,9 @@ macro block [for %key -> %value in %dict %body] =:
".."
|do
| local vars = setmetatable({}, {__index=vars})
- | for k, v in pairs(\%dict as lua expr\) do
- | \%key as lua expr\, \%value as lua expr\ = k, v
- | \%body as lua block\
+ | for k, v in pairs(\%dict as lua\) do
+ | \%key as lua\, \%value as lua\ = k, v
+ | \%body as lua\
| end
|end
@@ -43,7 +43,7 @@ rule [%item is in %list, %list contains %item, %list has %item] =:
if (%key == %item): return (yes)
return (no)
macro [%list has key %index, %list has index %index] =: ".."
- |(\%list as lua expr\[\%index as lua expr\] ~= nil)
+ |(\%list as lua\[\%index as lua\] ~= nil)
rule [..]
%item isn't in %list, %item is not in %list
@@ -57,17 +57,19 @@ rule [..]
macro [..]
%list doesn't have key %index, %list does not have key %index
%list doesn't have index %index, %list does not have index %index
-..=: ".."|(\%list as lua expr\[\%index as lua expr\] ~= nil)
+..=: ".."|(\%list as lua\[\%index as lua\] ~= nil)
macro [length of %list, size of %list, number of %list, len %list] =:
- ".."|#(\%list as lua expr\)
+ ".."|#(\%list as lua\)
# Chained lookup
macro [%list ->* %indices] =:
- %ret =: %list as lua expr
- for %index in %indices:
- %ret join=: ".."|[\%index as lua expr\]
- %ret
+ assert ((%indices's "type") == "List") ".."
+ |Expected List for chained lookup, not \%indices's "type"\
+ %ret =: ".."|(\%list as lua\)
+ for %index in (%indices's "value"):
+ %ret join=: ".."|[\%index as lua\]
+ ".."|(\%ret\)
# Assignment
macro block [..]
@@ -79,12 +81,15 @@ macro block [..]
|Dict assignment operation has the wrong type for the right hand side.
|Expected Thunk, but got \%new_value's "type"\.
|Maybe you used "=" instead of "=:"?
- if ((size of (%new_value ->*["value","value"])) > 1):
- error ".."|Dict assignment operation has too many values on the right hand side.
- ".."|\%list as lua expr\[\%index as lua expr\] = \(%new_value ->*["value","value",1]) as lua expr\
+ assert ((size of (%new_value ->*["value","value"])) == 1) ".."
+ |Dict assignment operation has the wrong number of values on the right hand side.
+ |Expected 1 value, but got \repr %new_value\
+ %new_value =: %new_value ->*["value","value",1]
+ if ((%new_value's "type") == "Statement"): %new_value =: %new_value's "value"
+ ".."|\%list as lua\[\%index as lua\] = \%new_value as lua\
macro [append %item to %list, add %item to %list] =:
- ".."|table.insert(\%list as lua expr\, \%item as lua expr\)
+ ".."|table.insert(\%list as lua\, \%item as lua\)
rule [flatten %lists] =:
%flat =: []
@@ -96,8 +101,8 @@ rule [flatten %lists] =:
rule [dict %items] =:
%dict =: []
for %pair in %items:
- lua block "vars.dict[vars.pair[1]] = vars.pair[2]"
- return %dict
+ %dict -> (first in %pair) =: last in %pair
+ %dict
rule [entries in %dict] =:
lua block ".."
@@ -114,18 +119,18 @@ macro [%expression for %var in %iterable] =:
".."
|(function(game, vars)
| local comprehension = {}
- | for i,value in ipairs(\%iterable as lua expr\) do
- | \%var as lua expr\ = value
- | comprehension[i] = \%expression as lua expr\
+ | for i,value in ipairs(\%iterable as lua\) do
+ | \%var as lua\ = value
+ | comprehension[i] = \%expression as lua\
| end
| return comprehension
|end)(game, setmetatable({}, {__index=vars}))
macro [%expression for all %iterable] =:
".."|(function(game, vars)
| local comprehension = {}
- | for i,value in ipairs(\%iterable as lua expr\) do
+ | for i,value in ipairs(\%iterable as lua\) do
| vars.it = value
- | comprehension[i] = \%expression as lua expr\
+ | comprehension[i] = \%expression as lua\
| end
| return comprehension
|end)(game, setmetatable({}, {__index=vars}))
diff --git a/lib/control_flow.nom b/lib/control_flow.nom
index e2caa2d..84bdb5c 100644
--- a/lib/control_flow.nom
+++ b/lib/control_flow.nom
@@ -3,121 +3,112 @@ require "lib/operators.nom"
require "lib/utils.nom"
# Conditionals
-macro block [if %condition %if_body] =:
- ".."|if \%condition as lua expr\ then
- | \(lua expr "vars.if_body.value") as lua block\
+macro statement [if %condition %if_body] =:
+ ".."|if \%condition as lua\ then
+ | \(lua expr "vars.if_body.value") as lua\
|end
-macro block [if %condition %if_body else %else_body] =:
- ".."|if \%condition as lua expr\ then
- | \(lua expr "vars.if_body.value") as lua block\
+macro statement [if %condition %if_body else %else_body] =:
+ ".."|if \%condition as lua\ then
+ | \(lua expr "vars.if_body.value") as lua\
|else
- | \(lua expr "vars.else_body.value") as lua block\
+ | \(lua expr "vars.else_body.value") as lua\
|end
# Return
macro block [return] =: "return nil"
macro block [return %return-value] =: ".."
- |do return \%return-value as lua expr\ end
+ |return \%return-value as lua\
macro [do %action] =: ".."
- |(\%action as lua expr\)(compiler, setmetatable({}, {__index=vars}))
+ |(\%action as lua\)(compiler, setmetatable({}, {__index=vars}))
# GOTOs
-macro block [-> %label] =: ".."
+macro statement [-> %label] =: ".."
|::label_\compiler "var_to_lua_identifier" [%label]\::
-macro block [go to %label] =: ".."
+macro statement [go to %label] =: ".."
|goto label_\compiler "var_to_lua_identifier" [%label]\
# Loop control flow
-macro block [break] =: "break"
-macro block [break for] =: "goto break_for"
-macro block [break for-all] =: "goto break_for_all"
-macro block [break repeat] =: "goto break_repeat"
-macro block [break repeat-until] =: "goto break_repeat_until"
-macro block [break repeat-while] =: "goto break_repeat_while"
-macro block [break %var, stop getting %var, no more %var] =: ".."
+macro statement [break] =: "break"
+macro statement [break for] =: "goto break_for"
+macro statement [break for-all] =: "goto break_for_all"
+macro statement [break repeat] =: "goto break_repeat"
+macro statement [break repeat-until] =: "goto break_repeat_until"
+macro statement [break repeat-while] =: "goto break_repeat_while"
+macro statement [break %var, stop getting %var, no more %var] =: ".."
|goto break_\compiler "var_to_lua_identifier" [%var]\
-macro block [continue] =: "continue"
-macro block [continue for] =: "goto continue_for"
-macro block [continue for-all] =: "goto continue_for_all"
-macro block [continue repeat] =: "goto continue_repeat"
-macro block [continue repeat-until] =: "goto continue_repeat_until"
-macro block [continue repeat-while] =: "goto continue_repeat_while"
-macro block [continue %var, go to next %var, on to the next %var] =: ".."
+macro statement [continue] =: "continue"
+macro statement [continue for] =: "goto continue_for"
+macro statement [continue for-all] =: "goto continue_for_all"
+macro statement [continue repeat] =: "goto continue_repeat"
+macro statement [continue repeat-until] =: "goto continue_repeat_until"
+macro statement [continue repeat-while] =: "goto continue_repeat_while"
+macro statement [continue %var, go to next %var, on to the next %var] =: ".."
|goto continue_\compiler "var_to_lua_identifier" [%var]\
# TODO: add labeled break/continue?
# While loops
macro block [repeat %body] =:
- ".."|do
- | while true do
- | \(lua expr "vars.body.value") as lua block\
- | ::continue_repeat::
- | end
- | ::break_repeat::
+ ".."|while true do
+ | \(lua expr "vars.body.value") as lua\
+ | ::continue_repeat::
|end
+ |::break_repeat::
macro block [repeat while %condition %body] =:
- ".."|do
- | while \%condition as lua expr\ do
- | \(lua expr "vars.body.value") as lua block\
- | ::continue_repeat_while::
- | end
- | ::break_repeat_while::
+ ".."|while \%condition as lua\ do
+ | \(lua expr "vars.body.value") as lua\
+ | ::continue_repeat_while::
|end
+ |::break_repeat_while::
macro block [repeat until %condition %body] =:
- ".."|do
- | while not (\%condition as lua expr\) do
- | \(lua expr "vars.body.value") as lua block\
- | ::continue_repeat_until::
- | end
- | ::break_repeat_until::
+ ".."|while not (\%condition as lua\) do
+ | \(lua expr "vars.body.value") as lua\
+ | ::continue_repeat_until::
|end
+ |::break_repeat_until::
# For loops
macro block [for %var in %iterable %body] =:
%var-type =: lua expr "vars.var.type"
assert (%var-type == "Var") ".."
|For loop has the wrong type for the loop variable. Expected Var, but got: \%var-type\
+ # This trashes the loop variables, just like in Python.
".."
- |do
- | local vars = setmetatable({}, {__index=vars})
- | for i,value in ipairs(\%iterable as lua expr\) do
- | \%var as lua expr\ = value
- | \(lua expr "vars.body.value") as lua block\
- | ::continue_for::
- | ::continue_\compiler "var_to_lua_identifier" [%var]\::
- | end
- | ::break_for::
- | ::break_\compiler "var_to_lua_identifier" [%var]\::
+ |for i,value in ipairs(\%iterable as lua\) do
+ | \%var as lua\ = value
+ | \(lua expr "vars.body.value") as lua\
+ | ::continue_for::
+ | ::continue_\compiler "var_to_lua_identifier" [%var]\::
|end
+ |::break_for::
+ |::break_\compiler "var_to_lua_identifier" [%var]\::
macro block [for all %iterable %body] =:
- ".."|do
- | local vars = setmetatable({}, {__index=vars})
- | for i,value in ipairs(\%iterable as lua expr\) do
- | vars.it = value
- | \(lua expr "vars.body.value") as lua block\
- | ::continue_for_all::
- | end
- | ::break_for_all::
+ pass # TODO: fix compiler bug
+ # This trashes the loop variables, just like in Python.
+ ".."|for i,value in ipairs(\%iterable as lua\) do
+ | vars.it = value
+ | \(lua expr "vars.body.value") as lua\
+ | ::continue_for_all::
|end
+ |::break_for_all::
# Switch statement/multi-branch if
macro block [when %body] =:
%result =: ""
for %statement in (lua expr "vars.body.value.value"):
%func-call =: lua expr "vars.statement.value"
- assert ((lua expr "vars['func-call'].type") != "FunctionCall") ".."
+ assert ((lua expr "vars['func-call'].type") == "FunctionCall") ".."
|Invalid format for 'when' statement. Only '?' blocks are allowed.
%tokens =: lua expr "vars['func-call'].value"
%q =: lua expr "vars.tokens[1]"
- assert (((lua expr "vars.q.type") != "Word") or ((lua expr "vars.q.value") != "?")) ".."
+ assert (((lua expr "vars.q.type") == "Word") and ((lua expr "vars.q.value") == "?")) ".."
|Invalid format for 'when' statement. Lines must begin with '?'
%thunk =: lua expr "vars.tokens[#vars.tokens]"
- assert ((lua expr "vars.thunk.type") != "Thunk") ".."
+ assert ((lua expr "vars.thunk.type") == "Thunk") ".."
|Invalid format for 'when' statement. Lines must have a body.
%condition_bits =: []
for %i in (2 up to (lua expr "#vars.tokens")):
@@ -128,7 +119,7 @@ macro block [when %body] =:
|
|do
| local ret
- | \(lua expr "vars.thunk.value") as lua block\
+ | \(lua expr "vars.thunk.value") as lua\
| return ret
|end
..else:
@@ -141,9 +132,9 @@ macro block [when %body] =:
["value", %condition_bits]
%result join=: ".."
|
- |if \%condition as lua expr\ then
+ |if \%condition as lua\ then
| local ret
- | \(lua expr "vars.thunk.value") as lua block\
+ | \(lua expr "vars.thunk.value") as lua\
| return ret
|end
@@ -151,17 +142,17 @@ macro block [when %body] =:
# Switch statement
macro block [when %branch-value %body] =:
- %result =: ".."|local branch_value = \%branch-value as lua expr\
+ %result =: ".."|local branch_value = \%branch-value as lua\
for %statement in (lua expr "vars.body.value.value"):
%func-call =: lua expr "vars.statement.value"
- assert ((lua expr "vars['func-call'].type") != "FunctionCall") ".."
+ assert ((lua expr "vars['func-call'].type") == "FunctionCall") ".."
|Invalid format for 'when' statement. Only == blocks are allowed.
%tokens =: lua expr "vars['func-call'].value"
%eq =: lua expr "vars.tokens[1]"
- assert (((lua expr "vars.eq.type") != "Word") or ((lua expr "vars.eq.value") != "==")) ".."
+ assert (((lua expr "vars.eq.type") == "Word") and ((lua expr "vars.eq.value") == "==")) ".."
|Invalid format for 'when' statement. Lines must begin with '=='
%thunk =: lua expr "vars.tokens[#vars.tokens]"
- assert ((lua expr "vars.thunk.type") != "Thunk") ".."
+ assert ((lua expr "vars.thunk.type") == "Thunk") ".."
|Invalid format for 'when' statement. Lines must have a body.
%condition_bits =: []
for %i in (2 up to (lua expr "#vars.tokens")):
@@ -171,7 +162,7 @@ macro block [when %branch-value %body] =:
|
|do
| local ret
- | \(lua expr "vars.thunk.value") as lua block\
+ | \(lua expr "vars.thunk.value") as lua\
| return ret
|end
..else:
@@ -184,9 +175,9 @@ macro block [when %branch-value %body] =:
["value", %condition_bits]
%result join=: ".."
|
- |if compiler.utils.equivalent(branch_condition, \%condition as lua expr\) then
+ |if compiler.utils.equivalent(branch_condition, \%condition as lua\) then
| local ret
- | \(lua expr "vars.thunk.value") as lua block\
+ | \(lua expr "vars.thunk.value") as lua\
| return ret
|end
%result
diff --git a/lib/metaprogramming.nom b/lib/metaprogramming.nom
index d2f8fb6..3d29eb2 100644
--- a/lib/metaprogramming.nom
+++ b/lib/metaprogramming.nom
@@ -5,36 +5,42 @@
# Macros:
-# macro block [macro block %spec = %user_macro] =: ..
lua block ".."
- |compiler:defmacro("macro block %spec = %user_macro", (function(compiler, vars, kind)
+ |local function make_fn(wrap_in_block)
+ | return function(compiler, vars, kind)
# Do a minimal amount of pre-processing (get the spec and the source)
- | local spec = compiler:get_invocations_from_definition(vars.spec, vars)
- | spec = compiler.utils.repr(spec)
- | local src = compiler.utils.repr(vars.user_macro.src)
- | local user_macro = compiler:tree_to_lua(vars.user_macro)
+ | local spec = compiler:get_invocations_from_definition(vars.spec, vars)
+ | spec = compiler.utils.repr(spec)
+ | local src = compiler.utils.repr(vars.user_macro.src)
+ | local user_macro = compiler:tree_to_lua(vars.user_macro)
# Then produce a block of code that creates the macro at runtime
- | local lua = [[
- |compiler:defmacro(%s, (function(compiler, vars, kind)
- | if kind == "Expression" then
- | compiler:error("Macro "..%s.." was defined to be a block, but is being used as an expression")
+ | local lua = [[
+ | compiler:defmacro(%s, (function(compiler, vars, kind)
+ | if kind == "Expression" then
+ | compiler:error("Macro "..%s.." was defined to be a block, but is being used as an expression")
+ | end
+ | local user_macro = %s
+ | local lua = user_macro(compiler, vars)
+ | %s
+ | return lua, true
+ | end), %s)
+ | ]]
+ | lua = lua:format(spec, compiler.utils.repr(spec), user_macro,
+ | wrap_in_block and [[lua = "do\\n "..lua.."\\nend"]] or "", src)
+ | return lua, true
| end
- | local user_macro = %s
- | return ("do\\n"..user_macro(compiler, vars).."\\nend"), true
- |end), %s)
- |]]
- | lua = lua:format(spec, compiler.utils.repr(spec), user_macro, src)
- | return lua, true
- |end), "N/A")
+ |end
+ |compiler:defmacro("macro statement %spec = %user_macro", make_fn(false), "N/A")
+ |compiler:defmacro("macro block %spec = %user_macro", make_fn(true), "N/A")
macro block [macro %spec = %user_macro] =:
".."|compiler:defmacro(
| \lua expr "compiler:get_invocations_from_definition(vars.spec, vars)"\,
- | \lua expr "compiler:tree_to_lua(vars.user_macro, 'Expression')"\,
+ | \lua expr "compiler:tree_to_lua(vars.user_macro)"\,
| \lua expr "compiler.utils.repr(vars.user_macro.src)"\)
macro [compiler] =: "compiler"
-macro [compiler's %key] =: ".."|compiler[\%key as lua expr\]
+macro [compiler's %key] =: ".."|compiler[\%key as lua\]
macro [compiler %method %args] =:
lua block ".."
|local args = {}
@@ -59,7 +65,7 @@ macro [compiler utils %method %args] =:
macro block [rule %spec = %body] =: ".."
|compiler:def(
| \compiler utils "repr" [compiler "get_invocations_from_definition" [%spec, lua expr "vars"]]\,
- | \compiler "tree_to_lua" [%body, lua expr "vars"]\,
+ | \compiler "tree_to_lua" [%body]\,
| \compiler utils "repr" [lua expr "vars.body.src"]\)
# Get the source code for a function
@@ -77,11 +83,8 @@ rule [help %invocation] =:
rule [%tree as value] =:
lua expr "compiler:tree_to_value(vars.tree, vars)"
-rule [%tree as lua block] =:
- lua expr "compiler:tree_to_lua(vars.tree, 'Statement')"
-
-rule [%tree as lua expr] =:
- lua expr "compiler:tree_to_lua(vars.tree, 'Expression')"
+rule [%tree as lua] =:
+ lua expr "compiler:tree_to_lua(vars.tree)"
# Compiler tools
rule [eval %code, run %code] =: compiler "run" [%code]
diff --git a/lib/operators.nom b/lib/operators.nom
index f6fea36..01289ef 100644
--- a/lib/operators.nom
+++ b/lib/operators.nom
@@ -12,10 +12,10 @@ macro [%if_expr if %condition else %else_expr] =:
#.. Note: this uses a function instead of (condition and if_expr or else_expr)
because that breaks if %if_expr is falsey.
".."|(function(compiler, vars)
- | if \%condition as lua expr\ then
- | return \%if_expr as lua expr\
+ | if \%condition as lua\ then
+ | return \%if_expr as lua\
| else
- | return \%else_expr as lua expr\
+ | return \%else_expr as lua\
| end
|end)(compiler, vars)
@@ -37,8 +37,8 @@ lua block ".."
| if #vars.rhs.value.value > 1 then
| compiler:error("Assignment operation should not have more than one value on the right hand side.")
| end
- | return callback(compiler:tree_to_lua(vars.var, "Expression"),
- | compiler:tree_to_lua(vars.rhs.value.value[1].value, "Expression")), true
+ | return callback(compiler:tree_to_lua(vars.var),
+ | compiler:tree_to_lua(vars.rhs.value.value[1].value)), true
| end
|end
|compiler:defmacro("%var = %rhs", helper(function(var,result) return var.." = "..result end))
@@ -62,31 +62,31 @@ lua block ".."
| end
| compiler:defmacro("%a "..nomsu_alias.." %b", (function(compiler, vars, kind)
| return "("..compiler:tree_to_lua(vars.a).." "..op.." "..compiler:tree_to_lua(vars.b)..")"
- | end), [[".."|(\\%a as lua expr\\ ]]..op..[[ \\%b as lua expr\\)]])
+ | end), [[".."|(\\%a as lua\\ ]]..op..[[ \\%b as lua\\)]])
|end
# == and != do equivalence checking, rather than identity checking
-macro [%a == %b] =: ".."|compiler.utils.equivalent(\%a as lua expr\, \%b as lua expr\)
-macro [%a != %b] =: ".."|(not compiler.utils.equivalent(\%a as lua expr\, \%b as lua expr\))
+macro [%a == %b] =: ".."|compiler.utils.equivalent(\%a as lua\, \%b as lua\)
+macro [%a != %b] =: ".."|(not compiler.utils.equivalent(\%a as lua\, \%b as lua\))
-# Commutative Operators defined for up to 10 operands
+# Commutative Operators defined for up to 8 operands
lua block ".."
|local comops = {"+","*","and","or"}
|for _,_op in ipairs(comops) do
| local op = _op
| local spec = "%1 "..op.." %2"
- | for i=3,10 do
- | spec = spec .. " %"..tostring(i)
+ | for n=3,8 do
+ | spec = spec .." "..op.." %"..tostring(n)
| compiler:defmacro(spec, (function(compiler, vars, kind)
| local bits = {}
- | for _,v in ipairs(vars) do
- | table.insert(bits, compiler:tree_to_lua(v))
+ | for i=1,n do
+ | table.insert(bits, (compiler:tree_to_lua(vars[tostring(i)])))
| end
| return "("..table.concat(bits, " "..op.." ")..")"
| end))
| end
|end
-# Chained compairsions (e.g. x < y <= z < w) are defined up to 10 operands
+# Chained compairsions (e.g. x < y <= z < w) are defined up to 8 operands
lua block ".."
|for _,chainers in ipairs{{"<","<="},{">",">="}} do
| local function recurse(chain)
@@ -109,8 +109,8 @@ lua block ".."
| end
| end)
| end
- # 9 operators == 10 operands, so don't continue any further
- | if #chain >= 9 then return end
+ # 7 operators == 8 operands, so don't continue any further
+ | if #chain >= 7 then return end
| for _,c in ipairs(chainers) do
| table.insert(chain, c)
| recurse(chain)
@@ -121,5 +121,5 @@ lua block ".."
|end
# Unary operators
-macro [- %a] =: ".."|-(\%a as lua expr\)
-macro [not %a] =: ".."|not (\%a as lua expr\)
+macro [- %a] =: ".."|-(\%a as lua\)
+macro [not %a] =: ".."|not (\%a as lua\)
diff --git a/lib/permissions.nom b/lib/permissions.nom
index 4b6c428..fd55ec8 100644
--- a/lib/permissions.nom
+++ b/lib/permissions.nom
@@ -5,35 +5,40 @@ require "lib/collections.nom"
# Permission functions
rule [restrict %rules to within %elite-rules] =:
+ say ".."|Restricting \%rules\ to within \%elite-rules\
%rules =: compiler "get_invocations" [%rules]
%elite-rules =: compiler "get_invocations" [%elite-rules]
for all (flatten [%elite-rules, %rules]):
- assert ((compiler's "defs") has %it) ".."|Undefined function: \%it\
+ assert ((compiler's "defs") has key %it) ".."|Undefined function: \%it\
for all %rules:
- assert (not (compiler "check_permission" [%it])) ".."
+ assert (compiler "check_permission" [%it]) ".."
|You do not have permission to restrict permissions for function: \%it\
- ((compiler's "defs")'s %it)'s "whiteset" =: dict (..)
- [%it, (yes)] for %it in %elite-rules
+ %foo =: dict (..)
+ [%it, yes] for %it in %elite-rules
+ say ".."|FFS: \%foo\
+ ((compiler's "defs")'s %it)'s "whiteset" =: %foo
rule [allow %elite-rules to use %rules] =:
+ say ".."|Allowing \%elite-rules\ to use \%rules\
%rules =: compiler "get_invocations" [%rules]
%elite-rules =: compiler "get_invocations" [%elite-rules]
for all (flatten [%elite-rules, %rules]):
- assert ((compiler's "defs") has %it) ".."|Undefined function: \%it\
+ assert ((compiler's "defs") has key %it) ".."|Undefined function: \%it\
for %fn in %rules:
- assert (not (compiler "check_permission" [%fn])) ".."
+ assert (compiler "check_permission" [%fn]) ".."
|You do not have permission to grant permissions for function: \%fn\
%whiteset =: ((compiler's "defs")'s %fn)'s "whiteset"
if (not %whiteset): on to the next %fn
for all %elite-rules: %whiteset's %it =: yes
rule [forbid %pleb-rules to use %rules] =:
+ say ".."|Forbidding \%pleb-rules\ to use \%rules\
%rules =: compiler "get_invocations" [%rules]
%pleb-rules =: compiler "get_invocations" [%pleb-rules]
for all (flatten [%pleb-rules, %used]):
- assert ((compiler's "defs") has %it) ".."|Undefined function: \%it\
+ assert ((compiler's "defs") has key %it) ".."|Undefined function: \%it\
for all %rules:
- assert (not (compiler "check_permission" [%it])) ".."
+ assert (compiler "check_permission" [%it]) ".."
|You do not have permission to grant permissions for function: \%it\
%whiteset =: ((compiler's "defs")'s %it)'s "whiteset"
assert %whiteset ".."
diff --git a/lib/secrets.nom b/lib/secrets.nom
index 4dd5a7a..60f7748 100644
--- a/lib/secrets.nom
+++ b/lib/secrets.nom
@@ -2,11 +2,11 @@ require "lib/core.nom"
macro block [with secrets %block] =: ".."
|local secrets = {}
- |\(%block's "value") as lua block\
+ |\(%block's "value") as lua\
macro block [with secrets as %secret_name %block] =: ".."
|local \%secret_name as value\ = {}
- |\(%block's "value") as lua block\
+ |\(%block's "value") as lua\
# Access the lua variable that should be within scope
macro [secrets] =: "secrets"
@@ -29,6 +29,6 @@ macro block [secret %key = %new_value] =:
|end
".."|do
| local ret
- | \lua expr "compiler:tree_to_lua(vars.new_value.value, 'Statement')"\
+ | \lua expr "compiler:tree_to_lua(vars.new_value.value)"\
| secrets[\repr (%key's "value")\] = ret
|end
diff --git a/lib/testing.nom b/lib/testing.nom
index 48b311f..94d9e8e 100644
--- a/lib/testing.nom
+++ b/lib/testing.nom
@@ -3,7 +3,7 @@ require "lib/metaprogramming.nom"
# For unit testing
macro block [test %code yields %expected] =:
%generated =: lua expr "compiler.utils.repr(compiler:stringify_tree(vars.code.value))"
- %expected =: %expected as lua expr
+ %expected =: %expected as lua
if (%generated != %expected):
say "Test failed!"
say "Expected:"
diff --git a/lib/utils.nom b/lib/utils.nom
index 57b8dfc..ec35c15 100644
--- a/lib/utils.nom
+++ b/lib/utils.nom
@@ -6,16 +6,16 @@ rule [error!, panic!, fail!, abort!] =:
rule [error %msg] =:
compiler "error"[%msg]
macro block [assert %condition] =: ".."
- |if not (\%condition as lua expr\) then
+ |if not (\%condition as lua\) then
| compiler:error()
|end
macro block [assert %condition %msg] =: ".."
- |if not (\%condition as lua expr\) then
- | compiler:error(\%msg as lua expr\)
+ |if not (\%condition as lua\) then
+ | compiler:error(\%msg as lua\)
|end
macro block [show generated lua %block] =: ".."
- |compiler:writeln(\lua expr "compiler.utils.repr(compiler:tree_to_lua(vars.block.value, 'Statement'))"\)
+ |compiler:writeln(\lua expr "compiler.utils.repr(compiler:tree_to_lua(vars.block.value))"\)
# String functions
@@ -32,54 +32,54 @@ rule [join %strs with glue %glue] =:
|return table.concat(str_bits, vars.glue)
macro [capitalize %str, %str capitalized] =: ".."
- |(\%str as lua expr\):gsub("%l", string.upper, 1)
+ |(\%str as lua\):gsub("%l", string.upper, 1)
macro [repr %obj] =:
- ".."|compiler.utils.repr(\%obj as lua expr\)
+ ".."|compiler.utils.repr(\%obj as lua\)
macro [%obj as string] =:
- ".."|compiler.utils.repr_if_not_string(\%obj as lua expr\)
+ ".."|compiler.utils.repr_if_not_string(\%obj as lua\)
macro [say %str] =:
- ".."|compiler:writeln(compiler.utils.repr_if_not_string(\%str as lua expr\))
+ ".."|compiler:writeln(compiler.utils.repr_if_not_string(\%str as lua\))
# Number ranges
macro [%start up to %stop] =: ".."
- |compiler.utils.range(\%start as lua expr\, \%stop as lua expr\-1)
+ |compiler.utils.range(\%start as lua\, \%stop as lua\-1)
macro [%start thru %stop, %start through %stop] =: ".."
- |compiler.utils.range(\%start as lua expr\, \%stop as lua expr\)
+ |compiler.utils.range(\%start as lua\, \%stop as lua\)
macro [%start down to %stop] =: ".."
- |compiler.utils.range(\%start as lua expr\, \%stop as lua expr\+1,-1)
+ |compiler.utils.range(\%start as lua\, \%stop as lua\+1,-1)
macro [%start down thru %stop, %start down through %stop] =: ".."
- |compiler.utils.range(\%start as lua expr\, \%stop as lua expr\,-1)
+ |compiler.utils.range(\%start as lua\, \%stop as lua\,-1)
macro [%start up to %stop via %step] =: ".."
- |compiler.utils.range(\%start as lua expr\,\%stop as lua expr\-1,vars.step)
+ |compiler.utils.range(\%start as lua\,\%stop as lua\-1,vars.step)
macro [%start thru %stop via %step, %start through %stop via %step] =: ".."
- |compiler.utils.range(\%start as lua expr\,\%stop as lua expr\,vars.step)
+ |compiler.utils.range(\%start as lua\,\%stop as lua\,vars.step)
macro [%start down to %stop via %step] =: ".."
- |compiler.utils.range(\%start as lua expr\,\%stop as lua expr\+1,-vars.step)
+ |compiler.utils.range(\%start as lua\,\%stop as lua\+1,-vars.step)
macro [%start down thru %stop via %step, %start down through %stop via %step] =: ".."
- |compiler.utils.range(\%start as lua expr\,\%stop as lua expr\,-vars.step)
+ |compiler.utils.range(\%start as lua\,\%stop as lua\,-vars.step)
# Common utility functions
macro [random number, random, rand] =: "math.random()"
-macro [random int %n, random integer %n, randint %n] =: ".."|math.random(\%n as lua expr\)
+macro [random int %n, random integer %n, randint %n] =: ".."|math.random(\%n as lua\)
macro [random from %low to %high, random number from %low to %high, rand %low %high] =: ".."
- |math.random(\%low as lua expr\, \%high as lua expr\)
+ |math.random(\%low as lua\, \%high as lua\)
rule [random choice from %elements, random choice %elements, random %elements] =:
lua expr ".."|vars.elements[math.random(#vars.elements)]
-macro [sum of %items, sum %items] =: ".."|compiler.utils.sum(\%items as lua expr\)
-macro [product of %items, product %items] =: ".."|compiler.utils.product(\%items as lua expr\)
-macro [all of %items] =: ".."|compiler.utils.all(\%items as lua expr\)
-macro [any of %items] =: ".."|compiler.utils.any(\%items as lua expr\)
+macro [sum of %items, sum %items] =: ".."|compiler.utils.sum(\%items as lua\)
+macro [product of %items, product %items] =: ".."|compiler.utils.product(\%items as lua\)
+macro [all of %items] =: ".."|compiler.utils.all(\%items as lua\)
+macro [any of %items] =: ".."|compiler.utils.any(\%items as lua\)
# This is a rule, not a macro so we can use vars.items twice without running it twice.
rule [avg of %items, average of %items] =:
lua expr ".."|(compiler.utils.sum(vars.items)/#vars.items)
macro [min of %items, smallest of %items, lowest of %items] =:
- ".."|compiler.utils.min(\%items as lua expr\)
+ ".."|compiler.utils.min(\%items as lua\)
macro [max of %items, biggest of %items, largest of %items, highest of %items] =:
- ".."|compiler.utils.min(\%items as lua expr\)
+ ".."|compiler.utils.min(\%items as lua\)
macro [min of %items with respect to %keys] =:
- ".."|compiler.utils.min(\%items as lua expr\, \%keys as lua expr\)
+ ".."|compiler.utils.min(\%items as lua\, \%keys as lua\)
macro [max of %items with respect to %keys] =:
- ".."|compiler.utils.max(\%items as lua expr\, \%keys as lua expr\)
+ ".."|compiler.utils.max(\%items as lua\, \%keys as lua\)
diff --git a/nomsu.moon b/nomsu.moon
index 549684f..c36dbb6 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -311,7 +311,7 @@ class NomsuCompiler
error("Failed to compile generated code:\n#{code}\n\n#{err}")
return (lua_thunk!)(self, vars or {})
- tree_to_lua: (tree, kind="Expression")=>
+ tree_to_lua: (tree)=>
assert tree, "No tree provided."
if not tree.type
@error "Invalid tree: #{utils.repr(tree)}"
@@ -319,8 +319,8 @@ class NomsuCompiler
buffer = {}
return_value = nil
- to_lua = (t,kind)->
- ret = @tree_to_lua(t,kind)
+ to_lua = (t)->
+ ret = @tree_to_lua(t)
return ret
add = (code)-> table.insert(buffer, code)
@@ -462,10 +462,8 @@ class NomsuCompiler
var_to_lua_identifier: (var)=>
if var.type != "Var"
@error("Tried to convert something that wasn't a Var into a lua identifier: it was not a Var, it was: "..label.type)
- identifier = "var_"
- for i=1,#var.value
- identifier ..= ("%x")\format(string.byte(var.value, i))
- return identifier
+ "var"..(var.value\gsub "%W", (verboten)->
+ if verboten == "_" then "__" else ("_%x")\format(verboten\byte!))
run_macro: (tree, kind="Expression")=>
name = @fn_name_from_tree(tree)