/*
* $Id: Interpreter.java,v 1.10 2006/06/18 19:10:38 juhal Exp $
*/
package bex;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
public class Interpreter implements Runnable {
public static final String VERSION = "1.1";
private EvalContext context;
private boolean quiet;
public Interpreter() {
try {
init(null, null, null, null, null);
} catch (Exception ex) {
// this should not happen with the defaults
throw new AssertionException(
"interpreter initialization failed", ex);
}
}
public Interpreter(
JavaBridge bridge,
Environment root,
Reader stdin,
PrintWriter stdout,
PrintWriter stderr)
throws EvalException, InternalEvalException {
init(bridge, root, stdin, stdout, stderr);
}
private void init(
JavaBridge bridge,
Environment root,
Reader stdin,
PrintWriter stdout,
PrintWriter stderr)
throws EvalException, InternalEvalException {
if (bridge == null)
bridge = new ReflectJavaBridge();
if (root == null)
root = getDefaultEnv(bridge);
this.context = new EvalContext(bridge, root, stdin, stdout, stderr);
}
public EvalContext getContext() {
return context;
}
public boolean isQuiet() {
return quiet;
}
public void setQuiet(boolean quiet) {
this.quiet = quiet;
}
public Object eval(String script)
throws ParseException, EvalException {
return eval(new StringReader(script));
}
public Object eval(File file)
throws ParseException, EvalException, IOException {
return eval(context, file);
}
public Object eval(Reader reader)
throws ParseException, EvalException {
return eval(context, reader);
}
public static Object eval(EvalContext ctx, String script)
throws ParseException, EvalException {
return eval(ctx, new StringReader(script));
}
public static Object eval(EvalContext ctx, File file)
throws ParseException, EvalException, IOException {
Reader reader = new BufferedReader(new FileReader(file));
try {
return eval(ctx, reader, file.getName());
} finally {
reader.close();
}
}
public static Object eval(EvalContext ctx, Reader reader)
throws ParseException, EvalException {
return eval(ctx, reader, null);
}
public static Object eval(EvalContext ctx, Reader reader, String sourceFile)
throws ParseException, EvalException {
Parser parser = new Parser(reader);
Object value = null;
while(true) {
Expression exp = parser.read();
if (exp == null) break;
if (exp == Expression.VOID) continue;
Node node = (Node)exp;
node.setSourceFile(sourceFile);
value = eval(ctx, exp);
if (value instanceof ReturnControl) break;
}
return value;
}
public static Object eval(EvalContext ctx, Expression exp)
throws EvalException {
try {
return exp.eval(ctx);
} catch (EvalException ee) {
ee.addScriptStackTraceElement((Node)exp);
throw ee;
}
}
public void put(String name, Object value)
throws EvalException, InternalEvalException {
context.root().setVariable(context, name, value);
}
public Object get(String name)
throws EvalException, InternalEvalException {
return context.root().getVariable(context, name);
}
public static Environment getDefaultEnv(JavaBridge bridge) {
Environment defenv = new Environment();
try {
EvalContext ctx = new EvalContext(bridge, defenv);
InputStream in = Interpreter.class.getResourceAsStream("default.bex");
if (in == null) throw new AssertionException("default.bex not found");
try {
eval(ctx, new InputStreamReader(in), "default.bex");
return defenv;
} finally {
in.close();
}
} catch (Exception e) {
System.err.println("failed to load default environment");
e.printStackTrace(System.err);
}
return new Environment();
}
private String getString(EvalContext ctx, String name, String defval) {
try {
Object val = ctx.root().getVariable(ctx, name);
if (val instanceof String) {
return (String) val;
} else if (val instanceof Callable) {
return String
.valueOf(((Callable) val).call(ctx, new Object[0]));
}
return (val != Primitive.VOID) ? String.valueOf(val) : defval;
} catch (Exception e) {
return defval;
}
}
private String getPrompt() {
return getString(context, "bex_prompt", "bex> ");
}
private String getMotd() {
return getString(context, "bex_motd",
"Bex script " + VERSION + " (c) Juha Lindström 2005-2006");
}
public void run() {
Expression exp = null;
Parser parser = new Parser(context.getStdin());
PrintWriter stdout = context.getStdout();
PrintWriter stderr = context.getStderr();
if (!isQuiet()) stdout.println(getMotd());
while(true) {
try {
if (!isQuiet()) {
stdout.print(getPrompt());
stdout.flush();
}
exp = parser.read();
if (exp == null) break;
if (exp == Expression.VOID) continue;
Object value = eval(context, exp);
if (!isQuiet()) stdout.println(value);
put("$_", value);
} catch (TokenMgrError e) {
stderr.println(e);
stderr.flush();
parser.ReInit(context.getStdin());
} catch (ParseException e) {
stderr.println(e);
stderr.flush();
parser.ReInit(context.getStdin());
} catch (TargetException te) {
te.printStackTrace(stderr);
stderr.flush();
} catch (EvalException ee) {
stderr.println(ee);
stderr.flush();
} catch (Throwable e) {
e.printStackTrace(stderr);
stderr.flush();
}
}
}
private static void evalBexrc(Interpreter interpreter) {
File f = new File(System.getenv("HOME"), ".bexrc");
if (f.exists()) {
try {
interpreter.eval(f);
} catch (Exception e) {
System.err.println("failed to evaluate .bexrc");
e.printStackTrace(System.err);
}
}
}
public static void main(String args[])
throws Exception {
int i = 0;
Interpreter interpreter = new Interpreter();
if (args.length > i && "-q".equals(args[i])) {
i++;
interpreter.setQuiet(true);
}
evalBexrc(interpreter);
boolean interactive = args.length == i;
if (args.length > i && "-i".equals(args[i])) {
i++;
interactive = true;
}
try {
if (args.length > i) {
String[] sargs = new String[args.length - (i + 1)];
if (sargs.length > 0)
System.arraycopy(args, i + 1, sargs, 0, sargs.length);
interpreter.put("$args", sargs);
interpreter.eval(new File(args[i]));
}
} catch (TargetException te) {
te.printStackTrace(System.err);
} catch (EvalException e) {
System.err.println(e);
}
if (interactive)
interpreter.run();
}
}