]> git.lizzy.rs Git - metalua.git/commitdiff
Merge branch 'master' of git@github.com:fab13n/metalua into cleanup
authorFabien Fleutot <fabien@MacFabien.home>
Tue, 3 Feb 2009 07:20:48 +0000 (08:20 +0100)
committerFabien Fleutot <fabien@MacFabien.home>
Tue, 3 Feb 2009 07:20:48 +0000 (08:20 +0100)
16 files changed:
.gitignore
src/bin/lua.exe [new file with mode: 0644]
src/bin/luac.exe [new file with mode: 0644]
src/compiler/lexer.lua
src/compiler/metalua.mlua
src/compiler/mlc.mlua
src/lib/metalua/extension/match.mlua
src/lib/metalua/extension/trycatch.mlua
src/lib/metalua/mlc_xcall.lua [new file with mode: 0644]
src/lib/metalua/package2.lua
src/make-install.sh [deleted file]
src/make.sh
src/samples/synth.mlua
src/samples/trycatch_test.mlua
src/samples/walk_id_test.mlua
src/samples/weaver.mlua

index 9216ea7ba8fdab08f4b0f6080591005a608f65a4..135852f9c7a6a4d8eee4033b63f94aebe42f9899 100644 (file)
@@ -16,6 +16,7 @@ src/lua/luac
 src/lua/lua
 src/compiler/bootstrap
 src/compiler/metalua
+distrib
 junk
 patches
 ran
diff --git a/src/bin/lua.exe b/src/bin/lua.exe
new file mode 100644 (file)
index 0000000..dc1c2c3
Binary files /dev/null and b/src/bin/lua.exe differ
diff --git a/src/bin/luac.exe b/src/bin/luac.exe
new file mode 100644 (file)
index 0000000..6f87524
Binary files /dev/null and b/src/bin/luac.exe differ
index 39c76a3eb7766365e453713c27d3ad8bd4cd589f..edfa666c620401292c69fe05d8753e67f2278cb2 100644 (file)
@@ -61,10 +61,23 @@ local function unescape_string (s)
 
    -- Turn the digits of an escape sequence into the corresponding
    -- character, e.g. [unesc_digits("123") == string.char(123)].
-   local function unesc_digits (x)
-      local k, j, i = x:reverse():byte(1, 3)
+   local function unesc_digits (backslashes, digits)
+      if #backslashes%2==0 then
+         -- Even number of backslashes, they escape each other, not the digits.
+        -- Return them so that unesc_letter() can treaat them
+        return backslashes..digits
+      else
+         -- Remove the odd backslash, which escapes the number sequence.
+         -- The rest will be returned and parsed by unesc_letter()
+         backslashes = backslashes :sub (1,-2)
+      end
+      local k, j, i = digits:reverse():byte(1, 3)
       local z = _G.string.byte "0"
-      return _G.string.char ((k or z) + 10*(j or z) + 100*(i or z) - 111*z)
+      local code = (k or z) + 10*(j or z) + 100*(i or z) - 111*z
+      if code > 255 then 
+        error ("Illegal escape sequence '\\"..digits.."' in string: ASCII codes must be in [0..255]") 
+      end
+      return backslashes .. string.char (code)
    end
 
    -- Take a letter [x], and returns the character represented by the 
@@ -78,8 +91,8 @@ local function unescape_string (s)
    end
 
    return s
+      :gsub ("(\\+)([0-9][0-9]?[0-9]?)", unesc_digits)
       :gsub ("\\(%D)",unesc_letter)
