0001: /*=============================================================================
0002: * Copyright Texas Instruments 2000-2003. All Rights Reserved.
0003: *
0004: * This program is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License as published by the Free Software Foundation; either
0007: * version 2 of the License, or (at your option) any later version.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012: * Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0017: *
0018: * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
0019: */
0020:
0021: package oscript.interpreter;
0022:
0023: import oscript.syntaxtree.*;
0024: import oscript.util.StackFrame;
0025: import oscript.data.*;
0026: import oscript.exceptions.*;
0027: import oscript.visitor.ObjectVisitor;
0028: import oscript.parser.OscriptParser;
0029: import oscript.parser.OscriptParserConstants;
0030: import oscript.parser.ParseException;
0031: import oscript.OscriptInterpreter;
0032: import oscript.translator.*;
0033:
0034: /* RET like instructions "return", "break", and "continue" are used by
0035: * throwing an exception, and catching it in the appropriate places.
0036: */
0037: class Return extends RuntimeException {
0038: Return() {
0039: super ();
0040: }
0041: }
0042:
0043: class Break extends RuntimeException {
0044: Break() {
0045: super ();
0046: }
0047: }
0048:
0049: class Continue extends RuntimeException {
0050: Continue() {
0051: super ();
0052: }
0053: }
0054:
0055: /* NOTE: in places where values are cached in the syntaxtree, there is too
0056: * much overlap between EvaluateVisitor and CompilerVisitor... try to
0057: * find a way to rectify this.
0058: */
0059:
0060: /**
0061: * The EvaluateVisitor is the heart of the interpreter.
0062: *
0063: * @author Rob Clark (rob@ti.com)
0064: * <!--$Format: " * @version $Revision$"$-->
0065: * @version 1.123
0066: */
0067: public class EvaluateVisitor implements ObjectVisitor,
0068: OscriptParserConstants {
0069: /**
0070: * The current scope. This is passed as an argument to the constructor,
0071: * and does not change for the live of the evaluator.
0072: */
0073: private Scope this Scope;
0074:
0075: /* For now I am using this naming convention to encode values that are
0076: * "returned" by some of the visit methods. I want to avoid the overhead
0077: * of allocating memory to return values, so we do it by instance variables.
0078: * The convention is that they are set by the visitor and read-only to
0079: * everyone else.
0080: */
0081: private int NodeToken_kind;
0082: private NodeToken NodeToken_lastToken; // for generating error messages
0083: private java.util.Vector NodeToken_lastSpecials;
0084:
0085: private int[] Arglist_names;
0086: private boolean Arglist_varargs;
0087:
0088: private int Permissions_attr;
0089:
0090: // to save a bit on the overhead of allocating a new object, and
0091: // filling in the stack trace (which we don't need), we reuse
0092: // these exceptions:
0093: private Value retVal = Value.UNDEFINED;
0094: private static final Return RETURN = new Return();
0095: private static final Break BREAK = new Break();
0096: private static final Continue CONTINUE = new Continue();
0097:
0098: /*=======================================================================*/
0099: /**
0100: * Class Constructor. An <code>EvaluateVisitor</code> is constructed
0101: * to evaluate within a specified context (scope). The context' purpose
0102: * is twofold: 1) it is used to implement block structure, for example:
0103: * <pre>
0104: * ... some script ...
0105: * {
0106: * var someVar;
0107: * ... some script ...
0108: * }
0109: * </pre>
0110: * the block containing the variable <code>someVar</code> is evaluated
0111: * in a new context (with the current context as the previous context).
0112: * <p>
0113: * It is also used for 2) implementing function/method calls. When a
0114: * function/method is called, a new context is created, with the
0115: * context the function/method was declared in as the previous
0116: * context.
0117: * <p>
0118: * NOTE: there are cases where we re-use the <code>EvaluateVisitor</code>
0119: * for efficiency... need to document that better.
0120: *
0121: * @param thisScope the context to evaluate within
0122: */
0123: public EvaluateVisitor(Scope this Scope) {
0124: this .this Scope = this Scope;
0125: }
0126:
0127: /*=======================================================================*/
0128: /**
0129: */
0130: public NodeToken getLastNodeToken() {
0131: return NodeToken_lastToken;
0132: }
0133:
0134: /*=======================================================================*/
0135: /**
0136: */
0137: public Value evaluateFunction(Program n) {
0138: Value val = null;
0139:
0140: try {
0141: val = (Value) (n.accept(this , null));
0142: } catch (Return r) {
0143: val = retVal;
0144: }
0145:
0146: if (val == null)
0147: val = Value.NULL;
0148:
0149: return val;
0150: }
0151:
0152: /*=======================================================================*/
0153: /**
0154: */
0155: public Object visit(NodeList n, Object argu) {
0156: return null;
0157: }
0158:
0159: /*=======================================================================*/
0160: /**
0161: */
0162: public Object visit(NodeListOptional n, Object argu) {
0163: return null;
0164: }
0165:
0166: /*=======================================================================*/
0167: /**
0168: */
0169: public Object visit(NodeOptional n, Object argu) {
0170: return null;
0171: }
0172:
0173: /*=======================================================================*/
0174: /**
0175: */
0176: public Object visit(NodeSequence n, Object argu) {
0177: return null;
0178: }
0179:
0180: /*=======================================================================*/
0181: /**
0182: */
0183: public Object visit(NodeToken n, Object argu) {
0184: NodeToken_kind = n.kind;
0185: NodeToken_lastToken = n;
0186:
0187: StackFrame.currentStackFrame().setLineNumber(this Scope,
0188: n.beginLine);
0189:
0190: if (n.specialTokens != null)
0191: NodeToken_lastSpecials = n.specialTokens;
0192:
0193: if (n.cachedValue == null) {
0194: switch (n.kind) {
0195: case IDENTIFIER:
0196: n.cachedValue = n.otokenImage;
0197: break;
0198: case INTEGER_LITERAL:
0199: case HEX_LITERAL:
0200: case OCTAL_LITERAL:
0201: case BINARY_LITERAL:
0202: case DECIMAL_LITERAL:
0203: n.cachedValue = OExactNumber
0204: .makeExactNumber(n.otokenImage
0205: .castToExactNumber());
0206: break;
0207: case FLOATING_POINT_LITERAL:
0208: n.cachedValue = OInexactNumber
0209: .makeInexactNumber(n.otokenImage
0210: .castToInexactNumber());
0211: break;
0212: case STRING_LITERAL:
0213: n.cachedValue = new OString(OString.chop(n.tokenImage
0214: .substring(1, n.tokenImage.length() - 1))); // should this be intern'd???
0215: break;
0216: case REGEXP_LITERAL:
0217: n.cachedValue = RegExp.createRegExp(n.otokenImage);
0218: break;
0219: case TRUE:
0220: n.cachedValue = OBoolean.TRUE;
0221: break;
0222: case FALSE:
0223: n.cachedValue = OBoolean.FALSE;
0224: break;
0225: case NULL:
0226: n.cachedValue = Value.NULL;
0227: break;
0228: case UNDEFINED:
0229: n.cachedValue = Value.UNDEFINED;
0230: break;
0231: case -1:
0232: default:
0233: // leave as null
0234: }
0235: }
0236:
0237: return n.cachedValue;
0238: }
0239:
0240: /*=======================================================================*/
0241: /**
0242: * <PRE>
0243: * f0 -> ( <UNIX_SELF_EXECUTABLE_COMMENT> )?
0244: * f1 -> Program(false)
0245: * f2 -> <EOF>
0246: * </PRE>
0247: */
0248: public Object visit(ProgramFile n, Object argu) {
0249: return n.f1.accept(this , argu);
0250: }
0251:
0252: /*=======================================================================*/
0253: /**
0254: * <PRE>
0255: * f0 -> ( EvaluationUnit() )*
0256: * </PRE>
0257: */
0258: public Object visit(Program n, Object argu) {
0259: Value val = null;
0260:
0261: for (int i = 0; i < n.f0.size(); i++) {
0262: val = (Value) (n.f0.elementAt(i).accept(this , argu));
0263: }
0264:
0265: return val;
0266: }
0267:
0268: /*=======================================================================*/
0269: /**
0270: * <PRE>
0271: * f0 -> ScopeBlock()
0272: * | VariableDeclarationBlock()
0273: * | FunctionDeclaration()
0274: * | TryStatement()
0275: * | ForLoopStatement()
0276: * | WhileLoopStatement()
0277: * | ConditionalStatement()
0278: * | SynchronizedStatement()
0279: * | ReturnStatement()
0280: * | BreakStatement()
0281: * | ContinueStatement()
0282: * | ExpressionBlock()
0283: * | ThrowBlock()
0284: * | ImportBlock()
0285: * | MixinBlock()
0286: * | EvalBlock()
0287: * </PRE>
0288: */
0289: public Object visit(EvaluationUnit n, Object argu) {
0290: return n.f0.accept(this , argu);
0291: }
0292:
0293: /*=======================================================================*/
0294: /**
0295: * <PRE>
0296: * f0 -> "{"
0297: * f1 -> Program()
0298: * f2 -> "}"
0299: * </PRE>
0300: */
0301: public Object visit(ScopeBlock n, Object argu) {
0302: // push new scope:
0303: Scope savedThisScope = this Scope;
0304: this Scope = new BasicScope(this Scope);
0305:
0306: Object retVal;
0307:
0308: try {
0309: retVal = n.f1.accept(this , argu);
0310: } finally {
0311: // pop:
0312: this Scope = savedThisScope;
0313: }
0314:
0315: return retVal;
0316: }
0317:
0318: /*=======================================================================*/
0319: /**
0320: * <PRE>
0321: * f0 -> VariableDeclaration()
0322: * f1 -> ";"
0323: * </PRE>
0324: */
0325: public Object visit(VariableDeclarationBlock n, Object argu) {
0326: return n.f0.accept(this , argu);
0327: }
0328:
0329: /*=======================================================================*/
0330: /**
0331: * <PRE>
0332: * f0 -> Expression()
0333: * f1 -> ";"
0334: * </PRE>
0335: */
0336: public Object visit(ExpressionBlock n, Object argu) {
0337: return n.f0.accept(this , argu);
0338: }
0339:
0340: /*=======================================================================*/
0341: /**
0342: * <PRE>
0343: * f0 -> "throw"
0344: * f1 -> Expression()
0345: * f2 -> ";"
0346: * </PRE>
0347: */
0348: public Object visit(ThrowBlock n, Object argu) {
0349: Value val = returnHelper((Value) (n.f1.accept(this , argu)));
0350:
0351: throw PackagedScriptObjectException.makeExceptionWrapper2(val);
0352: }
0353:
0354: /*=======================================================================*/
0355: /**
0356: * <PRE>
0357: * f0 -> "import"
0358: * f1 -> Expression()
0359: * f2 -> ";"
0360: * </PRE>
0361: */
0362: public Object visit(ImportBlock n, Object argu) {
0363: Value val = (Value) (n.f1.accept(this , argu));
0364: return OscriptInterpreter.importHelper(val.castToString(),
0365: this Scope);
0366: }
0367:
0368: /*=======================================================================*/
0369: /**
0370: * <PRE>
0371: * f0 -> "mixin"
0372: * f1 -> Expression()
0373: * f2 -> ";"
0374: * </PRE>
0375: */
0376: public Object visit(MixinBlock n, Object argu) {
0377: this Scope.mixin((Value) (n.f1.accept(this , argu)));
0378: return null;
0379: }
0380:
0381: /*=======================================================================*/
0382: /**
0383: * <PRE>
0384: * f0 -> "eval"
0385: * f1 -> Expression()
0386: * f2 -> ";"
0387: * </PRE>
0388: */
0389: public Object visit(EvalBlock n, Object argu) {
0390: // f1 should evaluate to a string:
0391: Value val = (Value) (n.f1.accept(this , argu));
0392:
0393: try {
0394: OscriptInterpreter.eval(val.castToString(), this Scope);
0395: } catch (ParseException e) {
0396: throw PackagedScriptObjectException
0397: .makeExceptionWrapper(new OException(e.getMessage()));
0398: }
0399:
0400: return null;
0401: }
0402:
0403: /*=======================================================================*/
0404: /**
0405: * <PRE>
0406: * f0 -> Permissions()
0407: * f1 -> "var"
0408: * f2 -> <IDENTIFIER>
0409: * f3 -> ( "=" Expression() )?
0410: * </PRE>
0411: */
0412: public Object visit(VariableDeclaration n, Object argu) {
0413: n.f0.accept(this , argu);
0414:
0415: Value val = null;
0416:
0417: if (n.f3.present())
0418: val = (Value) (((NodeSequence) (n.f3.node)).elementAt(1)
0419: .accept(this , argu));
0420:
0421: Value var = this Scope.createMember((Value) (n.f2.accept(this ,
0422: argu)), Permissions_attr);
0423:
0424: if (n.f3.present())
0425: var.opAssign(val);
0426:
0427: return null;
0428: }
0429:
0430: /*=======================================================================*/
0431: /**
0432: * <PRE>
0433: * f0 -> Permissions()
0434: * f1 -> "function"
0435: * f2 -> <IDENTIFIER>
0436: * f3 -> "("
0437: * f4 -> ( Arglist() )?
0438: * f5 -> ")"
0439: * f6 -> ( "extends" PrimaryExpressionWithTrailingFxnCallExpList() FunctionCallExpressionList() )?
0440: * f7 -> "{"
0441: * f8 -> Program()
0442: * f9 -> "}"
0443: * </PRE>
0444: */
0445: public Object visit(FunctionDeclaration n, Object argu) {
0446: return FunctionDeclarationTranslator.translate(n).accept(this ,
0447: argu);
0448: }
0449:
0450: /*=======================================================================*/
0451: /**
0452: * <PRE>
0453: * f0 -> Permissions()
0454: * f1 -> <IDENTIFIER>
0455: * f2 -> ( "," Permissions() <IDENTIFIER> )*
0456: * f3 -> ( "..." )?
0457: * </PRE>
0458: */
0459: public Object visit(Arglist n, Object argu) {
0460: if (n.cachedValue == null) {
0461: int len = 2 * (n.f2.size() + 1);
0462:
0463: n.cachedValue = new int[len];
0464: n.cachedValue[0] = Symbol.getSymbol(
0465: (OString) (n.f1.accept(this , argu))).getId();
0466: n.cachedValue[1] = getPermissions(n.f0,
0467: Reference.ATTR_PRIVATE);
0468:
0469: for (int i = 0; i < n.f2.size(); i++) {
0470: n.cachedValue[2 * (i + 1)] = Symbol.getSymbol(
0471: (OString) (((NodeSequence) (n.f2.elementAt(i)))
0472: .elementAt(2).accept(this , argu)))
0473: .getId();
0474: n.cachedValue[2 * (i + 1) + 1] = getPermissions(
0475: (Permissions) (((NodeSequence) (n.f2
0476: .elementAt(i))).elementAt(1)),
0477: Reference.ATTR_PRIVATE);
0478: }
0479: }
0480:
0481: Arglist_names = n.cachedValue;
0482: Arglist_varargs = n.f3.present();
0483:
0484: return null;
0485: }
0486:
0487: /*=======================================================================*/
0488: /**
0489: * <PRE>
0490: * f0 -> "try"
0491: * f1 -> EvaluationUnit()
0492: * f2 -> ( "catch" "(" Expression() <IDENTIFIER> ")" EvaluationUnit() )*
0493: * f3 -> ( "catch" "(" <IDENTIFIER> ")" EvaluationUnit() )?
0494: * f4 -> ( "finally" EvaluationUnit() )?
0495: * </PRE>
0496: */
0497: public Object visit(TryStatement n, Object argu) {
0498: try {
0499: n.f1.accept(this , argu);
0500: } catch (PackagedScriptObjectException e) {
0501: NodeToken nt = getLastNodeToken();
0502:
0503: boolean handled = false;
0504:
0505: for (int i = 0; (i < n.f2.size()) && !handled; i++) {
0506: NodeSequence seq = (NodeSequence) (n.f2.elementAt(i));
0507:
0508: Value val = (Value) (seq.elementAt(2)
0509: .accept(this , argu));
0510:
0511: if (e.val.bopInstanceOf(val).castToBoolean()) {
0512: handled = true;
0513:
0514: // push:
0515: Scope savedThisScope = this Scope;
0516: this Scope = new BasicScope(this Scope);
0517:
0518: try {
0519: Value var = this Scope
0520: .createMember((Value) (seq.elementAt(3)
0521: .accept(this , argu)), 0 /*XXX*/);
0522: var.opAssign(e.val);
0523:
0524: seq.elementAt(5).accept(this , argu);
0525: } finally {
0526: // pop:
0527: this Scope = savedThisScope;
0528: }
0529: }
0530: }
0531:
0532: if (n.f3.present() && !handled) {
0533: handled = true;
0534:
0535: NodeSequence seq = (NodeSequence) (n.f3.node);
0536:
0537: // push:
0538: Scope savedThisScope = this Scope;
0539: this Scope = new BasicScope(this Scope);
0540:
0541: try {
0542: Value var = this Scope
0543: .createMember((Value) (seq.elementAt(2)
0544: .accept(this , argu)), 0 /*XXX*/);
0545: var.opAssign(e.val);
0546:
0547: seq.elementAt(4).accept(this , argu);
0548: } finally {
0549: // pop:
0550: this Scope = savedThisScope;
0551: }
0552: }
0553:
0554: if (!handled)
0555: throw e;
0556: } finally {
0557: // XXX this is maybe a bug, if BREAK, CONTINUE, or RETURN are thrown...
0558: if (n.f4.present())
0559: ((NodeSequence) (n.f4.node)).elementAt(1).accept(this ,
0560: argu);
0561: }
0562:
0563: return null;
0564: }
0565:
0566: /*=======================================================================*/
0567: /**
0568: * <PRE>
0569: * f0 -> "for"
0570: * f1 -> "("
0571: * f2 -> ( PreLoopStatement() )?
0572: * f3 -> ";"
0573: * f4 -> ( Expression() )?
0574: * f5 -> ";"
0575: * f6 -> ( Expression() )?
0576: * f7 -> ")"
0577: * f8 -> EvaluationUnit()
0578: * </PRE>
0579: */
0580: public Object visit(ForLoopStatement n, Object argu) {
0581: return ForLoopStatementTranslator.translate(n).accept(this ,
0582: argu);
0583: }
0584:
0585: /*=======================================================================*/
0586: /**
0587: * <PRE>
0588: * f0 -> "for"
0589: * f1 -> "("
0590: * f2 -> PreLoopStatement()
0591: * f3 -> ":"
0592: * f4 -> Expression()
0593: * f5 -> ")"
0594: * f6 -> EvaluationUnit()
0595: * </PRE>
0596: */
0597: public Object visit(CollectionForLoopStatement n, Object argu) {
0598: return CollectionForLoopStatementTranslator.translate(n)
0599: .accept(this , argu);
0600: }
0601:
0602: /*=======================================================================*/
0603: /**
0604: * <PRE>
0605: * f0 -> VariableDeclaration()
0606: * | Expression()
0607: * </PRE>
0608: */
0609: public Object visit(PreLoopStatement n, Object argu) {
0610: return n.f0.accept(this , argu);
0611: }
0612:
0613: /*=======================================================================*/
0614: /**
0615: * <PRE>
0616: * f0 -> "while"
0617: * f1 -> "("
0618: * f2 -> Expression()
0619: * f3 -> ")"
0620: * f4 -> EvaluationUnit()
0621: * </PRE>
0622: */
0623: public Object visit(WhileLoopStatement n, Object argu) {
0624: while (((Value) (n.f2.accept(this , argu))).castToBoolean()) {
0625: // evaluate body:
0626: try {
0627: n.f4.accept(this , argu);
0628: } catch (Break e) {
0629: break;
0630: } catch (Continue e) {
0631: continue;
0632: }
0633: }
0634:
0635: return null;
0636: }
0637:
0638: /*=======================================================================*/
0639: /**
0640: * <PRE>
0641: * f0 -> "if"
0642: * f1 -> "("
0643: * f2 -> Expression()
0644: * f3 -> ")"
0645: * f4 -> EvaluationUnit()
0646: * f5 -> ( "else" EvaluationUnit() )?
0647: * </PRE>
0648: */
0649: public Object visit(ConditionalStatement n, Object argu) {
0650: Value val = (Value) (n.f2.accept(this , argu));
0651:
0652: if (val.castToBoolean()) {
0653: n.f4.accept(this , argu);
0654: } else if (n.f5.present()) {
0655: ((NodeSequence) (n.f5.node)).elementAt(1)
0656: .accept(this , argu);
0657: }
0658:
0659: return null;
0660: }
0661:
0662: /*=======================================================================*/
0663: /**
0664: * <PRE>
0665: * f0 -> "synchronized"
0666: * f1 -> "("
0667: * f2 -> Expression()
0668: * f3 -> ")"
0669: * f4 -> EvaluationUnit()
0670: * </PRE>
0671: */
0672: public Object visit(SynchronizedStatement n, Object argu) {
0673: Value syncVal = (Value) (n.f2.accept(this , argu));
0674:
0675: synchronized (syncVal.getMonitor()) {
0676: n.f4.accept(this , argu);
0677: }
0678:
0679: return null;
0680: }
0681:
0682: /*=======================================================================*/
0683: /**
0684: * <PRE>
0685: * f0 -> "return"
0686: * f1 -> ( Expression() )?
0687: * </PRE>
0688: */
0689: public Object visit(ReturnStatement n, Object argu) {
0690: retVal = Value.UNDEFINED;
0691:
0692: if (n.f1.present())
0693: retVal = returnHelper((Value) (n.f1.node.accept(this , argu)));
0694:
0695: throw RETURN;
0696: }
0697:
0698: private static final Value returnHelper(Value val) {
0699: // XXX
0700: return oscript.compiler.CompiledNodeEvaluator.returnHelper(val);
0701: }
0702:
0703: /*=======================================================================*/
0704: /**
0705: * <PRE>
0706: * f0 -> "break"
0707: * f1 -> ";"
0708: * </PRE>
0709: */
0710: public Object visit(BreakStatement n, Object argu) {
0711: throw new Break();
0712: }
0713:
0714: /*=======================================================================*/
0715: /**
0716: * <PRE>
0717: * f0 -> "continue"
0718: * f1 -> ";"
0719: * </PRE>
0720: */
0721: public Object visit(ContinueStatement n, Object argu) {
0722: throw new Continue();
0723: }
0724:
0725: /*=======================================================================*/
0726: /**
0727: * <PRE>
0728: * f0 -> AssignmentExpression()
0729: * f1 -> ( "," AssignmentExpression() )*
0730: * </PRE>
0731: */
0732: public Object visit(Expression n, Object argu) {
0733: Value val = (Value) (n.f0.accept(this , argu));
0734:
0735: for (int i = 0; i < n.f1.size(); i++) {
0736: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
0737: NodeToken op = (NodeToken) (seq.elementAt(0));
0738:
0739: val = (Value) (seq.elementAt(1).accept(this , argu));
0740: }
0741:
0742: return val;
0743: }
0744:
0745: /*=======================================================================*/
0746: /**
0747: * <PRE>
0748: * f0 -> "("
0749: * f1 -> ( FunctionCallExpressionListBody() )?
0750: * f2 -> ")"
0751: * </PRE>
0752: */
0753: public Object visit(FunctionCallExpressionList n, Object argu) {
0754: n.f0.accept(this , argu); // to record last NodeToken
0755:
0756: if (n.f1.present())
0757: return n.f1.node.accept(this , argu);
0758: else
0759: return new Value[0];
0760: }
0761:
0762: /*=======================================================================*/
0763: /**
0764: * <PRE>
0765: * f0 -> AssignmentExpression()
0766: * f1 -> ( "," AssignmentExpression() )*
0767: * </PRE>
0768: */
0769: public Object visit(FunctionCallExpressionListBody n, Object argu) {
0770: Value[] vals = new Value[1 + n.f1.size()];
0771:
0772: vals[0] = ((Value) (n.f0.accept(this , argu))).unhand();
0773:
0774: for (int i = 0; i < n.f1.size(); i++) {
0775: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
0776:
0777: vals[i + 1] = ((Value) (seq.elementAt(1).accept(this , argu)))
0778: .unhand();
0779: }
0780:
0781: return vals;
0782: }
0783:
0784: /*=======================================================================*/
0785: /**
0786: * <PRE>
0787: * f0 -> ConditionalExpression()
0788: * f1 -> ( ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" | ">>=" | "<<=" | ">>>=" | "&=" | "^=" | "|=" ) ConditionalExpression() )*
0789: * </PRE>
0790: */
0791: public Object visit(AssignmentExpression n, Object argu) {
0792: Value lastVal = null;
0793: int lastOp = -1;
0794:
0795: for (int i = n.f1.size() - 1; i >= -1; i--) {
0796: Value val;
0797: int op = lastOp; // the op this time through the loop was determined last time
0798:
0799: if (i >= 0) {
0800: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
0801:
0802: val = (Value) (seq.elementAt(1).accept(this , argu));
0803: lastOp = ((NodeToken) (((NodeChoice) (seq.elementAt(0))).choice)).kind;
0804: } else {
0805: val = (Value) (n.f0.accept(this , argu));
0806: }
0807:
0808: if (op != -1) {
0809: switch (op) {
0810: case ASSIGN:
0811: // no-op
0812: break;
0813: case PLUSASSIGN:
0814: lastVal = val.bopPlus(lastVal);
0815: break;
0816: case MINUSASSIGN:
0817: lastVal = val.bopMinus(lastVal);
0818: break;
0819: case STARASSIGN:
0820: lastVal = val.bopMultiply(lastVal);
0821: break;
0822: case SLASHASSIGN:
0823: lastVal = val.bopDivide(lastVal);
0824: break;
0825: case ANDASSIGN:
0826: lastVal = val.bopBitwiseAnd(lastVal);
0827: break;
0828: case ORASSIGN:
0829: lastVal = val.bopBitwiseOr(lastVal);
0830: break;
0831: case XORASSIGN:
0832: lastVal = val.bopBitwiseXor(lastVal);
0833: break;
0834: case REMASSIGN:
0835: lastVal = val.bopRemainder(lastVal);
0836: break;
0837: case LSHIFTASSIGN:
0838: lastVal = val.bopLeftShift(lastVal);
0839: break;
0840: case RSIGNEDSHIFTASSIGN:
0841: lastVal = val.bopSignedRightShift(lastVal);
0842: break;
0843: case RUNSIGNEDSHIFTASSIGN:
0844: lastVal = val.bopUnsignedRightShift(lastVal);
0845: break;
0846: default:
0847: throw new ProgrammingErrorException(
0848: "unknown operator: " + op);
0849: }
0850:
0851: val.opAssign(lastVal);
0852: }
0853:
0854: lastVal = val;
0855: }
0856:
0857: return lastVal;
0858: }
0859:
0860: /*=======================================================================*/
0861: /**
0862: * <PRE>
0863: * f0 -> LogicalOrExpression()
0864: * f1 -> ( "?" LogicalOrExpression() ":" LogicalOrExpression() )?
0865: * </PRE>
0866: */
0867: public Object visit(ConditionalExpression n, Object argu) {
0868: Value val = (Value) (n.f0.accept(this , argu));
0869:
0870: if (n.f1.present()) {
0871: if (val.castToBoolean())
0872: val = (Value) (((NodeListInterface) n.f1.node)
0873: .elementAt(1).accept(this , argu));
0874: else
0875: val = (Value) (((NodeListInterface) n.f1.node)
0876: .elementAt(3).accept(this , argu));
0877: }
0878:
0879: return val;
0880: }
0881:
0882: /*=======================================================================*/
0883: /**
0884: * <PRE>
0885: * f0 -> LogicalAndExpression()
0886: * f1 -> ( "||" LogicalAndExpression() )*
0887: * </PRE>
0888: */
0889: public Object visit(LogicalOrExpression n, Object argu) {
0890: Value val = (Value) (n.f0.accept(this , argu));
0891:
0892: for (int i = 0; i < n.f1.size(); i++) {
0893: if (val.castToBoolean())
0894: break;
0895:
0896: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
0897:
0898: // evaluate rhs:
0899: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
0900:
0901: val = val.bopLogicalOr(val2);
0902: }
0903:
0904: return val;
0905: }
0906:
0907: /*=======================================================================*/
0908: /**
0909: * <PRE>
0910: * f0 -> BitwiseOrExpression()
0911: * f1 -> ( "&&" BitwiseOrExpression() )*
0912: * </PRE>
0913: */
0914: public Object visit(LogicalAndExpression n, Object argu) {
0915: Value val = (Value) (n.f0.accept(this , argu));
0916:
0917: for (int i = 0; i < n.f1.size(); i++) {
0918: if (!val.castToBoolean())
0919: break;
0920:
0921: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
0922:
0923: // evaluate rhs:
0924: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
0925:
0926: val = val.bopLogicalAnd(val2);
0927: }
0928:
0929: return val;
0930: }
0931:
0932: /*=======================================================================*/
0933: /**
0934: * <PRE>
0935: * f0 -> BitwiseXorExpression()
0936: * f1 -> ( "|" BitwiseXorExpression() )*
0937: * </PRE>
0938: */
0939: public Object visit(BitwiseOrExpression n, Object argu) {
0940: Value val = (Value) (n.f0.accept(this , argu));
0941:
0942: for (int i = 0; i < n.f1.size(); i++) {
0943: Value val2 = (Value) ((((NodeSequence) n.f1.elementAt(i)))
0944: .elementAt(1).accept(this , argu));
0945:
0946: val = val.bopBitwiseOr(val2);
0947: }
0948:
0949: return val;
0950: }
0951:
0952: /*=======================================================================*/
0953: /**
0954: * <PRE>
0955: * f0 -> BitwiseAndExpression()
0956: * f1 -> ( "^" BitwiseAndExpression() )*
0957: * </PRE>
0958: */
0959: public Object visit(BitwiseXorExpression n, Object argu) {
0960: Value val = (Value) (n.f0.accept(this , argu));
0961:
0962: for (int i = 0; i < n.f1.size(); i++) {
0963: Value val2 = (Value) ((((NodeSequence) n.f1.elementAt(i)))
0964: .elementAt(1).accept(this , argu));
0965:
0966: val = val.bopBitwiseXor(val2);
0967: }
0968:
0969: return val;
0970: }
0971:
0972: /*=======================================================================*/
0973: /**
0974: * <PRE>
0975: * f0 -> EqualityExpression()
0976: * f1 -> ( "&" EqualityExpression() )*
0977: * </PRE>
0978: */
0979: public Object visit(BitwiseAndExpression n, Object argu) {
0980: Value val = (Value) (n.f0.accept(this , argu));
0981:
0982: for (int i = 0; i < n.f1.size(); i++) {
0983: Value val2 = (Value) ((((NodeSequence) n.f1.elementAt(i)))
0984: .elementAt(1).accept(this , argu));
0985:
0986: val = val.bopBitwiseAnd(val2);
0987: }
0988:
0989: return val;
0990: }
0991:
0992: /*=======================================================================*/
0993: /**
0994: * <PRE>
0995: * f0 -> RelationalExpression()
0996: * f1 -> ( ( "==" | "!=" ) RelationalExpression() )*
0997: * </PRE>
0998: */
0999: public Object visit(EqualityExpression n, Object argu) {
1000: Value val = (Value) (n.f0.accept(this , argu));
1001:
1002: for (int i = 0; i < n.f1.size(); i++) {
1003: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1004: NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1005:
1006: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
1007:
1008: switch (op.kind) {
1009: case EQ:
1010: val = val.bopEquals(val2);
1011: break;
1012: case NE:
1013: val = val.bopNotEquals(val2);
1014: break;
1015: default:
1016: throw new ProgrammingErrorException("bad binary op: "
1017: + OscriptParser.getTokenString(op.kind));
1018: }
1019: }
1020:
1021: return val;
1022: }
1023:
1024: /*=======================================================================*/
1025: /**
1026: * <PRE>
1027: * f0 -> ShiftExpression()
1028: * f1 -> ( ( "<" | ">" | ">=" | "<=" | "instanceof" ) ShiftExpression() )*
1029: * </PRE>
1030: */
1031: public Object visit(RelationalExpression n, Object argu) {
1032: Value val = (Value) (n.f0.accept(this , argu));
1033:
1034: for (int i = 0; i < n.f1.size(); i++) {
1035: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1036: NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1037:
1038: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
1039:
1040: switch (op.kind) {
1041: case LT:
1042: val = val.bopLessThan(val2);
1043: break;
1044: case GT:
1045: val = val.bopGreaterThan(val2);
1046: break;
1047: case LE:
1048: val = val.bopLessThanOrEquals(val2);
1049: break;
1050: case GE:
1051: val = val.bopGreaterThanOrEquals(val2);
1052: break;
1053: case INSTANCEOF:
1054: val = val.bopInstanceOf(val2);
1055: break;
1056: default:
1057: throw new ProgrammingErrorException("bad binary op: "
1058: + OscriptParser.getTokenString(op.kind));
1059: }
1060: }
1061:
1062: return val;
1063: }
1064:
1065: /*=======================================================================*/
1066: /**
1067: * <PRE>
1068: * f0 -> AdditiveExpression()
1069: * f1 -> ( ( "<<" | ">>" | ">>>" ) AdditiveExpression() )*
1070: * </PRE>
1071: */
1072: public Object visit(ShiftExpression n, Object argu) {
1073: Value val = (Value) (n.f0.accept(this , argu));
1074:
1075: for (int i = 0; i < n.f1.size(); i++) {
1076: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1077: NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1078:
1079: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
1080:
1081: switch (op.kind) {
1082: case LSHIFT:
1083: val = val.bopLeftShift(val2);
1084: break;
1085: case RSIGNEDSHIFT:
1086: val = val.bopSignedRightShift(val2);
1087: break;
1088: case RUNSIGNEDSHIFT:
1089: val = val.bopUnsignedRightShift(val2);
1090: break;
1091: default:
1092: throw new ProgrammingErrorException("bad binary op: "
1093: + OscriptParser.getTokenString(op.kind));
1094: }
1095: }
1096:
1097: return val;
1098: }
1099:
1100: /*=======================================================================*/
1101: /**
1102: * <PRE>
1103: * f0 -> MultiplicativeExpression()
1104: * f1 -> ( ( "+" | "-" ) MultiplicativeExpression() )*
1105: * </PRE>
1106: */
1107: public Object visit(AdditiveExpression n, Object argu) {
1108: Value val = (Value) (n.f0.accept(this , argu));
1109:
1110: for (int i = 0; i < n.f1.size(); i++) {
1111: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1112: NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1113:
1114: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
1115:
1116: switch (op.kind) {
1117: case PLUS:
1118: val = val.bopPlus(val2);
1119: break;
1120: case MINUS:
1121: val = val.bopMinus(val2);
1122: break;
1123: default:
1124: throw new ProgrammingErrorException("bad binary op: "
1125: + OscriptParser.getTokenString(op.kind));
1126: }
1127: }
1128:
1129: return val;
1130: }
1131:
1132: /*=======================================================================*/
1133: /**
1134: * <PRE>
1135: * f0 -> UnaryExpression()
1136: * f1 -> ( ( "*" | "/" | "%" ) UnaryExpression() )*
1137: * </PRE>
1138: */
1139: public Object visit(MultiplicativeExpression n, Object argu) {
1140: Value val = (Value) (n.f0.accept(this , argu));
1141:
1142: for (int i = 0; i < n.f1.size(); i++) {
1143: NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1144: NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1145:
1146: Value val2 = (Value) (seq.elementAt(1).accept(this , argu));
1147:
1148: switch (op.kind) {
1149: case STAR:
1150: val = val.bopMultiply(val2);
1151: break;
1152: case SLASH:
1153: val = val.bopDivide(val2);
1154: break;
1155: case REM:
1156: val = val.bopRemainder(val2);
1157: break;
1158: default:
1159: throw new ProgrammingErrorException("bad binary op: "
1160: + OscriptParser.getTokenString(op.kind));
1161: }
1162: }
1163:
1164: return val;
1165: }
1166:
1167: /*=======================================================================*/
1168: /**
1169: * <PRE>
1170: * f0 -> ( ( "++" | "--" | "+" | "-" | "~" | "!" ) )?
1171: * f1 -> PostfixExpression()
1172: * </PRE>
1173: */
1174: public Object visit(UnaryExpression n, Object argu) {
1175: Value val = (Value) (n.f1.accept(this , argu));
1176:
1177: if (n.f0.present()) {
1178: // get NodeToken_kind
1179: n.f0.node.accept(this , argu);
1180:
1181: switch (NodeToken_kind) {
1182: case INCR:
1183: val.opAssign(val.uopIncrement());
1184: break;
1185: case DECR:
1186: val.opAssign(val.uopDecrement());
1187: break;
1188: case PLUS:
1189: val = val.uopPlus();
1190: break;
1191: case MINUS:
1192: val = val.uopMinus();
1193: break;
1194: case TILDE:
1195: val = val.uopBitwiseNot();
1196: break;
1197: case BANG:
1198: val = val.uopLogicalNot();
1199: break;
1200: default:
1201: throw new ProgrammingErrorException("bad unary op: "
1202: + NodeToken_kind);
1203: }
1204: }
1205:
1206: return val;
1207: }
1208:
1209: /*=======================================================================*/
1210: /**
1211: * <PRE>
1212: * f0 -> TypeExpression()
1213: * f1 -> ( "++" | "--" )?
1214: * </PRE>
1215: */
1216: public Object visit(PostfixExpression n, Object argu) {
1217: Value val = (Value) (n.f0.accept(this , argu));
1218:
1219: if (n.f1.present()) {
1220: // get NodeToken_kind
1221: n.f1.node.accept(this , argu);
1222:
1223: // save original value:
1224: Value origVal = val.unhand();
1225:
1226: // do op:
1227: switch (NodeToken_kind) {
1228: case INCR:
1229: val.opAssign(val.uopIncrement());
1230: break;
1231: case DECR:
1232: val.opAssign(val.uopDecrement());
1233: break;
1234: default:
1235: throw new ProgrammingErrorException("bad unary op: "
1236: + NodeToken_kind);
1237: }
1238:
1239: val = origVal;
1240: }
1241:
1242: return val;
1243: }
1244:
1245: /*=======================================================================*/
1246: /**
1247: * <PRE>
1248: * f0 -> AllocationExpression()
1249: * | CastExpression()
1250: * | PrimaryExpression()
1251: * </PRE>
1252: */
1253: public Object visit(TypeExpression n, Object argu) {
1254: return n.f0.accept(this , argu);
1255: }
1256:
1257: /*=======================================================================*/
1258: /**
1259: * <PRE>
1260: * f0 -> "new"
1261: * f1 -> PrimaryExpressionWithTrailingFxnCallExpList()
1262: * f2 -> FunctionCallExpressionList()
1263: * </PRE>
1264: */
1265: public Object visit(AllocationExpression n, Object argu) {
1266: Value val = (Value) (n.f1.accept(this , argu));
1267: Value[] args = (Value[]) (n.f2.accept(this , argu));
1268:
1269: return val.callAsConstructor(args);
1270: }
1271:
1272: /*=======================================================================*/
1273: /**
1274: * <PRE>
1275: * f0 -> "("
1276: * f1 -> PrimaryExpressionNotFunction()
1277: * f2 -> ")"
1278: * f3 -> PrimaryExpression()
1279: * </PRE>
1280: */
1281: public Object visit(CastExpression n, Object argu) {
1282: return ((Value) (n.f1.accept(this , argu)))
1283: .bopCast((Value) (n.f3.accept(this , argu)));
1284: }
1285:
1286: /*=======================================================================*/
1287: /**
1288: * <PRE>
1289: * f0 -> PrimaryPrefix()
1290: * f1 -> ( PrimaryPostfix() )*
1291: * </PRE>
1292: */
1293: public Object visit(PrimaryExpression n, Object argu) {
1294: Value val = (Value) (n.f0.accept(this , argu));
1295:
1296: for (int i = 0; i < n.f1.size(); i++) {
1297: val = (Value) (n.f1.elementAt(i).accept(this , val));
1298: }
1299:
1300: return val;
1301: }
1302:
1303: /*=======================================================================*/
1304: /**
1305: * <PRE>
1306: * f0 -> PrimaryPrefix()
1307: * f1 -> ( PrimaryPostfix() )*
1308: * </PRE>
1309: */
1310: public Object visit(PrimaryExpressionNotFunction n, Object argu) {
1311: Value val = (Value) (n.f0.accept(this , argu));
1312:
1313: for (int i = 0; i < n.f1.size(); i++) {
1314: val = (Value) (n.f1.elementAt(i).accept(this , val));
1315: }
1316:
1317: return val;
1318: }
1319:
1320: /*=======================================================================*/
1321: /**
1322: * <PRE>
1323: * f0 -> PrimaryPrefix()
1324: * f1 -> ( PrimaryPostfixWithTrailingFxnCallExpList() )*
1325: * </PRE>
1326: */
1327: public Object visit(PrimaryExpressionWithTrailingFxnCallExpList n,
1328: Object argu) {
1329: Value val = (Value) (n.f0.accept(this , argu));
1330:
1331: for (int i = 0; i < n.f1.size(); i++) {
1332: val = (Value) (n.f1.elementAt(i).accept(this , val));
1333: }
1334:
1335: return val;
1336: }
1337:
1338: /*=======================================================================*/
1339: /**
1340: * <PRE>
1341: * f0 -> PrimaryPrefixNotFunction()
1342: * | FunctionPrimaryPrefix()
1343: * | ShorthandFunctionPrimaryPrefix()
1344: * </PRE>
1345: */
1346: public Object visit(PrimaryPrefix n, Object argu) {
1347: return n.f0.accept(this , argu);
1348: }
1349:
1350: /*=======================================================================*/
1351: /**
1352: * <PRE>
1353: * f0 -> ThisPrimaryPrefix()
1354: * | SuperPrimaryPrefix()
1355: * | CalleePrimaryPrefix()
1356: * | IdentifierPrimaryPrefix()
1357: * | ParenPrimaryPrefix()
1358: * | ArrayDeclarationPrimaryPrefix()
1359: * | Literal()
1360: * </PRE>
1361: */
1362: public Object visit(PrimaryPrefixNotFunction n, Object argu) {
1363: return n.f0.accept(this , argu);
1364: }
1365:
1366: /*=======================================================================*/
1367: /**
1368: * <PRE>
1369: * f0 -> "this"
1370: * </PRE>
1371: */
1372: public Object visit(ThisPrimaryPrefix n, Object argu) {
1373: return this Scope.getThis();
1374: }
1375:
1376: /*=======================================================================*/
1377: /**
1378: * <PRE>
1379: * f0 -> "super"
1380: * </PRE>
1381: */
1382: public Object visit(SuperPrimaryPrefix n, Object argu) {
1383: return this Scope.getSuper();
1384: }
1385:
1386: /*=======================================================================*/
1387: /**
1388: * <PRE>
1389: * f0 -> "callee"
1390: * </PRE>
1391: */
1392: public Object visit(CalleePrimaryPrefix n, Object argu) {
1393: return this Scope.getCallee();
1394: }
1395:
1396: /*=======================================================================*/
1397: /**
1398: * <PRE>
1399: * f0 -> <IDENTIFIER>
1400: * </PRE>
1401: */
1402: public Object visit(IdentifierPrimaryPrefix n, Object argu) {
1403: return this Scope
1404: .lookupInScope((Value) (n.f0.accept(this , argu)));
1405: }
1406:
1407: /*=======================================================================*/
1408: /**
1409: * <PRE>
1410: * f0 -> "("
1411: * f1 -> Expression()
1412: * f2 -> ")"
1413: * </PRE>
1414: */
1415: public Object visit(ParenPrimaryPrefix n, Object argu) {
1416: return n.f1.accept(this , argu);
1417: }
1418:
1419: /*=======================================================================*/
1420: private static final int[] EMPTY_ARG_NAMES = new int[0];
1421:
1422: /**
1423: * <PRE>
1424: * f0 -> "function"
1425: * f1 -> "("
1426: * f2 -> ( Arglist() )?
1427: * f3 -> ")"
1428: * f4 -> ( "extends" PrimaryExpressionWithTrailingFxnCallExpList() FunctionCallExpressionList() )?
1429: * f5 -> "{"
1430: * f6 -> Program()
1431: * f7 -> "}"
1432: * </PRE>
1433: */
1434: public Object visit(FunctionPrimaryPrefix n, Object argu) {
1435: if (n.fd == null) {
1436: Value oname = Symbol.getSymbol(n.id);
1437: String name = oname.castToString();
1438: int[] argIds;
1439: boolean varargs;
1440:
1441: // just in case, to get the specials...
1442: n.f0.accept(this , argu);
1443:
1444: // get arglist:
1445: if (n.f2.present()) {
1446: n.f2.node.accept(this , argu);
1447: argIds = Arglist_names;
1448: varargs = Arglist_varargs;
1449: } else {
1450: argIds = EMPTY_ARG_NAMES;
1451: varargs = false;
1452: }
1453:
1454: // get extends evaluator:
1455: oscript.NodeEvaluator functionCallExpressionListEvaluator = null;
1456:
1457: if (n.f4.present()) {
1458: FunctionCallExpressionList functionCallExpressionList = (FunctionCallExpressionList) (((NodeSequence) (n.f4.node))
1459: .elementAt(2));
1460:
1461: synchronized (functionCallExpressionList) {
1462: if (functionCallExpressionList.nodeEvaluator == null) {
1463: functionCallExpressionList.nodeEvaluator = oscript.OscriptInterpreter
1464: .createNodeEvaluator(name + "$extends",
1465: functionCallExpressionList);
1466: }
1467: }
1468:
1469: functionCallExpressionListEvaluator = functionCallExpressionList.nodeEvaluator;
1470: }
1471:
1472: oscript.NodeEvaluator nodeEvaluator = OscriptInterpreter
1473: .createNodeEvaluator(name, n.f6);
1474:
1475: {
1476: oscript.util.SymbolTable smit = nodeEvaluator
1477: .getSharedMemberIndexTable(oscript.NodeEvaluator.ALL);
1478: for (int i = 0; i < argIds.length; i += 2)
1479: smit.create(argIds[i]);
1480: }
1481:
1482: oscript.NodeEvaluator staticNodeEvaluator = null;
1483: if (n.f6.staticNodes != null)
1484: staticNodeEvaluator = OscriptInterpreter
1485: .createNodeEvaluator(name + "$static",
1486: n.f6.staticNodes);
1487:
1488: // the syntaxtree won't change, so we only need to parse the comment once:
1489: synchronized (n) {
1490: if (!n.commentParsed) {
1491: n.commentParsed = true;
1492: if (NodeToken_lastSpecials != null)
1493: n.comment = Function.extractJavadocComment(
1494: NodeToken_lastSpecials, oname, argIds);
1495: }
1496: }
1497:
1498: n.fd = new Function.FunctionData(n.id, argIds, varargs,
1499: functionCallExpressionListEvaluator, nodeEvaluator,
1500: staticNodeEvaluator, n.hasVarInScope,
1501: n.hasFxnInScope, n.comment);
1502: }
1503:
1504: // get extends:
1505: Value super Fxn = null;
1506: if (n.f4.present()) {
1507: Value val = (Value) (((NodeSequence) (n.f4.node))
1508: .elementAt(1).accept(this , argu));
1509: super Fxn = val.unhand();
1510: }
1511:
1512: return new Function(this Scope, super Fxn, n.fd);
1513: }
1514:
1515: /*=======================================================================*/
1516: /**
1517: * <PRE>
1518: * f0 -> "'{"
1519: * f1 -> Program(true)
1520: * f2 -> "}"
1521: * </PRE>
1522: */
1523: public Object visit(ShorthandFunctionPrimaryPrefix n, Object argu) {
1524: return ShorthandFunctionPrimaryPrefixTranslator.translate(n)
1525: .accept(this , argu);
1526: }
1527:
1528: /*=======================================================================*/
1529: /**
1530: * <PRE>
1531: * f0 -> "["
1532: * f1 -> (FunctionCallExpressionListBody())?
1533: * f2 -> "]"
1534: * </PRE>
1535: */
1536: public Object visit(ArrayDeclarationPrimaryPrefix n, Object argu) {
1537: Value[] vals;
1538:
1539: if (n.f1.present())
1540: vals = (Value[]) (n.f1.node.accept(this , argu));
1541: else
1542: vals = new Value[0];
1543:
1544: return new OArray(vals);
1545: }
1546:
1547: /*=======================================================================*/
1548: /**
1549: * <PRE>
1550: * f0 -> FunctionCallPrimaryPostfix()
1551: * | ArraySubscriptPrimaryPostfix()
1552: * | ThisScopeQualifierPrimaryPostfix()
1553: * | PropertyIdentifierPrimaryPostfix()
1554: * </PRE>
1555: */
1556: public Object visit(PrimaryPostfix n, Object argu) {
1557: return n.f0.accept(this , argu);
1558: }
1559:
1560: /*=======================================================================*/
1561: /**
1562: * <PRE>
1563: * f0 -> ArraySubscriptPrimaryPostfix()
1564: * | ThisScopeQualifierPrimaryPostfix()
1565: * | PropertyIdentifierPrimaryPostfix()
1566: * </PRE>
1567: */
1568: public Object visit(PrimaryPostfixWithTrailingFxnCallExpList n,
1569: Object argu) {
1570: return n.f0.accept(this , argu);
1571: }
1572:
1573: /*=======================================================================*/
1574: /**
1575: * <PRE>
1576: * f0 -> FunctionCallExpressionList()
1577: * </PRE>
1578: */
1579: public Object visit(FunctionCallPrimaryPostfix n, Object argu) {
1580: Value[] args = (Value[]) (n.f0.accept(this , argu));
1581:
1582: return ((Value) argu).callAsFunction(args);
1583: }
1584:
1585: /*=======================================================================*/
1586: /**
1587: * <PRE>
1588: * f0 -> "["
1589: * f1 -> Expression()
1590: * f2 -> ( ".." Expression() )?
1591: * f3 -> "]"
1592: * </PRE>
1593: */
1594: public Object visit(ArraySubscriptPrimaryPostfix n, Object argu) {
1595: Value idx1 = (Value) (n.f1.accept(this , argu));
1596:
1597: if (n.f2.present()) {
1598: Value idx2 = (Value) (((NodeSequence) (n.f2.node))
1599: .elementAt(1).accept(this , argu));
1600: return ((Value) argu).elementsAt(idx1, idx2);
1601: } else {
1602: return ((Value) argu).elementAt(idx1);
1603: }
1604: }
1605:
1606: /*=======================================================================*/
1607: /**
1608: * <PRE>
1609: * f0 -> "."
1610: * f1 -> <IDENTIFIER>
1611: * </PRE>
1612: */
1613: public Object visit(PropertyIdentifierPrimaryPostfix n, Object argu) {
1614: n.f0.accept(this , argu); // to record last NodeToken
1615: return ((Value) argu).getMember((Value) (n.f1
1616: .accept(this , argu)));
1617: }
1618:
1619: /*=======================================================================*/
1620: /**
1621: * <PRE>
1622: * f0 -> "."
1623: * f1 -> "this"
1624: * </PRE>
1625: */
1626: public Object visit(ThisScopeQualifierPrimaryPostfix n, Object argu) {
1627: n.f0.accept(this , argu); // to record last NodeToken
1628: return this Scope.getThis((Value) argu);
1629: }
1630:
1631: /*=======================================================================*/
1632: /**
1633: * <PRE>
1634: * f0 -> <INTEGER_LITERAL>
1635: * | <FLOATING_POINT_LITERAL>
1636: * | <STRING_LITERAL>
1637: * | <REGEXP_LITERAL>
1638: * | "true"
1639: * | "false"
1640: * | "null"
1641: * | "undefined"
1642: * </PRE>
1643: */
1644: public Object visit(Literal n, Object argu) {
1645: return n.f0.choice.accept(this , argu);
1646: }
1647:
1648: /*=======================================================================*/
1649: /**
1650: * <PRE>
1651: * f0 -> ( "static" | "const" | "private" | "protected" | "public" )*
1652: * </PRE>
1653: */
1654: public Object visit(Permissions n, Object argu) {
1655: Permissions_attr = getPermissions(n, Reference.ATTR_PROTECTED);
1656: return null;
1657: }
1658:
1659: /**
1660: * Get the permissions mask...
1661: *
1662: * @param n the permissions syntaxtree node
1663: * @param attr the default permissions value
1664: * @return the permissions mask
1665: */
1666: private int getPermissions(Permissions n, int attr) {
1667: for (int i = 0; i < n.f0.size(); i++) {
1668: n.f0.elementAt(i).accept(this , null);
1669:
1670: switch (NodeToken_kind) {
1671: case PRIVATE:
1672: attr = (attr & 0xf0) | Reference.ATTR_PRIVATE;
1673: break;
1674: case PROTECTED:
1675: attr = (attr & 0xf0) | Reference.ATTR_PROTECTED;
1676: break;
1677: case PUBLIC:
1678: attr = (attr & 0xf0) | Reference.ATTR_PUBLIC;
1679: break;
1680: case STATIC:
1681: attr |= Reference.ATTR_STATIC;
1682: break;
1683: case CONST:
1684: attr |= Reference.ATTR_CONST;
1685: break;
1686: default:
1687: throw new ProgrammingErrorException(
1688: "bad kind: "
1689: + OscriptParser
1690: .getTokenString(NodeToken_lastToken.kind));
1691: }
1692: }
1693:
1694: return attr;
1695: }
1696: }
1697:
1698: /*
1699: * Local Variables:
1700: * tab-width: 2
1701: * indent-tabs-mode: nil
1702: * mode: java
1703: * c-indentation-style: java
1704: * c-basic-offset: 2
1705: * eval: (c-set-offset 'substatement-open '0)
1706: * eval: (c-set-offset 'case-label '+)
1707: * eval: (c-set-offset 'inclass '+)
1708: * eval: (c-set-offset 'inline-open '0)
1709: * End:
1710: */
|