]> git.lizzy.rs Git - metalua.git/blob - src/lib/metalua/metaloop.mlua
fixed integration of interactive loop with external line editors such as ledit
[metalua.git] / src / lib / metalua / metaloop.mlua
1 require 'metalua.compiler'
2
3 module ('metaloop', package.seeall)
4
5 PRINT_AST  = true
6 LINE_WIDTH = 60
7 PROMPT     = "M> "
8 PROMPT2    = ">> "
9
10 do -- set readline() to a line reader, either editline otr a default
11    local status, _ = pcall(require, 'editline')
12    if status then
13       local rl_handle = editline.init 'metalua'
14       readline = |p| rl_handle:read(p) 
15    else
16       function readline (p)
17          io.write (p)
18          io.flush ()
19          return io.read '*l'
20       end
21    end
22 end
23
24 function reached_eof(lx, msg)
25    return lx:peek().tag=='Eof' or msg:find "token `Eof"
26 end
27
28 printf ("Metalua, interactive REPLoop.\n"..
29         "(c) 2006-2008 <metalua@gmail.com>")
30
31 function run()
32    local lines = { }
33    while true do
34       local src, lx, ast, f, results, success
35       repeat
36          local line = readline(next(lines) and PROMPT2 or PROMPT)
37          if not line then print(); os.exit(0) end -- line==nil iff eof on stdin
38          if not next(lines) then
39             line = line:gsub('^%s*=', 'return ')
40          end
41          table.insert(lines, line)
42          src = table.concat (lines, "\n")
43       until #line>0
44       
45       lx  = mlc.lexstream_of_luastring(src) 
46       success, ast = pcall(mlc.ast_of_lexstream, lx)
47       if success then
48          success, f = pcall(mlc.function_of_ast, ast, '=stdin')
49          if success then
50             results = { pcall(f) }
51             success = table.remove (results, 1)
52             if success then
53                -- Success!
54                table.iforeach(|x| table.print(x, LINE_WIDTH), results)
55                lines = { }
56             else
57                print "Evaluation error:"
58                print (results[1])
59                lines = { }
60             end
61          else
62             print "Can't compile into bytecode:"
63             print (f)
64             lines = { }
65          end
66       else
67          -- If lx has been read entirely, try to read another
68          -- line before failing.
69          if not reached_eof(lx, ast) then
70             print "Can't compile source into AST:"
71             print (ast)
72             lines = { } 
73          end
74       end
75    end
76 end