blob: 5e42f3026020ed907ff30f48ee97de0afab3d42b [file] [log] [blame]
-------------------------------------------------------------------------------
-- Copyright (c) 2006-2013 Fabien Fleutot and others.
--
-- All rights reserved.
--
-- This program and the accompanying materials are made available
-- under the terms of the Eclipse Public License v1.0 which
-- accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- This program and the accompanying materials are also made available
-- under the terms of the MIT public license which accompanies this
-- distribution, and is available at http://www.lua.org/license.html
--
-- Contributors:
-- Fabien Fleutot - API and implementation
--
-------------------------------------------------------------------------------
require 'metalua.compiler'
module ('metaloop', package.seeall)
PRINT_AST = true
LINE_WIDTH = 60
PROMPT = "M> "
PROMPT2 = ">> "
do -- set readline() to a line reader, either editline otr a default
local status, _ = pcall(require, 'editline')
if status then
local rl_handle = editline.init 'metalua'
readline = |p| rl_handle:read(p)
else
function readline (p)
io.write (p)
io.flush ()
return io.read '*l'
end
end
end
function reached_eof(lx, msg)
return lx:peek().tag=='Eof' or msg:find "token `Eof"
end
printf ("Metalua, interactive REPLoop.\n"..
"(c) 2006-2011 <metalua@gmail.com>")
function run()
local lines = { }
while true do
local src, lx, ast, f, results, success
repeat
local line = readline(next(lines) and PROMPT2 or PROMPT)
if not line then print(); os.exit(0) end -- line==nil iff eof on stdin
if not next(lines) then
line = line:gsub('^%s*=', 'return ')
end
table.insert(lines, line)
src = table.concat (lines, "\n")
until #line>0
lx = mlc.luastring_to_lexstream(src)
success, ast = pcall(mlc.lexstream_to_ast, lx)
if success then
local check_status, check_msg = pcall(mlc.check_ast, ast)
if not check_status then
print "Invalid AST:"
print (check_msg)
lines = { }
else
success, f = pcall(mlc.ast_to_function, ast, '=stdin')
if success then
results = { xpcall(f, debug.traceback) }
success = table.remove (results, 1)
if success then
-- Success!
table.iforeach(|x| table.print(x, LINE_WIDTH), results)
lines = { }
else
print "Evaluation error:"
print (results[1])
lines = { }
end
else
print "Can't compile into bytecode:"
print (f)
lines = { }
end
end
else
-- If lx has been read entirely, try to read another
-- line before failing.
if not reached_eof(lx, ast) then
print "Can't compile source into AST:"
print (ast)
lines = { }
end
end
end
end