move from my kotlin fork

This commit is contained in:
develar
2012-09-30 12:36:34 +04:00
commit 845189ca28
96 changed files with 7200 additions and 0 deletions
Generated
+1
View File
@@ -0,0 +1 @@
former-dast-ast
+10
View File
@@ -0,0 +1,10 @@
<component name="ArtifactManager">
<artifact name="dart-ast:jar">
<output-path>$PROJECT_DIR$/out/artifacts</output-path>
<root id="root">
<element id="archive" name="dart-ast.jar">
<element id="module-output" name="former-dast-ast" />
</element>
</root>
</artifact>
</component>
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
+58
View File
@@ -0,0 +1,58 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
<option name="myLocal" value="false" />
<inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSBitwiseOperatorUsage" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="" />
</inspection_tool>
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_onlyPrivateOrFinal" value="false" />
<option name="m_ignoreEmptyMethods" value="true" />
</inspection_tool>
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="UnnecessarilyQualifiedStaticUsage" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_ignoreStaticFieldAccesses" value="false" />
<option name="m_ignoreStaticMethodCalls" value="false" />
<option name="m_ignoreStaticAccessFromStaticContext" value="false" />
</inspection_tool>
<inspection_tool class="UnnecessarilyQualifiedStaticallyImportedElement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnnecessaryContinue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnnecessaryQualifierForThis" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnnecessaryThis" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
+7
View File
@@ -0,0 +1,7 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_PROFILE" value="true" />
<version value="1.0" />
</settings>
</component>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/former-dast-ast.iml" filepath="$PROJECT_DIR$/former-dast-ast.iml" />
</modules>
</component>
</project>
+5
View File
@@ -0,0 +1,5 @@
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
+125
View File
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
Generated
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+27
View File
@@ -0,0 +1,27 @@
<?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="module-library">
<library name="idea sdk">
<CLASSES>
<root url="jar://$MODULE_DIR$/../kotlin/ideaSDK/lib/annotations.jar!/" />
<root url="jar://$MODULE_DIR$/../kotlin/ideaSDK/lib/trove4j.jar!/" />
<root url="jar://$MODULE_DIR$/../kotlin/ideaSDK/lib/util.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$MODULE_DIR$/src" />
<root url="jar://$MODULE_DIR$/../kotlin/ideaSDK/lib/trove4j_src.jar!/src" />
<root url="jar://$MODULE_DIR$/../kotlin/ideaSDK/lib/trove4j_src.jar!/util/src" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>
+5
View File
@@ -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.
+45
View File
@@ -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,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;
import com.google.dart.compiler.backend.js.ast.*;
/**
* Searches for method invocations in constructor expressions that would not
* normally be surrounded by parentheses.
*/
public class JsConstructExpressionVisitor extends JsVisitor {
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 = false;
private JsConstructExpressionVisitor() {
}
/**
* We only look at the array expression since the index has its own scope.
*/
@Override
public boolean visit(JsArrayAccess x, JsContext ctx) {
accept(x.getArrayExpr());
return false;
}
/**
* Array literals have their own scoping.
*/
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
return false;
}
/**
* Functions have their own scoping.
*/
@Override
public boolean visit(JsFunction x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
containsInvocation = true;
return false;
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (!x.isLeaf()) {
accept(x.getQualifier());
}
return false;
}
/**
* New constructs bind to the nearest set of parentheses.
*/
@Override
public boolean visit(JsNew x, JsContext ctx) {
return false;
}
/**
* Object literals have their own scope.
*/
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
return false;
}
/**
* We only look at nodes that would not normally be surrounded by parentheses.
*/
@Override
protected <T extends JsVisitable> T doAccept(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.
Object o = node;
if (o instanceof JsExpression) {
JsExpression expression = (JsExpression) o;
int precedence = JsPrecedenceVisitor.exec(expression);
// Only visit expressions that won't automatically be surrounded by
// parentheses
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return node;
}
}
return super.doAccept(node);
}
}
@@ -0,0 +1,134 @@
// 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.JsArrayAccess;
import com.google.dart.compiler.backend.js.ast.JsArrayLiteral;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsContext;
import com.google.dart.compiler.backend.js.ast.JsExprStmt;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsInvocation;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.JsNew;
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral;
import com.google.dart.compiler.backend.js.ast.JsPostfixOperation;
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation;
import com.google.dart.compiler.backend.js.ast.JsRegExp;
import com.google.dart.compiler.backend.js.ast.JsVisitor;
/**
* 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 JsVisitor {
public static boolean exec(JsExprStmt 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 boolean visit(JsArrayAccess x, JsContext ctx) {
accept(x.getArrayExpr());
return false;
}
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsBinaryOperation x, JsContext ctx) {
accept(x.getArg1());
return false;
}
@Override
public boolean visit(JsConditional x, JsContext ctx) {
accept(x.getTestExpression());
return false;
}
@Override
public boolean visit(JsFunction x, JsContext ctx) {
needsParentheses = true;
return false;
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
accept(x.getQualifier());
return false;
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (!x.isLeaf()) {
accept(x.getQualifier());
}
return false;
}
@Override
public boolean visit(JsNew x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
needsParentheses = true;
return false;
}
@Override
public boolean visit(JsPostfixOperation x, JsContext ctx) {
accept(x.getArg());
return false;
}
@Override
public boolean visit(JsPrefixOperation x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsRegExp x, JsContext ctx) {
return false;
}
}
@@ -0,0 +1,280 @@
// 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.JsVars.JsVar;
/**
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
* 57)
*
* Precedence 17 is for indivisible primaries that either don't have children,
* or provide their own delimiters.
*
* Precedence 16 is for really important things that have their own AST classes.
*
* Precedence 15 is for the new construct.
*
* Precedence 14 is for unary operators.
*
* Precedences 12 through 4 are for non-assigning binary operators.
*
* Precedence 3 is for the tertiary conditional.
*
* Precedence 2 is for assignments.
*
* Precedence 1 is for comma operations.
*/
class JsPrecedenceVisitor extends JsVisitor {
static final int PRECEDENCE_NEW = 15;
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;
}
private int answer = -1;
private JsPrecedenceVisitor() {
}
@Override
public boolean visit(JsArrayAccess x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsBinaryOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsBlock x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsBreak x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsCase x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsCatch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsConditional x, JsContext ctx) {
answer = 3;
return false;
}
@Override
public boolean visit(JsContinue x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDebugger x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDefault x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDoWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsEmpty x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsExprStmt x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsFor x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsForIn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsFunction x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsIf x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsLabel x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (x.isLeaf()) {
answer = 17; // primary
} else {
answer = 16; // property access
}
return false;
}
@Override
public boolean visit(JsNew x, JsContext ctx) {
answer = PRECEDENCE_NEW;
return false;
}
@Override
public boolean visit(JsNullLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsParameter x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPostfixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsPrefixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsProgram x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsRegExp x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsReturn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsStringLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsSwitch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsThrow x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsTry x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsVar x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsVars x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
}
@@ -0,0 +1,158 @@
// 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.JsBlock;
import com.google.dart.compiler.backend.js.ast.JsBreak;
import com.google.dart.compiler.backend.js.ast.JsContext;
import com.google.dart.compiler.backend.js.ast.JsDebugger;
import com.google.dart.compiler.backend.js.ast.JsDoWhile;
import com.google.dart.compiler.backend.js.ast.JsEmpty;
import com.google.dart.compiler.backend.js.ast.JsExprStmt;
import com.google.dart.compiler.backend.js.ast.JsFor;
import com.google.dart.compiler.backend.js.ast.JsForIn;
import com.google.dart.compiler.backend.js.ast.JsIf;
import com.google.dart.compiler.backend.js.ast.JsLabel;
import com.google.dart.compiler.backend.js.ast.JsReturn;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.backend.js.ast.JsSwitch;
import com.google.dart.compiler.backend.js.ast.JsThrow;
import com.google.dart.compiler.backend.js.ast.JsTry;
import com.google.dart.compiler.backend.js.ast.JsVars;
import com.google.dart.compiler.backend.js.ast.JsVisitor;
import com.google.dart.compiler.backend.js.ast.JsWhile;
/**
* Determines if a statement at the end of a block requires a semicolon.
*
* For example, the following statements require semicolons:<br>
* <ul>
* <li>if (cond);</li>
* <li>while (cond);</li>
* </ul>
*
* The following do not require semicolons:<br>
* <ul>
* <li>return 1</li>
* <li>do {} while(true)</li>
* </ul>
*/
public class JsRequiresSemiVisitor extends JsVisitor {
public static boolean exec(JsStatement lastStatement) {
JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor();
visitor.accept(lastStatement);
return visitor.needsSemicolon;
}
private boolean needsSemicolon = false;
private JsRequiresSemiVisitor() {
}
@Override
public boolean visit(JsBlock x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsBreak x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsDebugger x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsDoWhile x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsEmpty x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsExprStmt x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsFor x, JsContext ctx) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
return false;
}
@Override
public boolean visit(JsForIn x, JsContext ctx) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
return false;
}
@Override
public boolean visit(JsIf x, JsContext ctx) {
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);
}
return false;
}
@Override
public boolean visit(JsLabel x, JsContext ctx) {
if (x.getStmt() instanceof JsEmpty) {
needsSemicolon = true;
}
return false;
}
@Override
public boolean visit(JsReturn x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsSwitch x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsThrow x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsTry x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsVars x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsWhile x, JsContext ctx) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
return false;
}
}
@@ -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() {
}
}
@@ -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;
import com.google.dart.compiler.backend.js.ast.JsBlock;
import com.google.dart.compiler.backend.js.ast.JsContext;
import com.google.dart.compiler.backend.js.ast.JsProgram;
import com.google.dart.compiler.backend.js.ast.JsProgramFragment;
import com.google.dart.compiler.util.TextOutput;
/**
* Generates JavaScript source from an AST.
*/
public class JsSourceGenerationVisitor extends JsToStringGenerationVisitor {
public JsSourceGenerationVisitor(TextOutput out) {
super(out);
}
@Override
public boolean visit(JsProgram program, JsContext ctx) {
return true;
}
@Override
public boolean visit(JsProgramFragment x, JsContext ctx) {
// Descend naturally.
return true;
}
@Override
public boolean visit(JsBlock x, JsContext ctx) {
printJsBlock(x, false, true);
return false;
}
}
File diff suppressed because it is too large Load Diff
@@ -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;
/**
* An interface that describes the boolean evaluation of an expression.
*/
public interface CanBooleanEval {
boolean isBooleanFalse();
boolean isBooleanTrue();
}
@@ -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;
import java.util.List;
/**
* Implemented by JavaScript objects that accept arguments.
*/
public interface HasArguments extends JsExpression {
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,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 com.google.dart.compiler.common.HasSymbol;
/**
* Implemented by JavaScript objects that have a name.
*/
public interface HasName extends HasSymbol {
JsName getName();
}
@@ -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;
/**
* Represents a javascript expression for array access.
*/
public final class JsArrayAccess extends JsExpressionImpl {
private JsExpression arrayExpr;
private JsExpression indexExpr;
public JsArrayAccess() {
super();
}
public JsArrayAccess(JsExpression arrayExpr, JsExpression indexExpr) {
this.arrayExpr = arrayExpr;
this.indexExpr = indexExpr;
}
public JsExpression getArrayExpr() {
return arrayExpr;
}
public JsExpression getIndexExpr() {
return indexExpr;
}
@Override
public boolean hasSideEffects() {
return arrayExpr.hasSideEffects() || indexExpr.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setArrayExpr(JsExpression arrayExpr) {
this.arrayExpr = arrayExpr;
}
public void setIndexExpr(JsExpression indexExpr) {
this.indexExpr = indexExpr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
arrayExpr = v.accept(arrayExpr);
indexExpr = v.accept(indexExpr);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.ARRAY_ACCESS;
}
}
@@ -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.intellij.util.SmartList;
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 boolean hasSideEffects() {
for (JsExpression expr : expressions) {
if (expr.hasSideEffects()) {
return true;
}
}
return false;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(expressions);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.ARRAY;
}
}
@@ -0,0 +1,100 @@
// 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;
/**
* Represents a JavaScript binary operation.
*/
public final class JsBinaryOperation extends JsExpressionImpl {
private JsExpression arg1;
private JsExpression arg2;
private final JsBinaryOperator op;
public JsBinaryOperation(JsBinaryOperator op) {
this(op, null, null);
}
public JsBinaryOperation(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 JsBinaryOperator getOperator() {
return op;
}
@Override
public boolean hasSideEffects() {
return op.isAssignment() || arg1.hasSideEffects() || arg2.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
// Precarious coding, but none of these can have null results.
if (op.getPrecedence() > 5) {
return true;
}
if (op == JsBinaryOperator.OR) {
if (arg1 instanceof CanBooleanEval) {
if (((CanBooleanEval) arg1).isBooleanTrue()) {
assert arg1.isDefinitelyNotNull();
return true;
}
}
}
// AND and OR can return nulls
if (op.isAssignment()) {
if (op == JsBinaryOperator.ASG) {
return arg2.isDefinitelyNotNull();
} else {
// All other ASG's are math ops.
return true;
}
}
if (op == JsBinaryOperator.COMMA) {
return arg2.isDefinitelyNotNull();
}
return false;
}
@Override
public boolean isDefinitelyNull() {
if (op == JsBinaryOperator.AND) {
return arg1.isDefinitelyNull();
}
return false;
}
@Override
public void traverse(JsVisitor 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);
}
@Override
public NodeKind getKind() {
return NodeKind.BINARY_OP;
}
}
@@ -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,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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Represents a JavaScript block statement.
*/
public class JsBlock extends JsNodeImpl implements JsStatement {
private final List<JsStatement> statements;
public JsBlock() {
this(new ArrayList<JsStatement>());
}
public JsBlock(JsStatement statement) {
this(Collections.singletonList(statement));
}
public JsBlock(JsStatement... statements) {
this(Arrays.asList(statements));
}
public JsBlock(List<JsStatement> statements) {
this.statements = statements;
}
public List<JsStatement> getStatements() {
return statements;
}
public boolean isEmpty() {
return statements.isEmpty();
}
public boolean isGlobalBlock() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(statements);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.BLOCK;
}
}
@@ -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;
/**
* Represents the JavaScript break statement.
*/
public final class JsBreak extends JsContinue {
public JsBreak() {
super(null);
}
public JsBreak(JsNameRef label) {
super(label);
}
@Override
public NodeKind getKind() {
return NodeKind.BREAK;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (label != null) {
v.accept(label);
}
}
v.endVisit(this, ctx);
}
}
@@ -0,0 +1,39 @@
// 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 JavaScript case statement.
*/
public final class JsCase extends JsSwitchMember {
private JsExpression caseExpr;
public JsCase() {
super();
}
public JsExpression getCaseExpr() {
return caseExpr;
}
public void setCaseExpr(JsExpression caseExpr) {
this.caseExpr = caseExpr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
caseExpr = v.accept(caseExpr);
v.acceptWithInsertRemove(statements);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.CASE;
}
}
@@ -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;
/**
* Represents a JavaScript catch clause.
*/
public class JsCatch extends JsNodeImpl implements HasCondition {
protected final JsCatchScope scope;
private JsBlock body;
private JsExpression condition;
private JsParameter param;
public JsCatch(JsScope parent, String ident) {
super();
assert (parent != null);
scope = new JsCatchScope(parent, ident);
param = new JsParameter(scope.findName(ident));
}
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 traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
param = v.accept(param);
if (condition != null) {
condition = v.accept(condition);
}
body = v.accept(body);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.CATCH;
}
}
@@ -0,0 +1,36 @@
// 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, String ident) {
super(parent, "Catch scope");
name = new JsName(this, ident);
}
@Override
public JsName declareName(String identifier) {
// Declare into parent scope!
return getParent().declareName(identifier);
}
@Override
public boolean hasOwnName(@NotNull String name) {
return findOwnName(name) != null;
}
@Override
protected JsName findOwnName(String ident) {
return name.getIdent().equals(ident) ? name : null;
}
}
@@ -0,0 +1,77 @@
// 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 a JavaScript conditional expression.
*/
public final class JsConditional extends JsExpressionImpl {
private JsExpression testExpr;
private JsExpression elseExpr;
private JsExpression thenExpr;
public JsConditional() {
}
public JsConditional(JsExpression testExpr, JsExpression thenExpr, JsExpression elseExpr) {
this.testExpr = testExpr;
this.thenExpr = thenExpr;
this.elseExpr = elseExpr;
}
public JsExpression getElseExpression() {
return elseExpr;
}
public JsExpression getTestExpression() {
return testExpr;
}
public JsExpression getThenExpression() {
return thenExpr;
}
@Override
public boolean hasSideEffects() {
return testExpr.hasSideEffects() || thenExpr.hasSideEffects() || elseExpr.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
return thenExpr.isDefinitelyNotNull() && elseExpr.isDefinitelyNotNull();
}
@Override
public boolean isDefinitelyNull() {
return thenExpr.isDefinitelyNull() && elseExpr.isDefinitelyNull();
}
public void setElseExpression(JsExpression elseExpr) {
this.elseExpr = elseExpr;
}
public void setTestExpression(JsExpression testExpr) {
this.testExpr = testExpr;
}
public void setThenExpression(JsExpression thenExpr) {
this.thenExpr = thenExpr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
testExpr = v.accept(testExpr);
thenExpr = v.accept(thenExpr);
elseExpr = v.accept(elseExpr);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.CONDITIONAL;
}
}
@@ -0,0 +1,27 @@
// 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;
/**
* 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 interface JsContext {
boolean canInsert();
boolean canRemove();
void insertAfter(JsVisitable node);
void insertBefore(JsVisitable node);
boolean isLvalue();
void removeMe();
void replaceMe(JsVisitable node);
}
@@ -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.Nullable;
/**
* Represents the JavaScript continue statement.
*/
public class JsContinue extends JsNodeImpl implements JsStatement {
protected final JsNameRef label;
public JsContinue() {
this(null);
}
public JsContinue(@Nullable JsNameRef label) {
super();
this.label = label;
}
public JsNameRef getLabel() {
return label;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (label != null) {
v.accept(label);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.CONTINUE;
}
}
@@ -0,0 +1,25 @@
// 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 a JavaScript debugger statement.
*/
public class JsDebugger extends JsNodeImpl implements JsStatement {
public JsDebugger() {
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.DEBUGGER;
}
}
@@ -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;
/**
* Represents the default option in a JavaScript swtich statement.
*/
public final class JsDefault extends JsSwitchMember {
public JsDefault() {
super();
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(statements);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.DEFAULT;
}
}
@@ -0,0 +1,31 @@
// 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 a JavaScript do..while statement.
*/
public class JsDoWhile extends JsWhile {
public JsDoWhile() {
}
public JsDoWhile(JsExpression condition, JsStatement body) {
super(condition, body);
}
@Override
public NodeKind getKind() {
return NodeKind.DO;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
condition = v.accept(condition);
body = v.accept(body);
}
v.endVisit(this, ctx);
}
}
@@ -0,0 +1,25 @@
// 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 an empty statement in JavaScript.
*/
public class JsEmpty extends JsNodeImpl implements JsStatement {
// Interned by JsProgram
JsEmpty() {
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.EMPTY;
}
}
@@ -0,0 +1,32 @@
// 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 JsExprStmt extends JsNodeImpl implements JsStatement {
private JsExpression expr;
public JsExprStmt(JsExpression expr) {
super();
this.expr = expr;
this.setSourceInfo(expr);
}
public JsExpression getExpression() {
return expr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
expr = v.accept(expr);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.EXPRESSION_STMT;
}
}
@@ -0,0 +1,25 @@
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.HasSourceInfo;
import com.google.dart.compiler.common.SourceInfo;
public interface JsExpression extends JsNode, SourceInfo, HasSourceInfo, JsVisitable {
/**
* Determines whether the expression can cause side effects.
*/
boolean hasSideEffects();
/**
* True if the target expression is definitely not null.
*/
boolean isDefinitelyNotNull();
/**
* True if the target expression is definitely null.
*/
boolean isDefinitelyNull();
boolean isLeaf();
JsStatement makeStmt();
}
@@ -0,0 +1,27 @@
// 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;
abstract class JsExpressionImpl extends JsNodeImpl implements JsExpression {
protected JsExpressionImpl() {
}
/**
* 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.
*/
@Override
public boolean isLeaf() {
// Conservatively say that it isn't a leaf.
// Individual subclasses can speak for themselves if they are a leaf.
return false;
}
@Override
public JsStatement makeStmt() {
return new JsExprStmt(this);
}
}
@@ -0,0 +1,99 @@
// 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.SourceInfo;
/**
* 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 #getInitExpr()} 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 JsNodeImpl implements JsStatement {
private JsStatement body;
private JsExpression condition;
private JsExpression incrExpr;
private JsExpression initExpr;
private JsVars initVars;
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpr) {
this.initVars = initVars;
this.incrExpr = incrementExpr;
this.condition = condition;
initExpr = null;
}
public JsFor(JsExpression initExpr, JsExpression condition, JsExpression incrementExpr) {
this.initExpr = initExpr;
this.incrExpr = incrementExpr;
this.condition = condition;
initVars = null;
}
public JsStatement getBody() {
return body;
}
public JsExpression getCondition() {
return condition;
}
public JsExpression getIncrExpr() {
return incrExpr;
}
public JsExpression getInitExpr() {
return initExpr;
}
public JsVars getInitVars() {
return initVars;
}
public void setBody(JsStatement body) {
this.body = body;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
assert (!(initExpr != null && initVars != null));
if (initExpr != null) {
initExpr = v.accept(initExpr);
}
else if (initVars != null) {
initVars = v.accept(initVars);
}
if (condition != null) {
condition = v.accept(condition);
}
if (incrExpr != null) {
incrExpr = v.accept(incrExpr);
}
body = v.accept(body);
}
v.endVisit(this, ctx);
}
@Override
public JsFor setSourceRef(SourceInfo info) {
super.setSourceRef(info);
return this;
}
@Override
public NodeKind getKind() {
return NodeKind.FOR;
}
}
@@ -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;
/**
* Represents a JavaScript for..in statement.
*/
public class JsForIn extends JsNodeImpl implements JsStatement {
private JsStatement body;
private JsExpression iterExpr;
private JsExpression objExpr;
// 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 JsStatement getBody() {
return body;
}
public JsExpression getIterExpr() {
return iterExpr;
}
public JsName getIterVarName() {
return iterVarName;
}
public JsExpression getObjExpr() {
return objExpr;
}
public void setBody(JsStatement body) {
this.body = body;
}
public void setIterExpr(JsExpression iterExpr) {
this.iterExpr = iterExpr;
}
public void setObjExpr(JsExpression objExpr) {
this.objExpr = objExpr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (iterExpr != null) {
iterExpr = v.acceptLvalue(iterExpr);
}
objExpr = v.accept(objExpr);
body = v.accept(body);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.FOR_IN;
}
}
@@ -0,0 +1,112 @@
// 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.SourceInfo;
import com.google.dart.compiler.common.Symbol;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public final class JsFunction extends JsLiteral implements HasName {
private JsBlock body;
private List<JsParameter> params;
private final JsScope scope;
private JsName name;
public JsFunction(JsScope parentScope) {
this(parentScope, (JsName) null);
}
public JsFunction(JsScope parentScope, JsBlock body) {
this(parentScope, (JsName) null);
this.body = body;
}
private JsFunction(JsScope parentScope, @Nullable JsName name) {
this.name = name;
this.scope = new JsScope(parentScope, name == null ? null : name.getIdent());
}
public JsBlock getBody() {
return body;
}
@Override
public JsName getName() {
return name;
}
@Override
public Symbol getSymbol() {
return name;
}
public List<JsParameter> getParameters() {
if (params == null) {
params = new SmartList<JsParameter>();
}
return params;
}
public JsScope getScope() {
return scope;
}
@Override
public boolean hasSideEffects() {
// If there's a name, the name is assigned to.
return name != null;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setBody(JsBlock body) {
this.body = body;
}
public void setName(@Nullable JsName name) {
this.name = name;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(params);
body = v.accept(body);
}
v.endVisit(this, ctx);
}
@Override
public JsFunction setSourceRef(SourceInfo info) {
super.setSourceRef(info);
return this;
}
@Override
public NodeKind getKind() {
return NodeKind.FUNCTION;
}
}
@@ -0,0 +1,19 @@
// 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;
/**
* Represnts a JavaScript block in the global scope.
*/
public class JsGlobalBlock extends JsBlock {
public JsGlobalBlock() {
}
@Override
public boolean isGlobalBlock() {
return true;
}
}
@@ -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;
/**
* Represents a JavaScript if statement.
*/
public final class JsIf extends JsNodeImpl implements JsStatement {
private JsExpression ifExpression;
private JsStatement thenStatement;
private JsStatement elseStatement;
public JsIf() {
}
public JsIf(JsExpression ifExpression, JsStatement thenStatement, JsStatement elseStatement) {
this.ifExpression = ifExpression;
this.thenStatement = thenStatement;
this.elseStatement = elseStatement;
}
public JsIf(JsExpression ifExpression, JsStatement thenStatement) {
this.ifExpression = ifExpression;
this.thenStatement = thenStatement;
}
public JsStatement getElseStatement() {
return elseStatement;
}
public JsExpression getIfExpression() {
return ifExpression;
}
public JsStatement getThenStatement() {
return thenStatement;
}
public void setElseStatement(JsStatement elseStmt) {
this.elseStatement = elseStmt;
}
public void setIfExpression(JsExpression ifExpr) {
this.ifExpression = ifExpr;
}
public void setThenStatement(JsStatement thenStmt) {
this.thenStatement = thenStmt;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
ifExpression = v.accept(ifExpression);
thenStatement = v.accept(thenStatement);
if (elseStatement != null) {
elseStatement = v.accept(elseStatement);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.IF;
}
}
@@ -0,0 +1,83 @@
// 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 java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Represents a JavaScript invocation.
*/
public final class JsInvocation extends JsExpressionImpl implements HasArguments {
private final List<JsExpression> arguments;
private JsExpression qualifier;
public JsInvocation() {
arguments = new SmartList<JsExpression>();
}
public JsInvocation(JsExpression qualifier, List<JsExpression> arguments) {
this.qualifier = qualifier;
this.arguments = arguments;
}
public JsInvocation(JsExpression qualifier, JsExpression arg) {
this(qualifier, Collections.singletonList(arg));
}
public JsInvocation(JsExpression qualifier, JsExpression... arguments) {
this(qualifier, Arrays.asList(arguments));
}
public JsInvocation(JsExpression qualifier) {
this();
this.qualifier = qualifier;
}
@Override
public List<JsExpression> getArguments() {
return arguments;
}
public JsExpression getQualifier() {
return qualifier;
}
@Override
public boolean hasSideEffects() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setQualifier(JsExpression qualifier) {
this.qualifier = qualifier;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
qualifier = v.accept(qualifier);
v.acceptList(arguments);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.INVOKE;
}
}
@@ -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.backend.js.ast;
import com.google.dart.compiler.common.Symbol;
/**
* Represents a JavaScript label statement.
*/
public class JsLabel extends JsNodeImpl implements JsStatement, HasName {
private final JsName label;
private JsStatement stmt;
public JsLabel(JsName label) {
this.label = label;
}
@Override
public JsName getName() {
return label;
}
@Override
public Symbol getSymbol() {
return label;
}
public JsStatement getStmt() {
return stmt;
}
public void setStmt(JsStatement stmt) {
this.stmt = stmt;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
stmt = v.accept(stmt);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.LABEL;
}
}
@@ -0,0 +1,100 @@
// 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 JsLiteral extends JsExpressionImpl implements CanBooleanEval {
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 boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.THIS;
}
}
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 boolean isBooleanFalse() {
return !value;
}
@Override
public boolean isBooleanTrue() {
return value;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.BOOLEAN;
}
}
}
@@ -0,0 +1,53 @@
// 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;
/**
* An abstract base class for named JavaScript objects.
*/
public class JsName implements Symbol {
private final JsScope enclosing;
private final String ident;
/**
* @param ident the unmangled ident to use for this name
*/
JsName(JsScope enclosing, String ident) {
this.enclosing = enclosing;
this.ident = ident;
}
public String getIdent() {
return ident;
}
public JsNameRef makeRef() {
return new JsNameRef(this);
}
@Override
public String toString() {
return ident;
}
@Override
public int hashCode() {
return ident.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof JsName)) {
return false;
}
JsName other = (JsName) obj;
return ident.equals(other.ident) && enclosing == other.enclosing;
}
}
@@ -0,0 +1,125 @@
// 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;
/**
* Represents a JavaScript expression that references a name.
*/
public final class JsNameRef extends JsExpressionImpl implements CanBooleanEval, HasName {
private String ident;
private JsName name;
private JsExpression qualifier;
public JsNameRef(JsName name) {
this.name = name;
}
public JsNameRef(String ident) {
this.ident = ident;
}
public JsNameRef(String ident, JsExpression qualifier) {
this.ident = ident;
this.qualifier = qualifier;
}
public JsNameRef(String ident, String qualifier) {
this(ident, new JsNameRef(qualifier));
}
public JsNameRef(JsName name, JsExpression qualifier) {
this.name = name;
this.qualifier = qualifier;
}
public String getIdent() {
return (name == null) ? ident : name.getIdent();
}
@Override
public JsName getName() {
return name;
}
@Override
public Symbol getSymbol() {
return name;
}
public JsExpression getQualifier() {
return qualifier;
}
@Override
public boolean hasSideEffects() {
if (qualifier == null) {
return false;
}
if (!qualifier.isDefinitelyNotNull()) {
// Could trigger NPE.
return true;
}
return qualifier.hasSideEffects();
}
@Override
public boolean isBooleanFalse() {
return isDefinitelyNull();
}
@Override
public boolean isBooleanTrue() {
return false;
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
if (name != null) {
return (JsLiteral.UNDEFINED.getName() == name);
}
return false;
}
@Override
public boolean isLeaf() {
if (qualifier == null) {
return true;
}
else {
return false;
}
}
public void resolve(JsName name) {
this.name = name;
this.ident = null;
}
public void setQualifier(JsExpression qualifier) {
this.qualifier = qualifier;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (qualifier != null) {
qualifier = v.accept(qualifier);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.NAME_REF;
}
}
@@ -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.intellij.util.SmartList;
import java.util.List;
/**
* Represents the JavaScript new expression.
*/
public final class JsNew extends JsExpressionImpl implements HasArguments {
private final List<JsExpression> arguments;
private JsExpression ctorExpression;
public JsNew(JsExpression ctorExpression) {
this(ctorExpression, new SmartList<JsExpression>());
}
public JsNew(JsExpression ctorExpression, List<JsExpression> arguments) {
this.ctorExpression = ctorExpression;
this.arguments = arguments;
}
@Override
public List<JsExpression> getArguments() {
return arguments;
}
public JsExpression getConstructorExpression() {
return ctorExpression;
}
@Override
public boolean hasSideEffects() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
// Sadly, in JS it can be!
// TODO: analysis could probably determine most instances cannot be null.
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
ctorExpression = v.accept(ctorExpression);
v.acceptList(arguments);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.NEW;
}
}
@@ -0,0 +1,9 @@
// 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 JsNode extends JsVisitable {
NodeKind getKind();
}
@@ -0,0 +1,41 @@
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.backend.js.JsSourceGenerationVisitor;
import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
import com.google.dart.compiler.common.AbstractNode;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.util.TextOutputImpl;
abstract class JsNodeImpl extends AbstractNode implements JsNode {
protected JsNodeImpl() {
}
// Causes source generation to delegate to the one visitor
public final String toSource() {
TextOutputImpl out = new TextOutputImpl();
JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
v.accept(this);
return out.toString();
}
// Causes source generation to delegate to the one visitor
@Override
public String toString() {
TextOutputImpl out = new TextOutputImpl();
JsToStringGenerationVisitor v = new JsToStringGenerationVisitor(out);
v.accept(this);
return out.toString();
}
@Override
public SourceInfo getSourceInfo() {
return this;
}
public JsNode setSourceRef(SourceInfo info) {
if (info != null) {
this.setSourceInfo(info);
}
return this;
}
}
@@ -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.backend.js.ast;
public final class JsNullLiteral extends JsValueLiteral {
JsNullLiteral() {
}
@Override
public boolean isBooleanFalse() {
return true;
}
@Override
public boolean isBooleanTrue() {
return false;
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return true;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.NULL;
}
}
@@ -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;
public abstract class JsNumberLiteral extends JsValueLiteral {
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public NodeKind getKind() {
return NodeKind.NUMBER;
}
public static final class JsDoubleLiteral extends JsNumberLiteral {
public final double value;
JsDoubleLiteral(double value) {
this.value = value;
}
@Override
public boolean isBooleanFalse() {
return value == 0.0;
}
@Override
public boolean isBooleanTrue() {
return value != 0.0;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
public String toString() {
return String.valueOf(value);
}
}
public static final class JsIntLiteral extends JsNumberLiteral {
public final int value;
JsIntLiteral(int value) {
this.value = value;
}
@Override
public boolean isBooleanFalse() {
return value == 0;
}
@Override
public boolean isBooleanTrue() {
return value != 0;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
public String toString() {
return String.valueOf(value);
}
}
}
@@ -0,0 +1,83 @@
// 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 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 boolean hasSideEffects() {
for (JsPropertyInitializer prop : properties) {
if (prop.hasSideEffects()) {
return true;
}
}
return false;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(properties);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.OBJECT;
}
}
@@ -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,39 @@
// 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;
/**
* A JavaScript parameter.
*/
public final class JsParameter extends JsNodeImpl implements HasName {
private final JsName name;
public JsParameter(JsName name) {
this.name = name;
}
@Override
public JsName getName() {
return name;
}
@Override
public Symbol getSymbol() {
return name;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PARAMETER;
}
}
@@ -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;
/**
* A JavaScript postfix operation.
*/
public final class JsPostfixOperation extends JsUnaryOperation {
public JsPostfixOperation(JsUnaryOperator op) {
this(op, null);
}
public JsPostfixOperation(JsUnaryOperator op, JsExpression arg) {
super(op, arg);
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
super.traverse(v, ctx);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.POSTFIX_OP;
}
}
@@ -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;
/**
* A JavaScript prefix operation.
*/
public final class JsPrefixOperation extends JsUnaryOperation implements CanBooleanEval {
public JsPrefixOperation(JsUnaryOperator op) {
this(op, null);
}
public JsPrefixOperation(JsUnaryOperator op, JsExpression arg) {
super(op, arg);
}
@Override
public boolean isBooleanFalse() {
if (getOperator() == JsUnaryOperator.VOID) {
return true;
}
if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
CanBooleanEval eval = (CanBooleanEval) getArg();
return eval.isBooleanTrue();
}
return false;
}
@Override
public boolean isBooleanTrue() {
if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
CanBooleanEval eval = (CanBooleanEval) getArg();
return eval.isBooleanFalse();
}
if (getOperator() == JsUnaryOperator.TYPEOF) {
return true;
}
return false;
}
@Override
public boolean isDefinitelyNotNull() {
if (getOperator() == JsUnaryOperator.TYPEOF) {
return true;
}
return getOperator() != JsUnaryOperator.VOID;
}
@Override
public boolean isDefinitelyNull() {
return getOperator() == JsUnaryOperator.VOID;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
super.traverse(v, ctx);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PREFIX_OP;
}
}
@@ -0,0 +1,128 @@
// 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.Nullable;
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 JsNodeImpl {
private final JsEmpty emptyStmt;
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 JsScope topScope;
/**
* Constructs a JavaScript program object.
*/
public JsProgram(String unitId) {
rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId);
setFragmentCount(1);
emptyStmt = new JsEmpty();
}
public JsEmpty getEmptyStmt() {
return emptyStmt;
}
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 JsScope getScope() {
return topScope;
}
/**
* Creates or retrieves a JsStringLiteral from an interned object pool.
*/
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 traverse(JsVisitor v, @Nullable JsContext ctx) {
if (v.visit(this, ctx)) {
for (JsProgramFragment fragment : fragments) {
v.accept(fragment);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM;
}
}
@@ -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;
/**
* One independently loadable fragment of a {@link JsProgram}.
*/
public class JsProgramFragment extends JsNodeImpl {
private final JsGlobalBlock globalBlock;
public JsProgramFragment() {
this.globalBlock = new JsGlobalBlock();
}
public JsBlock getGlobalBlock() {
return globalBlock;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.accept(globalBlock);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM_FRAGMENT;
}
}
@@ -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 org.jetbrains.annotations.NotNull;
/**
* Used in object literals to specify property values by name.
*/
public class JsPropertyInitializer extends JsNodeImpl {
private JsExpression labelExpr;
private JsExpression valueExpr;
public JsPropertyInitializer(@NotNull JsExpression labelExpr) {
this.labelExpr = labelExpr;
}
public JsPropertyInitializer(@NotNull JsExpression labelExpr, @NotNull JsExpression valueExpr) {
this(labelExpr);
this.valueExpr = valueExpr;
}
public JsExpression getLabelExpr() {
return labelExpr;
}
public JsExpression getValueExpr() {
return valueExpr;
}
public boolean hasSideEffects() {
return labelExpr.hasSideEffects() || valueExpr.hasSideEffects();
}
public void setValueExpr(@NotNull JsExpression valueExpr) {
this.valueExpr = valueExpr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
labelExpr = v.accept(labelExpr);
valueExpr = v.accept(valueExpr);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.PROPERTY_INIT;
}
}
@@ -0,0 +1,64 @@
// 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 regular expression.
*/
public final class JsRegExp extends JsValueLiteral {
private String flags;
private String pattern;
public JsRegExp() {
}
public String getFlags() {
return flags;
}
public String getPattern() {
return pattern;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setFlags(String suffix) {
this.flags = suffix;
}
public void setPattern(String re) {
this.pattern = re;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.REGEXP;
}
}
@@ -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;
/**
* A JavaScript return statement.
*/
public final class JsReturn extends JsNodeImpl implements JsStatement {
private JsExpression expr;
public JsReturn() {
}
public JsReturn(JsExpression expr) {
this.expr = expr;
}
public JsExpression getExpr() {
return expr;
}
public void setExpr(JsExpression expr) {
this.expr = expr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (expr != null) {
expr = v.accept(expr);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.RETURN;
}
}
@@ -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 com.google.dart.compiler.backend.js.JsReservedIdentifiers;
/**
* 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(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,176 @@
// 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.Collections;
import java.util.Map;
/**
* 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 class JsScope {
@Nullable
private final String description;
private Map<String, JsName> names = Collections.emptyMap();
private final JsScope parent;
protected int tempIndex = 0;
private final String scopeId;
public JsScope(JsScope parent, @Nullable String description) {
this(parent, description, null);
}
public JsScope(JsScope parent) {
this(parent, null);
}
public JsScope(JsScope parent, @Nullable String description, @Nullable String scopeId) {
assert (parent != null);
this.scopeId = scopeId;
this.description = description;
this.parent = parent;
}
@NotNull
public JsScope innerScope(@Nullable String scopeName) {
return new JsScope(this, scopeName);
}
protected JsScope(@Nullable String description) {
this.description = description;
this.parent = null;
this.scopeId = null;
}
/**
* 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.
*/
public JsName declareName(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(String suggestedName) {
String name = suggestedName;
int counter = 0;
while (hasOwnName(name)) {
name = suggestedName + '_' + counter++;
}
return doCreateName(name);
}
private String getNextTempName() {
// introduced by the compiler
return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++;
}
/**
* 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.
*/
public JsName declareTemporary() {
return declareFreshName(getNextTempName());
}
/**
* 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(String ident) {
JsName name = findOwnName(ident);
if (name == null && parent != null) {
return parent.findName(ident);
}
return name;
}
protected boolean hasOwnName(@NotNull String name) {
return names.containsKey(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;
}
}
protected JsName doCreateName(String ident) {
JsName name = new JsName(this, ident);
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(String ident) {
return names.get(ident);
}
}
@@ -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.backend.js.ast;
public interface JsStatement extends JsNode {
}
@@ -0,0 +1,53 @@
// 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 string literal expression.
*/
public final class JsStringLiteral extends 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 boolean isBooleanFalse() {
return value.length() == 0;
}
@Override
public boolean isBooleanTrue() {
return value.length() != 0;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
v.visit(this, ctx);
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.STRING;
}
}
@@ -0,0 +1,47 @@
// 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.ArrayList;
import java.util.List;
/**
* A JavaScript switch statement.
*/
public class JsSwitch extends JsNodeImpl implements JsStatement {
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
private JsExpression expr;
public JsSwitch() {
super();
}
public List<JsSwitchMember> getCases() {
return cases;
}
public JsExpression getExpr() {
return expr;
}
public void setExpr(JsExpression expr) {
this.expr = expr;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
expr = v.accept(expr);
v.acceptWithInsertRemove(cases);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.SWITCH;
}
}
@@ -0,0 +1,24 @@
// 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 java.util.List;
/**
* A member/case in a JavaScript switch object.
*/
public abstract class JsSwitchMember extends JsNodeImpl {
protected final List<JsStatement> statements = new SmartList<JsStatement>();
protected JsSwitchMember() {
super();
}
public List<JsStatement> getStatements() {
return statements;
}
}
@@ -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;
public class JsThrow extends JsNodeImpl 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 traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
expression = v.accept(expression);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.THROW;
}
}
@@ -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.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* A JavaScript <code>try</code> statement.
*/
public class JsTry extends JsNodeImpl 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 List<JsCatch> getCatches() {
return catches;
}
public JsBlock getFinallyBlock() {
return finallyBlock;
}
public JsBlock getTryBlock() {
return tryBlock;
}
public void setFinallyBlock(JsBlock block) {
this.finallyBlock = block;
}
public void setTryBlock(JsBlock block) {
tryBlock = block;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
tryBlock = v.accept(tryBlock);
v.acceptWithInsertRemove(catches);
if (finallyBlock != null) {
finallyBlock = v.accept(finallyBlock);
}
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.TRY;
}
}
@@ -0,0 +1,53 @@
// 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 prefix or postfix operation.
*/
public abstract class JsUnaryOperation extends JsExpressionImpl {
private JsExpression arg;
private final JsUnaryOperator op;
public JsUnaryOperation(JsUnaryOperator op) {
this(op, null);
}
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
super();
this.op = op;
this.arg = arg;
}
public JsExpression getArg() {
return arg;
}
public JsUnaryOperator getOperator() {
return op;
}
@Override
public final boolean hasSideEffects() {
return op.isModifying() || arg.hasSideEffects();
}
public void setArg(JsExpression arg) {
this.arg = arg;
}
@Override
public void traverse(JsVisitor 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,23 @@
// 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 string literal expression.
*/
public abstract class JsValueLiteral extends JsLiteral {
protected JsValueLiteral() {
}
@Override
public final boolean hasSideEffects() {
return false;
}
@Override
public final boolean isLeaf() {
return true;
}
}
@@ -0,0 +1,137 @@
// 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.SourceInfo;
import com.google.dart.compiler.common.Symbol;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* A JavaScript <code>var</code> statement.
*/
public class JsVars extends JsNodeImpl 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(Collections.singletonList(var), false);
}
public JsVars(JsVar... vars) {
this(Arrays.asList(vars), false);
}
public boolean isMultiline() {
return multiline;
}
/**
* A var declared using the JavaScript <code>var</code> statement.
*/
public static class JsVar extends JsNodeImpl implements HasName {
private final 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 Symbol getSymbol() {
return name;
}
public void setInitExpression(JsExpression initExpression) {
this.initExpression = initExpression;
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
if (initExpression != null) {
initExpression = v.accept(initExpression);
}
}
v.endVisit(this, ctx);
}
@Override
public JsVar setSourceRef(SourceInfo info) {
super.setSourceRef(info);
return this;
}
@Override
public NodeKind getKind() {
return NodeKind.VAR;
}
}
public void add(JsVar var) {
vars.add(var);
}
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();
}
@Override
public void traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(vars);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.VARS;
}
}
@@ -0,0 +1,18 @@
// 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;
/**
* Abstracts the idea that a class can be traversed.
*/
public interface JsVisitable {
/**
* 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(JsVisitor visitor, JsContext ctx);
}
@@ -0,0 +1,435 @@
// 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;
import java.util.List;
/**
* Implemented by nodes that will visit child nodes.
*/
public class JsVisitor {
protected static final JsContext LVALUE_CONTEXT = new JsContext() {
@Override
public boolean canInsert() {
return false;
}
@Override
public boolean canRemove() {
return false;
}
@Override
public void insertAfter(JsVisitable node) {
throw new UnsupportedOperationException();
}
@Override
public void insertBefore(JsVisitable node) {
throw new UnsupportedOperationException();
}
@Override
public boolean isLvalue() {
return true;
}
@Override
public void removeMe() {
throw new UnsupportedOperationException();
}
@Override
public void replaceMe(JsVisitable node) {
throw new UnsupportedOperationException();
}
};
protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
@Override
public boolean canInsert() {
return false;
}
@Override
public boolean canRemove() {
return false;
}
@Override
public void insertAfter(JsVisitable node) {
throw new UnsupportedOperationException();
}
@Override
public void insertBefore(JsVisitable node) {
throw new UnsupportedOperationException();
}
@Override
public boolean isLvalue() {
return false;
}
@Override
public void removeMe() {
throw new UnsupportedOperationException();
}
@Override
public void replaceMe(JsVisitable node) {
throw new UnsupportedOperationException();
}
};
public final <T extends JsVisitable> T accept(T node) {
return this.doAccept(node);
}
public final <T extends JsVisitable> void acceptList(List<T> collection) {
doAcceptList(collection);
}
public JsExpression acceptLvalue(JsExpression expr) {
return doAcceptLvalue(expr);
}
public final <T extends JsVisitable> void acceptWithInsertRemove(List<T> collection) {
doAcceptWithInsertRemove(collection);
}
public boolean didChange() {
throw new UnsupportedOperationException();
}
public void endVisit(JsArrayAccess x, JsContext ctx) {
}
public void endVisit(JsArrayLiteral x, JsContext ctx) {
}
public void endVisit(JsBinaryOperation x, JsContext ctx) {
}
public void endVisit(JsBlock x, JsContext ctx) {
}
public void endVisit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
}
public void endVisit(JsBreak x, JsContext ctx) {
}
public void endVisit(JsCase x, JsContext ctx) {
}
public void endVisit(JsCatch x, JsContext ctx) {
}
public void endVisit(JsConditional x, JsContext ctx) {
}
public void endVisit(JsContinue x, JsContext ctx) {
}
public void endVisit(JsDebugger x, JsContext ctx) {
}
public void endVisit(JsDefault x, JsContext ctx) {
}
public void endVisit(JsDoWhile x, JsContext ctx) {
}
public void endVisit(JsEmpty x, JsContext ctx) {
}
public void endVisit(JsExprStmt x, JsContext ctx) {
}
public void endVisit(JsFor x, JsContext ctx) {
}
public void endVisit(JsForIn x, JsContext ctx) {
}
public void endVisit(JsFunction x, JsContext ctx) {
}
public void endVisit(JsIf x, JsContext ctx) {
}
public void endVisit(JsInvocation x, JsContext ctx) {
}
public void endVisit(JsLabel x, JsContext ctx) {
}
public void endVisit(JsNameRef x, JsContext ctx) {
}
public void endVisit(JsNew x, JsContext ctx) {
}
public void endVisit(JsNullLiteral x, JsContext ctx) {
}
public void endVisit(JsNumberLiteral x, JsContext ctx) {
}
public void endVisit(JsObjectLiteral x, JsContext ctx) {
}
public void endVisit(JsParameter x, JsContext ctx) {
}
public void endVisit(JsPostfixOperation x, JsContext ctx) {
}
public void endVisit(JsPrefixOperation x, JsContext ctx) {
}
public void endVisit(JsProgram x, JsContext ctx) {
}
public void endVisit(JsProgramFragment x, JsContext ctx) {
}
public void endVisit(JsPropertyInitializer x, JsContext ctx) {
}
public void endVisit(JsRegExp x, JsContext ctx) {
}
public void endVisit(JsReturn x, JsContext ctx) {
}
public void endVisit(JsStringLiteral x, JsContext ctx) {
}
public void endVisit(JsSwitch x, JsContext ctx) {
}
public void endVisit(JsLiteral.JsThisRef x, JsContext ctx) {
}
public void endVisit(JsThrow x, JsContext ctx) {
}
public void endVisit(JsTry x, JsContext ctx) {
}
public void endVisit(JsVar x, JsContext ctx) {
}
public void endVisit(JsVars x, JsContext ctx) {
}
public void endVisit(JsWhile x, JsContext ctx) {
}
public boolean visit(JsArrayAccess x, JsContext ctx) {
return true;
}
public boolean visit(JsArrayLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsBinaryOperation x, JsContext ctx) {
return true;
}
public boolean visit(JsBlock x, JsContext ctx) {
return true;
}
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsBreak x, JsContext ctx) {
return true;
}
public boolean visit(JsCase x, JsContext ctx) {
return true;
}
public boolean visit(JsCatch x, JsContext ctx) {
return true;
}
public boolean visit(JsConditional x, JsContext ctx) {
return true;
}
public boolean visit(JsContinue x, JsContext ctx) {
return true;
}
public boolean visit(JsDebugger x, JsContext ctx) {
return true;
}
public boolean visit(JsDefault x, JsContext ctx) {
return true;
}
public boolean visit(JsDoWhile x, JsContext ctx) {
return true;
}
public boolean visit(JsEmpty x, JsContext ctx) {
return true;
}
public boolean visit(JsExprStmt x, JsContext ctx) {
return true;
}
public boolean visit(JsFor x, JsContext ctx) {
return true;
}
public boolean visit(JsForIn x, JsContext ctx) {
return true;
}
public boolean visit(JsFunction x, JsContext ctx) {
return true;
}
public boolean visit(JsIf x, JsContext ctx) {
return true;
}
public boolean visit(JsInvocation x, JsContext ctx) {
return true;
}
public boolean visit(JsLabel x, JsContext ctx) {
return true;
}
public boolean visit(JsNameRef x, JsContext ctx) {
return true;
}
public boolean visit(JsNew x, JsContext ctx) {
return true;
}
public boolean visit(JsNullLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsObjectLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsParameter x, JsContext ctx) {
return true;
}
public boolean visit(JsPostfixOperation x, JsContext ctx) {
return true;
}
public boolean visit(JsPrefixOperation x, JsContext ctx) {
return true;
}
public boolean visit(JsProgram x, JsContext ctx) {
return true;
}
public boolean visit(JsProgramFragment x, JsContext ctx) {
return true;
}
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
return true;
}
public boolean visit(JsRegExp x, JsContext ctx) {
return true;
}
public boolean visit(JsReturn x, JsContext ctx) {
return true;
}
public boolean visit(JsStringLiteral x, JsContext ctx) {
return true;
}
public boolean visit(JsSwitch x, JsContext ctx) {
return true;
}
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
return true;
}
public boolean visit(JsThrow x, JsContext ctx) {
return true;
}
public boolean visit(JsTry x, JsContext ctx) {
return true;
}
public boolean visit(JsVar x, JsContext ctx) {
return true;
}
public boolean visit(JsVars x, JsContext ctx) {
return true;
}
public boolean visit(JsWhile x, JsContext ctx) {
return true;
}
protected <T extends JsVisitable> T doAccept(T node) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
return node;
}
protected <T extends JsVisitable> void doAcceptList(List<T> collection) {
for (T node : collection) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
}
}
protected JsExpression doAcceptLvalue(JsExpression expr) {
doTraverse(expr, LVALUE_CONTEXT);
return expr;
}
protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
for (T node : collection) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
}
}
protected void doTraverse(JsVisitable node, JsContext ctx) {
node.traverse(this, ctx);
}
}
@@ -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;
/**
* A JavaScript <code>while</code> statement.
*/
public class JsWhile extends JsNodeImpl 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 traverse(JsVisitor v, JsContext ctx) {
if (v.visit(this, ctx)) {
condition = v.accept(condition);
body = v.accept(body);
}
v.endVisit(this, ctx);
}
@Override
public NodeKind getKind() {
return NodeKind.WHILE;
}
}
@@ -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;
enum NodeKind {
ARRAY_ACCESS,
ARRAY,
BINARY_OP,
BLOCK,
BOOLEAN,
BREAK,
CASE,
CATCH,
CONDITIONAL,
CONTINUE,
DEBUGGER,
DEFAULT,
DO,
EMPTY,
EXPRESSION_STMT,
FOR,
FOR_IN,
FUNCTION,
IF,
INVOKE,
LABEL,
NAME_REF,
NEW,
NULL,
NUMBER,
OBJECT,
PARAMETER,
POSTFIX_OP,
PREFIX_OP,
PROGRAM,
PROGRAM_FRAGMENT,
PROPERTY_INIT,
REGEXP,
RETURN,
STRING,
SWITCH,
THIS,
THROW,
TRY,
VARS,
VAR,
WHILE
}
@@ -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.common;
import com.google.dart.compiler.Source;
public class AbstractNode implements SourceInfo, HasSourceInfo {
protected SourceInfo sourceInfo;
@Override
public Source getSource() {
return sourceInfo.getSource();
}
@Override
public int getLine() {
return sourceInfo.getLine();
}
@Override
public int getColumn() {
return sourceInfo.getColumn();
}
@Override
public int getStart() {
return sourceInfo.getStart();
}
@Override
public int getLength() {
return sourceInfo.getLength();
}
@Override
public SourceInfo getSourceInfo() {
return this;
}
@Override
public void setSourceInfo(SourceInfo info) {
sourceInfo = info;
}
@Override
public final void setSourceLocation(Source source, int line, int column, int startPosition, int length) {
sourceInfo = new SourceInfoImpl(source, line, column, startPosition, length);
}
public final void setSourceRange(int startPosition, int length) {
//Preconditions.checkArgument(startPosition != -1 && length >= 0 || startPosition == -1 && length == 0);
//sourceInfo.sourceStart = startPosition;
//sourceInfo.sourceLength = length;
}
}
@@ -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.common;
import com.google.dart.compiler.Source;
/**
* Abstract view of a class that has source info.
*/
public interface HasSourceInfo {
/**
* Return the source info associated with this object.
*/
SourceInfo getSourceInfo();
/**
* Set the source info associated with this object. May only be called once.
* @param info
*/
void setSourceInfo(SourceInfo info);
/**
* Sets the source range of the original source file where the source fragment
* corresponding to this node was found.
*
* <p>
* Each node in the subtree (other than the contrived nodes) carries source
* range(s) information relating back to positions in the given source (the
* given source itself is not remembered with the AST). The source range
* usually begins at the first character of the first token corresponding to
* the node; leading whitespace and comments are <b>not</b> included. The
* source range usually extends through the last character of the last token
* corresponding to the node; trailing whitespace and comments are <b>not</b>
* included. There are a handful of exceptions (including the various body
* declarations). Source ranges nest properly: the source range for a child is
* always within the source range of its parent, and the source ranges of
* sibling nodes never overlap.
*
* @param source the associated source
* @param line the 1-based line index, or <code>-1</code>, if no source
* location is available
* @param column the 1-based column index, or <code>-1</code>, if no source
* location is available
* @param startPosition a 0-based character index, or <code>-1</code>, if no
* source location is available
* @param length a (possibly 0) length, or <code>-1</code>, if no source
* location is available
* @see SourceInfo#getStart()
* @see SourceInfo#getLength()
*/
void setSourceLocation(Source source, int line, int column, int startPosition, int length);
}
@@ -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.common;
/**
* @author johnlenz@google.com (John Lenz)
*/
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,11 @@
// 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;
/**
* @author johnlenz@google.com (John Lenz)
*/
public interface Symbol {
}
@@ -0,0 +1,49 @@
// 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.*;
/**
* @author johnlenz@google.com (John Lenz)
*/
public final class AstUtil {
private AstUtil() {
}
public static JsNameRef newQualifiedNameRef(String name) {
JsNameRef node = null;
int endPos;
int startPos = 0;
do {
endPos = name.indexOf('.', startPos);
String part = (endPos == -1
? name.substring(startPos)
: name.substring(startPos, endPos));
node = new JsNameRef(part, node);
startPos = endPos + 1;
}
while (endPos != -1);
return node;
}
/**
* 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;
}
}
@@ -0,0 +1,267 @@
// 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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Utility methods for operating on memory-efficient lists. All lists of size 0
* or 1 are assumed to be immutable. All lists of size greater than 1 are
* assumed to be mutable.
*/
public class Lists {
private Lists() {
}
public static <T> List<T> add(List<T> list, int index, T toAdd) {
switch (list.size()) {
case 0:
// Empty -> Singleton
if (index != 0) {
throw newIndexOutOfBounds(list, index);
}
return Collections.singletonList(toAdd);
case 1: {
// Singleton -> ArrayList
List<T> result = new ArrayList<T>(2);
switch (index) {
case 0:
result.add(toAdd);
result.add(list.get(0));
return result;
case 1:
result.add(list.get(0));
result.add(toAdd);
return result;
default:
throw newIndexOutOfBounds(list, index);
}
}
default:
// ArrayList
list.add(index, toAdd);
return list;
}
}
public static <T> List<T> add(List<T> list, T toAdd) {
switch (list.size()) {
case 0:
// Empty -> Singleton
return Collections.singletonList(toAdd);
case 1: {
// Singleton -> ArrayList
List<T> result = new ArrayList<T>(2);
result.add(list.get(0));
result.add(toAdd);
return result;
}
default:
// ArrayList
list.add(toAdd);
return list;
}
}
public static <T> List<T> addAll(List<T> list, int index, List<T> toAdd) {
switch (toAdd.size()) {
case 0:
// No-op.
return list;
case 1:
// Add one element.
return add(list, index, toAdd.get(0));
default:
// True list merge, result >= 2.
switch (list.size()) {
case 0:
if (index != 0) {
throw newIndexOutOfBounds(list, index);
}
return new ArrayList<T>(toAdd);
case 1: {
List<T> result = new ArrayList<T>(1 + toAdd.size());
switch (index) {
case 0:
result.addAll(toAdd);
result.add(list.get(0));
return result;
case 1:
result.add(list.get(0));
result.addAll(toAdd);
return result;
default:
throw newIndexOutOfBounds(list, index);
}
}
default:
list.addAll(index, toAdd);
return list;
}
}
}
public static <T> List<T> addAll(List<T> list, List<T> toAdd) {
switch (toAdd.size()) {
case 0:
// No-op.
return list;
case 1:
// Add one element.
return add(list, toAdd.get(0));
default:
// True list merge, result >= 2.
switch (list.size()) {
case 0:
return new ArrayList<T>(toAdd);
case 1: {
List<T> result = new ArrayList<T>(1 + toAdd.size());
result.add(list.get(0));
result.addAll(toAdd);
return result;
}
default:
list.addAll(toAdd);
return list;
}
}
}
public static <T> List<T> addAll(List<T> list, T... toAdd) {
switch (toAdd.length) {
case 0:
// No-op.
return list;
case 1:
// Add one element.
return add(list, toAdd[0]);
default:
// True list merge, result >= 2.
switch (list.size()) {
case 0:
return new ArrayList<T>(Arrays.asList(toAdd));
case 1: {
List<T> result = new ArrayList<T>(1 + toAdd.length);
result.add(list.get(0));
result.addAll(Arrays.asList(toAdd));
return result;
}
default:
list.addAll(Arrays.asList(toAdd));
return list;
}
}
}
public static <T> List<T> create() {
return Collections.emptyList();
}
public static <T> List<T> create(Collection<T> collection) {
switch (collection.size()) {
case 0:
return create();
default:
return new ArrayList<T>(collection);
}
}
public static <T> List<T> create(List<T> list) {
switch (list.size()) {
case 0:
return create();
case 1:
return create(list.get(0));
default:
return new ArrayList<T>(list);
}
}
public static <T> List<T> create(T item) {
return Collections.singletonList(item);
}
public static <T> List<T> create(T... items) {
switch (items.length) {
case 0:
return create();
case 1:
return create(items[0]);
default:
return new ArrayList<T>(Arrays.asList(items));
}
}
public static <T> List<T> remove(List<T> list, int toRemove) {
switch (list.size()) {
case 0:
// Empty
throw newIndexOutOfBounds(list, toRemove);
case 1:
// Singleton -> Empty
if (toRemove == 0) {
return Collections.emptyList();
} else {
throw newIndexOutOfBounds(list, toRemove);
}
case 2:
// ArrayList -> Singleton
switch (toRemove) {
case 0:
return Collections.singletonList(list.get(1));
case 1:
return Collections.singletonList(list.get(0));
default:
throw newIndexOutOfBounds(list, toRemove);
}
default:
// ArrayList
list.remove(toRemove);
return list;
}
}
public static <T> List<T> set(List<T> list, int index, T e) {
switch (list.size()) {
case 0:
// Empty
throw newIndexOutOfBounds(list, index);
case 1:
// Singleton
if (index == 0) {
return Collections.singletonList(e);
} else {
throw newIndexOutOfBounds(list, index);
}
default:
// ArrayList
list.set(index, e);
return list;
}
}
public static <T extends Comparable<? super T>> List<T> sort(List<T> list) {
if (list.size() > 1) {
Collections.sort(list);
}
return list;
}
public static <T> List<T> sort(List<T> list, Comparator<? super T> sort) {
if (list.size() > 1) {
Collections.sort(list, sort);
}
return list;
}
private static <T> IndexOutOfBoundsException newIndexOutOfBounds(List<T> list, int index) {
return new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size());
}
}
@@ -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,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.util;
/**
* Interface used for printing text output.
*/
public interface TextOutput {
int getPosition();
int getLine();
int getColumn();
void indentIn();
void indentOut();
void newline();
void newlineOpt();
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);
}
@@ -0,0 +1,174 @@
// 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;
/**
* An abstract base type to build TextOutput implementations.
*/
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;
public TextOutputImpl() {
this(false);
}
public TextOutputImpl(boolean compact) {
this.compact = compact;
this.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;
}
@Override
public void newlineOpt() {
if (!compact) {
newline();
}
}
@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;
justNewlined = false;
}
@Override
public void print(char[] s) {
maybeIndent();
printAndCount(s);
justNewlined = false;
}
@Override
public void print(CharSequence s) {
maybeIndent();
printAndCount(s);
justNewlined = false;
}
@Override
public void printOpt(char c) {
if (!compact) {
maybeIndent();
out.append(c);
position++;
column++;
}
}
@Override
public void printOpt(char[] s) {
if (!compact) {
maybeIndent();
printAndCount(s);
}
}
@Override
public void printOpt(String s) {
if (!compact) {
maybeIndent();
printAndCount(s);
}
}
private void maybeIndent() {
if (justNewlined && !compact) {
printAndCount(indents[identLevel]);
justNewlined = false;
}
}
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);
}
}