-      :gsub ("\\([0-9][0-9]?[0-9]?)", unesc_digits)
 end
 
 lexer.extractors = {
index 0620638f7e02490b1082dbb135412e56f2a3f1aa..3c3564d0c37b167e47cf329f27cde1ae0ad92d63 100644 (file)
@@ -4,7 +4,7 @@
 
 require 'metalua.compiler'
 require 'metalua.clopts'
-require 'serialize'
+require 'metalua.mlc_xcall'
 
 AST_COMPILE_ERROR_NUMBER        = -1
 RUNTIME_ERROR_NUMBER            = -3
@@ -12,25 +12,6 @@ BYTECODE_SYNTHESE_ERROR_NUMBER  = -100
 
 -{ extension 'match' }
 
-function spring_pcall (f, arg, name)
-   local pattern = 
-      [=[lua -l metalua.compiler -l serialize -e ]=]..
-      [=["print (serialize (%s ([[%s]], [[%s]])))"]=]
-   local cmd = string.format (pattern, f, arg, name)
-   --print ("Running the following process: " .. cmd)
-   local fd = io.popen (cmd)
-   local ast_src = fd:read '*a'
-   fd:close()
-   --print (data)
-   local ast_builder, msg = lua_loadstring(ast_src)
-   if not ast_builder then 
-      error ("can't compile data: "..msg) 
-      print (ast_src)
-   end
-   local ast = ast_builder()
-   return true, ast
-end
-
 local chunks  = { }
 local runargs = { }
 
@@ -156,10 +137,10 @@ local function main (...)
       local st, ast
       match x with
       | `Library{ l } -> st, ast = true, `Call{ `Id 'require', `String{ l } }
-      | `Literal{ e } -> st, ast = spring_pcall('mlc.ast_of_luastring', e, 'literal')
+      | `Literal{ e } -> st, ast = mlc_xcall.client_literal (e)
       | `File{ f } ->
-         st, ast = spring_pcall('mlc.ast_of_luafile', f, '@'..f)
-         -- Isolate each file in a separate fenv
+         st, ast = mlc_xcall.client_file (f)
+          -- Isolate each file in a separate fenv
          if st then
             ast = +{ function (...) -{ast} end (...)  }
             ast.source  = '@'..f -- TODO [EVE]
index e488546820e0e8dcc1672b0909b5940d898586f3..a3eeb6f6585a9c4c8e7a68d1f82f14c982c42573 100644 (file)
@@ -77,7 +77,7 @@ function mlc.convert (x, src_fmt, dst_fmt, name)
 
    if not name then name = '@'..x end
    local f, msg = io.open(x, "rb")
-   if not f then error(msg) end
+   if not f then error("While trying to open file '"..x.."': "..msg) end
    x = f:read'*a'
    f:close()
    
@@ -149,6 +149,8 @@ mlc.luacstring_of_function = string.dump
 
 lua_loadstring = loadstring
 local lua_loadstring = loadstring
+lua_loadfile = loadfile
+local lua_loadfile = loadfile
 
 function loadstring(str, name)
    if type(str) ~= 'string' then error 'string expected' end
@@ -190,5 +192,3 @@ function dofile(name)
    if not f then error(msg) end
    return f()
 end
-
-
index 72e5f7130aeba29e73d9355b3ca3c8c9a01c115f..3581b0c48e8cf55cab6ef25111509a5786133332 100644 (file)
@@ -174,13 +174,16 @@ function regexp_pattern_element_builder (pattern, term, cfg)
    assert (regexp.tag=="String", 
            "Left hand side operand for '/' in a pattern must be "..
            "a literal string representing a regular expression")
-   assert (sub_pattern.tag=="Table",
-           "Right hand side operand for '/' in a pattern must be "..
-           "an identifier or a list of identifiers")
-   for x in ivalues(sub_pattern) do
-      assert (x.tag=="Id" or x.tag=='Dots',
-              "Right hand side operand for '/' in a pattern must be "..
-              "a list of identifiers")
+   if sub_pattern.tag=="Table" then
+      for x in ivalues(sub_pattern) do
+        assert (x.tag=="Id" or x.tag=='Dots',
+                "Right hand side operand for '/' in a pattern must be "..
+                "a list of identifiers")
+      end
+   else
+      assert (sub_pattern.tag=="Id",
+             "Right hand side operand for '/' in a pattern must be "..
+              "an identifier or a list of identifiers")
    end
 
    -- Regexp patterns can only match strings
@@ -278,7 +281,6 @@ function case_builder (case, term_seq, cfg)
    acc_stat (`Label{on_success}, cfg)
    if guard then acc_test (+{not -{guard}}, cfg) end
    if cfg.dots_replacement then
