Imported dart-ast from https://github.com/develar/former-dast-ast to js/js.dart-ast

This commit is contained in:
Erokhin Stanislav
2014-01-27 17:28:30 +04:00
95 changed files with 5608 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
former-dast-ast
+10
View File
@@ -0,0 +1,10 @@
<component name="ArtifactManager">
<artifact build-on-make="true" 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>
+10
View File
@@ -0,0 +1,10 @@
<component name="ArtifactManager">
<artifact build-on-make="true" name="dart-ast-src">
<output-path>$PROJECT_DIR$/out/artifacts</output-path>
<root id="root">
<element id="archive" name="dart-ast-src.jar">
<element id="dir-copy" path="$PROJECT_DIR$/src" />
</element>
</root>
</artifact>
</component>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
</option>
</component>
</project>
+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>
@@ -0,0 +1,62 @@
<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" />
<inspection_tool class="UnusedCatchParameter" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_ignoreCatchBlocksWithComments" value="false" />
<option name="m_ignoreTestCases" value="false" />
</inspection_tool>
</profile>
</component>
@@ -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>
+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>
+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.
+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>
@@ -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,95 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js;
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 RecursiveJsVisitor {
public static boolean exec(JsExpression expression) {
if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return true;
}
JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
visitor.accept(expression);
return visitor.containsInvocation;
}
private boolean containsInvocation;
private JsConstructExpressionVisitor() {
}
/**
* We only look at the array expression since the index has its own scope.
*/
@Override
public void visitArrayAccess(JsArrayAccess x) {
accept(x.getArrayExpression());
}
/**
* Array literals have their own scoping.
*/
@Override
public void visitArray(JsArrayLiteral x) {
}
/**
* Functions have their own scoping.
*/
@Override
public void visitFunction(JsFunction x) {
}
@Override
public void visitInvocation(JsInvocation invocation) {
containsInvocation = true;
}
@Override
public void visitNameRef(JsNameRef nameRef) {
if (!nameRef.isLeaf()) {
accept(nameRef.getQualifier());
}
}
/**
* New constructs bind to the nearest set of parentheses.
*/
@Override
public void visitNew(JsNew x) {
}
/**
* Object literals have their own scope.
*/
@Override
public void visitObjectLiteral(JsObjectLiteral x) {
}
/**
* We only look at nodes that would not normally be surrounded by parentheses.
*/
@Override
public <T extends JsNode> void accept(T node) {
// Assign to Object to prevent 'inconvertible types' compile errors due
// to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
// reproducible in jdk1.6.0_02.
if (node instanceof JsExpression) {
JsExpression expression = (JsExpression) node;
int precedence = JsPrecedenceVisitor.exec(expression);
// Only visit expressions that won't automatically be surrounded by
// parentheses
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return;
}
}
super.accept(node);
}
}
@@ -0,0 +1,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.*;
import com.google.dart.compiler.backend.js.ast.JsExpressionStatement;
/**
* Determines if an expression statement needs to be surrounded by parentheses.
* <p/>
* The statement or the left-most expression needs to be surrounded by
* parentheses if the left-most expression is an object literal or a function
* object. Function declarations do not need parentheses.
* <p/>
* For example the following require parentheses:<br>
* <ul>
* <li>{ key : 'value'}</li>
* <li>{ key : 'value'}.key</li>
* <li>function () {return 1;}()</li>
* <li>function () {return 1;}.prototype</li>
* </ul>
* <p/>
* The following do not require parentheses:<br>
* <ul>
* <li>var x = { key : 'value'}</li>
* <li>"string" + { key : 'value'}.key</li>
* <li>function func() {}</li>
* <li>function() {}</li>
* </ul>
*/
public class JsFirstExpressionVisitor extends RecursiveJsVisitor {
public static boolean exec(JsExpressionStatement statement) {
JsExpression expression = statement.getExpression();
// Pure function declarations do not need parentheses
if (expression instanceof JsFunction) {
return false;
}
JsFirstExpressionVisitor visitor = new JsFirstExpressionVisitor();
visitor.accept(statement.getExpression());
return visitor.needsParentheses;
}
private boolean needsParentheses = false;
private JsFirstExpressionVisitor() {
}
@Override
public void visitArrayAccess(JsArrayAccess x) {
accept(x.getArrayExpression());
}
@Override
public void visitArray(JsArrayLiteral x) {
}
@Override
public void visitBinaryExpression(JsBinaryOperation x) {
accept(x.getArg1());
}
@Override
public void visitConditional(JsConditional x) {
accept(x.getTestExpression());
}
@Override
public void visitFunction(JsFunction x) {
needsParentheses = true;
}
@Override
public void visitInvocation(JsInvocation invocation) {
accept(invocation.getQualifier());
}
@Override
public void visitNameRef(JsNameRef nameRef) {
if (!nameRef.isLeaf()) {
accept(nameRef.getQualifier());
}
}
@Override
public void visitNew(JsNew x) {
}
@Override
public void visitObjectLiteral(JsObjectLiteral x) {
needsParentheses = true;
}
@Override
public void visitPostfixOperation(JsPostfixOperation x) {
accept(x.getArg());
}
@Override
public void visitPrefixOperation(JsPrefixOperation x) {
}
}
@@ -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 com.google.dart.compiler.backend.js.ast.*;
/**
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
* 57)
* <p/>
* Precedence 17 is for indivisible primaries that either don't have children,
* or provide their own delimiters.
* <p/>
* Precedence 16 is for really important things that have their own AST classes.
* <p/>
* Precedence 15 is for the new construct.
* <p/>
* Precedence 14 is for unary operators.
* <p/>
* Precedences 12 through 4 are for non-assigning binary operators.
* <p/>
* Precedence 3 is for the tertiary conditional.
* <p/>
* Precedence 2 is for assignments.
* <p/>
* Precedence 1 is for comma operations.
*/
class JsPrecedenceVisitor extends JsVisitor {
static final int PRECEDENCE_NEW = 15;
private int answer = -1;
private JsPrecedenceVisitor() {
}
public static int exec(JsExpression expression) {
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
visitor.accept(expression);
if (visitor.answer < 0) {
throw new RuntimeException("Precedence must be >= 0!");
}
return visitor.answer;
}
@Override
public void visitArrayAccess(JsArrayAccess x) {
answer = 16;
}
@Override
public void visitArray(JsArrayLiteral x) {
answer = 17; // primary
}
@Override
public void visitBinaryExpression(JsBinaryOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitBoolean(JsLiteral.JsBooleanLiteral x) {
answer = 17; // primary
}
@Override
public void visitConditional(JsConditional x) {
answer = 3;
}
@Override
public void visitFunction(JsFunction x) {
answer = 17; // primary
}
@Override
public void visitInvocation(JsInvocation invocation) {
answer = 16;
}
@Override
public void visitNameRef(JsNameRef nameRef) {
if (nameRef.isLeaf()) {
answer = 17; // primary
}
else {
answer = 16; // property access
}
}
@Override
public void visitNew(JsNew x) {
answer = PRECEDENCE_NEW;
}
@Override
public void visitNull(JsNullLiteral x) {
answer = 17; // primary
}
@Override
public void visitInt(JsNumberLiteral.JsIntLiteral x) {
answer = 17; // primary
}
@Override
public void visitDouble(JsNumberLiteral.JsDoubleLiteral x) {
answer = 17; // primary
}
@Override
public void visitObjectLiteral(JsObjectLiteral x) {
answer = 17; // primary
}
@Override
public void visitPostfixOperation(JsPostfixOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitPrefixOperation(JsPrefixOperation x) {
answer = x.getOperator().getPrecedence();
}
@Override
public void visitPropertyInitializer(JsPropertyInitializer x) {
answer = 17; // primary
}
@Override
public void visitRegExp(JsRegExp x) {
answer = 17; // primary
}
@Override
public void visitString(JsStringLiteral x) {
answer = 17; // primary
}
@Override
public void visitThis(JsLiteral.JsThisRef x) {
answer = 17; // primary
}
@Override
protected void visitElement(JsNode node) {
throw new RuntimeException("Only expressions have precedence.");
}
}
@@ -0,0 +1,80 @@
// 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.*;
/**
* Determines if a statement at the end of a block requires a semicolon.
* <p/>
* For example, the following statements require semicolons:<br>
* <ul>
* <li>if (cond);</li>
* <li>while (cond);</li>
* </ul>
* <p/>
* The following do not require semicolons:<br>
* <ul>
* <li>return 1</li>
* <li>do {} while(true)</li>
* </ul>
*/
public class JsRequiresSemiVisitor extends JsVisitor {
private boolean needsSemicolon;
private JsRequiresSemiVisitor() {
}
public static boolean exec(JsStatement lastStatement) {
JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor();
visitor.accept(lastStatement);
return visitor.needsSemicolon;
}
@Override
public void visitFor(JsFor x) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
}
@Override
public void visitForIn(JsForIn x) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
}
@Override
public void visitIf(JsIf x) {
JsStatement thenStmt = x.getThenStatement();
JsStatement elseStmt = x.getElseStatement();
JsStatement toCheck = thenStmt;
if (elseStmt != null) {
toCheck = elseStmt;
}
if (toCheck instanceof JsEmpty) {
needsSemicolon = true;
}
else {
// Must recurse to determine last statement (possible if-else chain).
accept(toCheck);
}
}
@Override
public void visitLabel(JsLabel x) {
if (x.getStatement() instanceof JsEmpty) {
needsSemicolon = true;
}
}
@Override
public void visitWhile(JsWhile x) {
if (x.getBody() instanceof JsEmpty) {
needsSemicolon = true;
}
}
}
@@ -0,0 +1,151 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js;
import gnu.trove.THashSet;
import java.util.Collections;
import java.util.Set;
/**
* Determines whether or not a particular string is a JavaScript keyword or not.
*/
public class JsReservedIdentifiers {
public static final Set<String> reservedGlobalSymbols;
static {
String[] commonBuiltins = new String[] {
// 15.1.1 Value Properties of the Global Object
"NaN", "Infinity", "undefined",
// 15.1.2 Function Properties of the Global Object
"eval", "parseInt", "parseFloat", "isNan", "isFinite",
// 15.1.3 URI Handling Function Properties
"decodeURI", "decodeURIComponent",
"encodeURI",
"encodeURIComponent",
// 15.1.4 Constructor Properties of the Global Object
"Object", "Function", "Array", "String", "Boolean", "Number", "Date",
"RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
"SyntaxError", "TypeError", "URIError",
// 15.1.5 Other Properties of the Global Object
"Math",
// 10.1.6 Activation Object
"arguments",
// B.2 Additional Properties (non-normative)
"escape", "unescape",
// Window props (https://developer.mozilla.org/en/DOM/window)
"applicationCache", "closed", "Components", "content", "controllers",
"crypto", "defaultStatus", "dialogArguments", "directories",
"document", "frameElement", "frames", "fullScreen", "globalStorage",
"history", "innerHeight", "innerWidth", "length",
"location", "locationbar", "localStorage", "menubar",
"mozInnerScreenX", "mozInnerScreenY", "mozScreenPixelsPerCssPixel",
"name", "navigator", "opener", "outerHeight", "outerWidth",
"pageXOffset", "pageYOffset", "parent", "personalbar", "pkcs11",
"returnValue", "screen", "scrollbars", "scrollMaxX", "scrollMaxY",
"self", "sessionStorage", "sidebar", "status", "statusbar", "toolbar",
"top", "window",
// Window methods (https://developer.mozilla.org/en/DOM/window)
"alert", "addEventListener", "atob", "back", "blur", "btoa",
"captureEvents", "clearInterval", "clearTimeout", "close", "confirm",
"disableExternalCapture", "dispatchEvent", "dump",
"enableExternalCapture", "escape", "find", "focus", "forward",
"GeckoActiveXObject", "getAttention", "getAttentionWithCycleCount",
"getComputedStyle", "getSelection", "home", "maximize", "minimize",
"moveBy", "moveTo", "open", "openDialog", "postMessage", "print",
"prompt", "QueryInterface", "releaseEvents", "removeEventListener",
"resizeBy", "resizeTo", "restore", "routeEvent", "scroll", "scrollBy",
"scrollByLines", "scrollByPages", "scrollTo", "setInterval",
"setResizeable", "setTimeout", "showModalDialog", "sizeToContent",
"stop", "uuescape", "updateCommands", "XPCNativeWrapper",
"XPCSafeJSOjbectWrapper",
// Mozilla Window event handlers, same cite
"onabort", "onbeforeunload", "onchange", "onclick", "onclose",
"oncontextmenu", "ondragdrop", "onerror", "onfocus", "onhashchange",
"onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown",
"onmousemove", "onmouseout", "onmouseover", "onmouseup",
"onmozorientation", "onpaint", "onreset", "onresize", "onscroll",
"onselect", "onsubmit", "onunload",
// Safari Web Content Guide
// http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
// WebKit Window member data, from WebKit DOM Reference
// (http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/WebKitDOMRef/DOMWindow_idl/Classes/DOMWindow/index.html)
// TODO(fredsa) Many, many more functions and member data to add
"ontouchcancel", "ontouchend", "ontouchmove", "ontouchstart",
"ongesturestart", "ongesturechange", "ongestureend",
// extra window methods
"uneval",
// keywords https://developer.mozilla.org/en/New_in_JavaScript_1.7,
// https://developer.mozilla.org/en/New_in_JavaScript_1.8.1
"getPrototypeOf", "let", "yield",
// "future reserved words"
"abstract", "int", "short", "boolean", "interface", "static", "byte",
"long", "char", "final", "native", "synchronized", "float", "package",
"throws", "goto", "private", "transient", "implements", "protected",
"volatile", "double", "public",
// IE methods
// (http://msdn.microsoft.com/en-us/library/ms535873(VS.85).aspx#)
"attachEvent", "clientInformation", "clipboardData", "createPopup",
"dialogHeight", "dialogLeft", "dialogTop", "dialogWidth",
"onafterprint", "onbeforedeactivate", "onbeforeprint",
"oncontrolselect", "ondeactivate", "onhelp", "onresizeend",
// Common browser-defined identifiers not defined in ECMAScript
"event", "external", "Debug", "Enumerator", "Global", "Image",
"ActiveXObject", "VBArray", "Components",
// Functions commonly defined on Object
"toString", "getClass", "constructor", "prototype", "valueOf",
// Client-side JavaScript identifiers, which are needed for linkers
// that don't ensure GWT's window != $wnd, document != $doc, etc.
// Taken from the Rhino book, pg 715
"Anchor", "Applet", "Attr", "Canvas", "CanvasGradient",
"CanvasPattern", "CanvasRenderingContext2D", "CDATASection",
"CharacterData", "Comment", "CSS2Properties", "CSSRule",
"CSSStyleSheet", "Document", "DocumentFragment", "DocumentType",
"DOMException", "DOMImplementation", "DOMParser", "Element", "Event",
"ExternalInterface", "FlashPlayer", "Form", "Frame", "History",
"HTMLCollection", "HTMLDocument", "HTMLElement", "IFrame", "Image",
"Input", "JSObject", "KeyEvent", "Link", "Location", "MimeType",
"MouseEvent", "Navigator", "Node", "NodeList", "Option", "Plugin",
"ProcessingInstruction", "Range", "RangeException", "Screen", "Select",
"Table", "TableCell", "TableRow", "TableSelection", "Text", "TextArea",
"UIEvent", "Window", "XMLHttpRequest", "XMLSerializer",
"XPathException", "XPathResult", "XSLTProcessor",
// These keywords trigger the loading of the java-plugin. For the
// next-generation plugin, this results in starting a new Java process.
"java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
"JavaArray", "JavaMember",
// GWT-defined identifiers
"$wnd", "$doc", "$entry", "$moduleName", "$moduleBase", "$gwt_version", "$sessionId",
// Identifiers used by JsStackEmulator; later set to obfuscatable
"$stack", "$stackDepth", "$location",
};
reservedGlobalSymbols = new THashSet<String>(commonBuiltins.length);
Collections.addAll(reservedGlobalSymbols, commonBuiltins);
}
private JsReservedIdentifiers() {
}
}
@@ -0,0 +1,13 @@
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
import com.google.dart.compiler.util.TextOutputImpl;
abstract class AbstractNode implements JsNode {
@Override
public String toString() {
TextOutputImpl out = new TextOutputImpl();
new JsToStringGenerationVisitor(out).accept(this);
return out.toString();
}
}
@@ -0,0 +1,51 @@
package com.google.dart.compiler.backend.js.ast;
public class ChameleonJsExpression implements JsExpression {
private JsExpression expression;
public ChameleonJsExpression(JsExpression initialExpression) {
expression = initialExpression;
}
public ChameleonJsExpression() {
}
public void resolve(JsExpression expression) {
this.expression = expression;
}
@Override
public boolean isLeaf() {
return expression.isLeaf();
}
@Override
public JsStatement makeStmt() {
return expression.makeStmt();
}
@Override
public void accept(JsVisitor visitor) {
expression.accept(visitor);
}
@Override
public void acceptChildren(JsVisitor visitor) {
expression.acceptChildren(visitor);
}
@Override
public Object getSource() {
return expression.getSource();
}
@Override
public void setSource(Object info) {
expression.setSource(info);
}
@Override
public JsExpression source(Object info) {
return expression.source(info);
}
}
@@ -0,0 +1,14 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import java.util.List;
/**
* Implemented by JavaScript objects that accept arguments.
*/
public interface HasArguments 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,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.backend.js.ast;
/**
* Represents a javascript expression for array access.
*/
public final class JsArrayAccess extends JsExpressionImpl {
private JsExpression arrayExpression;
private JsExpression indexExpression;
public JsArrayAccess() {
super();
}
public JsArrayAccess(JsExpression arrayExpression, JsExpression indexExpression) {
this.arrayExpression = arrayExpression;
this.indexExpression = indexExpression;
}
public JsExpression getArrayExpression() {
return arrayExpression;
}
public JsExpression getIndexExpression() {
return indexExpression;
}
public void setArrayExpression(JsExpression arrayExpression) {
this.arrayExpression = arrayExpression;
}
public void setIndexExpression(JsExpression indexExpression) {
this.indexExpression = indexExpression;
}
@Override
public void accept(JsVisitor v) {
v.visitArrayAccess(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(arrayExpression);
visitor.accept(indexExpression);
}
}
@@ -0,0 +1,38 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import 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 void accept(JsVisitor v) {
v.visitArray(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(expressions);
}
}
@@ -0,0 +1,51 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import org.jetbrains.annotations.Nullable;
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 void accept(JsVisitor v) {
v.visitBinaryExpression(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (op.isAssignment()) {
visitor.acceptLvalue(arg1);
}
else {
visitor.accept(arg1);
}
visitor.accept(arg2);
}
}
@@ -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,55 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
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 SourceInfoAwareJsNode 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 accept(JsVisitor v) {
v.visitBlock(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(statements);
}
}
@@ -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;
/**
* Represents the JavaScript break statement.
*/
public final class JsBreak extends JsContinue {
public JsBreak() {
super(null);
}
public JsBreak(String label) {
super(label);
}
@Override
public void accept(JsVisitor v) {
v.visitBreak(this);
}
}
@@ -0,0 +1,35 @@
// 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 caseExpression;
public JsCase() {
super();
}
public JsExpression getCaseExpression() {
return caseExpression;
}
public void setCaseExpression(JsExpression caseExpression) {
this.caseExpression = caseExpression;
}
@Override
public void accept(JsVisitor v) {
v.visitCase(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(caseExpression);
super.acceptChildren(visitor);
}
}
@@ -0,0 +1,63 @@
// 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 SourceInfoAwareJsNode 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 accept(JsVisitor v) {
v.visitCatch(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(param);
if (condition != null) {
visitor.accept(condition);
}
visitor.accept(body);
}
}
@@ -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,56 @@
// 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 JsConditional extends JsExpressionImpl {
private JsExpression testExpression;
private JsExpression elseExpression;
private JsExpression thenExpression;
public JsConditional() {
}
public JsConditional(JsExpression testExpression, JsExpression thenExpression, JsExpression elseExpression) {
this.testExpression = testExpression;
this.thenExpression = thenExpression;
this.elseExpression = elseExpression;
}
public JsExpression getElseExpression() {
return elseExpression;
}
public JsExpression getTestExpression() {
return testExpression;
}
public JsExpression getThenExpression() {
return thenExpression;
}
public void setElseExpression(JsExpression elseExpression) {
this.elseExpression = elseExpression;
}
public void setTestExpression(JsExpression testExpression) {
this.testExpression = testExpression;
}
public void setThenExpression(JsExpression thenExpression) {
this.thenExpression = thenExpression;
}
@Override
public void accept(JsVisitor v) {
v.visitConditional(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(testExpression);
visitor.accept(thenExpression);
visitor.accept(elseExpression);
}
}
@@ -0,0 +1,26 @@
// 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(JsNode node);
void insertBefore(JsNode node);
boolean isLvalue();
void removeMe();
void replaceMe(JsNode node);
}
@@ -0,0 +1,29 @@
// 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;
public class JsContinue extends SourceInfoAwareJsNode implements JsStatement {
protected final String label;
public JsContinue() {
this(null);
}
public JsContinue(@Nullable String label) {
super();
this.label = label;
}
public String getLabel() {
return label;
}
@Override
public void accept(JsVisitor v) {
v.visitContinue(this);
}
}
@@ -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;
/**
* Represents a JavaScript debugger statement.
*/
public class JsDebugger extends SourceInfoAwareJsNode implements JsStatement {
public JsDebugger() {
}
@Override
public void accept(JsVisitor v) {
v.visitDebugger(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
}
}
@@ -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;
/**
* Represents the default option in a JavaScript swtich statement.
*/
public final class JsDefault extends JsSwitchMember {
@Override
public void accept(JsVisitor v) {
v.visitDefault(this);
}
}
@@ -0,0 +1,22 @@
// 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 void accept(JsVisitor v) {
v.visitDoWhile(this);
}
}
@@ -0,0 +1,29 @@
package com.google.dart.compiler.backend.js.ast;
import java.util.Collections;
import java.util.Map;
public class JsDocComment extends JsExpressionImpl {
private final Map<String, Object> tags;
public JsDocComment(Map<String, Object> tags) {
this.tags = tags;
}
public Map<String, Object> getTags() {
return tags;
}
public JsDocComment(String tagName, JsNameRef tagValue) {
tags = Collections.<String, Object>singletonMap(tagName, tagValue);
}
public JsDocComment(String tagName, String tagValue) {
tags = Collections.<String, Object>singletonMap(tagName, tagValue);
}
@Override
public void accept(JsVisitor v) {
v.visitDocComment(this);
}
}
@@ -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;
public class JsEmpty extends SourceInfoAwareJsNode implements JsStatement {
JsEmpty() {
}
@Override
public void accept(JsVisitor v) {
v.visitEmpty(this);
}
}
@@ -0,0 +1,10 @@
package com.google.dart.compiler.backend.js.ast;
public interface JsExpression extends JsNode {
boolean isLeaf();
JsStatement makeStmt();
@Override
JsExpression source(Object info);
}
@@ -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.backend.js.ast;
import java.util.List;
abstract class JsExpressionImpl extends SourceInfoAwareJsNode implements JsExpression {
/**
* 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 JsExpressionStatement(this);
}
protected abstract static class JsExpressionHasArguments extends JsExpressionImpl implements HasArguments {
protected final List<JsExpression> arguments;
public JsExpressionHasArguments(List<JsExpression> arguments) {
this.arguments = arguments;
}
@Override
public List<JsExpression> getArguments() {
return arguments;
}
}
@Override
public JsExpression source(Object info) {
setSource(info);
return this;
}
}
@@ -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;
public final class JsExpressionStatement extends AbstractNode implements JsStatement {
private JsExpression expression;
public JsExpressionStatement(JsExpression expression) {
this.expression = expression;
}
public JsExpression getExpression() {
return expression;
}
@Override
public void accept(JsVisitor v) {
v.visitExpressionStatement(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(expression);
}
@Override
public Object getSource() {
return null;
}
@Override
public void setSource(Object info) {
throw new IllegalStateException("You must not set source info for JsExpressionStatement, set for expression");
}
@Override
public JsNode source(Object info) {
throw new IllegalStateException("You must not set source info for JsExpressionStatement, set for expression");
}
}
@@ -0,0 +1,98 @@
// 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 <code>for</code> statement. If specified at all, the initializer part is
* either a declaration of one or more variables, in which case
* {@link #getInitVars()} is used, or an expression, in which case
* {@link #getInitExpression()} is used. In the latter case, the comma operator is
* often used to create a compound expression.
* <p/>
* <p/>
* Note that any of the parts of the <code>for</code> loop header can be
* <code>null</code>, although the body will never be null.
*/
public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
private JsStatement body;
private JsExpression condition;
private JsExpression incrementExpression;
private JsExpression initExpression;
private JsVars initVars;
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression) {
this(initVars, condition, incrementExpression, null);
}
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
this.initVars = initVars;
this.incrementExpression = incrementExpression;
this.condition = condition;
this.body = body;
initExpression = null;
}
public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression) {
this(initExpression, condition, incrementExpression, null);
}
public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
this.initExpression = initExpression;
this.incrementExpression = incrementExpression;
this.condition = condition;
this.body = body;
initVars = null;
}
public JsStatement getBody() {
return body;
}
public JsExpression getCondition() {
return condition;
}
public JsExpression getIncrementExpression() {
return incrementExpression;
}
public JsExpression getInitExpression() {
return initExpression;
}
public JsVars getInitVars() {
return initVars;
}
public void setBody(JsStatement body) {
this.body = body;
}
@Override
public void accept(JsVisitor v) {
v.visitFor(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
assert (!(initExpression != null && initVars != null));
if (initExpression != null) {
visitor.accept(initExpression);
}
else if (initVars != null) {
visitor.accept(initVars);
}
if (condition != null) {
visitor.accept(condition);
}
if (incrementExpression != null) {
visitor.accept(incrementExpression);
}
visitor.accept(body);
}
}
@@ -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;
public class JsForIn extends SourceInfoAwareJsNode implements JsStatement {
private JsStatement body;
private JsExpression iterExpression;
private JsExpression objectExpression;
// Optional: the name of a new iterator variable to introduce
private final JsName iterVarName;
public JsForIn() {
this(null);
}
public JsForIn(JsName iterVarName) {
this.iterVarName = iterVarName;
}
public JsStatement getBody() {
return body;
}
public JsExpression getIterExpression() {
return iterExpression;
}
public JsName getIterVarName() {
return iterVarName;
}
public JsExpression getObjectExpression() {
return objectExpression;
}
public void setBody(JsStatement body) {
this.body = body;
}
public void setIterExpression(JsExpression iterExpression) {
this.iterExpression = iterExpression;
}
public void setObjectExpression(JsExpression objectExpression) {
this.objectExpression = objectExpression;
}
@Override
public void accept(JsVisitor v) {
v.visitForIn(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (iterExpression != null) {
visitor.acceptLvalue(iterExpression);
}
visitor.accept(objectExpression);
visitor.accept(body);
}
}
@@ -0,0 +1,76 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.Symbol;
import com.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;
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;
}
public void setBody(JsBlock body) {
this.body = body;
}
public void setName(@Nullable JsName name) {
this.name = name;
}
@Override
public void accept(JsVisitor v) {
v.visitFunction(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(params);
visitor.accept(body);
}
}
@@ -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;
/**
* Represents a JavaScript block in the global scope.
*/
public class JsGlobalBlock extends JsBlock {
public JsGlobalBlock() {
}
@Override
public boolean isGlobalBlock() {
return true;
}
}
@@ -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 if statement.
*/
public final class JsIf extends SourceInfoAwareJsNode 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 elseStatement) {
this.elseStatement = elseStatement;
}
public void setIfExpression(JsExpression ifExpression) {
this.ifExpression = ifExpression;
}
public void setThenStatement(JsStatement thenStatement) {
this.thenStatement = thenStatement;
}
@Override
public void accept(JsVisitor v) {
v.visitIf(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(ifExpression);
visitor.accept(thenStatement);
if (elseStatement != null) {
visitor.accept(elseStatement);
}
}
}
@@ -0,0 +1,61 @@
// 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;
public final class JsInvocation extends JsExpressionImpl.JsExpressionHasArguments {
private JsExpression qualifier;
public JsInvocation() {
super(new SmartList<JsExpression>());
}
public JsInvocation(JsExpression qualifier, List<JsExpression> arguments) {
super(arguments);
this.qualifier = qualifier;
}
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;
}
public void setQualifier(JsExpression qualifier) {
this.qualifier = qualifier;
}
@Override
public void accept(JsVisitor v) {
v.visitInvocation(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(qualifier);
visitor.acceptList(arguments);
}
}
@@ -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;
/**
* Represents a JavaScript label statement.
*/
public class JsLabel extends SourceInfoAwareJsNode implements JsStatement, HasName {
private final JsName label;
private JsStatement statement;
public JsLabel(JsName label) {
this.label = label;
}
public JsLabel(JsName label, JsStatement statement) {
this.label = label;
this.statement = statement;
}
@Override
public JsName getName() {
return label;
}
@Override
public Symbol getSymbol() {
return label;
}
public JsStatement getStatement() {
return statement;
}
public void setStatement(JsStatement statement) {
this.statement = statement;
}
@Override
public void accept(JsVisitor v) {
v.visitLabel(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(statement);
}
}
@@ -0,0 +1,61 @@
// 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 {
public static final JsValueLiteral THIS = new JsThisRef();
public static final JsNameRef UNDEFINED = new JsNameRef("undefined");
public static final JsNullLiteral NULL = new JsNullLiteral();
public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(true);
public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(false);
public static JsBooleanLiteral getBoolean(boolean truth) {
return truth ? TRUE : FALSE;
}
public static final class JsThisRef extends JsValueLiteral {
private JsThisRef() {
super();
}
@Override
public void accept(JsVisitor v) {
v.visitThis(this);
}
}
public static final class JsBooleanLiteral extends JsValueLiteral {
private final boolean value;
// Should be interned by JsProgram
private JsBooleanLiteral(boolean value) {
this.value = value;
}
public boolean getValue() {
return value;
}
@Override
public void accept(JsVisitor v) {
v.visitBoolean(this);
}
}
/**
* A JavaScript string literal expression.
*/
public abstract static class JsValueLiteral extends JsLiteral {
protected JsValueLiteral() {
}
@Override
public final boolean isLeaf() {
return true;
}
}
}
@@ -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,82 @@
// 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 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 isLeaf() {
return qualifier == null;
}
public void resolve(JsName name) {
this.name = name;
ident = null;
}
public void setQualifier(JsExpression qualifier) {
this.qualifier = qualifier;
}
@Override
public void accept(JsVisitor v) {
v.visitNameRef(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (qualifier != null) {
visitor.accept(qualifier);
}
}
}
@@ -0,0 +1,37 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import com.intellij.util.SmartList;
import java.util.List;
public final class JsNew extends JsExpressionImpl.JsExpressionHasArguments {
private JsExpression constructorExpression;
public JsNew(JsExpression constructorExpression) {
this(constructorExpression, new SmartList<JsExpression>());
}
public JsNew(JsExpression constructorExpression, List<JsExpression> arguments) {
super(arguments);
this.constructorExpression = constructorExpression;
}
public JsExpression getConstructorExpression() {
return constructorExpression;
}
@Override
public void accept(JsVisitor v) {
v.visitNew(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(constructorExpression);
visitor.acceptList(arguments);
}
}
@@ -0,0 +1,30 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
public interface JsNode {
/**
* Causes this object to have the visitor visit itself and its children.
*
* @param visitor the visitor that should traverse this node
*/
void accept(JsVisitor visitor);
void acceptChildren(JsVisitor visitor);
/**
* Return the source info associated with this object.
*/
Object getSource();
/**
* Set the source info associated with this object.
*
* @param info
*/
void setSource(Object info);
JsNode source(Object info);
}
@@ -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;
public final class JsNullLiteral extends JsLiteral.JsValueLiteral {
JsNullLiteral() {
}
@Override
public void accept(JsVisitor v) {
v.visitNull(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 abstract class JsNumberLiteral extends JsLiteral.JsValueLiteral {
public static final class JsDoubleLiteral extends JsNumberLiteral {
public final double value;
JsDoubleLiteral(double value) {
this.value = value;
}
@Override
public void accept(JsVisitor v) {
v.visitDouble(this);
}
public String toString() {
return String.valueOf(value);
}
}
public static final class JsIntLiteral extends JsNumberLiteral {
public final int value;
JsIntLiteral(int value) {
this.value = value;
}
@Override
public void accept(JsVisitor v) {
v.visitInt(this);
}
public String toString() {
return String.valueOf(value);
}
}
}
@@ -0,0 +1,50 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import 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 void accept(JsVisitor v) {
v.visitObjectLiteral(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(properties);
}
}
@@ -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,33 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.Symbol;
/**
* A JavaScript parameter.
*/
public final class JsParameter extends SourceInfoAwareJsNode 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 accept(JsVisitor v) {
v.visitParameter(this);
}
}
@@ -0,0 +1,20 @@
// 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 JsPostfixOperation extends JsUnaryOperation {
public JsPostfixOperation(JsUnaryOperator op) {
this(op, null);
}
public JsPostfixOperation(JsUnaryOperator op, JsExpression arg) {
super(op, arg);
}
@Override
public void accept(JsVisitor v) {
v.visitPostfixOperation(this);
}
}
@@ -0,0 +1,20 @@
// 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 JsPrefixOperation extends JsUnaryOperation {
public JsPrefixOperation(JsUnaryOperator op) {
this(op, null);
}
public JsPrefixOperation(JsUnaryOperator op, JsExpression arg) {
super(op, arg);
}
@Override
public void accept(JsVisitor v) {
v.visitPrefixOperation(this);
}
}
@@ -0,0 +1,121 @@
// 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 java.util.Map;
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsDoubleLiteral;
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiteral;
/**
* A JavaScript program.
*/
public final class JsProgram extends SourceInfoAwareJsNode {
private final JsEmpty emptyStatement;
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;
public JsProgram(String unitId) {
rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId);
setFragmentCount(1);
emptyStatement = new JsEmpty();
}
public JsEmpty getEmptyStatement() {
return emptyStatement;
}
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 accept(JsVisitor v) {
v.visitProgram(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
for (JsProgramFragment fragment : fragments) {
visitor.accept(fragment);
}
}
}
@@ -0,0 +1,30 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
/**
* One independently loadable fragment of a {@link JsProgram}.
*/
public class JsProgramFragment extends SourceInfoAwareJsNode {
private final JsGlobalBlock globalBlock;
public JsProgramFragment() {
globalBlock = new JsGlobalBlock();
}
public JsBlock getGlobalBlock() {
return globalBlock;
}
@Override
public void accept(JsVisitor v) {
v.visitProgramFragment(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(globalBlock);
}
}
@@ -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 org.jetbrains.annotations.NotNull;
/**
* Used in object literals to specify property values by name.
*/
public class JsPropertyInitializer extends SourceInfoAwareJsNode {
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 void setValueExpr(@NotNull JsExpression valueExpr) {
this.valueExpr = valueExpr;
}
@Override
public void accept(JsVisitor v) {
v.visitPropertyInitializer(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(labelExpr);
visitor.accept(valueExpr);
}
}
@@ -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;
public final class JsRegExp extends JsLiteral.JsValueLiteral {
private String flags;
private String pattern;
public JsRegExp() {
}
public String getFlags() {
return flags;
}
public String getPattern() {
return pattern;
}
public void setFlags(String suffix) {
flags = suffix;
}
public void setPattern(String re) {
pattern = re;
}
@Override
public void accept(JsVisitor v) {
v.visitRegExp(this);
}
}
@@ -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;
/**
* A JavaScript return statement.
*/
public final class JsReturn extends SourceInfoAwareJsNode implements JsStatement {
private JsExpression expression;
public JsReturn() {
}
public JsReturn(JsExpression expression) {
this.expression = expression;
}
public JsExpression getExpression() {
return expression;
}
public void setExpression(JsExpression expression) {
this.expression = expression;
}
@Override
public void accept(JsVisitor v) {
v.visitReturn(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (expression != null) {
visitor.accept(expression);
}
}
}
@@ -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;
parent = null;
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,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;
public final class JsStringLiteral extends JsLiteral.JsValueLiteral {
private final String value;
// These only get created by JsProgram so that they can be interned.
JsStringLiteral(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public void accept(JsVisitor v) {
v.visitString(this);
}
}
@@ -0,0 +1,44 @@
// 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 SourceInfoAwareJsNode implements JsStatement {
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
private JsExpression expression;
public JsSwitch() {
super();
}
public List<JsSwitchMember> getCases() {
return cases;
}
public JsExpression getExpression() {
return expression;
}
public void setExpression(JsExpression expression) {
this.expression = expression;
}
@Override
public void accept(JsVisitor v) {
v.visit(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(expression);
visitor.acceptWithInsertRemove(cases);
}
}
@@ -0,0 +1,29 @@
// 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 SourceInfoAwareJsNode {
protected final List<JsStatement> statements = new SmartList<JsStatement>();
protected JsSwitchMember() {
super();
}
public List<JsStatement> getStatements() {
return statements;
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(statements);
}
}
@@ -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;
public class JsThrow extends SourceInfoAwareJsNode implements JsStatement {
private JsExpression expression;
public JsThrow() {
}
public JsThrow(JsExpression expression) {
this.expression = expression;
}
public JsExpression getExpression() {
return expression;
}
public void setExpression(JsExpression expression) {
this.expression = expression;
}
@Override
public void accept(JsVisitor v) {
v.visitThrow(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(expression);
}
}
@@ -0,0 +1,63 @@
// 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 SourceInfoAwareJsNode implements JsStatement {
private final List<JsCatch> catches;
private JsBlock finallyBlock;
private JsBlock tryBlock;
public JsTry() {
catches = new SmartList<JsCatch>();
}
public JsTry(JsBlock tryBlock, List<JsCatch> catches, @Nullable JsBlock finallyBlock) {
this.tryBlock = tryBlock;
this.catches = catches;
this.finallyBlock = finallyBlock;
}
public List<JsCatch> getCatches() {
return catches;
}
public JsBlock getFinallyBlock() {
return finallyBlock;
}
public JsBlock getTryBlock() {
return tryBlock;
}
public void setFinallyBlock(JsBlock block) {
finallyBlock = block;
}
public void setTryBlock(JsBlock block) {
tryBlock = block;
}
@Override
public void accept(JsVisitor v) {
v.visitTry(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(tryBlock);
visitor.acceptWithInsertRemove(catches);
if (finallyBlock != null) {
visitor.accept(finallyBlock);
}
}
}
@@ -0,0 +1,46 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
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;
}
public void setArg(JsExpression arg) {
this.arg = arg;
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (op.isModifying()) {
// The delete operator is practically like an assignment of undefined, so
// for practical purposes we're treating it as an lvalue.
visitor.acceptLvalue(arg);
}
else {
visitor.accept(arg);
}
}
}
@@ -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,124 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.Symbol;
import com.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 SourceInfoAwareJsNode implements JsStatement, Iterable<JsVars.JsVar> {
private final List<JsVar> vars;
private final boolean multiline;
public JsVars() {
this(new SmartList<JsVar>(), false);
}
public JsVars(boolean multiline) {
this(new SmartList<JsVar>(), multiline);
}
public JsVars(List<JsVar> vars, boolean multiline) {
this.vars = vars;
this.multiline = multiline;
}
public JsVars(JsVar var) {
this(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 SourceInfoAwareJsNode 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 accept(JsVisitor v) {
v.visit(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
if (initExpression != null) {
visitor.accept(initExpression);
}
}
}
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 accept(JsVisitor v) {
v.visitVars(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.acceptWithInsertRemove(vars);
}
}
@@ -0,0 +1,210 @@
// 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;
public abstract class JsVisitor {
public <T extends JsNode> void accept(T node) {
node.accept(this);
}
public final <T extends JsNode> void acceptList(List<T> collection) {
for (T node : collection) {
accept(node);
}
}
public void acceptLvalue(JsExpression expression) {
accept(expression);
}
public final <T extends JsNode> void acceptWithInsertRemove(List<T> collection) {
for (T node : collection) {
accept(node);
}
}
public void visitArrayAccess(JsArrayAccess x) {
visitElement(x);
}
public void visitArray(JsArrayLiteral x) {
visitElement(x);
}
public void visitBinaryExpression(JsBinaryOperation x) {
visitElement(x);
}
public void visitBlock(JsBlock x) {
visitElement(x);
}
public void visitBoolean(JsLiteral.JsBooleanLiteral x) {
visitElement(x);
}
public void visitBreak(JsBreak x) {
visitElement(x);
}
public void visitCase(JsCase x) {
visitElement(x);
}
public void visitCatch(JsCatch x) {
visitElement(x);
}
public void visitConditional(JsConditional x) {
visitElement(x);
}
public void visitContinue(JsContinue x) {
visitElement(x);
}
public void visitDebugger(JsDebugger x) {
visitElement(x);
}
public void visitDefault(JsDefault x) {
visitElement(x);
}
public void visitDoWhile(JsDoWhile x) {
visitElement(x);
}
public void visitEmpty(JsEmpty x) {
visitElement(x);
}
public void visitExpressionStatement(JsExpressionStatement x) {
visitElement(x);
}
public void visitFor(JsFor x) {
visitElement(x);
}
public void visitForIn(JsForIn x) {
visitElement(x);
}
public void visitFunction(JsFunction x) {
visitElement(x);
}
public void visitIf(JsIf x) {
visitElement(x);
}
public void visitInvocation(JsInvocation invocation) {
visitElement(invocation);
}
public void visitLabel(JsLabel x) {
visitElement(x);
}
public void visitNameRef(JsNameRef nameRef) {
visitElement(nameRef);
}
public void visitNew(JsNew x) {
visitElement(x);
}
public void visitNull(JsNullLiteral x) {
visitElement(x);
}
public void visitInt(JsNumberLiteral.JsIntLiteral x) {
visitElement(x);
}
public void visitDouble(JsNumberLiteral.JsDoubleLiteral x) {
visitElement(x);
}
public void visitObjectLiteral(JsObjectLiteral x) {
visitElement(x);
}
public void visitParameter(JsParameter x) {
visitElement(x);
}
public void visitPostfixOperation(JsPostfixOperation x) {
visitElement(x);
}
public void visitPrefixOperation(JsPrefixOperation x) {
visitElement(x);
}
public void visitProgram(JsProgram x) {
visitElement(x);
}
public void visitProgramFragment(JsProgramFragment x) {
visitElement(x);
}
public void visitPropertyInitializer(JsPropertyInitializer x) {
visitElement(x);
}
public void visitRegExp(JsRegExp x) {
visitElement(x);
}
public void visitReturn(JsReturn x) {
visitElement(x);
}
public void visitString(JsStringLiteral x) {
visitElement(x);
}
public void visit(JsSwitch x) {
visitElement(x);
}
public void visitThis(JsLiteral.JsThisRef x) {
visitElement(x);
}
public void visitThrow(JsThrow x) {
visitElement(x);
}
public void visitTry(JsTry x) {
visitElement(x);
}
public void visit(JsVar x) {
visitElement(x);
}
public void visitVars(JsVars x) {
visitElement(x);
}
public void visitWhile(JsWhile x) {
visitElement(x);
}
public void visitDocComment(JsDocComment comment) {
visitElement(comment);
}
protected void visitElement(JsNode node) {
}
}
@@ -0,0 +1,48 @@
// 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 SourceInfoAwareJsNode implements JsStatement {
protected JsStatement body;
protected JsExpression condition;
public JsWhile() {
}
public JsWhile(JsExpression condition, JsStatement body) {
this.condition = condition;
this.body = body;
}
public JsStatement getBody() {
return body;
}
public JsExpression getCondition() {
return condition;
}
public void setBody(JsStatement body) {
this.body = body;
}
public void setCondition(JsExpression condition) {
this.condition = condition;
}
@Override
public void accept(JsVisitor v) {
v.visitWhile(this);
}
@Override
public void acceptChildren(JsVisitor visitor) {
visitor.accept(condition);
visitor.accept(body);
}
}
@@ -0,0 +1,8 @@
package com.google.dart.compiler.backend.js.ast;
public abstract class RecursiveJsVisitor extends JsVisitor {
@Override
protected void visitElement(JsNode node) {
node.acceptChildren(this);
}
}
@@ -0,0 +1,25 @@
package com.google.dart.compiler.backend.js.ast;
abstract class SourceInfoAwareJsNode extends AbstractNode {
private Object source;
@Override
public Object getSource() {
return source;
}
@Override
public void setSource(Object info) {
source = info;
}
@Override
public void acceptChildren(JsVisitor visitor) {
}
@Override
public JsNode source(Object info) {
source = info;
return this;
}
}
@@ -0,0 +1,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,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.util;
import com.google.dart.compiler.backend.js.ast.*;
/**
* @author johnlenz@google.com (John Lenz)
*/
public final class AstUtil {
private AstUtil() {
}
/**
* Returns a sequence of expressions (using the binary sequence operator).
*
* @param exprs - expressions to add to sequence
* @return a sequence of expressions.
*/
public static JsBinaryOperation newSequence(JsExpression... exprs) {
if (exprs.length < 2) {
throw new RuntimeException("newSequence expects at least two arguments");
}
JsExpression result = exprs[exprs.length - 1];
for (int i = exprs.length - 2; i >= 0; i--) {
result = new JsBinaryOperation(JsBinaryOperator.COMMA, exprs[i], result);
}
return (JsBinaryOperation) result;
}
}
@@ -0,0 +1,41 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Utility methods for operating on memory-efficient maps. All maps of size 0 or
* 1 are assumed to be immutable. All maps of size greater than 1 are assumed to
* be mutable.
*/
public class Maps {
private Maps() {
}
public static <K, V> Map<K, V> put(Map<K, V> map, K key, V value) {
switch (map.size()) {
case 0:
// Empty -> Singleton
return Collections.singletonMap(key, value);
case 1: {
if (map.containsKey(key)) {
return Collections.singletonMap(key, value);
}
// Singleton -> HashMap
Map<K, V> result = new HashMap<K, V>();
result.put(map.keySet().iterator().next(), map.values().iterator().next());
result.put(key, value);
return result;
}
default:
// HashMap
map.put(key, value);
return map;
}
}
}
@@ -0,0 +1,52 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.util;
/**
* Interface used for printing text output.
*/
public interface TextOutput {
int getPosition();
int getLine();
int getColumn();
void indentIn();
void indentOut();
void newline();
void print(char c);
void print(int v);
void print(double v);
void print(char[] s);
void print(CharSequence s);
void printOpt(char c);
void printOpt(char[] s);
void printOpt(String s);
boolean isCompact();
boolean isJustNewlined();
void setOutListener(OutListener outListener);
void maybeIndent();
public interface OutListener {
void newLined();
void indentedAfterNewLine();
}
}
@@ -0,0 +1,181 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.util;
import java.util.Arrays;
public class TextOutputImpl implements TextOutput {
private final boolean compact;
private int identLevel = 0;
private final static int indentGranularity = 2;
private char[][] indents = new char[][] {new char[0]};
private boolean justNewlined;
private final StringBuilder out;
private int position = 0;
private int line = 0;
private int column = 0;
private OutListener outListener;
public TextOutputImpl() {
this(false);
}
public boolean isCompact() {
return compact;
}
public TextOutputImpl(boolean compact) {
this.compact = compact;
out = new StringBuilder();
}
@Override
public String toString() {
return out.toString();
}
@Override
public int getPosition() {
return position;
}
@Override
public int getLine() {
return line;
}
@Override
public int getColumn() {
return column;
}
@Override
public void indentIn() {
++identLevel;
if (identLevel >= indents.length) {
// Cache a new level of indentation string.
char[] newIndentLevel = new char[identLevel * indentGranularity];
Arrays.fill(newIndentLevel, ' ');
char[][] newIndents = new char[indents.length + 1][];
System.arraycopy(indents, 0, newIndents, 0, indents.length);
newIndents[identLevel] = newIndentLevel;
indents = newIndents;
}
}
@Override
public void indentOut() {
--identLevel;
}
@Override
public void newline() {
out.append('\n');
position++;
line++;
column = 0;
justNewlined = true;
if (outListener != null) {
outListener.newLined();
}
}
@Override
public void print(double value) {
maybeIndent();
int oldLength = out.length();
out.append(value);
movePosition(out.length() - oldLength);
}
@Override
public void print(int value) {
maybeIndent();
int oldLength = out.length();
out.append(value);
movePosition(out.length() - oldLength);
}
@Override
public void print(char c) {
maybeIndent();
out.append(c);
movePosition(1);
}
private void movePosition(int l) {
position += l;
column += l;
}
@Override
public void print(char[] s) {
maybeIndent();
printAndCount(s);
}
@Override
public void print(CharSequence s) {
maybeIndent();
printAndCount(s);
}
@Override
public void printOpt(char c) {
if (!compact) {
print(c);
}
}
@Override
public void printOpt(char[] s) {
if (!compact) {
maybeIndent();
printAndCount(s);
}
}
@Override
public void printOpt(String s) {
if (!compact) {
maybeIndent();
printAndCount(s);
}
}
@Override
public void maybeIndent() {
if (justNewlined && !compact) {
printAndCount(indents[identLevel]);
justNewlined = false;
if (outListener != null) {
outListener.indentedAfterNewLine();
}
}
}
private void printAndCount(CharSequence charSequence) {
position += charSequence.length();
column += charSequence.length();
out.append(charSequence);
}
private void printAndCount(char[] chars) {
position += chars.length;
column += chars.length;
out.append(chars);
}
@Override
public boolean isJustNewlined() {
return justNewlined && !compact;
}
@Override
public void setOutListener(OutListener outListener) {
this.outListener = outListener;
}
}
@@ -0,0 +1,17 @@
package org.jetbrains.js.compiler;
import java.io.File;
public interface SourceMapBuilder {
void newLine();
void addMapping(String source, int sourceLine, int sourceColumn);
void processSourceInfo(Object info);
void addLink();
File getOutFile();
String build();
}