1 changed files with 0 additions and 472 deletions
-
472monty.sol
@ -1,472 +0,0 @@ |
|||
TOK = {LPAREN = 1, RPAREN = 2, INT = 3, BOOL = 4, NAME = 5, QUOTE = 6, EOF = 7} |
|||
keys = [] |
|||
for k in TOK do keys:insert(#keys, k) end |
|||
for k in keys do TOK[TOK[k]]=k end |
|||
|
|||
token = { |
|||
new = func (type, value) |
|||
return {type = type, value = value, __index = token} |
|||
end, |
|||
pretty = func(self) |
|||
tname = TOK[self.type] |
|||
tval = tostring(self.value) |
|||
return '{'+tname+':'+tval+'}' |
|||
end |
|||
} |
|||
|
|||
tokenizer = { |
|||
WS = " "+chr(8)+chr(9)+chr(10), |
|||
NAMESET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=+-*/.<>?!@$%^~", |
|||
DIGITS = "0123456789", |
|||
EOF = {}, |
|||
new = func (str) |
|||
res = {str = str, pushed = None, __index = tokenizer} |
|||
res:init() |
|||
return res |
|||
end, |
|||
init = func(self) |
|||
--print('In init, self is', self) |
|||
res.cur = res:token() |
|||
res.next = res:token() |
|||
end, |
|||
next_char = func(self) |
|||
if self.pushed == None then |
|||
--print('In next_char, self is', self) |
|||
--print('In next_char, self.str is', self.str) |
|||
if self.str:eof() then return self.EOF end |
|||
res = self.str:read(1) |
|||
else |
|||
--print('Retrieving from pushback', self.pushed) |
|||
res = self.pushed[0] |
|||
self.pushed = self.pushed:sub(1) |
|||
if self.pushed == "" then self.pushed = None end |
|||
end |
|||
--print(res) |
|||
return res |
|||
end, |
|||
push_back = func(self, s) |
|||
--print('Pushing back', s) |
|||
if s == self.EOF then print('WARNING: Attempted to push_back EOF'); return end |
|||
if self.pushed == None then |
|||
self.pushed = s |
|||
else |
|||
self.pushed = s + self.pushed |
|||
end |
|||
--print('self.pushed:', self.pushed) |
|||
end, |
|||
token = func (self) |
|||
--print('In token, self is', self) |
|||
--print('In token, self.str is', self.str) |
|||
c = self:next_char() |
|||
while !(c == self.EOF) do |
|||
if c == "" then return token.new(TOK.EOF, None) end |
|||
if c == "(" then return token.new(TOK.LPAREN, c) end |
|||
if c == ")" then return token.new(TOK.RPAREN, c) end |
|||
if self.NAMESET:find(c) >= 0 then |
|||
--print('{NAME}') |
|||
name = c |
|||
c = self:next_char() |
|||
while 1 do |
|||
found = 0 |
|||
if self.NAMESET:find(c) >= 0 then found = 1 end |
|||
if self.DIGITS:find(c) >= 0 then found = 1 end |
|||
if !found then break end |
|||
name += c |
|||
c = self:next_char() |
|||
if c == self.EOF then continue end |
|||
end |
|||
self:push_back(c) |
|||
return token.new(TOK.NAME, name) |
|||
end |
|||
if self.DIGITS:find(c) >= 0 then |
|||
val = c |
|||
c = self:next_char() |
|||
while self.DIGITS:find(c) >= 0 do |
|||
val += c |
|||
c = self:next_char() |
|||
if c == self.EOF then continue end |
|||
end |
|||
self:push_back(c) |
|||
return token.new(TOK.INT, toint(val)) |
|||
end |
|||
if c == "#" then |
|||
c = self:next_char() |
|||
if c == "t" then return token.new(TOK.BOOL, 1) end |
|||
if c == "f" then return token.new(TOK.BOOL, 0) end |
|||
error("Invalid value for bool literal: "+c) |
|||
end |
|||
if c == "'" then return token.new(TOK.QUOTE, c) end |
|||
if self.WS:find(c) >= 0 then |
|||
c = self:next_char() |
|||
continue |
|||
end |
|||
if c == ";" then |
|||
c = self:next_char() |
|||
while 1 do |
|||
if c == chr(10) then break end |
|||
c = self:next_char() |
|||
end |
|||
c = self:next_char() |
|||
continue |
|||
end |
|||
error("Invalid character in token stream: "+c) |
|||
end |
|||
return token.new(TOK.EOF, None) |
|||
end, |
|||
advance = func(self) |
|||
self.cur = self.next |
|||
self.next = self:token() |
|||
end |
|||
} |
|||
|
|||
|
|||
|
|||
ttreegen = { |
|||
new = func(tok) |
|||
return {tok = tok, __index = ttreegen} |
|||
end, |
|||
generate = func(self, consume) |
|||
res = self.TT_DISPATCH[self.tok.cur.type](self, self.tok.cur) |
|||
if None == consume then self.tok:advance() end |
|||
return res |
|||
end, |
|||
TT_DISPATCH = { |
|||
[TOK.LPAREN] = func(self, tok) |
|||
toklist = [] |
|||
self.tok:advance() |
|||
tok = self.tok.cur |
|||
while 1 do |
|||
if tok.type == TOK.RPAREN then break end |
|||
if tok.type == TOK.EOF then error('Encountered EOF while matching delimiter') end |
|||
toklist:insert(#toklist, self.TT_DISPATCH[tok.type](self, tok)) |
|||
self.tok:advance() |
|||
tok = self.tok.cur |
|||
end |
|||
return toklist |
|||
end, |
|||
[TOK.RPAREN] = func(self, tok) |
|||
error("Unexpected right parenthesis") |
|||
end, |
|||
[TOK.INT] = func(self, tok) |
|||
return tok |
|||
end, |
|||
[TOK.BOOL] = func(self, tok) |
|||
return tok |
|||
end, |
|||
[TOK.NAME] = func(self, tok) |
|||
return tok |
|||
end, |
|||
[TOK.QUOTE] = func(self, tok) |
|||
self.tok:advance() |
|||
tok.quoting = self:generate(0) |
|||
return tok |
|||
end, |
|||
[TOK.EOF] = func(self, tok) |
|||
return None |
|||
end |
|||
} |
|||
} |
|||
|
|||
EX = {CALL=1, ASSIGN=2, FUNCDECL=3, SCOPE=4, IFELSE=5, DATUM=6, LIT=7, REF=8, LIST=9} |
|||
keys = [] |
|||
for k in EX do keys:insert(#keys, k) end |
|||
for k in keys do EX[EX[k]]=k end |
|||
|
|||
node = { |
|||
new = func(type, value) |
|||
return {type=type, value=value, __index=node} |
|||
end, |
|||
pretty = func(self) return self.PRETTY_DISPATCH[self.type](self) end |
|||
PRETTY_DISPATCH = { |
|||
[EX.CALL] = func(self) |
|||
return '<CALL NAME='+(self.value.name)+' ARGS='+tostring(self.value.args:copy():map(func(i) if !(None == i) then return i:pretty() else return tostring(i) end end))+'>' |
|||
end, |
|||
[EX.ASSIGN] = func(self) |
|||
return '<ASSIGN NAME='+(self.value.name)+' VALUE='+(self.value.value:pretty())+'>' |
|||
end, |
|||
[EX.FUNCDECL] = func(self) |
|||
return '<FUNCDECL PARAMS='+tostring(self.value.params)+' BODY='+(self.value.body:pretty())+'>' |
|||
end, |
|||
[EX.SCOPE] = func(self) |
|||
return '<SCOPE '+(self.value:copy():map(func(i) return i:pretty() end))+'>' |
|||
end, |
|||
[EX.IFELSE] = func(self) |
|||
return '<IFELSE COND='+(self.value.cond:pretty())+' IFT='+(self.value.ift:pretty())+' IFF='+(self.value.iff:pretty())+'>' |
|||
end, |
|||
[EX.DATUM] = func(self) |
|||
return '#'+tostring(self.value) |
|||
end, |
|||
[EX.LIT] = func(self) |
|||
if type(self.value) == 'list' then |
|||
return '/'+tostring(self.value:copy():map(func(i) return i:pretty() end)) |
|||
end |
|||
return '/'+tostring(self.value) |
|||
end, |
|||
[EX.REF] = func(self) |
|||
--print('In EX.REF, self is', self) |
|||
res = '@'+tostring(self.value) |
|||
--print('In EX.REF, returning', res) |
|||
return res |
|||
end, |
|||
[EX.LIST] = func(self) |
|||
--print('In EX.LIST, self is', self) |
|||
return '<LIST '+(self.value:copy():map(func(i) return i:pretty() end))+'>' |
|||
end |
|||
} |
|||
} |
|||
|
|||
parser = { |
|||
new = func(ttgen) |
|||
return {ttgen = ttgen, __index = parser} |
|||
end, |
|||
parse = func(self, tt) |
|||
if type(tt) == 'map' then |
|||
--print('In parse, self is', self) |
|||
--print('In parse, tt is', tt) |
|||
--print('In parse, dispatch to', self.TT_PARSE_DISPATCH[tt.type]) |
|||
res = self.TT_PARSE_DISPATCH[tt.type](self, tt) |
|||
else |
|||
name = tt[0] |
|||
if !(name.type == TOK.NAME) then |
|||
error('Expected name as first element of expression-list') |
|||
end |
|||
rest = tt:copy() |
|||
rest:remove(0) |
|||
sc = self.SCALL_DISPATCH[name.value] |
|||
if !(None == sc) then |
|||
sc = None |
|||
res = self.SCALL_DISPATCH[name.value](self, rest) |
|||
else |
|||
res = node.new(EX.CALL, {name=name.value, args=rest:map(func(i) return self:parse(i) end)}) |
|||
end |
|||
end |
|||
--print('In parse, returning', res:pretty()) |
|||
return res |
|||
end, |
|||
TT_PARSE_DISPATCH = { |
|||
[TOK.INT] = func(self, tok) |
|||
return node.new(EX.LIT, tok.value) |
|||
end, |
|||
[TOK.BOOL] = func(self, tok) |
|||
return node.new(EX.LIT, tok.value) |
|||
end, |
|||
[TOK.NAME] = func(self, tok) |
|||
--print('In TOK.NAME, tok is', tok) |
|||
res = node.new(EX.REF, tok.value) |
|||
--print('In TOK.NAME, returning', res) |
|||
return res |
|||
end, |
|||
[TOK.QUOTE] = func(self, tok) |
|||
return self:parse_datum(tok.quoting) |
|||
end |
|||
}, |
|||
SCALL_DISPATCH = { |
|||
define = func(self, args) |
|||
name = args[0] |
|||
if !(name.type == TOK.NAME) then error('Define: expected name as first argument') end |
|||
value = self:parse(args[1]) |
|||
return node.new(EX.ASSIGN, {name=name.value, value=value}) |
|||
end, |
|||
["if"] = func(self, args) |
|||
cond = self:parse(args[0]) |
|||
ift = self:parse(args[1]) |
|||
iff = self:parse(args[2]) |
|||
return node.new(EX.IFELSE, {cond=cond, ift=ift, iff=iff}) |
|||
end, |
|||
begin = func(self, args) |
|||
args:map(func(i) return self:parse(i) end) |
|||
return node.new(EX.LIST, args) |
|||
end, |
|||
lambda = func(self, args) |
|||
--print('Lambda args:', args) |
|||
params = args[0] |
|||
if !(type(params) == 'list') then error('Lambda: expected parameters as first argument (got '+tostring(params)+')') end |
|||
params:map(func(i) |
|||
if !(type(i) == 'map') then error('Lambda: expected name token in argument list (got sublist)') end |
|||
if !(i.type == TOK.NAME) then error('Lambda: expected name token in argument list (got '+(i:pretty())+')') end |
|||
return i.value |
|||
end) |
|||
body = args:copy() |
|||
body:remove(0) |
|||
--print('Lambda body:', body) |
|||
body:map(func(i) return self:parse(i) end) |
|||
return node.new(EX.FUNCDECL, {params=params, body=node.new(EX.LIST, body)}) |
|||
end, |
|||
let = func(self, args) |
|||
defs = args[0] |
|||
if !(type(defs) == 'list') then error('Let: expected list of bindings are first argument') end |
|||
defs:map(func(i) |
|||
if !(type(i) == 'list') then error('Let: expected a binding entry') end |
|||
return self.SCALL_DISPATCH.define(self, i) |
|||
end) |
|||
body = args:copy() |
|||
body:remove(0) |
|||
body:map(func(i) return self:parse(i) end) |
|||
return node.new(EX.SCOPE, defs+body) |
|||
end, |
|||
letrec = func(self, args) |
|||
defs = args[0] |
|||
if !(type(defs) == 'list') then error('Let: expected list of bindings are first argument') end |
|||
defs:map(func(i) |
|||
if !(type(i) == 'list') then error('Let: expected a binding entry') end |
|||
return self.SCALL_DISPATCH.define(self, i) |
|||
end) |
|||
body = args:copy() |
|||
body:remove(0) |
|||
body:map(func(i) return self:parse(i) end) |
|||
return node.new(EX.LIST, defs+body) |
|||
end |
|||
} |
|||
parse_datum = func(self, tt) |
|||
if type(tt) == 'map' then |
|||
return self.TT_PARSE_DATUM_DISPATCH[tt.type](self, tt) |
|||
else |
|||
list = [] |
|||
for tok in tt do |
|||
list:insert(#list, self:parse_datum(tok)) |
|||
end |
|||
return node.new(EX.LIT, list) |
|||
end |
|||
end, |
|||
TT_PARSE_DATUM_DISPATCH = { |
|||
[TOK.INT] = func(self, tok) |
|||
return node.new(EX.LIT, tok.value) |
|||
end, |
|||
[TOK.BOOL] = func(self, tok) |
|||
return node.new(EX.LIT, tok.value) |
|||
end, |
|||
[TOK.NAME] = func(self, tok) |
|||
return node.new(EX.LIT, tok.value) |
|||
end, |
|||
[TOK.QUOTE] = func(self, tok) |
|||
return self:parse(tok.quoting) |
|||
end |
|||
}, |
|||
run = func(self) |
|||
tt = self.ttgen:generate() |
|||
list = [] |
|||
while 1 do |
|||
if None == tt then break end |
|||
--if type(tt) == 'list' then |
|||
list:insert(#list, self:parse(tt)) |
|||
--end |
|||
tt = self.ttgen:generate() |
|||
end |
|||
--print('In run, list is', list) |
|||
return node.new(EX.LIST, list) |
|||
end |
|||
} |
|||
|
|||
converter = { |
|||
new = func(p) |
|||
return {parser=p, __index = converter} |
|||
end, |
|||
make = func(self, node) |
|||
--print('In make, node is a', EX[node.type], 'of value', node) |
|||
res = self.MAKE_DISPATCH[node.type](self, node) |
|||
--print('In make, returning', res) |
|||
if type(res) == "astnode" then ast.print(res) end |
|||
return res |
|||
end, |
|||
MAKE_DISPATCH = { |
|||
[EX.CALL] = func(self, node) |
|||
e = parse('f()').stmtlist[0].expr |
|||
e.expr.ident = node.value.name |
|||
args = node.value.args:copy():map(func(i) return self:make(i) end) |
|||
--print('In EX.CALL, replacement args are', args) |
|||
e.args = args |
|||
--print('In EX.CALL, args are', e.args) |
|||
return e |
|||
end, |
|||
[EX.ASSIGN] = func(self, node) |
|||
e = parse('a = b').stmtlist[0].expr |
|||
e.ident = node.value.name |
|||
e.value = self:make(node.value.value) |
|||
return e |
|||
end, |
|||
[EX.FUNCDECL] = func(self, node) |
|||
e = parse('func() None None end').stmtlist[0].expr |
|||
params = node.value.params |
|||
--print('In EX.FUNCDECL, params are', params) |
|||
e.args = params |
|||
--print('In EX.FUNCDECL, args are', e.args) |
|||
e.body.stmtlist = self:make(node.value.body) |
|||
return e |
|||
end, |
|||
[EX.SCOPE] = func(self, node) |
|||
e = parse('(func() None None end)()').stmtlist[0].expr |
|||
node.type = EX.LIST |
|||
e.expr.body.stmtlist = self:make(node) |
|||
node.type = EX.SCOPE |
|||
return e |
|||
end, |
|||
[EX.IFELSE] = func(self, node) |
|||
e = parse('(func() if None then return None else return None end end)()').stmtlist[0].expr |
|||
e.expr.body.stmtlist[0].cond = self:make(node.value.cond) |
|||
e.expr.body.stmtlist[0].iftrue.stmtlist[0].ret = self:make(node.value.ift) |
|||
e.expr.body.stmtlist[0].iffalse.stmtlist[0].ret = self:make(node.value.iff) |
|||
return e |
|||
end, |
|||
[EX.DATUM] = func(self, node) error('EX.DATUM: Not implemented') end, |
|||
[EX.LIT] = func(self, node) |
|||
if type(node.value) == 'list' then |
|||
e = parse('[None]').stmtlist[0].expr |
|||
e.list = node.value:copy():map(func(i) return self:make(i) end) |
|||
else |
|||
e = parse('None').stmtlist[0].expr |
|||
if type(node.value) == "int" then |
|||
e.littype = ast.LIT_INT |
|||
e.ival = node.value |
|||
end |
|||
if type(node.value) == "string" then |
|||
e.littype = ast.LIT_STRING |
|||
e.str = node.value |
|||
end |
|||
end |
|||
return e |
|||
end, |
|||
[EX.REF] = func(self, node) |
|||
e = parse('a').stmtlist[0].expr |
|||
e.ident = node.value |
|||
return e |
|||
end, |
|||
[EX.LIST] = func(self, node) |
|||
e = parse('func() None end').stmtlist[0].expr |
|||
l = node.value:copy() |
|||
l:map(func(i) |
|||
s = parse('None').stmtlist[0] |
|||
s.expr = self:make(i) |
|||
return s |
|||
end) |
|||
lastidx = (#l) - 1 |
|||
r = parse('return None').stmtlist[0] |
|||
r.ret = l[lastidx].expr |
|||
l[lastidx] = r |
|||
--print('In EX.LIST, e is now' e) |
|||
e.body.stmtlist = l |
|||
return e.body.stmtlist |
|||
end |
|||
}, |
|||
run = func(self) |
|||
list = self:make(self.parser:run()) |
|||
res = parse('(func() None None end)()') |
|||
--print('In run, list is', list) |
|||
--for i in list do ast.print(i) end |
|||
res.stmtlist[0].expr.expr.body.stmtlist = list |
|||
return res |
|||
end |
|||
} |
|||
|
|||
_G = debug.globals() |
|||
_G['+'] = func(a, b) return a + b end |
|||
_G['-'] = func(a, b) return a - b end |
|||
_G['*'] = func(a, b) return a * b end |
|||
_G['/'] = func(a, b) return a / b end |
|||
_G['<'] = func(a, b) return a < b end |
|||
_G['>'] = func(a, b) return a > b end |
|||
_G['<='] = func(a, b) return a <= b end |
|||
_G['>='] = func(a, b) return a >= b end |
|||
_G['=='] = func(a, b) return a == b end |
|||
_G['eq'] = _G['=='] |
|||
_G['or'] = func(a, b) return a || b end |
|||
_G['and'] = func(a, b) return a && b end |
Write
Preview
Loading…
Cancel
Save
Reference in new issue