lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 30 January 2014 18:43, Fabien <fleutot+lua@gmail.com> wrote:
Not that hard. There are 3 extensions in Metalua wrt Lua 5.1: `Label{ }, `Goto{ } and `Stat{ }. The two formers are in Lua 5.2 and LuaJIT2, so we're only left with the latter, which allows to put a statement where an _expression_ was expected.

`Stat{ block, expr } is an _expression_ which executes block and evaluates to expr in block's scope (same principle as with repeat block until expr). It's intended for macros, not for regular code. It can be encoded as: +{ (function() -{block}; return -{expr} end)() }. This is incorrect in Lua 5.1 because of interferences between functions and getfenv/setfenv, but I've understood that these have been dropped from Lua 5.2 and LuaJIT2. And I seem to remember that LuaJIT was pretty good at inlining functions, so there won't even be a performance penalty.

One last trick would be to make gensym() generate legal variable names, but that's trivial as long as we agree on a reserved prefix.

I experimented with this, and with some simple changes it is possible to preprocess Metalua source such that it is "digestible" by LuaJIT (it should be simple to add the `Stat).

I used the simple driver program to successfully parse the sources in "metalua/extensions":

lua metalua_preprocess.lua metalua/extensions/match.mlua | luajit

They were parsed without errors with the changes, running some of them failed because they references 'mlua' files, which LuaJIT failed to find.


diff --git a/metalua/compiler/ast_to_src.mlua b/metalua/compiler/ast_to_src.mlua
index 9054088..03c632e 100644
--- a/metalua/compiler/ast_to_src.mlua
+++ b/metalua/compiler/ast_to_src.mlua
@@ -602,6 +602,13 @@ function M:Index (node, table, key)
    end
 end
 
+local function to_ident(name)
+  if type(name) == "table" and name.tag == "Id" then
+    return name[1]
+  end
+  return name
+end
+
 function M:Id (node, name)
    if is_ident (name) then
       self:acc (name)
@@ -613,6 +620,14 @@ function M:Id (node, name)
    end
 end
 
+function M:Label(node, name)
+  self:acc("::" .. to_ident(name) .. "::")
+end
+
+function M:Goto(node, name)
+  self:acc("goto " .. to_ident(name))
+end
+
 
 M.TDyn    = '*'
 M.TDynbar = '**'
diff --git a/metalua/grammar/generator.lua b/metalua/grammar/generator.lua
index 2680d8a..e6d7557 100644
--- a/metalua/grammar/generator.lua
+++ b/metalua/grammar/generator.lua
@@ -61,7 +61,8 @@ local gensymidx = 0
 
 function M.gensym (arg)
    gensymidx = gensymidx + 1
-   return { tag="Id", string.format(".%i.%s", gensymidx, arg or "")}
+   return { tag="Id", string.format("__TMP_%i_%s", gensymidx,
+    arg and arg:gsub("[^%w]", "_") or "")}
 end
 
 
require 'metalua.loader'
local c = require 'metalua.compiler'.new()
local ast = assert(c:srcfile_to_ast(arg[1]))
io.write(c:ast_to_src(ast))