package org.reldb.rel.v0.interpreter; import java.io.*; import org.reldb.rel.exceptions.*; import org.reldb.rel.v0.debuginfo.DebugInfo; import org.reldb.rel.v0.generator.Generator; import org.reldb.rel.v0.generator.OperatorDefinition; import org.reldb.rel.v0.generator.OperatorDefinitionRel; import org.reldb.rel.v0.generator.OperatorSignature; import org.reldb.rel.v0.languages.tutoriald.parser.*; import org.reldb.rel.v0.storage.*; import org.reldb.rel.v0.types.Heading; import org.reldb.rel.v0.types.Type; import org.reldb.rel.v0.values.ValueOperator; import org.reldb.rel.v0.vm.Dumper; import org.reldb.rel.v0.vm.VirtualMachine; public class Interpreter { private Generator generator; private VirtualMachine vm; private boolean debugOnRun = false; private boolean debugAST = false; public Interpreter(RelDatabase database, PrintStream outputStream) { generator = new Generator(database, outputStream); vm = new VirtualMachine(generator, database, outputStream); } public void setDebugOnRun(boolean flag) { debugOnRun = flag; } public void setDebugAST(boolean flag) { debugAST = flag; } public void reset() { generator.reset(); vm.reset(); } public Generator getGenerator() { return generator; } private void beginCompile() { if (debugOnRun) System.out.println("Compiling..."); } private void execute(OperatorDefinitionRel mainOperatorDefinition) { // Dump if debugging if (debugOnRun) { System.out.println("Compiled:"); (new Dumper()).dumpMachineCode(mainOperatorDefinition.getOperator()); System.out.println("Executing..."); } // Go if (mainOperatorDefinition != null) vm.execute(mainOperatorDefinition.getOperator()); else System.out.println("No execution performed."); } private void run(TutorialD parseEngine, OperatorDefinitionRel mainOperatorDefinition) { try { execute(mainOperatorDefinition); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + vm.getCurrentInstruction().getDebugInfo().toString(), es); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + vm.getCurrentInstruction().getDebugInfo().toString(), ef); } catch (Throwable t) { t.printStackTrace(); throw new ExceptionFatal(t.toString() + "\n" + vm.getCurrentInstruction().getDebugInfo().toString(), t); } } // TODO - make error trapping more location-specific. Current mechanism, using getCurrentNode(), is a hack. private static DebugInfo getDebugInfo(Generator generator, TutorialDParser parser) { return new DebugInfo(parser.getCurrentNode(), generator.getOperatorDefinitionLineReferenceStack(parser.getCurrentNode().first_token.beginLine)); } /** Compile and evaluate an expression. */ public static Evaluation evaluateExpression(RelDatabase database, String source, PrintStream outputStream) throws ParseException { return (new Interpreter(database, outputStream)).evaluate(source); } /** Compile and execute a statement. */ public static void executeStatement(RelDatabase database, String source, PrintStream outputStream) throws ParseException { (new Interpreter(database, outputStream)).interpret(source); } public static void executeStatementPrivileged(RelDatabase database, String source, String owner, PrintStream outputStream) throws ParseException { Interpreter interpreter = new Interpreter(database, outputStream); interpreter.getGenerator().setOwner(owner); interpreter.interpret(source); } public Evaluation evaluate(TutorialDVisitor parser, InputStream input) throws ParseException { beginCompile(); TutorialD parseEngine = new TutorialD(input); parseEngine.setTabSize(4); OperatorDefinitionRel mainOperatorDefinition = null; try { mainOperatorDefinition = (OperatorDefinitionRel)(parseEngine.evaluate().jjtAccept(parser, null)); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString(), es); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString(), ef); } if (mainOperatorDefinition != null) { run(parseEngine, mainOperatorDefinition); if (vm.getStackCount() != 1) throw new ExceptionFatal("Invalid count of values on the stack: " + vm.getStackCount()); return new Evaluation(vm.getCurrentContext(), mainOperatorDefinition.getDeclaredReturnType(), vm.pop()); } else { System.out.println("No evaluation performed."); return null; } } /** Compile a statement. */ public void compileStatement(TutorialDVisitor parser, InputStream input) throws ParseException { beginCompile(); TutorialD parseEngine = new TutorialD(input); parseEngine.setTabSize(4); try { parseEngine.statement().jjtAccept(parser, null); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } } /** Compile a statement. */ public void compileStatement(TutorialDVisitor parser, String input) throws ParseException { compileStatement(parser, new ByteArrayInputStream(input.getBytes())); } /** Compile a statement. */ public void compileStatement(String input) throws ParseException { compileStatement(new TutorialDParser(generator), input); } /** Compile a top-level operator definition, but instead of persisting it, return it. */ public OperatorDefinition compileOperator(String input) throws ParseException { TutorialDParser parser = new TutorialDParser(generator); parser.beginOperatorsNonStorable(); compileStatement(parser, input); parser.endOperatorsNonStorable(); return parser.getLastPersistentOperatorDefinition(); } /** Compile an anonymous operator definition. */ public ValueOperator compileAnonymousOperator(String source) throws ParseException { TutorialDParser parser = new TutorialDParser(generator); return (ValueOperator)evaluate(parser, source).getValue(); } /** Obtain the return type of an operator */ public Type getOperatorReturnType(String input) throws ParseException { TutorialDParser parser = new TutorialDParser(generator); parser.beginOperatorsNonStorable(); beginCompile(); parser.endOperatorsNonStorable(); TutorialD parseEngine = new TutorialD(new ByteArrayInputStream(input.getBytes())); parseEngine.setTabSize(4); try { return (Type)parseEngine.getoperatorreturntype().jjtAccept(parser, null); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } } /** Compile a heading and return it. */ public Heading getHeading(String input) throws ParseException { TutorialDParser parser = new TutorialDParser(generator); beginCompile(); TutorialD parseEngine = new TutorialD(new ByteArrayInputStream(input.getBytes())); parseEngine.setTabSize(4); try { return (Heading)parseEngine.getheading().jjtAccept(parser, null); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } } /** Obtain an operator signature. */ public OperatorSignature getOperatorSignature(String input) throws ParseException { TutorialDParser parser = new TutorialDParser(generator); beginCompile(); TutorialD parseEngine = new TutorialD(new ByteArrayInputStream(input.getBytes())); parseEngine.setTabSize(4); try { return (OperatorSignature)parseEngine.getsignature().jjtAccept(parser, null); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } } public void interpret(TutorialDVisitor parser, InputStream input) throws ParseException { beginCompile(); TutorialD parseEngine = new TutorialD(input); parseEngine.setTabSize(4); OperatorDefinitionRel mainOperatorDefinition; try { mainOperatorDefinition = (OperatorDefinitionRel)(parseEngine.code().jjtAccept(parser, null)); } catch (ExceptionSemantic es) { throw new ExceptionSemantic(es.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } catch (ExceptionFatal ef) { throw new ExceptionFatal(ef.getMessage() + "\n" + getDebugInfo(generator, (TutorialDParser)parser).toString()); } run(parseEngine, mainOperatorDefinition); vm.outputTupleUpdateNotices(); } public void interpret(InputStream input) throws ParseException { TutorialDVisitor parser; if (debugAST) parser = new TutorialDDebugger(); else parser = new TutorialDParser(generator); interpret(parser, input); } public void interpret(String input) throws ParseException { interpret(new ByteArrayInputStream(input.getBytes())); } public void interpret(TutorialDVisitor parser, String input) throws ParseException { interpret(parser, new ByteArrayInputStream(input.getBytes())); } public Evaluation evaluate(InputStream input) throws ParseException { TutorialDVisitor parser; if (debugAST) parser = new TutorialDDebugger(); else parser = new TutorialDParser(generator); return evaluate(parser, input); } public Evaluation evaluate(String input) throws ParseException { return evaluate(new ByteArrayInputStream(input.getBytes())); } public Evaluation evaluate(TutorialDVisitor parser, String input) throws ParseException { return evaluate(parser, new ByteArrayInputStream(input.getBytes())); } }