1
0
Fork 0
mirror of https://github.com/Reuh/candran.git synced 2025-10-27 09:59:29 +00:00
Fixed plenty of bugs.

Tests are lacking.
This commit is contained in:
Étienne Fildadut 2017-08-25 19:20:29 +02:00
parent 6b95bfb698
commit d249c353c5
7 changed files with 315 additions and 95 deletions

View file

@ -46,13 +46,15 @@ return function(code, ast, options)
-- Add the module "mod" to the list of modules to require, and load its field "field" (or the whole module if nil) into the variable "name".
local function addRequire(mod, name, field)
if not required[mod] then
requireStr ..= "local " .. options.requirePrefix .. name .. (" = require(%q)"):format(mod) .. (field and "."..field or "") .. options.newline
requireStr ..= "local " .. options.variablePrefix .. name .. (" = require(%q)"):format(mod) .. (field and "."..field or "") .. options.newline
required[mod] = true
end
end
-- Returns the required module variable name.
local function getRequire(name)
return options.requirePrefix .. name
--- Variable management
-- Returns the prefixed variable name.
local function var(name)
return options.variablePrefix .. name
end
--- AST traversal helpers
@ -112,18 +114,27 @@ return function(code, ast, options)
end
return tags[forceTag or ast.tag](ast, ...)
end
-- Tag constructors
--- Lua function calls writer
local UNPACK = (list, i, j) -- table.unpack
return "table.unpack(" .. list .. (i and (", " .. i .. (j and (", " .. j) or "")) or "") .. ")"
end
local APPEND = (t, toAppend) -- append values "toAppend" (multiple values possible) to t
return "do" .. indent() .. "local a = table.pack(" .. toAppend .. ")" .. newline() .. "table.move(a, 1, a.n, #" .. t .. "+1, " .. t .. ")" .. unindent() .. "end"
end
--- Tag constructors
tags = setmetatable({
-- block: { stat* } --
Block = (t)
local hasPush = not peek("push") and any(t, { "Push" }, func) -- push in block and push context not yet defined
local hasPush = peek("push") == nil and any(t, { "Push" }, func) -- push in block and push context not yet defined
if hasPush and hasPush == t[#t] then -- if the first push is the last statement, it's just a return
hasPush.tag = "Return"
hasPush = false
end
local r = ""
if hasPush then
r ..= push("push", "__PUSH__") .. "local __PUSH__ = {}" .. newline()
r ..= push("push", var("push")) .. "local " .. var("push") .. " = {}" .. newline()
end
for i=1, #t-1, 1 do
r ..= lua(t[i]) .. newline()
@ -132,7 +143,7 @@ return function(code, ast, options)
r ..= lua(t[#t])
end
if hasPush and (t[#t] and t[#t].tag ~= "Return") then -- add return only if needed
r ..= newline() .. "return unpack(__PUSH__)" .. pop("push")
r ..= newline() .. "return " .. UNPACK(var("push")) .. pop("push")
end
return r
end,
@ -291,7 +302,7 @@ return function(code, ast, options)
for _, val in ipairs(t) do
r ..= push .. "[#" .. push .. "+1] = " .. lua(val) .. newline()
end
return r .. "return unpack(" .. push .. ")"
return r .. "return " .. UNPACK(push)
else
return "return "..lua(t, "_lhs")
end
@ -299,7 +310,18 @@ return function(code, ast, options)
-- Push{ <expr*> }
Push = (t)
local var = assert(peek("push"), "no context given for push")
return var .. "[#" .. var .. "+1] = " .. lua(t, "_lhs")
r = ""
for i=1, #t-1, 1 do
r ..= var .. "[#" .. var .. "+1] = " .. lua(t[i]) .. newline()
end
if t[#t] then
if t[#t].tag == "Call" or t[#t].tag == "Invoke" then
r ..= APPEND(var, lua(t[#t]))
else
r ..= var .. "[#" .. var .. "+1] = " .. lua(t[#t])
end
end
return r
end,
-- Break
Break = ()
@ -363,7 +385,21 @@ return function(code, ast, options)
for _, d in ipairs(decl) do
r ..= d .. newline()
end
return r .. lua(t[2]) .. unindent() .. "end"
if t[2][#t[2]] and t[2][#t[2]].tag == "Push" then -- convert final push to return
t[2][#t[2]].tag = "Return"
end
local hasPush = any(t[2], { "Push" }, func)
if hasPush then
r ..= push("push", var("push")) .. "local " .. var("push") .. " = {}" .. newline()
else
push("push", false) -- no push here (make sure higher push don't affect us)
end
r ..= lua(t[2])
if hasPush then
r ..= newline() .. "return " .. UNPACK(var("push"))
end
pop("push")
return r .. unindent() .. "end"
end,
Function = (t)
return "function" .. lua(t, "_functionWithoutKeyword")
@ -416,12 +452,15 @@ return function(code, ast, options)
local hasPush = any(t, { "Push" }, func)
local r = "(function()" .. indent()
if hasPush then
r ..= push("push", "__PUSH__") .. "local __PUSH__ = {}" .. newline()
r ..= push("push", var("push")) .. "local " .. var("push") .. " = {}" .. newline()
else
push("push", false) -- no push here (make sure higher push don't affect us)
end
r ..= lua(t, stat)
if hasPush then
r ..= newline() .. "return unpack(__PUSH__)" .. pop("push")
r ..= newline() .. "return " .. UNPACK(var("push"))
end
pop("push")
r ..= unindent() .. "end)()"
return r
end,

View file

@ -1,27 +1,34 @@
tags._opid.idiv = function(left, right)
UNPACK = (list, i, j)
return "unpack(" .. list .. (i and (", " .. i .. (j and (", " .. j) or "")) or "") .. ")"
end
APPEND = (t, toAppend)
return "do" .. indent() .. "local a, p = { " .. toAppend .. " }, #" .. t .. "+1" .. newline() .. "for i=1, #a do" .. indent() .. t .. "[p] = a[i]" .. newline() .. "p = p + 1" .. unindent() .. "end" .. unindent() .. "end"
end
tags._opid.idiv = (left, right)
return "math.floor(" .. lua(left) .. " / " .. lua(right) .. ")"
end
tags._opid.band = function(left, right)
tags._opid.band = (left, right)
addRequire("bit", "band", "band")
return getRequire("band") .. "(" .. lua(left) .. ", " .. lua(right) .. ")"
end
tags._opid.bor = function(left, right)
tags._opid.bor = (left, right)
addRequire("bit", "bor", "bor")
return getRequire("bor") .. "(" .. lua(left) .. ", " .. lua(right) .. ")"
end
tags._opid.bxor = function(left, right)
tags._opid.bxor = (left, right)
addRequire("bit", "bxor", "bxor")
return getRequire("bxor") .. "(" .. lua(left) .. ", " .. lua(right) .. ")"
end
tags._opid.shl = function(left, right)
tags._opid.shl = (left, right)
addRequire("bit", "lshift", "lshift")
return getRequire("lshift") .. "(" .. lua(left) .. ", " .. lua(right) .. ")"
end
tags._opid.shr = function(left, right)
tags._opid.shr = (left, right)
addRequire("bit", "rshift", "rshift")
return getRequire("rshift") .. "(" .. lua(left) .. ", " .. lua(right) .. ")"
end
tags._opid.bnot = function(right)
tags._opid.bnot = (right)
addRequire("bit", "bnot", "bnot")
return getRequire("bnot") .. "(" .. lua(right) .. ")"
end