]> git.lizzy.rs Git - metalua.git/blobdiff - metalua/repl.mlua
Merge branch 'master' of ssh://git.eclipse.org/gitroot/koneki/org.eclipse.koneki...
[metalua.git] / metalua / repl.mlua
diff --git a/metalua/repl.mlua b/metalua/repl.mlua
new file mode 100644 (file)
index 0000000..4a39adf
--- /dev/null
@@ -0,0 +1,108 @@
+-------------------------------------------------------------------------------
+-- 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
+--
+-------------------------------------------------------------------------------
+
+-- Keep these global:
+PRINT_AST  = true
+LINE_WIDTH = 60
+PROMPT     = "M> "
+PROMPT2    = ">> "
+
+local pp=require 'metalua.pprint'
+local M = { }
+
+mlc = require 'metalua.compiler'.new()
+
+local readline
+
+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
+      local status, rl = pcall(require, 'readline')
+      if status then
+         rl.set_options{histfile='~/.metalua_history', keeplines=100, completion=false }
+         readline = rl.readline
+      else -- neither editline nor readline available
+         function readline (p)
+            io.write (p)
+            io.flush ()
+            return io.read '*l'
+         end
+      end
+   end
+end
+
+local function reached_eof(lx, msg)
+   return lx:peek().tag=='Eof' or msg:find "token `Eof"
+end
+
+
+function M.run()
+    pp.printf ("Metalua, interactive REPLoop.\n"..
+            "(c) 2006-2013 <metalua@gmail.com>")
+   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 :src_to_lexstream(src)
+      success, ast = pcall(mlc.lexstream_to_ast, mlc, lx)
+      if success then
+          success, f = pcall(mlc.ast_to_function, mlc, ast, '=stdin')
+          if success then
+              results = { xpcall(f, debug.traceback) }
+              success = table.remove (results, 1)
+              if success then
+                  -- Success!
+                  for _, x in ipairs(results) do
+                      pp.print(x, {line_max=LINE_WIDTH, metalua_tag=true})
+                  end
+                  lines = { }
+              else
+                  print "Evaluation error:"
+                  print (results[1])
+                  lines = { }
+              end
+          else
+              print "Can't compile into bytecode:"
+              print (f)
+              lines = { }
+          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
+
+return M
\ No newline at end of file