|
3 | 3 |
|
4 | 4 | mlc_xcall = { } |
5 | 5 |
|
| 6 | + |
| 7 | +-- This is the back-end function, called in a separate lua process |
| 8 | +-- by `mlc_xcall.client_*()' through `os.execute()'. |
| 9 | +-- * inputs: |
| 10 | +-- * the name of a lua source file to compile in a separate process |
| 11 | +-- * the name of a writable file where the resulting ast is dumped |
| 12 | +-- with `serialize()'. |
| 13 | +-- * results: |
| 14 | +-- * an exit status of 0 or -1, depending on whethet compilation |
| 15 | +-- succeeded; |
| 16 | +-- * the ast file filled will either the serialized ast, or the |
| 17 | +-- error message. |
6 | 18 | function mlc_xcall.server (luafilename, astfilename) |
7 | 19 |
|
8 | 20 | -- We don't want these to be loaded when people only do client-side business |
9 | 21 | require 'metalua.compiler' |
10 | 22 | require 'serialize' |
11 | 23 |
|
12 | 24 | -- compile the content of luafile name in an AST, serialized in astfilename |
13 | | - local ast = mlc.luafile_to_ast (luafilename) |
| 25 | + local status, ast = pcall (mlc.luafile_to_ast, luafilename) |
14 | 26 | local out = io.open (astfilename, 'w') |
15 | | - out:write (serialize (ast)) |
16 | | - out:close () |
| 27 | + if status then -- success |
| 28 | + out:write (serialize (ast)) |
| 29 | + out:close () |
| 30 | + os.exit (0) |
| 31 | + else -- failure, `ast' is actually the error message |
| 32 | + out:write (ast) |
| 33 | + out:close () |
| 34 | + os.exit (-1) |
| 35 | + end |
17 | 36 | end |
18 | 37 |
|
| 38 | +-- Compile the file whose name is passed as argument, in a separate process, |
| 39 | +-- communicating through a temporary file. |
| 40 | +-- returns: |
| 41 | +-- * true or false, indicating whether the compilation succeeded |
| 42 | +-- * the ast, or the error message. |
19 | 43 | function mlc_xcall.client_file (luafile) |
20 | 44 |
|
21 | | - --printf("\n\nmlc_xcall.client_file(%q)\n\n", luafile) |
| 45 | + -- printf("\n\nmlc_xcall.client_file(%q)\n\n", luafile) |
22 | 46 |
|
23 | 47 | local tmpfilename = os.tmpname() |
24 | | - local cmd = string.format ([[lua -l metalua.mlc_xcall -e "mlc_xcall.server('%s', '%s')"]], |
25 | | - luafile :gsub ([[\]], [[\\]]), |
26 | | - tmpfilename :gsub([[\]], [[\\]])) |
| 48 | + local cmd = string.format ( |
| 49 | + [=[lua -l metalua.mlc_xcall -e "mlc_xcall.server([[%s]], [[%s]])"]=], |
| 50 | + luafile, tmpfilename) |
27 | 51 |
|
28 | | - --printf("os.execute [[%s]]\n\n", cmd) |
| 52 | + -- printf("os.execute [[%s]]\n\n", cmd) |
29 | 53 |
|
30 | | - local ret = os.execute (cmd) |
31 | | - if ret~=0 then error "xcall failure. FIXME: transmit failure and backtrace" end |
32 | | - local ast = (lua_loadfile or loadfile) (tmpfilename) () |
| 54 | + local status = (0 == os.execute (cmd)) |
| 55 | + local result -- ast or error msg |
| 56 | + if status then |
| 57 | + result = (lua_loadfile or loadfile) (tmpfilename) () |
| 58 | + else |
| 59 | + local f = io.open (tmpfilename) |
| 60 | + result = f :read '*a' |
| 61 | + f :close() |
| 62 | + end |
33 | 63 | os.remove(tmpfilename) |
34 | | - return true, ast |
| 64 | + return status, result |
35 | 65 | end |
36 | 66 |
|
| 67 | +-- Compile a source string into an ast, by dumping it in a tmp |
| 68 | +-- file then calling `mlc_xcall.client_file()'. |
| 69 | +-- returns: the same as `mlc_xcall.client_file()'. |
37 | 70 | function mlc_xcall.client_literal (luasrc) |
38 | 71 | local srcfilename = os.tmpname() |
39 | 72 | local srcfile, msg = io.open (srcfilename, 'w') |
|
0 commit comments