aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcore.moon94
-rwxr-xr-xgame2.moon122
-rw-r--r--nomic.moon81
3 files changed, 151 insertions, 146 deletions
diff --git a/core.moon b/core.moon
index 8d76915..9328676 100755
--- a/core.moon
+++ b/core.moon
@@ -28,9 +28,13 @@ g\defmacro "let %varname = %value", (vars, helpers, ftype)=>
.lua "vars[#{.ded(.transform(vars.varname))} = #{.ded(.transform(vars.value))}"
return nil
-g\defmacro {"true", "yes"}, (vars,helpers,ftype)=> helpers.lua("true")
-g\defmacro {"false", "no"}, (vars,helpers,ftype)=> helpers.lua("false")
-g\defmacro "nil", (vars,helpers,ftype)=> helpers.lua("nil")
+singleton = (aliases, value)->
+ g\defmacro aliases, (vars,helpers,ftype)=>
+ if ftype == "Expression"
+ helpers.lua(value)
+ else
+ helpers.lua("ret = #{value}")
+
infix = (ops)->
for op in *ops
alias = op
@@ -50,6 +54,10 @@ unary = (ops)->
elseif ftype == "Expression"
helpers.lua("#{op}(#{helpers.var('x')})")
else error("Unknown: #{ftype}")
+
+singleton {"true","yes"}, "true"
+singleton {"false","no"}, "false"
+singleton {"nil","null"}, "nil"
infix{"+","-","*","/","==",{"!=","~="},"<","<=",">",">=","^","and","or"}
unary{"-","#","not"}
g\def [[%x == %y]], (args)=> utils.equivalent(args.x, args.y)
@@ -108,5 +116,83 @@ g\def {[[# %list]], [[length of %list]], [[size of %list]]}, (args)=>
return
return #(.list)
+g\defmacro "if %condition %if_body else %else_body", (vars,helpers,ftype)=>
+ with helpers
+ switch ftype
+ when "Expression"
+ .lua "((#{.ded(.transform(vars.condition))}) and"
+ .indented ->
+ .lua "("..(.ded(.transform(vars.if_body)))..")"
+ .lua "or ("..(.ded(.transform(vars.if_body))).."))(game, vars)"
+ when "Statement"
+ .lua("if (#{.ded(.transform(vars.condition))}) then")
+ .indented ->
+ if_body = vars.if_body
+ while if_body.type != "Block"
+ if_body = if_body.value
+ if if_body == nil then error("Failed to find body.")
+ for statement in *if_body.value
+ .lua(.ded(.transform(statement)))
+ .lua("else")
+ .indented ->
+ else_body = vars.else_body
+ while else_body.type != "Block"
+ else_body = else_body.value
+ if else_body == nil then error("Failed to find body.")
+ for statement in *else_body.value
+ .lua(.ded(.transform(statement)))
+ .lua("end")
+ return nil
+
+g\defmacro "for %varname in %iterable %body", (vars,helpers,ftype)=>
+ with helpers
+ switch ftype
+ when "Expression"
+ .lua "(function(game, vars)"
+ .indented ->
+ .lua "local comprehension, vars = {}, setmetatable({}, {__index=vars})"
+ .lua "for i, value in ipairs(#{.ded(.transform(vars.iterable))}) do"
+ .indented ->
+ .lua "local comp_value"
+ .lua "vars[#{.ded(.transform(vars.varname))}] = value"
+ body = vars.body
+ while body.type != "Block"
+ body = body.value
+ if body == nil then error("Failed to find body.")
+ for statement in *body.value
+ -- TODO: Clean up this ugly bit
+ .lua("comp_value = "..(.ded(.transform(statement.value, {type:"Expression"}))))
+ .lua "table.insert(comprehension, comp_value)"
+ .lua "end"
+ .lua "return comprehension"
+ .lua "end)(game,vars)"
+ when "Statement"
+ .lua "do"
+ .indented ->
+ .lua "local vars = setmetatable({}, {__index=vars})"
+ .lua "for i, value in ipairs(#{.ded(.transform(vars.iterable))}) do"
+ .indented ->
+ .lua "vars[#{.ded(.transform(vars.varname))}] = value"
+ body = vars.body
+ while body.type != "Block"
+ body = body.value
+ if body == nil then error("Failed to find body.")
+ for statement in *body.value
+ .lua(.ded(.transform(statement)))
+ .lua "end"
+ .lua "end"
+ return nil
+
+g\simplemacro "if %condition %body", [[
+if %condition %body
+..else: nil
+]]
+
+g\simplemacro "unless %condition %body", [[
+if (not %condition) %body
+..else: nil]]
+
+g\def [[do %action]], (vars)=> return vars.action(self,vars)
+
-return game
+return g
diff --git a/game2.moon b/game2.moon
index e487991..eb1d4c5 100755
--- a/game2.moon
+++ b/game2.moon
@@ -1,49 +1,10 @@
#!/usr/bin/env moon
utils = require 'utils'
Game = require 'nomic'
-g = Game()
+g = Game(require'core')
print("===========================================================================================")
-g\def "rule %spec %body", (vars)=>
- self\def vars.spec, vars.body
- print "Defined rule: #{vars.spec}"
-
-g\def "say %x", (vars)=>
- print(utils.repr(vars.x))
-
-g\defmacro "return %retval", (vars,helpers,ftype)=>
- with helpers
- switch ftype
- when "Expression"
- error("Cannot use a return statement as an expression")
- when "Statement"
- .lua "do return "..(.ded(.transform(vars.retval))).." end"
- else
- error"Unknown: #{ftype}"
- return nil
-
-g\defmacro "true", (vars,helpers,ftype)=> helpers.lua("true")
-g\defmacro "false", (vars,helpers,ftype)=> helpers.lua("false")
-g\defmacro "nil", (vars,helpers,ftype)=> helpers.lua("nil")
-infix = (ops)->
- for op in *ops
- g\defmacro "%x #{op} %y", (vars,helpers,ftype)=>
- if ftype == "Statement"
- helpers.lua("ret = (#{helpers.var('x')} #{op} #{helpers.var('y')})")
- elseif ftype == "Expression"
- helpers.lua("(#{helpers.var('x')} #{op} #{helpers.var('y')})")
- else error("Unknown: #{ftype}")
-unary = (ops)->
- for op in *ops
- g\defmacro "#{op} %x", (vars,helpers,ftype)=>
- if ftype == "Statement"
- helpers.lua("ret = #{op}(#{helpers.var('x')})")
- elseif ftype == "Expression"
- helpers.lua("#{op}(#{helpers.var('x')})")
- else error("Unknown: #{ftype}")
-infix{"+","-","*","/","==","!=","<","<=",">",">=","^"}
-unary{"-","#","not"}
g\test[[
say "foo"
@@ -224,76 +185,6 @@ say both ..
say "done"
]]
-g\defmacro "if %condition %if_body else %else_body", (vars,helpers,ftype)=>
- with helpers
- switch ftype
- when "Expression"
- .lua "((#{.ded(.transform(vars.condition))}) and"
- .indented ->
- .lua "("..(.ded(.transform(vars.if_body)))..")"
- .lua "or ("..(.ded(.transform(vars.if_body))).."))(game, vars)"
- when "Statement"
- .lua("if (#{.ded(.transform(vars.condition))}) then")
- .indented ->
- if_body = vars.if_body
- while if_body.type != "Block"
- if_body = if_body.value
- if if_body == nil then error("Failed to find body.")
- for statement in *if_body.value
- .lua(.ded(.transform(statement)))
- .lua("else")
- .indented ->
- else_body = vars.else_body
- while else_body.type != "Block"
- else_body = else_body.value
- if else_body == nil then error("Failed to find body.")
- for statement in *else_body.value
- .lua(.ded(.transform(statement)))
- .lua("end")
- return nil
-
-g\defmacro "for %varname in %iterable %body", (vars,helpers,ftype)=>
- with helpers
- switch ftype
- when "Expression"
- .lua "(function(game, vars)"
- .indented ->
- .lua "local comprehension, vars = {}, setmetatable({}, {__index=vars})"
- .lua "for i, value in ipairs(#{.ded(.transform(vars.iterable))}) do"
- .indented ->
- .lua "local comp_value"
- .lua "vars[#{.ded(.transform(vars.varname))}] = value"
- body = vars.body
- while body.type != "Block"
- body = body.value
- if body == nil then error("Failed to find body.")
- for statement in *body.value
- -- TODO: Clean up this ugly bit
- .lua("comp_value = "..(.ded(.transform(statement.value, {type:"Expression"}))))
- .lua "table.insert(comprehension, comp_value)"
- .lua "end"
- .lua "return comprehension"
- .lua "end)(game,vars)"
- when "Statement"
- .lua "do"
- .indented ->
- .lua "local vars = setmetatable({}, {__index=vars})"
- .lua "for i, value in ipairs(#{.ded(.transform(vars.iterable))}) do"
- .indented ->
- .lua "vars[#{.ded(.transform(vars.varname))}] = value"
- body = vars.body
- while body.type != "Block"
- body = body.value
- if body == nil then error("Failed to find body.")
- for statement in *body.value
- .lua(.ded(.transform(statement)))
- .lua "end"
- .lua "end"
- return nil
-
---g\defmacro "if %condition %if_body", "if %condition %if_body else: return nil"
-
-g\def [[do %action]], (vars)=> return vars.action(self,vars)
g\run[[
rule "do %thing also %also-thing":
do %thing
@@ -334,13 +225,20 @@ g\run[[
say (1 + (-(2 * 3)))
]]
-g\run_debug[[
+g\run[[
for "x" in ["A","B","C"]:
say %x
]]
-g\run_debug[[
+g\run[[
say (for "x" in [1,2,3]:%x + 100)
say (..)
for "x" in [1,2,3]:
%x + 200
]]
+
+g\run[[
+if (1 == 1):
+ say "Simple macros work!"
+unless (1 > 2):
+ say "This one too!"
+]]
diff --git a/nomic.moon b/nomic.moon
index a8eb4d5..a2a35a6 100644
--- a/nomic.moon
+++ b/nomic.moon
@@ -63,26 +63,26 @@ add_indent_tokens = (str)->
string <- '"' (("\\" .) / [^"])* '"'
]=]
indentflagger = re.compile indentflagger, defs
- indentflagger\match(str)
+ indentflagger\match(str.."\n")
while #indent_stack > 1
table.remove indent_stack
table.insert result, "}\n"
return (table.concat result)\sub(1,-2)
lingo = [=[
- file <- ({} {| {:body: (" " block) :} ({:errors: errors :})? |} {}) -> File
- errors <- ({} {.+} {}) -> Errors
- block <- ({} {| statement (%nodent statement)* |} {}) -> Block
- statement <- ({} (functioncall / expression) {}) -> Statement
- one_liner <- ({} {|
- (({}
- (({} {|
+ file <- ({ {| {:body: (" " block) :} ({:errors: errors :})? |} }) -> File
+ errors <- ({ {.+} }) -> Errors
+ block <- ({ {| statement (%nodent statement)* |} }) -> Block
+ statement <- ({ (functioncall / expression) }) -> Statement
+ one_liner <- ({ {|
+ (({
+ (({ {|
(expression (%word_boundary fn_bit)+) / (word (%word_boundary fn_bit)*)
- |} {}) -> FunctionCall)
- {}) -> Statement)
- |} {}) -> Block
+ |} }) -> FunctionCall)
+ }) -> Statement)
+ |} }) -> Block
- functioncall <- ({} {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} {}) -> FunctionCall
+ functioncall <- ({ {| (expression %word_boundary fn_bits) / (word (%word_boundary fn_bits)?) |} }) -> FunctionCall
fn_bit <- (expression / word)
fn_bits <-
((".." %ws? (%indent %nodent indented_fn_bits %dedent) (%nodent ".." %ws? fn_bits)?)
@@ -92,35 +92,36 @@ lingo = [=[
fn_bit ((%nodent / %word_boundary) indented_fn_bits)?
thunk <-
- ({} ":" %ws?
+ ({ ":" %ws?
((%indent %nodent block %dedent (%nodent "..")?)
- / (one_liner (%ws? ((%nodent? "..")))?)) {}) -> Thunk
+ / (one_liner (%ws? ((%nodent? "..")))?)) }) -> Thunk
- word <- ({} !number {%wordchar+} {}) -> Word
- expression <- ({} (string / number / variable / list / thunk / subexpression) {}) -> Expression
+ word <- ({ !number {%wordchar+} }) -> Word
+ expression <- ({ (string / number / variable / list / thunk / subexpression) }) -> Expression
- string <- ({} '"' {(("\\" .) / [^"])*} '"' {}) -> String
- number <- ({} {'-'? [0-9]+ ("." [0-9]+)?} {}) -> Number
- variable <- ({} ("%" {%wordchar+}) {}) -> Var
+ string <- ({ '"' {(("\\" .) / [^"])*} '"' }) -> String
+ number <- ({ {'-'? [0-9]+ ("." [0-9]+)?} }) -> Number
+ variable <- ({ ("%" {%wordchar+}) }) -> Var
subexpression <-
("(" %ws? (functioncall / expression) %ws? ")")
- / ("(..)" %ws? %indent %nodent (expression / (({} {| indented_fn_bits |} {}) -> FunctionCall)) %dedent (%nodent "..")?)
+ / ("(..)" %ws? %indent %nodent (expression / (({ {| indented_fn_bits |} }) -> FunctionCall)) %dedent (%nodent "..")?)
- list <- ({} {|
+ list <- ({ {|
("[..]" %ws? %indent %nodent indented_list ","? %dedent (%nodent "..")?)
/ ("[" %ws? (list_items ","?)? %ws?"]")
- |} {}) -> List
+ |} }) -> List
list_items <- (expression (list_sep list_items)?)
list_sep <- %ws? "," %ws?
indented_list <-
expression (((list_sep %nodent?) / %nodent) indented_list)?
]=]
+wordchar = lpeg.P(1)-lpeg.S(' \t\n\r%:;,.{}[]()"')
defs =
eol: #(linebreak) + (lpeg.P("")-lpeg.P(1))
ws: lpeg.S(" \t")^1
- wordchar: lpeg.P(1)-lpeg.S(' \t\n\r%:;,.{}[]()"')
+ wordchar: wordchar
indent: linebreak * lpeg.P("{") * lpeg.S(" \t")^0
nodent: linebreak * lpeg.P(" ") * lpeg.S(" \t")^0
dedent: linebreak * lpeg.P("}") * lpeg.S(" \t")^0
@@ -129,8 +130,8 @@ defs =
setmetatable(defs, {
__index: (t,key)->
--print("WORKING for #{key}")
- fn = (start, value, stop, ...)->
- token = {type: key, range:{start,stop}, value: value}
+ fn = (src, value, ...)->
+ token = {type: key, src:src, value: value}
return token
t[key] = fn
return fn
@@ -139,9 +140,9 @@ lingo = re.compile lingo, defs
class Game
- new:=>
- @defs = {}
- @macros = {}
+ new:(parent)=>
+ @defs = setmetatable({}, {__index:parent and parent.defs})
+ @macros = setmetatable({}, {__index: parent and parent.macros})
@debug = false
call: (fn_name,...)=>
@@ -154,7 +155,7 @@ class Game
for i,name in ipairs(arg_names)
args[name] = select(i,...)
if @debug
- print("arg #{utils.repr(name,true)} = #{select(i,...)}")
+ print("arg #{utils.repr(name,true)} = #{utils.repr(select(i,...), true)}")
ret = fn(self, args)
if @debug
print "returned #{utils.repr(ret,true)}"
@@ -189,6 +190,26 @@ class Game
invocations,arg_names = self\get_invocations spec
for invocation in *invocations
@macros[invocation] = {fn, arg_names}
+
+ simplemacro: (spec, replacement)=>
+ replace_grammar = [[
+ stuff <- {~ (var / string / .)+ ~}
+ var <- ("%" {%wordchar+}) -> replacer
+ string <- '"' (("\\" .) / [^"])* '"'
+ ]]
+ replacement = add_indent_tokens replacement
+ fn = (vars, helpers, ftype)=>
+ replacer = (varname)->
+ ret = vars[varname].src
+ return ret
+ replacement_grammar = re.compile(replace_grammar, {:wordchar, :replacer})
+ replaced = replacement_grammar\match(replacement)
+ tree = lingo\match (replaced)
+ if not tree
+ error "Couldn't match:\n#{replaced}"
+ helpers.lua(helpers.transform(tree.value.body))
+ return code
+ self\defmacro spec, fn
run: (text)=>
if @debug
@@ -276,7 +297,7 @@ class Game
lua "end)"
when "Errors"
- -- TODO: Better error reporting via tree.range[1]
+ -- TODO: Better error reporting via tree.src
error("\nParse error on: #{tree.value}")
when "Block"