| JavaDoq: Interpreter.java |
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 }
| JavaDoq: Interpreter.java |