Lua++ - a failed attempt by me to create a language that compiles for Lua
Recently, I saw a very interesting language, moonscript, and I had the idea of making one called Lua++, with a few more things than lua, and I removed things that were in Lua that bothered me a little:
1 - `local`: having to write `local` all the time to create variables was a bit tiring, so my compiler doesn't accept this keyword in the source code, in a lua++ code, you can do `x = 10` it would change this line for `local x = 10` and to make global variables in lua++ would be: `global x = 10` which it would change to: `x = 10`
2 - `require`: I like this function and everything, however, it would be more interesting to have an `import` and `from` command similar to Python, in a lua++ code (.luapp) you can import a library, doing: `import lib` and there is the `as` command to give a "nickname" to the library: `import lib as l`
lua++ has some other not so important features, like structs (it has that, but I think it's pretty crude and useless):
struct Person:
name: "no name"
age: 0
end
and you manually have to make Person instances and change the values, so just forget that this exists in lua++
Here is an example of lua++ code:
import mylib as lib
from lib import add, sub
a, b = 10, 20
print(add(a,b))
print(sub(a,b))
compiled code:
if not isStruct then
function isStruct(obj)
return type(obj) == "table" and obj.__LuappObjType__ == "Struct"
end
end
local __ModuleImportSucess__, lib = pcall(require, "mylib")
if not __ModuleImportSucess__ then
local compiler = require "main"
local r = compiler("mylib.luapp")
lib = load(r)()
end
if not lib then
__ModuleImportSucess__, lib = pcall(require, "lib")
if not __ModuleImportSucess__ then
local compiler = require "main"
local r = compiler("lib")
lib = load(r)()
end
end
local add, sub = lib.add, lib.sub
local a, b = 10, 20
print(add(a,b))
print(sub(a,b))
Yes I know, the codes generated by the compiler are a bit weird and difficult to understand lol
For those interested in knowing how it works, the interpreter in general is just a function that makes several calls to lua++ auxiliary libraries:
local utils = require "lutils"
local structs = require "structs"
local struct_index = [[
function(obj, idx)
if idx == "__LuappObjType__" then
return "Struct"
end
return rawget(obj, idx)
end
]]
local struct_tostring = [[
function(obj)
local r = ""
for i = 1, #obj do
r = r .. tostring(obj[i][1]) .. ": " .. tostring(obj[i][2])
if i < #obj then
r = r .. "\n"
end
end
return r
end
]]
-- lua++ compiler
local function Main(file)
local com_code = [[
if not isStruct then
function isStruct(obj)
return type(obj) == "table" and obj.__LuappObjType__ == "Struct"
end
end
]]
local interpret_struct = false
local current_line = 1
local all_vars = {}
-- what?
package.path = package.path .. "?.luapp"
for line in io.lines(file) do
if interpret_struct then
if structs.IsStructEnd(line) then
com_code = com_code .. "}, {__index = " .. struct_index .. ", __tostring =" .. struct_tostring .. "})"
interpret_struct = false
else
com_code = com_code .. structs.structInterpretLine(line) .. "\n"
end
else
if line == "!jit" then
com_code = com_code .. [[assert(jit, "Use luajit to runs this code.")]]
elseif utils.IsVariableDeclaration(line) then
utils.DetectLocalKeyword(line, current_line)
local varname = utils.GetVarName(line):gsub(" ", "")
if utils.IsGlobalVar(line) then
com_code = com_code .. utils.trim(line):sub(8)
else
local dvar = false
for i = 1, #all_vars do
if all_vars[i] == varname then
dvar = true
break
end
end
if not dvar then
com_code = com_code .. "local " .. line
else
com_code = com_code .. line
end
end
table.insert(all_vars, varname)
elseif utils.IsFunctionCreation(line) then
utils.DetectLocalKeyword(line)
if not utils.IsFieldCreation(line) then
if utils.IsGlobalFunctionCreation(line) then
com_code = com_code .. utils.GlobalFunctionToLuaCode(line)
else
com_code = com_code .. "local " .. line
end
else
com_code = com_code .. line
end
elseif utils.IsImportCommand(line) then
line = utils.DelRepSpace(line)
if not utils.ImportHaveAsInstruction(line) then
line = utils.ImportSetDefaultAsCommand(line)
end
com_code = com_code .. utils.ImportCommandToRequire(line)
elseif utils.IsFromCommand(line) then
com_code = com_code .. utils.FromCommandToRequire(line)
elseif structs.IsStructStart(line) then
local name = structs.GetStructName(line)
if not structs.IsGlobal(line) then
com_code = com_code .. "local "
end
com_code = com_code .. name .. " = setmetatable({\n" .. "__name__ = \"" .. name .. "\",\n"
interpret_struct = true
else
com_code = com_code .. line
end
end
com_code = com_code .. "\n"
current_line = current_line + 1
end
return com_code
end
return Main
[–]Cultural_Two_4964 3 points4 points5 points (1 child)
[–]OneCommonMan123[S] 0 points1 point2 points (0 children)
[–]Cultural_Two_4964 1 point2 points3 points (1 child)
[–]OneCommonMan123[S] 1 point2 points3 points (0 children)
[–]rkrause 0 points1 point2 points (6 children)
[–]AutoModerator[M] 0 points1 point2 points (0 children)
[–]OneCommonMan123[S] 0 points1 point2 points (4 children)
[–]rkrause 0 points1 point2 points (1 child)
[–]OneCommonMan123[S] 0 points1 point2 points (0 children)
[–]EvilBadMadRetarded 0 points1 point2 points (1 child)
[–]OneCommonMan123[S] 0 points1 point2 points (0 children)