-      eprintf ("Dots replacement required in a match")
       replace_dots (block, cfg.dots_replacement)
    end
    block.tag = 'Do'
index 7c7e4d8e4c60c3805183c2af5fe2b4eff78fa8bb..5466a07f6fe80718ddd7ed2b989ece9648f2cce7 100644 (file)
 -{ extension 'H' }
 -{ extension 'log' }
 
-require 'metalua.extension.match'
-
 -- Get match parsers and builder, for catch cases handling:
-local match_alpha = require 'extension.match'
+local match_alpha = require 'metalua.extension.match'
 local H = H:new{side='inside', alpha = match_alpha }
 
 -- We'll need to track rogue return statements:
diff --git a/src/lib/metalua/mlc_xcall.lua b/src/lib/metalua/mlc_xcall.lua
new file mode 100644 (file)
index 0000000..a93744f
--- /dev/null
@@ -0,0 +1,48 @@
+-- lua -l mlc_xcall -e 'luafile_to_astfile ("/tmp/tmp12345.lua", "/tmp/tmp54321.ast")'
+-- lua -l mlc_xcall -e 'lua_to_astfile ("/tmp/tmp54321.ast")'
+
+mlc_xcall = { }
+
+function mlc_xcall.server (luafilename, astfilename)
+
+   -- We don't want these to be loaded when people only do client-side business
+   require 'metalua.compiler'
+   require 'serialize'
+
+   -- compile the content of luafile name in an AST, serialized in astfilename
+   local ast = mlc.luafile_to_ast (luafilename)
+   local out = io.open (astfilename, 'w')
+   out:write (serialize (ast))
+   out:close ()
+end
+
+function mlc_xcall.client_file (luafile)
+
+   --printf("\n\nmlc_xcall.client_file(%q)\n\n", luafile)
+
+   local tmpfilename = os.tmpname()
+   local cmd = string.format ([[lua -l metalua.mlc_xcall -e "mlc_xcall.server('%s', '%s')"]], 
+                             luafile :gsub ([[\]], [[\\]]), 
+                             tmpfilename :gsub([[\]], [[\\]]))
+
+   --printf("os.execute [[%s]]\n\n", cmd)
+
+   local ret = os.execute (cmd)
+   if ret~=0 then error "xcall failure. FIXME: transmit failure and backtrace" end
+   local ast = (lua_loadfile or loadfile) (tmpfilename) ()
+   os.remove(tmpfilename)
+   return true, ast
+end
+
+function mlc_xcall.client_literal (luasrc)
+   local srcfilename = os.tmpname()
+   local srcfile, msg = io.open (srcfilename, 'w')
+   if not srcfile then print(msg) end
+   srcfile :write (luasrc)
+   srcfile :close ()
+   local status, ast = mlc_xcall.client_file (srcfilename)
+   os.remove(srcfilename)
+   return status, ast
+end
+
+return mlc_xcall
\ No newline at end of file
index 6940ef04a4a465a4f5b9761b650a09ea2fbe6f4d..78912ac527c8bc8bd3660450897510fee7749358 100644 (file)
@@ -75,9 +75,11 @@ function package.metalua_loader (name)
       local luastring = file:read '*a'
       file:close()
       return mlc.function_of_luastring (luastring, name)
-   else
+   else      
       file:close()
-      return spring_load (filename_or_msg)
+      require 'metalua.mlc_xcall'
+      local status, ast = mlc_xcall.client_file (filename_or_msg)
+      return mlc.function_of_ast(ast)
    end
 end
 
