/** * Runs the interpreter * * @param is the reader from which the statements are read * @param fname the name of the parsed stream * @return the result of the evaluation of the last statement */ public Object interpret(final Reader r, final String fname) throws InterpreterException { try { final SourceCodeParser p = this.parserFactory.createParser(r, fname); final List statements = p.parseStream(); final ListIterator it = statements.listIterator(); Object result = null; while (it.hasNext()) { Node n = (Node) it.next(); Visitor v = new NameVisitor(this.nameVisitorContext); final Object o = n.acceptVisitor(v); if (o != null) { n = (Node) o; } v = new TypeChecker(this.checkVisitorContext); n.acceptVisitor(v); this.evalVisitorContext.defineVariables( this.checkVisitorContext.getCurrentScopeVariables()); v = new EvaluationVisitor(this.evalVisitorContext); result = n.acceptVisitor(v); } return result; } catch (final ExecutionError e) { // e.printStackTrace(); throw new InterpreterException(e); } catch (final ParseError e) { // e.printStackTrace(); throw new InterpreterException(e); } catch (final Throwable d) { d.printStackTrace(); throw new InterpreterException(new ParseError("Impossible d'évaluer l'expression!")); } }
/** * This method is used to implement constructor invocation. * * @param c the declaring class of the constructor * @param cpd the parameter descriptor * @param args the arguments passed to this constructor * @return the arguments to give to the 'super' or 'this' constructor followed by the new values * of the constructor arguments */ protected Object[] interpretArguments( final Class c, final ConstructorParametersDescriptor cpd, final Object[] args) { if (cpd.variables == null) { cpd.importationManager.setClassLoader(this.classLoader); final Context ctx = new StaticContext(this, c, cpd.importationManager); ctx.setAdditionalClassLoaderContainer(this.classLoader); final Visitor nv = new NameVisitor(ctx); final Visitor tc = new TypeChecker(ctx); // Check the parameters if (cpd.parameters != null) { final ListIterator it = cpd.parameters.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(tc); } } if (cpd.arguments != null) { ListIterator it = cpd.arguments.listIterator(); while (it.hasNext()) { final Node root = (Node) it.next(); final Object res = root.acceptVisitor(nv); if (res != null) { it.set(res); } } it = cpd.arguments.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(tc); } } cpd.variables = ctx.getCurrentScopeVariables(); } final Context ctx = new StaticContext(this, c, cpd.variables); ctx.setAdditionalClassLoaderContainer(this.classLoader); // Set the arguments values if (cpd.parameters != null) { final Iterator it = cpd.parameters.iterator(); int i = 0; while (it.hasNext()) { ctx.set(((FormalParameter) it.next()).getName(), args[i++]); } } Object[] result = new Object[0]; if (cpd.arguments != null) { final Visitor v = new EvaluationVisitor(ctx); final ListIterator it = cpd.arguments.listIterator(); result = new Object[cpd.arguments.size()]; int i = 0; while (it.hasNext()) { result[i++] = ((Node) it.next()).acceptVisitor(v); } } return result; }
/** * Interprets the body of a method * * @param c the declaring class of the method * @param md the method descriptor * @param obj the object (this) * @param params the arguments */ protected Object interpretMethod( final Class c, final MethodDescriptor md, final Object obj, final Object[] params) { final MethodDeclaration meth = md.method; final List mparams = meth.getParameters(); final List stmts = meth.getBody().getStatements(); final String name = meth.getName(); Context context = null; if (Modifier.isStatic(md.method.getAccessFlags())) { if (md.variables == null) { md.importationManager.setClassLoader(this.classLoader); // pass 1: names resolution Context ctx = new StaticContext(this, c, md.importationManager); ctx.setAdditionalClassLoaderContainer(this.classLoader); Visitor v = new NameVisitor(ctx); ListIterator it = mparams.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } it = stmts.listIterator(); while (it.hasNext()) { final Object o = ((Node) it.next()).acceptVisitor(v); if (o != null) { it.set(o); } } // pass 2: type checking ctx = new StaticContext(this, c, md.importationManager); ctx.setAdditionalClassLoaderContainer(this.classLoader); v = new TypeChecker(ctx); it = mparams.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } it = stmts.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } md.variables = ctx.getCurrentScopeVariables(); // Test of the additional context existence if (!name.equals("<clinit>") && !name.equals("<init>")) { try { md.contextField = c.getField("local$Variables$Reference$0"); } catch (final NoSuchFieldException e) { } } } // pass 3: evaluation context = new StaticContext(this, c, md.variables); } else { if (md.variables == null) { md.importationManager.setClassLoader(this.classLoader); // pass 1: names resolution Context ctx = new MethodContext(this, c, c, md.importationManager); ctx.setAdditionalClassLoaderContainer(this.classLoader); Visitor v = new NameVisitor(ctx); Context ctx2 = new MethodContext(this, c, c, md.importationManager); ctx2.setAdditionalClassLoaderContainer(this.classLoader); Visitor v2 = new NameVisitor(ctx2); // Initializes the context with the outerclass variables Object[][] cc = null; try { final Field f = c.getField("local$Variables$Class$0"); cc = (Object[][]) f.get(obj); for (int i = 0; i < cc.length; i++) { final Object[] cell = cc[i]; if (!((String) cell[0]).equals("this")) { ctx.defineConstant((String) cell[0], cell[1]); } } } catch (final Exception e) { } // Visit the parameters and the body of the method ListIterator it = mparams.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } it = stmts.listIterator(); while (it.hasNext()) { final Node n = (Node) it.next(); Object o = null; if (n.hasProperty(NodeProperties.INSTANCE_INITIALIZER)) { o = n.acceptVisitor(v2); } else { o = n.acceptVisitor(v); } if (o != null) { it.set(o); } } // pass 2: type checking ctx = new MethodContext(this, c, c, md.importationManager); ctx.setAdditionalClassLoaderContainer(this.classLoader); v = new TypeChecker(ctx); ctx2 = new MethodContext(this, c, c, md.importationManager); ctx2.setAdditionalClassLoaderContainer(this.classLoader); v2 = new TypeChecker(ctx2); // Initializes the context with outerclass variables if (cc != null) { for (int i = 0; i < cc.length; i++) { final Object[] cell = cc[i]; if (!((String) cell[0]).equals("this")) { ctx.defineConstant((String) cell[0], cell[1]); } } } // Visit the parameters and the body of the method it = mparams.listIterator(); while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } it = stmts.listIterator(); while (it.hasNext()) { final Node n = (Node) it.next(); if (n.hasProperty(NodeProperties.INSTANCE_INITIALIZER)) { n.acceptVisitor(v2); } else { n.acceptVisitor(v); } } md.variables = ctx.getCurrentScopeVariables(); // Test of the additional context existence if (!name.equals("<clinit>") && !name.equals("<init>")) { try { md.contextField = c.getField("local$Variables$Reference$0"); } catch (final NoSuchFieldException e) { } } } // pass 3: evaluation context = new MethodContext(this, c, obj, md.variables); } context.setAdditionalClassLoaderContainer(this.classLoader); // Set the arguments values Iterator it = mparams.iterator(); int i = 0; while (it.hasNext()) { context.set(((FormalParameter) it.next()).getName(), params[i++]); } // Set the final local variables values if (md.contextField != null) { Map vars = null; try { vars = (Map) md.contextField.get(obj); } catch (final IllegalAccessException e) { } if (vars != null) { it = vars.keySet().iterator(); while (it.hasNext()) { final String s = (String) it.next(); if (!s.equals("this")) { context.setConstant(s, vars.get(s)); } } } } final Visitor v = new EvaluationVisitor(context); it = stmts.iterator(); try { while (it.hasNext()) { ((Node) it.next()).acceptVisitor(v); } } catch (final ReturnException e) { return e.getValue(); } return null; }