aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2017-08-16 18:07:00 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2017-08-16 18:07:00 -0700
commit5fb8fabaf735f9a2ee97f7d07b85293ff8e9c987 (patch)
treeff766b3beebd251fb4662ebe52c4c69ed2056205
parentf6ab7587e1d036aa0a0c97ec0f82f66220ed3bdd (diff)
Lots of fixes and cleanup.
-rw-r--r--core.moon38
-rwxr-xr-xgame1.moon45
-rw-r--r--nomic.moon85
3 files changed, 122 insertions, 46 deletions
diff --git a/core.moon b/core.moon
index 0523996..66649f5 100644
--- a/core.moon
+++ b/core.moon
@@ -2,11 +2,38 @@
nomic = require 'nomic'
game = nomic()
+is_list = (t)->
+ i = 0
+ for _ in pairs(t)
+ i += 1
+ if t[i] == nil then return false
+ return true
+
+repr = (x)->
+ if type(x) == 'table'
+ if is_list x
+ "[#{table.concat([repr(i) for i in *x], ", ")}]"
+ else
+ "{#{table.concat(["#{k}: #{v}" for k,v in pairs x], ", ")}}"
+ else
+ tostring(x)
+
game\def {[[print $str]], [[say $str]]}, (locals)=>
with locals
- print(.str)
+ print(repr(.str))
+ return nil
+
+game\def [[help $invocation]], (locals)=>
+ with locals
+ if @rules[.invocation]
+ print(@rules[.invocation])
+ return nil
+ for i,r in pairs(@rules)
+ if i\match .invocation
+ print("Rule: #{@rules[.invocation]}")
return nil
+
game\def [[return $retval]], (locals)=> locals.retval
game\def [[do $thunk]], (locals)=>
@@ -16,9 +43,8 @@ game\def {[[true]], [[yes]]}, (locals)=> true
game\def {[[false]], [[no]]}, (locals)=> false
game\def {[[nil]], [[None]], [[nop]], [[done]]}, (locals)=> nil
-game\def [[$x == $y]], (locals)=>
+game\def {[[$x == $y]], [[equal $x $y]]}, (locals)=>
with locals
- print("testing equality of #{.x} and #{.y}")
if type(.x) != type(.y)
return false
if type(.x) == 'table'
@@ -39,6 +65,12 @@ game\def [[$x <= $y]], (locals)=> locals.x <= locals.y
game\def [[$x > $y]], (locals)=> locals.x > locals.y
game\def [[$x >= $y]], (locals)=> locals.x >= locals.y
+game\def {[[$x + $y]], [[$x plus $y]]}, (locals)=> locals.x + locals.y
+game\def {[[$x - $y]], [[$x minus $y]]}, (locals)=> locals.x - locals.y
+game\def {[[$x * $y]], [[$x times $y]]}, (locals)=> locals.x * locals.y
+game\def {[[$x / $y]], [[$x divided by $y]]}, (locals)=> locals.x / locals.y
+game\def {[[$x ^ $y]], [[$x to the power of $y]]}, (locals)=> locals.x ^ locals.y
+
game\def [[if $condition then $body else $else_body]], (locals)=>
with locals
diff --git a/game1.moon b/game1.moon
index ace0f00..f60917d 100755
--- a/game1.moon
+++ b/game1.moon
@@ -1,10 +1,8 @@
#!/usr/bin/env moon
game = require 'core'
-export __DEBUG__
-__DEBUG__ = true
------------------ BASIC TESTS ---------------------
-game\run [[
+game\run [=[
say "=========== INITIALIZING GAME ============"
@@ -27,15 +25,28 @@ say (return "returned value")
do {say "did"}
say 6
say -6
-say [1,2,3]
-
-]]
-error("done")
-
-game\run "say [1,2,3]"
-game\run "sum [1,2,3]"
-game\run "say (sum [1,2,3])"
-
+say []
+say [1,2,3,4]
+say [[1,2],[3,[4,5]]]
+say (sum [1,2,3,4])
+help "fart"
+help "fart;twice"
+
+"five" := {return 5}
+say (6 times 6)
+"fitz" := {say (return 99)}
+fitz
+"bazwiz $x" := {say (sum $x)}
+bazwiz [10,20,30]
+"foobar $x" := {say (return $x)}
+foobar 55
+
+"$x squared" := {$x times $x}
+"$x plus one" := {$x + 1}
+"$x foo" := {($x * $x) + 1}
+say (5 foo)
+
+]=]
game\def [[you]], (_)=> @you
game\run [[you]]
@@ -66,9 +77,14 @@ game\def [[the value of $key $relation]], (locals)=>
with locals
return (@relations[.relation] or {})[.key]
-game\def [[it is true that $key $relation $value]], [[return ((the value of $key $relation) == $value)]]
+game\def [[it is true that $key $relation $value]], [[(the value of $key $relation) == $value]]
+
+game\def [[it is true that $key $relation]], [[(the value of $key $relation) == (true)]]
-game\def [[it is true that $key $relation]], [[return ((the value of $key $relation) == (true))]]
+game\run[[
+ remember that "socrates" "is mortal"
+ say (it is true that "socrates" "is mortal"))
+]]
game\run [[remember that "socrates" "is mortal"]]
@@ -92,7 +108,6 @@ game\run [[say (if (1 == 1) then {return "Ternary yes"} else {return "Ternary no
game\def [[$who is a member]], [[return (it is true that $who "is a member")]]
game\def [[you are a member]], [[return ((you) is a member)]]
game\run [[say (you are a member)]]
-error("done")
game\run [[
if (you are a member) then {say "youre a member!"} else {say "youre not a member"}
diff --git a/nomic.moon b/nomic.moon
index 21389a7..62b54c0 100644
--- a/nomic.moon
+++ b/nomic.moon
@@ -5,25 +5,27 @@ type = moon.type
export __DEBUG__
+currently_parsing = nil
-as_value = (x, globals, locals)->
- assert (globals and locals), "Shit's fucked"
+
+as_value = (x, game, locals)->
+ assert (game and locals), "Shit's fucked"
if type(x) == 'number' or type(x) == 'string' or type(x) == 'table'
return x
- ret = x\as_value globals, locals
+ ret = x\as_value game, locals
return ret
class Var
new:(@name)=>
- as_value:(globals, locals)=>
+ as_value:(game, locals)=>
if __DEBUG__
print("Looking up variable #{@name} = #{locals[@name]}")
if locals[@name] == nil
print("LOCALS:")
for k,v in pairs locals
print(" #{k} = #{v}")
- print("GLOBALS:")
- for k,v in pairs globals
+ print("game:")
+ for k,v in pairs game
print(" #{k} = #{v}")
error("Could not find #{@name}")
locals[@name]
@@ -45,51 +47,55 @@ class Action
__tostring:=> "Action(#{@name})"
- as_value:(globals, locals)=>
- assert((globals and locals), "f'd up")
- ret = @\run globals, locals
+ as_value:(game, locals)=>
+ assert((game and locals), "f'd up")
+ ret = @\run game, locals
return ret
- run:(globals, locals)=>
- assert((globals and locals), "f'd up")
- rule = globals.rules[@name]
+ run:(game, locals)=>
+ assert((game and locals), "f'd up")
+ rule = game.rules[@name]
unless rule
error("Tried to run rule, but couldn't find: #{@name}")
arg_names = rule.arg_names
new_locals = {}
for i, arg in ipairs(@args)
- new_locals[arg_names[i]] = as_value(arg, globals, locals)
+ new_locals[arg_names[i]] = as_value(arg, game, locals)
- ret = rule.fn(globals, new_locals)
+ ret = rule.fn(game, new_locals)
return ret
class Thunk
new:(@actions)=>
+ if @actions.startPos
+ assert currently_parsing, "Not currently parsing!"
+ @body_str = currently_parsing\sub(@actions.startPos, @actions.endPos-1)
if __DEBUG__
print("CONSTRUCTING THUNK WITH ACTIONS:")
for k,v in pairs @actions
print(" #{k} = #{v}")
as_value:=>@
- run:(globals, locals)=>
- assert((globals and locals), "f'd up")
+ run:(game, locals)=>
+ assert((game and locals), "f'd up")
ret = nil
for a in *@actions
- ret = a\run globals,locals
+ ret = a\run game,locals
return ret
__tostring:=>
- "Thunk(#{table.concat([tostring(a) for a in *@actions], ", ") .. tostring(@actions.returnValue or "") })"
+ --"Thunk(#{table.concat([tostring(a) for a in *@actions], ", ") .. tostring(@actions.returnValue or "") })"
+ "{#{@body_str}}"
lingo = [[
- actions <- {| (%nl " "*)* ((" "*) action ((%nl " "*)+ action)*)? (%nl " "*)* |} -> Thunk
- action <- {| token (" "+ token)* " "* |} -> Action
- token <- expression / ({(!"[" !%nl [^ {}()$])+} -> Word)
+ actions <- {| {:startPos: {}:} (%ws*) (%nl %ws*)* (action ((%nl %ws*)+ action)*)? (%nl %ws*)* {:endPos: {}:} |} -> Thunk
+ action <- {| token (%ws+ token)* %ws* |} -> Action
+ token <- expression / (!"$" {%wordchars+} -> Word)
expression <- number / string / list / variable / thunk / subexpression
number <- ('-'? [0-9]+ ("." [0-9]+)?) -> tonumber
string <- ('"' {(("\\" .) / [^"])*} '"') -> tostring
- list <- {| '[' (expression (',' (' '*) expression)*)? ']' |}
- variable <- ("$" {%S+}) -> Var
- subexpression <- "(" action ")"
- thunk <- ("{" {| actions |} "}") -> Thunk
+ list <- {| '[' (expression (',' (%ws*) expression)*)? ']' |}
+ variable <- ("$" {%wordchars+}) -> Var
+ subexpression <- ("(" %ws* action ")")
+ thunk <- ("{" actions "}")
]]
defs = {
Var: (...)->Var(...)
@@ -98,6 +104,8 @@ defs = {
Thunk: (...)->Thunk(...)
tostring: tostring
tonumber: tonumber
+ ws: lpeg.S(" \t")
+ wordchars: lpeg.P(1)-lpeg.S(' \t\n{}[]()"')
}
lingo = re.compile lingo, defs
@@ -105,13 +113,17 @@ class Rule
new:(invocations, action)=>
if type(action) == 'string'
@body_str = action
+ export currently_parsing
+ old_parsing = currently_parsing
+ currently_parsing = action
thunk = lingo\match action
+ currently_parsing = old_parsing
unless thunk
error("failed to parse!")
- @fn = (globals,locals)-> thunk\run(globals, locals)
+ @fn = (game,locals)-> thunk\run(game, locals)
elseif type(action) == Thunk
@body_str = tostring(action)
- @fn = (globals,locals)-> action\run(globals, locals)
+ @fn = (game,locals)-> action\run(game, locals)
elseif type(action) == 'function'
@body_str = "<lua function>"
@fn = action
@@ -149,6 +161,8 @@ class Rule
def = (game, invocation, action)->
invocations = if type(invocation) == 'table' then invocation else {invocation}
rule = Rule(invocations, action)
+ if game.src
+ rule.body_str = game.src
for invocation in *rule.invocations
game.rules[invocation] = rule
if __DEBUG__
@@ -157,17 +171,32 @@ def = (game, invocation, action)->
run = (game, str)->
if __DEBUG__
print(">> #{str\gsub("\n", "\n.. ")}")
+ export currently_parsing
+ old_parsing = currently_parsing
+ currently_parsing = str
thunk = lingo\match str
+ currently_parsing = old_parsing
unless thunk
error("failed to parse nomic:\n#{str}")
+ -- TODO: remove
game.you = "@spill"
ret = thunk\run game, {}
if ret != nil
print("= #{ret}")
return ret
+repl = (game)->
+ while true
+ io.write(">> ")
+ buf = ""
+ while buf\sub(-2,-1) != "\n\n"
+ buf ..= io.read("*line").."\n"
+ if buf == "exit\n\n" or buf == "quit\n\n"
+ break
+ game\run buf
+
return ()->
- game = {rules:{}, relations:{}, :run, :def}
+ game = {rules:{}, relations:{}, :run, :def, :repl}
game\def [[$invocations := $body]], (locals)=>
game\def locals.invocations, locals.body
return nil