aboutsummaryrefslogtreecommitdiff
path: root/nomic.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2017-08-18 17:06:47 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2017-08-18 17:06:47 -0700
commit73051b34d9ea46710d1e36be4b867a50ccc01eac (patch)
tree6b1859914a9d9782cf1c6d235cca3722ee3b99f2 /nomic.moon
parent5fb8fabaf735f9a2ee97f7d07b85293ff8e9c987 (diff)
Reworked to use lua codegen.
Diffstat (limited to 'nomic.moon')
-rw-r--r--nomic.moon136
1 files changed, 58 insertions, 78 deletions
diff --git a/nomic.moon b/nomic.moon
index 62b54c0..cca67e0 100644
--- a/nomic.moon
+++ b/nomic.moon
@@ -3,11 +3,8 @@ lpeg = require 'lpeg'
moon = require 'moon'
type = moon.type
-export __DEBUG__
-
currently_parsing = nil
-
as_value = (x, game, locals)->
assert (game and locals), "Shit's fucked"
if type(x) == 'number' or type(x) == 'string' or type(x) == 'table'
@@ -18,16 +15,8 @@ as_value = (x, game, locals)->
class Var
new:(@name)=>
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("game:")
- for k,v in pairs game
- print(" #{k} = #{v}")
- error("Could not find #{@name}")
+ error("Attempt to access undefined variable: #{@name}")
locals[@name]
__tostring:=> "Var(#{@text})"
@@ -39,10 +28,6 @@ class Action
new:(tokens)=>
words = [(if type(t) == Word then t.text else "$") for t in *tokens]
@name = table.concat(words, ";")
- if __DEBUG__
- print("ACTION: #{@name}")
- for t in *tokens
- print(" TOKEN: #{t}")
@args = [t for t in *tokens when type(t) != Word]
__tostring:=> "Action(#{@name})"
@@ -66,21 +51,21 @@ class Action
return ret
class Thunk
- new:(@actions)=>
+ new:(@actions, @body_str)=>
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}")
+ unless @body_str
+ @body_str = currently_parsing\sub(@actions.startPos, @actions.endPos-1)
+
as_value:=>@
+
run:(game, locals)=>
assert((game and locals), "f'd up")
ret = nil
for a in *@actions
ret = a\run game,locals
return ret
+
__tostring:=>
--"Thunk(#{table.concat([tostring(a) for a in *@actions], ", ") .. tostring(@actions.returnValue or "") })"
"{#{@body_str}}"
@@ -110,22 +95,12 @@ defs = {
lingo = re.compile lingo, defs
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 = (game,locals)-> thunk\run(game, locals)
- elseif type(action) == Thunk
- @body_str = tostring(action)
+ new:(invocations, action, docstring)=>
+ if type(action) == Thunk
+ @body_str = docstring or tostring(action)
@fn = (game,locals)-> action\run(game, locals)
elseif type(action) == 'function'
- @body_str = "<lua function>"
+ @body_str = docstring or "<lua function>"
@fn = action
else
error("Invalid action type: #{type(action)}")
@@ -158,46 +133,51 @@ class Rule
"Rule: #{table.concat(@raw_invocations, " | ")} :=\n #{@body_str\gsub("\n","\n ")}"
-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__
- print rule
-
-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
+class Game
+ new:(parent)=>
+ @rules = setmetatable({}, {__index:parent and parent.rules or nil})
+ @relations = setmetatable({}, {__index:parent and parent.relations or nil})
+
+ def: (invocation, action, docstring)=>
+ invocations = if type(invocation) == 'table' then invocation else {invocation}
+ rule = Rule(invocations, action, docstring)
+ for invocation in *rule.invocations
+ @rules[invocation] = rule
+
+ proxy: (rule)=>
+ for i in *rule.invocations
+ @rules[i] = rule
+
+ run: (str, user)=>
+ export currently_parsing
+ old_parsing = currently_parsing
+ currently_parsing = str
+ ok,thunk = pcall lingo.match, lingo, str
+ currently_parsing = old_parsing
+ if not ok
+ error(thunk)
+
+ unless thunk
+ error("failed to parse nomic:\n#{str}")
+
+ prev_you = @you
+ @you = user or "anon"
+ ok,ret = pcall thunk.run, thunk, @, {}
+ @you = prev_you
+ if not ok
+ error(ret)
+ 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, :repl}
- game\def [[$invocations := $body]], (locals)=>
- game\def locals.invocations, locals.body
- return nil
- return game
+ repl:=>
+ 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
+ @\run buf
+
+return Game