diff --git a/moonscript/compile.lua b/moonscript/compile.lua index fc66fea..522f27b 100644 --- a/moonscript/compile.lua +++ b/moonscript/compile.lua @@ -29,6 +29,8 @@ local moonlib = { end } +local must_return = data.Set{ 'parens', 'exp', 'value', 'string', 'table', 'fndef' } + local compiler_index = { push = function(self) self._scope:push{} end, pop = function(self) self._scope:pop() end, @@ -37,7 +39,7 @@ local compiler_index = { self._indent = self._indent + amount end, - pretty = function(self, tbl) + pretty = function(self, tbl, indent_front) local out = {} for _, line in ipairs(tbl) do if type(line) == "table" then @@ -48,7 +50,12 @@ local compiler_index = { table.insert(out, line) end end - return table.concat(out, "\n"..self:ichar()) + + local block = table.concat(out, "\n"..self:ichar()) + if indent_front then + block = self:ichar()..block + end + return block end, has_name = function(self, name) @@ -181,24 +188,25 @@ local compiler_index = { local out if #block == 0 then out = ("function(%s) end"):format(args) - elseif #block == 1 then - out = ("function(%s) %s end"):format(args, self:value(block[1])) + elseif #block == 1 and must_return[ntype(block[1])] then + out = ("function(%s) %s end"):format(args, self:block(block, true, 0)) else out = ("function(%s)\n%s\n%send"):format( - args, self:block(block, 1), self:ichar()) + args, self:block(block, true), self:ichar()) end self:pop() return out end, - ["if"] = function(self, node) + -- compile if + ["if"] = function(self, node, return_value) local cond, block = node[2], node[3] local ichr = self:ichar() local out = { ("if %s then"):format(self:value(cond)), - self:block(block, 1) + self:block(block, return_value) } for i = 4,#node do @@ -213,7 +221,7 @@ local compiler_index = { else error("Unknown if clause: "..clause[1]) end - table.insert(out, self:block(block, 1)) + table.insert(out, self:block(block, return_value)) end table.insert(out, ichr.."end") @@ -225,7 +233,8 @@ local compiler_index = { local _, cond, block = unpack(node) local ichr = self:ichar() - return ("while %s do\n%s\n%send"):format(self:value(cond), self:block(block, 1), ichr) + return ("while %s do\n%s\n%send"):format(self:value(cond), + self:block(block, nil, 1), ichr) end, name_list = function(self, node) @@ -267,17 +276,25 @@ local compiler_index = { } end, - block = function(self, node, inc) + block = function(self, node, return_value, inc) + inc = inc or 1 + self:push() - if inc then self:indent(inc) end + self:indent(inc) local lines = {} - local i = self:ichar() - for _, ln in ipairs(node) do - table.insert(lines, i..self:value(ln)) + local len = #node + for i=1,len do + local ln = node[i] + local value = self:stm(ln, return_value and i == len) + if type(value) == "table" then + for _, v in value do + table.insert(lines, value) + end + else + table.insert(lines, value) + end end - if inc then self:indent(-inc) end - self:pop() -- add semicolons where they might be needed for i, left, k, right in itwos(lines) do @@ -286,7 +303,12 @@ local compiler_index = { end end - return table.concat(lines, "\n") + local out = self:pretty(lines, true) + + self:indent(-inc) + self:pop() + + return out end, table = function(self, node) @@ -376,18 +398,35 @@ local compiler_index = { return delim..inner..(delim_end or delim) end, - value = function(self, node) + value = function(self, node, ...) + if return_value == nil then return_value = true end + if type(node) == "table" then local fn = self[node[1]] if not fn then error("Unknown op: "..tostring(node[1])) end - return fn(self, node) + return fn(self, node, ...) end return node end, + -- has no return value, meant to be on line of it's own + stm = function(self, node, return_value) + local value = self:value(node, return_value) + + if must_return[ntype(node)] then + if return_value then + return "return "..value + else + return self:value({"assign", {"_"}, {value}}, false) + end + end + + return value + end, + minus = function(self, node) local _, value = unpack(node) return "-"..self:value(value) @@ -428,7 +467,7 @@ end function tree(tree) local compiler = build_compiler() - return compiler:block(tree) + return compiler:block(tree, false, 0) end diff --git a/moonscript/data.lua b/moonscript/data.lua index 01d952e..3dd3104 100644 --- a/moonscript/data.lua +++ b/moonscript/data.lua @@ -29,3 +29,11 @@ function Stack(...) return self end +function Set(items) + local self = {} + for _,item in ipairs(items) do + self[item] = true + end + return self +end + diff --git a/tests/outputs/assign.lua b/tests/outputs/assign.lua index 572d904..4b5645b 100644 --- a/tests/outputs/assign.lua +++ b/tests/outputs/assign.lua @@ -1,6 +1,6 @@ -function() +local _ = function() local joop = 2302 - function(hi) + return function(hi) local d = 100 hi = 1021 local a, b, c = 1, 2, 3 diff --git a/tests/outputs/cond.lua b/tests/outputs/cond.lua index 9230d15..b1a86c9 100644 --- a/tests/outputs/cond.lua +++ b/tests/outputs/cond.lua @@ -1,25 +1,25 @@ local you_cool = false if cool then if you_cool then - one + local _ = one else if eatdic then - yeah + local _ = yeah else - two - three + local _ = two + _ = three end end else - no + local _ = no end if cool then - no + local _ = no end if cool then - no + local _ = no else - yes + local _ = yes end if cool then wow(cool) @@ -29,12 +29,12 @@ end if working then if cool then if cool then - okay + local _ = okay else - what + local _ = what end else - nah + local _ = nah end end while true do @@ -46,7 +46,7 @@ while 5 + 5 do end while also do i(work(too)) - "okay" + local _ = "okay" end if yeah then no(day) diff --git a/tests/outputs/lists.lua b/tests/outputs/lists.lua index 8165ea5..beddb58 100644 --- a/tests/outputs/lists.lua +++ b/tests/outputs/lists.lua @@ -62,13 +62,17 @@ end)(); return tmp end)() require("util") -local dump = function(x) print(util.dump(x)) end +local dump = function(x) + print(util.dump(x)) +end local range = function(count) local i = 0 - return(coroutine.wrap(function() while i < count do - coroutine.yield(i) - i = i + 1 - end end)) + return(coroutine.wrap(function() + while i < count do + coroutine.yield(i) + i = i + 1 + end + end)) end dump((function() local tmp = {} diff --git a/tests/outputs/syntax.lua b/tests/outputs/syntax.lua index cffd1b9..171389c 100644 --- a/tests/outputs/syntax.lua +++ b/tests/outputs/syntax.lua @@ -1,13 +1,19 @@ -local x = function() print(what) end -function() end -function() function() function() end end end +local x = function() + print(what) +end +local _ = function() end +_ = function() return function() return function() end end end go(to(the(barn))) -open(function() the(function() door end) end) +open(function() + the(function() return door end) +end) open(function() the(door) - local hello = function() my(func) end + local hello = function() + my(func) + end end) -local h = function() hi end +local h = function() return hi end eat(function() end, world) local a = 1 + 2 * 3 / 6 a = another @@ -15,7 +21,7 @@ local bunch, go, here = world func(arg1, arg2, another, arg3) here = function() end local we = yeah -local the, different = function() approach end, yeah +local the, different = function() return approach end, yeah dad() dad(lord) hello(one, two)(); @@ -34,25 +40,31 @@ yeah = ((1 + 5) * 3) / 2 yeah = ((1 + 5) * 3) / 2 + i % 100 local whoa = (1 + 2) * (3 + 4) * (4 + 5); (function() end)() -return(5 + function() 4 + 2 end) -return(5 + (function() 4 end) + 2) +return(5 + function() return 4 + 2 end) +return(5 + (function() return 4 end) + 2) print(5 + function() - 34 + _ = 34 good(nads) end) something('else', "ya") something('else') something("else") here(we)("go")[12123] -local something = { test = 12323, what = function() print("hello world") end } +local something = { test = 12323, what = function() + print("hello world") + end } print(something.test) local frick = { hello = "world" } local argon = { num = 100, world = function(self) print(self.num) - return({ something = function() print("hi from something") end }) + return({ something = function() + print("hi from something") + end }) end, somethin = function(self,str) print("string is", str) - return({ world = function(a,b) print("sum", a + b) end }) + return({ world = function(a,b) + print("sum", a + b) + end }) end } something.what() argon:world().something() @@ -70,19 +82,21 @@ end)() if cool then print("hello") else - cool + _ = cool end print("nutjob") if hello then - 343 + _ = 343 end if cool then print("what") else - cool + _ = cool end local arg = { ... } -x = function(...) dump({ ... }) end +x = function(...) + dump({ ... }) +end x = not true local y = not (5 + 5) y = #"hello"