0001 
0002 /*
0003  *  Descripter 1.0 - Java Script Engines
0004  *  Copyright (C) 2010-2015  Jianjun Liu (J.J.Liu)
0005  *  
0006  *  This program is free software: you can redistribute it and/or modify
0007  *  it under the terms of the GNU Affero General Public License as published by
0008  *  the Free Software Foundation, either version 3 of the License, or
0009  *  (at your option) any later version.
0010  *  
0011  *  This program is distributed in the hope that it will be useful,
0012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  *  GNU Affero General Public License for more details.
0015  *  
0016  *  You should have received a copy of the GNU Affero General Public License
0017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 package org.descripter.js;
0021 
0022 import java.io.Reader;
0023 import java.io.StringReader;
0024 import java.util.Set;
0025 
0026 import org.descripter.js.api.*;
0027 import org.descripter.js.parse.*;
0028 
0029 /**
0030  * <p>Represents a visitor to interpret parsed JavaScript.</p>
0031  * 
0032  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.descripter.org" target="_blank">http://www.descripter.org</a>
0033  * @since Descripter 1.0
0034  */
0035 public class Interpreter extends Visitor<Script<?>> implements JSParserVisitor
0036 {
0037     /**
0038      * <p>Constructs a visitor of this type.</p>
0039      * <p>Note, a script source can be interpreted in any script context.</p>
0040      * @param script A script context.
0041      * @since Descripter 1.0
0042      */
0043     public Interpreter(Script<?> script) {
0044         super(script);
0045     }
0046 
0047     /**
0048      * <p>Evaluates a piece of script code in the current script context.</p>
0049      * @param js JavaScript source.
0050      * @return The returned value from the script code.
0051      * @since Descripter 1.0
0052      */
0053     @Override
0054     public Object eval(String js) {
0055         return eval(new StringReader(js));
0056     }
0057 
0058     /**
0059      * <p>Evaluates the script code from the given reader in the current context.</p>
0060      * @param reader A {@link Reader} to read script source.
0061      * @return The returned value from the script code.
0062      * @since Descripter 1.0
0063      */
0064     public Object eval(Reader reader) {
0065         try {
0066             return new JSParser(reader).Program().jjtAccept(this, this);
0067         } catch (ParseException e) {
0068             throw new RuntimeException(e);
0069         }
0070     }
0071 
0072     /**
0073      * <p>Visits the children nodes of the specified node with the same argument datum and 
0074      * returns the argument.</p>
0075      * @param node The node to visit.
0076      * @param data An {@link Object} datum passed to this method.
0077      * @return An {@link Object} datum.
0078      * @since Descripter 1.0
0079      */
0080     protected final Object visitChildren(AbstractNode node, Object data) {
0081         node.acceptChildren(this, data);
0082         return data;
0083     }
0084 
0085     /**
0086      * <p>Visits the children nodes of the specified node with the same argument datum and 
0087      * returns an array of the returned data.</p>
0088      * @param node The node to visit.
0089      * @param data An {@link Object} datum passed to this method.
0090      * @return An array of the returned {@link Object} data.
0091      * @since Descripter 1.0
0092      */
0093     protected final Object evalChildren(AbstractNode node, Object data) {
0094         Object[] a = node.acceptChildren(this, data);
0095         return a != null && a.length > 0 ? a[a.length - 1] : data;
0096     }
0097 
0098     /**
0099      * <p>Visits a parsed node of the specified type.</p>
0100      * @param node The node to visit.
0101      * @param data An {@link Object} datum passed to this method.
0102      * @return An {@link Object} datum.
0103      * @since Descripter 1.0
0104      */
0105     @Override
0106     public Object visit(SimpleNode node, Object data) {
0107         return node.jjtAccept(this, data);
0108     }
0109 
0110     /**
0111      * <p>Visits a parsed node of the specified type.</p>
0112      * @param node The node to visit.
0113      * @param data An {@link Object} datum passed to this method.
0114      * @return An {@link Object} datum.
0115      * @since Descripter 1.0
0116      */
0117     @Override
0118     public Object visit(ECMAThisReference node, Object data) {
0119         if (DEBUG) debug(node);
0120         return get(core()._this);
0121     }
0122 
0123     /**
0124      * <p>Visits a parsed node of the specified type.</p>
0125      * @param node The node to visit.
0126      * @param data An {@link Object} datum passed to this method.
0127      * @return An {@link Object} datum.
0128      * @since Descripter 1.0
0129      */
0130     @Override
0131     public Object visit(ECMAGroup node, Object data) {
0132         if (DEBUG) debug(node);
0133         return node.getChild(0).jjtAccept(this, data);
0134     }
0135 
0136     /**
0137      * <p>Visits a parsed node of the specified type.</p>
0138      * @param node The node to visit.
0139      * @param data An {@link Object} datum passed to this method.
0140      * @return An {@link Object} datum.
0141      * @since Descripter 1.0
0142      */
0143     @Override
0144     public Object visit(ECMALiteral node, Object data) {
0145         if (DEBUG) debug(node);
0146         String s = node.jjtGetValue().toString();
0147         switch (node.firstToken.kind) {
0148             case JSParserConstants.BOOLEAN_LITERAL:
0149                 return s.toLowerCase().equals("true") ? true : false;
0150             case JSParserConstants.HEX_INTEGER_LITERAL:
0151                 try {
0152                     return Integer.parseInt(s.substring(2), 16);
0153                 } catch(NumberFormatException e) {
0154                     return Long.parseLong(s.substring(2), 16);
0155                 }
0156             case JSParserConstants.DECIMAL_LITERAL:
0157                 try {
0158                     return Integer.parseInt(s);
0159                 } catch(NumberFormatException e) {
0160                     try {
0161                         return Long.parseLong(s);
0162                     } catch(NumberFormatException nfe) {
0163                         return Double.parseDouble(s);
0164                     }
0165                 }
0166             case JSParserConstants.NULL_LITERAL:
0167                 return get(core()._null);
0168             case JSParserConstants.REGULAR_EXPRESSION_LITERAL:
0169                 int last = s.lastIndexOf('/');
0170                 return re(s.substring(1, last), s.substring(last + 1));
0171             default:
0172                 return s.substring(1, s.length() - 1);
0173         }
0174     }
0175 
0176     /**
0177      * <p>Visits a parsed node of the specified type.</p>
0178      * @param node The node to visit.
0179      * @param data An {@link Object} datum passed to this method.
0180      * @return An {@link Object} datum.
0181      * @since Descripter 1.0
0182      */
0183     @Override
0184     public Object visit(ECMAIdentifier node, Object data) {
0185         if (DEBUG) debug(node);
0186         return var(data, node.jjtGetValue());
0187     }
0188 
0189     /**
0190      * <p>Visits a parsed node of the specified type.</p>
0191      * @param node The node to visit.
0192      * @param data An {@link Object} datum passed to this method.
0193      * @return An {@link Object} datum.
0194      * @since Descripter 1.0
0195      */
0196     @Override
0197     public Object visit(ECMAArrayLiteral node, Object data) {
0198         if (DEBUG) debug(node);
0199         return array(node.acceptChildren(this, this));
0200     }
0201 
0202     /**
0203      * <p>Visits a parsed node of the specified type.</p>
0204      * @param node The node to visit.
0205      * @param data An {@link Object} datum passed to this method.
0206      * @return An {@link Object} datum.
0207      * @since Descripter 1.0
0208      */
0209     @Override
0210     public Object visit(ECMAObjectLiteral node, Object data) {
0211         if (DEBUG) debug(node);
0212         return visitChildren(node, object());
0213     }
0214 
0215     /**
0216      * <p>Visits a parsed node of the specified type.</p>
0217      * @param node The node to visit.
0218      * @param data An {@link Object} datum passed to this method.
0219      * @return An {@link Object} datum.
0220      * @since Descripter 1.0
0221      */
0222     @Override
0223     public Object visit(ECMAPropertyAssignment node, Object data) {
0224         if (DEBUG) debug(node);
0225         set(data, node.getChild(0).jjtGetValue(), node.getChild(1).jjtAccept(this, this));
0226         return data;
0227     }
0228 
0229     /**
0230      * <p>Visits a parsed node of the specified type.</p>
0231      * @param node The node to visit.
0232      * @param data An {@link Object} datum passed to this method.
0233      * @return An {@link Object} datum.
0234      * @since Descripter 1.0
0235      */
0236     @Override
0237     public Object visit(ECMAAccess node, Object data) {
0238         if (DEBUG) debug(node);
0239         data = node.getChild(0).jjtAccept(this, data);
0240         for (int i = 1; i < node.jjtGetNumChildren(); i++) {
0241             data = node.getChild(i).jjtAccept(this, data);
0242         }
0243         return data;
0244     }
0245 
0246     /**
0247      * <p>Visits a parsed node of the specified type.</p>
0248      * @param node The node to visit.
0249      * @param data An {@link Object} datum passed to this method.
0250      * @return An {@link Object} datum.
0251      * @since Descripter 1.0
0252      */
0253     @Override
0254     public Object visit(ECMANewOperation node, Object data) {
0255         if (DEBUG) debug(node);
0256         return alloc(
0257                 node.getChild(0).jjtAccept(this, this),
0258                 node.getChild(1).acceptChildren(this, this)
0259         );
0260     }
0261 
0262     /**
0263      * <p>Visits a parsed node of the specified type.</p>
0264      * @param node The node to visit.
0265      * @param data An {@link Object} datum passed to this method.
0266      * @return An {@link Object} datum.
0267      * @since Descripter 1.0
0268      */
0269     @Override
0270     public Object visit(ECMAAllocation node, Object data) {
0271         if (DEBUG) debug(node);
0272         return alloc(
0273                 node.getChild(0).jjtAccept(this, this)
0274         );
0275     }
0276 
0277     /**
0278      * <p>Visits a parsed node of the specified type.</p>
0279      * @param node The node to visit.
0280      * @param data An {@link Object} datum passed to this method.
0281      * @return An {@link Object} datum.
0282      * @since Descripter 1.0
0283      */
0284     @Override
0285     public Object visit(ECMAArrayAccessor node, Object data) {
0286         if (DEBUG) debug(node);
0287         return var(data, node.getChild(0).jjtAccept(this, this).toString());
0288     }
0289 
0290     /**
0291      * <p>Visits a parsed node of the specified type.</p>
0292      * @param node The node to visit.
0293      * @param data An {@link Object} datum passed to this method.
0294      * @return An {@link Object} datum.
0295      * @since Descripter 1.0
0296      */
0297     @Override
0298     public Object visit(ECMAMemberAccessor node, Object data) {
0299         if (DEBUG) debug(node);
0300         return node.getChild(0).jjtAccept(this, data);
0301     }
0302 
0303     /**
0304      * <p>Visits a parsed node of the specified type.</p>
0305      * @param node The node to visit.
0306      * @param data An {@link Object} datum passed to this method.
0307      * @return An {@link Object} datum.
0308      * @since Descripter 1.0
0309      */
0310     @Override
0311     public Object visit(ECMAArguments node, Object data) {
0312         if (DEBUG) debug(node);
0313         return call(data, node.acceptChildren(this, this));
0314     }
0315 
0316     /**
0317      * <p>Visits a parsed node of the specified type.</p>
0318      * @param node The node to visit.
0319      * @param data An {@link Object} datum passed to this method.
0320      * @return An {@link Object} datum.
0321      * @since Descripter 1.0
0322      */
0323     @Override
0324     public Object visit(ECMAPostfixExpression node, Object data) {
0325         if (DEBUG) debug(node);
0326         Var v = (Var)node.getChild(0).jjtAccept(this, this);
0327         switch (node.getChild(1).firstToken.kind) {
0328             case JSParserConstants.INC:
0329                 return v.uninc();
0330             case JSParserConstants.DEC:
0331                 return v.undec();
0332             default:
0333                 throw new RuntimeException();
0334         }
0335     }
0336 
0337     /**
0338      * <p>Visits a parsed node of the specified type.</p>
0339      * @param node The node to visit.
0340      * @param data An {@link Object} datum passed to this method.
0341      * @return An {@link Object} datum.
0342      * @since Descripter 1.0
0343      */
0344     @Override
0345     public Object visit(ECMAOperator node, Object data) {
0346         if (DEBUG) debug(node);
0347         if (data instanceof Object[]) {
0348             Object a = ((Object[])data)[0], b = ((Object[])data)[1];
0349             switch (node.firstToken.kind) {
0350                 case JSParserConstants.LT:
0351                     return lt  (a, b);
0352                 case JSParserConstants.GT:
0353                     return gt  (a, b);
0354                 case JSParserConstants.LTE:
0355                     return lte (a, b);
0356                 case JSParserConstants.GTE:
0357                     return gte (a, b);
0358                 case JSParserConstants.EQ:
0359                     return eq  (a, b);
0360                 case JSParserConstants.NE:
0361                     return !eq (a, b);
0362                 case JSParserConstants.EQS:
0363                     return eqs (a, b);
0364                 case JSParserConstants.NEQS:
0365                     return !eqs(a, b);
0366                 case JSParserConstants.PLUS:
0367                     return add (a, b);
0368                 case JSParserConstants.MINUS:
0369                     return sub (a, b);
0370                 case JSParserConstants.MUL:
0371                     return mul (a, b);
0372                 case JSParserConstants.MOD:
0373                     return mod (a, b);
0374                 case JSParserConstants.DIV:
0375                     return div (a, b);
0376                 case JSParserConstants.SHL:
0377                     return shl (a, b);
0378                 case JSParserConstants.SHR:
0379                     return shr (a, b);
0380                 case JSParserConstants.SHRU:
0381                     return shru(a, b);
0382                 case JSParserConstants.AND:
0383                     return and (a, b);
0384                 case JSParserConstants.OR:
0385                     return or  (a, b);
0386                 case JSParserConstants.XOR:
0387                     return xor (a, b);
0388                 case JSParserConstants.BAND:
0389                     return band(a, b);
0390                 case JSParserConstants.BOR:
0391                     return bor (a, b);
0392                 case JSParserConstants.ASSIGN:
0393                     return ((Var)b).assign(a);
0394                 case JSParserConstants.AADD:
0395                     return ((Var)b).aadd(a);
0396                 case JSParserConstants.ASUB:
0397                     return ((Var)b).asub(a);
0398                 case JSParserConstants.AMUL:
0399                     return ((Var)b).amul(a);
0400                 case JSParserConstants.ADIV:
0401                     return ((Var)b).adiv(a);
0402                 case JSParserConstants.ASHL:
0403                     return ((Var)b).ashl(a);
0404                 case JSParserConstants.ASHR:
0405                     return ((Var)b).ashr(a);
0406                 case JSParserConstants.ASHRU:
0407                     return ((Var)b).ashru(a);
0408                 case JSParserConstants.AAND:
0409                     return ((Var)b).aand(a);
0410                 case JSParserConstants.AOR:
0411                     return ((Var)b).aor(a);
0412                 case JSParserConstants.AXOR:
0413                     return ((Var)b).axor(a);
0414                 case JSParserConstants.INSTANCEOF:
0415                     return instanceOf(b, a);
0416                 default:
0417                     return null;
0418             }
0419         } else {
0420             switch (node.firstToken.kind) {
0421                 case JSParserConstants.DELETE:
0422                     return ((Var)data).delete();
0423                 case JSParserConstants.VOID:
0424                     return null;
0425                 case JSParserConstants.TYPEOF:
0426                     return typeof(data);
0427                 case JSParserConstants.INC:
0428                     return ((Var)data).inc();
0429                 case JSParserConstants.DEC:
0430                     return ((Var)data).dec();
0431                 case JSParserConstants.PLUS:
0432                     return data;
0433                 case JSParserConstants.MINUS:
0434                     return neg(data);
0435                 case JSParserConstants.NOT:
0436                     return not(data);
0437                 case JSParserConstants.BNOT:
0438                     return bnot(data);
0439                 default:
0440                     return null;
0441             }
0442         }
0443     }
0444 
0445     /**
0446      * <p>Visits a parsed node of the specified type.</p>
0447      * @param node The node to visit.
0448      * @param data An {@link Object} datum passed to this method.
0449      * @return An {@link Object} datum.
0450      * @since Descripter 1.0
0451      */
0452     @Override
0453     public Object visit(ECMAUnaryExpression node, Object data) {
0454         if (DEBUG) debug(node);
0455         return node.getChild(0).jjtAccept(this, node.getChild(1).jjtAccept(this, this));
0456     }
0457 
0458     /**
0459      * <p>Visits a parsed node of the specified type.</p>
0460      * @param node The node to visit.
0461      * @param data An {@link Object} datum passed to this method.
0462      * @return An {@link Object} datum.
0463      * @since Descripter 1.0
0464      */
0465     @Override
0466     public Object visit(ECMABinaryOperation node, Object data) {
0467         if (DEBUG) debug(node);
0468         Object o = node.getChild(0).jjtAccept(this, this);
0469         for (int i = 1, n = node.jjtGetNumChildren(); i < n; i += 2) {
0470             o = node.getChild(i).jjtAccept(
0471                     this, new Object[]{o, node.getChild( i + 1).jjtAccept(this, this)}
0472             );
0473         }
0474         return o;
0475     }
0476 
0477     /**
0478      * <p>Visits a parsed node of the specified type.</p>
0479      * @param node The node to visit.
0480      * @param data An {@link Object} datum passed to this method.
0481      * @return An {@link Object} datum.
0482      * @since Descripter 1.0
0483      */
0484     @Override
0485     public Object visit(ECMAAndOperation node, Object data) {
0486         if (DEBUG) debug(node);
0487         Object o = node.getChild(0).jjtAccept(this, this);
0488         for (int i = 1, n = node.jjtGetNumChildren(); i < n; i += 2) {
0489             if (bool(o)) {
0490                 o = node.getChild(i).jjtAccept(
0491                         this, new Object[]{o, node.getChild( i + 1).jjtAccept(this, this)}
0492                 );
0493             }
0494         }
0495         return o;
0496     }
0497 
0498     /**
0499      * <p>Visits a parsed node of the specified type.</p>
0500      * @param node The node to visit.
0501      * @param data An {@link Object} datum passed to this method.
0502      * @return An {@link Object} datum.
0503      * @since Descripter 1.0
0504      */
0505     @Override
0506     public Object visit(ECMAOrOperation node, Object data) {
0507         if (DEBUG) debug(node);
0508         Object o = node.getChild(0).jjtAccept(this, this);
0509         for (int i = 1, n = node.jjtGetNumChildren(); i < n; i += 2) {
0510             if (bnot(o)) {
0511                 o = node.getChild(i).jjtAccept(
0512                         this, new Object[]{o, node.getChild( i + 1).jjtAccept(this, this)}
0513                 );
0514             }
0515         }
0516         return o;
0517     }
0518 
0519     /**
0520      * <p>Visits a parsed node of the specified type.</p>
0521      * @param node The node to visit.
0522      * @param data An {@link Object} datum passed to this method.
0523      * @return An {@link Object} datum.
0524      * @since Descripter 1.0
0525      */
0526     @Override
0527     public Object visit(ECMAConditionalExpression node, Object data) {
0528         if (DEBUG) debug(node);
0529         return bool(node.getChild(0).jjtAccept(this, this)) ?
0530                     node.getChild(1).jjtAccept(this, this) :
0531                     node.getChild(2).jjtAccept(this, this);
0532     }
0533 
0534     /**
0535      * <p>Visits a parsed node of the specified type.</p>
0536      * @param node The node to visit.
0537      * @param data An {@link Object} datum passed to this method.
0538      * @return An {@link Object} datum.
0539      * @since Descripter 1.0
0540      */
0541     @Override
0542     public Object visit(ECMAAssignmentExpression node, Object data) {
0543         if (DEBUG) debug(node);
0544         return node.getChild(1).jjtAccept(this, new Object[]{
0545                 node.getChild(2).jjtAccept(this, this),
0546                 node.getChild(0).jjtAccept(this, this)
0547         });
0548     }
0549 
0550     /**
0551      * <p>Visits a parsed node of the specified type.</p>
0552      * @param node The node to visit.
0553      * @param data An {@link Object} datum passed to this method.
0554      * @return An {@link Object} datum.
0555      * @since Descripter 1.0
0556      */
0557     @Override
0558     public Object visit(ECMACommaExpression node, Object data) {
0559         if (DEBUG) debug(node);
0560         return visitChildren(node, data);
0561     }
0562 
0563     /**
0564      * <p>Visits a parsed node of the specified type.</p>
0565      * @param node The node to visit.
0566      * @param data An {@link Object} datum passed to this method.
0567      * @return An {@link Object} datum.
0568      * @since Descripter 1.0
0569      */
0570     @Override
0571     public Object visit(ECMAJavaStatement node, Object data) {
0572         throw new UnsupportedOperationException();
0573     }
0574 
0575     /**
0576      * <p>Visits a parsed node of the specified type.</p>
0577      * @param node The node to visit.
0578      * @param data An {@link Object} datum passed to this method.
0579      * @return An {@link Object} datum.
0580      * @since Descripter 1.0
0581      */
0582     @Override
0583     public Object visit(ECMABlock node, Object data) {
0584         if (DEBUG) debug(node);
0585         Interpreter interp = new Interpreter(this);
0586         return interp.visitChildren(node, interp);
0587     }
0588 
0589     /**
0590      * <p>Visits a parsed node of the specified type.</p>
0591      * @param node The node to visit.
0592      * @param data An {@link Object} datum passed to this method.
0593      * @return An {@link Object} datum.
0594      * @since Descripter 1.0
0595      */
0596     @Override
0597     public Object visit(ECMAStatementList node, Object data) {
0598         if (DEBUG) debug(node);
0599         return visitChildren(node, this);
0600     }
0601 
0602     /**
0603      * <p>Visits a parsed node of the specified type.</p>
0604      * @param node The node to visit.
0605      * @param data An {@link Object} datum passed to this method.
0606      * @return An {@link Object} datum.
0607      * @since Descripter 1.0
0608      */
0609     @Override
0610     public Object visit(ECMAVariableStatement node, Object data) {
0611         if (DEBUG) debug(node);
0612         return node.getChild(0).jjtAccept(this, this);
0613     }
0614 
0615     /**
0616      * <p>Visits a parsed node of the specified type.</p>
0617      * @param node The node to visit.
0618      * @param data An {@link Object} datum passed to this method.
0619      * @return An {@link Object} datum.
0620      * @since Descripter 1.0
0621      */
0622     @Override
0623     public Object visit(ECMAVariableDeclarationList node, Object data) {
0624         if (DEBUG) debug(node);
0625         return visitChildren(node, data);
0626     }
0627 
0628     /**
0629      * <p>Visits a parsed node of the specified type.</p>
0630      * @param node The node to visit.
0631      * @param data An {@link Object} datum passed to this method.
0632      * @return An {@link Object} datum.
0633      * @since Descripter 1.0
0634      */
0635     @Override
0636     public Object visit(ECMAVariableDeclaration node, Object data) {
0637         if (DEBUG) debug(node);
0638         Var v = ((Script<?>)data).my(node.getChild(0).jjtGetValue().toString());
0639         if (node.jjtGetNumChildren() > 1) {
0640             v.assign(node.getChild(1).jjtAccept(this, this));
0641         }
0642         return v;
0643     }
0644 
0645     /**
0646      * <p>Visits a parsed node of the specified type.</p>
0647      * @param node The node to visit.
0648      * @param data An {@link Object} datum passed to this method.
0649      * @return An {@link Object} datum.
0650      * @since Descripter 1.0
0651      */
0652     @Override
0653     public Object visit(ECMAEmptyExpression node, Object data) {
0654         if (DEBUG) debug(node);
0655         return data;
0656     }
0657 
0658     /**
0659      * <p>Visits a parsed node of the specified type.</p>
0660      * @param node The node to visit.
0661      * @param data An {@link Object} datum passed to this method.
0662      * @return An {@link Object} datum.
0663      * @since Descripter 1.0
0664      */
0665     @Override
0666     public Object visit(ECMAExpressionStatement node, Object data) {
0667         if (DEBUG) debug(node);
0668         return node.getChild(0).jjtAccept(this, data);
0669     }
0670 
0671     /**
0672      * <p>Visits a parsed node of the specified type.</p>
0673      * @param node The node to visit.
0674      * @param data An {@link Object} datum passed to this method.
0675      * @return An {@link Object} datum.
0676      * @since Descripter 1.0
0677      */
0678     @Override
0679     public Object visit(ECMAIfStatement node, Object data) {
0680         if (DEBUG) debug(node);
0681         if (bool(node.getChild(0).jjtAccept(this, this))) {
0682             node.getChild(1).jjtAccept(this, this);
0683         } else if (node.jjtGetNumChildren() > 2) {
0684             node.getChild(2).jjtAccept(this, this);
0685         }
0686         return null;
0687     }
0688 
0689     /**
0690      * <p>Visits a parsed node of the specified type.</p>
0691      * @param node The node to visit.
0692      * @param data An {@link Object} datum passed to this method.
0693      * @return An {@link Object} datum.
0694      * @since Descripter 1.0
0695      */
0696     @Override
0697     public Object visit(ECMADoWhileStatement node, Object data) {
0698         if (DEBUG) debug(node);
0699         do {
0700             try {
0701                 node.getChild(0).jjtAccept(this, this);
0702             } catch (Break e) {
0703                 e.tryThrow(null);
0704                 break;
0705             } catch (Continue e) {
0706                 e.tryThrow(null);
0707                 continue;
0708             }
0709         } while (bool(node.getChild(1).jjtAccept(this, this)));
0710         return null;
0711     }
0712 
0713     /**
0714      * <p>Visits a parsed node of the specified type.</p>
0715      * @param node The node to visit.
0716      * @param data An {@link Object} datum passed to this method.
0717      * @return An {@link Object} datum.
0718      * @since Descripter 1.0
0719      */
0720     @Override
0721     public Object visit(ECMAWhileStatement node, Object data) {
0722         if (DEBUG) debug(node);
0723         while (bool(node.getChild(0).jjtAccept(this, this))) {
0724             try {
0725                 node.getChild(1).jjtAccept(this, this);
0726             } catch (Break e) {
0727                 e.tryThrow(null);
0728                 break;
0729             } catch (Continue e) {
0730                 e.tryThrow(null);
0731                 continue;
0732             }
0733         };
0734         return null;
0735     }
0736 
0737     /**
0738      * <p>Visits a parsed node of the specified type.</p>
0739      * @param node The node to visit.
0740      * @param data An {@link Object} datum passed to this method.
0741      * @return An {@link Object} datum.
0742      * @since Descripter 1.0
0743      */
0744     @Override
0745     public Object visit(ECMAForStatement node, Object data) {
0746         if (DEBUG) debug(node);
0747         return visitForStatement(node);
0748     }
0749 
0750     /**
0751      * <p>Visits a parsed node of the specified type.</p>
0752      * @param node The node to visit.
0753      * @return An {@link Object} datum.
0754      * @since Descripter 1.0
0755      */
0756     protected Object visitForStatement(AbstractNode node) {
0757         node.getChild(0).jjtAccept(this, this);
0758         while (bool(node.getChild(1).jjtAccept(this, true))) {
0759             try {
0760                 node.getChild(3).jjtAccept(this, this);
0761                 node.getChild(2).jjtAccept(this, this);
0762             } catch (Break e) {
0763                 e.tryThrow(null);
0764                 break;
0765             } catch (Continue e) {
0766                 e.tryThrow(null);
0767                 continue;
0768             }
0769         }
0770         return null;
0771     }
0772 
0773     /**
0774      * <p>Visits a parsed node of the specified type.</p>
0775      * @param node The node to visit.
0776      * @param data An {@link Object} datum passed to this method.
0777      * @return An {@link Object} datum.
0778      * @since Descripter 1.0
0779      */
0780     @Override
0781     public Object visit(ECMAForVarStatement node, Object data) {
0782         if (DEBUG) debug(node);
0783         return new Interpreter(this).visitForStatement(node);
0784     }
0785 
0786     /**
0787      * <p>Visits a parsed node of the specified type.</p>
0788      * @param node The node to visit.
0789      * @param data An {@link Object} datum passed to this method.
0790      * @return An {@link Object} datum.
0791      * @since Descripter 1.0
0792      */
0793     @Override
0794     public Object visit(ECMAForVarInStatement node, Object data) {
0795         if (DEBUG) debug(node);
0796         return new Interpreter(this).visitForInStatement(node);
0797     }
0798 
0799     /**
0800      * <p>Visits a parsed node of the specified type.</p>
0801      * @param node The node to visit.
0802      * @return An {@link Object} datum.
0803      * @since Descripter 1.0
0804      */
0805     protected Object visitForInStatement(AbstractNode node) {
0806         if (DEBUG) debug(node);
0807         Var var = (Var)node.getChild(0).jjtAccept(this, this);
0808         Objective<?> base = object(node.getChild(1).jjtAccept(this, this));
0809         if (base != null) {
0810             Set<Key> keys = base.keys();
0811             for (Key k : keys) {
0812                 var.assign(k);
0813                 try {
0814                     node.getChild(2).jjtAccept(this, this);
0815                 } catch (Break e) {
0816                     e.tryThrow(null);
0817                     break;
0818                 } catch (Continue e) {
0819                     e.tryThrow(null);
0820                     continue;
0821                 }
0822             }
0823         }
0824         return null;
0825     }
0826 
0827     /**
0828      * <p>Visits a parsed node of the specified type.</p>
0829      * @param node The node to visit.
0830      * @param data An {@link Object} datum passed to this method.
0831      * @return An {@link Object} datum.
0832      * @since Descripter 1.0
0833      */
0834     @Override
0835     public Object visit(ECMAForInStatement node, Object data) {
0836         if (DEBUG) debug(node);
0837         return visitForInStatement(node);
0838     }
0839 
0840     /**
0841      * <p>Visits a parsed node of the specified type.</p>
0842      * @param node The node to visit.
0843      * @param data An {@link Object} datum passed to this method.
0844      * @return An {@link Object} datum.
0845      * @since Descripter 1.0
0846      */
0847     @Override
0848     public Object visit(ECMAContinueStatement node, Object data) {
0849         if (DEBUG) debug(node);
0850         throw node.jjtGetNumChildren() < 1 ? new Continue() :
0851             new Continue(node.getChild(0).jjtGetValue());
0852     }
0853 
0854     /**
0855      * <p>Visits a parsed node of the specified type.</p>
0856      * @param node The node to visit.
0857      * @param data An {@link Object} datum passed to this method.
0858      * @return An {@link Object} datum.
0859      * @since Descripter 1.0
0860      */
0861     @Override
0862     public Object visit(ECMABreakStatement node, Object data) {
0863         if (DEBUG) debug(node);
0864         throw node.jjtGetNumChildren() < 1 ? new Break() :
0865                 new Break(node.getChild(0).jjtGetValue());
0866     }
0867 
0868     /**
0869      * <p>Visits a parsed node of the specified type.</p>
0870      * @param node The node to visit.
0871      * @param data An {@link Object} datum passed to this method.
0872      * @return An {@link Object} datum.
0873      * @since Descripter 1.0
0874      */
0875     @Override
0876     public Object visit(ECMAReturnStatement node, Object data) {
0877         if (DEBUG) debug(node);
0878         throw new Return(node.jjtGetNumChildren() < 1 ? null :
0879             node.getChild(0).jjtAccept(this, data));
0880     }
0881 
0882     /**
0883      * <p>Visits a parsed node of the specified type.</p>
0884      * @param node The node to visit.
0885      * @param data An {@link Object} datum passed to this method.
0886      * @return An {@link Object} datum.
0887      * @since Descripter 1.0
0888      */
0889     @Override
0890     public Object visit(final ECMAWithStatement node, Object data) {
0891         if (DEBUG) debug(node);
0892         new With<Interpreter>(this, node.getChild(0).jjtAccept(this, this)) {
0893             @Override
0894             public void run() {
0895                 Interpreter interp = new Interpreter(this);
0896                 node.getChild(1).jjtAccept(interp, interp);
0897             }
0898             
0899         }.run();
0900         return null;
0901     }
0902 
0903     /**
0904      * <p>Visits a parsed node of the specified type.</p>
0905      * @param node The node to visit.
0906      * @param data An {@link Object} datum passed to this method.
0907      * @return An {@link Object} datum.
0908      * @since Descripter 1.0
0909      */
0910     @Override
0911     public Object visit(ECMASwitchStatement node, Object data) {
0912         if (DEBUG) debug(node);
0913         try {
0914             return node.getChild(1).jjtAccept(this, new Object[]{
0915                     node.getChild(0).jjtAccept(this, this), false
0916                 });
0917         } catch (Break e) {
0918             return null;
0919         }
0920     }
0921 
0922     /**
0923      * <p>Visits a parsed node of the specified type.</p>
0924      * @param node The node to visit.
0925      * @param data An {@link Object} datum passed to this method.
0926      * @return An {@link Object} datum.
0927      * @since Descripter 1.0
0928      */
0929     @Override
0930     public Object visit(ECMACaseBlock node, Object data) {
0931         if (DEBUG) debug(node);
0932         return visitChildren(node, data);
0933     }
0934 
0935     /**
0936      * <p>Visits a parsed node of the specified type.</p>
0937      * @param node The node to visit.
0938      * @param data An {@link Object} datum passed to this method.
0939      * @return An {@link Object} datum.
0940      * @since Descripter 1.0
0941      */
0942     @Override
0943     public Object visit(ECMACaseClause node, Object data) {
0944         if (DEBUG) debug(node);
0945         if (bnot(((Object[])data)[1])) {
0946             node.getChild(0).jjtAccept(this, data);
0947         }
0948         if (bool(((Object[])data)[1])) {
0949             return node.getChild(1).jjtAccept(this, this);
0950         }
0951         return null;
0952     }
0953 
0954     /**
0955      * <p>Visits a parsed node of the specified type.</p>
0956      * @param node The node to visit.
0957      * @param data An {@link Object} datum passed to this method.
0958      * @return An {@link Object} datum.
0959      * @since Descripter 1.0
0960      */
0961     @Override
0962     public Object visit(ECMACase node, Object data) {
0963         if (DEBUG) debug(node);
0964         if (node.jjtGetNumChildren() > 0) {
0965             ((Object[])data)[1] = eqs(
0966                     ((Object[])data)[0],
0967                     node.getChild(0).jjtAccept(this, this)
0968             );
0969         } else {
0970             ((Object[])data)[1] = true;
0971         }
0972         return null;
0973     }
0974 
0975     /**
0976      * <p>Visits a parsed node of the specified type.</p>
0977      * @param node The node to visit.
0978      * @param data An {@link Object} datum passed to this method.
0979      * @return An {@link Object} datum.
0980      * @since Descripter 1.0
0981      */
0982     @Override
0983     public Object visit(ECMALabelledStatement node, Object data) {
0984         if (DEBUG) debug(node);
0985         Object label = node.getChild(0).jjtGetValue();
0986         while (true) {
0987             try {
0988                 node.getChild(1).jjtAccept(this, this);
0989             } catch (Break e) {
0990                 e.tryThrow(label);
0991                 return null;
0992             } catch (Continue e) {
0993                 e.tryThrow(label);
0994                 continue;
0995             }
0996         }
0997     }
0998 
0999     /**
1000      * <p>Visits a parsed node of the specified type.</p>
1001      * @param node The node to visit.
1002      * @param data An {@link Object} datum passed to this method.
1003      * @return An {@link Object} datum.
1004      * @since Descripter 1.0
1005      */
1006     @Override
1007     public Object visit(ECMAThrowStatement node, Object data) {
1008         if (DEBUG) debug(node);
1009         throw new Thrown(node.getChild(0).jjtAccept(this, this));
1010     }
1011 
1012     /**
1013      * <p>Visits a parsed node of the specified type.</p>
1014      * @param node The node to visit.
1015      * @param data An {@link Object} datum passed to this method.
1016      * @return An {@link Object} datum.
1017      * @since Descripter 1.0
1018      */
1019     @Override
1020     public Object visit(ECMATryStatement node, Object data) {
1021         if (DEBUG) debug(node);
1022         boolean catched = false;
1023         int last = node.jjtGetNumChildren() - 1;
1024         try {
1025             return node.getChild(0).jjtAccept(this, this);
1026         } catch (Thrown e) {
1027             if (last > 1) {
1028                 node.getChild(last - 1).jjtAccept(this, e);
1029                 node.getChild(last).jjtAccept(this, this);
1030             } else {
1031                 node.getChild(last).jjtAccept(this, e);
1032             }
1033             catched = true;
1034         } catch (Abrupt e) {
1035             catched = true;
1036             throw e;
1037         } finally {
1038             if (!catched) {
1039                 node.getChild(last).jjtAccept(this, this);
1040             }
1041         }
1042         return null;
1043     }
1044 
1045     /**
1046      * <p>Visits a parsed node of the specified type.</p>
1047      * @param node The node to visit.
1048      * @param data An {@link Object} datum passed to this method.
1049      * @return An {@link Object} datum.
1050      * @since Descripter 1.0
1051      */
1052     @Override
1053     public Object visit(ECMACatch node, Object data) {
1054         if (DEBUG) debug(node);
1055         Interpreter interp = new Interpreter(this);
1056         interp.var(node.getChild(0).jjtGetValue()).assign(data);
1057         return node.getChild(1).jjtAccept(interp, interp);
1058     }
1059 
1060     /**
1061      * <p>Visits a parsed node of the specified type.</p>
1062      * @param node The node to visit.
1063      * @param data An {@link Object} datum passed to this method.
1064      * @return An {@link Object} datum.
1065      * @since Descripter 1.0
1066      */
1067     @Override
1068     public Object visit(ECMAFinally node, Object data) {
1069         if (DEBUG) debug(node);
1070         Object o = node.getChild(0).jjtAccept(this, this);
1071         if (data instanceof Thrown) {
1072             throw (Thrown)data;
1073         }
1074         return o;
1075     }
1076 
1077     /**
1078      * <p>Visits a parsed node of the specified type.</p>
1079      * @param node The node to visit.
1080      * @param data An {@link Object} datum passed to this method.
1081      * @return An {@link Object} datum.
1082      * @since Descripter 1.0
1083      */
1084     @Override
1085     public Object visit(ECMADebuggerStatement node, Object data) {
1086         return null;
1087     }
1088 
1089     /**
1090      * <p>Visits a parsed node of the specified type.</p>
1091      * @param node The node to visit.
1092      * @param data An {@link Object} datum passed to this method.
1093      * @return An {@link Object} datum.
1094      * @since Descripter 1.0
1095      */
1096     @Override
1097     public Object visit(final ECMAFunctionDeclaration node, Object data) {
1098         if (DEBUG) debug(node);
1099         return visitFunction(node, data);
1100     }
1101 
1102     /**
1103      * <p>Visits a parsed node of the specified type.</p>
1104      * @param node The node to visit.
1105      * @param data An {@link Object} datum passed to this method.
1106      * @return An {@link Object} datum.
1107      * @since Descripter 1.0
1108      */
1109     protected Object visitFunction(final AbstractNode node, Object data) {
1110         Function<?> f = new Function<Interpreter>(this) {
1111             @Override
1112             protected Functor<Interpreter> functor() {
1113                 return new Functor<Interpreter>(this) {
1114                     @Override
1115                     public Object function() {
1116                         Interpreter interp = new Interpreter(this);
1117                         int n = node.jjtGetNumChildren();
1118                         node.getChild(n - 2).jjtAccept(interp, this);
1119                         try {
1120                             return interp.evalChildren(node.getChild(n - 1), this);
1121                         } catch (Return e) {
1122                             return e.value;
1123                         } catch (Break e) {
1124                             if (e.value != null) {
1125                                 throw new RuntimeException(e);
1126                             }
1127                             return null;
1128                         } catch (Abrupt e) {
1129                             throw new RuntimeException(e);
1130                         }
1131                     }
1132                 };
1133             }
1134         };
1135         if (node.jjtGetNumChildren() > 2) {
1136             var(node.getChild(0).jjtGetValue()).assign(f);
1137         }
1138         return f;
1139     }
1140 
1141     /**
1142      * <p>Visits a parsed node of the specified type.</p>
1143      * @param node The node to visit.
1144      * @param data An {@link Object} datum passed to this method.
1145      * @return An {@link Object} datum.
1146      * @since Descripter 1.0
1147      */
1148     @Override
1149     public Object visit(final ECMAFunctionExpression node, Object data) {
1150         if (DEBUG) debug(node);
1151         return visitFunction(node, data);
1152     }
1153 
1154     /**
1155      * <p>Visits a parsed node of the specified type.</p>
1156      * @param node The node to visit.
1157      * @param data An {@link Object} datum passed to this method.
1158      * @return An {@link Object} datum.
1159      * @since Descripter 1.0
1160      */
1161     @Override
1162     public Object visit(ECMAFormalParameterList node, Object data) {
1163         if (DEBUG) debug(node);
1164         int n = node.jjtGetNumChildren();
1165         Functor<?> f = (Functor<?>)data;
1166         for (int i = 0; i < n; i++) {
1167             f.my(node.getChild(i).jjtGetValue().toString()).assign(f.arguments().get(i));           
1168         }
1169         return f;
1170     }
1171 
1172     /**
1173      * <p>Visits a parsed node of the specified type.</p>
1174      * @param node The node to visit.
1175      * @param data An {@link Object} datum passed to this method.
1176      * @return An {@link Object} datum.
1177      * @since Descripter 1.0
1178      */
1179     @Override
1180     public Object visit(ECMAProgram node, Object data) {
1181         if (DEBUG) debug(node);
1182         return evalChildren(node, data);
1183     }
1184 }