diff --git a/src/make-install.sh b/src/make-install.sh
deleted file mode 100755 (executable)
index 3a03a13..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-echo "This script is currently empty. Run ./make.sh first, then a correct make-install.sh will be generated."
-exit -1
index 740202d89b18ecca97c66e2fa9120e822d3cfbeb..f7f87982e759e9fb422e3ccadf2da7c0bb4851d4 100755 (executable)
@@ -1,3 +1,5 @@
+#! /bin/sh
+
 # --- BEGINNING OF USER-EDITABLE PART ---
 
 # Metalua sources
@@ -5,15 +7,29 @@ BASE=${PWD}
 
 # Temporary building location.
 # Upon installation, everything will be moved to ${INSTALL_LIB} and ${INSTALL_BIN}
-BUILD=/tmp/metalua-build
-BUILD_BIN=${BUILD}/bin
-BUILD_LIB=${BUILD}/lib
+
+if [ -z "${BUILD}" ]; then
+  BUILD=/tmp/metalua-build
+fi
+
+if [ -z "${BUILD_BIN}" ]; then
+  BUILD_BIN=${BUILD}/bin
+fi
+
+if [ -z "${BUILD_LIB}" ]; then
+  BUILD_LIB=${BUILD}/lib
+fi
 
 # Where to place the final results
 # INSTALL_BIN=/usr/local/bin
 # INSTALL_LIB=/usr/local/lib/lua/5.1
-INSTALL_BIN=~/local/bin
-INSTALL_LIB=~/local/lib/lua
+if [ -z "${INSTALL_BIN}" ]; then
+  INSTALL_BIN=~/local/bin
+fi
+
+if [ -z "${INSTALL_LIB}" ]; then
+  INSTALL_LIB=~/local/lib/lua
+fi
 
 # Where to find Lua executables.
 # On many Debian-based systems, those can be installed with "sudo apt-get install lua5.1"
