mirror of
https://github.com/leafo/moonscript.git
synced 2025-01-09 00:04:22 +00:00
funcall and indexing is good
This commit is contained in:
parent
eb0f05cc3c
commit
4936446f1c
@ -9,42 +9,61 @@ require "util"
|
||||
-- end, _G)
|
||||
-- })
|
||||
|
||||
|
||||
local map, bind = util.map, util.bind
|
||||
|
||||
local indent_char = " "
|
||||
|
||||
function ntype(node)
|
||||
if type(node) ~= "table" then return "value" end
|
||||
return node[1]
|
||||
end
|
||||
|
||||
local compilers = {
|
||||
_indent = 0,
|
||||
ichar = function(self)
|
||||
return indent_char:rep(self._indent)
|
||||
end,
|
||||
|
||||
fncall = function(self, node)
|
||||
local _, name, args = unpack(node)
|
||||
return name .. self:args(args)
|
||||
chain = function(self, node)
|
||||
local callee = node[2]
|
||||
local actions = {}
|
||||
for i = 3,#node do
|
||||
local t, arg = unpack(node[i])
|
||||
if t == "call" then
|
||||
table.insert(actions, "("..table.concat(self:values(arg), ', ')..")")
|
||||
elseif t == "index" then
|
||||
table.insert(actions, "["..self:value(arg).."]")
|
||||
else
|
||||
error("Unknown chain action: "..t)
|
||||
end
|
||||
end
|
||||
|
||||
local callee_value = self:value(callee)
|
||||
if ntype(callee) == "exp" then
|
||||
callee_value = "("..callee_value..")"
|
||||
end
|
||||
|
||||
return callee_value..table.concat(actions)
|
||||
end,
|
||||
|
||||
fndef = function(self, node)
|
||||
local _, args, block = unpack(node)
|
||||
if #block == 1 then
|
||||
if #block == 0 then
|
||||
return "function() end"
|
||||
elseif #block == 1 then
|
||||
return ("function(%s) %s end"):format(
|
||||
table.concat(args, ", "), self:value(block[1]))
|
||||
end
|
||||
return ("function(%s)\n%s\n%send"):format(
|
||||
table.concat(args, ", "), self:block(block, 1), self:ichar())
|
||||
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,
|
||||
|
||||
["if"] = function(self, node)
|
||||
local _, cond, block = unpack(node)
|
||||
return ("if %s then\n%s\n%send"):format(
|
||||
self:value(cond), self:block(block, 1), self:ichar())
|
||||
end,
|
||||
|
||||
block = function(self, node, inc)
|
||||
if inc then self._indent = self._indent + inc end
|
||||
local lines = {}
|
||||
@ -55,11 +74,12 @@ local compilers = {
|
||||
if inc then self._indent = self._indent - inc end
|
||||
return table.concat(lines, "\n")
|
||||
end,
|
||||
|
||||
assign = function(self, node)
|
||||
local _, names, values = unpack(node)
|
||||
|
||||
return "local "..table.concat(names, ", ").." = "..table.concat(map(values, bind(self, "value")), ", ")
|
||||
return "local "..table.concat(names, ", ").." = "..table.concat(self:values(values), ", ")
|
||||
end,
|
||||
|
||||
exp = function(self, node)
|
||||
local values = {}
|
||||
for i = 2, #node do
|
||||
@ -67,6 +87,7 @@ local compilers = {
|
||||
end
|
||||
return table.concat(values, " ")
|
||||
end,
|
||||
|
||||
value = function(self, node)
|
||||
if type(node) == "table" then
|
||||
local op = unpack(node)
|
||||
@ -74,6 +95,16 @@ local compilers = {
|
||||
end
|
||||
|
||||
return node
|
||||
end,
|
||||
|
||||
-- a list of values
|
||||
values = function(self, items, start)
|
||||
start = start or 1
|
||||
local compiled = {}
|
||||
for i = start,#items do
|
||||
table.insert(compiled, self:value(items[i]))
|
||||
end
|
||||
return compiled
|
||||
end
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ local compile = require"moonscript.compile"
|
||||
local dump = require"moonscript.dump"
|
||||
local data = require"moonscript.data"
|
||||
|
||||
local ntype = compile.ntype
|
||||
|
||||
local Stack = data.Stack
|
||||
|
||||
local function count_indent(str)
|
||||
@ -24,16 +26,16 @@ local C, Ct, Cmt = lpeg.C, lpeg.Ct, lpeg.Cmt
|
||||
|
||||
local White = S" \t\n"^0
|
||||
local Space = S" \t"^0
|
||||
local ASpace = S" \t"^1
|
||||
local Break = S"\n"
|
||||
local Stop = Break + -1
|
||||
local Indent = C(S"\t "^0) / count_indent
|
||||
|
||||
local _Name = C(R("az", "AZ", "__") * R("az", "AZ", "__")^0)
|
||||
local Name = _Name * Space
|
||||
local Num = C(R("09")^1) / tonumber * Space
|
||||
local Name = Space * C(R("az", "AZ", "__") * R("az", "AZ", "__")^0)
|
||||
local Num = Space * C(R("09")^1) / tonumber
|
||||
|
||||
local FactorOp = lpeg.C(S"+-") * Space
|
||||
local TermOp = lpeg.C(S"*/%") * Space
|
||||
local FactorOp = Space * lpeg.C(S"+-")
|
||||
local TermOp = Space * lpeg.C(S"*/%")
|
||||
|
||||
local function wrap(fn)
|
||||
local env = getfenv(fi)
|
||||
@ -94,7 +96,7 @@ local build_grammar = wrap(function()
|
||||
|
||||
local _indent = Stack(0) -- current indent
|
||||
|
||||
local last_pos = 0 -- used to keep track of error
|
||||
local last_pos = 0 -- used to know where to report error
|
||||
local function check_indent(str, pos, indent)
|
||||
last_pos = pos
|
||||
return _indent:top() == indent
|
||||
@ -115,19 +117,34 @@ local build_grammar = wrap(function()
|
||||
local keywords = {}
|
||||
local function key(word)
|
||||
keywords[word] = true
|
||||
return word * Space
|
||||
return Space * word
|
||||
end
|
||||
|
||||
local function sym(chars)
|
||||
return chars * Space
|
||||
return Space * chars
|
||||
end
|
||||
|
||||
local function symx(chars)
|
||||
return chars
|
||||
end
|
||||
|
||||
local function flatten_func(callee, args)
|
||||
if #args == 0 then return callee end
|
||||
|
||||
args = {"call", args}
|
||||
if ntype(callee) == "chain" then
|
||||
table.insert(callee, args)
|
||||
return callee
|
||||
end
|
||||
|
||||
return {"chain", callee, args}
|
||||
end
|
||||
|
||||
-- make sure name is not a keyword
|
||||
local _Name = Cmt(Name, function(str, pos, name)
|
||||
local Name = Cmt(Name, function(str, pos, name)
|
||||
if keywords[name] then return false end
|
||||
return true, name
|
||||
end)
|
||||
local Name = _Name * Space
|
||||
|
||||
local g = lpeg.P{
|
||||
File,
|
||||
@ -141,15 +158,20 @@ local build_grammar = wrap(function()
|
||||
InBlock = #Cmt(Indent, advance_indent) * Block * OutBlock,
|
||||
OutBlock = Cmt("", pop_indent),
|
||||
|
||||
FunCall = _Name * (sym"(" * Ct(ExpList^-1) * sym")" + Space * Ct(ExpList)) / mark"fncall",
|
||||
|
||||
If = key"if" * Exp * Body / mark"if",
|
||||
|
||||
Assign = Ct(NameList) * sym"=" * Ct(ExpList) / mark"assign",
|
||||
|
||||
Exp = Ct(Term * (FactorOp * Term)^0) / flatten_or_mark"exp",
|
||||
Term = Ct(Value * (TermOp * Value)^0) / flatten_or_mark"exp",
|
||||
Value = Assign + FunLit + FunCall + Num + Name + TableLit,
|
||||
|
||||
Value = Assign + FunLit + (FunCall + Callable) * Ct(ExpList^0) / flatten_func + Num,
|
||||
|
||||
Callable = Name + Parens,
|
||||
Parens = sym"(" * Exp * sym")",
|
||||
|
||||
-- a plain function/index
|
||||
FunCall = Callable * (symx"(" * Ct(ExpList^-1)/mark"call" * sym")" + symx"[" * Exp/mark"index" * sym"]")^1 / mark"chain",
|
||||
|
||||
TableLit = sym"{" * Ct(ExpList^-1) * sym"}" / mark"list",
|
||||
|
||||
|
11
test.lua
11
test.lua
@ -16,7 +16,7 @@ local function diff(a_fname, b_fname)
|
||||
return io.popen(diff_tool.." ".. a_fname.." "..b_fname, "r"):read("*a")
|
||||
end
|
||||
|
||||
local function input_name(name) return opts.in_dir .. "/" .. name end
|
||||
local function input_name(name) return opts.in_dir.."/".. name end
|
||||
local function output_name(name)
|
||||
return opts.out_dir.."/"..name:match(opts.input_pattern)..opts.output_ext
|
||||
end
|
||||
@ -28,7 +28,11 @@ local function run_file(name)
|
||||
local parse = require "moonscript.parse"
|
||||
local compile = require "moonscript.compile"
|
||||
|
||||
return compile.tree(parse.string(file_str))
|
||||
local tree, err = parse.string(file_str)
|
||||
if not tree then
|
||||
error("Compile error in "..name.."\n"..err)
|
||||
end
|
||||
return compile.tree(tree)
|
||||
end
|
||||
|
||||
local function inputs(pattern)
|
||||
@ -53,6 +57,7 @@ local actions = {
|
||||
end
|
||||
end,
|
||||
run = function(pattern)
|
||||
local failed = false
|
||||
local tests_run, result = 0
|
||||
for file in inputs(pattern) do
|
||||
tests_run = tests_run + 1
|
||||
@ -86,7 +91,7 @@ local actions = {
|
||||
print("No tests matching pattern:", pattern)
|
||||
end
|
||||
elseif tests_run == 1 then
|
||||
print(result)
|
||||
-- print(result)
|
||||
end
|
||||
end,
|
||||
list = function(pattern)
|
||||
|
@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
|
||||
x = -> print what
|
||||
|
50
tests/inputs/syntax.moon
Normal file
50
tests/inputs/syntax.moon
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
x = -> print what
|
||||
|
||||
|
||||
->
|
||||
|
||||
-> -> ->
|
||||
go to the barn
|
||||
|
||||
open -> the -> door
|
||||
|
||||
open ->
|
||||
the door
|
||||
hello = ->
|
||||
my func
|
||||
|
||||
h = -> hi
|
||||
|
||||
eat ->, world
|
||||
|
||||
a = 1 + 2* 3 / 6
|
||||
|
||||
a, bunch, go, here = another, world
|
||||
|
||||
func arg1, arg2, another, arg3
|
||||
|
||||
here, we = () ->, yeah
|
||||
the, different = () -> approach, yeah
|
||||
|
||||
dad()
|
||||
dad(lord)
|
||||
hello(one,two)()
|
||||
(5 + 5)(world)
|
||||
|
||||
fun(a)(b)
|
||||
|
||||
fun(a) b
|
||||
|
||||
fun(a) b, bad hello
|
||||
|
||||
hello world what are you doing here
|
||||
|
||||
|
||||
what(the)[3243] world, yeck heck
|
||||
|
||||
hairy[hands][are](gross) okay okay[world]
|
||||
|
||||
(get[something] + 5)[years]
|
||||
|
@ -1 +0,0 @@
|
||||
local x = function() print(what) end
|
27
tests/outputs/syntax.lua
Normal file
27
tests/outputs/syntax.lua
Normal file
@ -0,0 +1,27 @@
|
||||
local x = function() print(what) end
|
||||
function() end
|
||||
function() function() function() end end end
|
||||
go(to(the(barn)))
|
||||
open(function() the(function() door end) end)
|
||||
open(function()
|
||||
the(door)
|
||||
local hello = function() my(func) end
|
||||
end)
|
||||
local h = function() hi end
|
||||
eat(function() end, world)
|
||||
local a = 1 + 2 * 3 / 6
|
||||
local a, bunch, go, here = another, world
|
||||
func(arg(1, arg(2, another, arg(3))))
|
||||
local here, we = function() end, yeah
|
||||
local the, different = function() approach end, yeah
|
||||
dad()
|
||||
dad(lord)
|
||||
hello(one, two)()
|
||||
(5 + 5)(world)
|
||||
fun(a)(b)
|
||||
fun(a)(b)
|
||||
fun(a)(b, bad(hello))
|
||||
hello(world(what(are(you(doing(here))))))
|
||||
what(the)[3243](world, yeck(heck))
|
||||
hairy[hands][are](gross)(okay(okay[world]))
|
||||
(get[something] + 5)[years]
|
Loading…
Reference in New Issue
Block a user