diff --git a/moonscript/compile/value.lua b/moonscript/compile/value.lua index 8f8e8f2..0722024 100644 --- a/moonscript/compile/value.lua +++ b/moonscript/compile/value.lua @@ -95,7 +95,7 @@ return { elseif t == "dot" then return ".", tostring(arg) elseif t == "colon" then - return ":", arg, chain_item(node[3]) + return ":", tostring(arg) elseif t == "colon_stub" then return user_error("Uncalled colon stub") else diff --git a/moonscript/compile/value.moon b/moonscript/compile/value.moon index 515fed8..c8f9891 100644 --- a/moonscript/compile/value.moon +++ b/moonscript/compile/value.moon @@ -64,7 +64,7 @@ string_chars = { elseif t == "dot" ".", tostring arg elseif t == "colon" - ":", arg, chain_item(node[3]) + ":", tostring arg elseif t == "colon_stub" user_error "Uncalled colon stub" else diff --git a/moonscript/parse.lua b/moonscript/parse.lua index 026734d..13fb8aa 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -27,10 +27,10 @@ Num = Space * (Num / function(v) v } end) -local Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign +local Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, join_chain, flatten_string_chain, wrap_decorator, check_lua_string, self_assign do local _obj_0 = require("moonscript.parse.util") - Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.flatten_func, _obj_0.flatten_string_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign + Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, join_chain, flatten_string_chain, wrap_decorator, check_lua_string, self_assign = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.join_chain, _obj_0.flatten_string_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign end local build_grammar = wrap_env(debug_grammar, function(root) local _indent = Stack(0) @@ -148,13 +148,12 @@ local build_grammar = wrap_env(debug_grammar, function(root) CharOperators = Space * C(S("+-*/%^><")), WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op(".."), BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0, - Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName, + Assignable = Cmt(Chain, check_assignable) + Name + SelfName, Exp = Ct(Value * (BinaryOperator * Value) ^ 0) / flatten_or_mark("exp"), SimpleValue = If + Unless + Switch + With + ClassDecl + ForEach + For + While + Cmt(Do, check_do) + sym("-") * -SomeSpace * Exp / mark("minus") + sym("#") * Exp / mark("length") + key("not") * Exp / mark("not") + TblComprehension + TableLit + Comprehension + FunLit + Num, - ChainValue = StringChain + ((Chain + DotChain + Callable) * Ct(InvokeArgs ^ -1)) / flatten_func, - Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue), + ChainValue = (Chain + Callable) * Ct(InvokeArgs ^ -1) / join_chain, + Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue + String), SliceValue = SimpleValue + ChainValue, - StringChain = String * (Ct((ColonCall + ColonSuffix) * ChainTail ^ -1) * Ct(InvokeArgs ^ -1)) ^ -1 / flatten_string_chain, String = Space * DoubleString + Space * SingleString + LuaString, SingleString = simple_string("'"), DoubleString = simple_string('"', true), @@ -164,13 +163,11 @@ local build_grammar = wrap_env(debug_grammar, function(root) Callable = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"), Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"), FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(ExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""), - ChainTail = ChainItem ^ 1 * ColonSuffix ^ -1 + ColonSuffix, - Chain = Callable * ChainTail / mark("chain"), - DotChain = (sym(".") * Cc(-1) * (_Name / mark("dot")) * ChainTail ^ -1) / mark("chain") + (sym("\\") * Cc(-1) * ((_Name * Invoke / mark("colon")) * ChainTail ^ -1 + (_Name / mark("colon_stub")))) / mark("chain"), - ChainItem = Invoke + Slice + symx("[") * Exp / mark("index") * sym("]") + symx(".") * _Name / mark("dot") + ColonCall, + Chain = (Callable + String + -S(".\\")) * ChainItems / mark("chain"), + ChainItems = ChainItem ^ 1 * ColonChainItem ^ -1 + ColonChainItem, + ChainItem = Invoke + symx(".") * _Name / mark("dot") + Slice + symx("[") * Exp / mark("index") * sym("]"), + ColonChainItem = symx("\\") * _Name / mark("colon") * (Invoke * ChainItems ^ -1) ^ -1, Slice = symx("[") * (SliceValue + Cc(1)) * sym(",") * (SliceValue + Cc("")) * (sym(",") * SliceValue) ^ -1 * sym("]") / mark("slice"), - ColonCall = symx("\\") * (_Name * Invoke) / mark("colon"), - ColonSuffix = symx("\\") * _Name / mark("colon_stub"), Invoke = FnArgs / mark("call") + SingleString / wrap_func_arg + DoubleString / wrap_func_arg + #P("[") * LuaString / wrap_func_arg, TableValue = KeyValue + Ct(Exp), TableLit = sym("{") * Ct(TableValueList ^ -1 * sym(",") ^ -1 * (SpaceBreak * TableLitLine * (sym(",") ^ -1 * SpaceBreak * TableLitLine) ^ 0 * sym(",") ^ -1) ^ -1) * White * sym("}") / mark("table"), diff --git a/moonscript/parse.moon b/moonscript/parse.moon index a224580..dac6b81 100644 --- a/moonscript/parse.moon +++ b/moonscript/parse.moon @@ -3,6 +3,7 @@ lpeg = require "lpeg" lpeg.setmaxstack 10000 -- whoa + err_msg = "Failed to parse:%s\n [%d] >> %s" import Stack from require "moonscript.data" @@ -27,7 +28,7 @@ Num = Space * (Num / (v) -> {"number", v}) { :Indent, :Cut, :ensure, :extract_line, :mark, :pos, :flatten_or_mark, :is_assignable, :check_assignable, :format_assign, :format_single_assign, - :sym, :symx, :simple_string, :wrap_func_arg, :flatten_func, + :sym, :symx, :simple_string, :wrap_func_arg, :join_chain, :flatten_string_chain, :wrap_decorator, :check_lua_string, :self_assign } = require "moonscript.parse.util" @@ -183,7 +184,7 @@ build_grammar = wrap_env debug_grammar, (root) -> WordOperators: op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." BinaryOperator: (WordOperators + CharOperators) * SpaceBreak^0 - Assignable: Cmt(DotChain + Chain, check_assignable) + Name + SelfName + Assignable: Cmt(Chain, check_assignable) + Name + SelfName Exp: Ct(Value * (BinaryOperator * Value)^0) / flatten_or_mark"exp" SimpleValue: @@ -202,20 +203,17 @@ build_grammar = wrap_env debug_grammar, (root) -> FunLit + Num - ChainValue: -- a function call or an object access - StringChain + - ((Chain + DotChain + Callable) * Ct(InvokeArgs^-1)) / flatten_func + -- a function call or an object access + ChainValue: (Chain + Callable) * Ct(InvokeArgs^-1) / join_chain Value: pos( SimpleValue + Ct(KeyValueList) / mark"table" + - ChainValue) + ChainValue + + String) SliceValue: SimpleValue + ChainValue - StringChain: String * - (Ct((ColonCall + ColonSuffix) * ChainTail^-1) * Ct(InvokeArgs^-1))^-1 / flatten_string_chain - String: Space * DoubleString + Space * SingleString + LuaString SingleString: simple_string("'") DoubleString: simple_string('"', true) @@ -232,33 +230,23 @@ build_grammar = wrap_env debug_grammar, (root) -> FnArgs: symx"(" * SpaceBreak^0 * Ct(ExpList^-1) * SpaceBreak^0 * sym")" + sym"!" * -P"=" * Ct"" - ChainTail: ChainItem^1 * ColonSuffix^-1 + ColonSuffix - -- a list of funcalls and indexes on a callable - Chain: Callable * ChainTail / mark"chain" + Chain: (Callable + String + -S".\\") * ChainItems / mark"chain" - -- shorthand dot call for use in with statement - DotChain: - (sym"." * Cc(-1) * (_Name / mark"dot") * ChainTail^-1) / mark"chain" + - (sym"\\" * Cc(-1) * ( - (_Name * Invoke / mark"colon") * ChainTail^-1 + - (_Name / mark"colon_stub") - )) / mark"chain" + ChainItems: ChainItem^1 * ColonChainItem^-1 + ColonChainItem ChainItem: Invoke + - Slice + - symx"[" * Exp/mark"index" * sym"]" + symx"." * _Name/mark"dot" + - ColonCall + Slice + + symx"[" * Exp/mark"index" * sym"]" + + ColonChainItem: symx"\\" * _Name / mark"colon" * (Invoke * ChainItems^-1)^-1 Slice: symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") * (sym"," * SliceValue)^-1 *sym"]" / mark"slice" - ColonCall: symx"\\" * (_Name * Invoke) / mark"colon" - ColonSuffix: symx"\\" * _Name / mark"colon_stub" - - Invoke: FnArgs/mark"call" + + Invoke: FnArgs / mark"call" + SingleString / wrap_func_arg + DoubleString / wrap_func_arg + #P"[" * LuaString / wrap_func_arg @@ -314,6 +302,7 @@ build_grammar = wrap_env debug_grammar, (root) -> ExpList: Exp * (sym"," * Exp)^0 ExpListLow: Exp * ((sym"," + sym";") * Exp)^0 + -- open args InvokeArgs: -P"-" * (ExpList * (sym"," * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock^-1) + TableBlock)^-1 + TableBlock) ArgBlock: ArgLine * (sym"," * SpaceBreak * ArgLine)^0 * PopIndent ArgLine: CheckIndent * ExpList diff --git a/moonscript/parse/util.lua b/moonscript/parse/util.lua index 6db63f0..a93665d 100644 --- a/moonscript/parse/util.lua +++ b/moonscript/parse/util.lua @@ -178,8 +178,8 @@ wrap_func_arg = function(value) } } end -local flatten_func -flatten_func = function(callee, args) +local join_chain +join_chain = function(callee, args) if #args == 0 then return callee end @@ -188,13 +188,7 @@ flatten_func = function(callee, args) args } if ntype(callee) == "chain" then - local stub = callee[#callee] - if ntype(stub) == "colon_stub" then - stub[1] = "colon" - table.insert(stub, args) - else - table.insert(callee, args) - end + table.insert(callee, args) return callee end return { @@ -208,7 +202,7 @@ flatten_string_chain = function(str, chain, args) if not (chain) then return str end - return flatten_func({ + return flatten_chain({ "chain", str, unpack(chain) @@ -259,7 +253,7 @@ return { symx = symx, simple_string = simple_string, wrap_func_arg = wrap_func_arg, - flatten_func = flatten_func, + join_chain = join_chain, flatten_string_chain = flatten_string_chain, wrap_decorator = wrap_decorator, check_lua_string = check_lua_string, diff --git a/moonscript/parse/util.moon b/moonscript/parse/util.moon index e12e1f8..2039e3b 100644 --- a/moonscript/parse/util.moon +++ b/moonscript/parse/util.moon @@ -127,27 +127,21 @@ simple_string = (delim, allow_interpolation) -> -- wraps a single value in format needed to be passed as function arguments wrap_func_arg = (value) -> {"call", {value}} --- flatten out the parsed function node -flatten_func = (callee, args) -> +-- chains are parsed in two captures, the chain and then the open arguments +-- if there are open arguments, then append them to the end of the chain as a call +join_chain = (callee, args) -> return callee if #args == 0 args = {"call", args} if ntype(callee) == "chain" - -- check for colon stub needing arguments - stub = callee[#callee] - if ntype(stub) == "colon_stub" - stub[1] = "colon" - table.insert stub, args - else - table.insert callee, args - + table.insert callee, args return callee {"chain", callee, args} flatten_string_chain = (str, chain, args) -> return str unless chain - flatten_func {"chain", str, unpack chain}, args + flatten_chain {"chain", str, unpack chain}, args -- constructor for decorator node wrap_decorator = (stm, dec) -> @@ -163,5 +157,5 @@ self_assign = (name, pos) -> { :Indent, :Cut, :ensure, :extract_line, :mark, :pos, :flatten_or_mark, :is_assignable, :check_assignable, :format_assign, :format_single_assign, - :sym, :symx, :simple_string, :wrap_func_arg, :flatten_func, + :sym, :symx, :simple_string, :wrap_func_arg, :join_chain, :flatten_string_chain, :wrap_decorator, :check_lua_string, :self_assign } diff --git a/moonscript/transform.lua b/moonscript/transform.lua index 8590ec8..0b1e1d0 100644 --- a/moonscript/transform.lua +++ b/moonscript/transform.lua @@ -12,10 +12,10 @@ do local _obj_0 = require("moonscript.transform.names") NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName end -local Run, transform_last_stm, last_stm +local Run, transform_last_stm, last_stm, chain_is_stub do local _obj_0 = require("moonscript.transform.statements") - Run, transform_last_stm, last_stm = _obj_0.Run, _obj_0.transform_last_stm, _obj_0.last_stm + Run, transform_last_stm, last_stm, chain_is_stub = _obj_0.Run, _obj_0.transform_last_stm, _obj_0.last_stm, _obj_0.chain_is_stub end local destructure = require("moonscript.transform.destructure") local NOOP = { @@ -1498,7 +1498,6 @@ Value = Transformer({ }) end, chain = function(self, node) - local stub = node[#node] for i = 3, #node do local part = node[i] if ntype(part) == "dot" and data.lua_keywords[part[2]] then @@ -1517,10 +1516,11 @@ Value = Transformer({ "parens", node[2] } - elseif type(stub) == "table" and stub[1] == "colon_stub" then - table.remove(node, #node) + end + if chain_is_stub(node) then local base_name = NameProxy("base") local fn_name = NameProxy("fn") + local colon = table.remove(node) local is_super = ntype(node[2]) == "ref" and node[2][2] == "super" return build.block_exp({ build.assign({ @@ -1540,7 +1540,7 @@ Value = Transformer({ base = base_name, { "dot", - stub[2] + colon[2] } }) } diff --git a/moonscript/transform.moon b/moonscript/transform.moon index 4352554..9be3292 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -8,7 +8,7 @@ import ntype, mtype, build, smart_node, is_slice, value_is_singular from types import insert from table import NameProxy, LocalName from require "moonscript.transform.names" -import Run, transform_last_stm, last_stm from require "moonscript.transform.statements" +import Run, transform_last_stm, last_stm, chain_is_stub from require "moonscript.transform.statements" destructure = require "moonscript.transform.destructure" NOOP = {"noop"} @@ -910,8 +910,6 @@ Value = Transformer { -- pull out colon chain chain: (node) => - stub = node[#node] - -- escape lua keywords used in dot accessors for i=3,#node part = node[i] @@ -921,12 +919,11 @@ Value = Transformer { if ntype(node[2]) == "string" -- add parens if callee is raw string node[2] = {"parens", node[2] } - elseif type(stub) == "table" and stub[1] == "colon_stub" - -- convert colon stub into code - table.remove node, #node + if chain_is_stub node base_name = NameProxy "base" fn_name = NameProxy "fn" + colon = table.remove node is_super = ntype(node[2]) == "ref" and node[2][2] == "super" build.block_exp { @@ -938,7 +935,7 @@ Value = Transformer { build.assign { names: {fn_name} values: { - build.chain { base: base_name, {"dot", stub[2]} } + build.chain { base: base_name, {"dot", colon[2]} } } } diff --git a/moonscript/transform/statements.lua b/moonscript/transform/statements.lua index f71aede..169590e 100644 --- a/moonscript/transform/statements.lua +++ b/moonscript/transform/statements.lua @@ -68,8 +68,14 @@ transform_last_stm = function(stms, fn) return _accum_0 end)() end +local chain_is_stub +chain_is_stub = function(chain) + local stub = chain[#chain] + return stub and ntype(stub) == "colon" +end return { Run = Run, last_stm = last_stm, - transform_last_stm = transform_last_stm + transform_last_stm = transform_last_stm, + chain_is_stub = chain_is_stub } diff --git a/moonscript/transform/statements.moon b/moonscript/transform/statements.moon index 0e3baeb..59d8e36 100644 --- a/moonscript/transform/statements.moon +++ b/moonscript/transform/statements.moon @@ -40,6 +40,9 @@ transform_last_stm = (stms, fn) -> else stm +chain_is_stub = (chain) -> + stub = chain[#chain] + stub and ntype(stub) == "colon" -{:Run, :last_stm, :transform_last_stm} +{:Run, :last_stm, :transform_last_stm, :chain_is_stub}