Source Code Cross Referenced for JavascriptGenerator.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » sc » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » Laszlo 4.0.10 » org.openlaszlo.sc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- mode: Java; c-basic-offset: 2; -*- */
0002:
0003:        /**
0004:         * Javascript Generation
0005:         *
0006:         * @author steele@osteele.com
0007:         * @author ptw@openlaszlo.org
0008:         * @description: JavaScript -> JavaScript translator
0009:         *
0010:         * Transform the parse tree from ECMA ~4 to ECMA 3.  Includes
0011:         * analyzing constraint functions and generating their dependencies.
0012:         */package org.openlaszlo.sc;
0013:
0014:        import java.io.*;
0015:        import java.util.*;
0016:
0017:        import org.openlaszlo.sc.parser.*;
0018:
0019:        public class JavascriptGenerator extends CommonGenerator implements 
0020:                Translator {
0021:
0022:            protected void setRuntime(String runtiem) {
0023:                assert org.openlaszlo.compiler.Compiler.SCRIPT_RUNTIMES
0024:                        .contains(runtime) : "unknown runtime " + runtime;
0025:            }
0026:
0027:            // Make Javascript globals 'known'
0028:            Set globals = new HashSet(Arrays.asList(new String[] { "NaN",
0029:                    "Infinity", "undefined", "eval", "parseInt", "parseFloat",
0030:                    "isNaN", "isFinite", "decodeURI", "decodeURIComponent",
0031:                    "encodeURI", "encodeURIComponent", "Object", "Function",
0032:                    "Array", "String", "Boolean", "Number", "Date", "RegExp",
0033:                    "Error", "EvalError", "RangeError", "ReferenceError",
0034:                    "SyntaxError", "TypeError", "URIError", "Math" }));
0035:
0036:            public SimpleNode translate(SimpleNode program) {
0037:                // TODO: [2003-04-15 ptw] bind context slot macro
0038:                try {
0039:                    context = new TranslationContext(ASTProgram.class, context);
0040:                    context.setProperty(TranslationContext.VARIABLES, globals);
0041:                    return translateInternal(program, "b", true);
0042:                } finally {
0043:                    context = context.parent;
0044:                }
0045:            }
0046:
0047:            public String newLabel(SimpleNode node) {
0048:                throw new CompilerImplementationError("nyi: newLabel");
0049:            }
0050:
0051:            int tempNum = 0;
0052:
0053:            String newTemp() {
0054:                return newTemp("$lzsc$");
0055:            }
0056:
0057:            String newTemp(String prefix) {
0058:                return prefix + tempNum++;
0059:            }
0060:
0061:            static LessHalfAssedHashMap XfixInstrs = new LessHalfAssedHashMap();
0062:            static {
0063:                XfixInstrs.put(ParserConstants.INCR, "+");
0064:                XfixInstrs.put(ParserConstants.DECR, "-");
0065:            };
0066:
0067:            static LessHalfAssedHashMap AssignOpTable = new LessHalfAssedHashMap();
0068:            static {
0069:                AssignOpTable.put(ParserConstants.PLUSASSIGN, "+");
0070:                AssignOpTable.put(ParserConstants.MINUSASSIGN, "-");
0071:                AssignOpTable.put(ParserConstants.STARASSIGN, "*");
0072:                AssignOpTable.put(ParserConstants.SLASHASSIGN, "/");
0073:                AssignOpTable.put(ParserConstants.ANDASSIGN, "&");
0074:                AssignOpTable.put(ParserConstants.ORASSIGN, "|");
0075:                AssignOpTable.put(ParserConstants.XORASSIGN, "^");
0076:                AssignOpTable.put(ParserConstants.REMASSIGN, "%");
0077:                AssignOpTable.put(ParserConstants.LSHIFTASSIGN, "<<");
0078:                AssignOpTable.put(ParserConstants.RSIGNEDSHIFTASSIGN, ">>");
0079:                AssignOpTable.put(ParserConstants.RUNSIGNEDSHIFTASSIGN, ">>>");
0080:            };
0081:
0082:            // Code to meter a function call.  If name is set, uses that,
0083:            // otherwise uses arguments.callee._dbg_name.  This code must be appended
0084:            // to the function prefix or suffix, as appropriate.
0085:            //
0086:            // NOTE: [2006-06-24 ptw] This is an inline version of the LFC
0087:            // `LzProfile.event` method and must be kept in sync with that.
0088:            SimpleNode meterFunctionEvent(SimpleNode node, String event,
0089:                    String name) {
0090:                String getname;
0091:                if (name != null) {
0092:                    getname = "'" + name + "'";
0093:                } else {
0094:                    getname = "arguments.callee._dbg_name";
0095:                }
0096:
0097:                // Note _root.$lzprofiler can be undedefined to disable profiling
0098:                // at run time.
0099:
0100:                // N.B., According to the Javascript spec, getTime() returns
0101:                // the time in milliseconds, but we have observed that the
0102:                // Flash player on some platforms tries to be accurate to
0103:                // microseconds (by including fractional milliseconds).  On
0104:                // other platforms, the time is not even accurate to
0105:                // milliseconds, hence the kludge to manually increment the
0106:                // clock to create a monotonic ordering.
0107:
0108:                // The choice of 0.01 to increment by is based on the
0109:                // observation that when floats are used as member names in an
0110:                // object they are coerced to strings with only 15 significant
0111:                // digits.  This should suffice for the next (10^13)-1
0112:                // microseconds (about 300 years).
0113:
0114:                return parseFragment("var $lzsc$lzp = global['$lzprofiler'];"
0115:                        + "if ($lzsc$lzp) {"
0116:                        + "  var $lzsc$tick = $lzsc$lzp.tick;"
0117:                        + "  var $lzsc$now = (new Date).getTime();"
0118:                        + "  if ($lzsc$tick >= $lzsc$now) {"
0119:                        + "    $lzsc$now = $lzsc$tick + 0.0078125;" + "  }"
0120:                        + "  $lzsc$lzp.tick = $lzsc$now;" + "  $lzsc$lzp."
0121:                        + event + "[$lzsc$now] = " + getname + ";" + "}");
0122:            }
0123:
0124:            // Only used by warning generator, hence not metered.
0125:            // FIXME: [2006-01-17 ptw] Regression compatibility Object -> String
0126:            String report(String reportMethod, SimpleNode node, Object message) {
0127:                return reportMethod + "(" + message + "," + node.filename + ","
0128:                        + node.beginLine + ")";
0129:            }
0130:
0131:            // Only used by warning generator, hence not metered.
0132:            // FIXME: [2006-01-17 ptw] Regression compatibility Object -> String
0133:            String report(String reportMethod, SimpleNode node, Object message,
0134:                    String extraArg) {
0135:                return reportMethod + "(" + message + "," + node.filename + ","
0136:                        + node.beginLine + "," + extraArg + ")";
0137:            }
0138:
0139:            // Emits code to check that a function is defined.  If reference is
0140:            // set, expects the function reference to be at the top of the stack
0141:            // when called, otherwise expects the function object.
0142:            // TODO: [2006-01-04 ptw] Rewrite as a source transform
0143:            SimpleNode checkUndefinedFunction(SimpleNode node,
0144:                    JavascriptReference reference) {
0145:                if (options.getBoolean(Compiler.DEBUG)
0146:                        && options
0147:                                .getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)
0148:                        && node.filename != null) {
0149:                    return parseFragment("typeof "
0150:                            + reference.get()
0151:                            + " != 'function' ? "
0152:                            + report("$reportNotFunction", node, reference
0153:                                    .get()) + " : " + reference.get());
0154:                }
0155:                return null;
0156:            }
0157:
0158:            // Emits code to check that an object method is defined.  Does a trial
0159:            // fetch of methodName to verify that it is a function.
0160:            SimpleNode checkUndefinedMethod(SimpleNode node,
0161:                    JavascriptReference reference, String methodName) {
0162:                if (options.getBoolean(Compiler.DEBUG)
0163:                        && options
0164:                                .getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)
0165:                        && node.filename != null) {
0166:                    String o = newTemp();
0167:                    String om = newTemp();
0168:                    return parseFragment("var "
0169:                            + o
0170:                            + " = "
0171:                            + reference.get()
0172:                            + ";"
0173:                            + "if (typeof("
0174:                            + o
0175:                            + ") == undefined) {"
0176:                            + "  "
0177:                            + report("$reportUndefinedObjectProperty", node,
0178:                                    methodName)
0179:                            + "}"
0180:                            + "var "
0181:                            + om
0182:                            + " = "
0183:                            + o
0184:                            + "["
0185:                            + methodName
0186:                            + "];"
0187:                            + "if (typeof("
0188:                            + om
0189:                            + ") != 'function') {"
0190:                            + "  "
0191:                            + report("$reportUndefinedMethod", node,
0192:                                    methodName, om) + "}");
0193:                }
0194:                return null;
0195:            }
0196:
0197:            SimpleNode translateInternal(SimpleNode program, String cpass,
0198:                    boolean top) {
0199:                assert program instanceof  ASTProgram;
0200:                // TODO: [2003-04-15 ptw] bind context slot macro
0201:                try {
0202:                    context = new TranslationContext(ASTProgram.class, context);
0203:                    return visitProgram(program, program.getChildren(), cpass,
0204:                            top);
0205:                } finally {
0206:                    context = context.parent;
0207:                }
0208:            }
0209:
0210:            void showStats(SimpleNode node) {
0211:                // No implementation to collect stats for Javascript
0212:            }
0213:
0214:            public SimpleNode visitProgram(SimpleNode node,
0215:                    SimpleNode[] directives, String cpass) {
0216:                return visitProgram(node, directives, cpass, false);
0217:            }
0218:
0219:            public SimpleNode visitProgram(SimpleNode node,
0220:                    SimpleNode[] directives, String cpass, boolean top) {
0221:                // cpass is "b"oth, 1, or 2
0222:                assert "b".equals(cpass) || "1".equals(cpass)
0223:                        || "2".equals(cpass) : "bad pass: " + cpass;
0224:                if ("b".equals(cpass)) {
0225:                    node = visitProgram(node, directives, "1", top);
0226:                    // Everything is done in one pass for now.
0227:                    //       directives = node.getChildren();
0228:                    //       node = visitProgram(node, directives, "2", top);
0229:                    return node;
0230:                }
0231:                if ("1".equals(cpass) && top) {
0232:                    // emit compile-time contants to runtime
0233:                    Map constants = (Map) options
0234:                            .get(Compiler.COMPILE_TIME_CONSTANTS);
0235:                    if (constants != null) {
0236:                        String code = "";
0237:                        for (Iterator i = constants.entrySet().iterator(); i
0238:                                .hasNext();) {
0239:                            Map.Entry entry = (Map.Entry) i.next();
0240:                            Object value = entry.getValue();
0241:                            // Python cruft
0242:                            if (value instanceof  String) {
0243:                                value = "\"" + value + "\"";
0244:                            } else if ((new Integer(0)).equals(value)) {
0245:                                value = "false";
0246:                            } else if ((new Integer(1)).equals(value)) {
0247:                                value = "true";
0248:                            }
0249:                            code += "var " + entry.getKey() + " = " + value
0250:                                    + ";";
0251:                        }
0252:                        List c = new ArrayList();
0253:                        c.add(parseFragment(code));
0254:                        c.addAll(Arrays.asList(directives));
0255:                        directives = (SimpleNode[]) c.toArray(directives);
0256:                        node.setChildren(directives);
0257:                    }
0258:                }
0259:                //     System.err.println("visitProgram: " + cpass);
0260:                for (int index = 0, len = directives.length; index < len; index++) {
0261:                    SimpleNode directive = directives[index];
0262:                    SimpleNode newDirective = directive;
0263:                    SimpleNode[] children = directive.getChildren();
0264:                    if (directive instanceof  ASTDirectiveBlock) {
0265:                        Compiler.OptionMap savedOptions = options;
0266:                        try {
0267:                            options = options.copy();
0268:                            newDirective = visitProgram(directive, children,
0269:                                    cpass);
0270:                        } finally {
0271:                            options = savedOptions;
0272:                        }
0273:                    } else if (directive instanceof  ASTIfDirective) {
0274:                        if (!options
0275:                                .getBoolean(Compiler.CONDITIONAL_COMPILATION)) {
0276:                            // TBD: different type; change to CONDITIONALS
0277:                            throw new CompilerError("`if` at top level");
0278:                        }
0279:                        Boolean value = evaluateCompileTimeConditional(directive
0280:                                .get(0));
0281:                        if (value == null) {
0282:                            newDirective = visitIfStatement(directive, children);
0283:                        } else if (value.booleanValue()) {
0284:                            SimpleNode clause = directive.get(1);
0285:                            newDirective = visitProgram(clause, clause
0286:                                    .getChildren(), cpass);
0287:                        } else if (directive.size() > 2) {
0288:                            SimpleNode clause = directive.get(2);
0289:                            newDirective = visitProgram(clause, clause
0290:                                    .getChildren(), cpass);
0291:                        } else {
0292:                            newDirective = new ASTEmptyExpression(0);
0293:                        }
0294:                    } else if (directive instanceof  ASTIncludeDirective) {
0295:                        // Disabled by default, since it isn't supported in the
0296:                        // product.  (It doesn't go through the compilation
0297:                        // manager for dependency tracking.)
0298:                        if (!options.getBoolean(Compiler.INCLUDES)) {
0299:                            throw new UnimplementedError(
0300:                                    "unimplemented: #include", directive);
0301:                        }
0302:                        String userfname = (String) ((ASTLiteral) directive
0303:                                .get(0)).getValue();
0304:                        newDirective = translateInclude(userfname, cpass);
0305:                    } else if (directive instanceof  ASTProgram) {
0306:                        // This is what an include looks like in pass 2
0307:                        newDirective = visitProgram(directive, children, cpass);
0308:                    } else if (directive instanceof  ASTPragmaDirective) {
0309:                        newDirective = visitPragmaDirective(directive,
0310:                                directive.getChildren());
0311:                    } else {
0312:                        if ("1".equals(cpass)) {
0313:                            // Function, class, and top-level expressions are processed in pass 1
0314:                            if (directive instanceof  ASTFunctionDeclaration) {
0315:                                newDirective = visitStatement(directive);
0316:                            } else if (directive instanceof  ASTClassDefinition) {
0317:                                newDirective = visitStatement(directive);
0318:                            } else if (directive instanceof  ASTModifiedDefinition) {
0319:                                newDirective = visitModifiedDefinition(
0320:                                        directive, directive.getChildren());
0321:                            } else if (directive instanceof  ASTStatement) {
0322:                                // Statements are processed in pass 1 for now
0323:                                newDirective = visitStatement(directive);
0324:                                ;
0325:                            } else {
0326:                                newDirective = visitExpression(directive, false);
0327:                            }
0328:                        }
0329:                        if ("2".equals(cpass)) {
0330:                            // There is no pass 2 any more
0331:                            assert false : "bad pass " + cpass;
0332:                        }
0333:                    }
0334:                    if (!newDirective.equals(directive)) {
0335:                        //         System.err.println("directive: " + directive + " -> " + newDirective);
0336:                        directives[index] = newDirective;
0337:                    }
0338:                }
0339:                showStats(node);
0340:                return node;
0341:            }
0342:
0343:            SimpleNode translateInclude(String userfname, String cpass) {
0344:
0345:                if (Compiler.CachedInstructions == null) {
0346:                    Compiler.CachedInstructions = new ScriptCompilerCache();
0347:                }
0348:
0349:                File file = includeNameToFile(userfname);
0350:                String source = includeFileToSourceString(file, userfname);
0351:
0352:                try {
0353:                    String optionsKey = getCodeGenerationOptionsKey(Collections
0354:                            .singletonList(
0355:                            // The constant pool isn't cached, so it doesn't affect code
0356:                            // generation so far as the cache is concerned.
0357:                            Compiler.DISABLE_CONSTANT_POOL));
0358:                    // If these could be omitted from the key for files that didn't
0359:                    // reference them, then the cache could be shared between krank
0360:                    // and krank debug.  (The other builds differ either on OBFUSCATE,
0361:                    // RUNTIME, NAMEFUNCTIONS, or PROFILE, so there isn't any other
0362:                    // possible sharing.)
0363:                    String instrsKey = file.getAbsolutePath();
0364:                    // Only cache on file and pass, to keep cache size resonable,
0365:                    // but check against optionsKey
0366:                    String instrsChecksum = "" + file.lastModified()
0367:                            + optionsKey; // source;
0368:                    // Use previously modified parse tree if it exists
0369:                    SimpleNode instrs = (SimpleNode) Compiler.CachedInstructions
0370:                            .get(instrsKey + cpass, instrsChecksum);
0371:                    if (instrs == null) {
0372:                        ParseResult result = parseFile(file, userfname, source);
0373:                        if ("1".equals(cpass)) {
0374:                            instrs = result.parse;
0375:                            instrs = translateInternal(instrs, cpass, false);
0376:                        } else if ("2".equals(cpass)) {
0377:                            instrs = (SimpleNode) Compiler.CachedInstructions
0378:                                    .get(instrsKey + "1", instrsChecksum);
0379:                            assert instrs != null : "pass 2 before pass 1?";
0380:                            instrs = translateInternal(instrs, cpass, false);
0381:                        } else {
0382:                            assert false : "bad pass " + cpass;
0383:                        }
0384:                        if (!result.hasIncludes) {
0385:                            if (options.getBoolean(Compiler.CACHE_COMPILES)) {
0386:                                Compiler.CachedInstructions.put(instrsKey
0387:                                        + cpass, instrsChecksum, instrs);
0388:                            }
0389:                        }
0390:                    }
0391:                    return instrs;
0392:                } catch (ParseException e) {
0393:                    System.err.println("while compiling "
0394:                            + file.getAbsolutePath());
0395:                    throw e;
0396:                }
0397:            }
0398:
0399:            public SimpleNode visitFunctionDeclaration(SimpleNode node,
0400:                    SimpleNode[] ast) {
0401:                // Inner functions are handled by translateFunction
0402:                if (context.findFunctionContext() != null) {
0403:                    return null;
0404:                } else {
0405:                    assert (!options.getBoolean(Compiler.CONSTRAINT_FUNCTION));
0406:                    // Make sure all our top-level functions have root context
0407:                    if (false && ASTProgram.class.equals(context.type)) {
0408:                        Map map = new HashMap();
0409:                        map.put("_1", new Compiler.Splice(ast));
0410:                        SimpleNode newNode = (new Compiler.Parser())
0411:                                .substitute("with (_root) { _1 }", map);
0412:                        return visitStatement(newNode);
0413:                    } else {
0414:                        return translateFunction(node, true, ast);
0415:                    }
0416:                }
0417:            }
0418:
0419:            //
0420:            // Statements
0421:            //
0422:
0423:            public SimpleNode visitVariableStatement(SimpleNode node,
0424:                    SimpleNode[] children) {
0425:                boolean scriptElement = options
0426:                        .getBoolean(Compiler.SCRIPT_ELEMENT);
0427:                if (scriptElement) {
0428:                    assert children.length == 1;
0429:                    // In script, variables are declared at the top of the function
0430:                    // so we convert the variableStatement into a Statement here.
0431:                    node = new ASTStatement(0);
0432:                    node.set(0, children[0]);
0433:                }
0434:                return visitChildren(node);
0435:            }
0436:
0437:            public SimpleNode visitVariableDeclaration(SimpleNode node,
0438:                    SimpleNode[] children) {
0439:                ASTIdentifier id = (ASTIdentifier) children[0];
0440:                boolean scriptElement = options
0441:                        .getBoolean(Compiler.SCRIPT_ELEMENT);
0442:                if (scriptElement) {
0443:                    if (children.length > 1) {
0444:                        // In script, variables are declared at the top of the
0445:                        // function so we convert the declaration into an assignment
0446:                        // here.
0447:                        SimpleNode newNode = new ASTAssignmentExpression(0);
0448:                        newNode.set(0, children[0]);
0449:                        ASTOperator assign = new ASTOperator(0);
0450:                        assign.setOperator(ParserConstants.ASSIGN);
0451:                        newNode.set(1, assign);
0452:                        newNode.set(2, children[1]);
0453:                        return visitExpression(newNode);
0454:                    } else {
0455:                        // Declarations already handled in a script
0456:                        return new ASTEmptyExpression(0);
0457:                    }
0458:                } else {
0459:                    if (children.length > 1) {
0460:                        SimpleNode initValue = children[1];
0461:                        JavascriptReference ref = translateReference(id);
0462:                        children[1] = visitExpression(initValue);
0463:                        children[0] = ref.init();
0464:                        return node;
0465:                    } else {
0466:                        JavascriptReference ref = translateReference(id);
0467:                        children[0] = ref.declare();
0468:                        return node;
0469:                    }
0470:                }
0471:            }
0472:
0473:            public SimpleNode visitIfStatement(SimpleNode node,
0474:                    SimpleNode[] children) {
0475:                SimpleNode test = children[0];
0476:                SimpleNode a = children[1];
0477:                SimpleNode b = (children.length > 2) ? children[2] : null;
0478:                // Compile-time conditional evaluations
0479:                //     System.err.println("visitIfStatement: " +  (new ParseTreePrinter()).visit(node));
0480:                Boolean value = evaluateCompileTimeConditional(test);
0481:                if (value != null) {
0482:                    //       System.err.println("" + test + " == " + value);
0483:                    if (value.booleanValue()) {
0484:                        return visitStatement(a);
0485:                    } else if (b != null) {
0486:                        return visitStatement(b);
0487:                    } else {
0488:                        return new ASTEmptyExpression(0);
0489:                    }
0490:                } else if (b != null) {
0491:                    children[0] = visitExpression(test);
0492:                    children[1] = visitStatement(a);
0493:                    children[2] = visitStatement(b);
0494:                } else {
0495:                    children[0] = visitExpression(test);
0496:                    children[1] = visitStatement(a);
0497:                }
0498:                return node;
0499:            }
0500:
0501:            public SimpleNode visitWhileStatement(SimpleNode node,
0502:                    SimpleNode[] children) {
0503:                SimpleNode test = children[0];
0504:                SimpleNode body = children[1];
0505:                // TODO: [2003-04-15 ptw] bind context slot macro
0506:                try {
0507:                    context = new TranslationContext(ASTWhileStatement.class,
0508:                            context);
0509:                    children[0] = visitExpression(test);
0510:                    children[1] = visitStatement(body);
0511:                    return node;
0512:                } finally {
0513:                    context = context.parent;
0514:                }
0515:            }
0516:
0517:            public SimpleNode visitDoWhileStatement(SimpleNode node,
0518:                    SimpleNode[] children) {
0519:                SimpleNode body = children[0];
0520:                SimpleNode test = children[1];
0521:                // TODO: [2003-04-15 ptw] bind context slot macro
0522:                try {
0523:                    context = new TranslationContext(ASTDoWhileStatement.class,
0524:                            context);
0525:                    children[0] = visitStatement(body);
0526:                    children[1] = visitExpression(test);
0527:                    return node;
0528:                } finally {
0529:                    context = context.parent;
0530:                }
0531:            }
0532:
0533:            public SimpleNode visitForStatement(SimpleNode node,
0534:                    SimpleNode[] children) {
0535:                return translateForStatement(node, children);
0536:            }
0537:
0538:            public SimpleNode visitForVarStatement(SimpleNode node,
0539:                    SimpleNode[] children) {
0540:                return translateForStatement(node, children);
0541:            }
0542:
0543:            SimpleNode translateForStatement(SimpleNode node,
0544:                    SimpleNode[] children) {
0545:                SimpleNode init = children[0];
0546:                SimpleNode test = children[1];
0547:                SimpleNode step = children[2];
0548:                SimpleNode body = children[3];
0549:                // TODO: [2003-04-15 ptw] bind context slot macro
0550:                Compiler.OptionMap savedOptions = options;
0551:                try {
0552:                    options = options.copy();
0553:                    context = new TranslationContext(ASTForStatement.class,
0554:                            context);
0555:                    options.putBoolean(Compiler.WARN_GLOBAL_ASSIGNMENTS, true);
0556:                    children[0] = visitStatement(init);
0557:                    options.putBoolean(Compiler.WARN_GLOBAL_ASSIGNMENTS, false);
0558:                    children[1] = visitExpression(test);
0559:                    children[3] = visitStatement(body);
0560:                    children[2] = visitStatement(step);
0561:                    return node;
0562:                } finally {
0563:                    context = context.parent;
0564:                    options = savedOptions;
0565:                }
0566:            }
0567:
0568:            public SimpleNode visitForInStatement(SimpleNode node,
0569:                    SimpleNode[] children) {
0570:                SimpleNode var = children[0];
0571:                SimpleNode obj = children[1];
0572:                SimpleNode body = children[2];
0573:                // TODO: [2003-04-15 ptw] bind context slot macro
0574:                try {
0575:                    context = new TranslationContext(ASTForInStatement.class,
0576:                            context);
0577:                    children[1] = visitExpression(obj);
0578:                    JavascriptReference ref = translateReference(var);
0579:                    children[0] = ref.set(true);
0580:                    children[2] = visitStatement(body);
0581:                    return node;
0582:                } finally {
0583:                    context = context.parent;
0584:                }
0585:            }
0586:
0587:            // This works because keys are always strings, and enumerate pushes
0588:            // a null before all the keys
0589:            public void unwindEnumeration(SimpleNode node) {
0590:            }
0591:
0592:            SimpleNode translateForInStatement(SimpleNode node, SimpleNode var,
0593:                    Instructions.Instruction varset, SimpleNode obj,
0594:                    SimpleNode body) {
0595:                // TODO: [2003-04-15 ptw] bind context slot macro
0596:                try {
0597:                    SimpleNode[] children = node.getChildren();
0598:                    context = new TranslationContext(ASTForInStatement.class,
0599:                            context);
0600:                    children[2] = visitExpression(obj);
0601:                    JavascriptReference ref = translateReference(var);
0602:                    if (varset == Instructions.VarEquals) {
0603:                        children[0] = ref.init();
0604:                    } else {
0605:                        children[0] = ref.set(true);
0606:                    }
0607:                    children[3] = visitStatement(body);
0608:                    return node;
0609:                } finally {
0610:                    context = context.parent;
0611:                }
0612:            }
0613:
0614:            SimpleNode translateAbruptCompletion(SimpleNode node, String type,
0615:                    ASTIdentifier label) {
0616:                return node;
0617:            }
0618:
0619:            public SimpleNode visitReturnStatement(SimpleNode node,
0620:                    SimpleNode[] children) {
0621:                SimpleNode value = children[0];
0622:                children[0] = visitExpression(value);
0623:                return node;
0624:            }
0625:
0626:            public SimpleNode visitWithStatement(SimpleNode node,
0627:                    SimpleNode[] children) {
0628:                SimpleNode expr = children[0];
0629:                SimpleNode stmt = children[1];
0630:                children[0] = visitExpression(expr);
0631:                children[1] = visitStatement(stmt);
0632:                return node;
0633:            }
0634:
0635:            public SimpleNode visitTryStatement(SimpleNode node,
0636:                    SimpleNode[] children) {
0637:                SimpleNode block = children[0];
0638:                int len = children.length;
0639:                assert len == 2 || len == 3;
0640:                children[0] = visitStatement(block);
0641:                if (len == 2) {
0642:                    // Could be catch or finally clause
0643:                    SimpleNode catfin = children[1];
0644:                    if (catfin instanceof  ASTCatchClause) {
0645:                        // Treat the catch identifier as a binding.  This is not quite
0646:                        // right, need to integrate with variable analyzer, but this is
0647:                        // the one case in ECMAScript where a variable does have block
0648:                        // extent.
0649:                        catfin.set(0, translateReference(catfin.get(0))
0650:                                .declare());
0651:                        catfin.set(1, visitStatement(catfin.get(1)));
0652:                    } else {
0653:                        assert catfin instanceof  ASTFinallyClause;
0654:                        catfin.set(0, visitStatement(catfin.get(0)));
0655:                    }
0656:                } else if (len == 3) {
0657:                    SimpleNode cat = children[1];
0658:                    SimpleNode fin = children[2];
0659:                    assert cat instanceof  ASTCatchClause;
0660:                    // Treat the catch identifier as a binding.  This is not quite
0661:                    // right, need to integrate with variable analyzer, but this is
0662:                    // the one case in ECMAScript where a variable does have block
0663:                    // extent.
0664:                    cat.set(0, translateReference(cat.get(0)).declare());
0665:                    cat.set(1, visitStatement(cat.get(1)));
0666:                    assert fin instanceof  ASTFinallyClause;
0667:                    fin.set(0, visitStatement(fin.get(0)));
0668:                }
0669:                return node;
0670:            }
0671:
0672:            public SimpleNode visitThrowStatement(SimpleNode node,
0673:                    SimpleNode[] children) {
0674:                SimpleNode expr = children[0];
0675:                children[0] = visitExpression(expr);
0676:                return node;
0677:            }
0678:
0679:            public SimpleNode visitSwitchStatement(SimpleNode node,
0680:                    SimpleNode[] children) {
0681:                SimpleNode expr = children[0];
0682:                // TODO: [2003-04-15 ptw] bind context slot macro
0683:                try {
0684:                    context = new TranslationContext(ASTSwitchStatement.class,
0685:                            context);
0686:                    children[0] = visitExpression(expr);
0687:                    for (int i = 1, len = children.length; i < len; i++) {
0688:                        SimpleNode clause = children[i];
0689:                        if (clause instanceof  ASTDefaultClause) {
0690:                            if (clause.size() > 0) {
0691:                                clause.set(0, visitStatement(clause.get(0)));
0692:                            }
0693:                        } else {
0694:                            assert clause instanceof  ASTCaseClause : "case clause expected";
0695:                            clause.set(0, visitExpression(clause.get(0)));
0696:                            if (clause.size() > 1) {
0697:                                clause.set(1, visitStatement(clause.get(1)));
0698:                            }
0699:                        }
0700:                    }
0701:                    return node;
0702:                } finally {
0703:                    context = context.parent;
0704:                }
0705:            }
0706:
0707:            //
0708:            // Expressions
0709:            //
0710:
0711:            boolean isExpressionType(SimpleNode node) {
0712:                if (node instanceof  Compiler.PassThroughNode) {
0713:                    node = ((Compiler.PassThroughNode) node).realNode;
0714:                }
0715:                return super .isExpressionType(node);
0716:            }
0717:
0718:            public SimpleNode visitExpression(SimpleNode node) {
0719:                return visitExpression(node, true);
0720:            }
0721:
0722:            /* This function, unlike the other expression visitors, can be
0723:               applied to any expression node, so it dispatches based on the
0724:               node's class. */
0725:            public SimpleNode visitExpression(SimpleNode node,
0726:                    boolean isReferenced) {
0727:                assert isExpressionType(node) : "" + node + ": "
0728:                        + (new ParseTreePrinter()).visit(node)
0729:                        + " is not an expression";
0730:
0731:                if (this .debugVisit) {
0732:                    System.err.println("visitExpression: " + node.getClass());
0733:                }
0734:
0735:                SimpleNode newNode = dispatchExpression(node, isReferenced);
0736:
0737:                if ((!isReferenced) && (newNode == null)) {
0738:                    newNode = new ASTEmptyExpression(0);
0739:                }
0740:                if (this .debugVisit) {
0741:                    if (!newNode.equals(node)) {
0742:                        System.err.println("expression: " + node + " -> "
0743:                                + newNode);
0744:                    }
0745:                }
0746:                return newNode;
0747:            }
0748:
0749:            public SimpleNode visitIdentifier(SimpleNode node,
0750:                    boolean isReferenced, SimpleNode[] children) {
0751:                // Side-effect free expressions can be suppressed if not referenced
0752:                // Following is disabled by default for regression testing.
0753:                // TODO: [2003-02-17 ows] enable this
0754:                if ((!isReferenced)
0755:                        && options
0756:                                .getBoolean(Compiler.ELIMINATE_DEAD_EXPRESSIONS)) {
0757:                    return null;
0758:                }
0759:                if ("_root".equals(((ASTIdentifier) node).getName())
0760:                        && (!options.getBoolean(Compiler.ALLOW_ROOT))) {
0761:                    throw new SemanticError("Illegal variable name: " + node,
0762:                            node);
0763:                }
0764:                return translateReference(node).get();
0765:            }
0766:
0767:            public SimpleNode visitLiteral(SimpleNode node,
0768:                    boolean isReferenced, SimpleNode[] children) {
0769:                // Side-effect free expressions can be suppressed if not referenced
0770:                // Following is disabled by default for regression testing.
0771:                // TODO: [2003-02-17 ows] enable this
0772:                if ((!isReferenced)
0773:                        && options
0774:                                .getBoolean(Compiler.ELIMINATE_DEAD_EXPRESSIONS)) {
0775:                    return null;
0776:                }
0777:                return translateLiteralNode(node);
0778:            }
0779:
0780:            public SimpleNode visitExpressionList(SimpleNode node,
0781:                    boolean isReferenced, SimpleNode[] children) {
0782:                // all but last expression will not be referenced, so
0783:                // visitExpression will pop it.  If the list is not referenced,
0784:                // then the last will be popped too
0785:                int i = 0, len = children.length - 1;
0786:                for (; i < len; i++) {
0787:                    children[i] = visitExpression(children[i], false);
0788:                }
0789:                children[len] = visitExpression(children[len], isReferenced);
0790:                return node;
0791:            }
0792:
0793:            public SimpleNode visitEmptyExpression(SimpleNode node,
0794:                    boolean isReferenced, SimpleNode[] children) {
0795:                // Side-effect free expressions can be suppressed if not referenced
0796:                if ((!isReferenced)) {
0797:                    return null;
0798:                }
0799:                return node;
0800:            }
0801:
0802:            public SimpleNode visitThisReference(SimpleNode node,
0803:                    boolean isReferenced, SimpleNode[] children) {
0804:                // Side-effect free expressions can be suppressed if not referenced
0805:                if ((!isReferenced)) {
0806:                    return null;
0807:                }
0808:                return translateReference(node).get();
0809:            }
0810:
0811:            public SimpleNode visitArrayLiteral(SimpleNode node,
0812:                    boolean isReferenced, SimpleNode[] children) {
0813:                boolean suppressed = (!isReferenced);
0814:                for (int i = 0, len = children.length; i < len; i++) {
0815:                    children[i] = visitExpression(children[i], isReferenced);
0816:                }
0817:                return node;
0818:            }
0819:
0820:            public SimpleNode visitObjectLiteral(SimpleNode node,
0821:                    boolean isReferenced, SimpleNode[] children) {
0822:                boolean isKey = true;
0823:                for (int i = 0, len = children.length; i < len; i++) {
0824:                    SimpleNode item = children[i];
0825:                    if (isKey && item instanceof  ASTIdentifier) {
0826:                        // Identifiers are a shorthand for a literal string, should
0827:                        // not be evaluated (or remapped).
0828:                        ;
0829:                    } else {
0830:                        children[i] = visitExpression(item);
0831:                    }
0832:                    isKey = (!isKey);
0833:                }
0834:                return node;
0835:            }
0836:
0837:            public SimpleNode visitFunctionExpression(SimpleNode node,
0838:                    boolean isReferenced, SimpleNode[] children) {
0839:                Compiler.OptionMap savedOptions = options;
0840:                try {
0841:                    options = options.copy();
0842:                    options.putBoolean(Compiler.CONSTRAINT_FUNCTION, false);
0843:                    // Make sure all our top-level functions have root context
0844:                    //       if (ASTProgram.class.equals(context.type)) {
0845:                    //         Map map = new HashMap();
0846:                    //         map.put("_1", new Compiler.Splice(children));
0847:                    //         SimpleNode newNode = (new Compiler.Parser()).substitute("with (_root) { _1 }", map);
0848:                    //         visitStatement(newNode);
0849:                    //       } else {
0850:                    return translateFunction(node, false, children);
0851:                    //       }
0852:                } finally {
0853:                    options = savedOptions;
0854:                }
0855:            }
0856:
0857:            public SimpleNode visitFunctionCallParameters(SimpleNode node,
0858:                    boolean isReferenced, SimpleNode[] children) {
0859:                translateFunctionCallParameters(node, isReferenced, children);
0860:                return node;
0861:            }
0862:
0863:            public SimpleNode[] translateFunctionCallParameters(
0864:                    SimpleNode node, boolean isReferenced, SimpleNode[] children) {
0865:                for (int i = 0, len = children.length; i < len; i++) {
0866:                    children[i] = visitExpression(children[i]);
0867:                }
0868:                return children;
0869:            }
0870:
0871:            public SimpleNode visitPropertyIdentifierReference(SimpleNode node,
0872:                    boolean isReferenced, SimpleNode[] children) {
0873:                return translateReference(node).get();
0874:            }
0875:
0876:            public SimpleNode visitPropertyValueReference(SimpleNode node,
0877:                    boolean isReferenced, SimpleNode[] children) {
0878:                return translateReference(node).get();
0879:            }
0880:
0881:            public SimpleNode makeCheckedNode(SimpleNode node) {
0882:                if (options.getBoolean(Compiler.DEBUG)
0883:                        && options
0884:                                .getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
0885:                    String file = "null";
0886:                    String line = "null";
0887:                    if (node.filename != null) {
0888:                        file = ScriptCompiler.quote(node.filename);
0889:                        line = "" + node.beginLine;
0890:                    }
0891:                    Map map = new HashMap();
0892:                    map.put("_1", node);
0893:                    return new Compiler.PassThroughNode((new Compiler.Parser())
0894:                            .substitute("(Debug.evalCarefully(" + file + ", "
0895:                                    + line
0896:                                    + ", function () { return _1; }, this))",
0897:                                    map));
0898:                }
0899:                return node;
0900:            }
0901:
0902:            SimpleNode noteCallSite(SimpleNode node) {
0903:                // Note current call-site in a function context and backtracing
0904:                if ((options.getBoolean(Compiler.DEBUG_BACKTRACE) && (node.beginLine != 0))
0905:                        && (context.findFunctionContext() != null)) {
0906:                    SimpleNode newNode = new ASTExpressionList(0);
0907:                    newNode
0908:                            .set(0, (new Compiler.Parser()).parse(
0909:                                    "$lzsc$a.lineno = " + node.beginLine)
0910:                                    .get(0).get(0));
0911:                    newNode.set(1, new Compiler.PassThroughNode(node));
0912:                    return visitExpression(newNode);
0913:                }
0914:                return node;
0915:            }
0916:
0917:            // Could do inline expansions here, like setAttribute
0918:            public SimpleNode visitCallExpression(SimpleNode node,
0919:                    boolean isReferenced, SimpleNode[] children) {
0920:                SimpleNode fnexpr = children[0];
0921:                SimpleNode[] args = children[1].getChildren();
0922:                int arglen = args.length;
0923:
0924:                // TODO: [2002-12-03 ptw] There should be a more general
0925:                // mechanism for matching patterns against AST's and replacing
0926:                // them.
0927:                // FIXME: [2002-12-03 ptw] This substitution is not correct
0928:                // because it does not verify that the method being inlined is
0929:                // actually LzNode.setAttribute.
0930:                if (
0931:                // Here this means 'compiling the lfc'
0932:                options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY)
0933:                        && (!options.getBoolean("passThrough"))
0934:                        && (fnexpr instanceof  ASTPropertyIdentifierReference)) {
0935:                    SimpleNode[] fnchildren = fnexpr.getChildren();
0936:                    String name = ((ASTIdentifier) fnchildren[1]).getName();
0937:                    // We can't expand this if an expression value is expected,
0938:                    // since we don't have 'let'
0939:                    if (name.equals("setAttribute") && (!isReferenced)) {
0940:                        SimpleNode scope = fnchildren[0];
0941:                        SimpleNode property = args[0];
0942:                        SimpleNode value = args[1];
0943:                        List newBody = new ArrayList();
0944:                        String this var = "$lzsc$" + UUID().toString();
0945:                        String propvar = "$lzsc$" + UUID().toString();
0946:                        String valvar = "$lzsc$" + UUID().toString();
0947:                        String changedvar = "$lzsc$" + UUID().toString();
0948:                        String svar = "$lzsc$" + UUID().toString();
0949:                        String evtvar = "$lzsc$" + UUID().toString();
0950:                        String decls = "";
0951:                        ParseTreePrinter ptp = new ParseTreePrinter();
0952:                        if (scope instanceof  ASTIdentifier
0953:                                || scope instanceof  ASTThisReference) {
0954:                            this var = ptp.visit(scope);
0955:                        } else {
0956:                            decls += "var " + this var + " = "
0957:                                    + ptp.visit(scope) + ";";
0958:                        }
0959:                        if (property instanceof  ASTLiteral
0960:                                || property instanceof  ASTIdentifier) {
0961:                            propvar = ptp.visit(property);
0962:                            if (property instanceof  ASTLiteral) {
0963:                                assert propvar.startsWith("\"")
0964:                                        || propvar.startsWith("'");
0965:                                evtvar = propvar.substring(0, 1) + "on"
0966:                                        + propvar.substring(1);
0967:                            }
0968:                        } else {
0969:                            decls += "var " + propvar + " = "
0970:                                    + ptp.visit(property) + ";";
0971:                        }
0972:                        if (value instanceof  ASTLiteral
0973:                                || value instanceof  ASTIdentifier) {
0974:                            valvar = ptp.visit(value);
0975:                        } else {
0976:                            decls += "var " + valvar + " = " + ptp.visit(value)
0977:                                    + ";";
0978:                        }
0979:                        if (arglen > 2) {
0980:                            SimpleNode ifchanged = args[2];
0981:                            if (ifchanged instanceof  ASTLiteral
0982:                                    || ifchanged instanceof  ASTIdentifier) {
0983:                                changedvar = ptp.visit(ifchanged);
0984:                            } else {
0985:                                decls += "var " + changedvar + " = "
0986:                                        + ptp.visit(ifchanged) + ";";
0987:                            }
0988:                        }
0989:                        newBody.add(parseFragment(decls));
0990:                        String fragment = "if (! ("
0991:                                + this var
0992:                                + ".__LZdeleted "
0993:                                + ((arglen > 2) ? ("|| (" + changedvar
0994:                                        + " && (" + this var + "[" + propvar
0995:                                        + "] == " + valvar + "))") : "")
0996:                                + ")) {"
0997:                                + "var "
0998:                                + svar
0999:                                + " = "
1000:                                + this var
1001:                                + ".setters;"
1002:                                + "if ("
1003:                                + svar
1004:                                + " && ("
1005:                                + propvar
1006:                                + " in "
1007:                                + svar
1008:                                + ")) {"
1009:                                + "    "
1010:                                + this var
1011:                                + "["
1012:                                + svar
1013:                                + "["
1014:                                + propvar
1015:                                + "]]("
1016:                                + valvar
1017:                                + ");"
1018:                                + "} else {"
1019:                                + "    if ($debug) {"
1020:                                + "        if ("
1021:                                + svar
1022:                                + " == null) {"
1023:                                + "            Debug.warn('null setters on', "
1024:                                + this var
1025:                                + ", "
1026:                                + propvar
1027:                                + ", "
1028:                                + valvar
1029:                                + ");"
1030:                                + "        }"
1031:                                + "    }"
1032:                                + "    "
1033:                                + this var
1034:                                + "[ "
1035:                                + propvar
1036:                                + " ] = "
1037:                                + valvar
1038:                                + ";"
1039:                                + ((property instanceof  ASTLiteral) ? ""
1040:                                        : ("    var " + evtvar
1041:                                                + " = (\"on\" + " + propvar + ");"))
1042:                                + "    if (" + evtvar + " in " + this var
1043:                                + ") {" + "        if (" + this var + "["
1044:                                + evtvar + "].ready) {" + this var + "[ "
1045:                                + evtvar + " ].sendEvent( " + valvar + " ); }"
1046:                                + "    }" + "}}";
1047:                        newBody.add(parseFragment(fragment));
1048:                        SimpleNode newStmts = new ASTStatementList(0);
1049:                        newStmts.setChildren((SimpleNode[]) newBody
1050:                                .toArray(new SimpleNode[0]));
1051:                        return visitStatement(newStmts);
1052:                    }
1053:                }
1054:
1055:                children[1].setChildren(translateFunctionCallParameters(node,
1056:                        isReferenced, args));
1057:                children[0] = translateReferenceForCall(fnexpr, true, node);
1058:                //     if (options.getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
1059:                //       return makeCheckedNode(node);
1060:                //     }
1061:                return noteCallSite(node);
1062:            }
1063:
1064:            public SimpleNode visitSuperCallExpression(SimpleNode node,
1065:                    boolean isReferenced, SimpleNode[] children) {
1066:                SimpleNode n = translateSuperCallExpression(node, isReferenced,
1067:                        children);
1068:                return visitExpression(n, isReferenced);
1069:            }
1070:
1071:            public SimpleNode visitNewExpression(SimpleNode node,
1072:                    boolean isReferenced, SimpleNode[] children) {
1073:                for (int i = 0, len = children.length; i < len; i++) {
1074:                    SimpleNode child = children[i];
1075:                    children[i] = visitExpression(child, isReferenced);
1076:                }
1077:                return noteCallSite(node);
1078:            }
1079:
1080:            public SimpleNode visitPrefixExpression(SimpleNode node,
1081:                    boolean isReferenced, SimpleNode[] children) {
1082:                int op = ((ASTOperator) children[0]).getOperator();
1083:                SimpleNode ref = children[1];
1084:                if (translateReference(ref).isChecked()) {
1085:                    // The undefined reference checker needs to have this expanded
1086:                    // to work
1087:                    Map map = new HashMap();
1088:                    map.put("_1", ref);
1089:                    String pattern = "(function () { var $lzsc$tmp = _1; return _1 = $lzsc$tmp "
1090:                            + XfixInstrs.get(op) + " 1; })()";
1091:                    SimpleNode n = (new Compiler.Parser()).substitute(pattern,
1092:                            map);
1093:                    return visitExpression(n);
1094:                }
1095:                children[1] = translateReference(ref, 2).get();
1096:                return node;
1097:            }
1098:
1099:            public SimpleNode visitPostfixExpression(SimpleNode node,
1100:                    boolean isReferenced, SimpleNode[] children) {
1101:                SimpleNode ref = children[0];
1102:                int op = ((ASTOperator) children[1]).getOperator();
1103:                if (translateReference(ref).isChecked()) {
1104:                    // The undefined reference checker needs to have this expanded
1105:                    // to work
1106:                    Map map = new HashMap();
1107:                    map.put("_1", ref);
1108:                    String pattern = "(function () { var $lzsc$tmp = _1; _1 = $lzsc$tmp "
1109:                            + XfixInstrs.get(op) + " 1; return $lzsc$tmp; })()";
1110:                    SimpleNode n = (new Compiler.Parser()).substitute(pattern,
1111:                            map);
1112:                    return visitExpression(n);
1113:                }
1114:                children[0] = translateReference(ref, 2).get();
1115:                return node;
1116:            }
1117:
1118:            public SimpleNode visitUnaryExpression(SimpleNode node,
1119:                    boolean isReferenced, SimpleNode[] children) {
1120:                int op = ((ASTOperator) children[0]).getOperator();
1121:                // I guess the parser doesn't know the difference
1122:                if (ParserConstants.INCR == (op)
1123:                        || ParserConstants.DECR == (op)) {
1124:                    return visitPrefixExpression(node, isReferenced, children);
1125:                }
1126:                SimpleNode arg = children[1];
1127:                // special-case typeof(variable) to not emit undefined-variable
1128:                // checks so there is a warning-free way to check for undefined
1129:                if (ParserConstants.TYPEOF == (op)
1130:                        && (arg instanceof  ASTIdentifier
1131:                                || arg instanceof  ASTPropertyValueReference || arg instanceof  ASTPropertyIdentifierReference)) {
1132:                    children[1] = translateReference(arg).get(false);
1133:                } else {
1134:                    children[1] = visitExpression(arg);
1135:                }
1136:                return node;
1137:            }
1138:
1139:            public SimpleNode visitBinaryExpressionSequence(SimpleNode node,
1140:                    boolean isReferenced, SimpleNode[] children) {
1141:                SimpleNode a = children[0];
1142:                SimpleNode op = children[1];
1143:                SimpleNode b = children[2];
1144:                if (ParserConstants.CAST == ((ASTOperator) op).getOperator()) {
1145:                    // Approximate a cast b as a
1146:                    // TODO: [2008-01-08 ptw] We could typecheck and throw an error
1147:                    // in debug mode
1148:                    return visitExpression(a);
1149:                }
1150:                if (ParserConstants.IS == ((ASTOperator) op).getOperator()) {
1151:                    // Approximate a is b as b['$lzsc$isa'] ? b.$lzsc$isa(a) : (a
1152:                    // instanceof b)
1153:                    Map map = new HashMap();
1154:                    map.put("_1", a);
1155:                    map.put("_2", b);
1156:                    String pattern;
1157:                    if ((a instanceof  ASTIdentifier
1158:                            || a instanceof  ASTPropertyValueReference || a instanceof  ASTPropertyIdentifierReference)
1159:                            && (b instanceof  ASTIdentifier
1160:                                    || b instanceof  ASTPropertyValueReference || b instanceof  ASTPropertyIdentifierReference)) {
1161:                        pattern = "(_2['$lzsc$isa'] ? _2.$lzsc$isa(_1) : (_1 instanceof _2))";
1162:                    } else {
1163:                        pattern = "((function (a, b) {return b['$lzsc$isa'] ? b.$lzsc$isa(a) : (a instanceof b)})(_1, _2))";
1164:                    }
1165:                    SimpleNode n = (new Compiler.Parser()).substitute(pattern,
1166:                            map);
1167:                    return visitExpression(n);
1168:                }
1169:                children[0] = visitExpression(a);
1170:                children[2] = visitExpression(b);
1171:                return node;
1172:            }
1173:
1174:            SimpleNode translateAndOrExpression(SimpleNode node, boolean isand,
1175:                    SimpleNode a, SimpleNode b) {
1176:                SimpleNode[] children = node.getChildren();
1177:                children[0] = visitExpression(a);
1178:                children[1] = visitExpression(b);
1179:                return node;
1180:            }
1181:
1182:            public SimpleNode visitConditionalExpression(SimpleNode node,
1183:                    boolean isReferenced, SimpleNode[] children) {
1184:                SimpleNode test = children[0];
1185:                SimpleNode a = children[1];
1186:                SimpleNode b = children[2];
1187:                children[0] = visitExpression(test);
1188:                children[1] = visitExpression(a);
1189:                children[2] = visitExpression(b);
1190:                return node;
1191:            }
1192:
1193:            public SimpleNode visitAssignmentExpression(SimpleNode node,
1194:                    boolean isReferenced, SimpleNode[] children) {
1195:                JavascriptReference lhs = translateReference(children[0]);
1196:                int op = ((ASTOperator) children[1]).getOperator();
1197:                SimpleNode rhs = visitExpression(children[2]);
1198:                if (op != ParserConstants.ASSIGN && lhs.isChecked()) {
1199:                    // The undefined reference checker needs to have this expanded
1200:                    // to work
1201:                    Map map = new HashMap();
1202:                    map.put("_1", lhs.get());
1203:                    map.put("_2", rhs);
1204:                    map.put("_3", lhs.set());
1205:                    String pattern = "(function () { var $lzsc$tmp = _1; return _3 = $lzsc$tmp "
1206:                            + AssignOpTable.get(op) + " _2; })()";
1207:                    SimpleNode n = (new Compiler.Parser()).substitute(pattern,
1208:                            map);
1209:                    return visitExpression(n);
1210:                }
1211:                children[2] = rhs;
1212:                children[0] = lhs.set();
1213:                return node;
1214:            }
1215:
1216:            // useName => declaration not expression
1217:            SimpleNode translateFunction(SimpleNode node, boolean useName,
1218:                    SimpleNode[] children) {
1219:                // TODO: [2003-04-15 ptw] bind context slot macro
1220:                SimpleNode[] result;
1221:                // methodName and scriptElement
1222:                Compiler.OptionMap savedOptions = options;
1223:                try {
1224:                    options = options.copy();
1225:                    context = new TranslationContext(
1226:                            ASTFunctionExpression.class, context);
1227:                    result = translateFunctionInternal(node, useName, children);
1228:                } finally {
1229:                    options = savedOptions;
1230:                    context = context.parent;
1231:                }
1232:                node = result[0];
1233:                // Dependency function is not compiled in the function context
1234:                if (result[1] != null) {
1235:                    SimpleNode dependencies = result[1];
1236:                    Map map = new HashMap();
1237:                    map.put("_1", node);
1238:                    map.put("_2", translateFunction(dependencies, false,
1239:                            dependencies.getChildren()));
1240:                    SimpleNode newNode = (new Compiler.Parser())
1241:                            .substitute(
1242:                                    "(function () {var $lzsc$f = _1; $lzsc$f.dependencies = _2; return $lzsc$f })();",
1243:                                    map);
1244:                    return newNode;
1245:                }
1246:                return node;
1247:            }
1248:
1249:            static java.util.regex.Pattern identifierPattern = java.util.regex.Pattern
1250:                    .compile("[\\w$_]+");
1251:
1252:            // Internal helper function for above
1253:            // useName => declaration not expression
1254:            SimpleNode[] translateFunctionInternal(SimpleNode node,
1255:                    boolean useName, SimpleNode[] children) {
1256:                // ast can be any of:
1257:                //   FunctionDefinition(name, args, body)
1258:                //   FunctionDeclaration(name, args, body)
1259:                //   FunctionDeclaration(args, body)
1260:                // Handle the two arities:
1261:                String functionName = null;
1262:                SimpleNode params;
1263:                SimpleNode stmts;
1264:                SimpleNode depExpr = null;
1265:                int stmtsIndex;
1266:                ASTIdentifier functionNameIdentifier = null;
1267:                if (children.length == 3) {
1268:                    functionNameIdentifier = (ASTIdentifier) children[0];
1269:                    params = children[1];
1270:                    stmts = children[stmtsIndex = 2];
1271:                    functionName = functionNameIdentifier.getName();
1272:                } else {
1273:                    params = children[0];
1274:                    stmts = children[stmtsIndex = 1];
1275:                }
1276:                // inner functions do not get scriptElement treatment, shadow any
1277:                // outer declaration
1278:                options.putBoolean(Compiler.SCRIPT_ELEMENT, false);
1279:                // or the magic with(this) treatment
1280:                options.putBoolean(Compiler.WITH_THIS, false);
1281:                // function block
1282:                String userFunctionName = null;
1283:                String filename = node.filename != null ? node.filename
1284:                        : "unknown file";
1285:                String lineno = "" + node.beginLine;
1286:                if (functionName != null) {
1287:                    userFunctionName = functionName;
1288:                    if (!useName) {
1289:                        if ((!identifierPattern.matcher(functionName).matches())
1290:                                // Some JS engines die if you name function expressions
1291:                                || options.getBoolean(Compiler.DEBUG_SIMPLE)) {
1292:                            // This is a function-expression that has been annotated
1293:                            // with a non-legal function name, so remove that and put it
1294:                            // in _dbg_name (below)
1295:                            functionName = null;
1296:                            children[0] = new ASTEmptyExpression(0);
1297:                        }
1298:                    }
1299:                } else {
1300:                    userFunctionName = "" + filename + "#" + lineno + "/"
1301:                            + node.beginColumn;
1302:                }
1303:                // Tell metering to look up the name at runtime if it is not a
1304:                // global name (this allows us to name closures more
1305:                // mnemonically at runtime
1306:                String meterFunctionName = useName ? functionName : null;
1307:                Set pnames = new LinkedHashSet();
1308:                SimpleNode[] paramIds = params.getChildren();
1309:                for (int i = 0, len = paramIds.length; i < len; i++) {
1310:                    pnames.add(((ASTIdentifier) paramIds[i]).getName());
1311:                }
1312:                // Pull all the pragmas from the beginning of the
1313:                // statement list: process them, and remove them
1314:                assert stmts instanceof  ASTStatementList;
1315:                List stmtList = new ArrayList(Arrays
1316:                        .asList(stmts.getChildren()));
1317:                for (int i = 0, len = stmtList.size(); i < len; i++) {
1318:                    SimpleNode stmt = (SimpleNode) stmtList.get(i);
1319:                    if (stmt instanceof  ASTPragmaDirective) {
1320:                        SimpleNode newNode = visitStatement(stmt);
1321:                        if (!newNode.equals(stmt)) {
1322:                            stmtList.set(i, newNode);
1323:                        }
1324:                    } else {
1325:                        break;
1326:                    }
1327:                }
1328:                String methodName = (String) options.get(Compiler.METHOD_NAME);
1329:                // Backwards compatibility with tag compiler
1330:                if (methodName != null && functionNameIdentifier != null) {
1331:                    functionNameIdentifier.setName(functionName = methodName);
1332:                }
1333:                if (options.getBoolean(Compiler.CONSTRAINT_FUNCTION)) {
1334:                    //       assert (functionName != null);
1335:                    if (ReferenceCollector.DebugConstraints) {
1336:                        System.err.println("stmts: " + stmts);
1337:                    }
1338:                    // Find dependencies.
1339:                    //
1340:                    // Compute this before any transformations on the function body.
1341:                    //
1342:                    // The job of a constraint function is to compute a value.
1343:                    // The current implementation inlines the call to set the
1344:                    // attribute that the constraint is attached to, within the
1345:                    // constraint function it  Walking the statements of
1346:                    // the function will process the expression that computes
1347:                    // the value; it will also process the call to
1348:                    // setAttribute, but ReferenceCollector knows to ignore
1349:                    //
1350:                    ReferenceCollector dependencies = new ReferenceCollector(
1351:                            options.getBoolean(Compiler.COMPUTE_METAREFERENCES));
1352:                    // Only visit original body
1353:                    for (Iterator i = stmtList.iterator(); i.hasNext();) {
1354:                        SimpleNode stmt = (SimpleNode) i.next();
1355:                        dependencies.visit(stmt);
1356:                    }
1357:                    depExpr = dependencies.computeReferences(userFunctionName);
1358:                    if (options.getBoolean(Compiler.PRINT_CONSTRAINTS)) {
1359:                        (new ParseTreePrinter()).print(depExpr);
1360:                    }
1361:                }
1362:                List prefix = new ArrayList();
1363:                List error = new ArrayList();
1364:                List suffix = new ArrayList();
1365:                if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
1366:                    prefix
1367:                            .add(parseFragment("var $lzsc$d = Debug, $lzsc$s = $lzsc$d.backtraceStack;"
1368:                                    + "if ($lzsc$s) {"
1369:                                    + "  var $lzsc$a = Array.prototype.slice.call(arguments, 0);"
1370:                                    + "  $lzsc$a.callee = arguments.callee;"
1371:                                    + "  $lzsc$a['this'] = this;"
1372:                                    + "  $lzsc$s.push($lzsc$a);"
1373:                                    + "  if ($lzsc$s.length > $lzsc$s.maxDepth) {$lzsc$d.stackOverflow()};"
1374:                                    + "}"));
1375:                    error
1376:                            .add(parseFragment("if ($lzsc$s && (! $lzsc$d.uncaughtBacktraceStack)) {"
1377:                                    + "  $lzsc$d.uncaughtBacktraceStack = $lzsc$s.slice(0);"
1378:                                    + "}" + "throw($lzsc$e);"));
1379:                    suffix.add(parseFragment("if ($lzsc$s) {"
1380:                            + "  $lzsc$s.pop();" + "}"));
1381:                }
1382:                if (options.getBoolean(Compiler.PROFILE)) {
1383:                    prefix.add((meterFunctionEvent(node, "calls",
1384:                            meterFunctionName)));
1385:                    suffix.add((meterFunctionEvent(node, "returns",
1386:                            meterFunctionName)));
1387:                }
1388:
1389:                // Analyze local variables (and functions)
1390:                VariableAnalyzer analyzer = new VariableAnalyzer(
1391:                        params,
1392:                        options
1393:                                .getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY));
1394:                for (Iterator i = prefix.iterator(); i.hasNext();) {
1395:                    analyzer.visit((SimpleNode) i.next());
1396:                }
1397:                for (Iterator i = stmtList.iterator(); i.hasNext();) {
1398:                    analyzer.visit((SimpleNode) i.next());
1399:                }
1400:                for (Iterator i = suffix.iterator(); i.hasNext();) {
1401:                    analyzer.visit((SimpleNode) i.next());
1402:                }
1403:                analyzer.computeReferences();
1404:                // Parameter _must_ be in order
1405:                LinkedHashSet parameters = analyzer.parameters;
1406:                // Linked for determinism for regression testing
1407:                Set variables = analyzer.variables;
1408:                LinkedHashMap fundefs = analyzer.fundefs;
1409:                Set closed = analyzer.closed;
1410:                Set free = analyzer.free;
1411:                // Note usage due to activation object and withThis
1412:                if (!free.isEmpty()) {
1413:                    // TODO: [2005-06-29 ptw] with (_root) should not be
1414:                    // necessary for the activation object case now that it is
1415:                    // done at top level to get [[scope]] right.
1416:                    if (options.getBoolean(Compiler.ACTIVATION_OBJECT)) {
1417:                        analyzer.incrementUsed("_root");
1418:                    }
1419:                    if (options.getBoolean(Compiler.WITH_THIS)) {
1420:                        analyzer.incrementUsed("this");
1421:                    }
1422:                }
1423:                Map used = analyzer.used;
1424:                // If this is a closure, annotate the Username for metering
1425:                if ((!closed.isEmpty()) && (userFunctionName != null)
1426:                        && options.getBoolean(Compiler.PROFILE)) {
1427:                    // Is there any other way to construct a closure in js
1428:                    // other than a function returning a function?
1429:                    if (context.findFunctionContext().parent
1430:                            .findFunctionContext() != null) {
1431:                        userFunctionName = "" + closed + "." + userFunctionName;
1432:                    }
1433:                }
1434:                if (false) {
1435:                    System.err.println(userFunctionName + ":: parameters: "
1436:                            + parameters + ", variables: " + variables
1437:                            + ", fundefs: " + fundefs + ", used: " + used
1438:                            + ", closed: " + closed + ", free: " + free);
1439:                }
1440:                // Deal with warnings
1441:                if (options.getBoolean(Compiler.WARN_UNUSED_PARAMETERS)) {
1442:                    Set unusedParams = new LinkedHashSet(parameters);
1443:                    unusedParams.removeAll(used.keySet());
1444:                    for (Iterator i = unusedParams.iterator(); i.hasNext();) {
1445:                        System.err.println("Warning: parameter " + i.next()
1446:                                + " of " + userFunctionName + " unused in "
1447:                                + filename + "(" + lineno + ")");
1448:                    }
1449:                }
1450:                if (options.getBoolean(Compiler.WARN_UNUSED_LOCALS)) {
1451:                    Set unusedVariables = new LinkedHashSet(variables);
1452:                    unusedVariables.removeAll(used.keySet());
1453:                    for (Iterator i = unusedVariables.iterator(); i.hasNext();) {
1454:                        System.err.println("Warning: variable " + i.next()
1455:                                + " of " + userFunctionName + " unused in "
1456:                                + filename + "(" + lineno + ")");
1457:                    }
1458:                }
1459:                // auto-declared locals
1460:                Set auto = new LinkedHashSet();
1461:                auto.add("this");
1462:                auto.add("arguments");
1463:                auto.retainAll(used.keySet());
1464:                // parameters, locals, and auto-registers
1465:                Set known = new LinkedHashSet(parameters);
1466:                known.addAll(variables);
1467:                known.addAll(auto);
1468:                // for now, ensure that super has a value
1469:                known.remove("super");
1470:
1471:                // Look for #pragma
1472:                boolean scriptElement = options
1473:                        .getBoolean(Compiler.SCRIPT_ELEMENT);
1474:                Map registerMap = new HashMap();
1475:                if (!scriptElement) {
1476:                    // All parameters and locals are remapped to 'registers' of the
1477:                    // form `$n`.  This prevents them from colliding with member
1478:                    // slots due to implicit `with (this)` added below, and also makes
1479:                    // the emitted code more compact.
1480:                    int regno = 1;
1481:                    boolean debug = options.getBoolean(Compiler.NAME_FUNCTIONS);
1482:                    for (Iterator i = (new LinkedHashSet(known)).iterator(); i
1483:                            .hasNext();) {
1484:                        String k = (String) i.next();
1485:                        String r;
1486:                        if (auto.contains(k) || closed.contains(k)) {
1487:                            ;
1488:                        } else {
1489:                            if (debug) {
1490:                                r = "$" + regno++ + "_" + k;
1491:                            } else {
1492:                                r = "$" + regno++;
1493:                            }
1494:                            registerMap.put(k, r);
1495:                            // remove from known map
1496:                            known.remove(k);
1497:                        }
1498:                    }
1499:                }
1500:                // Always set register map.  Inner functions should not see
1501:                // parent registers (which they would if the setting of the
1502:                // registermap were conditional on function vs. function2)
1503:                context.setProperty(TranslationContext.REGISTERS, registerMap);
1504:                // Set the knownSet.  This includes the parent's known set, so
1505:                // closed over variables are not treated as free.
1506:                Set knownSet = new LinkedHashSet(known);
1507:                // Add parent known
1508:                Set parentKnown = (Set) context.parent
1509:                        .get(TranslationContext.VARIABLES);
1510:                if (parentKnown != null) {
1511:                    knownSet.addAll(parentKnown);
1512:                }
1513:                context.setProperty(TranslationContext.VARIABLES, knownSet);
1514:
1515:                // Replace params
1516:                for (int i = 0, len = paramIds.length; i < len; i++) {
1517:                    ASTIdentifier oldParam = (ASTIdentifier) paramIds[i];
1518:                    SimpleNode newParam = translateReference(oldParam)
1519:                            .declare();
1520:                    params.set(i, newParam);
1521:                }
1522:
1523:                List newBody = new ArrayList();
1524:
1525:                int activationObjectSize = 0;
1526:                if (scriptElement) {
1527:                    // Create all variables (including inner functions) in global scope
1528:                    if (!variables.isEmpty()) {
1529:                        String code = "";
1530:                        for (Iterator i = variables.iterator(); i.hasNext();) {
1531:                            code += "_root." + (String) i.next() + "= void 0;";
1532:                        }
1533:                        newBody.add(parseFragment(code));
1534:                    }
1535:                } else {
1536:                    // Leave var declarations as is
1537:                    // Emit function declarations here
1538:                    if (!fundefs.isEmpty()) {
1539:                        String code = "";
1540:                        for (Iterator i = fundefs.keySet().iterator(); i
1541:                                .hasNext();) {
1542:                            code += "var " + (String) i.next() + ";";
1543:                        }
1544:                        newBody.add(parseFragment(code));
1545:                    }
1546:                }
1547:
1548:                // Cf. LPP-4850: Prefix has to come after declarations (above).
1549:                // FIXME: (LPP-2075) [2006-05-19 ptw] Wrap body in try and make
1550:                // suffix be a finally clause, so suffix will not be skipped by
1551:                // inner returns.
1552:                newBody.addAll(prefix);
1553:
1554:                // Now emit functions in the activation context
1555:                // Note: variable has already been declared so assignment does the
1556:                // right thing (either assigns to global or local
1557:                for (Iterator i = fundefs.keySet().iterator(); i.hasNext();) {
1558:                    String name = (String) i.next();
1559:                    if (scriptElement || used.containsKey(name)) {
1560:                        SimpleNode fundecl = (SimpleNode) fundefs.get(name);
1561:                        SimpleNode funexpr = new ASTFunctionExpression(0);
1562:                        funexpr.setBeginLocation(fundecl.filename,
1563:                                fundecl.beginLine, fundecl.beginColumn);
1564:                        funexpr.setChildren(fundecl.getChildren());
1565:                        Map map = new HashMap();
1566:                        map.put("_1", funexpr);
1567:                        // Do I need a new one of these each time?
1568:                        newBody.add((new Compiler.Parser()).substitute(name
1569:                                + " = _1;", map));
1570:                    }
1571:                }
1572:                if ((!free.isEmpty()) && options.getBoolean(Compiler.WITH_THIS)) {
1573:                    SimpleNode newStmts = new ASTStatementList(0);
1574:                    newStmts.setChildren((SimpleNode[]) stmtList
1575:                            .toArray(new SimpleNode[0]));
1576:                    SimpleNode withNode = new ASTWithStatement(0);
1577:                    SimpleNode id = new ASTThisReference(0);
1578:                    withNode.set(0, id);
1579:                    withNode.set(1, newStmts);
1580:                    newBody.add(withNode);
1581:                } else {
1582:                    newBody.addAll(stmtList);
1583:                }
1584:                // FIXME: (LPP-2075) [2006-05-19 ptw] Wrap body in try and make
1585:                // suffix be a finally clause, so suffix will not be skipped by
1586:                // inner returns.
1587:                if (!suffix.isEmpty() || !error.isEmpty()) {
1588:                    int i = 0;
1589:                    SimpleNode newStmts = new ASTStatementList(0);
1590:                    newStmts.setChildren((SimpleNode[]) newBody
1591:                            .toArray(new SimpleNode[0]));
1592:                    SimpleNode tryNode = new ASTTryStatement(0);
1593:                    tryNode.set(i++, newStmts);
1594:                    if (!error.isEmpty()) {
1595:                        SimpleNode catchNode = new ASTCatchClause(0);
1596:                        SimpleNode catchStmts = new ASTStatementList(0);
1597:                        catchStmts.setChildren((SimpleNode[]) error
1598:                                .toArray(new SimpleNode[0]));
1599:                        catchNode.set(0, new ASTIdentifier("$lzsc$e"));
1600:                        catchNode.set(1, catchStmts);
1601:                        tryNode.set(i++, catchNode);
1602:                    }
1603:                    if (!suffix.isEmpty()) {
1604:                        SimpleNode finallyNode = new ASTFinallyClause(0);
1605:                        SimpleNode suffixStmts = new ASTStatementList(0);
1606:                        suffixStmts.setChildren((SimpleNode[]) suffix
1607:                                .toArray(new SimpleNode[0]));
1608:                        finallyNode.set(0, suffixStmts);
1609:                        tryNode.set(i, finallyNode);
1610:                    }
1611:                    newBody = new ArrayList();
1612:                    newBody.add(tryNode);
1613:                }
1614:                // Process amended body
1615:                SimpleNode newStmts = new ASTStatementList(0);
1616:                newStmts.setChildren((SimpleNode[]) newBody
1617:                        .toArray(new SimpleNode[0]));
1618:                newStmts = visitStatement(newStmts);
1619:                // Finally replace the function body with that whole enchilada
1620:                children[stmtsIndex] = newStmts;
1621:                if (options.getBoolean(Compiler.NAME_FUNCTIONS)) {
1622:                    // TODO: [2007-09-04 ptw] Come up with a better way to
1623:                    // distinguish LFC from user stack frames.  See
1624:                    // lfc/debugger/LzBactrace
1625:                    String fn = (options
1626:                            .getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) ? "lfc/"
1627:                            : "")
1628:                            + filename;
1629:                    if (functionName != null &&
1630:                    // Either it is a declaration or we are not doing
1631:                            // backtraces, so the name will be available from the
1632:                            // runtime
1633:                            (useName || (!(options
1634:                                    .getBoolean(Compiler.DEBUG_BACKTRACE))))) {
1635:                        if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
1636:                            SimpleNode newNode = new ASTStatementList(0);
1637:                            newNode.set(0, new Compiler.PassThroughNode(node));
1638:                            newNode.set(1, parseFragment(functionName
1639:                                    + "._dbg_filename = "
1640:                                    + ScriptCompiler.quote(fn)));
1641:                            newNode.set(2, parseFragment(functionName
1642:                                    + "._dbg_lineno = " + lineno));
1643:                            node = visitStatement(newNode);
1644:                        }
1645:                    } else {
1646:                        Map map = new HashMap();
1647:                        map.put("_1", node);
1648:                        SimpleNode newNode = new Compiler.PassThroughNode(
1649:                                (new Compiler.Parser())
1650:                                        .substitute(
1651:                                                "(function () {"
1652:                                                        + "   var $lzsc$temp = _1;"
1653:                                                        + "   $lzsc$temp._dbg_name = "
1654:                                                        + ScriptCompiler
1655:                                                                .quote(userFunctionName)
1656:                                                        + ";"
1657:                                                        + ((options
1658:                                                                .getBoolean(Compiler.DEBUG_BACKTRACE)) ? ("   $lzsc$temp._dbg_filename = "
1659:                                                                + ScriptCompiler
1660:                                                                        .quote(fn)
1661:                                                                + ";"
1662:                                                                + "   $lzsc$temp._dbg_lineno = "
1663:                                                                + lineno + ";")
1664:                                                                : "")
1665:                                                        + "   return $lzsc$temp})()",
1666:                                                map));
1667:                        node = newNode;
1668:                    }
1669:                }
1670:                if (options.getBoolean(Compiler.CONSTRAINT_FUNCTION)) {
1671:                    return new SimpleNode[] { node, depExpr };
1672:                }
1673:                return new SimpleNode[] { node, null };
1674:            }
1675:
1676:            SimpleNode translateLiteralNode(SimpleNode node) {
1677:                return node;
1678:            }
1679:
1680:            SimpleNode translateReferenceForCall(SimpleNode ast) {
1681:                return translateReferenceForCall(ast, false, null);
1682:            }
1683:
1684:            /* Contract is to leave a reference on the stack that will be
1685:               dereferenced by CallFunction, etc.  Returns true if it
1686:               succeeds.  Returns false if the ast is such that only the
1687:               value of the reference can be pushed.  In this case, the
1688:               callee, must use "CallMethod UNDEF" to call the value
1689:               instead */
1690:            SimpleNode translateReferenceForCall(SimpleNode ast,
1691:                    boolean checkDefined, SimpleNode node) {
1692:                SimpleNode[] children = ast.getChildren();
1693:                if (checkDefined) {
1694:                    assert node != null : "Must supply node for checkDefined";
1695:                }
1696:                if (ast instanceof  ASTPropertyIdentifierReference) {
1697:                    JavascriptReference ref = translateReference(children[0]);
1698:                    String name = ((ASTIdentifier) children[1]).getName();
1699:                    //       if (checkDefined) {
1700:                    //         // TODO: needs to transform node
1701:                    //         checkUndefinedMethod(node, ref, name);
1702:                    //       }
1703:                    children[0] = ref.get();
1704:                }
1705:                if (ast instanceof  ASTPropertyValueReference) {
1706:                    // TODO: [2002-10-26 ptw] (undefined reference coverage) Check
1707:                    JavascriptReference ref = translateReference(children[0]);
1708:                    children[1] = visitExpression(children[1]);
1709:                    children[0] = ref.get();
1710:                }
1711:                // The only other reason you visit a reference is to make a funcall
1712:                boolean isref = true;
1713:                if (ast instanceof  ASTIdentifier) {
1714:                    JavascriptReference ref = translateReference(ast);
1715:                    ast = ref.preset();
1716:                } else {
1717:                    ast = visitExpression(ast);
1718:                }
1719:                // TODO: wrap into node
1720:                //     if (checkDefined) {
1721:                //       checkUndefinedFunction(
1722:                //         node,
1723:                //         isref && ast instanceof ASTIdentifier ? ((ASTIdentifier)ast).getName() : null);
1724:                //     }
1725:                return ast;
1726:            }
1727:
1728:            JavascriptReference translateReference(SimpleNode node) {
1729:                return translateReference(node, 1);
1730:            }
1731:
1732:            static public class JavascriptReference {
1733:                protected Compiler.OptionMap options;
1734:                SimpleNode node;
1735:                SimpleNode checkedNode = null;
1736:
1737:                public JavascriptReference(Translator translator,
1738:                        SimpleNode node, int referenceCount) {
1739:                    this .options = translator.getOptions();
1740:                    this .node = node;
1741:                }
1742:
1743:                public boolean isChecked() {
1744:                    return checkedNode != null;
1745:                }
1746:
1747:                public SimpleNode get(boolean checkUndefined) {
1748:                    if (checkUndefined && checkedNode != null) {
1749:                        return checkedNode;
1750:                    }
1751:                    return this .node;
1752:                }
1753:
1754:                public SimpleNode get() {
1755:                    return get(true);
1756:                }
1757:
1758:                public SimpleNode preset() {
1759:                    return this .node;
1760:                }
1761:
1762:                public SimpleNode set(Boolean warnGlobal) {
1763:                    return this .node;
1764:                }
1765:
1766:                public SimpleNode set() {
1767:                    return set(null);
1768:                }
1769:
1770:                public SimpleNode set(boolean warnGlobal) {
1771:                    return set(Boolean.valueOf(warnGlobal));
1772:                }
1773:
1774:                public SimpleNode declare() {
1775:                    return this .node;
1776:                }
1777:
1778:                public SimpleNode init() {
1779:                    return this .node;
1780:                }
1781:            }
1782:
1783:            static public abstract class MemberReference extends
1784:                    JavascriptReference {
1785:                protected SimpleNode object;
1786:
1787:                public MemberReference(Translator translator, SimpleNode node,
1788:                        int referenceCount, SimpleNode object) {
1789:                    super (translator, node, referenceCount);
1790:                    this .object = object;
1791:                }
1792:            }
1793:
1794:            static public class VariableReference extends JavascriptReference {
1795:                TranslationContext context;
1796:                public final String name;
1797:
1798:                public VariableReference(Translator translator,
1799:                        SimpleNode node, int referenceCount, String name) {
1800:                    super (translator, node, referenceCount);
1801:                    this .name = name;
1802:                    this .context = (TranslationContext) translator.getContext();
1803:                    Map registers = (Map) context
1804:                            .get(TranslationContext.REGISTERS);
1805:                    // Replace identifiers with their 'register' (i.e. rename them)
1806:                    if (registers != null && registers.containsKey(name)) {
1807:                        String register = (String) registers.get(name);
1808:                        ASTIdentifier newNode = new ASTIdentifier(0);
1809:                        newNode.setName(register);
1810:                        this .node = new Compiler.PassThroughNode(newNode);
1811:                        return;
1812:                    }
1813:                    if (options.getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
1814:                        Set variables = (Set) context
1815:                                .get(TranslationContext.VARIABLES);
1816:                        if (variables != null) {
1817:                            boolean known = variables.contains(name);
1818:                            // Ensure undefined is "defined"
1819:                            known |= "undefined".equals(name);
1820:                            if (!known) {
1821:                                this .checkedNode = ((JavascriptGenerator) translator)
1822:                                        .makeCheckedNode(node);
1823:                            }
1824:                        }
1825:                    }
1826:                }
1827:
1828:                public SimpleNode declare() {
1829:                    Set variables = (Set) context
1830:                            .get(TranslationContext.VARIABLES);
1831:                    if (variables != null) {
1832:                        variables.add(this .name);
1833:                    }
1834:                    return this .node;
1835:                }
1836:
1837:                public SimpleNode init() {
1838:                    Set variables = (Set) context
1839:                            .get(TranslationContext.VARIABLES);
1840:                    if (variables != null) {
1841:                        variables.add(this .name);
1842:                    }
1843:                    return this .node;
1844:                }
1845:
1846:                public SimpleNode get(boolean checkUndefined) {
1847:                    if (checkUndefined && checkedNode != null) {
1848:                        return checkedNode;
1849:                    }
1850:                    return node;
1851:                }
1852:
1853:                public SimpleNode set(Boolean warnGlobal) {
1854:                    if (warnGlobal == null) {
1855:                        if (context.type instanceof  ASTProgram) {
1856:                            warnGlobal = Boolean.FALSE;
1857:                        } else {
1858:                            warnGlobal = Boolean
1859:                                    .valueOf(options
1860:                                            .getBoolean(Compiler.WARN_GLOBAL_ASSIGNMENTS));
1861:                        }
1862:                    }
1863:                    if ((checkedNode != null) && warnGlobal.booleanValue()) {
1864:                        System.err
1865:                                .println("Warning: Assignment to free variable "
1866:                                        + name
1867:                                        + " in "
1868:                                        + node.filename
1869:                                        + " ("
1870:                                        + node.beginLine + ")");
1871:                    }
1872:                    return node;
1873:                }
1874:            }
1875:
1876:            static public Set uncheckedProperties = new HashSet(Arrays
1877:                    .asList(new String[] { "call", "apply", "prototype" }));
1878:
1879:            static public class PropertyReference extends MemberReference {
1880:                String propertyName;
1881:
1882:                public PropertyReference(Translator translator,
1883:                        SimpleNode node, int referenceCount, SimpleNode object,
1884:                        ASTIdentifier propertyName) {
1885:                    super (translator, node, referenceCount, object);
1886:                    this .propertyName = (String) propertyName.getName();
1887:                    // TODO: [2006-04-24 ptw] Don't make checkedNode when you know
1888:                    // that the member exists
1889:                    // This is not right, but Opera does not support [[Call]] on
1890:                    // call or apply, so we can't check for them
1891:                    //       if (! uncheckedProperties.contains(this.propertyName)) {
1892:                    //         this.checkedNode = ((JavascriptGenerator)translator).makeCheckedNode(node);
1893:                    //       }
1894:                }
1895:            }
1896:
1897:            static public class IndexReference extends MemberReference {
1898:                SimpleNode indexExpr;
1899:
1900:                public IndexReference(Translator translator, SimpleNode node,
1901:                        int referenceCount, SimpleNode object,
1902:                        SimpleNode indexExpr) {
1903:                    super (translator, node, referenceCount, object);
1904:                    this .indexExpr = indexExpr;
1905:                    // We don't check index references for compatibility with SWF compiler
1906:                }
1907:            }
1908:
1909:            JavascriptReference translateReference(SimpleNode node,
1910:                    int referenceCount) {
1911:                if (node instanceof  ASTIdentifier) {
1912:                    return new VariableReference(this , node, referenceCount,
1913:                            ((ASTIdentifier) node).getName());
1914:                }
1915:
1916:                SimpleNode[] args = node.getChildren();
1917:                if (node instanceof  ASTPropertyIdentifierReference) {
1918:                    args[0] = visitExpression(args[0]);
1919:                    // If args[1] is an identifier, it is a literal, otherwise
1920:                    // translate it.
1921:                    if (!(args[1] instanceof  ASTIdentifier)) {
1922:                        args[1] = visitExpression(args[1]);
1923:                    }
1924:                    return new PropertyReference(this , node, referenceCount,
1925:                            args[0], (ASTIdentifier) args[1]);
1926:                } else if (node instanceof  ASTPropertyValueReference) {
1927:                    args[0] = visitExpression(args[0]);
1928:                    args[1] = visitExpression(args[1]);
1929:                    return new IndexReference(this , node, referenceCount,
1930:                            args[0], args[1]);
1931:                }
1932:
1933:                return new JavascriptReference(this , node, referenceCount);
1934:            }
1935:        }
1936:
1937:        /**
1938:         * @copyright Copyright 2006-2008 Laszlo Systems, Inc.  All Rights
1939:         * Reserved.  Use is subject to license terms.
1940:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.