diff --git a/candran.lua b/candran.lua index b63f0a6..2327364 100644 --- a/candran.lua +++ b/candran.lua @@ -401,6 +401,18 @@ end return r end, ["Paren"] = function(t) return "(" .. lua(t[1]) .. ")" +end, ["DoExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Do") .. unindent() .. "end)()" +end, ["WhileExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "While") .. unindent() .. "end)()" +end, ["RepeatExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Repeat") .. unindent() .. "end)()" +end, ["IfExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "If") .. unindent() .. "end)()" +end, ["FornumExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Fornum") .. unindent() .. "end)()" +end, ["ForninExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Forin") .. unindent() .. "end)()" end, ["Call"] = function(t) return lua(t[1]) .. "(" .. lua(t, "_lhs", 2) .. ")" end, ["Invoke"] = function(t) @@ -705,6 +717,18 @@ end return r end, ["Paren"] = function(t) return "(" .. lua(t[1]) .. ")" +end, ["DoExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Do") .. unindent() .. "end)()" +end, ["WhileExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "While") .. unindent() .. "end)()" +end, ["RepeatExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Repeat") .. unindent() .. "end)()" +end, ["IfExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "If") .. unindent() .. "end)()" +end, ["FornumExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Fornum") .. unindent() .. "end)()" +end, ["ForninExpr"] = function(t) +return "(function()" .. indent() .. lua(t, "Forin") .. unindent() .. "end)()" end, ["Call"] = function(t) return lua(t[1]) .. "(" .. lua(t, "_lhs", 2) .. ")" end, ["Invoke"] = function(t) @@ -1887,9 +1911,13 @@ table["insert"](t1, 1, { end return t1 end +local function statToExpr(t) +t["tag"] = t["tag"] .. "Expr" +return t +end local G = { V("Lua"), ["Lua"] = V("Shebang") ^ - 1 * V("Skip") * V("Block") * expect(P(- 1), "Extra"), ["Shebang"] = P("#!") * (P(1) - P("\ -")) ^ 0, ["Block"] = tagC("Block", V("Stat") ^ 0 * (V("RetStat") + V("ImplicitRetStat")) ^ - 1), ["Stat"] = V("IfStat") + V("DoStat") + V("WhileStat") + V("RepeatStat") + V("ForStat") + V("LocalStat") + V("LetStat") + V("FuncStat") + V("BreakStat") + V("ContinueStat") + V("LabelStat") + V("GoToStat") + V("FuncCall") + V("Assignment") + sym(";") + - V("BlockEnd") * throw("InvalidStat"), ["BlockEnd"] = P("return") + "end" + "elseif" + "else" + "until" + - 1 + V("ImplicitRetStat"), ["IfStat"] = tagC("If", V("IfPart") * V("ElseIfPart") ^ 0 * V("ElsePart") ^ - 1 * expect(kw("end"), "EndIf")), ["IfPart"] = kw("if") * expect(V("Expr"), "ExprIf") * expect(kw("then"), "ThenIf") * V("Block"), ["ElseIfPart"] = kw("elseif") * expect(V("Expr"), "ExprEIf") * expect(kw("then"), "ThenEIf") * V("Block"), ["ElsePart"] = kw("else") * V("Block"), ["DoStat"] = kw("do") * V("Block") * expect(kw("end"), "EndDo") / tagDo, ["WhileStat"] = tagC("While", kw("while") * expect(V("Expr"), "ExprWhile") * V("WhileBody")), ["WhileBody"] = expect(kw("do"), "DoWhile") * V("Block") * expect(kw("end"), "EndWhile"), ["RepeatStat"] = tagC("Repeat", kw("repeat") * V("Block") * expect(kw("until"), "UntilRep") * expect(V("Expr"), "ExprRep")), ["ForStat"] = kw("for") * expect(V("ForNum") + V("ForIn"), "ForRange") * expect(kw("end"), "EndFor"), ["ForNum"] = tagC("Fornum", V("Id") * sym("=") * V("NumRange") * V("ForBody")), ["NumRange"] = expect(V("Expr"), "ExprFor1") * expect(sym(","), "CommaFor") * expect(V("Expr"), "ExprFor2") * (sym(",") * expect(V("Expr"), "ExprFor3")) ^ - 1, ["ForIn"] = tagC("Forin", V("NameList") * expect(kw("in"), "InFor") * expect(V("ExprList"), "EListFor") * V("ForBody")), ["ForBody"] = expect(kw("do"), "DoFor") * V("Block"), ["LocalStat"] = kw("local") * expect(V("LocalFunc") + V("LocalAssign"), "DefLocal"), ["LocalFunc"] = tagC("Localrec", kw("function") * expect(V("Id"), "NameLFunc") * V("FuncBody")) / fixFuncStat, ["LocalAssign"] = tagC("Local", V("NameList") * (sym("=") * expect(V("ExprList"), "EListLAssign") + Ct(Cc()))), ["LetStat"] = kw("let") * expect(V("LetAssign"), "DefLet"), ["LetAssign"] = tagC("Let", V("NameList") * (sym("=") * expect(V("ExprList"), "EListLAssign") + Ct(Cc()))), ["Assignment"] = tagC("Set", V("VarList") * V("BinOp") ^ - 1 * (sym("=") / "=") * V("BinOp") ^ - 1 * expect(V("ExprList"), "EListAssign")), ["FuncStat"] = tagC("Set", kw("function") * expect(V("FuncName"), "FuncName") * V("FuncBody")) / fixFuncStat, ["FuncName"] = Cf(V("Id") * (sym(".") * expect(V("StrId"), "NameFunc1")) ^ 0, insertIndex) * (sym(":") * expect(V("StrId"), "NameFunc2")) ^ - 1 / markMethod, ["FuncBody"] = tagC("Function", V("FuncParams") * V("Block") * expect(kw("end"), "EndFunc")), ["FuncParams"] = expect(sym("("), "OParenPList") * V("ParList") * expect(sym(")"), "CParenPList"), ["ParList"] = V("NamedParList") * (sym(",") * expect(tagC("Dots", sym("...")), "ParList")) ^ - 1 / addDots + Ct(tagC("Dots", sym("..."))) + Ct(Cc()), ["NamedParList"] = tagC("NamedParList", commaSep(V("NamedPar"))), ["NamedPar"] = tagC("ParPair", V("ParKey") * expect(sym("="), "EqField") * expect(V("Expr"), "ExprField")) + V("Id"), ["ParKey"] = V("Id") * # ("=" * - P("=")), ["LabelStat"] = tagC("Label", sym("::") * expect(V("Name"), "Label") * expect(sym("::"), "CloseLabel")), ["GoToStat"] = tagC("Goto", kw("goto") * expect(V("Name"), "Goto")), ["BreakStat"] = tagC("Break", kw("break")), ["ContinueStat"] = tagC("Continue", kw("continue")), ["RetStat"] = tagC("Return", kw("return") * commaSep(V("Expr"), "RetList") ^ - 1 * sym(";") ^ - 1), ["ImplicitRetStat"] = tagC("Return", commaSep(V("Expr"), "RetList") * sym(";") ^ - 1), ["NameList"] = tagC("NameList", commaSep(V("Id"))), ["VarList"] = tagC("VarList", commaSep(V("VarExpr"), "VarList")), ["ExprList"] = tagC("ExpList", commaSep(V("Expr"), "ExprList")), ["Expr"] = V("OrExpr"), ["OrExpr"] = chainOp(V("AndExpr"), V("OrOp"), "OrExpr"), ["AndExpr"] = chainOp(V("RelExpr"), V("AndOp"), "AndExpr"), ["RelExpr"] = chainOp(V("BOrExpr"), V("RelOp"), "RelExpr"), ["BOrExpr"] = chainOp(V("BXorExpr"), V("BOrOp"), "BOrExpr"), ["BXorExpr"] = chainOp(V("BAndExpr"), V("BXorOp"), "BXorExpr"), ["BAndExpr"] = chainOp(V("ShiftExpr"), V("BAndOp"), "BAndExpr"), ["ShiftExpr"] = chainOp(V("ConcatExpr"), V("ShiftOp"), "ShiftExpr"), ["ConcatExpr"] = V("AddExpr") * (V("ConcatOp") * expect(V("ConcatExpr"), "ConcatExpr")) ^ - 1 / binaryOp, ["AddExpr"] = chainOp(V("MulExpr"), V("AddOp"), "AddExpr"), ["MulExpr"] = chainOp(V("UnaryExpr"), V("MulOp"), "MulExpr"), ["UnaryExpr"] = V("UnaryOp") * expect(V("UnaryExpr"), "UnaryExpr") / unaryOp + V("PowExpr"), ["PowExpr"] = V("SimpleExpr") * (V("PowOp") * expect(V("UnaryExpr"), "PowExpr")) ^ - 1 / binaryOp, ["SimpleExpr"] = tagC("Number", V("Number")) + tagC("String", V("String")) + tagC("Nil", kw("nil")) + tagC("Boolean", kw("false") * Cc(false)) + tagC("Boolean", kw("true") * Cc(true)) + tagC("Dots", sym("...")) + V("FuncDef") + V("Table") + V("SuffixedExpr"), ["FuncCall"] = Cmt(V("SuffixedExpr"), function(s, i, exp) +")) ^ 0, ["Block"] = tagC("Block", V("Stat") ^ 0 * (V("RetStat") + V("ImplicitRetStat")) ^ - 1), ["Stat"] = V("IfStat") + V("DoStat") + V("WhileStat") + V("RepeatStat") + V("ForStat") + V("LocalStat") + V("LetStat") + V("FuncStat") + V("BreakStat") + V("ContinueStat") + V("LabelStat") + V("GoToStat") + V("FuncCall") + V("Assignment") + sym(";") + - V("BlockEnd") * throw("InvalidStat"), ["BlockEnd"] = P("return") + "end" + "elseif" + "else" + "until" + - 1 + V("ImplicitRetStat"), ["IfStat"] = tagC("If", V("IfPart") * V("ElseIfPart") ^ 0 * V("ElsePart") ^ - 1 * expect(kw("end"), "EndIf")), ["IfPart"] = kw("if") * expect(V("Expr"), "ExprIf") * expect(kw("then"), "ThenIf") * V("Block"), ["ElseIfPart"] = kw("elseif") * expect(V("Expr"), "ExprEIf") * expect(kw("then"), "ThenEIf") * V("Block"), ["ElsePart"] = kw("else") * V("Block"), ["DoStat"] = kw("do") * V("Block") * expect(kw("end"), "EndDo") / tagDo, ["WhileStat"] = tagC("While", kw("while") * expect(V("Expr"), "ExprWhile") * V("WhileBody")), ["WhileBody"] = expect(kw("do"), "DoWhile") * V("Block") * expect(kw("end"), "EndWhile"), ["RepeatStat"] = tagC("Repeat", kw("repeat") * V("Block") * expect(kw("until"), "UntilRep") * expect(V("Expr"), "ExprRep")), ["ForStat"] = kw("for") * expect(V("ForNum") + V("ForIn"), "ForRange") * expect(kw("end"), "EndFor"), ["ForNum"] = tagC("Fornum", V("Id") * sym("=") * V("NumRange") * V("ForBody")), ["NumRange"] = expect(V("Expr"), "ExprFor1") * expect(sym(","), "CommaFor") * expect(V("Expr"), "ExprFor2") * (sym(",") * expect(V("Expr"), "ExprFor3")) ^ - 1, ["ForIn"] = tagC("Forin", V("NameList") * expect(kw("in"), "InFor") * expect(V("ExprList"), "EListFor") * V("ForBody")), ["ForBody"] = expect(kw("do"), "DoFor") * V("Block"), ["LocalStat"] = kw("local") * expect(V("LocalFunc") + V("LocalAssign"), "DefLocal"), ["LocalFunc"] = tagC("Localrec", kw("function") * expect(V("Id"), "NameLFunc") * V("FuncBody")) / fixFuncStat, ["LocalAssign"] = tagC("Local", V("NameList") * (sym("=") * expect(V("ExprList"), "EListLAssign") + Ct(Cc()))), ["LetStat"] = kw("let") * expect(V("LetAssign"), "DefLet"), ["LetAssign"] = tagC("Let", V("NameList") * (sym("=") * expect(V("ExprList"), "EListLAssign") + Ct(Cc()))), ["Assignment"] = tagC("Set", V("VarList") * V("BinOp") ^ - 1 * (sym("=") / "=") * V("BinOp") ^ - 1 * expect(V("ExprList"), "EListAssign")), ["FuncStat"] = tagC("Set", kw("function") * expect(V("FuncName"), "FuncName") * V("FuncBody")) / fixFuncStat, ["FuncName"] = Cf(V("Id") * (sym(".") * expect(V("StrId"), "NameFunc1")) ^ 0, insertIndex) * (sym(":") * expect(V("StrId"), "NameFunc2")) ^ - 1 / markMethod, ["FuncBody"] = tagC("Function", V("FuncParams") * V("Block") * expect(kw("end"), "EndFunc")), ["FuncParams"] = expect(sym("("), "OParenPList") * V("ParList") * expect(sym(")"), "CParenPList"), ["ParList"] = V("NamedParList") * (sym(",") * expect(tagC("Dots", sym("...")), "ParList")) ^ - 1 / addDots + Ct(tagC("Dots", sym("..."))) + Ct(Cc()), ["NamedParList"] = tagC("NamedParList", commaSep(V("NamedPar"))), ["NamedPar"] = tagC("ParPair", V("ParKey") * expect(sym("="), "EqField") * expect(V("Expr"), "ExprField")) + V("Id"), ["ParKey"] = V("Id") * # ("=" * - P("=")), ["LabelStat"] = tagC("Label", sym("::") * expect(V("Name"), "Label") * expect(sym("::"), "CloseLabel")), ["GoToStat"] = tagC("Goto", kw("goto") * expect(V("Name"), "Goto")), ["BreakStat"] = tagC("Break", kw("break")), ["ContinueStat"] = tagC("Continue", kw("continue")), ["RetStat"] = tagC("Return", kw("return") * commaSep(V("Expr"), "RetList") ^ - 1 * sym(";") ^ - 1), ["ImplicitRetStat"] = tagC("Return", commaSep(V("Expr"), "RetList") * sym(";") ^ - 1), ["NameList"] = tagC("NameList", commaSep(V("Id"))), ["VarList"] = tagC("VarList", commaSep(V("VarExpr"), "VarList")), ["ExprList"] = tagC("ExpList", commaSep(V("Expr"), "ExprList")), ["Expr"] = V("OrExpr"), ["OrExpr"] = chainOp(V("AndExpr"), V("OrOp"), "OrExpr"), ["AndExpr"] = chainOp(V("RelExpr"), V("AndOp"), "AndExpr"), ["RelExpr"] = chainOp(V("BOrExpr"), V("RelOp"), "RelExpr"), ["BOrExpr"] = chainOp(V("BXorExpr"), V("BOrOp"), "BOrExpr"), ["BXorExpr"] = chainOp(V("BAndExpr"), V("BXorOp"), "BXorExpr"), ["BAndExpr"] = chainOp(V("ShiftExpr"), V("BAndOp"), "BAndExpr"), ["ShiftExpr"] = chainOp(V("ConcatExpr"), V("ShiftOp"), "ShiftExpr"), ["ConcatExpr"] = V("AddExpr") * (V("ConcatOp") * expect(V("ConcatExpr"), "ConcatExpr")) ^ - 1 / binaryOp, ["AddExpr"] = chainOp(V("MulExpr"), V("AddOp"), "AddExpr"), ["MulExpr"] = chainOp(V("UnaryExpr"), V("MulOp"), "MulExpr"), ["UnaryExpr"] = V("UnaryOp") * expect(V("UnaryExpr"), "UnaryExpr") / unaryOp + V("PowExpr"), ["PowExpr"] = V("SimpleExpr") * (V("PowOp") * expect(V("UnaryExpr"), "PowExpr")) ^ - 1 / binaryOp, ["SimpleExpr"] = tagC("Number", V("Number")) + tagC("String", V("String")) + tagC("Nil", kw("nil")) + tagC("Boolean", kw("false") * Cc(false)) + tagC("Boolean", kw("true") * Cc(true)) + tagC("Dots", sym("...")) + V("FuncDef") + V("Table") + V("SuffixedExpr") + V("StatExpr"), ["StatExpr"] = (V("IfStat") + V("DoStat") + V("WhileStat") + V("RepeatStat") + V("ForStat")) / statToExpr, ["FuncCall"] = Cmt(V("SuffixedExpr"), function(s, i, exp) return exp["tag"] == "Call" or exp["tag"] == "Invoke", exp end), ["VarExpr"] = Cmt(V("SuffixedExpr"), function(s, i, exp) return exp["tag"] == "Id" or exp["tag"] == "Index", exp diff --git a/compiler/lua53.can b/compiler/lua53.can index 4314d35..75906b0 100644 --- a/compiler/lua53.can +++ b/compiler/lua53.can @@ -316,6 +316,30 @@ return function(code, ast, options) Paren = (t) return "(" .. lua(t[1]) .. ")" end, + -- DoExpr{ stat* } + DoExpr = (t) + return "(function()" .. indent() .. lua(t, "Do") .. unindent() .. "end)()" + end, + -- WhileExpr{ expr block } + WhileExpr = (t) + return "(function()" .. indent() .. lua(t, "While") .. unindent() .. "end)()" + end, + -- RepeatExpr{ expr block } + RepeatExpr = (t) + return "(function()" .. indent() .. lua(t, "Repeat") .. unindent() .. "end)()" + end, + -- IfExpr{ (expr block)+ block? } + IfExpr = (t) + return "(function()" .. indent() .. lua(t, "If") .. unindent() .. "end)()" + end, + -- FornumExpr{ ident expr expr expr? block } + FornumExpr = (t) + return "(function()" .. indent() .. lua(t, "Fornum") .. unindent() .. "end)()" + end, + -- Forin{ {ident+} {expr+} block } + ForninExpr = (t) + return "(function()" .. indent() .. lua(t, "Forin") .. unindent() .. "end)()" + end, -- apply (below) -- lhs (below) diff --git a/ideas.txt b/ideas.txt index 93f7bcb..6eed337 100644 --- a/ideas.txt +++ b/ideas.txt @@ -20,7 +20,7 @@ Example rejected ideas: Of course, if you really thinks these would be useful or you found a clever way of making theses work, feel free to open an issue or pull request and discuss. -Most of Candran's additions were inspired by MoonScript and CoffeeScript. +Most of Candran's additions were inspired by MoonScript, CoffeeScript, and Lilia (https://love2d.org/forums/viewtopic.php?f=3&t=82650&sid=b6d9a8dec64afcc1c67806cb5ba65458). Please note that the following ideas are just random though and won't be necessarly implemented, and some won't even work together. @@ -45,7 +45,7 @@ local a = [x for x in pairs(stuff)] local a = [x for x in pairs(stuff) if x == true] local a = [x for x in pairs(stuff) if x == true for...] local a = x for x in pairs(stuff) -local a = for x in pairs(stuff) do x +local a = for x in pairs(stuff) do x end local no_color = {k,v for k,v in pairs(thing) if k ~= "color"} local a = (x if x == true) @@ -61,23 +61,6 @@ end)() foo() if stuff > other end -* block expressions -local a = do - return true -end --> -local a = (() - return true -end)() - -local a = if x == true then - return a -end - -With implicits returns?... - -local stuff = for ... (accumulate in a table) - * try / except|catch / finally / else / other keywords try error("hey") @@ -125,7 +108,6 @@ And in implicit assignments: for i, {x, y} in ipairs(positions) do * Other potential inspiration -https://love2d.org/forums/viewtopic.php?f=3&t=82650&sid=b6d9a8dec64afcc1c67806cb5ba65458 https://www.ruby-lang.org/fr/ Well done, you're at the end of the file! diff --git a/lib/lua-parser/parser.lua b/lib/lua-parser/parser.lua index a599220..f6fdcc5 100644 --- a/lib/lua-parser/parser.lua +++ b/lib/lua-parser/parser.lua @@ -268,6 +268,11 @@ local function fixAnonymousMethodParams(t1, t2) return t1 end +local function statToExpr(t) + t.tag = t.tag .. "Expr" + return t +end + -- grammar local G = { V"Lua", Lua = V"Shebang"^-1 * V"Skip" * V"Block" * expect(P(-1), "Extra"); @@ -353,7 +358,10 @@ local G = { V"Lua", + tagC("Dots", sym("...")) + V"FuncDef" + V"Table" - + V"SuffixedExpr"; + + V"SuffixedExpr" + + V"StatExpr"; + + StatExpr = (V"IfStat" + V"DoStat" + V"WhileStat" + V"RepeatStat" + V"ForStat") / statToExpr; FuncCall = Cmt(V"SuffixedExpr", function(s, i, exp) return exp.tag == "Call" or exp.tag == "Invoke", exp end); VarExpr = Cmt(V"SuffixedExpr", function(s, i, exp) return exp.tag == "Id" or exp.tag == "Index", exp end);