From 9dea1c26b487ae723d99ba1e5e5887b09aec87dd Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 26 May 2024 13:06:12 -0300 Subject: Fix Lua 5.1 support and add tests --- .gitignore | 2 ++ build.sh | 5 ++++ cratera.lua | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cratera/init.lua | 83 -------------------------------------------------------- testbc.lua | 29 ++++++++++++++++++++ 5 files changed, 119 insertions(+), 83 deletions(-) create mode 100644 .gitignore create mode 100755 build.sh create mode 100644 cratera.lua delete mode 100644 cratera/init.lua create mode 100644 testbc.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..731e4eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/out/ +/testsdump.cratera diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..173fe8c --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +mkdir -p out/cratera/ +# worst tool for this job +cp -r cratera/* out/cratera/ +cp cratera.lua out/cratera/init.lua diff --git a/cratera.lua b/cratera.lua new file mode 100644 index 0000000..6c0335b --- /dev/null +++ b/cratera.lua @@ -0,0 +1,83 @@ +--[[ + Cratera Compiler - 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 . +--]] + +-- This code is highly experimental and not very good + +local parser = require "cratera.parser" +local luatokens = require "cratera.luatokens" +local compiler = require "cratera.compiler" + +local LUA_SIGNATURE = string.dump(function() end):sub(1,1) + +local function cratera_load(reader, ...) + if type(reader) == "string" and reader:sub(1,1) == LUA_SIGNATURE then + -- bytecode + return (loadstring or load)(reader, ...) + end + local f, s, i = parser.stream(luatokens.defs, reader) + if type(s[parser.DATA]) == "string" and s[parser.DATA]:sub(1,1) == LUA_SIGNATURE then + -- bytecode + local function fn() + fn = reader + return s[parser.DATA] + end + return (load)(function() return fn() end, ...) + end + local nl = 1 + local otherstate = {} -- needed to match linenumbers + local f, s, i = parser.stream(compiler.defs, function() + local tokens + repeat + local pos, state, transemsg, etoken, estate = f(s, i) + otherstate.linenumber = state.line + i = pos + if not i then return nil end + if not state then error(transemsg) end + tokens = {} + for i,v in ipairs(state) do + state[i] = nil + tokens[i] = v + end + until #tokens > 0 or not transemsg + return tokens + end, otherstate) + local function fn() + function fn() + local tokens + repeat + local pos, state, transemsg, etoken, estate, est = f(s, i) + i = pos + if not i then return nil end + if not state then error(transemsg .. " " .. tostring(etoken)) end + tokens = {""} + for i,v in ipairs(state) do + state[i] = nil + tokens[i+1] = v + end + until #tokens > 1 or not transemsg + return table.concat(tokens, " ") + end + local ret = fn() + return string.sub(ret, 2) + end + return load(function() + return fn() + end, ...) +end + +return {load = cratera_load} diff --git a/cratera/init.lua b/cratera/init.lua deleted file mode 100644 index a07068e..0000000 --- a/cratera/init.lua +++ /dev/null @@ -1,83 +0,0 @@ ---[[ - Cratera Compiler - 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 . ---]] - --- This code is highly experimental and not very good - -local parser = require "cratera.parser" -local luatokens = require "cratera.luatokens" -local compiler = require "cratera.compiler" - -local LUA_SIGNATURE = string.dump(function() end):sub(1,1) - -local function cratera_load(reader, ...) - if type(reader) == "string" and reader:sub(1,1) == LUA_SIGNATURE then - -- bytecode - return (loadstring or load)(reader, ...) - end - local f, s, i = parser.stream(luatokens.defs, reader) - if type(s[parser.DATA]) == "string" and s[parser.DATA]:sub(1,1) == LUA_SIGNATURE then - -- bytecode - local function fn() - fn = reader - return s[parser.DATA] - end - return (loadstring or load)(function() return fn() end, ...) - end - local nl = 1 - local otherstate = {} -- needed to match linenumbers - local f, s, i = parser.stream(compiler.defs, function() - local tokens - repeat - local pos, state, transemsg, etoken, estate = f(s, i) - otherstate.linenumber = state.line - i = pos - if not i then return nil end - if not state then error(transemsg) end - tokens = {} - for i,v in ipairs(state) do - state[i] = nil - tokens[i] = v - end - until #tokens > 0 or not transemsg - return tokens - end, otherstate) - local function fn() - function fn() - local tokens - repeat - local pos, state, transemsg, etoken, estate, est = f(s, i) - i = pos - if not i then return nil end - if not state then error(transemsg .. " " .. tostring(etoken)) end - tokens = {""} - for i,v in ipairs(state) do - state[i] = nil - tokens[i+1] = v - end - until #tokens > 1 or not transemsg - return table.concat(tokens, " ") - end - local ret = fn() - return string.sub(ret, 2) - end - return load(function() - return fn() - end, ...) -end - -return {load = cratera_load} diff --git a/testbc.lua b/testbc.lua new file mode 100644 index 0000000..7b4a6e2 --- /dev/null +++ b/testbc.lua @@ -0,0 +1,29 @@ +local cratera = require "cratera" + +local function stream(filename, mode) + local file, err = io.open(filename, mode) + if not file then return nil, err end + return function() + local data, err = file:read(8192) + if not data then file:close() return nil, err end + return data + end +end + +-- load tests, streaming +local tests = assert(cratera.load(stream("tests.cratera", "rb"))) + +-- dump tests +local testsdump = string.dump(tests) + +-- check if cratera can load them +assert(cratera.load(testsdump))() + +-- output to a file +local file = io.open("testsdump.cratera", "wb") +assert(file:write(testsdump)) +assert(file:flush()) +assert(file:close()) + +-- load again, streaming, precompiled, and from a file +assert(cratera.load(stream("testsdump.cratera", "rb")))() -- cgit 1.4.1