diff --git a/mozilla/js/js2/jsc/build/java/makefile b/mozilla/js/js2/jsc/build/java/makefile index f4a6d22da4e..25489f881a1 100644 --- a/mozilla/js/js2/jsc/build/java/makefile +++ b/mozilla/js/js2/jsc/build/java/makefile @@ -27,7 +27,11 @@ generator: javac -d classes -classpath classes ../../src/java/generator/*.java sanity: - java -classpath classes Main -d ../../test/sanity.js + java -classpath classes Main -a ../../test/sanity.js + +testgen: + java -classpath classes Main -d ../../test/ecma-e4/02.expressions/primary.1.js + java -classpath classes Main -d ../../test/ecma-e4/06.functions/function.1.js test: java -classpath classes Main -d ../../test/ecma-e4/02.expressions/primary.1.js @@ -49,3 +53,7 @@ test: java -classpath classes Main -d ../../test/ecma-e4/03.statements/with.1.js java -classpath classes Main -d ../../test/ecma-e4/04.definitions/definition.1.js java -classpath classes Main -d ../../test/ecma-e4/04.definitions/definition.2.js + +test_functions: + java -classpath classes Main -debug -asm ../../test/ecma-e4/06.functions/function.1.js + diff --git a/mozilla/js/js2/jsc/readme b/mozilla/js/js2/jsc/readme index e681ad9e840..b3a44beb350 100644 --- a/mozilla/js/js2/jsc/readme +++ b/mozilla/js/js2/jsc/readme @@ -1,14 +1,13 @@ J S C R E A D M E F I L E Jeff Dyer, Mountain View Compiler Company -Dec-15-2000 +Jan-26-2001 OVERVIEW JSC (JavaScript Compiler) is a stand-alone front-end implementation of the JS2 language specification. Its purpose is to demonstrate how JS2 programs are statically prepared for execution by a JS2 interpreter. -Its output is a psuedo intermediate language suitable for reading by -human beings. +Its output is assembly code that is assembled by the JS engine. BUILDING JSC @@ -31,7 +30,7 @@ utility, such as: If all goes well, the sanity test will run and you will see something like - ../../test/sanity.js: 0 errors [120 msec] --> completion( 0, okay, null ) + ../../test/sanity.js: 0 errors [120 msec] on the last line of the console output. To run more extensive tests, use the build command: @@ -61,22 +60,15 @@ produce a new file given the name of the original source file with the suffix '.jsil' appended to it. Errors are written to a file with the suffix '.err' appended to it. - -STATUS OF JSC - -Dec-1-2000 ----------- -Signficant portions of the type system, compile-time constant evaluator, -and name management systems are working. Missing are semantics for -using, import, export, and unit parsing. More tests are also needed. - - -ISSUES - -* Intermediate form of references, classes, and interfaces. - CHANGES +Jan-26-2001 +----------- +Added first cut at xml icode generation. In particular function definitions, +call and binary expressions are implemented. Object and array literals are +also implemented. Many of the tests used for verifying the parser and semantic +analyzer, are not yet working. + Dec-15-2000 ----------- Removed dependency on sun.tools packages. diff --git a/mozilla/js/js2/jsc/src/java/generator/JSILGenerator.java b/mozilla/js/js2/jsc/src/java/generator/JSILGenerator.java index 4d17fcaf5a9..aaa645b1800 100644 --- a/mozilla/js/js2/jsc/src/java/generator/JSILGenerator.java +++ b/mozilla/js/js2/jsc/src/java/generator/JSILGenerator.java @@ -22,9 +22,10 @@ package com.compilercompany.ecmascript; import java.io.*; +import java.util.*; -/** - * Generates psuedo intermediate code. +/* + * Generates code for the JSVM. */ public class JSILGenerator extends Evaluator implements Tokens { @@ -36,914 +37,1470 @@ public class JSILGenerator extends Evaluator implements Tokens { out = new PrintStream( new FileOutputStream(filename) ); } + private boolean doASM; + public JSILGenerator(boolean doASM) { + this.doASM = doASM; + } + private static void emit(String str) { if( debug ) { - Debugger.trace("emit " + str); + Debugger.trace("emitln " + str); } if( out!=null ) { - out.println(str); + out.print(str); } else { } } + private static void emitln(String str) { + if( out!=null ) { + out.println(""); + emit(str); + } + else { + } + } + + private static String opName(int id) { + String name = ""; + switch(id) { + case plus_token: + name = "Add"; + break; + case minus_token: + name = "Subtract"; + break; + case mult_token: + name = "Multiply"; + break; + case div_token: + name = "Divide"; + break; + case modulus_token: + name = "Remainder"; + break; + case leftshift_token: + name = "LeftShift"; + break; + case rightshift_token: + name = "RightShift"; + break; + case unsignedrightshift_token: + name = "LogicalRightShift"; + break; + case bitwiseand_token: + name = "BitwiseAnd"; + break; + case bitwiseor_token: + name = "BitwiseOr"; + break; + case bitwisexor_token: + name = "BitwiseXor"; + break; + case logicaland_token: + name = "LogicalAnd"; + break; + case logicalor_token: + name = "LogicalOr"; + break; + case logicalxor_token: + name = "LogicalXor"; + break; + case lessthan_token: + name = "Less"; + break; + case lessthanorequals_token: + name = "LessOrEqual"; + break; + case equals_token: + name = "Equal"; + break; + case strictequals_token: + name = "Identical"; + break; + default: + break; + } + return name; + } + + Value evaluate( Context context, Node node ) throws Exception { - String tag = "missing evaluator for " + node.getClass(); emit(context.getIndent()+tag); return null; + String tag = "missing evaluator for " + node.getClass(); emitln(context.getIndent()+tag); return null; } // Expression evaluators + /* + * This reference + */ - Value evaluate( Context context, ThisExpressionNode node ) throws Exception { - String tag = "ThisExpression "; - emit(context.getIndent()+tag); + Value evaluate( Context context, ThisExpressionNode node ) throws Exception { + emitln("this"); return null; } + /* + * Unqualified identifier + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates a dynamic name lookup of an unqualified identifier. + * Identifier nodes that can be statically bound, are converted + * to reference values during constant evaluation, and gen'd as + * static property accesses. + */ + Value evaluate( Context context, IdentifierNode node ) throws Exception { - String tag = "Identifier "; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - emit(context.getIndent()+node.name); - } - context.indent--; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_NAME "+rname+",'"+node.name+"'"); return null; } + /* + * Qualified identifier + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Generates a dynamic name lookup of a qualified identifier. + * Identifier nodes that can be statically bound, are converted + * to reference values during constant evaluation, and gen'd as + * static property accesses. + */ + Value evaluate( Context context, QualifiedIdentifierNode node ) throws Exception { - String tag = "QualifiedIdentifier "; - emit(context.getIndent()+tag); - context.indent++; - if( node.qualifier != null ) { - node.qualifier.evaluate(context,this); - } - if( node.name != null ) { - emit(context.getIndent()+node.name); - } - context.indent--; + if( node.qualifier != null ) { + node.qualifier.evaluate(context,this); + } + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + String qname = Machine.nameRegister(node.qualifier.store); + emitln(context.getIndent()+"LOAD_QNAME "+rname+","+qname+",'"+node.name+"'"); return null; } + /* + * Boolean literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a boolean value. + */ + Value evaluate( Context context, LiteralBooleanNode node ) throws Exception { - String tag = "LiteralBoolean: " + node.value; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_BOOLEAN "+rname+",'"+node.value+"'"); return null; } + /* + * Null literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of null. + */ + Value evaluate( Context context, LiteralNullNode node ) throws Exception { - String tag = "LiteralNull "; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_NULL "+rname); return null; } - Value evaluate( Context context, LiteralNumberNode node ) throws Exception { - String tag = "LiteralNumber: " + node.value; - emit(context.getIndent()+tag); + /* + * Number literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a number. + */ + + Value evaluate( Context context, LiteralNumberNode node ) throws Exception { + Debugger.trace("evaluate(LiteralNumber) with node = "+node); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_IMMEDIATE "+rname+","+node.value); + Debugger.trace("evaluate(LiteralNumber) with node = "+node+", store = " + node.store); return null; } + /* + * String literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a string value. + */ + Value evaluate( Context context, LiteralStringNode node ) throws Exception { - String tag = "LiteralString: " + node.value; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_STRING "+rname+",'"+node.value+"'"); return null; } - Value evaluate( Context context, LiteralUndefinedNode node ) throws Exception { - String tag = "LiteralUndefined "; - emit(context.getIndent()+tag); - return null; - } + /* + * Regular expression literal + * + * STATUS + * Not implemented + */ Value evaluate( Context context, LiteralRegExpNode node ) throws Exception { - String tag = "LiteralRegExp: " + node.value; - emit(context.getIndent()+tag); + if( doASM ) { + } else { + String tag = "LiteralRegExp: " + node.value; + emitln(context.getIndent()+tag); + } return null; } + /* + * Unit expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UnitExpressionNode node ) throws Exception { - String tag = "UnitExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.value != null ) { - node.value.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + if( node.value != null ) { + node.value.evaluate(context,this); + } + if( node.type != null ) { + node.type.evaluate(context,this); + } return null; } + /* + * Parenthesized expression + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Simply evaluates the constituent part. + */ + Value evaluate( Context context, ParenthesizedExpressionNode node ) throws Exception { - String tag = "ParenthesizedExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Parenthesized list expression + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Simply evaluates the constituent part. + */ + Value evaluate( Context context, ParenthesizedListExpressionNode node ) throws Exception { - String tag = "ParenthesizedListExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Function literal + * + * STATUS + * Not implemented. + * + * NOTES + * Generates the code for an anonymous function nested in + * the lexical scope of its definition. + */ + Value evaluate( Context context, FunctionExpressionNode node ) throws Exception { - String tag = "FunctionExpression "; - emit(context.getIndent()+tag); - context.indent++; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_CLOSURE "+rname+",ICodeModule"); + + /* if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.signature != null ) { - node.signature.evaluate(context,this); - } - if( node.body != null ) { - node.body.evaluate(context,this); - } - context.indent--; + node.name.evaluate(context,this); + } + if( node.signature != null ) { + node.signature.evaluate(context,this); + } + if( node.body != null ) { + node.body.evaluate(context,this); + } + */ return null; } + /* + * Object literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates code for object creation and initialization + * to make an object value with the form of the literal. + */ + Value evaluate( Context context, LiteralObjectNode node ) throws Exception { - String tag = "LiteralObject "; - emit(context.getIndent()+tag); - context.indent++; - if( node.fieldlist != null ) { - node.fieldlist.evaluate(context,this); - } - context.indent--; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_OBJECT "+rname+",'Object'"); + + // for each property in value, init a property in the new object. + + ObjectValue value = (ObjectValue) node.value; + Enumeration k = value.slots.keys(); + Enumeration e = value.slots.elements(); + while(k.hasMoreElements()) { + String tname = Machine.nameRegister(new Store(null,Machine.allocateTempRegister())); + Slot s = (Slot) e.nextElement(); + String p = (String) k.nextElement(); + if(s.value.getType(context)==NumberType.type) { + emitln(context.getIndent()+"LOAD_IMMEDIATE "+tname+","+s.value); + } + else + if(s.value.getType(context)==StringType.type) { + emitln(context.getIndent()+"LOAD_STRING "+tname+",'"+s.value+"'"); + } + emitln(context.getIndent()+"SET_PROP "+rname+",'"+p+"',"+tname); + } return null; } - Value evaluate( Context context, LiteralFieldNode node ) throws Exception { - String tag = "LiteralField "; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.value != null ) { - node.value.evaluate(context,this); - } - context.indent--; - return null; - } + /* + * Array literal + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Generates code for object creation and initialization + * to make an object value with the form of the literal. + * [Only handles number and string values.] + */ Value evaluate( Context context, LiteralArrayNode node ) throws Exception { - String tag = "LiteralArray "; - emit(context.getIndent()+tag); - context.indent++; - if( node.elementlist != null ) { - node.elementlist.evaluate(context,this); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_ARRAY "+rname); + + // for each property in value, init a property in the new object. + + if(node.value == null) { + return null; } - context.indent--; + + int p = 0; + ListValue value = (ListValue) node.value; + Enumeration e = value.elements(); + while(e.hasMoreElements()) { + String tname = Machine.nameRegister(new Store(null,Machine.allocateTempRegister())); + Value v = (Value) e.nextElement(); + if(v.getType(context)==NumberType.type) { + emitln(context.getIndent()+"LOAD_IMMEDIATE "+tname+","+v); + } + else + if(v.getType(context)==StringType.type) { + emitln(context.getIndent()+"LOAD_STRING "+tname+",'"+v+"'"); + } + emitln(context.getIndent()+"SET_PROP "+rname+",'"+p+++"',"+tname); + } return null; } + /* + * Postfix expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, PostfixExpressionNode node ) throws Exception { - String tag = "PostfixExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * New expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, NewExpressionNode node ) throws Exception { - String tag = "NewExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Indexed member expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IndexedMemberExpressionNode node ) throws Exception { - String tag = "IndexedMemberExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.base != null ) { + node.base.evaluate(context,this); + } + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Property access + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for getting a property of a value. + */ + Value evaluate( Context context, MemberExpressionNode node ) throws Exception { - String tag = "MemberExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; + if( node.base != null ) { + node.base.evaluate(context,this); + } + String dname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + + rname = Machine.nameRegister(node.base.store); + dname = Machine.nameRegister(node.store); + ReferenceValue ref = (ReferenceValue) node.ref; + emitln(context.getIndent()+"GET_PROP "+ + dname+","+rname+",'"+ref.getName()+"'"); return null; } + /* + * Classof + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for getting the class object of a value. + */ + Value evaluate( Context context, ClassofExpressionNode node ) throws Exception { - String tag = "ClassofExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - context.indent--; + + if( node.base != null ) { + node.base.evaluate(context,this); + } + + String dname,lname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + rname = Machine.nameRegister(node.base.store); + dname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"GET_CLASS "+ + dname+","+rname); return null; } + /* + * Coersion + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for coercing a value to another value of a specific type. + */ + Value evaluate( Context context, CoersionExpressionNode node ) throws Exception { - String tag = "CoersionExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + + Debugger.trace("CoersionExpressionNode with type = " + node.type); + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + + if( node.type != null ) { + node.type.evaluate(context,this); + } + + String dreg,ereg,treg; + node.store = new Store(null,Machine.allocateTempRegister()); + ereg = Machine.nameRegister(node.expr.store); + treg = Machine.nameRegister(node.type.store); + dreg = Machine.nameRegister(node.store); + emitln(context.getIndent()+"CAST "+ + dreg+","+ereg+","+treg); + Debugger.trace("JSILGenerator.evaluate(CoersionExpressionNode) with node.store = " + node.store); return null; } + /* + * Call expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CallExpressionNode node ) throws Exception { - String tag = "CallExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.member != null ) { - node.member.evaluate(context,this); - } - if( node.args != null ) { - node.args.evaluate(context,this); - } - context.indent--; + if( node.member != null ) { + node.member.evaluate(context,this); + } + String args = ""; + Debugger.trace("evaluate(CallExpressionNode) with node.args = " + node.args); + if( node.args != null ) { + node.args.evaluate(context,this); + ListNode list = (ListNode)node.args; + while(list!=null) { + args = Machine.nameRegister(list.item.store)+((args=="")?"":",")+args; + list = (ListNode)list.list; + } + } + node.store = new Store(null,Machine.allocateTempRegister()); + String reg1 = Machine.nameRegister(node.store); + String reg2 = Machine.nameRegister(node.member.store); + emitln(context.getIndent()+"CALL "+ + reg1+","+reg2+",("+args+")"); return null; } + /* + * Unary expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UnaryExpressionNode node ) throws Exception { - String tag = "UnaryExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Binary expression + * + * STATUS + * Partially implemented + */ + Value evaluate( Context context, BinaryExpressionNode node ) throws Exception { - String tag = "BinaryExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.lhs != null ) { + Value rhs,lhs; + + + // compute the lhs value using either + // 1 lhs expression + // 2 unbound reference + // 3 bound reference + + String dname,lname,rname; + + if( node.lhs_slot != null ) { + lname = Machine.nameRegister(node.lhs_slot.store); + } else if ( node.lhs_ref != null ) { + // get the value of the reference and map lname to its location. + lname = "TBD"; + } else { node.lhs.evaluate(context,this); - } - if( node.rhs != null ) { + lname = Machine.nameRegister(node.lhs.store); + } + + if( node.rhs_slot != null ) { + rname = Machine.nameRegister(node.rhs_slot.store); + } else if ( node.rhs_ref != null ) { + // get the value of the reference and map rname to its location. + rname = "TBD"; + } else { node.rhs.evaluate(context,this); - } - context.indent--; + rname = Machine.nameRegister(node.rhs.store); + } + + node.store = new Store(null,Machine.allocateTempRegister()); + dname = Machine.nameRegister(node.store); + + emitln(context.getIndent()+"GENERIC_BINARY_OP "+ + dname+","+opName(node.op)+ + ","+lname + "," + rname); + return null; } + /* + * Conditional expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ConditionalExpressionNode node ) throws Exception { - String tag = "ConditionalExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.condition != null ) { - node.condition.evaluate(context,this); - } - if( node.thenexpr != null ) { - node.thenexpr.evaluate(context,this); - } - if( node.elseexpr != null ) { - node.elseexpr.evaluate(context,this); - } - context.indent--; + if( node.condition != null ) { + node.condition.evaluate(context,this); + } + if( node.thenexpr != null ) { + node.thenexpr.evaluate(context,this); + } + if( node.elseexpr != null ) { + node.elseexpr.evaluate(context,this); + } return null; } + /* + * Assignment expression + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, AssignmentExpressionNode node ) throws Exception { - String tag = "AssignmentExpression: " + ((node.op==empty_token)?"":Token.getTokenClassName(node.op)); - emit(context.getIndent()+tag); - context.indent++; - if( node.lhs != null ) { - node.lhs.evaluate(context,this); + // during constant eval, + // save reference to lhs in node. (key!) + + // 1 Load the rhs value into temporary storage + // 2 Load the lhs value into temporary storage + // 3 Operate (move,generic_binary_op) + // 4 Store the result in the place indicated by the lhs reference. + + if( node.rhs != null ) { + node.rhs.evaluate(context,this); + } + if( node.lhs != null ) { + node.lhs.evaluate(context,this); + } + + String dname,lname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + lname = Machine.nameRegister(node.lhs.store); + rname = Machine.nameRegister(node.rhs.store); + dname = Machine.nameRegister(node.store); + if( node.op == assign_token ) { + emitln(context.getIndent()+"MOVE "+dname+","+rname); + } else { + emitln(context.getIndent()+"GENERIC_BINARY_OP "+dname+",OP,"+lname+","+rname); + } + + ReferenceValue ref = (ReferenceValue) node.ref; + if( ref.scope == null ) { + emitln(context.getIndent()+"SAVE_NAME '"+ + ref.getName()+"',"+dname); + } else { + String bname = Machine.nameRegister(((MemberExpressionNode)node.lhs).base.store); + emitln(context.getIndent()+"SET_PROP "+bname+",'"+ + ref.getName()+"',"+dname); } - if( node.rhs != null ) { - node.rhs.evaluate(context,this); - } - context.indent--; return null; } + /* + * List + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ListNode node ) throws Exception { - String tag = "List"; - //emit(context.getIndent()+tag); - if( node.list != null ) { - node.list.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } + if( node.list != null ) { + node.list.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } // Statements + /* + * Statement list + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, StatementListNode node ) throws Exception { - String tag = "StatementList"; - //emit(context.getIndent()+tag); - if( node.list != null ) { - node.list.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } + if( node.list != null ) { + node.list.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } + /* + * Empty statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, EmptyStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"EmptyStatement"; - emit(context.getIndent()+tag); return null; } + /* + * Expression statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ExpressionStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ExpressionStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Annotated block + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AnnotatedBlockNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"AnnotatedBlock"; - emit(context.getIndent()+tag); - context.indent++; - if( node.attributes != null ) { - node.attributes.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.attributes != null ) { + node.attributes.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Labeled statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, LabeledStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"LabeledStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.label != null ) { - node.label.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.label != null ) { + node.label.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * If statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IfStatementNode node ) throws Exception { - - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"IfStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.condition != null ) { - node.condition.evaluate(context,this); - } - if( node.thenactions != null ) { - node.thenactions.evaluate(context,this); - } - if( node.elseactions != null ) { - node.elseactions.evaluate(context,this); - } - context.indent--; + if( node.condition != null ) { + node.condition.evaluate(context,this); + } + if( node.thenactions != null ) { + node.thenactions.evaluate(context,this); + } + if( node.elseactions != null ) { + node.elseactions.evaluate(context,this); + } return null; } + /* + * Switch statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, SwitchStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"SwitchStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Case label + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CaseLabelNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"CaseLabel"; - emit(context.getIndent()+tag); - context.indent++; - if( node.label != null ) { - node.label.evaluate(context,this); - } else { - emit(context.getIndent()+"default"); - } - context.indent--; + if( node.label != null ) { + node.label.evaluate(context,this); + } else { + emitln(context.getIndent()+"default"); + } return null; } + /* + * Do statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, DoStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"DoStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.statements != null ) { + node.statements.evaluate(context,this); + } + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * While statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, WhileStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"WhileStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * For statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ForStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ForStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.initialize != null ) { - node.initialize.evaluate(context,this); - } - if( node.test != null ) { - node.test.evaluate(context,this); - } - if( node.increment != null ) { - node.increment.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.initialize != null ) { + node.initialize.evaluate(context,this); + } + if( node.test != null ) { + node.test.evaluate(context,this); + } + if( node.increment != null ) { + node.increment.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * For in statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ForInStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ForInStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.property != null ) { - node.property.evaluate(context,this); - } - if( node.object != null ) { - node.object.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.property != null ) { + node.property.evaluate(context,this); + } + if( node.object != null ) { + node.object.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * With statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, WithStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"WithStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * Continue statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ContinueStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ContinueStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Break statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, BreakStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"BreakStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Return statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ReturnStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ReturnStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + String rname = Machine.nameRegister(node.expr.store); + emitln(context.getIndent()+"RETURN "+rname); return null; } + /* + * Throw statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ThrowStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ThrowStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ThrowStatement"; + emitln(context.getIndent()+tag); + context.indent++; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Try statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, TryStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"TryStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.tryblock != null ) { - node.tryblock.evaluate(context,this); - } - if( node.catchlist != null ) { - node.catchlist.evaluate(context,this); - } - if( node.finallyblock != null ) { - node.finallyblock.evaluate(context,this); - } - context.indent--; + if( node.tryblock != null ) { + node.tryblock.evaluate(context,this); + } + if( node.catchlist != null ) { + node.catchlist.evaluate(context,this); + } + if( node.finallyblock != null ) { + node.finallyblock.evaluate(context,this); + } return null; } + /* + * Catch clause + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CatchClauseNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"CatchClause"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Finally clause + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, FinallyClauseNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"FinallyClause"; - emit(context.getIndent()+tag); - context.indent++; - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Use statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UseStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"UseStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Include statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IncludeStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"IncludeStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } // Definitions + /* + * Import definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ImportDefinitionNode node ) throws Exception { - String tag = "ImportDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Import binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ImportBindingNode node ) throws Exception { - String tag = "ImportBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } - context.indent--; + if( node.identifier != null ) { + node.identifier.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } + /* + * Annotated definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AnnotatedDefinitionNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"AnnotatedDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.attributes != null ) { - node.attributes.evaluate(context,this); - } - if( node.definition != null ) { - node.definition.evaluate(context,this); - } - context.indent--; + if( node.attributes != null ) { + node.attributes.evaluate(context,this); + } + if( node.definition != null ) { + node.definition.evaluate(context,this); + } return null; } + /* + * Attribute list + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AttributeListNode node ) throws Exception { - String tag = "AttributeList"; - //emit(context.getIndent()+tag); - //context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - if( node.list != null ) { - node.list.evaluate(context,this); - } - //context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Export definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ExportDefinitionNode node ) throws Exception { - String tag = "ExportDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Export binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ExportBindingNode node ) throws Exception { - String tag = "ExportBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.value != null ) { - node.value.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.value != null ) { + node.value.evaluate(context,this); + } return null; } + /* + * Variable definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, VariableDefinitionNode node ) throws Exception { - String tag = "VariableDefinition: " + Token.getTokenClassName(node.kind); - emit(context.getIndent()+tag); - context.indent++; - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Variable binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, VariableBindingNode node ) throws Exception { - String tag = "VariableBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.variable != null ) { - node.variable.evaluate(context,this); - } - if( node.initializer != null ) { - node.initializer.evaluate(context,this); - } - context.indent--; + if( node.variable != null ) { + node.variable.evaluate(context,this); + } + if( node.initializer != null ) { + node.initializer.evaluate(context,this); + } return null; } + /* + * Typed variable + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, TypedVariableNode node ) throws Exception { - String tag = "TypedVariable"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + if( node.identifier != null ) { + node.identifier.evaluate(context,this); + } + if( node.type != null ) { + node.type.evaluate(context,this); + } return null; } + /* + * Function definition + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionDefinitionNode node ) throws Exception { - String tag = "FunctionDefinition"; - emit(context.getIndent()+tag); + Machine.init(node.fixedCount); + emitln(context.getIndent()+""); return null; } + /* + * Function declaration + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionDeclarationNode node ) throws Exception { - String tag = "FunctionDeclaration"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.signature != null ) { - node.signature.evaluate(context,this); - } - context.indent--; + ReferenceValue ref = (ReferenceValue) node.ref; + emit("name="+ref.getName()); + //if( node.name != null ) { + // node.name.evaluate(context,this); + //} + if( node.signature != null ) { + node.signature.evaluate(context,this); + } return null; } + /* + * Function signature + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionSignatureNode node ) throws Exception { - String tag = "FunctionSignature"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.result != null ) { - node.result.evaluate(context,this); - } - context.indent--; + emit(" type="); + if( node.result != null ) { + ReferenceValue ref = (ReferenceValue) node.ref; + emit(ref.getName()); + } else { + emit("Object"); + } + emit("/>"); + +Debugger.trace("evaluate(FunctionSignatureNode) with node.parameter = " + node.parameter); + + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } return null; } + /* + * Function name + * + * STATUS + * Not used + */ + Value evaluate( Context context, FunctionNameNode node ) throws Exception { - String tag = "FunctionName: " + ((node.kind==empty_token)?"":Token.getTokenClassName(node.kind)); - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; return null; } + /* + * Parameter + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ParameterNode node ) throws Exception { - String tag = "Parameter"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + emitln(context.getIndent()+""); return null; } + /* + * Optional parameter + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, OptionalParameterNode node ) throws Exception { - String tag = "OptionalParameter"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.initializer != null ) { - node.initializer.evaluate(context,this); - } - context.indent--; + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } + if( node.initializer != null ) { + node.initializer.evaluate(context,this); + } return null; } + /* + * Class definition + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ClassDefinitionNode node ) throws Exception { - String tag = "ClassDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.inheritance != null ) { - node.inheritance.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + emitln(""); + context.indent++; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.inheritance != null ) { + node.inheritance.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } + context.indent--; return null; } + /* + * Inheritance definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, InheritanceNode node ) throws Exception { - String tag = "Inheritance"; - emit(context.getIndent()+tag); - context.indent++; - if( node.baseclass != null ) { - node.baseclass.evaluate(context,this); - } - if( node.interfaces != null ) { - node.interfaces.evaluate(context,this); - } - context.indent--; + if( node.baseclass != null ) { + node.baseclass.evaluate(context,this); + } + if( node.interfaces != null ) { + node.interfaces.evaluate(context,this); + } return null; } + /* + * Class declaration + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ClassDeclarationNode node ) throws Exception { - String tag = "ClassDeclaration"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } return null; } + /* + * Namespace definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, NamespaceDefinitionNode node ) throws Exception { - String tag = "NamespaceDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.extendslist != null ) { - node.extendslist.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.extendslist != null ) { + node.extendslist.evaluate(context,this); + } return null; } + /* + * Package definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, PackageDefinitionNode node ) throws Exception { - String tag = "PackageDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Program + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ProgramNode node ) throws Exception { - if( node.statements != null ) { - String tag = "Program"; - emit(context.getIndent()+tag); - context.indent++; - node.statements.evaluate(context,this); - context.indent--; - } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } } +/* + * Static model of the virtual machine. + */ + +class Machine { + + private static boolean debug = true; + + static int registerCount; + static int fixedRegisterCount; + + static void init(int fixedCount) { + Debugger.trace("Machine.init() with fixedCount = " + fixedCount); + registerCount = fixedRegisterCount = fixedCount; + } + + static int allocateTempRegister() { + return registerCount++; + } + + static void resetTempRegisters() { + } + + static void resetAllRegisters() { + } + + static String nameRegister(Store store) { + return "R"+ (store.index+1); + } + + static String nameTemp() { + return "R"+ (registerCount+1); + } +} + /* * The end. */ diff --git a/mozilla/js/js2/jsc/src/java/main/Main.java b/mozilla/js/js2/jsc/src/java/main/Main.java index 7814d7e2601..cceefdd1142 100644 --- a/mozilla/js/js2/jsc/src/java/main/Main.java +++ b/mozilla/js/js2/jsc/src/java/main/Main.java @@ -47,6 +47,7 @@ public class Main { private static boolean traceInput = false; private static boolean traceLexer = false; private static boolean traceParser = false; + private static boolean doASM = false; private static boolean debug = false; @@ -67,6 +68,8 @@ public class Main { traceParser = true; } else if (args[i].equals("-d")||args[i].equals("-debug")) { debug = true; + } else if (args[i].equals("-a")||args[i].equals("-asm")) { + doASM = true; } else if (args[i].charAt(0) == '-') { System.out.println("Unknown.option "+ args[i]); } else { @@ -148,7 +151,7 @@ public class Main { if( traceParser ) { Debugger.trace("setting parser output to " + input[i]); JSILGenerator.setOut( input[i]+".par" ); - node.evaluate(context,new JSILGenerator()); + node.evaluate(context,new JSILGenerator(false)); } //Evaluator evaluator; @@ -157,14 +160,14 @@ public class Main { context.setEvaluator(new BlockEvaluator()); node.evaluate(context, context.getEvaluator()); - JSILGenerator.setOut( input[i]+".blocks" ); - context.setEvaluator(new JSILGenerator()); - node.evaluate(context, context.getEvaluator()); + //JSILGenerator.setOut( input[i]+".blocks" ); + //context.setEvaluator(new JSILGenerator(false)); + //node.evaluate(context, context.getEvaluator()); context.setEvaluator(new ConstantEvaluator()); value = node.evaluate(context, context.getEvaluator()); - context.setEvaluator(new JSILGenerator()); + context.setEvaluator(new JSILGenerator(doASM)); JSILGenerator.setOut( input[i]+".jsil" ); node.evaluate(context, context.getEvaluator()); errorCount = context.errorCount(); @@ -172,7 +175,7 @@ public class Main { t = System.currentTimeMillis() - t; //Debugger.trace(""+global); - System.out.println(input[i] + ": "+ errorCount +" errors [" + Long.toString(t) + " msec] --> " + value.getValue(context) ); + System.out.println(input[i] + ": "+ errorCount +" errors [" + Long.toString(t) + " msec]"); } catch( Exception x ) { x.printStackTrace(); diff --git a/mozilla/js/js2/jsc/src/java/parser/Node.java b/mozilla/js/js2/jsc/src/java/parser/Node.java index 5272bd10978..7bdeaf963dc 100644 --- a/mozilla/js/js2/jsc/src/java/parser/Node.java +++ b/mozilla/js/js2/jsc/src/java/parser/Node.java @@ -32,6 +32,7 @@ public class Node { Block block; int position; + Store store; public Node() { } diff --git a/mozilla/js/js2/jsc/src/java/parser/NodeFactory.java b/mozilla/js/js2/jsc/src/java/parser/NodeFactory.java index 20d02c8bf38..20e47f60457 100644 --- a/mozilla/js/js2/jsc/src/java/parser/NodeFactory.java +++ b/mozilla/js/js2/jsc/src/java/parser/NodeFactory.java @@ -102,9 +102,6 @@ public final class NodeFactory { static SuperExpressionNode SuperExpression() { return new SuperExpressionNode(); } - static EvalExpressionNode EvalExpression( Node expr ) { - return new EvalExpressionNode(expr); - } static ListNode List( Node list, Node item ) { return new ListNode(list,item,item.pos()); } diff --git a/mozilla/js/js2/jsc/src/java/parser/Nodes.java b/mozilla/js/js2/jsc/src/java/parser/Nodes.java index dd22da325b5..2507689d9f8 100644 --- a/mozilla/js/js2/jsc/src/java/parser/Nodes.java +++ b/mozilla/js/js2/jsc/src/java/parser/Nodes.java @@ -86,6 +86,7 @@ final class AssignmentExpressionNode extends Node implements Tokens { Node lhs, rhs; int op; + /*Reference*/Value ref; AssignmentExpressionNode( Node lhs, int op, Node rhs ) { this.lhs = lhs; @@ -139,6 +140,8 @@ final class BinaryExpressionNode extends Node { protected Node lhs, rhs; protected int op; + Value lhs_ref,rhs_ref; + Slot lhs_slot,rhs_slot; BinaryExpressionNode( int op, Node lhs, Node rhs ) { this.op = op; @@ -331,6 +334,7 @@ final class ClassofExpressionNode extends Node { final class CoersionExpressionNode extends Node { Node expr, type; + String typename; CoersionExpressionNode( Node expr, Node type, int pos ) { super(pos); @@ -427,11 +431,11 @@ final class DoStatementNode extends Node { final class ElementListNode extends Node { - Node list, expr; + Node list, item; - ElementListNode( Node list, Node expr ) { + ElementListNode( Node list, Node item ) { this.list = list; - this.expr = expr; + this.item = item; } public Value evaluate( Context context, Evaluator evaluator ) throws Exception { @@ -439,7 +443,7 @@ final class ElementListNode extends Node { } public String toString() { - return "elementlist( " + list + ", " + expr + " )"; + return "elementlist( " + list + ", " + item + " )"; } } @@ -479,27 +483,6 @@ final class ExpressionStatementNode extends Node { } } -/** - * EvalExpressionNode - */ - -final class EvalExpressionNode extends Node { - - Node expr; - - EvalExpressionNode( Node expr ) { - this.expr = expr; - } - - public Value evaluate( Context context, Evaluator evaluator ) throws Exception { - return evaluator.evaluate( context, this ); - } - - public String toString() { - return "evalexpression( " + expr + " )"; - } -} - /** * ExportBindingNode */ @@ -726,6 +709,7 @@ final class FunctionDeclarationNode extends Node { Node name, signature; Slot slot; + /*Reference*/Value ref; FunctionDeclarationNode( Node name, Node signature ) { this.name = name; @@ -748,6 +732,7 @@ final class FunctionDeclarationNode extends Node { final class FunctionDefinitionNode extends Node { Node decl, body; + int fixedCount; FunctionDefinitionNode( Node decl, Node body ) { this.decl = decl; @@ -782,7 +767,7 @@ final class FunctionNameNode extends Node { FunctionNameNode( int kind, Node name ) { this.kind = kind; - this.name = name; + this.name = (IdentifierNode)name; } public Value evaluate( Context context, Evaluator evaluator ) throws Exception { @@ -802,6 +787,7 @@ final class FunctionSignatureNode extends Node { Node parameter, result; Slot slot; + Value ref; FunctionSignatureNode( Node parameter, Node result ) { this.parameter = parameter; @@ -824,6 +810,7 @@ final class FunctionSignatureNode extends Node { class IdentifierNode extends Node { String name; + /*Reference*/Value ref; IdentifierNode( String name, int pos ) { super(pos); @@ -1128,6 +1115,7 @@ final class ListNode extends Node { final class LiteralArrayNode extends Node { Node elementlist; + /*List*/Value value; LiteralArrayNode( Node elementlist ) { this.elementlist = elementlist; @@ -1171,6 +1159,7 @@ final class LiteralFieldNode extends Node { Node name; Node value; + /*Reference*/Value ref; LiteralFieldNode( Node name, Node value ) { this.name = name; @@ -1232,6 +1221,7 @@ final class LiteralNumberNode extends Node { final class LiteralObjectNode extends Node { Node fieldlist; + /*Object*/Value value; LiteralObjectNode( Node fieldlist ) { this.fieldlist = fieldlist; @@ -1334,6 +1324,7 @@ final class LiteralUndefinedNode extends Node { final class MemberExpressionNode extends Node { Node base, name; + /*Reference*/Value ref; MemberExpressionNode( Node base, Node name, int pos ) { super(pos); @@ -1474,6 +1465,7 @@ final class ParameterNode extends Node { Node identifier; Node type; Slot slot; + String name; ParameterNode( Node identifier, Node type ) { this.identifier = identifier; diff --git a/mozilla/js/js2/jsc/src/java/parser/Slot.java b/mozilla/js/js2/jsc/src/java/parser/Slot.java index d1727d0deb2..5c23a8f47a2 100644 --- a/mozilla/js/js2/jsc/src/java/parser/Slot.java +++ b/mozilla/js/js2/jsc/src/java/parser/Slot.java @@ -31,9 +31,10 @@ public class Slot { Value type; Value value; Block block; + Store store; public String toString() { - return "{ "+attrs+", "+type+", "+value+" }"; + return "{ "+attrs+", "+type+", "+value+", "+store+" }"; } } diff --git a/mozilla/js/js2/jsc/src/java/parser/Store.java b/mozilla/js/js2/jsc/src/java/parser/Store.java new file mode 100644 index 00000000000..30f3ca36fb0 --- /dev/null +++ b/mozilla/js/js2/jsc/src/java/parser/Store.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Mountain View Compiler + * Company. Portions created by Mountain View Compiler Company are + * Copyright (C) 1998-2000 Mountain View Compiler Company. All + * Rights Reserved. + * + * Contributor(s): + * Jeff Dyer + */ + +package com.compilercompany.ecmascript; + +/** + * Represents an abstract unit of storage. + */ + +public class Store { + Scope scope; + int index; + + Store(Scope scope, int index) { + this.scope = scope; + this.index = index; + } + + public String toString() { + return "store( " + index + " )"; + } +} + +/* + * The end. + */ diff --git a/mozilla/js/js2/jsc/src/java/parser/Value.java b/mozilla/js/js2/jsc/src/java/parser/Value.java index b2429b07f9c..f7f1c88874c 100644 --- a/mozilla/js/js2/jsc/src/java/parser/Value.java +++ b/mozilla/js/js2/jsc/src/java/parser/Value.java @@ -95,6 +95,10 @@ abstract public class Value implements Scope { */ } + int size() { + return 0; + } + public Value construct(Context context, Value args) throws Exception { throw new Exception("Constructor object expected in new expression"); } diff --git a/mozilla/js/js2/jsc/src/java/semantics/ConstantEvaluator.java b/mozilla/js/js2/jsc/src/java/semantics/ConstantEvaluator.java index 4fdf52254f5..372ab40bd5a 100644 --- a/mozilla/js/js2/jsc/src/java/semantics/ConstantEvaluator.java +++ b/mozilla/js/js2/jsc/src/java/semantics/ConstantEvaluator.java @@ -44,6 +44,10 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { /** * IdentifierNode + * + * The reference value serves as a weak alias to the object being + * bound to. It is interpreted by its context (e.g. a member expr + * as a selector for a member of the base activation frame. */ Value evaluate( Context context, IdentifierNode node ) throws Exception { @@ -304,7 +308,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating LiteralObjectNode = " + node); } - Value value; + ObjectValue value; Type type; type = new ObjectType(""); @@ -316,6 +320,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { context.popScope(); } + node.value = value; // save it for code generation. + return value; } @@ -376,17 +382,19 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating LiteralArrayNode = " + node); } - Value value; + ListValue value; Type type; type = ArrayType.type; if( node.elementlist != null ) { - value = node.elementlist.evaluate(context,this); + value = (ListValue)node.elementlist.evaluate(context,this); } else { - value = NullValue.nullValue; + value = null; } + node.value = value; // save for code generation. + return type.convert(context,value); } @@ -407,6 +415,41 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { testEvaluator("ArrayLiteral",input,expected); } + /** + * ElementListNode + */ + + Value evaluate( Context context, ElementListNode node ) throws Exception { + + if( debug ) { + Debugger.trace("evaluating ElementListNode = " + node); + } + + ListValue list; + + if( node.list != null ) { + if( node.list instanceof ListNode ) { + list = (ListValue) node.list.evaluate(context,this); + } else { + list = new ListValue(); + list.push(node.list.evaluate(context,this)); + } + } + else { + list = new ListValue(); + } + + if( node.item != null ) { + list.push(node.item.evaluate(context,this)); + } + else { + // do nothing. + } + + return list; + + } + /** * PostfixExpressionNode * @@ -492,6 +535,10 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { * MemberExpressionNode * * { base:NewSubexpressionNode name:IdentifierNode } + * + * A member expression evaluates to a reference value. If the value of the + * reference is a compile-time constant, then return the value as a literal. + * Otherwise return undefined. */ Value evaluate( Context context, MemberExpressionNode node ) throws Exception { @@ -502,17 +549,18 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Value value; Value base; - ReferenceValue ref; String name; base = node.base.evaluate(context,this).getValue(context); value = node.name.evaluate(context,this); - if( value instanceof ReferenceValue ) { - ref = (ReferenceValue) value; - ref.scope = base; + if( !UndefinedType.type.includes(base) && + value instanceof ReferenceValue ) { + ((ReferenceValue)value).scope = base; + node.ref = value; } else { - error(context,0,"Expecting reference expression after dot operator.",node.name.pos()); + value = UndefinedValue.undefinedValue; + //error(context,0,"Expecting reference expression after dot operator.",node.name.pos()); } return value; @@ -665,7 +713,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { callee = node.member.evaluate(context,this).getValue(context); if( node.args != null ) { - args = node.args.evaluate(context,this); + args = node.args.evaluate(context,this); } if( !FunctionType.type.includes(callee) ) { @@ -704,6 +752,27 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { if( debug ) { Debugger.trace("evaluating BinaryExpressionNode = " + node); } + + // if rhs is a constant, then replace with a literal. + // if it is a local definition, then load it directly. + // otherwise, put result in temporary and use it directly. + + + Value value; + + value = node.lhs.evaluate(context,this); + if( value instanceof ReferenceValue ) { + node.lhs = null; + node.lhs_ref = value; + node.lhs_slot = ((ReferenceValue)value).getSlot(context); + } + value = node.rhs.evaluate(context,this); + if( value instanceof ReferenceValue ) { + node.rhs = null; + node.rhs_ref = value; + node.rhs_slot = ((ReferenceValue)value).getSlot(context); + } + return UndefinedValue.undefinedValue; } @@ -735,11 +804,14 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Value value = UndefinedValue.undefinedValue; if( lref != UndefinedValue.undefinedValue ) { Slot slot = ((ReferenceValue)lref).getSlot(context); - Debugger.trace("slot " + slot); + Debugger.trace("ConstantEvaluator.evaluat(AssignmentExpression) with slot " + slot); if( slot != null ) { Value rref = node.rhs.evaluate(context,this); slot.value = rref.getValue(context); } + node.ref = (ReferenceValue)lref; + } else { + throw new Exception("internal error: assignment lhs is not a reference."); } return value; @@ -1079,6 +1151,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating ReturnStatementNode = " + node); } + node.expr.evaluate(context,this); + return new CodeValue(node); } @@ -1208,7 +1282,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { static { try { - namespace_parameters = new ObjectValue(new NamespaceType("_parameters_")); + namespace_parameters = new ObjectValue(new TypeValue(new NamespaceType("_parameters_"))); } catch ( Exception x ) { x.printStackTrace(); Debugger.trace("oops, something is not right."); @@ -1577,12 +1651,17 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { * 2. Save result in code slot. */ + private int local_offset; + public Value evaluate( Context context, FunctionDefinitionNode node ) throws Exception { if( debug ) { Debugger.trace( "evaluating FunctionDefinitionNode: " + node ); } + local_offset = 0; // start a new activation frame. + + used_namespaces.addElement(namespace_parameters); Value value = node.decl.evaluate(context,this); if( node.body!=null) { @@ -1595,6 +1674,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { context.popScope(); } + node.fixedCount = local_offset; + return UndefinedValue.undefinedValue; } @@ -1633,7 +1714,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace( "evaluating FunctionDeclarationNode: " + node ); } - ReferenceValue ref = (ReferenceValue) node.name.evaluate(context,this); + ReferenceValue ref; + node.ref = ref = (ReferenceValue) node.name.evaluate(context,this); String name = ref.getName(); ref.scope = context.getLocal(); @@ -1747,20 +1829,21 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Scope local = context.getLocal(); node.slot = local.add(namespace_parameters,"_result_"); - Value result; + Value type; if( node.result!=null ) { - result = node.result.evaluate(context,this).getValue(context); + node.ref = node.result.evaluate(context,this); + type = node.ref.getValue(context); } else { - result = ObjectType.type; + type = ObjectType.type; } - if( !TypeType.type.includes(result) ) { - error(context,"Result type expression does not evaluate to a type. result = " + result.type,node.pos()); + if( !TypeType.type.includes(type) ) { + error(context,"Result type expression does not evaluate to a type. result = " + type.type,node.pos()); } - node.slot.type = (TypeValue) result; + node.slot.type = type; - return result; + return type; } /** @@ -1783,8 +1866,9 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { ref = (ReferenceValue) node.identifier.evaluate(context,this); name = ref.getName(); - node.slot = local.add(namespace_parameters,name); - //node.identifier.slot.block = context.getBlock(); + node.slot = local.add(namespace_parameters,name); + node.slot.store = new Store(local,local_offset++); + node.name = name; // for code generation. return ref; } @@ -2338,6 +2422,7 @@ class Flow { } return preds; } + } /* diff --git a/mozilla/js/js2/jsc/src/java/semantics/values/ObjectValue.java b/mozilla/js/js2/jsc/src/java/semantics/values/ObjectValue.java index 83fa043fa82..62c227d9b70 100644 --- a/mozilla/js/js2/jsc/src/java/semantics/values/ObjectValue.java +++ b/mozilla/js/js2/jsc/src/java/semantics/values/ObjectValue.java @@ -176,6 +176,14 @@ public class ObjectValue extends Value implements Attributes, Scope { return slot; } + /** + * + */ + + int size() { + return slots.size(); + } + /** * */ diff --git a/mozilla/js/js2/jsc/src/java/semantics/values/ReferenceValue.java b/mozilla/js/js2/jsc/src/java/semantics/values/ReferenceValue.java index 4605bd1cf1b..8cd2f67e1f3 100644 --- a/mozilla/js/js2/jsc/src/java/semantics/values/ReferenceValue.java +++ b/mozilla/js/js2/jsc/src/java/semantics/values/ReferenceValue.java @@ -45,7 +45,7 @@ public class ReferenceValue extends Value { if( debug ) { Debugger.trace( "creating reference scope = " + scope + - " name = " + name + " namespaces = " + namespaces ); + " name = " + name + " used_namespaces = " + namespaces ); } this.scope = scope; @@ -91,6 +91,10 @@ public class ReferenceValue extends Value { break; } } + + if( slot==null ) { + slot = scope.get(qualifier/*=null*/,name); + } } if( debug ) { Debugger.trace("leaving getSlotInScope() with slot="+slot); diff --git a/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/binary.1.js b/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/binary.1.js index accd34d9cbd..e739de8cf89 100644 --- a/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/binary.1.js +++ b/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/binary.1.js @@ -60,5 +60,6 @@ function run() { } /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */ diff --git a/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js b/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js index d9a75434716..d95e49ce9cb 100644 --- a/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js +++ b/mozilla/js/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js @@ -7,17 +7,18 @@ function title() { } function run() { - a.b::c.d[e](f,g)[h].i++; + //a.b::c.d[e](f,g)[h].i++; delete p; void 0; typeof ob; - ++a.b--; - --a.b++; + //++a.b--; + //--a.b++; +a; -a; !a; } /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */ diff --git a/mozilla/js/js2/jsc/test/ecma-e4/04.definitions/definition.1.js b/mozilla/js/js2/jsc/test/ecma-e4/04.definitions/definition.1.js index a1e03fa47b2..1b72bf9dba8 100644 --- a/mozilla/js/js2/jsc/test/ecma-e4/04.definitions/definition.1.js +++ b/mozilla/js/js2/jsc/test/ecma-e4/04.definitions/definition.1.js @@ -32,5 +32,5 @@ unit const liter = makeLiter; showerrors unit const liter = Unit.dm.pow(3); /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. All rights reserved. */ diff --git a/mozilla/js/js2/jsc/test/sanity.js b/mozilla/js/js2/jsc/test/sanity.js index a8ddb681f4f..a0a7fb90647 100644 --- a/mozilla/js/js2/jsc/test/sanity.js +++ b/mozilla/js/js2/jsc/test/sanity.js @@ -2,18 +2,19 @@ * Sanity test. */ -const result = 'okay'; - function title() { return "sanity"; } - -function run() { +function g(a,b) { + return a+b; } -result; +function run() { + return g(1,2); +} -/** - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. +/* + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */ diff --git a/mozilla/js2/jsc/build/java/makefile b/mozilla/js2/jsc/build/java/makefile index f4a6d22da4e..25489f881a1 100644 --- a/mozilla/js2/jsc/build/java/makefile +++ b/mozilla/js2/jsc/build/java/makefile @@ -27,7 +27,11 @@ generator: javac -d classes -classpath classes ../../src/java/generator/*.java sanity: - java -classpath classes Main -d ../../test/sanity.js + java -classpath classes Main -a ../../test/sanity.js + +testgen: + java -classpath classes Main -d ../../test/ecma-e4/02.expressions/primary.1.js + java -classpath classes Main -d ../../test/ecma-e4/06.functions/function.1.js test: java -classpath classes Main -d ../../test/ecma-e4/02.expressions/primary.1.js @@ -49,3 +53,7 @@ test: java -classpath classes Main -d ../../test/ecma-e4/03.statements/with.1.js java -classpath classes Main -d ../../test/ecma-e4/04.definitions/definition.1.js java -classpath classes Main -d ../../test/ecma-e4/04.definitions/definition.2.js + +test_functions: + java -classpath classes Main -debug -asm ../../test/ecma-e4/06.functions/function.1.js + diff --git a/mozilla/js2/jsc/readme b/mozilla/js2/jsc/readme index e681ad9e840..b3a44beb350 100644 --- a/mozilla/js2/jsc/readme +++ b/mozilla/js2/jsc/readme @@ -1,14 +1,13 @@ J S C R E A D M E F I L E Jeff Dyer, Mountain View Compiler Company -Dec-15-2000 +Jan-26-2001 OVERVIEW JSC (JavaScript Compiler) is a stand-alone front-end implementation of the JS2 language specification. Its purpose is to demonstrate how JS2 programs are statically prepared for execution by a JS2 interpreter. -Its output is a psuedo intermediate language suitable for reading by -human beings. +Its output is assembly code that is assembled by the JS engine. BUILDING JSC @@ -31,7 +30,7 @@ utility, such as: If all goes well, the sanity test will run and you will see something like - ../../test/sanity.js: 0 errors [120 msec] --> completion( 0, okay, null ) + ../../test/sanity.js: 0 errors [120 msec] on the last line of the console output. To run more extensive tests, use the build command: @@ -61,22 +60,15 @@ produce a new file given the name of the original source file with the suffix '.jsil' appended to it. Errors are written to a file with the suffix '.err' appended to it. - -STATUS OF JSC - -Dec-1-2000 ----------- -Signficant portions of the type system, compile-time constant evaluator, -and name management systems are working. Missing are semantics for -using, import, export, and unit parsing. More tests are also needed. - - -ISSUES - -* Intermediate form of references, classes, and interfaces. - CHANGES +Jan-26-2001 +----------- +Added first cut at xml icode generation. In particular function definitions, +call and binary expressions are implemented. Object and array literals are +also implemented. Many of the tests used for verifying the parser and semantic +analyzer, are not yet working. + Dec-15-2000 ----------- Removed dependency on sun.tools packages. diff --git a/mozilla/js2/jsc/src/java/generator/JSILGenerator.java b/mozilla/js2/jsc/src/java/generator/JSILGenerator.java index 4d17fcaf5a9..aaa645b1800 100644 --- a/mozilla/js2/jsc/src/java/generator/JSILGenerator.java +++ b/mozilla/js2/jsc/src/java/generator/JSILGenerator.java @@ -22,9 +22,10 @@ package com.compilercompany.ecmascript; import java.io.*; +import java.util.*; -/** - * Generates psuedo intermediate code. +/* + * Generates code for the JSVM. */ public class JSILGenerator extends Evaluator implements Tokens { @@ -36,914 +37,1470 @@ public class JSILGenerator extends Evaluator implements Tokens { out = new PrintStream( new FileOutputStream(filename) ); } + private boolean doASM; + public JSILGenerator(boolean doASM) { + this.doASM = doASM; + } + private static void emit(String str) { if( debug ) { - Debugger.trace("emit " + str); + Debugger.trace("emitln " + str); } if( out!=null ) { - out.println(str); + out.print(str); } else { } } + private static void emitln(String str) { + if( out!=null ) { + out.println(""); + emit(str); + } + else { + } + } + + private static String opName(int id) { + String name = ""; + switch(id) { + case plus_token: + name = "Add"; + break; + case minus_token: + name = "Subtract"; + break; + case mult_token: + name = "Multiply"; + break; + case div_token: + name = "Divide"; + break; + case modulus_token: + name = "Remainder"; + break; + case leftshift_token: + name = "LeftShift"; + break; + case rightshift_token: + name = "RightShift"; + break; + case unsignedrightshift_token: + name = "LogicalRightShift"; + break; + case bitwiseand_token: + name = "BitwiseAnd"; + break; + case bitwiseor_token: + name = "BitwiseOr"; + break; + case bitwisexor_token: + name = "BitwiseXor"; + break; + case logicaland_token: + name = "LogicalAnd"; + break; + case logicalor_token: + name = "LogicalOr"; + break; + case logicalxor_token: + name = "LogicalXor"; + break; + case lessthan_token: + name = "Less"; + break; + case lessthanorequals_token: + name = "LessOrEqual"; + break; + case equals_token: + name = "Equal"; + break; + case strictequals_token: + name = "Identical"; + break; + default: + break; + } + return name; + } + + Value evaluate( Context context, Node node ) throws Exception { - String tag = "missing evaluator for " + node.getClass(); emit(context.getIndent()+tag); return null; + String tag = "missing evaluator for " + node.getClass(); emitln(context.getIndent()+tag); return null; } // Expression evaluators + /* + * This reference + */ - Value evaluate( Context context, ThisExpressionNode node ) throws Exception { - String tag = "ThisExpression "; - emit(context.getIndent()+tag); + Value evaluate( Context context, ThisExpressionNode node ) throws Exception { + emitln("this"); return null; } + /* + * Unqualified identifier + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates a dynamic name lookup of an unqualified identifier. + * Identifier nodes that can be statically bound, are converted + * to reference values during constant evaluation, and gen'd as + * static property accesses. + */ + Value evaluate( Context context, IdentifierNode node ) throws Exception { - String tag = "Identifier "; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - emit(context.getIndent()+node.name); - } - context.indent--; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_NAME "+rname+",'"+node.name+"'"); return null; } + /* + * Qualified identifier + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Generates a dynamic name lookup of a qualified identifier. + * Identifier nodes that can be statically bound, are converted + * to reference values during constant evaluation, and gen'd as + * static property accesses. + */ + Value evaluate( Context context, QualifiedIdentifierNode node ) throws Exception { - String tag = "QualifiedIdentifier "; - emit(context.getIndent()+tag); - context.indent++; - if( node.qualifier != null ) { - node.qualifier.evaluate(context,this); - } - if( node.name != null ) { - emit(context.getIndent()+node.name); - } - context.indent--; + if( node.qualifier != null ) { + node.qualifier.evaluate(context,this); + } + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + String qname = Machine.nameRegister(node.qualifier.store); + emitln(context.getIndent()+"LOAD_QNAME "+rname+","+qname+",'"+node.name+"'"); return null; } + /* + * Boolean literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a boolean value. + */ + Value evaluate( Context context, LiteralBooleanNode node ) throws Exception { - String tag = "LiteralBoolean: " + node.value; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_BOOLEAN "+rname+",'"+node.value+"'"); return null; } + /* + * Null literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of null. + */ + Value evaluate( Context context, LiteralNullNode node ) throws Exception { - String tag = "LiteralNull "; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_NULL "+rname); return null; } - Value evaluate( Context context, LiteralNumberNode node ) throws Exception { - String tag = "LiteralNumber: " + node.value; - emit(context.getIndent()+tag); + /* + * Number literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a number. + */ + + Value evaluate( Context context, LiteralNumberNode node ) throws Exception { + Debugger.trace("evaluate(LiteralNumber) with node = "+node); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_IMMEDIATE "+rname+","+node.value); + Debugger.trace("evaluate(LiteralNumber) with node = "+node+", store = " + node.store); return null; } + /* + * String literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates an immediate load of a string value. + */ + Value evaluate( Context context, LiteralStringNode node ) throws Exception { - String tag = "LiteralString: " + node.value; - emit(context.getIndent()+tag); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"LOAD_STRING "+rname+",'"+node.value+"'"); return null; } - Value evaluate( Context context, LiteralUndefinedNode node ) throws Exception { - String tag = "LiteralUndefined "; - emit(context.getIndent()+tag); - return null; - } + /* + * Regular expression literal + * + * STATUS + * Not implemented + */ Value evaluate( Context context, LiteralRegExpNode node ) throws Exception { - String tag = "LiteralRegExp: " + node.value; - emit(context.getIndent()+tag); + if( doASM ) { + } else { + String tag = "LiteralRegExp: " + node.value; + emitln(context.getIndent()+tag); + } return null; } + /* + * Unit expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UnitExpressionNode node ) throws Exception { - String tag = "UnitExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.value != null ) { - node.value.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + if( node.value != null ) { + node.value.evaluate(context,this); + } + if( node.type != null ) { + node.type.evaluate(context,this); + } return null; } + /* + * Parenthesized expression + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Simply evaluates the constituent part. + */ + Value evaluate( Context context, ParenthesizedExpressionNode node ) throws Exception { - String tag = "ParenthesizedExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Parenthesized list expression + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Simply evaluates the constituent part. + */ + Value evaluate( Context context, ParenthesizedListExpressionNode node ) throws Exception { - String tag = "ParenthesizedListExpression "; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Function literal + * + * STATUS + * Not implemented. + * + * NOTES + * Generates the code for an anonymous function nested in + * the lexical scope of its definition. + */ + Value evaluate( Context context, FunctionExpressionNode node ) throws Exception { - String tag = "FunctionExpression "; - emit(context.getIndent()+tag); - context.indent++; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_CLOSURE "+rname+",ICodeModule"); + + /* if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.signature != null ) { - node.signature.evaluate(context,this); - } - if( node.body != null ) { - node.body.evaluate(context,this); - } - context.indent--; + node.name.evaluate(context,this); + } + if( node.signature != null ) { + node.signature.evaluate(context,this); + } + if( node.body != null ) { + node.body.evaluate(context,this); + } + */ return null; } + /* + * Object literal + * + * STATUS + * Jan-03-2001: Coded + * + * NOTES + * Generates code for object creation and initialization + * to make an object value with the form of the literal. + */ + Value evaluate( Context context, LiteralObjectNode node ) throws Exception { - String tag = "LiteralObject "; - emit(context.getIndent()+tag); - context.indent++; - if( node.fieldlist != null ) { - node.fieldlist.evaluate(context,this); - } - context.indent--; + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_OBJECT "+rname+",'Object'"); + + // for each property in value, init a property in the new object. + + ObjectValue value = (ObjectValue) node.value; + Enumeration k = value.slots.keys(); + Enumeration e = value.slots.elements(); + while(k.hasMoreElements()) { + String tname = Machine.nameRegister(new Store(null,Machine.allocateTempRegister())); + Slot s = (Slot) e.nextElement(); + String p = (String) k.nextElement(); + if(s.value.getType(context)==NumberType.type) { + emitln(context.getIndent()+"LOAD_IMMEDIATE "+tname+","+s.value); + } + else + if(s.value.getType(context)==StringType.type) { + emitln(context.getIndent()+"LOAD_STRING "+tname+",'"+s.value+"'"); + } + emitln(context.getIndent()+"SET_PROP "+rname+",'"+p+"',"+tname); + } return null; } - Value evaluate( Context context, LiteralFieldNode node ) throws Exception { - String tag = "LiteralField "; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.value != null ) { - node.value.evaluate(context,this); - } - context.indent--; - return null; - } + /* + * Array literal + * + * STATUS + * Jan-09-2001: Coded + * + * NOTES + * Generates code for object creation and initialization + * to make an object value with the form of the literal. + * [Only handles number and string values.] + */ Value evaluate( Context context, LiteralArrayNode node ) throws Exception { - String tag = "LiteralArray "; - emit(context.getIndent()+tag); - context.indent++; - if( node.elementlist != null ) { - node.elementlist.evaluate(context,this); + node.store = new Store(null,Machine.allocateTempRegister()); + String rname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"NEW_ARRAY "+rname); + + // for each property in value, init a property in the new object. + + if(node.value == null) { + return null; } - context.indent--; + + int p = 0; + ListValue value = (ListValue) node.value; + Enumeration e = value.elements(); + while(e.hasMoreElements()) { + String tname = Machine.nameRegister(new Store(null,Machine.allocateTempRegister())); + Value v = (Value) e.nextElement(); + if(v.getType(context)==NumberType.type) { + emitln(context.getIndent()+"LOAD_IMMEDIATE "+tname+","+v); + } + else + if(v.getType(context)==StringType.type) { + emitln(context.getIndent()+"LOAD_STRING "+tname+",'"+v+"'"); + } + emitln(context.getIndent()+"SET_PROP "+rname+",'"+p+++"',"+tname); + } return null; } + /* + * Postfix expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, PostfixExpressionNode node ) throws Exception { - String tag = "PostfixExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * New expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, NewExpressionNode node ) throws Exception { - String tag = "NewExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Indexed member expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IndexedMemberExpressionNode node ) throws Exception { - String tag = "IndexedMemberExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.base != null ) { + node.base.evaluate(context,this); + } + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Property access + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for getting a property of a value. + */ + Value evaluate( Context context, MemberExpressionNode node ) throws Exception { - String tag = "MemberExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; + if( node.base != null ) { + node.base.evaluate(context,this); + } + String dname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + + rname = Machine.nameRegister(node.base.store); + dname = Machine.nameRegister(node.store); + ReferenceValue ref = (ReferenceValue) node.ref; + emitln(context.getIndent()+"GET_PROP "+ + dname+","+rname+",'"+ref.getName()+"'"); return null; } + /* + * Classof + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for getting the class object of a value. + */ + Value evaluate( Context context, ClassofExpressionNode node ) throws Exception { - String tag = "ClassofExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.base != null ) { - node.base.evaluate(context,this); - } - context.indent--; + + if( node.base != null ) { + node.base.evaluate(context,this); + } + + String dname,lname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + rname = Machine.nameRegister(node.base.store); + dname = Machine.nameRegister(node.store); + emitln(context.getIndent()+"GET_CLASS "+ + dname+","+rname); return null; } + /* + * Coersion + * + * STATUS + * Jan-05-2001: Coded + * + * NOTES + * Generates code for coercing a value to another value of a specific type. + */ + Value evaluate( Context context, CoersionExpressionNode node ) throws Exception { - String tag = "CoersionExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + + Debugger.trace("CoersionExpressionNode with type = " + node.type); + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + + if( node.type != null ) { + node.type.evaluate(context,this); + } + + String dreg,ereg,treg; + node.store = new Store(null,Machine.allocateTempRegister()); + ereg = Machine.nameRegister(node.expr.store); + treg = Machine.nameRegister(node.type.store); + dreg = Machine.nameRegister(node.store); + emitln(context.getIndent()+"CAST "+ + dreg+","+ereg+","+treg); + Debugger.trace("JSILGenerator.evaluate(CoersionExpressionNode) with node.store = " + node.store); return null; } + /* + * Call expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CallExpressionNode node ) throws Exception { - String tag = "CallExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.member != null ) { - node.member.evaluate(context,this); - } - if( node.args != null ) { - node.args.evaluate(context,this); - } - context.indent--; + if( node.member != null ) { + node.member.evaluate(context,this); + } + String args = ""; + Debugger.trace("evaluate(CallExpressionNode) with node.args = " + node.args); + if( node.args != null ) { + node.args.evaluate(context,this); + ListNode list = (ListNode)node.args; + while(list!=null) { + args = Machine.nameRegister(list.item.store)+((args=="")?"":",")+args; + list = (ListNode)list.list; + } + } + node.store = new Store(null,Machine.allocateTempRegister()); + String reg1 = Machine.nameRegister(node.store); + String reg2 = Machine.nameRegister(node.member.store); + emitln(context.getIndent()+"CALL "+ + reg1+","+reg2+",("+args+")"); return null; } + /* + * Unary expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UnaryExpressionNode node ) throws Exception { - String tag = "UnaryExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Binary expression + * + * STATUS + * Partially implemented + */ + Value evaluate( Context context, BinaryExpressionNode node ) throws Exception { - String tag = "BinaryExpression: " + Token.getTokenClassName(node.op); - emit(context.getIndent()+tag); - context.indent++; - if( node.lhs != null ) { + Value rhs,lhs; + + + // compute the lhs value using either + // 1 lhs expression + // 2 unbound reference + // 3 bound reference + + String dname,lname,rname; + + if( node.lhs_slot != null ) { + lname = Machine.nameRegister(node.lhs_slot.store); + } else if ( node.lhs_ref != null ) { + // get the value of the reference and map lname to its location. + lname = "TBD"; + } else { node.lhs.evaluate(context,this); - } - if( node.rhs != null ) { + lname = Machine.nameRegister(node.lhs.store); + } + + if( node.rhs_slot != null ) { + rname = Machine.nameRegister(node.rhs_slot.store); + } else if ( node.rhs_ref != null ) { + // get the value of the reference and map rname to its location. + rname = "TBD"; + } else { node.rhs.evaluate(context,this); - } - context.indent--; + rname = Machine.nameRegister(node.rhs.store); + } + + node.store = new Store(null,Machine.allocateTempRegister()); + dname = Machine.nameRegister(node.store); + + emitln(context.getIndent()+"GENERIC_BINARY_OP "+ + dname+","+opName(node.op)+ + ","+lname + "," + rname); + return null; } + /* + * Conditional expression + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ConditionalExpressionNode node ) throws Exception { - String tag = "ConditionalExpression"; - emit(context.getIndent()+tag); - context.indent++; - if( node.condition != null ) { - node.condition.evaluate(context,this); - } - if( node.thenexpr != null ) { - node.thenexpr.evaluate(context,this); - } - if( node.elseexpr != null ) { - node.elseexpr.evaluate(context,this); - } - context.indent--; + if( node.condition != null ) { + node.condition.evaluate(context,this); + } + if( node.thenexpr != null ) { + node.thenexpr.evaluate(context,this); + } + if( node.elseexpr != null ) { + node.elseexpr.evaluate(context,this); + } return null; } + /* + * Assignment expression + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, AssignmentExpressionNode node ) throws Exception { - String tag = "AssignmentExpression: " + ((node.op==empty_token)?"":Token.getTokenClassName(node.op)); - emit(context.getIndent()+tag); - context.indent++; - if( node.lhs != null ) { - node.lhs.evaluate(context,this); + // during constant eval, + // save reference to lhs in node. (key!) + + // 1 Load the rhs value into temporary storage + // 2 Load the lhs value into temporary storage + // 3 Operate (move,generic_binary_op) + // 4 Store the result in the place indicated by the lhs reference. + + if( node.rhs != null ) { + node.rhs.evaluate(context,this); + } + if( node.lhs != null ) { + node.lhs.evaluate(context,this); + } + + String dname,lname,rname; + node.store = new Store(null,Machine.allocateTempRegister()); + lname = Machine.nameRegister(node.lhs.store); + rname = Machine.nameRegister(node.rhs.store); + dname = Machine.nameRegister(node.store); + if( node.op == assign_token ) { + emitln(context.getIndent()+"MOVE "+dname+","+rname); + } else { + emitln(context.getIndent()+"GENERIC_BINARY_OP "+dname+",OP,"+lname+","+rname); + } + + ReferenceValue ref = (ReferenceValue) node.ref; + if( ref.scope == null ) { + emitln(context.getIndent()+"SAVE_NAME '"+ + ref.getName()+"',"+dname); + } else { + String bname = Machine.nameRegister(((MemberExpressionNode)node.lhs).base.store); + emitln(context.getIndent()+"SET_PROP "+bname+",'"+ + ref.getName()+"',"+dname); } - if( node.rhs != null ) { - node.rhs.evaluate(context,this); - } - context.indent--; return null; } + /* + * List + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ListNode node ) throws Exception { - String tag = "List"; - //emit(context.getIndent()+tag); - if( node.list != null ) { - node.list.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } + if( node.list != null ) { + node.list.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } // Statements + /* + * Statement list + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, StatementListNode node ) throws Exception { - String tag = "StatementList"; - //emit(context.getIndent()+tag); - if( node.list != null ) { - node.list.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } + if( node.list != null ) { + node.list.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } + /* + * Empty statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, EmptyStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"EmptyStatement"; - emit(context.getIndent()+tag); return null; } + /* + * Expression statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ExpressionStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ExpressionStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Annotated block + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AnnotatedBlockNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"AnnotatedBlock"; - emit(context.getIndent()+tag); - context.indent++; - if( node.attributes != null ) { - node.attributes.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.attributes != null ) { + node.attributes.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Labeled statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, LabeledStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"LabeledStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.label != null ) { - node.label.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.label != null ) { + node.label.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * If statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IfStatementNode node ) throws Exception { - - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"IfStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.condition != null ) { - node.condition.evaluate(context,this); - } - if( node.thenactions != null ) { - node.thenactions.evaluate(context,this); - } - if( node.elseactions != null ) { - node.elseactions.evaluate(context,this); - } - context.indent--; + if( node.condition != null ) { + node.condition.evaluate(context,this); + } + if( node.thenactions != null ) { + node.thenactions.evaluate(context,this); + } + if( node.elseactions != null ) { + node.elseactions.evaluate(context,this); + } return null; } + /* + * Switch statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, SwitchStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"SwitchStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Case label + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CaseLabelNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"CaseLabel"; - emit(context.getIndent()+tag); - context.indent++; - if( node.label != null ) { - node.label.evaluate(context,this); - } else { - emit(context.getIndent()+"default"); - } - context.indent--; + if( node.label != null ) { + node.label.evaluate(context,this); + } else { + emitln(context.getIndent()+"default"); + } return null; } + /* + * Do statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, DoStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"DoStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.statements != null ) { + node.statements.evaluate(context,this); + } + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * While statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, WhileStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"WhileStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * For statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ForStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ForStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.initialize != null ) { - node.initialize.evaluate(context,this); - } - if( node.test != null ) { - node.test.evaluate(context,this); - } - if( node.increment != null ) { - node.increment.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.initialize != null ) { + node.initialize.evaluate(context,this); + } + if( node.test != null ) { + node.test.evaluate(context,this); + } + if( node.increment != null ) { + node.increment.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * For in statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ForInStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ForInStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.property != null ) { - node.property.evaluate(context,this); - } - if( node.object != null ) { - node.object.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.property != null ) { + node.property.evaluate(context,this); + } + if( node.object != null ) { + node.object.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * With statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, WithStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"WithStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - if( node.statement != null ) { - node.statement.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + if( node.statement != null ) { + node.statement.evaluate(context,this); + } return null; } + /* + * Continue statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ContinueStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ContinueStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Break statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, BreakStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"BreakStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Return statement + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ReturnStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ReturnStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } + String rname = Machine.nameRegister(node.expr.store); + emitln(context.getIndent()+"RETURN "+rname); return null; } + /* + * Throw statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ThrowStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ThrowStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"ThrowStatement"; + emitln(context.getIndent()+tag); + context.indent++; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Try statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, TryStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"TryStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.tryblock != null ) { - node.tryblock.evaluate(context,this); - } - if( node.catchlist != null ) { - node.catchlist.evaluate(context,this); - } - if( node.finallyblock != null ) { - node.finallyblock.evaluate(context,this); - } - context.indent--; + if( node.tryblock != null ) { + node.tryblock.evaluate(context,this); + } + if( node.catchlist != null ) { + node.catchlist.evaluate(context,this); + } + if( node.finallyblock != null ) { + node.finallyblock.evaluate(context,this); + } return null; } + /* + * Catch clause + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, CatchClauseNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"CatchClause"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Finally clause + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, FinallyClauseNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"FinallyClause"; - emit(context.getIndent()+tag); - context.indent++; - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Use statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, UseStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"UseStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.expr != null ) { - node.expr.evaluate(context,this); - } - context.indent--; + if( node.expr != null ) { + node.expr.evaluate(context,this); + } return null; } + /* + * Include statement + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, IncludeStatementNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"IncludeStatement"; - emit(context.getIndent()+tag); - context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } // Definitions + /* + * Import definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ImportDefinitionNode node ) throws Exception { - String tag = "ImportDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Import binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ImportBindingNode node ) throws Exception { - String tag = "ImportBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.item != null ) { - node.item.evaluate(context,this); - } - context.indent--; + if( node.identifier != null ) { + node.identifier.evaluate(context,this); + } + if( node.item != null ) { + node.item.evaluate(context,this); + } return null; } + /* + * Annotated definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AnnotatedDefinitionNode node ) throws Exception { - String tag = (node.isLeader ? "*"+node.block+":" : ""+node.block+": ")+"AnnotatedDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.attributes != null ) { - node.attributes.evaluate(context,this); - } - if( node.definition != null ) { - node.definition.evaluate(context,this); - } - context.indent--; + if( node.attributes != null ) { + node.attributes.evaluate(context,this); + } + if( node.definition != null ) { + node.definition.evaluate(context,this); + } return null; } + /* + * Attribute list + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, AttributeListNode node ) throws Exception { - String tag = "AttributeList"; - //emit(context.getIndent()+tag); - //context.indent++; - if( node.item != null ) { - node.item.evaluate(context,this); - } - if( node.list != null ) { - node.list.evaluate(context,this); - } - //context.indent--; + if( node.item != null ) { + node.item.evaluate(context,this); + } + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Export definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ExportDefinitionNode node ) throws Exception { - String tag = "ExportDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Export binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, ExportBindingNode node ) throws Exception { - String tag = "ExportBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.value != null ) { - node.value.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.value != null ) { + node.value.evaluate(context,this); + } return null; } + /* + * Variable definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, VariableDefinitionNode node ) throws Exception { - String tag = "VariableDefinition: " + Token.getTokenClassName(node.kind); - emit(context.getIndent()+tag); - context.indent++; - if( node.list != null ) { - node.list.evaluate(context,this); - } - context.indent--; + if( node.list != null ) { + node.list.evaluate(context,this); + } return null; } + /* + * Variable binding + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, VariableBindingNode node ) throws Exception { - String tag = "VariableBinding"; - emit(context.getIndent()+tag); - context.indent++; - if( node.variable != null ) { - node.variable.evaluate(context,this); - } - if( node.initializer != null ) { - node.initializer.evaluate(context,this); - } - context.indent--; + if( node.variable != null ) { + node.variable.evaluate(context,this); + } + if( node.initializer != null ) { + node.initializer.evaluate(context,this); + } return null; } + /* + * Typed variable + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, TypedVariableNode node ) throws Exception { - String tag = "TypedVariable"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + if( node.identifier != null ) { + node.identifier.evaluate(context,this); + } + if( node.type != null ) { + node.type.evaluate(context,this); + } return null; } + /* + * Function definition + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionDefinitionNode node ) throws Exception { - String tag = "FunctionDefinition"; - emit(context.getIndent()+tag); + Machine.init(node.fixedCount); + emitln(context.getIndent()+""); return null; } + /* + * Function declaration + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionDeclarationNode node ) throws Exception { - String tag = "FunctionDeclaration"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.signature != null ) { - node.signature.evaluate(context,this); - } - context.indent--; + ReferenceValue ref = (ReferenceValue) node.ref; + emit("name="+ref.getName()); + //if( node.name != null ) { + // node.name.evaluate(context,this); + //} + if( node.signature != null ) { + node.signature.evaluate(context,this); + } return null; } + /* + * Function signature + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, FunctionSignatureNode node ) throws Exception { - String tag = "FunctionSignature"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.result != null ) { - node.result.evaluate(context,this); - } - context.indent--; + emit(" type="); + if( node.result != null ) { + ReferenceValue ref = (ReferenceValue) node.ref; + emit(ref.getName()); + } else { + emit("Object"); + } + emit("/>"); + +Debugger.trace("evaluate(FunctionSignatureNode) with node.parameter = " + node.parameter); + + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } return null; } + /* + * Function name + * + * STATUS + * Not used + */ + Value evaluate( Context context, FunctionNameNode node ) throws Exception { - String tag = "FunctionName: " + ((node.kind==empty_token)?"":Token.getTokenClassName(node.kind)); - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; return null; } + /* + * Parameter + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ParameterNode node ) throws Exception { - String tag = "Parameter"; - emit(context.getIndent()+tag); - context.indent++; - if( node.identifier != null ) { - node.identifier.evaluate(context,this); - } - if( node.type != null ) { - node.type.evaluate(context,this); - } - context.indent--; + emitln(context.getIndent()+""); return null; } + /* + * Optional parameter + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, OptionalParameterNode node ) throws Exception { - String tag = "OptionalParameter"; - emit(context.getIndent()+tag); - context.indent++; - if( node.parameter != null ) { - node.parameter.evaluate(context,this); - } - if( node.initializer != null ) { - node.initializer.evaluate(context,this); - } - context.indent--; + if( node.parameter != null ) { + node.parameter.evaluate(context,this); + } + if( node.initializer != null ) { + node.initializer.evaluate(context,this); + } return null; } + /* + * Class definition + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ClassDefinitionNode node ) throws Exception { - String tag = "ClassDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.inheritance != null ) { - node.inheritance.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + emitln(""); + context.indent++; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.inheritance != null ) { + node.inheritance.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } + context.indent--; return null; } + /* + * Inheritance definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, InheritanceNode node ) throws Exception { - String tag = "Inheritance"; - emit(context.getIndent()+tag); - context.indent++; - if( node.baseclass != null ) { - node.baseclass.evaluate(context,this); - } - if( node.interfaces != null ) { - node.interfaces.evaluate(context,this); - } - context.indent--; + if( node.baseclass != null ) { + node.baseclass.evaluate(context,this); + } + if( node.interfaces != null ) { + node.interfaces.evaluate(context,this); + } return null; } + /* + * Class declaration + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ClassDeclarationNode node ) throws Exception { - String tag = "ClassDeclaration"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } return null; } + /* + * Namespace definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, NamespaceDefinitionNode node ) throws Exception { - String tag = "NamespaceDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.extendslist != null ) { - node.extendslist.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.extendslist != null ) { + node.extendslist.evaluate(context,this); + } return null; } + /* + * Package definition + * + * STATUS + * Not implemented + */ + Value evaluate( Context context, PackageDefinitionNode node ) throws Exception { - String tag = "PackageDefinition"; - emit(context.getIndent()+tag); - context.indent++; - if( node.name != null ) { - node.name.evaluate(context,this); - } - if( node.statements != null ) { - node.statements.evaluate(context,this); - } - context.indent--; + if( node.name != null ) { + node.name.evaluate(context,this); + } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } + /* + * Program + * + * STATUS + * Jan-24-2001: Coded + */ + Value evaluate( Context context, ProgramNode node ) throws Exception { - if( node.statements != null ) { - String tag = "Program"; - emit(context.getIndent()+tag); - context.indent++; - node.statements.evaluate(context,this); - context.indent--; - } + if( node.statements != null ) { + node.statements.evaluate(context,this); + } return null; } } +/* + * Static model of the virtual machine. + */ + +class Machine { + + private static boolean debug = true; + + static int registerCount; + static int fixedRegisterCount; + + static void init(int fixedCount) { + Debugger.trace("Machine.init() with fixedCount = " + fixedCount); + registerCount = fixedRegisterCount = fixedCount; + } + + static int allocateTempRegister() { + return registerCount++; + } + + static void resetTempRegisters() { + } + + static void resetAllRegisters() { + } + + static String nameRegister(Store store) { + return "R"+ (store.index+1); + } + + static String nameTemp() { + return "R"+ (registerCount+1); + } +} + /* * The end. */ diff --git a/mozilla/js2/jsc/src/java/main/Main.java b/mozilla/js2/jsc/src/java/main/Main.java index 7814d7e2601..cceefdd1142 100644 --- a/mozilla/js2/jsc/src/java/main/Main.java +++ b/mozilla/js2/jsc/src/java/main/Main.java @@ -47,6 +47,7 @@ public class Main { private static boolean traceInput = false; private static boolean traceLexer = false; private static boolean traceParser = false; + private static boolean doASM = false; private static boolean debug = false; @@ -67,6 +68,8 @@ public class Main { traceParser = true; } else if (args[i].equals("-d")||args[i].equals("-debug")) { debug = true; + } else if (args[i].equals("-a")||args[i].equals("-asm")) { + doASM = true; } else if (args[i].charAt(0) == '-') { System.out.println("Unknown.option "+ args[i]); } else { @@ -148,7 +151,7 @@ public class Main { if( traceParser ) { Debugger.trace("setting parser output to " + input[i]); JSILGenerator.setOut( input[i]+".par" ); - node.evaluate(context,new JSILGenerator()); + node.evaluate(context,new JSILGenerator(false)); } //Evaluator evaluator; @@ -157,14 +160,14 @@ public class Main { context.setEvaluator(new BlockEvaluator()); node.evaluate(context, context.getEvaluator()); - JSILGenerator.setOut( input[i]+".blocks" ); - context.setEvaluator(new JSILGenerator()); - node.evaluate(context, context.getEvaluator()); + //JSILGenerator.setOut( input[i]+".blocks" ); + //context.setEvaluator(new JSILGenerator(false)); + //node.evaluate(context, context.getEvaluator()); context.setEvaluator(new ConstantEvaluator()); value = node.evaluate(context, context.getEvaluator()); - context.setEvaluator(new JSILGenerator()); + context.setEvaluator(new JSILGenerator(doASM)); JSILGenerator.setOut( input[i]+".jsil" ); node.evaluate(context, context.getEvaluator()); errorCount = context.errorCount(); @@ -172,7 +175,7 @@ public class Main { t = System.currentTimeMillis() - t; //Debugger.trace(""+global); - System.out.println(input[i] + ": "+ errorCount +" errors [" + Long.toString(t) + " msec] --> " + value.getValue(context) ); + System.out.println(input[i] + ": "+ errorCount +" errors [" + Long.toString(t) + " msec]"); } catch( Exception x ) { x.printStackTrace(); diff --git a/mozilla/js2/jsc/src/java/parser/Node.java b/mozilla/js2/jsc/src/java/parser/Node.java index 5272bd10978..7bdeaf963dc 100644 --- a/mozilla/js2/jsc/src/java/parser/Node.java +++ b/mozilla/js2/jsc/src/java/parser/Node.java @@ -32,6 +32,7 @@ public class Node { Block block; int position; + Store store; public Node() { } diff --git a/mozilla/js2/jsc/src/java/parser/NodeFactory.java b/mozilla/js2/jsc/src/java/parser/NodeFactory.java index 20d02c8bf38..20e47f60457 100644 --- a/mozilla/js2/jsc/src/java/parser/NodeFactory.java +++ b/mozilla/js2/jsc/src/java/parser/NodeFactory.java @@ -102,9 +102,6 @@ public final class NodeFactory { static SuperExpressionNode SuperExpression() { return new SuperExpressionNode(); } - static EvalExpressionNode EvalExpression( Node expr ) { - return new EvalExpressionNode(expr); - } static ListNode List( Node list, Node item ) { return new ListNode(list,item,item.pos()); } diff --git a/mozilla/js2/jsc/src/java/parser/Nodes.java b/mozilla/js2/jsc/src/java/parser/Nodes.java index dd22da325b5..2507689d9f8 100644 --- a/mozilla/js2/jsc/src/java/parser/Nodes.java +++ b/mozilla/js2/jsc/src/java/parser/Nodes.java @@ -86,6 +86,7 @@ final class AssignmentExpressionNode extends Node implements Tokens { Node lhs, rhs; int op; + /*Reference*/Value ref; AssignmentExpressionNode( Node lhs, int op, Node rhs ) { this.lhs = lhs; @@ -139,6 +140,8 @@ final class BinaryExpressionNode extends Node { protected Node lhs, rhs; protected int op; + Value lhs_ref,rhs_ref; + Slot lhs_slot,rhs_slot; BinaryExpressionNode( int op, Node lhs, Node rhs ) { this.op = op; @@ -331,6 +334,7 @@ final class ClassofExpressionNode extends Node { final class CoersionExpressionNode extends Node { Node expr, type; + String typename; CoersionExpressionNode( Node expr, Node type, int pos ) { super(pos); @@ -427,11 +431,11 @@ final class DoStatementNode extends Node { final class ElementListNode extends Node { - Node list, expr; + Node list, item; - ElementListNode( Node list, Node expr ) { + ElementListNode( Node list, Node item ) { this.list = list; - this.expr = expr; + this.item = item; } public Value evaluate( Context context, Evaluator evaluator ) throws Exception { @@ -439,7 +443,7 @@ final class ElementListNode extends Node { } public String toString() { - return "elementlist( " + list + ", " + expr + " )"; + return "elementlist( " + list + ", " + item + " )"; } } @@ -479,27 +483,6 @@ final class ExpressionStatementNode extends Node { } } -/** - * EvalExpressionNode - */ - -final class EvalExpressionNode extends Node { - - Node expr; - - EvalExpressionNode( Node expr ) { - this.expr = expr; - } - - public Value evaluate( Context context, Evaluator evaluator ) throws Exception { - return evaluator.evaluate( context, this ); - } - - public String toString() { - return "evalexpression( " + expr + " )"; - } -} - /** * ExportBindingNode */ @@ -726,6 +709,7 @@ final class FunctionDeclarationNode extends Node { Node name, signature; Slot slot; + /*Reference*/Value ref; FunctionDeclarationNode( Node name, Node signature ) { this.name = name; @@ -748,6 +732,7 @@ final class FunctionDeclarationNode extends Node { final class FunctionDefinitionNode extends Node { Node decl, body; + int fixedCount; FunctionDefinitionNode( Node decl, Node body ) { this.decl = decl; @@ -782,7 +767,7 @@ final class FunctionNameNode extends Node { FunctionNameNode( int kind, Node name ) { this.kind = kind; - this.name = name; + this.name = (IdentifierNode)name; } public Value evaluate( Context context, Evaluator evaluator ) throws Exception { @@ -802,6 +787,7 @@ final class FunctionSignatureNode extends Node { Node parameter, result; Slot slot; + Value ref; FunctionSignatureNode( Node parameter, Node result ) { this.parameter = parameter; @@ -824,6 +810,7 @@ final class FunctionSignatureNode extends Node { class IdentifierNode extends Node { String name; + /*Reference*/Value ref; IdentifierNode( String name, int pos ) { super(pos); @@ -1128,6 +1115,7 @@ final class ListNode extends Node { final class LiteralArrayNode extends Node { Node elementlist; + /*List*/Value value; LiteralArrayNode( Node elementlist ) { this.elementlist = elementlist; @@ -1171,6 +1159,7 @@ final class LiteralFieldNode extends Node { Node name; Node value; + /*Reference*/Value ref; LiteralFieldNode( Node name, Node value ) { this.name = name; @@ -1232,6 +1221,7 @@ final class LiteralNumberNode extends Node { final class LiteralObjectNode extends Node { Node fieldlist; + /*Object*/Value value; LiteralObjectNode( Node fieldlist ) { this.fieldlist = fieldlist; @@ -1334,6 +1324,7 @@ final class LiteralUndefinedNode extends Node { final class MemberExpressionNode extends Node { Node base, name; + /*Reference*/Value ref; MemberExpressionNode( Node base, Node name, int pos ) { super(pos); @@ -1474,6 +1465,7 @@ final class ParameterNode extends Node { Node identifier; Node type; Slot slot; + String name; ParameterNode( Node identifier, Node type ) { this.identifier = identifier; diff --git a/mozilla/js2/jsc/src/java/parser/Slot.java b/mozilla/js2/jsc/src/java/parser/Slot.java index d1727d0deb2..5c23a8f47a2 100644 --- a/mozilla/js2/jsc/src/java/parser/Slot.java +++ b/mozilla/js2/jsc/src/java/parser/Slot.java @@ -31,9 +31,10 @@ public class Slot { Value type; Value value; Block block; + Store store; public String toString() { - return "{ "+attrs+", "+type+", "+value+" }"; + return "{ "+attrs+", "+type+", "+value+", "+store+" }"; } } diff --git a/mozilla/js2/jsc/src/java/parser/Store.java b/mozilla/js2/jsc/src/java/parser/Store.java new file mode 100644 index 00000000000..30f3ca36fb0 --- /dev/null +++ b/mozilla/js2/jsc/src/java/parser/Store.java @@ -0,0 +1,45 @@ +/* + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Mountain View Compiler + * Company. Portions created by Mountain View Compiler Company are + * Copyright (C) 1998-2000 Mountain View Compiler Company. All + * Rights Reserved. + * + * Contributor(s): + * Jeff Dyer + */ + +package com.compilercompany.ecmascript; + +/** + * Represents an abstract unit of storage. + */ + +public class Store { + Scope scope; + int index; + + Store(Scope scope, int index) { + this.scope = scope; + this.index = index; + } + + public String toString() { + return "store( " + index + " )"; + } +} + +/* + * The end. + */ diff --git a/mozilla/js2/jsc/src/java/parser/Value.java b/mozilla/js2/jsc/src/java/parser/Value.java index b2429b07f9c..f7f1c88874c 100644 --- a/mozilla/js2/jsc/src/java/parser/Value.java +++ b/mozilla/js2/jsc/src/java/parser/Value.java @@ -95,6 +95,10 @@ abstract public class Value implements Scope { */ } + int size() { + return 0; + } + public Value construct(Context context, Value args) throws Exception { throw new Exception("Constructor object expected in new expression"); } diff --git a/mozilla/js2/jsc/src/java/semantics/ConstantEvaluator.java b/mozilla/js2/jsc/src/java/semantics/ConstantEvaluator.java index 4fdf52254f5..372ab40bd5a 100644 --- a/mozilla/js2/jsc/src/java/semantics/ConstantEvaluator.java +++ b/mozilla/js2/jsc/src/java/semantics/ConstantEvaluator.java @@ -44,6 +44,10 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { /** * IdentifierNode + * + * The reference value serves as a weak alias to the object being + * bound to. It is interpreted by its context (e.g. a member expr + * as a selector for a member of the base activation frame. */ Value evaluate( Context context, IdentifierNode node ) throws Exception { @@ -304,7 +308,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating LiteralObjectNode = " + node); } - Value value; + ObjectValue value; Type type; type = new ObjectType(""); @@ -316,6 +320,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { context.popScope(); } + node.value = value; // save it for code generation. + return value; } @@ -376,17 +382,19 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating LiteralArrayNode = " + node); } - Value value; + ListValue value; Type type; type = ArrayType.type; if( node.elementlist != null ) { - value = node.elementlist.evaluate(context,this); + value = (ListValue)node.elementlist.evaluate(context,this); } else { - value = NullValue.nullValue; + value = null; } + node.value = value; // save for code generation. + return type.convert(context,value); } @@ -407,6 +415,41 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { testEvaluator("ArrayLiteral",input,expected); } + /** + * ElementListNode + */ + + Value evaluate( Context context, ElementListNode node ) throws Exception { + + if( debug ) { + Debugger.trace("evaluating ElementListNode = " + node); + } + + ListValue list; + + if( node.list != null ) { + if( node.list instanceof ListNode ) { + list = (ListValue) node.list.evaluate(context,this); + } else { + list = new ListValue(); + list.push(node.list.evaluate(context,this)); + } + } + else { + list = new ListValue(); + } + + if( node.item != null ) { + list.push(node.item.evaluate(context,this)); + } + else { + // do nothing. + } + + return list; + + } + /** * PostfixExpressionNode * @@ -492,6 +535,10 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { * MemberExpressionNode * * { base:NewSubexpressionNode name:IdentifierNode } + * + * A member expression evaluates to a reference value. If the value of the + * reference is a compile-time constant, then return the value as a literal. + * Otherwise return undefined. */ Value evaluate( Context context, MemberExpressionNode node ) throws Exception { @@ -502,17 +549,18 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Value value; Value base; - ReferenceValue ref; String name; base = node.base.evaluate(context,this).getValue(context); value = node.name.evaluate(context,this); - if( value instanceof ReferenceValue ) { - ref = (ReferenceValue) value; - ref.scope = base; + if( !UndefinedType.type.includes(base) && + value instanceof ReferenceValue ) { + ((ReferenceValue)value).scope = base; + node.ref = value; } else { - error(context,0,"Expecting reference expression after dot operator.",node.name.pos()); + value = UndefinedValue.undefinedValue; + //error(context,0,"Expecting reference expression after dot operator.",node.name.pos()); } return value; @@ -665,7 +713,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { callee = node.member.evaluate(context,this).getValue(context); if( node.args != null ) { - args = node.args.evaluate(context,this); + args = node.args.evaluate(context,this); } if( !FunctionType.type.includes(callee) ) { @@ -704,6 +752,27 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { if( debug ) { Debugger.trace("evaluating BinaryExpressionNode = " + node); } + + // if rhs is a constant, then replace with a literal. + // if it is a local definition, then load it directly. + // otherwise, put result in temporary and use it directly. + + + Value value; + + value = node.lhs.evaluate(context,this); + if( value instanceof ReferenceValue ) { + node.lhs = null; + node.lhs_ref = value; + node.lhs_slot = ((ReferenceValue)value).getSlot(context); + } + value = node.rhs.evaluate(context,this); + if( value instanceof ReferenceValue ) { + node.rhs = null; + node.rhs_ref = value; + node.rhs_slot = ((ReferenceValue)value).getSlot(context); + } + return UndefinedValue.undefinedValue; } @@ -735,11 +804,14 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Value value = UndefinedValue.undefinedValue; if( lref != UndefinedValue.undefinedValue ) { Slot slot = ((ReferenceValue)lref).getSlot(context); - Debugger.trace("slot " + slot); + Debugger.trace("ConstantEvaluator.evaluat(AssignmentExpression) with slot " + slot); if( slot != null ) { Value rref = node.rhs.evaluate(context,this); slot.value = rref.getValue(context); } + node.ref = (ReferenceValue)lref; + } else { + throw new Exception("internal error: assignment lhs is not a reference."); } return value; @@ -1079,6 +1151,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace("evaluating ReturnStatementNode = " + node); } + node.expr.evaluate(context,this); + return new CodeValue(node); } @@ -1208,7 +1282,7 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { static { try { - namespace_parameters = new ObjectValue(new NamespaceType("_parameters_")); + namespace_parameters = new ObjectValue(new TypeValue(new NamespaceType("_parameters_"))); } catch ( Exception x ) { x.printStackTrace(); Debugger.trace("oops, something is not right."); @@ -1577,12 +1651,17 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { * 2. Save result in code slot. */ + private int local_offset; + public Value evaluate( Context context, FunctionDefinitionNode node ) throws Exception { if( debug ) { Debugger.trace( "evaluating FunctionDefinitionNode: " + node ); } + local_offset = 0; // start a new activation frame. + + used_namespaces.addElement(namespace_parameters); Value value = node.decl.evaluate(context,this); if( node.body!=null) { @@ -1595,6 +1674,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { context.popScope(); } + node.fixedCount = local_offset; + return UndefinedValue.undefinedValue; } @@ -1633,7 +1714,8 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Debugger.trace( "evaluating FunctionDeclarationNode: " + node ); } - ReferenceValue ref = (ReferenceValue) node.name.evaluate(context,this); + ReferenceValue ref; + node.ref = ref = (ReferenceValue) node.name.evaluate(context,this); String name = ref.getName(); ref.scope = context.getLocal(); @@ -1747,20 +1829,21 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { Scope local = context.getLocal(); node.slot = local.add(namespace_parameters,"_result_"); - Value result; + Value type; if( node.result!=null ) { - result = node.result.evaluate(context,this).getValue(context); + node.ref = node.result.evaluate(context,this); + type = node.ref.getValue(context); } else { - result = ObjectType.type; + type = ObjectType.type; } - if( !TypeType.type.includes(result) ) { - error(context,"Result type expression does not evaluate to a type. result = " + result.type,node.pos()); + if( !TypeType.type.includes(type) ) { + error(context,"Result type expression does not evaluate to a type. result = " + type.type,node.pos()); } - node.slot.type = (TypeValue) result; + node.slot.type = type; - return result; + return type; } /** @@ -1783,8 +1866,9 @@ public class ConstantEvaluator extends Evaluator implements Tokens, Attributes { ref = (ReferenceValue) node.identifier.evaluate(context,this); name = ref.getName(); - node.slot = local.add(namespace_parameters,name); - //node.identifier.slot.block = context.getBlock(); + node.slot = local.add(namespace_parameters,name); + node.slot.store = new Store(local,local_offset++); + node.name = name; // for code generation. return ref; } @@ -2338,6 +2422,7 @@ class Flow { } return preds; } + } /* diff --git a/mozilla/js2/jsc/src/java/semantics/values/ObjectValue.java b/mozilla/js2/jsc/src/java/semantics/values/ObjectValue.java index 83fa043fa82..62c227d9b70 100644 --- a/mozilla/js2/jsc/src/java/semantics/values/ObjectValue.java +++ b/mozilla/js2/jsc/src/java/semantics/values/ObjectValue.java @@ -176,6 +176,14 @@ public class ObjectValue extends Value implements Attributes, Scope { return slot; } + /** + * + */ + + int size() { + return slots.size(); + } + /** * */ diff --git a/mozilla/js2/jsc/src/java/semantics/values/ReferenceValue.java b/mozilla/js2/jsc/src/java/semantics/values/ReferenceValue.java index 4605bd1cf1b..8cd2f67e1f3 100644 --- a/mozilla/js2/jsc/src/java/semantics/values/ReferenceValue.java +++ b/mozilla/js2/jsc/src/java/semantics/values/ReferenceValue.java @@ -45,7 +45,7 @@ public class ReferenceValue extends Value { if( debug ) { Debugger.trace( "creating reference scope = " + scope + - " name = " + name + " namespaces = " + namespaces ); + " name = " + name + " used_namespaces = " + namespaces ); } this.scope = scope; @@ -91,6 +91,10 @@ public class ReferenceValue extends Value { break; } } + + if( slot==null ) { + slot = scope.get(qualifier/*=null*/,name); + } } if( debug ) { Debugger.trace("leaving getSlotInScope() with slot="+slot); diff --git a/mozilla/js2/jsc/test/ecma-e4/02.expressions/binary.1.js b/mozilla/js2/jsc/test/ecma-e4/02.expressions/binary.1.js index accd34d9cbd..e739de8cf89 100644 --- a/mozilla/js2/jsc/test/ecma-e4/02.expressions/binary.1.js +++ b/mozilla/js2/jsc/test/ecma-e4/02.expressions/binary.1.js @@ -60,5 +60,6 @@ function run() { } /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */ diff --git a/mozilla/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js b/mozilla/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js index d9a75434716..d95e49ce9cb 100644 --- a/mozilla/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js +++ b/mozilla/js2/jsc/test/ecma-e4/02.expressions/prefixunary.1.js @@ -7,17 +7,18 @@ function title() { } function run() { - a.b::c.d[e](f,g)[h].i++; + //a.b::c.d[e](f,g)[h].i++; delete p; void 0; typeof ob; - ++a.b--; - --a.b++; + //++a.b--; + //--a.b++; +a; -a; !a; } /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */ diff --git a/mozilla/js2/jsc/test/ecma-e4/04.definitions/definition.1.js b/mozilla/js2/jsc/test/ecma-e4/04.definitions/definition.1.js index a1e03fa47b2..1b72bf9dba8 100644 --- a/mozilla/js2/jsc/test/ecma-e4/04.definitions/definition.1.js +++ b/mozilla/js2/jsc/test/ecma-e4/04.definitions/definition.1.js @@ -32,5 +32,5 @@ unit const liter = makeLiter; showerrors unit const liter = Unit.dm.pow(3); /* - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. + * Copyright (c) 1999-2001, Mountain View Compiler Company. All rights reserved. */ diff --git a/mozilla/js2/jsc/test/sanity.js b/mozilla/js2/jsc/test/sanity.js index a8ddb681f4f..a0a7fb90647 100644 --- a/mozilla/js2/jsc/test/sanity.js +++ b/mozilla/js2/jsc/test/sanity.js @@ -2,18 +2,19 @@ * Sanity test. */ -const result = 'okay'; - function title() { return "sanity"; } - -function run() { +function g(a,b) { + return a+b; } -result; +function run() { + return g(1,2); +} -/** - * Copyright (c) 1999, Mountain View Compiler Company. All rights reserved. +/* + * Copyright (c) 1999-2001, Mountain View Compiler Company. + * All rights reserved. */