@@ -33,7 +49,7 @@ echo '*** Create the distribution directories, populate them with lib sources **
 mkdir -p ${BUILD_BIN}
 mkdir -p ${BUILD_LIB}
 cp -R lib/* ${BUILD_LIB}/
-cp -R bin/* ${BUILD_BIN}/
+# cp -R bin/* ${BUILD_BIN}/ # No binaries provided for unix (for now)
 
 echo '*** Generate a callable metalua shell script ***'
 
@@ -96,4 +112,4 @@ chmod a+x make-install.sh
 
 echo
 echo "Build completed, proceed to installation with './make-install.sh' or 'sudo ./make-install.sh'"
-echo
\ No newline at end of file
+echo
index e572b4bcf24e8b16055f4bc860144986a289f581..01090eee14161821917e170052861487b1b60377 100644 (file)
@@ -553,8 +553,8 @@ end
 -- Read a file, get its AST, use synth to regenerate sources
 -- from that AST
 --------------------------------------------------------------------------------
-require 'mlc'
+require 'metalua.compiler'
 local filename = (arg[2] or arg[1]) or arg[0]
 local ast = mlc.luafile_to_ast (filename)
 
-print(synth.run(ast)) 
\ No newline at end of file
+print(synth.run(ast))
index aff10c46c786a0b029d3d64bcda56dbf7cfe2dce..fa4f671816b2890817b9b61bab43c3c55ecbd550 100644 (file)
@@ -32,7 +32,7 @@ print "4) error, with a finally"
 try
    print "   Hi"
    error "bang"
-catch "bang"/_ then
+catch "bang"/{_} then
    print "   Bang caught"
 finally
    print "   Finally OK"
@@ -47,7 +47,7 @@ try
    catch "some_other_error" then
       assert (false, "mismatch, this must not happen")
    end
-catch "some_error"/x then
+   catch "some_error"/{x} then
    printf("   Successfully caught %q across a try that didn't catch", x)
 catch x then
    assert (false, "We shouldn't reach this catch-all")
index 37dd7947c1381bde789b64e37552f985b156b96a..f8f01a0f54f0083b977b86a9d4b9d9fdf5291310 100644 (file)
@@ -1,6 +1,6 @@
 -{ extension 'match' }
 
-require 'walk.id'
+require 'metalua.walk.id'
 
 ast = +{ block:
          y = type(1)
index 8a000370f71ce5809c9eb2b0ea32e32b21625cf3..f428a419d857e8d7141459431ea750daae6005f0 100644 (file)
@@ -1,5 +1,5 @@
-require 'mlc'
-require 'walk'
+require 'metalua.mlc'
+require 'metalua.walk'
 
 function weave_ast (src, ast, name)
 
@@ -22,10 +22,25 @@ function weave_ast (src, ast, name)
    -- the `Local{ } node, although it's not directly included in it.
    -------------------------------------------------------------------
    function node.down(ast, parent)
+      ----------------------------------------------------
+      -- `Do{ } blocks are processed twice:
+      --  * once as a statement
+      --  * once as a block, child of itself
+      -- This prevents them from becoming their own child.
+      ----------------------------------------------------
+      if ast==parent then return end
+
       if not ast.lineinfo then 
-         weaveable [ast], weaveable [parent] = false, false
+         weaveable [ast] = false, false
+         if parent then weaveable [parent] = false end
       else
          weaveable [ast] = true
+         
+         -- normalize lineinfo
+         -- TODO: FIXME
+         if ast.lineinfo.first[3] > ast.lineinfo.last[3] then
+           ast.lineinfo.first, ast.lineinfo.last = ast.lineinfo.last, ast.lineinfo.first
+         end
       end
       ast_children [ast] = { }
       ast_parent [ast] = parent
@@ -44,8 +59,14 @@ function weave_ast (src, ast, name)
       local _acc = { }
       local function acc(x) table.insert (_acc, x) end
       
+      if not next(ast) then -- shadow node, remove from ast_children
+         local x = ast_children[ast_parent[ast]]
+         for i,a in ipairs (x) do if a==ast then table.remove (x, i); break end end
+         return "" -- no need to continue, we know that the node is empty!
+      end
+      
       -- ast Can't be weaved normally, try something else --
-      local function synthetize (ast)         
+      local function synthetize (ast)
          acc "-{expr: "
          acc (table.tostring (ast, 'nohash', 80, 8))
          acc " }"
@@ -53,15 +74,19 @@ function weave_ast (src, ast, name)
 
       -- regular weaving of chidren in the parent's sources --
       local function weave (ast)
+         -- sort children in appearence order
+         local comp = |a,b| a.lineinfo.first[3] < b.lineinfo.first[3]
+         table.sort (ast_children [ast], comp)
          local li = ast.lineinfo
          if not li then return synthetize (ast) end
          local a, d = li.first[3], li.last[3]
          for child in ivalues (ast_children [ast]) do
             local li = child.lineinfo
             local b, c = li.first[3], li.last[3]
-            acc (src:sub (a, b-1))
+            acc (src:sub (a, b - 1))
             acc (translation [child])
-            a = c+1
+            a = c + 1
          end
          acc (src:sub (a, d))
       end
@@ -81,10 +106,15 @@ end
 
 -- Get the source. If none is given, use itself as an example. --
 local filename = arg[2] or arg[1] or arg[0]
-local f = io.open (filename, 'r')
+local f = assert (io.open (filename, 'r'))
 local src = f:read '*a'
 f:close()
 
 local ast = mlc.luastring_to_ast (src, name)
-
-print (weave_ast (src, ast))
+if not next(ast) then
+   io.write (src) -- Empty ast, probably empty file, or comments only
+else
+   local before = src:sub (1, ast.lineinfo.first[3]-1)
+   local after  = src:sub (ast.lineinfo.last[3]+1, -1)
+   io.write (before .. weave_ast (src, ast) .. after)
+end