KJS: rename "js.dart-ast" module to "js.ast"
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
Google Dart Js backend was removed - https://code.google.com/p/dart/source/detail?r=4771
|
||||
|
||||
According to http://www.apache.org/legal/3party.html we can include "Google Dart Js backend" in source form, because code license is "New BSD License" (Authorized License).
|
||||
|
||||
This part of code will be removed when kotlin will be rewritten on kotlin.
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Abstract interface to a source file.
|
||||
*/
|
||||
public interface Source {
|
||||
|
||||
/**
|
||||
* Determines whether the given source exists.
|
||||
*/
|
||||
boolean exists();
|
||||
|
||||
/**
|
||||
* Returns the last-modified timestamp for this source, using the same units as
|
||||
* {@link Date#getTime()}.
|
||||
*/
|
||||
long getLastModified();
|
||||
|
||||
/**
|
||||
* Gets the name of this source.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets a reader for the dart file's source code. The caller is responsible for closing the
|
||||
* returned reader.
|
||||
*/
|
||||
Reader getSourceReader() throws IOException;
|
||||
|
||||
/**
|
||||
* Gets the identifier for this source. This is used to uniquely identify the
|
||||
* source, but should not be used to obtain the source content. Use
|
||||
* {@link #getSourceReader()} to obtain the source content.
|
||||
*/
|
||||
URI getUri();
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Searches for method invocations in constructor expressions that would not
|
||||
* normally be surrounded by parentheses.
|
||||
*/
|
||||
public class JsConstructExpressionVisitor extends RecursiveJsVisitor {
|
||||
public static boolean exec(JsExpression expression) {
|
||||
if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
|
||||
return true;
|
||||
}
|
||||
JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
|
||||
visitor.accept(expression);
|
||||
return visitor.containsInvocation;
|
||||
}
|
||||
|
||||
private boolean containsInvocation;
|
||||
|
||||
private JsConstructExpressionVisitor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* We only look at the array expression since the index has its own scope.
|
||||
*/
|
||||
@Override
|
||||
public void visitArrayAccess(@NotNull JsArrayAccess x) {
|
||||
accept(x.getArrayExpression());
|
||||
}
|
||||
|
||||
/**
|
||||
* Array literals have their own scoping.
|
||||
*/
|
||||
@Override
|
||||
public void visitArray(@NotNull JsArrayLiteral x) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions have their own scoping.
|
||||
*/
|
||||
@Override
|
||||
public void visitFunction(@NotNull JsFunction x) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvocation(@NotNull JsInvocation invocation) {
|
||||
containsInvocation = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef) {
|
||||
if (!nameRef.isLeaf()) {
|
||||
accept(nameRef.getQualifier());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* New constructs bind to the nearest set of parentheses.
|
||||
*/
|
||||
@Override
|
||||
public void visitNew(@NotNull JsNew x) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Object literals have their own scope.
|
||||
*/
|
||||
@Override
|
||||
public void visitObjectLiteral(@NotNull JsObjectLiteral x) {
|
||||
}
|
||||
|
||||
/**
|
||||
* We only look at nodes that would not normally be surrounded by parentheses.
|
||||
*/
|
||||
@Override
|
||||
public <T extends JsNode> void accept(T node) {
|
||||
// Assign to Object to prevent 'inconvertible types' compile errors due
|
||||
// to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
|
||||
// reproducible in jdk1.6.0_02.
|
||||
if (node instanceof JsExpression) {
|
||||
JsExpression expression = (JsExpression) node;
|
||||
int precedence = JsPrecedenceVisitor.exec(expression);
|
||||
// Only visit expressions that won't automatically be surrounded by
|
||||
// parentheses
|
||||
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.accept(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpressionStatement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Determines if an expression statement needs to be surrounded by parentheses.
|
||||
* <p/>
|
||||
* The statement or the left-most expression needs to be surrounded by
|
||||
* parentheses if the left-most expression is an object literal or a function
|
||||
* object. Function declarations do not need parentheses.
|
||||
* <p/>
|
||||
* For example the following require parentheses:<br>
|
||||
* <ul>
|
||||
* <li>{ key : 'value'}</li>
|
||||
* <li>{ key : 'value'}.key</li>
|
||||
* <li>function () {return 1;}()</li>
|
||||
* <li>function () {return 1;}.prototype</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* The following do not require parentheses:<br>
|
||||
* <ul>
|
||||
* <li>var x = { key : 'value'}</li>
|
||||
* <li>"string" + { key : 'value'}.key</li>
|
||||
* <li>function func() {}</li>
|
||||
* <li>function() {}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class JsFirstExpressionVisitor extends RecursiveJsVisitor {
|
||||
public static boolean exec(JsExpressionStatement statement) {
|
||||
JsExpression expression = statement.getExpression();
|
||||
// Pure function declarations do not need parentheses
|
||||
if (expression instanceof JsFunction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsFirstExpressionVisitor visitor = new JsFirstExpressionVisitor();
|
||||
visitor.accept(statement.getExpression());
|
||||
return visitor.needsParentheses;
|
||||
}
|
||||
|
||||
private boolean needsParentheses = false;
|
||||
|
||||
private JsFirstExpressionVisitor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArrayAccess(@NotNull JsArrayAccess x) {
|
||||
accept(x.getArrayExpression());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArray(@NotNull JsArrayLiteral x) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(@NotNull JsBinaryOperation x) {
|
||||
accept(x.getArg1());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConditional(@NotNull JsConditional x) {
|
||||
accept(x.getTestExpression());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunction(@NotNull JsFunction x) {
|
||||
needsParentheses = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvocation(@NotNull JsInvocation invocation) {
|
||||
accept(invocation.getQualifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef) {
|
||||
if (!nameRef.isLeaf()) {
|
||||
accept(nameRef.getQualifier());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNew(@NotNull JsNew x) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteral(@NotNull JsObjectLiteral x) {
|
||||
needsParentheses = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
|
||||
accept(x.getArg());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
|
||||
* 57)
|
||||
* <p/>
|
||||
* Precedence 17 is for indivisible primaries that either don't have children,
|
||||
* or provide their own delimiters.
|
||||
* <p/>
|
||||
* Precedence 16 is for really important things that have their own AST classes.
|
||||
* <p/>
|
||||
* Precedence 15 is for the new construct.
|
||||
* <p/>
|
||||
* Precedence 14 is for unary operators.
|
||||
* <p/>
|
||||
* Precedences 12 through 4 are for non-assigning binary operators.
|
||||
* <p/>
|
||||
* Precedence 3 is for the tertiary conditional.
|
||||
* <p/>
|
||||
* Precedence 2 is for assignments.
|
||||
* <p/>
|
||||
* Precedence 1 is for comma operations.
|
||||
*/
|
||||
class JsPrecedenceVisitor extends JsVisitor {
|
||||
static final int PRECEDENCE_NEW = 15;
|
||||
|
||||
private int answer = -1;
|
||||
|
||||
private JsPrecedenceVisitor() {
|
||||
}
|
||||
|
||||
public static int exec(JsExpression expression) {
|
||||
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
|
||||
visitor.accept(expression);
|
||||
if (visitor.answer < 0) {
|
||||
throw new RuntimeException("Precedence must be >= 0!");
|
||||
}
|
||||
return visitor.answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArrayAccess(@NotNull JsArrayAccess x) {
|
||||
answer = 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArray(@NotNull JsArrayLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(@NotNull JsBinaryOperation x) {
|
||||
answer = x.getOperator().getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBoolean(@NotNull JsLiteral.JsBooleanLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConditional(@NotNull JsConditional x) {
|
||||
answer = 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunction(@NotNull JsFunction x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvocation(@NotNull JsInvocation invocation) {
|
||||
answer = 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef) {
|
||||
if (nameRef.isLeaf()) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
else {
|
||||
answer = 16; // property access
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNew(@NotNull JsNew x) {
|
||||
answer = PRECEDENCE_NEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNull(@NotNull JsNullLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInt(@NotNull JsNumberLiteral.JsIntLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDouble(@NotNull JsNumberLiteral.JsDoubleLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteral(@NotNull JsObjectLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
|
||||
answer = x.getOperator().getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
|
||||
answer = x.getOperator().getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPropertyInitializer(@NotNull JsPropertyInitializer x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRegExp(@NotNull JsRegExp x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitString(@NotNull JsStringLiteral x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThis(@NotNull JsLiteral.JsThisRef x) {
|
||||
answer = 17; // primary
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitElement(@NotNull JsNode node) {
|
||||
throw new RuntimeException("Only expressions have precedence.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Determines if a statement at the end of a block requires a semicolon.
|
||||
* <p/>
|
||||
* For example, the following statements require semicolons:<br>
|
||||
* <ul>
|
||||
* <li>if (cond);</li>
|
||||
* <li>while (cond);</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* The following do not require semicolons:<br>
|
||||
* <ul>
|
||||
* <li>return 1</li>
|
||||
* <li>do {} while(true)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class JsRequiresSemiVisitor extends JsVisitor {
|
||||
private boolean needsSemicolon;
|
||||
|
||||
private JsRequiresSemiVisitor() {
|
||||
}
|
||||
|
||||
public static boolean exec(JsStatement lastStatement) {
|
||||
JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor();
|
||||
visitor.accept(lastStatement);
|
||||
return visitor.needsSemicolon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFor(@NotNull JsFor x) {
|
||||
if (x.getBody() instanceof JsEmpty) {
|
||||
needsSemicolon = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForIn(@NotNull JsForIn x) {
|
||||
if (x.getBody() instanceof JsEmpty) {
|
||||
needsSemicolon = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIf(@NotNull JsIf x) {
|
||||
JsStatement thenStmt = x.getThenStatement();
|
||||
JsStatement elseStmt = x.getElseStatement();
|
||||
JsStatement toCheck = thenStmt;
|
||||
if (elseStmt != null) {
|
||||
toCheck = elseStmt;
|
||||
}
|
||||
if (toCheck instanceof JsEmpty) {
|
||||
needsSemicolon = true;
|
||||
}
|
||||
else {
|
||||
// Must recurse to determine last statement (possible if-else chain).
|
||||
accept(toCheck);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLabel(@NotNull JsLabel x) {
|
||||
if (x.getStatement() instanceof JsEmpty) {
|
||||
needsSemicolon = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhile(@NotNull JsWhile x) {
|
||||
if (x.getBody() instanceof JsEmpty) {
|
||||
needsSemicolon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import gnu.trove.THashSet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Determines whether or not a particular string is a JavaScript keyword or not.
|
||||
*/
|
||||
public class JsReservedIdentifiers {
|
||||
public static final Set<String> reservedGlobalSymbols;
|
||||
|
||||
static {
|
||||
String[] commonBuiltins = new String[] {
|
||||
// 15.1.1 Value Properties of the Global Object
|
||||
"NaN", "Infinity", "undefined",
|
||||
|
||||
// 15.1.2 Function Properties of the Global Object
|
||||
"eval", "parseInt", "parseFloat", "isNan", "isFinite",
|
||||
|
||||
// 15.1.3 URI Handling Function Properties
|
||||
"decodeURI", "decodeURIComponent",
|
||||
"encodeURI",
|
||||
"encodeURIComponent",
|
||||
|
||||
// 15.1.4 Constructor Properties of the Global Object
|
||||
"Object", "Function", "Array", "String", "Boolean", "Number", "Date",
|
||||
"RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
|
||||
"SyntaxError", "TypeError", "URIError",
|
||||
|
||||
// 15.1.5 Other Properties of the Global Object
|
||||
"Math",
|
||||
|
||||
// 10.1.6 Activation Object
|
||||
"arguments",
|
||||
|
||||
// B.2 Additional Properties (non-normative)
|
||||
"escape", "unescape",
|
||||
|
||||
// Window props (https://developer.mozilla.org/en/DOM/window)
|
||||
"applicationCache", "closed", "Components", "content", "controllers",
|
||||
"crypto", "defaultStatus", "dialogArguments", "directories",
|
||||
"document", "frameElement", "frames", "fullScreen", "globalStorage",
|
||||
"history", "innerHeight", "innerWidth", "length",
|
||||
"location", "locationbar", "localStorage", "menubar",
|
||||
"mozInnerScreenX", "mozInnerScreenY", "mozScreenPixelsPerCssPixel",
|
||||
"name", "navigator", "opener", "outerHeight", "outerWidth",
|
||||
"pageXOffset", "pageYOffset", "parent", "personalbar", "pkcs11",
|
||||
"returnValue", "screen", "scrollbars", "scrollMaxX", "scrollMaxY",
|
||||
"self", "sessionStorage", "sidebar", "status", "statusbar", "toolbar",
|
||||
"top", "window",
|
||||
|
||||
// Window methods (https://developer.mozilla.org/en/DOM/window)
|
||||
"alert", "addEventListener", "atob", "back", "blur", "btoa",
|
||||
"captureEvents", "clearInterval", "clearTimeout", "close", "confirm",
|
||||
"disableExternalCapture", "dispatchEvent", "dump",
|
||||
"enableExternalCapture", "escape", "find", "focus", "forward",
|
||||
"GeckoActiveXObject", "getAttention", "getAttentionWithCycleCount",
|
||||
"getComputedStyle", "getSelection", "home", "maximize", "minimize",
|
||||
"moveBy", "moveTo", "open", "openDialog", "postMessage", "print",
|
||||
"prompt", "QueryInterface", "releaseEvents", "removeEventListener",
|
||||
"resizeBy", "resizeTo", "restore", "routeEvent", "scroll", "scrollBy",
|
||||
"scrollByLines", "scrollByPages", "scrollTo", "setInterval",
|
||||
"setResizeable", "setTimeout", "showModalDialog", "sizeToContent",
|
||||
"stop", "uuescape", "updateCommands", "XPCNativeWrapper",
|
||||
"XPCSafeJSOjbectWrapper",
|
||||
|
||||
// Mozilla Window event handlers, same cite
|
||||
"onabort", "onbeforeunload", "onchange", "onclick", "onclose",
|
||||
"oncontextmenu", "ondragdrop", "onerror", "onfocus", "onhashchange",
|
||||
"onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown",
|
||||
"onmousemove", "onmouseout", "onmouseover", "onmouseup",
|
||||
"onmozorientation", "onpaint", "onreset", "onresize", "onscroll",
|
||||
"onselect", "onsubmit", "onunload",
|
||||
|
||||
// Safari Web Content Guide
|
||||
// http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
|
||||
// WebKit Window member data, from WebKit DOM Reference
|
||||
// (http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/WebKitDOMRef/DOMWindow_idl/Classes/DOMWindow/index.html)
|
||||
// TODO(fredsa) Many, many more functions and member data to add
|
||||
"ontouchcancel", "ontouchend", "ontouchmove", "ontouchstart",
|
||||
"ongesturestart", "ongesturechange", "ongestureend",
|
||||
|
||||
// extra window methods
|
||||
"uneval",
|
||||
|
||||
// keywords https://developer.mozilla.org/en/New_in_JavaScript_1.7,
|
||||
// https://developer.mozilla.org/en/New_in_JavaScript_1.8.1
|
||||
"getPrototypeOf", "let", "yield",
|
||||
|
||||
// "future reserved words"
|
||||
"abstract", "int", "short", "boolean", "interface", "static", "byte",
|
||||
"long", "char", "final", "native", "synchronized", "float", "package",
|
||||
"throws", "goto", "private", "transient", "implements", "protected",
|
||||
"volatile", "double", "public",
|
||||
|
||||
// IE methods
|
||||
// (http://msdn.microsoft.com/en-us/library/ms535873(VS.85).aspx#)
|
||||
"attachEvent", "clientInformation", "clipboardData", "createPopup",
|
||||
"dialogHeight", "dialogLeft", "dialogTop", "dialogWidth",
|
||||
"onafterprint", "onbeforedeactivate", "onbeforeprint",
|
||||
"oncontrolselect", "ondeactivate", "onhelp", "onresizeend",
|
||||
|
||||
// Common browser-defined identifiers not defined in ECMAScript
|
||||
"event", "external", "Debug", "Enumerator", "Global", "Image",
|
||||
"ActiveXObject", "VBArray", "Components",
|
||||
|
||||
// Functions commonly defined on Object
|
||||
"toString", "getClass", "constructor", "prototype", "valueOf",
|
||||
|
||||
// Client-side JavaScript identifiers, which are needed for linkers
|
||||
// that don't ensure GWT's window != $wnd, document != $doc, etc.
|
||||
// Taken from the Rhino book, pg 715
|
||||
"Anchor", "Applet", "Attr", "Canvas", "CanvasGradient",
|
||||
"CanvasPattern", "CanvasRenderingContext2D", "CDATASection",
|
||||
"CharacterData", "Comment", "CSS2Properties", "CSSRule",
|
||||
"CSSStyleSheet", "Document", "DocumentFragment", "DocumentType",
|
||||
"DOMException", "DOMImplementation", "DOMParser", "Element", "Event",
|
||||
"ExternalInterface", "FlashPlayer", "Form", "Frame", "History",
|
||||
"HTMLCollection", "HTMLDocument", "HTMLElement", "IFrame", "Image",
|
||||
"Input", "JSObject", "KeyEvent", "Link", "Location", "MimeType",
|
||||
"MouseEvent", "Navigator", "Node", "NodeList", "Option", "Plugin",
|
||||
"ProcessingInstruction", "Range", "RangeException", "Screen", "Select",
|
||||
"Table", "TableCell", "TableRow", "TableSelection", "Text", "TextArea",
|
||||
"UIEvent", "Window", "XMLHttpRequest", "XMLSerializer",
|
||||
"XPathException", "XPathResult", "XSLTProcessor",
|
||||
|
||||
// These keywords trigger the loading of the java-plugin. For the
|
||||
// next-generation plugin, this results in starting a new Java process.
|
||||
"java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
|
||||
"JavaArray", "JavaMember",
|
||||
|
||||
// GWT-defined identifiers
|
||||
"$wnd", "$doc", "$entry", "$moduleName", "$moduleBase", "$gwt_version", "$sessionId",
|
||||
|
||||
// Identifiers used by JsStackEmulator; later set to obfuscatable
|
||||
"$stack", "$stackDepth", "$location",
|
||||
};
|
||||
|
||||
reservedGlobalSymbols = new THashSet<String>(commonBuiltins.length);
|
||||
Collections.addAll(reservedGlobalSymbols, commonBuiltins);
|
||||
}
|
||||
|
||||
private JsReservedIdentifiers() {
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
|
||||
import com.google.dart.compiler.util.TextOutputImpl;
|
||||
|
||||
abstract class AbstractNode extends HasMetadata implements JsNode {
|
||||
@Override
|
||||
public String toString() {
|
||||
TextOutputImpl out = new TextOutputImpl();
|
||||
new JsToStringGenerationVisitor(out).accept(this);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
protected <T extends HasMetadata> T withMetadataFrom(T other) {
|
||||
this.copyMetadataFrom(other);
|
||||
//noinspection unchecked
|
||||
return (T) this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implemented by JavaScript objects that accept arguments.
|
||||
*/
|
||||
public interface HasArguments {
|
||||
List<JsExpression> getArguments();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Implemented by JavaScript objects with conditional execution.
|
||||
*/
|
||||
public interface HasCondition {
|
||||
|
||||
JsExpression getCondition();
|
||||
|
||||
void setCondition(JsExpression condition);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.HasSymbol;
|
||||
|
||||
/**
|
||||
* Implemented by JavaScript objects that have a name.
|
||||
*/
|
||||
public interface HasName extends HasSymbol {
|
||||
JsName getName();
|
||||
|
||||
void setName(JsName name);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a javascript expression for array access.
|
||||
*/
|
||||
public final class JsArrayAccess extends JsExpression {
|
||||
private JsExpression arrayExpression;
|
||||
private JsExpression indexExpression;
|
||||
|
||||
public JsArrayAccess() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JsArrayAccess(JsExpression arrayExpression, JsExpression indexExpression) {
|
||||
this.arrayExpression = arrayExpression;
|
||||
this.indexExpression = indexExpression;
|
||||
}
|
||||
|
||||
public JsExpression getArrayExpression() {
|
||||
return arrayExpression;
|
||||
}
|
||||
|
||||
public JsExpression getIndexExpression() {
|
||||
return indexExpression;
|
||||
}
|
||||
|
||||
public void setArrayExpression(JsExpression arrayExpression) {
|
||||
this.arrayExpression = arrayExpression;
|
||||
}
|
||||
|
||||
public void setIndexExpression(JsExpression indexExpression) {
|
||||
this.indexExpression = indexExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitArrayAccess(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(arrayExpression);
|
||||
visitor.accept(indexExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
arrayExpression = v.accept(arrayExpression);
|
||||
indexExpression = v.accept(indexExpression);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsArrayAccess deepCopy() {
|
||||
JsExpression arrayCopy = AstUtil.deepCopy(arrayExpression);
|
||||
JsExpression indexCopy = AstUtil.deepCopy(indexExpression);
|
||||
|
||||
return new JsArrayAccess(arrayCopy, indexCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript expression for array literals.
|
||||
*/
|
||||
public final class JsArrayLiteral extends JsLiteral {
|
||||
private final List<JsExpression> expressions;
|
||||
|
||||
public JsArrayLiteral() {
|
||||
expressions = new SmartList<JsExpression>();
|
||||
}
|
||||
|
||||
public JsArrayLiteral(List<JsExpression> expressions) {
|
||||
this.expressions = expressions;
|
||||
}
|
||||
|
||||
public List<JsExpression> getExpressions() {
|
||||
return expressions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitArray(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(expressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptList(expressions);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsArrayLiteral deepCopy() {
|
||||
return new JsArrayLiteral(AstUtil.deepCopy(expressions)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class JsBinaryOperation extends JsExpression {
|
||||
private JsExpression arg1;
|
||||
private JsExpression arg2;
|
||||
|
||||
@NotNull
|
||||
private final JsBinaryOperator op;
|
||||
|
||||
public JsBinaryOperation(@NotNull JsBinaryOperator op, @Nullable JsExpression arg1, @Nullable JsExpression arg2) {
|
||||
this.op = op;
|
||||
this.arg1 = arg1;
|
||||
this.arg2 = arg2;
|
||||
}
|
||||
|
||||
public JsExpression getArg1() {
|
||||
return arg1;
|
||||
}
|
||||
|
||||
public JsExpression getArg2() {
|
||||
return arg2;
|
||||
}
|
||||
|
||||
public void setArg1(JsExpression arg1) {
|
||||
this.arg1 = arg1;
|
||||
}
|
||||
|
||||
public void setArg2(JsExpression arg2) {
|
||||
this.arg2 = arg2;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsBinaryOperator getOperator() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitBinaryExpression(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (op.isAssignment()) {
|
||||
visitor.acceptLvalue(arg1);
|
||||
}
|
||||
else {
|
||||
visitor.accept(arg1);
|
||||
}
|
||||
visitor.accept(arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (op.isAssignment()) {
|
||||
arg1 = v.acceptLvalue(arg1);
|
||||
} else {
|
||||
arg1 = v.accept(arg1);
|
||||
}
|
||||
arg2 = v.accept(arg2);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression deepCopy() {
|
||||
return new JsBinaryOperation(op, AstUtil.deepCopy(arg1), AstUtil.deepCopy(arg2)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Represents the operator in a JavaScript binary operation.
|
||||
*/
|
||||
public enum JsBinaryOperator implements JsOperator {
|
||||
/*
|
||||
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
|
||||
* (page 57)
|
||||
*
|
||||
*
|
||||
* Precedence 15 is for really important things that have their own AST
|
||||
* classes.
|
||||
*
|
||||
* Precedence 14 is for unary operators.
|
||||
*/
|
||||
|
||||
MUL("*", 13, LEFT | INFIX), DIV("/", 13, LEFT | INFIX), MOD("%", 13, LEFT
|
||||
| INFIX),
|
||||
|
||||
ADD("+", 12, LEFT | INFIX), SUB("-", 12, LEFT | INFIX),
|
||||
|
||||
SHL("<<", 11, LEFT | INFIX), SHR(">>", 11, LEFT | INFIX), SHRU(">>>", 11,
|
||||
LEFT | INFIX),
|
||||
|
||||
LT("<", 10, LEFT | INFIX), LTE("<=", 10, LEFT | INFIX), GT(">", 10, LEFT
|
||||
| INFIX), GTE(">=", 10, LEFT | INFIX), INSTANCEOF("instanceof", 10, LEFT
|
||||
| INFIX), INOP("in", 10, LEFT | INFIX),
|
||||
|
||||
EQ("==", 9, LEFT | INFIX), NEQ("!=", 9, LEFT | INFIX), REF_EQ("===", 9, LEFT
|
||||
| INFIX), REF_NEQ("!==", 9, LEFT | INFIX),
|
||||
|
||||
BIT_AND("&", 8, LEFT | INFIX),
|
||||
|
||||
BIT_XOR("^", 7, LEFT | INFIX),
|
||||
|
||||
BIT_OR("|", 6, LEFT | INFIX),
|
||||
|
||||
AND("&&", 5, LEFT | INFIX),
|
||||
|
||||
OR("||", 4, LEFT | INFIX),
|
||||
|
||||
// Precedence 3 is for the condition operator.
|
||||
|
||||
// These assignment operators are right-associative.
|
||||
ASG("=", 2, INFIX), ASG_ADD("+=", 2, INFIX), ASG_SUB("-=", 2, INFIX), ASG_MUL(
|
||||
"*=", 2, INFIX), ASG_DIV("/=", 2, INFIX), ASG_MOD("%=", 2, INFIX), ASG_SHL(
|
||||
"<<=", 2, INFIX), ASG_SHR(">>=", 2, INFIX), ASG_SHRU(">>>=", 2, INFIX), ASG_BIT_AND(
|
||||
"&=", 2, INFIX), ASG_BIT_OR("|=", 2, INFIX), ASG_BIT_XOR("^=", 2, INFIX),
|
||||
|
||||
COMMA(",", 1, LEFT | INFIX);
|
||||
|
||||
private final int mask;
|
||||
private final int precedence;
|
||||
private final String symbol;
|
||||
|
||||
private JsBinaryOperator(String symbol, int precedence, int mask) {
|
||||
this.symbol = symbol;
|
||||
this.precedence = precedence;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public boolean isAssignment() {
|
||||
return getPrecedence() == ASG.getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKeyword() {
|
||||
return this == INSTANCEOF || this == INOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeftAssociative() {
|
||||
return (mask & LEFT) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrecedenceLessThan(JsOperator other) {
|
||||
return precedence < other.getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInfix() {
|
||||
return (mask & INFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPostfix() {
|
||||
return (mask & POSTFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPrefix() {
|
||||
return (mask & PREFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript block statement.
|
||||
*/
|
||||
public class JsBlock extends SourceInfoAwareJsNode implements JsStatement {
|
||||
@NotNull
|
||||
private final List<JsStatement> statements;
|
||||
|
||||
public JsBlock() {
|
||||
this(new ArrayList<JsStatement>());
|
||||
}
|
||||
|
||||
public JsBlock(JsStatement statement) {
|
||||
this(new SmartList<JsStatement>(statement));
|
||||
}
|
||||
|
||||
public JsBlock(JsStatement... statements) {
|
||||
this(new SmartList<JsStatement>(statements));
|
||||
}
|
||||
|
||||
public JsBlock(@NotNull List<JsStatement> statements) {
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JsStatement> getStatements() {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return statements.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isGlobalBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitBlock(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(statements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptStatementList(statements);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsBlock deepCopy() {
|
||||
return new JsBlock(AstUtil.deepCopy(statements)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript break statement.
|
||||
*/
|
||||
public final class JsBreak extends JsContinue {
|
||||
public JsBreak() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public JsBreak(JsNameRef label) {
|
||||
super(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitBreak(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (label != null){
|
||||
label = v.accept(label);
|
||||
}
|
||||
}
|
||||
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsBreak deepCopy() {
|
||||
return new JsBreak(AstUtil.deepCopy(label)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript case statement.
|
||||
*/
|
||||
public final class JsCase extends JsSwitchMember {
|
||||
private JsExpression caseExpression;
|
||||
|
||||
public JsCase() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JsExpression getCaseExpression() {
|
||||
return caseExpression;
|
||||
}
|
||||
|
||||
public void setCaseExpression(JsExpression caseExpression) {
|
||||
this.caseExpression = caseExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitCase(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(caseExpression);
|
||||
super.acceptChildren(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
caseExpression = v.accept(caseExpression);
|
||||
v.acceptStatementList(statements);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsCase deepCopy() {
|
||||
JsCase caseCopy = new JsCase();
|
||||
caseCopy.caseExpression = AstUtil.deepCopy(caseExpression);
|
||||
caseCopy.statements.addAll(AstUtil.deepCopy(statements));
|
||||
|
||||
return caseCopy.withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript catch clause.
|
||||
*/
|
||||
public class JsCatch extends SourceInfoAwareJsNode implements HasCondition {
|
||||
|
||||
protected final JsCatchScope scope;
|
||||
private JsBlock body;
|
||||
private JsExpression condition;
|
||||
private JsParameter param;
|
||||
|
||||
public JsCatch(JsScope parent, @NotNull String ident) {
|
||||
super();
|
||||
assert (parent != null);
|
||||
scope = new JsCatchScope(parent, ident);
|
||||
param = new JsParameter(scope.findName(ident));
|
||||
}
|
||||
|
||||
public JsCatch(JsScope parent, @NotNull String ident, @NotNull JsStatement catchBody) {
|
||||
this(parent, ident);
|
||||
if (catchBody instanceof JsBlock) {
|
||||
body = (JsBlock) catchBody;
|
||||
} else {
|
||||
body = new JsBlock(catchBody);
|
||||
}
|
||||
}
|
||||
|
||||
public JsBlock getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsExpression getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public JsParameter getParameter() {
|
||||
return param;
|
||||
}
|
||||
|
||||
public JsScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setBody(JsBlock body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCondition(JsExpression condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitCatch(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(param);
|
||||
if (condition != null) {
|
||||
visitor.accept(condition);
|
||||
}
|
||||
visitor.accept(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
param = v.accept(param);
|
||||
if (condition != null) {
|
||||
condition = v.accept(condition);
|
||||
}
|
||||
body = v.acceptStatement(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsCatch deepCopy() {
|
||||
JsCatchScope scopeCopy = scope.copy();
|
||||
JsBlock bodyCopy = AstUtil.deepCopy(body);
|
||||
JsExpression conditionCopy = AstUtil.deepCopy(condition);
|
||||
JsParameter paramCopy = AstUtil.deepCopy(param);
|
||||
|
||||
return new JsCatch(scopeCopy, bodyCopy, conditionCopy, paramCopy).withMetadataFrom(this);
|
||||
}
|
||||
|
||||
private JsCatch(JsCatchScope scope, JsBlock body, JsExpression condition, JsParameter param) {
|
||||
this.scope = scope;
|
||||
this.body = body;
|
||||
this.condition = condition;
|
||||
this.param = param;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A special scope used only for catch blocks. It only holds a single symbol:
|
||||
* the catch argument's name.
|
||||
*/
|
||||
public class JsCatchScope extends JsScope {
|
||||
private final JsName name;
|
||||
|
||||
public JsCatchScope(JsScope parent, @NotNull String ident) {
|
||||
super(parent, "Catch scope");
|
||||
name = new JsName(this, ident, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JsName declareName(@NotNull String identifier) {
|
||||
// Declare into parent scope!
|
||||
return getParent().declareName(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOwnName(@NotNull String name) {
|
||||
return findOwnName(name) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsCatchScope copy() {
|
||||
return new JsCatchScope(getParent(), name.getIdent());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsName findOwnName(@NotNull String ident) {
|
||||
return name.getIdent().equals(ident) ? name : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class JsConditional extends JsExpression {
|
||||
private JsExpression testExpression;
|
||||
private JsExpression elseExpression;
|
||||
private JsExpression thenExpression;
|
||||
|
||||
public JsConditional() {
|
||||
}
|
||||
|
||||
public JsConditional(JsExpression testExpression, JsExpression thenExpression, JsExpression elseExpression) {
|
||||
this.testExpression = testExpression;
|
||||
this.thenExpression = thenExpression;
|
||||
this.elseExpression = elseExpression;
|
||||
}
|
||||
|
||||
public JsExpression getElseExpression() {
|
||||
return elseExpression;
|
||||
}
|
||||
|
||||
public JsExpression getTestExpression() {
|
||||
return testExpression;
|
||||
}
|
||||
|
||||
public JsExpression getThenExpression() {
|
||||
return thenExpression;
|
||||
}
|
||||
|
||||
public void setElseExpression(JsExpression elseExpression) {
|
||||
this.elseExpression = elseExpression;
|
||||
}
|
||||
|
||||
public void setTestExpression(JsExpression testExpression) {
|
||||
this.testExpression = testExpression;
|
||||
}
|
||||
|
||||
public void setThenExpression(JsExpression thenExpression) {
|
||||
this.thenExpression = thenExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitConditional(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(testExpression);
|
||||
visitor.accept(thenExpression);
|
||||
visitor.accept(elseExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
testExpression = v.accept(testExpression);
|
||||
thenExpression = v.accept(thenExpression);
|
||||
elseExpression = v.accept(elseExpression);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsConditional deepCopy() {
|
||||
JsExpression testCopy = AstUtil.deepCopy(testExpression);
|
||||
JsExpression thenCopy = AstUtil.deepCopy(thenExpression);
|
||||
JsExpression elseCopy = AstUtil.deepCopy(elseExpression);
|
||||
|
||||
return new JsConditional(testCopy, thenCopy, elseCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The context in which a JsNode visitation occurs. This represents the set of
|
||||
* possible operations a JsVisitor subclass can perform on the currently visited
|
||||
* node.
|
||||
*/
|
||||
public abstract class JsContext<T extends JsNode> {
|
||||
|
||||
public <R extends T> void addPrevious(R node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public <R extends T> void addPrevious(List<R> nodes) {
|
||||
for (R node : nodes) {
|
||||
addPrevious(node);
|
||||
}
|
||||
}
|
||||
|
||||
public <R extends T> void addNext(R node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public abstract void removeMe();
|
||||
|
||||
public abstract <R extends T> void replaceMe(R node);
|
||||
|
||||
@Nullable
|
||||
public abstract T getCurrentNode();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class JsContinue extends SourceInfoAwareJsNode implements JsStatement {
|
||||
protected JsNameRef label;
|
||||
|
||||
public JsContinue() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public JsContinue(@Nullable JsNameRef label) {
|
||||
super();
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public JsNameRef getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitContinue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor v) {
|
||||
if (label != null){
|
||||
v.accept(label);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (label != null){
|
||||
label = v.accept(label);
|
||||
}
|
||||
}
|
||||
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsContinue deepCopy() {
|
||||
if (label == null) return new JsContinue();
|
||||
|
||||
return new JsContinue(AstUtil.deepCopy(label)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript debugger statement.
|
||||
*/
|
||||
public class JsDebugger extends SourceInfoAwareJsNode implements JsStatement {
|
||||
public JsDebugger() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitDebugger(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsDebugger deepCopy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents the default option in a JavaScript swtich statement.
|
||||
*/
|
||||
public final class JsDefault extends JsSwitchMember {
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitDefault(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptStatementList(statements);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsDefault deepCopy() {
|
||||
JsDefault defaultCopy = new JsDefault();
|
||||
defaultCopy.statements.addAll(AstUtil.deepCopy(statements));
|
||||
return defaultCopy.withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript do..while statement.
|
||||
*/
|
||||
public class JsDoWhile extends JsWhile {
|
||||
public JsDoWhile() {
|
||||
}
|
||||
|
||||
public JsDoWhile(JsExpression condition, JsStatement body) {
|
||||
super(condition, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitDoWhile(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
body = v.acceptStatement(body);
|
||||
condition = v.accept(condition);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsDoWhile deepCopy() {
|
||||
JsExpression conditionCopy = AstUtil.deepCopy(condition);
|
||||
JsStatement bodyCopy = AstUtil.deepCopy(body);
|
||||
|
||||
return new JsDoWhile(conditionCopy, bodyCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class JsDocComment extends JsExpression {
|
||||
private final Map<String, Object> tags;
|
||||
|
||||
public JsDocComment(Map<String, Object> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public Map<String, Object> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public JsDocComment(String tagName, JsNameRef tagValue) {
|
||||
tags = Collections.<String, Object>singletonMap(tagName, tagValue);
|
||||
}
|
||||
|
||||
public JsDocComment(String tagName, String tagValue) {
|
||||
tags = Collections.<String, Object>singletonMap(tagName, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitDocComment(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsDocComment deepCopy() {
|
||||
return new JsDocComment(tags).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast
|
||||
|
||||
object JsEmpty : SourceInfoAwareJsNode(), JsStatement {
|
||||
|
||||
override fun accept(v: JsVisitor) {
|
||||
v.visitEmpty(this)
|
||||
}
|
||||
|
||||
override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) {
|
||||
v.visit(this, ctx)
|
||||
v.endVisit(this, ctx)
|
||||
}
|
||||
|
||||
override fun deepCopy(): JsEmpty {
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class JsExpression extends SourceInfoAwareJsNode {
|
||||
/**
|
||||
* Determines whether or not this expression is a leaf, such as a
|
||||
* {@link JsNameRef}, {@link JsLiteral.JsBooleanLiteral}, and so on. Leaf expressions
|
||||
* never need to be parenthesized.
|
||||
*/
|
||||
public boolean isLeaf() {
|
||||
// Conservatively say that it isn't a leaf.
|
||||
// Individual subclasses can speak for themselves if they are a leaf.
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsStatement makeStmt() {
|
||||
return new JsExpressionStatement(this);
|
||||
}
|
||||
|
||||
protected abstract static class JsExpressionHasArguments extends JsExpression implements HasArguments {
|
||||
protected final List<JsExpression> arguments;
|
||||
|
||||
public JsExpressionHasArguments(List<JsExpression> arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JsExpression> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsExpression source(Object info) {
|
||||
setSource(info);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract JsExpression deepCopy();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class JsExpressionStatement extends AbstractNode implements JsStatement {
|
||||
@NotNull
|
||||
private JsExpression expression;
|
||||
|
||||
public JsExpressionStatement(@NotNull JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitExpressionStatement(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSource(Object info) {
|
||||
throw new IllegalStateException("You must not set source info for JsExpressionStatement, set for expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsNode source(Object info) {
|
||||
throw new IllegalStateException("You must not set source info for JsExpressionStatement, set for expression");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
expression = v.accept(expression);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpressionStatement deepCopy() {
|
||||
return new JsExpressionStatement(expression.deepCopy()).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A <code>for</code> statement. If specified at all, the initializer part is
|
||||
* either a declaration of one or more variables, in which case
|
||||
* {@link #getInitVars()} is used, or an expression, in which case
|
||||
* {@link #getInitExpression()} is used. In the latter case, the comma operator is
|
||||
* often used to create a compound expression.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Note that any of the parts of the <code>for</code> loop header can be
|
||||
* <code>null</code>, although the body will never be null.
|
||||
*/
|
||||
public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
|
||||
private JsStatement body;
|
||||
private JsExpression condition;
|
||||
private JsExpression incrementExpression;
|
||||
private JsExpression initExpression;
|
||||
private JsVars initVars;
|
||||
|
||||
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression) {
|
||||
this(initVars, condition, incrementExpression, null);
|
||||
}
|
||||
|
||||
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
|
||||
this.initVars = initVars;
|
||||
this.incrementExpression = incrementExpression;
|
||||
this.condition = condition;
|
||||
this.body = body;
|
||||
initExpression = null;
|
||||
}
|
||||
|
||||
public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression) {
|
||||
this(initExpression, condition, incrementExpression, null);
|
||||
}
|
||||
|
||||
public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
|
||||
this.initExpression = initExpression;
|
||||
this.incrementExpression = incrementExpression;
|
||||
this.condition = condition;
|
||||
this.body = body;
|
||||
initVars = null;
|
||||
}
|
||||
|
||||
public JsStatement getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public JsExpression getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public JsExpression getIncrementExpression() {
|
||||
return incrementExpression;
|
||||
}
|
||||
|
||||
public JsExpression getInitExpression() {
|
||||
return initExpression;
|
||||
}
|
||||
|
||||
public JsVars getInitVars() {
|
||||
return initVars;
|
||||
}
|
||||
|
||||
public void setBody(JsStatement body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitFor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
assert (!(initExpression != null && initVars != null));
|
||||
|
||||
if (initExpression != null) {
|
||||
visitor.accept(initExpression);
|
||||
}
|
||||
else if (initVars != null) {
|
||||
visitor.accept(initVars);
|
||||
}
|
||||
|
||||
if (condition != null) {
|
||||
visitor.accept(condition);
|
||||
}
|
||||
|
||||
if (incrementExpression != null) {
|
||||
visitor.accept(incrementExpression);
|
||||
}
|
||||
visitor.accept(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
assert (!(initExpression != null && initVars != null));
|
||||
|
||||
if (initExpression != null) {
|
||||
initExpression = v.accept(initExpression);
|
||||
} else if (initVars != null) {
|
||||
JsStatement newInitVars = v.<JsStatement>acceptStatement(initVars);
|
||||
if (newInitVars instanceof JsVars) {
|
||||
initVars = (JsVars) newInitVars;
|
||||
}
|
||||
else {
|
||||
initVars = null;
|
||||
if (newInitVars instanceof JsExpressionStatement) {
|
||||
initExpression = ((JsExpressionStatement) newInitVars).getExpression();
|
||||
} else if (newInitVars != null) {
|
||||
ctx.addPrevious(newInitVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (condition != null) {
|
||||
condition = v.accept(condition);
|
||||
}
|
||||
|
||||
if (incrementExpression != null) {
|
||||
incrementExpression = v.accept(incrementExpression);
|
||||
}
|
||||
body = v.acceptStatement(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsFor deepCopy() {
|
||||
JsStatement bodyCopy = AstUtil.deepCopy(body);
|
||||
JsExpression conditionCopy = AstUtil.deepCopy(condition);
|
||||
JsExpression incrementalExprCopy = AstUtil.deepCopy(incrementExpression);
|
||||
|
||||
JsFor result;
|
||||
if (initVars != null) {
|
||||
result = new JsFor(initVars.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
|
||||
} else {
|
||||
result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
|
||||
}
|
||||
|
||||
return result.withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JsForIn extends SourceInfoAwareJsNode implements JsStatement {
|
||||
private JsStatement body;
|
||||
private JsExpression iterExpression;
|
||||
private JsExpression objectExpression;
|
||||
|
||||
// Optional: the name of a new iterator variable to introduce
|
||||
private final JsName iterVarName;
|
||||
|
||||
public JsForIn() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public JsForIn(JsName iterVarName) {
|
||||
this.iterVarName = iterVarName;
|
||||
}
|
||||
|
||||
public JsForIn(JsName iterVarName, JsExpression iterExpression, JsExpression objectExpression, JsStatement body) {
|
||||
|
||||
this.iterVarName = iterVarName;
|
||||
this.iterExpression = iterExpression;
|
||||
this.objectExpression = objectExpression;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public JsStatement getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public JsExpression getIterExpression() {
|
||||
return iterExpression;
|
||||
}
|
||||
|
||||
public JsName getIterVarName() {
|
||||
return iterVarName;
|
||||
}
|
||||
|
||||
public JsExpression getObjectExpression() {
|
||||
return objectExpression;
|
||||
}
|
||||
|
||||
public void setBody(JsStatement body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public void setIterExpression(JsExpression iterExpression) {
|
||||
this.iterExpression = iterExpression;
|
||||
}
|
||||
|
||||
public void setObjectExpression(JsExpression objectExpression) {
|
||||
this.objectExpression = objectExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitForIn(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (iterExpression != null) {
|
||||
visitor.acceptLvalue(iterExpression);
|
||||
}
|
||||
visitor.accept(objectExpression);
|
||||
visitor.accept(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (iterExpression != null) {
|
||||
iterExpression = v.acceptLvalue(iterExpression);
|
||||
}
|
||||
objectExpression = v.accept(objectExpression);
|
||||
body = v.acceptStatement(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsForIn deepCopy() {
|
||||
JsStatement bodyCopy = AstUtil.deepCopy(body);
|
||||
JsExpression iterCopy = AstUtil.deepCopy(iterExpression);
|
||||
JsExpression objectCopy = AstUtil.deepCopy(objectExpression);
|
||||
|
||||
return new JsForIn(iterVarName, iterCopy, objectCopy, bodyCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class JsFunction extends JsLiteral implements HasName {
|
||||
@NotNull
|
||||
private JsBlock body;
|
||||
private List<JsParameter> params;
|
||||
@NotNull
|
||||
private final JsFunctionScope scope;
|
||||
private JsName name;
|
||||
|
||||
public JsFunction(@NotNull JsScope parentScope, @NotNull String description) {
|
||||
this(parentScope, description, null);
|
||||
}
|
||||
|
||||
public JsFunction(@NotNull JsScope parentScope, @NotNull JsBlock body, @NotNull String description) {
|
||||
this(parentScope, description, null);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
private JsFunction(@NotNull JsScope parentScope, @NotNull String description, @Nullable JsName name) {
|
||||
this.name = name;
|
||||
scope = new JsFunctionScope(parentScope, name == null ? description : name.getIdent());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsBlock getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol getSymbol() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JsParameter> getParameters() {
|
||||
if (params == null) {
|
||||
params = new SmartList<JsParameter>();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsFunctionScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setBody(@NotNull JsBlock body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(@Nullable JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitFunction(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(getParameters());
|
||||
visitor.accept(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptList(getParameters());
|
||||
body = v.acceptStatement(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsFunction deepCopy() {
|
||||
JsFunction functionCopy = new JsFunction(scope.getParent(), scope.getDescription(), name);
|
||||
functionCopy.getScope().copyOwnNames(scope);
|
||||
functionCopy.setBody(body.deepCopy());
|
||||
functionCopy.params = AstUtil.deepCopy(params);
|
||||
|
||||
return functionCopy.withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript block in the global scope.
|
||||
*/
|
||||
public class JsGlobalBlock extends JsBlock {
|
||||
|
||||
public JsGlobalBlock() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobalBlock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsGlobalBlock deepCopy() {
|
||||
JsGlobalBlock globalBlockCopy = new JsGlobalBlock();
|
||||
List<JsStatement> statementscopy = AstUtil.deepCopy(getStatements());
|
||||
globalBlockCopy.getStatements().addAll(statementscopy);
|
||||
return globalBlockCopy.withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript if statement.
|
||||
*/
|
||||
public final class JsIf extends SourceInfoAwareJsNode implements JsStatement {
|
||||
@NotNull
|
||||
private JsExpression ifExpression;
|
||||
|
||||
@NotNull
|
||||
private JsStatement thenStatement;
|
||||
|
||||
@Nullable
|
||||
private JsStatement elseStatement;
|
||||
|
||||
public JsIf(@NotNull JsExpression ifExpression, @NotNull JsStatement thenStatement, @Nullable JsStatement elseStatement) {
|
||||
this.ifExpression = ifExpression;
|
||||
this.thenStatement = thenStatement;
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
public JsIf(@NotNull JsExpression ifExpression, @NotNull JsStatement thenStatement) {
|
||||
this(ifExpression, thenStatement, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsStatement getElseStatement() {
|
||||
return elseStatement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getIfExpression() {
|
||||
return ifExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsStatement getThenStatement() {
|
||||
return thenStatement;
|
||||
}
|
||||
|
||||
public void setElseStatement(@Nullable JsStatement elseStatement) {
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
public void setIfExpression(@NotNull JsExpression ifExpression) {
|
||||
this.ifExpression = ifExpression;
|
||||
}
|
||||
|
||||
public void setThenStatement(@NotNull JsStatement thenStatement) {
|
||||
this.thenStatement = thenStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitIf(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(ifExpression);
|
||||
visitor.accept(thenStatement);
|
||||
if (elseStatement != null) {
|
||||
visitor.accept(elseStatement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
ifExpression = v.accept(ifExpression);
|
||||
thenStatement = v.acceptStatement(thenStatement);
|
||||
if (elseStatement != null) {
|
||||
elseStatement = v.acceptStatement(elseStatement);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsIf deepCopy() {
|
||||
JsExpression ifCopy = AstUtil.deepCopy(ifExpression);
|
||||
JsStatement thenCopy = AstUtil.deepCopy(thenStatement);
|
||||
JsStatement elseCopy = AstUtil.deepCopy(elseStatement);
|
||||
|
||||
return new JsIf(ifCopy, thenCopy, elseCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class JsInvocation extends JsExpression.JsExpressionHasArguments {
|
||||
@NotNull
|
||||
private JsExpression qualifier;
|
||||
|
||||
public JsInvocation(@NotNull JsExpression qualifier, @NotNull List<JsExpression> arguments) {
|
||||
super(arguments);
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
public JsInvocation(@NotNull JsExpression qualifier, JsExpression... arguments) {
|
||||
this(qualifier, new SmartList<JsExpression>(arguments));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JsExpression> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getQualifier() {
|
||||
return qualifier;
|
||||
}
|
||||
|
||||
public void setQualifier(@NotNull JsExpression qualifier) {
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitInvocation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(qualifier);
|
||||
visitor.acceptList(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
qualifier = v.accept(qualifier);
|
||||
v.acceptList(arguments);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsInvocation deepCopy() {
|
||||
JsExpression qualifierCopy = AstUtil.deepCopy(qualifier);
|
||||
List<JsExpression> argumentsCopy = AstUtil.deepCopy(arguments);
|
||||
return new JsInvocation(qualifierCopy, argumentsCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript label statement.
|
||||
*/
|
||||
public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasName {
|
||||
private JsName label;
|
||||
|
||||
private JsStatement statement;
|
||||
|
||||
public JsLabel(JsName label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public JsLabel(JsName label, JsStatement statement) {
|
||||
this.label = label;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(JsName name) {
|
||||
label = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol getSymbol() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public JsStatement getStatement() {
|
||||
return statement;
|
||||
}
|
||||
|
||||
public void setStatement(JsStatement statement) {
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitLabel(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
statement = v.acceptStatement(statement);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsLabel deepCopy() {
|
||||
return new JsLabel(label, AstUtil.deepCopy(statement.deepCopy())).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class JsLiteral extends JsExpression {
|
||||
public static final JsValueLiteral THIS = new JsThisRef();
|
||||
public static final JsNameRef UNDEFINED = new JsNameRef("undefined");
|
||||
|
||||
public static final JsNullLiteral NULL = new JsNullLiteral();
|
||||
|
||||
public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(true);
|
||||
public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(false);
|
||||
|
||||
public static JsBooleanLiteral getBoolean(boolean truth) {
|
||||
return truth ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
public static final class JsThisRef extends JsValueLiteral {
|
||||
private JsThisRef() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitThis(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class JsBooleanLiteral extends JsValueLiteral {
|
||||
private final boolean value;
|
||||
|
||||
// Should be interned by JsProgram
|
||||
private JsBooleanLiteral(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitBoolean(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A JavaScript string literal expression.
|
||||
*/
|
||||
public abstract static class JsValueLiteral extends JsLiteral {
|
||||
protected JsValueLiteral() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isLeaf() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression deepCopy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An abstract base class for named JavaScript objects.
|
||||
*/
|
||||
public class JsName extends HasMetadata implements Symbol {
|
||||
private static int ordinalGenerator;
|
||||
private final JsScope enclosing;
|
||||
private final int ordinal;
|
||||
|
||||
@NotNull
|
||||
private final String ident;
|
||||
|
||||
private final boolean temporary;
|
||||
|
||||
/**
|
||||
* @param ident the unmangled ident to use for this name
|
||||
*/
|
||||
JsName(JsScope enclosing, @NotNull String ident, boolean temporary) {
|
||||
this.enclosing = enclosing;
|
||||
this.ident = ident;
|
||||
this.temporary = temporary;
|
||||
ordinal = temporary ? ordinalGenerator++ : 0;
|
||||
}
|
||||
|
||||
public int getOrdinal() {
|
||||
return ordinal;
|
||||
}
|
||||
|
||||
public JsScope getEnclosing() {
|
||||
return enclosing;
|
||||
}
|
||||
|
||||
public boolean isTemporary() {
|
||||
return temporary;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getIdent() {
|
||||
return ident;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsNameRef makeRef() {
|
||||
return new JsNameRef(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ident;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript expression that references a name.
|
||||
*/
|
||||
public final class JsNameRef extends JsExpression implements HasName {
|
||||
private String ident;
|
||||
private JsName name;
|
||||
private JsExpression qualifier;
|
||||
|
||||
public JsNameRef(@NotNull JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public JsNameRef(@NotNull String ident) {
|
||||
this.ident = ident;
|
||||
}
|
||||
|
||||
public JsNameRef(@NotNull String ident, JsExpression qualifier) {
|
||||
this.ident = ident;
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
public JsNameRef(@NotNull String ident, @NotNull String qualifier) {
|
||||
this(ident, new JsNameRef(qualifier));
|
||||
}
|
||||
|
||||
public JsNameRef(@NotNull JsName name, JsExpression qualifier) {
|
||||
this.name = name;
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getIdent() {
|
||||
return (name == null) ? ident : name.getIdent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Symbol getSymbol() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsExpression getQualifier() {
|
||||
return qualifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return qualifier == null;
|
||||
}
|
||||
|
||||
public void resolve(JsName name) {
|
||||
this.name = name;
|
||||
ident = null;
|
||||
}
|
||||
|
||||
public void setQualifier(JsExpression qualifier) {
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitNameRef(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (qualifier != null) {
|
||||
visitor.accept(qualifier);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (qualifier != null) {
|
||||
qualifier = v.accept(qualifier);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsNameRef deepCopy() {
|
||||
JsExpression qualifierCopy = AstUtil.deepCopy(qualifier);
|
||||
|
||||
if (name != null) return new JsNameRef(name, qualifierCopy).withMetadataFrom(this);
|
||||
|
||||
return new JsNameRef(ident, qualifierCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class JsNew extends JsExpression.JsExpressionHasArguments {
|
||||
private JsExpression constructorExpression;
|
||||
|
||||
public JsNew(JsExpression constructorExpression) {
|
||||
this(constructorExpression, new SmartList<JsExpression>());
|
||||
}
|
||||
|
||||
public JsNew(JsExpression constructorExpression, List<JsExpression> arguments) {
|
||||
super(arguments);
|
||||
this.constructorExpression = constructorExpression;
|
||||
}
|
||||
|
||||
public JsExpression getConstructorExpression() {
|
||||
return constructorExpression;
|
||||
}
|
||||
|
||||
public void setConstructorExpression(JsExpression constructorExpression) {
|
||||
this.constructorExpression = constructorExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitNew(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(constructorExpression);
|
||||
visitor.acceptList(arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
constructorExpression = v.accept(constructorExpression);
|
||||
v.acceptList(arguments);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsNew deepCopy() {
|
||||
JsExpression constructorCopy = AstUtil.deepCopy(constructorExpression);
|
||||
List<JsExpression> argumentsCopy = AstUtil.deepCopy(arguments);
|
||||
return new JsNew(constructorCopy, argumentsCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface JsNode {
|
||||
/**
|
||||
* Causes this object to have the visitor visit itself and its children.
|
||||
*
|
||||
* @param visitor the visitor that should traverse this node
|
||||
*/
|
||||
void accept(JsVisitor visitor);
|
||||
|
||||
void acceptChildren(JsVisitor visitor);
|
||||
|
||||
/**
|
||||
* Return the source info associated with this object.
|
||||
*/
|
||||
Object getSource();
|
||||
|
||||
/**
|
||||
* Set the source info associated with this object.
|
||||
*
|
||||
* @param info
|
||||
*/
|
||||
void setSource(Object info);
|
||||
|
||||
JsNode source(Object info);
|
||||
|
||||
@NotNull
|
||||
JsNode deepCopy();
|
||||
|
||||
/**
|
||||
* Causes this object to have the visitor visit itself and its children.
|
||||
*
|
||||
* @param visitor the visitor that should traverse this node
|
||||
* @param ctx the context of an existing traversal
|
||||
*/
|
||||
void traverse(JsVisitorWithContext visitor, JsContext ctx);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public final class JsNullLiteral extends JsLiteral.JsValueLiteral {
|
||||
JsNullLiteral() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitNull(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public abstract class JsNumberLiteral extends JsLiteral.JsValueLiteral {
|
||||
public static final JsIntLiteral ZERO = new JsIntLiteral(0);
|
||||
|
||||
public static final class JsDoubleLiteral extends JsNumberLiteral {
|
||||
public final double value;
|
||||
|
||||
JsDoubleLiteral(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitDouble(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class JsIntLiteral extends JsNumberLiteral {
|
||||
public final int value;
|
||||
|
||||
JsIntLiteral(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitInt(this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class JsObjectLiteral extends JsLiteral {
|
||||
private final List<JsPropertyInitializer> properties;
|
||||
|
||||
private final boolean multiline;
|
||||
|
||||
public JsObjectLiteral() {
|
||||
this(new SmartList<JsPropertyInitializer>());
|
||||
}
|
||||
|
||||
public JsObjectLiteral(boolean multiline) {
|
||||
this(new SmartList<JsPropertyInitializer>(), multiline);
|
||||
}
|
||||
|
||||
public boolean isMultiline() {
|
||||
return multiline;
|
||||
}
|
||||
|
||||
public JsObjectLiteral(List<JsPropertyInitializer> properties) {
|
||||
this(properties, false);
|
||||
}
|
||||
|
||||
public JsObjectLiteral(List<JsPropertyInitializer> properties, boolean multiline) {
|
||||
this.properties = properties;
|
||||
this.multiline = multiline;
|
||||
}
|
||||
|
||||
public List<JsPropertyInitializer> getPropertyInitializers() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitObjectLiteral(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptList(properties);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsObjectLiteral deepCopy() {
|
||||
return new JsObjectLiteral(AstUtil.deepCopy(properties), multiline).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public interface JsOperator {
|
||||
int INFIX = 0x02;
|
||||
int LEFT = 0x01;
|
||||
int POSTFIX = 0x04;
|
||||
int PREFIX = 0x08;
|
||||
|
||||
int getPrecedence();
|
||||
|
||||
String getSymbol();
|
||||
|
||||
boolean isKeyword();
|
||||
|
||||
boolean isLeftAssociative();
|
||||
|
||||
boolean isPrecedenceLessThan(JsOperator other);
|
||||
|
||||
boolean isValidInfix();
|
||||
|
||||
boolean isValidPostfix();
|
||||
|
||||
boolean isValidPrefix();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A JavaScript parameter.
|
||||
*/
|
||||
public final class JsParameter extends SourceInfoAwareJsNode implements HasName {
|
||||
@NotNull
|
||||
private JsName name;
|
||||
|
||||
public JsParameter(@NotNull JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(@NotNull JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Symbol getSymbol() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitParameter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsParameter deepCopy() {
|
||||
return new JsParameter(name).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class JsPostfixOperation extends JsUnaryOperation {
|
||||
public JsPostfixOperation(JsUnaryOperator op, JsExpression arg) {
|
||||
super(op, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitPostfixOperation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
super.traverse(v, ctx);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsPostfixOperation deepCopy() {
|
||||
return new JsPostfixOperation(getOperator(), AstUtil.deepCopy(getArg())).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class JsPrefixOperation extends JsUnaryOperation {
|
||||
public JsPrefixOperation(JsUnaryOperator op, JsExpression arg) {
|
||||
super(op, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitPrefixOperation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
super.traverse(v, ctx);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsPrefixOperation deepCopy() {
|
||||
return new JsPrefixOperation(getOperator(), AstUtil.deepCopy(getArg())).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import gnu.trove.TDoubleObjectHashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsDoubleLiteral;
|
||||
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiteral;
|
||||
|
||||
/**
|
||||
* A JavaScript program.
|
||||
*/
|
||||
public final class JsProgram extends SourceInfoAwareJsNode {
|
||||
|
||||
private JsProgramFragment[] fragments;
|
||||
|
||||
private final TDoubleObjectHashMap<JsDoubleLiteral> doubleLiteralMap = new TDoubleObjectHashMap<JsDoubleLiteral>();
|
||||
private final TIntObjectHashMap<JsIntLiteral> intLiteralMap = new TIntObjectHashMap<JsIntLiteral>();
|
||||
|
||||
private final JsRootScope rootScope;
|
||||
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
|
||||
private final JsObjectScope topScope;
|
||||
|
||||
public JsProgram() {
|
||||
rootScope = new JsRootScope(this);
|
||||
topScope = new JsObjectScope(rootScope, "Global");
|
||||
setFragmentCount(1);
|
||||
}
|
||||
|
||||
public JsBlock getFragmentBlock(int fragment) {
|
||||
if (fragment < 0 || fragment >= fragments.length) {
|
||||
throw new IllegalArgumentException("Invalid fragment: " + fragment);
|
||||
}
|
||||
return fragments[fragment].getGlobalBlock();
|
||||
}
|
||||
|
||||
public JsBlock getGlobalBlock() {
|
||||
return getFragmentBlock(0);
|
||||
}
|
||||
|
||||
public JsNumberLiteral getNumberLiteral(double value) {
|
||||
JsDoubleLiteral literal = doubleLiteralMap.get(value);
|
||||
if (literal == null) {
|
||||
literal = new JsDoubleLiteral(value);
|
||||
doubleLiteralMap.put(value, literal);
|
||||
}
|
||||
|
||||
return literal;
|
||||
}
|
||||
|
||||
public JsNumberLiteral getNumberLiteral(int value) {
|
||||
JsIntLiteral literal = intLiteralMap.get(value);
|
||||
if (literal == null) {
|
||||
literal = new JsIntLiteral(value);
|
||||
intLiteralMap.put(value, literal);
|
||||
}
|
||||
|
||||
return literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the quasi-mythical root scope. This is not the same as the top scope;
|
||||
* all unresolvable identifiers wind up here, because they are considered
|
||||
* external to the program.
|
||||
*/
|
||||
public JsRootScope getRootScope() {
|
||||
return rootScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the top level scope. This is the scope of all the statements in the
|
||||
* main program.
|
||||
*/
|
||||
public JsObjectScope getScope() {
|
||||
return topScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or retrieves a JsStringLiteral from an interned object pool.
|
||||
*/
|
||||
@NotNull
|
||||
public JsStringLiteral getStringLiteral(String value) {
|
||||
JsStringLiteral literal = stringLiteralMap.get(value);
|
||||
if (literal == null) {
|
||||
literal = new JsStringLiteral(value);
|
||||
stringLiteralMap.put(value, literal);
|
||||
}
|
||||
return literal;
|
||||
}
|
||||
|
||||
public void setFragmentCount(int fragments) {
|
||||
this.fragments = new JsProgramFragment[fragments];
|
||||
for (int i = 0; i < fragments; i++) {
|
||||
this.fragments[i] = new JsProgramFragment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitProgram(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
for (JsProgramFragment fragment : fragments) {
|
||||
visitor.accept(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
for (JsProgramFragment fragment : fragments) {
|
||||
v.accept(fragment);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsProgram deepCopy() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* One independently loadable fragment of a {@link JsProgram}.
|
||||
*/
|
||||
public class JsProgramFragment extends SourceInfoAwareJsNode {
|
||||
private final JsGlobalBlock globalBlock;
|
||||
|
||||
public JsProgramFragment() {
|
||||
globalBlock = new JsGlobalBlock();
|
||||
}
|
||||
|
||||
public JsBlock getGlobalBlock() {
|
||||
return globalBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitProgramFragment(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(globalBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptStatement(globalBlock);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsProgramFragment deepCopy() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Used in object literals to specify property values by name.
|
||||
*/
|
||||
public class JsPropertyInitializer extends SourceInfoAwareJsNode {
|
||||
@NotNull
|
||||
private JsExpression labelExpr;
|
||||
@NotNull
|
||||
private JsExpression valueExpr;
|
||||
|
||||
public JsPropertyInitializer(@NotNull JsExpression labelExpr, @NotNull JsExpression valueExpr) {
|
||||
this.labelExpr = labelExpr;
|
||||
this.valueExpr = valueExpr;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getLabelExpr() {
|
||||
return labelExpr;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getValueExpr() {
|
||||
return valueExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitPropertyInitializer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(labelExpr);
|
||||
visitor.accept(valueExpr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
JsExpression newLabel = v.accept(labelExpr);
|
||||
JsExpression newValue = v.accept(valueExpr);
|
||||
assert newLabel != null: "Label cannot be replaced with null";
|
||||
assert newValue != null: "Value cannot be replaced with null";
|
||||
labelExpr = newLabel;
|
||||
valueExpr = newValue;
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsPropertyInitializer deepCopy() {
|
||||
return new JsPropertyInitializer(labelExpr.deepCopy(), valueExpr.deepCopy()).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public final class JsRegExp extends JsLiteral.JsValueLiteral {
|
||||
private String flags;
|
||||
private String pattern;
|
||||
|
||||
public JsRegExp() {
|
||||
}
|
||||
|
||||
public String getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public void setFlags(String suffix) {
|
||||
flags = suffix;
|
||||
}
|
||||
|
||||
public void setPattern(String re) {
|
||||
pattern = re;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitRegExp(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A JavaScript return statement.
|
||||
*/
|
||||
public final class JsReturn extends SourceInfoAwareJsNode implements JsStatement {
|
||||
private JsExpression expression;
|
||||
|
||||
public JsReturn() {
|
||||
}
|
||||
|
||||
public JsReturn(JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public JsExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public void setExpression(JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitReturn(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (expression != null) {
|
||||
visitor.accept(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (expression != null) {
|
||||
expression = v.accept(expression);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsReturn deepCopy() {
|
||||
return new JsReturn(AstUtil.deepCopy(expression)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.backend.js.JsReservedIdentifiers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The root scope is the parent of every scope. All identifiers in this scope
|
||||
* are not obfuscatable. This scope is prefilled with reserved global
|
||||
* JavaScript symbols.
|
||||
*/
|
||||
public final class JsRootScope extends JsScope {
|
||||
private final JsProgram program;
|
||||
|
||||
public JsRootScope(JsProgram program) {
|
||||
super("Root");
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsProgram getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsName findOwnName(@NotNull String ident) {
|
||||
JsName name = super.findOwnName(ident);
|
||||
if (name == null) {
|
||||
if (JsReservedIdentifiers.reservedGlobalSymbols.contains(ident)) {
|
||||
/*
|
||||
* Lazily add JsNames for reserved identifiers. Since a JsName for a reserved global symbol
|
||||
* must report a legitimate enclosing scope, we can't simply have a shared set of symbol
|
||||
* names.
|
||||
*/
|
||||
name = doCreateName(ident);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.Maps;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* A scope is a factory for creating and allocating
|
||||
* {@link JsName}s. A JavaScript AST is
|
||||
* built in terms of abstract name objects without worrying about obfuscation,
|
||||
* keyword/identifier blacklisting, and so on.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Scopes are associated with
|
||||
* {@link JsFunction}s, but the two are
|
||||
* not equivalent. Functions <i>have</i> scopes, but a scope does not
|
||||
* necessarily have an associated Function. Examples of this include the
|
||||
* {@link JsRootScope} and synthetic
|
||||
* scopes that might be created by a client.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Scopes can have parents to provide constraints when allocating actual
|
||||
* identifiers for names. Specifically, names in child scopes are chosen such
|
||||
* that they do not conflict with names in their parent scopes. The ultimate
|
||||
* parent is usually the global scope (see
|
||||
* {@link JsProgram#getRootScope()}),
|
||||
* but parentless scopes are useful for managing names that are always accessed
|
||||
* with a qualifier and could therefore never be confused with the global scope
|
||||
* hierarchy.
|
||||
*/
|
||||
public abstract class JsScope {
|
||||
@NotNull
|
||||
private final String description;
|
||||
private Map<String, JsName> names = Collections.emptyMap();
|
||||
private Map<JsName, Object> temporaryNames;
|
||||
private Set<JsName> readonlyTemporaryNames = null;
|
||||
private final JsScope parent;
|
||||
|
||||
private static final Pattern FRESH_NAME_SUFFIX = Pattern.compile("[\\$_]\\d+$");
|
||||
|
||||
public JsScope(JsScope parent, @NotNull String description) {
|
||||
this.description = description;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
protected JsScope(@NotNull String description) {
|
||||
this.description = description;
|
||||
parent = null;
|
||||
}
|
||||
|
||||
public Set<JsName> getTemporaryNames() {
|
||||
if (temporaryNames == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
if (readonlyTemporaryNames == null) {
|
||||
readonlyTemporaryNames = Collections.unmodifiableSet(temporaryNames.keySet());
|
||||
}
|
||||
return readonlyTemporaryNames;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsScope innerObjectScope(@NotNull String scopeName) {
|
||||
return new JsObjectScope(this, scopeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a name object associated with the specified identifier in this scope,
|
||||
* creating it if necessary.<br/>
|
||||
* If the JsName does not exist yet, a new JsName is created. The identifier,
|
||||
* short name, and original name of the newly created JsName are equal to
|
||||
* the given identifier.
|
||||
*
|
||||
* @param identifier An identifier that is unique within this scope.
|
||||
*/
|
||||
@NotNull
|
||||
public JsName declareName(@NotNull String identifier) {
|
||||
JsName name = findOwnName(identifier);
|
||||
return name != null ? name : doCreateName(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new variable with an unique ident in this scope.
|
||||
* The generated JsName is guaranteed to have an identifier that does not clash with any existing variables in the scope.
|
||||
* Future declarations of variables might however clash with the temporary
|
||||
* (unless they use this function).
|
||||
*/
|
||||
@NotNull
|
||||
public JsName declareFreshName(@NotNull String suggestedName) {
|
||||
assert !suggestedName.isEmpty();
|
||||
String ident = getFreshIdent(suggestedName);
|
||||
return doCreateName(ident);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsName declareTemporaryName(@NotNull String suggestedName) {
|
||||
assert !suggestedName.isEmpty();
|
||||
JsName name = new JsName(this, suggestedName, true);
|
||||
if (temporaryNames == null) {
|
||||
temporaryNames = new WeakHashMap<JsName, Object>();
|
||||
}
|
||||
temporaryNames.put(name, this);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a temporary variable with an unique name in this scope.
|
||||
* The generated temporary is guaranteed to have an identifier (but not short
|
||||
* name) that does not clash with any existing variables in the scope.
|
||||
* Future declarations of variables might however clash with the temporary.
|
||||
*/
|
||||
@NotNull
|
||||
public JsName declareTemporary() {
|
||||
return declareTemporaryName("tmp$");
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find the name object for the specified ident, searching in this
|
||||
* scope, and if not found, in the parent scopes.
|
||||
*
|
||||
* @return <code>null</code> if the identifier has no associated name
|
||||
*/
|
||||
@Nullable
|
||||
public final JsName findName(@NotNull String ident) {
|
||||
JsName name = findOwnName(ident);
|
||||
if (name == null && parent != null) {
|
||||
return parent.findName(ident);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean hasOwnName(@NotNull String name) {
|
||||
return names.containsKey(name);
|
||||
}
|
||||
|
||||
private boolean hasName(@NotNull String name) {
|
||||
return hasOwnName(name) || (parent != null && parent.hasName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent scope of this scope, or <code>null</code> if this is the
|
||||
* root scope.
|
||||
*/
|
||||
public final JsScope getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public JsProgram getProgram() {
|
||||
assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent";
|
||||
return parent.getProgram();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
if (parent != null) {
|
||||
return description + "->" + parent;
|
||||
}
|
||||
else {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
public void copyOwnNames(JsScope other) {
|
||||
names = new HashMap<String, JsName>(names);
|
||||
names.putAll(other.names);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected JsName doCreateName(@NotNull String ident) {
|
||||
JsName name = new JsName(this, ident, false);
|
||||
names = Maps.put(names, ident, name);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find the name object for the specified ident, searching in this
|
||||
* scope only.
|
||||
*
|
||||
* @return <code>null</code> if the identifier has no associated name
|
||||
*/
|
||||
protected JsName findOwnName(@NotNull String ident) {
|
||||
return names.get(ident);
|
||||
}
|
||||
|
||||
/**
|
||||
* During inlining names can be refreshed multiple times,
|
||||
* so "a" becomes "a_0", then becomes "a_0_0"
|
||||
* in case a_0 has been declared in calling scope.
|
||||
*
|
||||
* That's ugly. To resolve it, we rename
|
||||
* clashing names with "[_$]\\d+" suffix,
|
||||
* incrementing last number.
|
||||
*
|
||||
* Fresh name for "a0" should still be "a0_0".
|
||||
*/
|
||||
@NotNull
|
||||
protected String getFreshIdent(@NotNull String suggestedIdent) {
|
||||
char sep = '_';
|
||||
String baseName = suggestedIdent;
|
||||
int counter = 0;
|
||||
|
||||
Matcher matcher = FRESH_NAME_SUFFIX.matcher(suggestedIdent);
|
||||
if (matcher.find()) {
|
||||
String group = matcher.group();
|
||||
baseName = matcher.replaceAll("");
|
||||
sep = group.charAt(0);
|
||||
counter = Integer.valueOf(group.substring(1));
|
||||
}
|
||||
|
||||
String freshName = suggestedIdent;
|
||||
while (hasName(freshName)) {
|
||||
freshName = baseName + sep + counter++;
|
||||
}
|
||||
|
||||
return freshName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface JsStatement extends JsNode {
|
||||
@NotNull
|
||||
@Override
|
||||
JsStatement deepCopy();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public final class JsStringLiteral extends JsLiteral.JsValueLiteral {
|
||||
|
||||
private final String value;
|
||||
|
||||
// These only get created by JsProgram so that they can be interned.
|
||||
JsStringLiteral(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitString(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
v.visit(this, ctx);
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A JavaScript switch statement.
|
||||
*/
|
||||
public class JsSwitch extends SourceInfoAwareJsNode implements JsStatement {
|
||||
|
||||
private final List<JsSwitchMember> cases;
|
||||
private JsExpression expression;
|
||||
|
||||
public JsSwitch() {
|
||||
super();
|
||||
cases = new ArrayList<JsSwitchMember>();
|
||||
}
|
||||
|
||||
public JsSwitch(JsExpression expression, List<JsSwitchMember> cases) {
|
||||
this.expression = expression;
|
||||
this.cases = cases;
|
||||
}
|
||||
|
||||
public List<JsSwitchMember> getCases() {
|
||||
return cases;
|
||||
}
|
||||
|
||||
public JsExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public void setExpression(JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(expression);
|
||||
visitor.acceptWithInsertRemove(cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
expression = v.accept(expression);
|
||||
v.acceptList(cases);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsSwitch deepCopy() {
|
||||
JsExpression expressionCopy = AstUtil.deepCopy(expression);
|
||||
List<JsSwitchMember> casesCopy = AstUtil.deepCopy(cases);
|
||||
|
||||
return new JsSwitch(expressionCopy, casesCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A member/case in a JavaScript switch object.
|
||||
*/
|
||||
public abstract class JsSwitchMember extends SourceInfoAwareJsNode {
|
||||
protected final List<JsStatement> statements = new SmartList<JsStatement>();
|
||||
|
||||
protected JsSwitchMember() {
|
||||
super();
|
||||
}
|
||||
|
||||
public List<JsStatement> getStatements() {
|
||||
return statements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(statements);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract JsSwitchMember deepCopy();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JsThrow extends SourceInfoAwareJsNode implements JsStatement {
|
||||
private JsExpression expression;
|
||||
|
||||
public JsThrow() {
|
||||
}
|
||||
|
||||
public JsThrow(JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public JsExpression getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public void setExpression(JsExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitThrow(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
expression = v.accept(expression);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsThrow deepCopy() {
|
||||
return new JsThrow(AstUtil.deepCopy(expression)).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>try</code> statement.
|
||||
*/
|
||||
public class JsTry extends SourceInfoAwareJsNode implements JsStatement {
|
||||
private final List<JsCatch> catches;
|
||||
private JsBlock finallyBlock;
|
||||
private JsBlock tryBlock;
|
||||
|
||||
public JsTry() {
|
||||
catches = new SmartList<JsCatch>();
|
||||
}
|
||||
|
||||
public JsTry(JsBlock tryBlock, List<JsCatch> catches, @Nullable JsBlock finallyBlock) {
|
||||
this.tryBlock = tryBlock;
|
||||
this.catches = catches;
|
||||
this.finallyBlock = finallyBlock;
|
||||
}
|
||||
|
||||
public JsTry(JsBlock tryBlock, @Nullable JsCatch jsCatch, @Nullable JsBlock finallyBlock) {
|
||||
this(tryBlock, new SmartList<JsCatch>(), finallyBlock);
|
||||
|
||||
if (jsCatch != null) {
|
||||
catches.add(jsCatch);
|
||||
}
|
||||
}
|
||||
|
||||
public List<JsCatch> getCatches() {
|
||||
return catches;
|
||||
}
|
||||
|
||||
public JsBlock getFinallyBlock() {
|
||||
return finallyBlock;
|
||||
}
|
||||
|
||||
public JsBlock getTryBlock() {
|
||||
return tryBlock;
|
||||
}
|
||||
|
||||
public void setFinallyBlock(JsBlock block) {
|
||||
finallyBlock = block;
|
||||
}
|
||||
|
||||
public void setTryBlock(JsBlock block) {
|
||||
tryBlock = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitTry(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(tryBlock);
|
||||
visitor.acceptWithInsertRemove(catches);
|
||||
if (finallyBlock != null) {
|
||||
visitor.accept(finallyBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
tryBlock = v.acceptStatement(tryBlock);
|
||||
v.acceptList(catches);
|
||||
if (finallyBlock != null) {
|
||||
finallyBlock = v.acceptStatement(finallyBlock);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsTry deepCopy() {
|
||||
JsBlock tryCopy = AstUtil.deepCopy(tryBlock);
|
||||
List<JsCatch> catchCopy = AstUtil.deepCopy(catches);
|
||||
JsBlock finallyCopy = AstUtil.deepCopy(finallyBlock);
|
||||
|
||||
return new JsTry(tryCopy, catchCopy, finallyCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public abstract class JsUnaryOperation extends JsExpression {
|
||||
|
||||
private JsExpression arg;
|
||||
|
||||
private final JsUnaryOperator op;
|
||||
|
||||
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
|
||||
super();
|
||||
this.op = op;
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
public JsExpression getArg() {
|
||||
return arg;
|
||||
}
|
||||
|
||||
public JsUnaryOperator getOperator() {
|
||||
return op;
|
||||
}
|
||||
|
||||
public void setArg(JsExpression arg) {
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (op.isModifying()) {
|
||||
// The delete operator is practically like an assignment of undefined, so
|
||||
// for practical purposes we're treating it as an lvalue.
|
||||
visitor.acceptLvalue(arg);
|
||||
}
|
||||
else {
|
||||
visitor.accept(arg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (op.isModifying()) {
|
||||
/*
|
||||
* The delete operator is practically like an assignment of undefined, so for practical
|
||||
* purposes we're treating it as an lvalue.
|
||||
*/
|
||||
arg = v.acceptLvalue(arg);
|
||||
} else {
|
||||
arg = v.accept(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* A JavaScript unary operator.
|
||||
*/
|
||||
public enum JsUnaryOperator implements JsOperator {
|
||||
|
||||
/*
|
||||
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
|
||||
* (page 57)
|
||||
*/
|
||||
BIT_NOT("~", 14, PREFIX), DEC("--", 14, POSTFIX | PREFIX), DELETE("delete", 14, PREFIX), INC(
|
||||
"++", 14, POSTFIX | PREFIX), NEG("-", 14, PREFIX), POS("+", 14, PREFIX),
|
||||
NOT("!", 14, PREFIX), TYPEOF("typeof", 14, PREFIX), VOID("void", 14, PREFIX);
|
||||
|
||||
private final int mask;
|
||||
private final int precedence;
|
||||
private final String symbol;
|
||||
|
||||
private JsUnaryOperator(String symbol, int precedence, int mask) {
|
||||
this.symbol = symbol;
|
||||
this.precedence = precedence;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKeyword() {
|
||||
return this == DELETE || this == TYPEOF || this == VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeftAssociative() {
|
||||
return (mask & LEFT) != 0;
|
||||
}
|
||||
|
||||
public boolean isModifying() {
|
||||
return this == DEC || this == INC || this == DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrecedenceLessThan(JsOperator other) {
|
||||
return precedence < other.getPrecedence();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInfix() {
|
||||
return (mask & INFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPostfix() {
|
||||
return (mask & POSTFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPrefix() {
|
||||
return (mask & PREFIX) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.common.Symbol;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>var</code> statement.
|
||||
*/
|
||||
public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterable<JsVars.JsVar> {
|
||||
private final List<JsVar> vars;
|
||||
|
||||
private final boolean multiline;
|
||||
|
||||
public JsVars() {
|
||||
this(new SmartList<JsVar>(), false);
|
||||
}
|
||||
|
||||
public JsVars(boolean multiline) {
|
||||
this(new SmartList<JsVar>(), multiline);
|
||||
}
|
||||
|
||||
public JsVars(List<JsVar> vars, boolean multiline) {
|
||||
this.vars = vars;
|
||||
this.multiline = multiline;
|
||||
}
|
||||
|
||||
public JsVars(JsVar var) {
|
||||
this(new SmartList<JsVar>(var), false);
|
||||
}
|
||||
|
||||
public JsVars(JsVar... vars) {
|
||||
this(new SmartList<JsVar>(vars), false);
|
||||
}
|
||||
|
||||
public boolean isMultiline() {
|
||||
return multiline;
|
||||
}
|
||||
|
||||
/**
|
||||
* A var declared using the JavaScript <code>var</code> statement.
|
||||
*/
|
||||
public static class JsVar extends SourceInfoAwareJsNode implements HasName {
|
||||
private JsName name;
|
||||
private JsExpression initExpression;
|
||||
|
||||
public JsVar(JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public JsVar(JsName name, @Nullable JsExpression initExpression) {
|
||||
this.name = name;
|
||||
this.initExpression = initExpression;
|
||||
}
|
||||
|
||||
public JsExpression getInitExpression() {
|
||||
return initExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol getSymbol() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setInitExpression(JsExpression initExpression) {
|
||||
this.initExpression = initExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
if (initExpression != null) {
|
||||
visitor.accept(initExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (initExpression != null) {
|
||||
initExpression = v.accept(initExpression);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsVar deepCopy() {
|
||||
if (initExpression == null) return new JsVar(name);
|
||||
|
||||
return new JsVar(name, initExpression.deepCopy()).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(JsVar var) {
|
||||
vars.add(var);
|
||||
}
|
||||
|
||||
public void addAll(Collection<? extends JsVars.JsVar> vars) {
|
||||
this.vars.addAll(vars);
|
||||
}
|
||||
|
||||
public void addAll(JsVars otherVars) {
|
||||
this.vars.addAll(otherVars.vars);
|
||||
}
|
||||
|
||||
public void addIfHasInitializer(JsVar var) {
|
||||
if (var.getInitExpression() != null) {
|
||||
add(var);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return vars.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<JsVar> iterator() {
|
||||
return vars.iterator();
|
||||
}
|
||||
|
||||
public List<JsVar> getVars() {
|
||||
return vars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitVars(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.acceptWithInsertRemove(vars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptList(vars);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsVars deepCopy() {
|
||||
return new JsVars(AstUtil.deepCopy(vars), multiline).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar
|
||||
|
||||
abstract class JsVisitor {
|
||||
open fun <T : JsNode?> accept(node: T) {
|
||||
node?.accept(this)
|
||||
}
|
||||
|
||||
fun <T : JsNode> acceptList(collection: List<T>) {
|
||||
for (node in collection) {
|
||||
accept(node)
|
||||
}
|
||||
}
|
||||
|
||||
fun acceptLvalue(expression: JsExpression) {
|
||||
accept(expression)
|
||||
}
|
||||
|
||||
fun <T : JsNode> acceptWithInsertRemove(collection: List<T>) {
|
||||
for (node in collection) {
|
||||
accept(node)
|
||||
}
|
||||
}
|
||||
|
||||
open fun visitArrayAccess(x: JsArrayAccess): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitArray(x: JsArrayLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitBinaryExpression(x: JsBinaryOperation): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitBlock(x: JsBlock): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitBoolean(x: JsLiteral.JsBooleanLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitBreak(x: JsBreak): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitCase(x: JsCase): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitCatch(x: JsCatch): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitConditional(x: JsConditional): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitContinue(x: JsContinue): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitDebugger(x: JsDebugger): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitDefault(x: JsDefault): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitDoWhile(x: JsDoWhile): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitEmpty(x: JsEmpty): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitExpressionStatement(x: JsExpressionStatement): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitFor(x: JsFor): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitForIn(x: JsForIn): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitFunction(x: JsFunction): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitIf(x: JsIf): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitInvocation(invocation: JsInvocation): Unit =
|
||||
visitElement(invocation)
|
||||
|
||||
open fun visitLabel(x: JsLabel): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitNameRef(nameRef: JsNameRef): Unit =
|
||||
visitElement(nameRef)
|
||||
|
||||
open fun visitNew(x: JsNew): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitNull(x: JsNullLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitInt(x: JsNumberLiteral.JsIntLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitDouble(x: JsNumberLiteral.JsDoubleLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitObjectLiteral(x: JsObjectLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitParameter(x: JsParameter): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitPostfixOperation(x: JsPostfixOperation): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitPrefixOperation(x: JsPrefixOperation): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitProgram(x: JsProgram): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitProgramFragment(x: JsProgramFragment): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitPropertyInitializer(x: JsPropertyInitializer): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitRegExp(x: JsRegExp): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitReturn(x: JsReturn): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitString(x: JsStringLiteral): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visit(x: JsSwitch): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitThis(x: JsLiteral.JsThisRef): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitThrow(x: JsThrow): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitTry(x: JsTry): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visit(x: JsVar): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitVars(x: JsVars): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitWhile(x: JsWhile): Unit =
|
||||
visitElement(x)
|
||||
|
||||
open fun visitDocComment(comment: JsDocComment): Unit =
|
||||
visitElement(comment)
|
||||
|
||||
protected open fun visitElement(node: JsNode) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Taken from GWT project with modifications.
|
||||
* Original:
|
||||
* repository: https://gwt.googlesource.com/gwt
|
||||
* revision: e32bf0a95029165d9e6ab457c7ee7ca8b07b908c
|
||||
* file: dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
|
||||
*/
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implemented by nodes that will visit child nodes.
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public abstract class JsVisitorWithContext {
|
||||
|
||||
public final <T extends JsNode> T accept(T node) {
|
||||
if (node == null) return null;
|
||||
|
||||
return doAccept(node);
|
||||
}
|
||||
|
||||
public JsExpression acceptLvalue(JsExpression expr) {
|
||||
if (expr == null) return null;
|
||||
|
||||
return doAcceptLvalue(expr);
|
||||
}
|
||||
|
||||
public final <T extends JsNode> void acceptList(List<T> collection) {
|
||||
doAcceptList(collection);
|
||||
}
|
||||
|
||||
public final <T extends JsStatement> T acceptStatement(T statement) {
|
||||
if (statement == null) return null;
|
||||
|
||||
//noinspection unchecked
|
||||
return (T) doAcceptStatement(statement);
|
||||
}
|
||||
|
||||
public final void acceptStatementList(List<JsStatement> statements) {
|
||||
doAcceptStatementList(statements);
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsArrayAccess x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsArrayLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsBinaryOperation x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsBlock x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsLiteral.JsBooleanLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsBreak x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsCase x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsCatch x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsConditional x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsContinue x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsDebugger x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsDefault x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsDoWhile x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsEmpty x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsExpressionStatement x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsFor x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsForIn x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsFunction x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsIf x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsInvocation x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsLabel x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsName x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsNameRef x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsNew x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsNullLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsNumberLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsObjectLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsParameter x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsPostfixOperation x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsPrefixOperation x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsProgram x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsProgramFragment x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsPropertyInitializer x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsRegExp x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsReturn x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsStringLiteral x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsSwitch x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsLiteral.JsThisRef x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsThrow x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsTry x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsVars.JsVar x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsVars x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(@NotNull JsWhile x, @NotNull JsContext ctx) {
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsArrayAccess x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsArrayLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsBinaryOperation x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsBlock x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsLiteral.JsBooleanLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsBreak x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsCase x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsCatch x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsConditional x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsContinue x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsDebugger x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsDefault x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsDoWhile x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsEmpty x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsExpressionStatement x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsFor x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsForIn x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsFunction x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsIf x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsInvocation x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsLabel x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsName x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsNameRef x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsNew x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsNullLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsNumberLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsObjectLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsParameter x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsPostfixOperation x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsPrefixOperation x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsProgram x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsProgramFragment x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsPropertyInitializer x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsRegExp x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsReturn x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsStringLiteral x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsSwitch x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsLiteral.JsThisRef x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsThrow x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsTry x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsVars.JsVar x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsVars x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(@NotNull JsWhile x, @NotNull JsContext ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract <T extends JsNode> T doAccept(T node);
|
||||
|
||||
protected abstract JsExpression doAcceptLvalue(JsExpression expr);
|
||||
|
||||
protected abstract <T extends JsNode> void doAcceptList(List<T> collection);
|
||||
|
||||
protected abstract <T extends JsStatement> JsStatement doAcceptStatement(T statement);
|
||||
|
||||
protected abstract void doAcceptStatementList(List<JsStatement> statements);
|
||||
|
||||
protected abstract <T extends JsNode> void doTraverse(T node, JsContext ctx) ;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Taken from GWT project with modifications.
|
||||
* Original:
|
||||
* repository: https://gwt.googlesource.com/gwt
|
||||
* revision: e32bf0a95029165d9e6ab457c7ee7ca8b07b908c
|
||||
* file: dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
|
||||
*/
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A visitor for iterating through and modifying an AST.
|
||||
*/
|
||||
public class JsVisitorWithContextImpl extends JsVisitorWithContext {
|
||||
|
||||
private final Stack<JsContext<JsStatement>> statementContexts = new Stack<JsContext<JsStatement>>();
|
||||
|
||||
public class ListContext<T extends JsNode> extends JsContext<T> {
|
||||
private List<T> nodes;
|
||||
private int index;
|
||||
|
||||
// Those are reset in every iteration of traverse()
|
||||
private final List<T> previous = new SmartList<T>();
|
||||
private final List<T> next = new SmartList<T>();
|
||||
private boolean removed = false;
|
||||
|
||||
@Override
|
||||
public <R extends T> void addPrevious(R node) {
|
||||
previous.add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends T> void addNext(R node) {
|
||||
next.add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMe() {
|
||||
removed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends T> void replaceMe(R node) {
|
||||
checkReplacement(nodes.get(index), node);
|
||||
nodes.set(index, node);
|
||||
removed = false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T getCurrentNode() {
|
||||
if (!removed && index < nodes.size()) {
|
||||
return nodes.get(index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void traverse(List<T> nodes) {
|
||||
assert previous.isEmpty(): "addPrevious() was called before traverse()";
|
||||
assert next.isEmpty(): "addNext() was called before traverse()";
|
||||
this.nodes = nodes;
|
||||
|
||||
for (index = 0; index < nodes.size(); index++) {
|
||||
removed = false;
|
||||
previous.clear();
|
||||
next.clear();
|
||||
doTraverse(getCurrentNode(), this);
|
||||
|
||||
if (!previous.isEmpty()) {
|
||||
nodes.addAll(index, previous);
|
||||
index += previous.size();
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
nodes.remove(index);
|
||||
index--;
|
||||
}
|
||||
|
||||
if (!next.isEmpty()) {
|
||||
nodes.addAll(index + 1, next);
|
||||
index += next.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LvalueContext extends NodeContext<JsExpression> {
|
||||
}
|
||||
|
||||
private class NodeContext<T extends JsNode> extends JsContext<T> {
|
||||
protected T node;
|
||||
|
||||
@Override
|
||||
public void removeMe() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends T> void replaceMe(R node) {
|
||||
checkReplacement(this.node, node);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T getCurrentNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
protected T traverse(T node) {
|
||||
this.node = node;
|
||||
doTraverse(node, this);
|
||||
return this.node;
|
||||
}
|
||||
}
|
||||
|
||||
protected static void checkReplacement(@SuppressWarnings("UnusedParameters") JsNode origNode, JsNode newNode) {
|
||||
if (newNode == null) throw new RuntimeException("Cannot replace with null");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsNode> T doAccept(T node) {
|
||||
return new NodeContext<T>().traverse(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsExpression doAcceptLvalue(JsExpression expr) {
|
||||
return new LvalueContext().traverse(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsStatement> JsStatement doAcceptStatement(T statement) {
|
||||
List<JsStatement> statements = new SmartList<JsStatement>(statement);
|
||||
doAcceptStatementList(statements);
|
||||
|
||||
if (statements.size() == 1) {
|
||||
return statements.get(0);
|
||||
}
|
||||
|
||||
return new JsBlock(statements);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAcceptStatementList(List<JsStatement> statements) {
|
||||
ListContext<JsStatement> context = new ListContext<JsStatement>();
|
||||
statementContexts.push(context);
|
||||
context.traverse(statements);
|
||||
statementContexts.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsNode> void doAcceptList(List<T> collection) {
|
||||
new ListContext<T>().traverse(collection);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected JsContext<JsStatement> getLastStatementLevelContext() {
|
||||
return statementContexts.peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsNode> void doTraverse(T node, JsContext ctx) {
|
||||
node.traverse(this, ctx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>while</code> statement.
|
||||
*/
|
||||
public class JsWhile extends SourceInfoAwareJsNode implements JsStatement {
|
||||
protected JsStatement body;
|
||||
protected JsExpression condition;
|
||||
|
||||
public JsWhile() {
|
||||
}
|
||||
|
||||
public JsWhile(JsExpression condition, JsStatement body) {
|
||||
this.condition = condition;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public JsStatement getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public JsExpression getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public void setBody(JsStatement body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public void setCondition(JsExpression condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JsVisitor v) {
|
||||
v.visitWhile(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
visitor.accept(condition);
|
||||
visitor.accept(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitorWithContext v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
condition = v.accept(condition);
|
||||
body = v.acceptStatement(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsWhile deepCopy() {
|
||||
JsExpression conditionCopy = AstUtil.deepCopy(condition);
|
||||
JsStatement bodyCopy = AstUtil.deepCopy(body);
|
||||
|
||||
return new JsWhile(conditionCopy, bodyCopy).withMetadataFrom(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class RecursiveJsVisitor extends JsVisitor {
|
||||
@Override
|
||||
protected void visitElement(@NotNull JsNode node) {
|
||||
node.acceptChildren(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
public abstract class SourceInfoAwareJsNode extends AbstractNode {
|
||||
private Object source;
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSource(Object info) {
|
||||
source = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptChildren(JsVisitor visitor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsNode source(Object info) {
|
||||
source = info;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast
|
||||
|
||||
import java.util.Stack
|
||||
|
||||
class JsObjectScope(parent: JsScope, description: String) : JsScope(parent, description)
|
||||
|
||||
object JsDynamicScope : JsScope(null, "Scope for dynamic declarations") {
|
||||
override fun doCreateName(name: String) = JsName(this, name, false)
|
||||
}
|
||||
|
||||
open class JsFunctionScope(parent: JsScope, description: String) : JsScope(parent, description) {
|
||||
|
||||
private val labelScopes = Stack<LabelScope>()
|
||||
private val topLabelScope: LabelScope?
|
||||
get() = if (labelScopes.isNotEmpty()) labelScopes.peek() else null
|
||||
|
||||
override fun hasOwnName(name: String): Boolean = RESERVED_WORDS.contains(name) || super.hasOwnName(name)
|
||||
|
||||
open fun declareNameUnsafe(identifier: String): JsName = super.declareName(identifier)
|
||||
|
||||
open fun enterLabel(label: String): JsName {
|
||||
val scope = LabelScope(topLabelScope, label)
|
||||
labelScopes.push(scope)
|
||||
return scope.labelName
|
||||
}
|
||||
|
||||
open fun exitLabel() {
|
||||
assert(labelScopes.isNotEmpty()) { "No scope to exit from" }
|
||||
labelScopes.pop()
|
||||
}
|
||||
|
||||
open fun findLabel(label: String): JsName? =
|
||||
topLabelScope?.findName(label)
|
||||
|
||||
private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident") {
|
||||
val labelName: JsName
|
||||
|
||||
init {
|
||||
val freshIdent = when {
|
||||
ident in RESERVED_WORDS -> getFreshIdent(ident)
|
||||
parent != null -> parent.getFreshIdent(ident)
|
||||
else -> ident
|
||||
}
|
||||
|
||||
labelName = JsName(this@JsFunctionScope, freshIdent, false)
|
||||
}
|
||||
|
||||
override fun findOwnName(name: String): JsName? =
|
||||
if (name == ident) labelName else null
|
||||
|
||||
/**
|
||||
* Safe call is necessary, because hasOwnName can be called
|
||||
* in constructor before labelName is initialized (see KT-4394)
|
||||
*/
|
||||
@Suppress("UNNECESSARY_SAFE_CALL")
|
||||
override fun hasOwnName(name: String): Boolean =
|
||||
name in RESERVED_WORDS
|
||||
|| name == ident
|
||||
|| name == labelName?.ident
|
||||
|| parent?.hasOwnName(name) ?: false
|
||||
}
|
||||
|
||||
companion object {
|
||||
val RESERVED_WORDS: Set<String> = setOf(
|
||||
// keywords
|
||||
"await", "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else", "finally", "for", "function", "if",
|
||||
"in", "instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with",
|
||||
|
||||
// future reserved words
|
||||
"class", "const", "enum", "export", "extends", "import", "super",
|
||||
|
||||
// as future reserved words in strict mode
|
||||
"implements", "interface", "let", "package", "private", "protected", "public", "static", "yield",
|
||||
|
||||
// additional reserved words
|
||||
"null", "true", "false",
|
||||
|
||||
// disallowed as variable names in strict mode
|
||||
"eval", "arguments",
|
||||
|
||||
// global identifiers usually declared in a typical JS interpreter
|
||||
"NaN", "isNaN", "Infinity", "undefined",
|
||||
"Error", "Object", "Math", "String", "Number", "Boolean", "Date", "Array", "RegExp", "JSON",
|
||||
|
||||
// global identifiers usually declared in know environments (node.js, browser, require.js, WebWorkers, etc)
|
||||
"require", "define", "module", "window", "self",
|
||||
|
||||
// the special Kotlin object
|
||||
"Kotlin"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class DelegatingJsFunctionScopeWithTemporaryParent(
|
||||
private val delegatingScope: JsFunctionScope,
|
||||
parent: JsScope
|
||||
) : JsFunctionScope(parent, "<delegating scope to delegatingScope>") {
|
||||
|
||||
override fun hasOwnName(name: String): Boolean =
|
||||
delegatingScope.hasOwnName(name)
|
||||
|
||||
override fun findOwnName(ident: String): JsName? =
|
||||
delegatingScope.findOwnName(ident)
|
||||
|
||||
override fun declareNameUnsafe(identifier: String): JsName =
|
||||
delegatingScope.declareNameUnsafe(identifier)
|
||||
|
||||
override fun declareName(identifier: String): JsName =
|
||||
delegatingScope.declareName(identifier)
|
||||
|
||||
override fun declareFreshName(suggestedName: String): JsName =
|
||||
delegatingScope.declareFreshName(suggestedName)
|
||||
|
||||
override fun declareTemporary(): JsName =
|
||||
delegatingScope.declareTemporary()
|
||||
|
||||
override fun enterLabel(label: String): JsName =
|
||||
delegatingScope.enterLabel(label)
|
||||
|
||||
override fun exitLabel() =
|
||||
delegatingScope.exitLabel()
|
||||
|
||||
override fun findLabel(label: String): JsName? =
|
||||
delegatingScope.findLabel(label)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast.metadata
|
||||
|
||||
abstract class HasMetadata {
|
||||
private val metadata: MutableMap<String, Any?> = hashMapOf()
|
||||
|
||||
fun <T> getData(key: String): T {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return metadata[key] as T
|
||||
}
|
||||
|
||||
fun <T> setData(key: String, value: T) {
|
||||
metadata[key] = value
|
||||
}
|
||||
|
||||
fun hasData(key: String): Boolean {
|
||||
return metadata.containsKey(key)
|
||||
}
|
||||
|
||||
fun removeData(key: String) {
|
||||
metadata.remove(key)
|
||||
}
|
||||
|
||||
fun copyMetadataFrom(other: HasMetadata) {
|
||||
metadata.putAll(other.metadata)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast.metadata
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class MetadataProperty<in T : HasMetadata, R>(val default: R) {
|
||||
operator fun getValue(thisRef: T, desc: KProperty<*>): R {
|
||||
if (!thisRef.hasData(desc.name)) return default
|
||||
return thisRef.getData<R>(desc.name)
|
||||
}
|
||||
|
||||
operator fun setValue(thisRef: T, desc: KProperty<*>, value: R) {
|
||||
thisRef.setData(desc.name, value)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@file:JvmName("MetadataProperties")
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast.metadata
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
var JsName.staticRef: JsNode? by MetadataProperty(default = null)
|
||||
|
||||
// TODO: move this to module 'js.inliner' and change dependency on 'frontend' to dependency on 'descriptors'
|
||||
var JsInvocation.inlineStrategy: InlineStrategy? by MetadataProperty(default = null)
|
||||
|
||||
var JsInvocation.descriptor: CallableDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
var JsInvocation.psiElement: PsiElement? by MetadataProperty(default = null)
|
||||
|
||||
var JsNameRef.inlineStrategy: InlineStrategy? by MetadataProperty(default = null)
|
||||
|
||||
var JsNameRef.descriptor: CallableDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
var JsNameRef.psiElement: PsiElement? by MetadataProperty(default = null)
|
||||
|
||||
var JsFunction.isLocal: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var JsInvocation.typeCheck: TypeCheck? by MetadataProperty(default = null)
|
||||
|
||||
/**
|
||||
* For function and lambda bodies indicates what declaration corresponds to.
|
||||
* When absent (`null`) on body of a named function, this function is from external JS module.
|
||||
*/
|
||||
var JsFunction.functionDescriptor: FunctionDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
/**
|
||||
* For return statement specifies corresponding target descriptor given by [functionDescriptor].
|
||||
* For all JsReturn nodes created by K2JSTranslator, this property is filled, either for local/non-local labeled and non-labeled returns.
|
||||
*
|
||||
* Absence of this property (expressed as `null`) means that the corresponding JsReturn got from external JS library.
|
||||
* In this case we assume that such return can never be non-local.
|
||||
*/
|
||||
var JsReturn.returnTarget: FunctionDescriptor? by MetadataProperty(default = null)
|
||||
|
||||
var HasMetadata.synthetic: Boolean by MetadataProperty(default = false)
|
||||
|
||||
var HasMetadata.sideEffects: SideEffectKind by MetadataProperty(default = SideEffectKind.AFFECTS_STATE)
|
||||
|
||||
var JsFunction.coroutineType: KotlinType? by MetadataProperty(default = null)
|
||||
|
||||
/**
|
||||
* Denotes a suspension call-site that is to be processed by coroutine transformer.
|
||||
* More clearly, denotes invocation that should immediately return from coroutine state machine
|
||||
*/
|
||||
var JsInvocation.isSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a pre-suspend call-site that is to be processed by coroutine transformer.
|
||||
* For normal suspend call-sites both [isSuspend] and [isPreSuspend] present.
|
||||
* For inlined suspend calls fake calls are generated before and after inlined function body.
|
||||
*/
|
||||
var JsInvocation.isPreSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a fake suspend call for inlining purposes.
|
||||
*/
|
||||
var JsInvocation.isFakeSuspend: Boolean by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a reference to coroutine's `result` field that contains result of
|
||||
* last suspended invocation.
|
||||
*/
|
||||
var JsNameRef.coroutineResult by MetadataProperty(default = false)
|
||||
|
||||
/**
|
||||
* Denotes a reference to coroutine's `interceptor` field that contains coroutines's interceptor
|
||||
*/
|
||||
var JsNameRef.coroutineController by MetadataProperty(default = false)
|
||||
|
||||
var JsName.imported by MetadataProperty(default = false)
|
||||
|
||||
var JsFunction.coroutineMetadata: CoroutineMetadata? by MetadataProperty(default = null)
|
||||
|
||||
class CoroutineMetadata(
|
||||
val doResumeName: JsName,
|
||||
val resumeName: JsName,
|
||||
val stateName: JsName,
|
||||
val exceptionStateName: JsName,
|
||||
val finallyPathName: JsName,
|
||||
val resultName: JsName,
|
||||
val exceptionName: JsName,
|
||||
val facadeName: JsName,
|
||||
val baseClassRef: JsExpression,
|
||||
val suspendObjectRef: JsExpression,
|
||||
val hasController: Boolean
|
||||
)
|
||||
|
||||
enum class TypeCheck {
|
||||
TYPEOF,
|
||||
INSTANCEOF,
|
||||
OR_NULL,
|
||||
AND_PREDICATE
|
||||
}
|
||||
|
||||
enum class SideEffectKind {
|
||||
AFFECTS_STATE,
|
||||
DEPENDS_ON_STATE,
|
||||
PURE
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.common;
|
||||
|
||||
public interface HasSymbol {
|
||||
/**
|
||||
* @return Return the original user visible name for a Object represented
|
||||
* in a source map.
|
||||
*/
|
||||
Symbol getSymbol();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.common;
|
||||
|
||||
import com.google.dart.compiler.Source;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Tracks file and line information for AST nodes.
|
||||
*/
|
||||
public interface SourceInfo extends Serializable {
|
||||
|
||||
/**
|
||||
* The source code provider.
|
||||
*/
|
||||
Source getSource();
|
||||
|
||||
/**
|
||||
* @return A 1-based line number into the original source file indicating
|
||||
* where the source fragment begins.
|
||||
*/
|
||||
int getLine();
|
||||
|
||||
/**
|
||||
* @return A 1-based column number into the original source file indicating
|
||||
* where the source fragment begins.
|
||||
*/
|
||||
int getColumn();
|
||||
|
||||
/**
|
||||
* Returns the character index into the original source file indicating
|
||||
* where the source fragment corresponding to this node begins.
|
||||
*
|
||||
* <p>
|
||||
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
||||
*
|
||||
* @return the 0-based character index, or <code>-1</code>
|
||||
* if no source startPosition information is recorded for this node
|
||||
* @see #getLength()
|
||||
* @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
|
||||
*/
|
||||
int getStart();
|
||||
|
||||
/**
|
||||
* Returns the length in characters of the original source file indicating
|
||||
* where the source fragment corresponding to this node ends.
|
||||
* <p>
|
||||
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
||||
*
|
||||
* @return a (possibly 0) length, or <code>0</code>
|
||||
* if no source source position information is recorded for this node
|
||||
* @see #getStart()
|
||||
* @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
|
||||
*/
|
||||
int getLength();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.google.dart.compiler.common;
|
||||
|
||||
import com.google.dart.compiler.Source;
|
||||
|
||||
public class SourceInfoImpl implements SourceInfo {
|
||||
protected Source source = null;
|
||||
protected int line = -1;
|
||||
protected int column = -1;
|
||||
protected int start = -1;
|
||||
protected int length = -1;
|
||||
|
||||
public SourceInfoImpl(Source source, int line, int column, int start, int length) {
|
||||
this.source = source;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Source getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.common;
|
||||
|
||||
public interface Symbol {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.util;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class AstUtil {
|
||||
private AstUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequence of expressions (using the binary sequence operator).
|
||||
*
|
||||
* @param exprs - expressions to add to sequence
|
||||
* @return a sequence of expressions.
|
||||
*/
|
||||
public static JsBinaryOperation newSequence(JsExpression... exprs) {
|
||||
if (exprs.length < 2) {
|
||||
throw new RuntimeException("newSequence expects at least two arguments");
|
||||
}
|
||||
JsExpression result = exprs[exprs.length - 1];
|
||||
for (int i = exprs.length - 2; i >= 0; i--) {
|
||||
result = new JsBinaryOperation(JsBinaryOperator.COMMA, exprs[i], result);
|
||||
}
|
||||
return (JsBinaryOperation) result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends JsNode> T deepCopy(@Nullable T node) {
|
||||
if (node == null) return null;
|
||||
|
||||
//noinspection unchecked
|
||||
return (T) node.deepCopy();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends JsNode> List<T> deepCopy(@Nullable List<T> nodes) {
|
||||
if (nodes == null) return new SmartList<T>();
|
||||
|
||||
List<T> nodesCopy = new ArrayList<T>(nodes.size());
|
||||
for (T node : nodes) {
|
||||
nodesCopy.add(deepCopy(node));
|
||||
}
|
||||
|
||||
return nodesCopy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utility methods for operating on memory-efficient maps. All maps of size 0 or
|
||||
* 1 are assumed to be immutable. All maps of size greater than 1 are assumed to
|
||||
* be mutable.
|
||||
*/
|
||||
public class Maps {
|
||||
private Maps() {
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> put(Map<K, V> map, K key, V value) {
|
||||
switch (map.size()) {
|
||||
case 0:
|
||||
// Empty -> Singleton
|
||||
return Collections.singletonMap(key, value);
|
||||
case 1: {
|
||||
if (map.containsKey(key)) {
|
||||
return Collections.singletonMap(key, value);
|
||||
}
|
||||
// Singleton -> HashMap
|
||||
Map<K, V> result = new HashMap<K, V>();
|
||||
result.put(map.keySet().iterator().next(), map.values().iterator().next());
|
||||
result.put(key, value);
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
// HashMap
|
||||
map.put(key, value);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.util;
|
||||
|
||||
/**
|
||||
* Interface used for printing text output.
|
||||
*/
|
||||
public interface TextOutput {
|
||||
int getPosition();
|
||||
|
||||
int getLine();
|
||||
|
||||
int getColumn();
|
||||
|
||||
void indentIn();
|
||||
|
||||
void indentOut();
|
||||
|
||||
void newline();
|
||||
|
||||
void print(char c);
|
||||
|
||||
void print(int v);
|
||||
|
||||
void print(double v);
|
||||
|
||||
void print(char[] s);
|
||||
|
||||
void print(CharSequence s);
|
||||
|
||||
void printOpt(char c);
|
||||
|
||||
void printOpt(char[] s);
|
||||
|
||||
void printOpt(String s);
|
||||
|
||||
boolean isCompact();
|
||||
|
||||
boolean isJustNewlined();
|
||||
|
||||
void setOutListener(OutListener outListener);
|
||||
|
||||
void maybeIndent();
|
||||
|
||||
public interface OutListener {
|
||||
void newLined();
|
||||
|
||||
void indentedAfterNewLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TextOutputImpl implements TextOutput {
|
||||
private final boolean compact;
|
||||
private int identLevel = 0;
|
||||
private final static int indentGranularity = 2;
|
||||
private char[][] indents = new char[][] {new char[0]};
|
||||
private boolean justNewlined;
|
||||
private final StringBuilder out;
|
||||
private int position = 0;
|
||||
private int line = 0;
|
||||
private int column = 0;
|
||||
|
||||
private OutListener outListener;
|
||||
|
||||
public TextOutputImpl() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public boolean isCompact() {
|
||||
return compact;
|
||||
}
|
||||
|
||||
public TextOutputImpl(boolean compact) {
|
||||
this.compact = compact;
|
||||
out = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indentIn() {
|
||||
++identLevel;
|
||||
if (identLevel >= indents.length) {
|
||||
// Cache a new level of indentation string.
|
||||
char[] newIndentLevel = new char[identLevel * indentGranularity];
|
||||
Arrays.fill(newIndentLevel, ' ');
|
||||
char[][] newIndents = new char[indents.length + 1][];
|
||||
System.arraycopy(indents, 0, newIndents, 0, indents.length);
|
||||
newIndents[identLevel] = newIndentLevel;
|
||||
indents = newIndents;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indentOut() {
|
||||
--identLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newline() {
|
||||
out.append('\n');
|
||||
position++;
|
||||
line++;
|
||||
column = 0;
|
||||
justNewlined = true;
|
||||
if (outListener != null) {
|
||||
outListener.newLined();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(double value) {
|
||||
maybeIndent();
|
||||
int oldLength = out.length();
|
||||
out.append(value);
|
||||
movePosition(out.length() - oldLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(int value) {
|
||||
maybeIndent();
|
||||
int oldLength = out.length();
|
||||
out.append(value);
|
||||
movePosition(out.length() - oldLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char c) {
|
||||
maybeIndent();
|
||||
out.append(c);
|
||||
movePosition(1);
|
||||
}
|
||||
|
||||
private void movePosition(int l) {
|
||||
position += l;
|
||||
column += l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char[] s) {
|
||||
maybeIndent();
|
||||
printAndCount(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(CharSequence s) {
|
||||
maybeIndent();
|
||||
printAndCount(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printOpt(char c) {
|
||||
if (!compact) {
|
||||
print(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printOpt(char[] s) {
|
||||
if (!compact) {
|
||||
maybeIndent();
|
||||
printAndCount(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printOpt(String s) {
|
||||
if (!compact) {
|
||||
maybeIndent();
|
||||
printAndCount(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeIndent() {
|
||||
if (justNewlined && !compact) {
|
||||
printAndCount(indents[identLevel]);
|
||||
justNewlined = false;
|
||||
if (outListener != null) {
|
||||
outListener.indentedAfterNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printAndCount(CharSequence charSequence) {
|
||||
position += charSequence.length();
|
||||
column += charSequence.length();
|
||||
out.append(charSequence);
|
||||
}
|
||||
|
||||
private void printAndCount(char[] chars) {
|
||||
position += chars.length;
|
||||
column += chars.length;
|
||||
out.append(chars);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJustNewlined() {
|
||||
return justNewlined && !compact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutListener(OutListener outListener) {
|
||||
this.outListener = outListener;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user