lua: Add interop core function lua-eval
authorDov Murik <dov.murik@gmail.com>
Sun, 12 Jun 2016 01:30:44 +0000 (21:30 -0400)
committerDov Murik <dov.murik@gmail.com>
Sun, 12 Jun 2016 01:37:56 +0000 (21:37 -0400)
lua/core.lua
lua/tests/stepA_mal.mal [new file with mode: 0644]

index 05401d1..3376b09 100644 (file)
@@ -5,7 +5,7 @@ local printer = require('printer')
 local readline = require('readline')
 local socket = require('socket')
 
-local Nil, List, _pr_str = types.Nil, types.List, printer._pr_str
+local Nil, List, HashMap, _pr_str = types.Nil, types.List, types.HashMap, printer._pr_str
 
 local M = {}
 
@@ -199,6 +199,40 @@ local function seq(obj, ...)
     return Nil
 end
 
+local function lua_to_mal(a)
+  if a == nil then
+    return Nil
+  elseif type(a) == "boolean" or type(a) == "number" or type(a) == "string" then
+    return a
+  elseif type(a) == "table" then
+    local first_key, _ = next(a)
+    if first_key == nil then
+      return List:new({})
+    elseif type(first_key) == "number" then
+      local list = {}
+      for i, v in ipairs(a) do
+        list[i] = lua_to_mal(v)
+      end
+      return List:new(list)
+    else
+      local hashmap = {}
+      for k, v in pairs(a) do
+        hashmap[lua_to_mal(k)] = lua_to_mal(v)
+      end
+      return HashMap:new(hashmap)
+    end
+  end
+  return tostring(a)
+end
+
+local function lua_eval(str)
+    local f, err = loadstring("return "..str)
+    if err then
+        types.throw("lua-eval: can't load code: "..err)
+    end
+    return lua_to_mal(f())
+end
+
 M.ns = {
     ['='] =  types._equal_Q,
     throw = types.throw,
@@ -263,6 +297,8 @@ M.ns = {
     deref = function(a) return a.val end,
     ['reset!'] = function(a,b) a.val = b; return b end,
     ['swap!'] = swap_BANG,
+
+    ['lua-eval'] = lua_eval,
 }
 
 return M
diff --git a/lua/tests/stepA_mal.mal b/lua/tests/stepA_mal.mal
new file mode 100644 (file)
index 0000000..b52a902
--- /dev/null
@@ -0,0 +1,38 @@
+;; Testing basic Lua interop
+
+;;; lua-eval adds the string "return " to the beginning of the evaluated string
+;;; and supplies that to Lua's loadstring().  If complex programs are needed,
+;;; those can be wrapped by an anonymous function which is called immediately
+;;; (see the foo = 8 example below).
+
+(lua-eval "7")
+;=>7
+
+(lua-eval "'7'")
+;=>"7"
+
+(lua-eval "123 == 123")
+;=>true
+
+(lua-eval "123 == 456")
+;=>false
+
+(lua-eval "{7,8,9}")
+;=>(7 8 9)
+
+(lua-eval "{abc = 789}")
+;=>{"abc" 789}
+
+(lua-eval "print('hello')")
+; hello
+;=>nil
+
+(lua-eval "(function() foo = 8 end)()")
+(lua-eval "foo")
+;=>8
+
+(lua-eval "string.gsub('This sentence has five words', '%w+', function(w) return '*'..#w..'*' end)")
+;=>"*4* *8* *3* *4* *5*"
+
+(lua-eval "table.concat({3, 'a', 45, 'b'}, '|')")
+;=>"3|a|45|b"