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