summary refs log tree commit diff stats
path: root/compiler.lua
diff options
context:
space:
mode:
Diffstat (limited to 'compiler.lua')
-rw-r--r--compiler.lua239
1 files changed, 239 insertions, 0 deletions
diff --git a/compiler.lua b/compiler.lua
new file mode 100644
index 0000000..d67f9ec
--- /dev/null
+++ b/compiler.lua
@@ -0,0 +1,239 @@
+--[[
+    This file is part of cratera.lua - pure-Lua Cratera-to-Lua transpiler
+    Copyright (C) 2019  Soni L.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+--]]
+
+--[[
+    This software is based on Lua 5.1 and Lua 5.3
+
+    Lua 5.1 license:
+
+/******************************************************************************
+* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+    Lua 5.3 license:
+
+/******************************************************************************
+* Copyright (C) 1994-2018 Lua.org, PUC-Rio.
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+--]]
+
+-- a parser.lua-based cratera compiler
+-- a few notes:
+-- * all "next" should be tables. as well as all "super" (which should be "next").
+--   (it wouldn't work properly without this)
+-- * when calling into a deeper level, remember to use the second return value "retry"
+--   (i.e. set it to true)
+
+local parser = require "parser"
+local selfify = parser.selfify
+local STATE = parser.STATE
+local l = require "luatokens".tokens
+local assert, type, setmetatable = assert, type, setmetatable
+
+local function tostring__name(self)
+    return getmetatable(self).__name
+end
+
+local function Upvaldesc() return {
+    name = nil, -- TString -- upvalue name (for debug information)
+    instack = false, -- lu_byte -- whether it is in stack (register)
+    idx = 0, -- lu_byte -- index of upvalue (in stack or in outer function's list)
+} end
+local function LocVar() return {
+    varname = nil, -- TString
+    startpc = 0, -- int -- first point where variable is active
+    endpc = 0, -- int -- first point where variable is dead
+} end
+local function Proto() return { -- is a GC object
+    numparams = 0, -- lu_byte -- number of fixed parameters
+    is_vararg = false, -- lu_byte but boolean
+    maxstacksize = 0, -- lu_byte -- number of registers needed by this function
+    k = {}, -- TValue * -- constants used by the function
+    code = {}, -- Instruction * -- opcodes
+    p = {}, -- Proto ** -- functions defined inside the function
+    lineinfo = {}, -- int * -- map from opcodes to source lines (debug information)
+    locvars = {}, -- LocVar * -- information about local variables (debug information)
+    uvalues = {}, -- Upvaldesc * -- upvalue information
+} end
+local function FuncState() return {
+    f = nil, -- Proto -- current function header
+    prev = nil, -- FuncState -- enclosing function
+    ls = nil, -- LexState -- lexical state
+    bl = nil, -- BlockCnt -- chain of current blocks
+    pc = 0, -- int -- next position to code (equivalent to 'ncode')
+    lasttarget = 0, -- int -- 'label' of last 'jump label'
+    jpc = 0, -- int -- number of pending jumps to 'pc'
+    --nk = 0, -- int -- number of elements in 'k'
+    --np = 0, -- int -- number of elements in 'p'
+    firstlocal = 0, -- int -- index of first local var (in Dyndata array)
+    nlocvars = 0, -- short -- number of elements in 'f->locvars'
+    nactvar = 0, -- lu_byte -- number of active local variables
+    nups = 0, -- lu_byte -- number of upvalues
+    freereg = 0, -- lu_byte -- first free register
+} end
+local function Labeldesc() return {
+    name = nil, -- TString -- label identifier
+    pc = nil, -- int -- position in code
+    line = nil, -- int -- line where it appeared
+    nactvar = nil, -- lu_byte -- local level where it appears in current block
+} end
+local function Dyndata() return {
+    actvar = {}, -- ArrayList of Vardesc (short) -- list of active local variables
+    gt = {}, -- Labellist (ArrayList of Labeldesc) -- list of pending gotos
+    label = {}, -- Labellist (ArrayList of Labeldesc) -- list of active labels
+} end
+local function ParserState() return { -- LexState
+    fs = nil, -- FuncState *
+    dyd = nil, -- Dyndata *
+} end
+
+local gotostatname = {[parser.EOZ] = false}
+local gotostatnamemt = {__index=gotostatname, __name="gotostatname", __tostring=tostring__name}
+gotostatname[parser.FALLBACK] = function(state, token)
+    assert(type(token) == "string")
+    state[#state+1] = "goto"
+    state[#state+1] = token
+    return state[STATE].next
+end
+
+local gotostat = {[parser.EOZ] = false}
+local gotostatmt = {__index=gotostat, __name="gotostat", __tostring=tostring__name}
+gotostat[l.TK_NAME] = function(state, token)
+    return setmetatable({next = state[STATE].next}, gotostatnamemt)
+end
+
+local singlevar = {[parser.EOZ] = false}
+local singlevarmt = {__index=singlevar, __name="singlevar", __tostring=tostring__name}
+singlevar[parser.FALLBACK] = function(state, token)
+    assert(type(token) == "string")
+    state[#state+1] = token
+    return state[STATE].next
+end
+
+local primaryexp = {[parser.EOZ] = false}
+local primaryexpmt = {__name="primaryexp", __tostring=tostring__name}
+primaryexp['('] = function(state, token) end
+primaryexp[l.TK_NAME] = function(state, token)
+    return setmetatable({next=state[STATE].next}, singlevarmt)
+end
+
+local suffixedexp = {}
+local suffixedexpmt = {__name="suffixedexp", __tostring=tostring__name}
+suffixedexp.next = function() end
+
+local exprstat = {}
+local exprstatmt = {__index=exprstat, __name="exprstat", __tostring=tostring__name}
+exprstat.next = {}
+
+local statementt = {[parser.EOZ] = false}
+local statementmt = {__index=statementt, __name="statement", __tostring=tostring__name}
+local function statement(state, token)
+    local cur = state[STATE]
+    return setmetatable({next = cur.next}, statementmt), true
+end
+statementt[";"] = function(state, token)
+    state[#state+1] = token
+    return "next"
+end
+statementt[l.TK_IF] = function(state, token) end
+statementt[l.TK_WHILE] = function(state, token) end
+statementt[l.TK_DO] = function(state, token) end
+statementt[l.TK_FOR] = function(state, token) end
+statementt[l.TK_REPEAT] = function(state, token) end
+statementt[l.TK_FUNCTION] = function(state, token) end
+statementt[l.TK_LOCAL] = function(state, token) end
+statementt[l.TK_DBCOLON] = function(state, token) end
+statementt[l.TK_RETURN] = function(state, token) end
+statementt[l.TK_BREAK] = function(state, token)
+    state[#state+1] = "break"
+    return "next"
+end
+statementt[l.TK_GOTO] = function(state, token)
+    return setmetatable({next = state[STATE].next}, gotostatmt)
+end
+statementt[parser.FALLBACK] = function(state, token)
+    return setmetatable({super = state[STATE].next}, exprstatmt), true
+end
+
+local statlistt = {}
+local statlistmt = {__index=statlistt, __name="statlist", __tostring=tostring__name}
+local function statlist(state, token)
+    local cur = state[STATE]
+    return setmetatable(selfify({super = cur.next, withuntil = cur.withuntil}, "next"), statlistmt), true
+end
+statlistt[l.TK_ELSE] = function() return "super", true end
+statlistt[l.TK_ELSEIF] = function() return "super", true end
+statlistt[l.TK_END] = function() return "super", true end
+statlistt[parser.EOZ] = function() return "super", true end
+statlistt[l.TK_UNTIL] = function() return "withuntil", true end
+statlistt[parser.FALLBACK] = statement
+
+local mainfunc = setmetatable({}, {__name="mainfunc", __tostring=tostring__name})
+mainfunc.withuntil = "super"
+mainfunc[parser.EOZ] = parser.FALLBACK
+mainfunc[parser.FALLBACK] = statlist
+mainfunc.next = {
+    [parser.EOZ] = {}
+}
+
+local defs = setmetatable({}, {__name="defs", __tostring=tostring__name})
+defs[parser.EOZ] = parser.FALLBACK
+defs[parser.FALLBACK] = function(state, token) return mainfunc, true end
+
+
+return {
+    defs = defs,
+}