Skip to content

LuaJIT with custom syntax to support preprocessing, metaprogramming, and functional iteration operator.

Notifications You must be signed in to change notification settings

cyril0124/luajit-pro

Repository files navigation

luajit-pro

luajit-pro is a LuaJIT fork with some extra syntax. It is based on the openresty fork of LuaJIT 2.1.0.

We add an extra syntax transformer on the lj_load.c which contains the entry point of the file loader and string loader of LuaJIT. So the original file will be passed into our custom syntax transformer first and the custom syntax will be tansformed into Lua code which can be further parsed and compiled by LuaJIT later(see lj_load_helper.cpp for the detailed implementaion).

The luaji-pro process the input code in two stage:

  • The first stage is to perform preprocessing, which is done by the cpp tool.
  • The second stage is to perform syntax transformation, which is done by the luaji-pro itself.

The temporary file generated by the luajit-pro is saved in .luajit-pro directory in the current working directory and will be deleted after the program exits.

luajit-pro

Features

luajit-pro adds some extra syntax/feature to LuaJIT, such as:

  • C/C++ like preprocess using cpp command. (make sure that cpp command is available and exist on your PATH)
  • Implement metaprogramming using internal Lua virtual machine.
  • Functional operators foreach, map, filter, zipWithIndex for Lua table, which is inspired by Scala.

Install

To install luajit-pro, you simply need to execute the following command in your terminal:

bash init.sh

The default install path is the luajit2 path itself. You can change the install path by setting the install_dir in install_luajit.sh.

Examples

To enable the extra syntax, we need to add a directive(i.e. "--[[luajit-pro]]") to the Lua code file at fist line.

--[[luajit-pro]]

--
-- Other codes...
--

Preprocess

---[[luajit-pro]]

#define PRINT(X) print(__LINE__, X)

PRINT("HELLO")

#ifdef SOME_MACRO
    print("SOME_MACRO is defined!")
#else
    print("SOME_MACRO is not defined!")
#endif

#include "some_outer_file.lua"

Metaprogramming

The metaprogramming code block is started with $comp_time and the content is inside the {}. The code inside the block will be executed at compile time and the result will be inserted into the original code.

---[[luajit-pro]]

$comp_time {
    f = string.format
    s = ""
    for i = 1, 3 do
        s = s .. f("print(\"from $comp_time\", %d)", i) .. "\n"
    end
    return s -- To successfully insert the generated code, make sure that the generated code is a string and return it.
}

The generated code is:

print("from $comp_time", 1)
print("from $comp_time", 2)
print("from $comp_time", 3)

Functional operators

Notice that the commented codes below the extra syntax codes are the actual generated Lua codes.

foreach

local tbl = {1, 2, 3}

tbl.foreach{ x => 
    local tmp = "tmp"
    print(x, tmp)
}
-- for _, x in ipairs(tbl) do 
--     local tmp = "tmp"
--     print(x, tmp)
-- end

tbl.foreach{print}
-- for _, ref in ipairs(tbl) do print(ref) end


tbl.zipWithIndex.foreach{ (i, x) => 
    print(i, x)
}
-- for i, x in ipairs(tbl) do 
--     print(i, x)
-- end

tbl.foreach.zipWithIndex{ (x, i) =>
    print(i, x)
}
-- for i, x in ipairs(tbl) do 
--     print(i, x)
-- end

map

local tbl = {1, 2, 3}

local result = tbl.map{ x => 
    local tmp = "tmp"
    return tostring(x) .. tmp
}
-- local result = {}; for _, x in ipairs(tbl) do 
--     local tmp = "tmp"
--     _tinsert(result, tostring(x) .. tmp
-- ) end

local function trans(x)
    return x * 2
end

local result2 = tbl.map{trans}
-- local result2 = {}; for _, ref in ipairs(tbl) do _tinsert(result2, trans(ref) ) end

result3 = tbl.zipWithIndex.map{ (i, x) => 
    return i .. x
}
-- result3 = {}; for i, x in ipairs(tbl) do 
--     _tinsert(result3, i .. x
-- ) end

result4 = tbl.map.zipWithIndex{ (x, i) =>
    return i .. x
}
-- result4 = {}; for i, x in ipairs(tbl) do 
--     _tinsert(result4, i .. x
-- ) end

filter

local tbl = {1, 2, 3, 4}

local result = tbl.filter{ x => return x % 2 == 0 }
-- local result = {}; for _, x in ipairs(tbl) do if x % 2 == 0  then _tinsert(result, x) end end

local function filter_func(x)
    return x % 2 == 0
end

local result2 = tbl.filter{filter_func}
-- local result2 = {}; for _, ref in ipairs(tbl) do if filter_func(ref) then _tinsert(result2, ref) end end

result3 = tbl.zipWithIndex.filter{ (i, x) => 
    return i > 2 and x % 2 == 0
}
-- result3 = {}; for i, x in ipairs(tbl) do 
--     if i > 2 and x % 2 == 0
--  then _tinsert(result3, x) end end

result4 = tbl.filter.zipWithIndex{ (x, i) => 
    return i > 2 and x % 2 == 0 
}
-- result4 = {}; for i, x in ipairs(tbl) do 
--     if i > 2 and x % 2 == 0
--  then _tinsert(result4, x) end end

TODO

The code implementation of this repo is too simple and crude, and there is much room for improvement in the future.

  • Add more functional operators.
  • Add more metaprogramming features.
  • Add more preprocess features.
  • Add more examples.

About

LuaJIT with custom syntax to support preprocessing, metaprogramming, and functional iteration operator.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published