function calls, compiler

This commit is contained in:
leaf corcoran 2011-05-16 01:53:44 -07:00
parent 3bc7a28d13
commit 65cdd26784
2 changed files with 104 additions and 20 deletions

View File

@ -4,43 +4,83 @@ module("moonscript", package.seeall)
require"util" require"util"
require"lpeg" require"lpeg"
require"moonscript.compile"
local R, S, V, P = lpeg.R, lpeg.S, lpeg.V, lpeg.P local R, S, V, P = lpeg.R, lpeg.S, lpeg.V, lpeg.P
local C, Ct = lpeg.C, lpeg.Ct local C, Ct = lpeg.C, lpeg.Ct
local Space = S" \n\t"^0 local Space = S" \t"^0
local Indent = S"\t"^0 local Indent = S"\t"^0
local Break = S"\n"^1 local Break = S"\n" + -1
local ArgDelim = "," * Space
local Name = C(R("az", "AZ", "__") * R("az", "AZ", "__")^0) * Space local Name = C(R("az", "AZ", "__") * R("az", "AZ", "__")^0) * Space
local Num = C(R("09")^1) * Space local Num = C(R("09")^1) / tonumber * Space
local FactorOp = lpeg.C(S"+-") * Space local FactorOp = lpeg.C(S"+-") * Space
local TermOp = lpeg.C(S"*/%") * Space local TermOp = lpeg.C(S"*/%") * Space
function define(items) function wrap(fn)
for _, name in ipairs(items) do local env = getfenv(fi)
_G[name] = lpeg.V(name)
return setfenv(fn, setmetatable({}, {
__index = function(self, name)
local value = env[name]
if value ~= nil then return value end
if name:match"^[A-Z][A-Za-z0-9]*$" then
local v = V(name)
rawset(self, name, v)
return v
end
error("unknown variable referenced: "..name)
end
}))
end
function mark(name)
return function(...)
return name, ...
end end
end end
define { "Block", "Line", "Value", "Exp", "Factor", "Term" } function flatten(tbl)
if #tbl == 1 then
return tbl[1]
end
return tbl
end
local grammar = lpeg.P{
local build_grammar = wrap(function()
local g = lpeg.P{
Block, Block,
Block = Ct(Line^0), Block = Ct(Line^0),
Line = Ct(C"print" * Space * Exp * Space), Line = Ct(Funcall) * Break,
Exp = Ct(Value * (FactorOp * Value)^0), Funcall = Name * ArgList / mark"fncall",
Value = Num + Name ArgList = Ct(Exp * (ArgDelim * Exp)^0),
Exp = Ct(Value * (FactorOp * Value)^0) / flatten,
Value = Funcall + Num + Name
} }
grammar = Space * grammar * Space * -1 return Space * g * Space * -1
end)
local grammar = build_grammar()
local program = [[ local program = [[
print 2323 hello world nuts
print hi + world + 2342 eat 232, 343
print 23424
]] ]]
-- print hi + world + 2342
-- print 23424
-- ]]
print(util.dump(grammar:match(program)))
local tree = grammar:match(program)
if not tree then error("failed to compile") end
print(util.dump(tree))
print(compile.tree(tree))
local program2 = [[ local program2 = [[
if something if something
@ -73,7 +113,6 @@ class Hello
}} }}
]] ]]
function names() function names()
tests = { tests = {
"hello", "hello",

45
moonscript/compile.lua Normal file
View File

@ -0,0 +1,45 @@
module("moonscript.compile", package.seeall)
require "util"
-- setmetatable(_M, {
-- __call = setfenv(function(self, ...)
-- compile(...)
-- end, _G)
-- })
local compilers = {
fncall = function(self, node)
local _, name, args = unpack(node)
return name .. self:args(args)
end,
args = function(self, node)
local values = {}
for _, v in ipairs(node) do
table.insert(values, self:value(v))
end
return "(" .. table.concat(values, ", ") .. ")"
end,
value = function(self, node)
if type(node) == "table" then
local op = unpack(node)
return self[op](self, node)
end
return node
end
}
_M.tree = function(tree)
local buff = {}
for _, line in ipairs(tree) do
local op = line[1]
local fn = compilers[op]
if not fn then error("Unknown op: "..op) end
table.insert(buff, compilers[op](compilers, line))
end
return table.concat(buff, "\n")
end