move from my kotlin fork
This commit is contained in:
Generated
+1
@@ -0,0 +1 @@
|
|||||||
|
former-dast-ast
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<component name="ArtifactManager">
|
||||||
|
<artifact name="dart-ast:jar">
|
||||||
|
<output-path>$PROJECT_DIR$/out/artifacts</output-path>
|
||||||
|
<root id="root">
|
||||||
|
<element id="archive" name="dart-ast.jar">
|
||||||
|
<element id="module-output" name="former-dast-ast" />
|
||||||
|
</element>
|
||||||
|
</root>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
Generated
+23
@@ -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>
|
||||||
|
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||||
|
</project>
|
||||||
|
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0" is_locked="false">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<option name="myLocal" value="false" />
|
||||||
|
<inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="JSBitwiseOperatorUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="TOP_LEVEL_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="INNER_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="METHOD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="FIELD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="IGNORE_DEPRECATED" value="false" />
|
||||||
|
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
|
||||||
|
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
|
||||||
|
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
|
||||||
|
<option name="myAdditionalJavadocTags" value="" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="m_onlyPrivateOrFinal" value="false" />
|
||||||
|
<option name="m_ignoreEmptyMethods" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="UnnecessarilyQualifiedStaticUsage" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="m_ignoreStaticFieldAccesses" value="false" />
|
||||||
|
<option name="m_ignoreStaticMethodCalls" value="false" />
|
||||||
|
<option name="m_ignoreStaticAccessFromStaticContext" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="UnnecessarilyQualifiedStaticallyImportedElement" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="UnnecessaryContinue" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="UnnecessaryQualifierForThis" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="UnnecessaryThis" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
+7
@@ -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>
|
||||||
Generated
+10
@@ -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>
|
||||||
|
|
||||||
Generated
+9
@@ -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>
|
||||||
|
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="DependencyValidationManager">
|
||||||
|
<state>
|
||||||
|
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
Generated
+125
@@ -0,0 +1,125 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Palette2">
|
||||||
|
<group name="Swing">
|
||||||
|
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Button" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="RadioButton" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="CheckBox" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||||
|
<initial-values>
|
||||||
|
<property name="text" value="Label" />
|
||||||
|
</initial-values>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||||
|
<preferred-size width="150" height="-1" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||||
|
<preferred-size width="150" height="50" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||||
|
<preferred-size width="200" height="200" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||||
|
<preferred-size width="-1" height="20" />
|
||||||
|
</default-constraints>
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||||
|
</item>
|
||||||
|
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||||
|
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||||
|
</item>
|
||||||
|
</group>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
||||||
@@ -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,5 @@
|
|||||||
|
Google Dart Js backend was removed - https://code.google.com/p/dart/source/detail?r=4771
|
||||||
|
|
||||||
|
According to http://www.apache.org/legal/3party.html we can include "Google Dart Js backend" in source form, because code license is "New BSD License" (Authorized License).
|
||||||
|
|
||||||
|
This part of code will be removed when kotlin will be rewritten on kotlin.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract interface to a source file.
|
||||||
|
*/
|
||||||
|
public interface Source {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the given source exists.
|
||||||
|
*/
|
||||||
|
boolean exists();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last-modified timestamp for this source, using the same units as
|
||||||
|
* {@link Date#getTime()}.
|
||||||
|
*/
|
||||||
|
long getLastModified();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this source.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a reader for the dart file's source code. The caller is responsible for closing the
|
||||||
|
* returned reader.
|
||||||
|
*/
|
||||||
|
Reader getSourceReader() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the identifier for this source. This is used to uniquely identify the
|
||||||
|
* source, but should not be used to obtain the source content. Use
|
||||||
|
* {@link #getSourceReader()} to obtain the source content.
|
||||||
|
*/
|
||||||
|
URI getUri();
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for method invocations in constructor expressions that would not
|
||||||
|
* normally be surrounded by parentheses.
|
||||||
|
*/
|
||||||
|
public class JsConstructExpressionVisitor extends JsVisitor {
|
||||||
|
|
||||||
|
public static boolean exec(JsExpression expression) {
|
||||||
|
if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
|
||||||
|
visitor.accept(expression);
|
||||||
|
return visitor.containsInvocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsInvocation = false;
|
||||||
|
|
||||||
|
private JsConstructExpressionVisitor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We only look at the array expression since the index has its own scope.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayAccess x, JsContext ctx) {
|
||||||
|
accept(x.getArrayExpr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array literals have their own scoping.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayLiteral x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions have their own scoping.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsFunction x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsInvocation x, JsContext ctx) {
|
||||||
|
containsInvocation = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNameRef x, JsContext ctx) {
|
||||||
|
if (!x.isLeaf()) {
|
||||||
|
accept(x.getQualifier());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New constructs bind to the nearest set of parentheses.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNew x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object literals have their own scope.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsObjectLiteral x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We only look at nodes that would not normally be surrounded by parentheses.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected <T extends JsVisitable> T doAccept(T node) {
|
||||||
|
// Assign to Object to prevent 'inconvertible types' compile errors due
|
||||||
|
// to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
|
||||||
|
// reproducible in jdk1.6.0_02.
|
||||||
|
Object o = node;
|
||||||
|
if (o instanceof JsExpression) {
|
||||||
|
JsExpression expression = (JsExpression) o;
|
||||||
|
int precedence = JsPrecedenceVisitor.exec(expression);
|
||||||
|
// Only visit expressions that won't automatically be surrounded by
|
||||||
|
// parentheses
|
||||||
|
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.doAccept(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsArrayLiteral;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsConditional;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsContext;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExprStmt;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFunction;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsNew;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsPostfixOperation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsRegExp;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if an expression statement needs to be surrounded by parentheses.
|
||||||
|
* <p/>
|
||||||
|
* The statement or the left-most expression needs to be surrounded by
|
||||||
|
* parentheses if the left-most expression is an object literal or a function
|
||||||
|
* object. Function declarations do not need parentheses.
|
||||||
|
* <p/>
|
||||||
|
* For example the following require parentheses:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>{ key : 'value'}</li>
|
||||||
|
* <li>{ key : 'value'}.key</li>
|
||||||
|
* <li>function () {return 1;}()</li>
|
||||||
|
* <li>function () {return 1;}.prototype</li>
|
||||||
|
* </ul>
|
||||||
|
* <p/>
|
||||||
|
* The following do not require parentheses:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>var x = { key : 'value'}</li>
|
||||||
|
* <li>"string" + { key : 'value'}.key</li>
|
||||||
|
* <li>function func() {}</li>
|
||||||
|
* <li>function() {}</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class JsFirstExpressionVisitor extends JsVisitor {
|
||||||
|
public static boolean exec(JsExprStmt statement) {
|
||||||
|
JsExpression expression = statement.getExpression();
|
||||||
|
// Pure function declarations do not need parentheses
|
||||||
|
if (expression instanceof JsFunction) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsFirstExpressionVisitor visitor = new JsFirstExpressionVisitor();
|
||||||
|
visitor.accept(statement.getExpression());
|
||||||
|
return visitor.needsParentheses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needsParentheses = false;
|
||||||
|
|
||||||
|
private JsFirstExpressionVisitor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayAccess x, JsContext ctx) {
|
||||||
|
accept(x.getArrayExpr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayLiteral x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBinaryOperation x, JsContext ctx) {
|
||||||
|
accept(x.getArg1());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsConditional x, JsContext ctx) {
|
||||||
|
accept(x.getTestExpression());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsFunction x, JsContext ctx) {
|
||||||
|
needsParentheses = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsInvocation x, JsContext ctx) {
|
||||||
|
accept(x.getQualifier());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNameRef x, JsContext ctx) {
|
||||||
|
if (!x.isLeaf()) {
|
||||||
|
accept(x.getQualifier());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNew x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsObjectLiteral x, JsContext ctx) {
|
||||||
|
needsParentheses = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsPostfixOperation x, JsContext ctx) {
|
||||||
|
accept(x.getArg());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsPrefixOperation x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsRegExp x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
|
||||||
|
* 57)
|
||||||
|
*
|
||||||
|
* Precedence 17 is for indivisible primaries that either don't have children,
|
||||||
|
* or provide their own delimiters.
|
||||||
|
*
|
||||||
|
* Precedence 16 is for really important things that have their own AST classes.
|
||||||
|
*
|
||||||
|
* Precedence 15 is for the new construct.
|
||||||
|
*
|
||||||
|
* Precedence 14 is for unary operators.
|
||||||
|
*
|
||||||
|
* Precedences 12 through 4 are for non-assigning binary operators.
|
||||||
|
*
|
||||||
|
* Precedence 3 is for the tertiary conditional.
|
||||||
|
*
|
||||||
|
* Precedence 2 is for assignments.
|
||||||
|
*
|
||||||
|
* Precedence 1 is for comma operations.
|
||||||
|
*/
|
||||||
|
class JsPrecedenceVisitor extends JsVisitor {
|
||||||
|
static final int PRECEDENCE_NEW = 15;
|
||||||
|
|
||||||
|
public static int exec(JsExpression expression) {
|
||||||
|
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
|
||||||
|
visitor.accept(expression);
|
||||||
|
if (visitor.answer < 0) {
|
||||||
|
throw new RuntimeException("Precedence must be >= 0!");
|
||||||
|
}
|
||||||
|
return visitor.answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int answer = -1;
|
||||||
|
|
||||||
|
private JsPrecedenceVisitor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayAccess x, JsContext ctx) {
|
||||||
|
answer = 16;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsArrayLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBinaryOperation x, JsContext ctx) {
|
||||||
|
answer = x.getOperator().getPrecedence();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBlock x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBreak x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsCase x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsCatch x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsConditional x, JsContext ctx) {
|
||||||
|
answer = 3;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsContinue x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsDebugger x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsDefault x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsDoWhile x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsEmpty x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsExprStmt x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsFor x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsForIn x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsFunction x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsIf x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsInvocation x, JsContext ctx) {
|
||||||
|
answer = 16;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsLabel x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNameRef x, JsContext ctx) {
|
||||||
|
if (x.isLeaf()) {
|
||||||
|
answer = 17; // primary
|
||||||
|
} else {
|
||||||
|
answer = 16; // property access
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNew x, JsContext ctx) {
|
||||||
|
answer = PRECEDENCE_NEW;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNullLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsObjectLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsParameter x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsPostfixOperation x, JsContext ctx) {
|
||||||
|
answer = x.getOperator().getPrecedence();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsPrefixOperation x, JsContext ctx) {
|
||||||
|
answer = x.getOperator().getPrecedence();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsProgram x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsRegExp x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsReturn x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsStringLiteral x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsSwitch x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
|
||||||
|
answer = 17; // primary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsThrow x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsTry x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsVar x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsVars x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsWhile x, JsContext ctx) {
|
||||||
|
throw new RuntimeException("Only expressions have precedence.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBreak;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsContext;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsDebugger;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsDoWhile;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsEmpty;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExprStmt;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsFor;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsForIn;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsIf;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsLabel;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsReturn;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsStatement;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsSwitch;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsThrow;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsTry;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsVars;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsVisitor;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsWhile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a statement at the end of a block requires a semicolon.
|
||||||
|
*
|
||||||
|
* For example, the following statements require semicolons:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>if (cond);</li>
|
||||||
|
* <li>while (cond);</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* The following do not require semicolons:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>return 1</li>
|
||||||
|
* <li>do {} while(true)</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class JsRequiresSemiVisitor extends JsVisitor {
|
||||||
|
|
||||||
|
public static boolean exec(JsStatement lastStatement) {
|
||||||
|
JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor();
|
||||||
|
visitor.accept(lastStatement);
|
||||||
|
return visitor.needsSemicolon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needsSemicolon = false;
|
||||||
|
|
||||||
|
private JsRequiresSemiVisitor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBlock x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBreak x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsDebugger x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsDoWhile x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsEmpty x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsExprStmt x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsFor x, JsContext ctx) {
|
||||||
|
if (x.getBody() instanceof JsEmpty) {
|
||||||
|
needsSemicolon = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsForIn x, JsContext ctx) {
|
||||||
|
if (x.getBody() instanceof JsEmpty) {
|
||||||
|
needsSemicolon = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsIf x, JsContext ctx) {
|
||||||
|
JsStatement thenStmt = x.getThenStatement();
|
||||||
|
JsStatement elseStmt = x.getElseStatement();
|
||||||
|
JsStatement toCheck = thenStmt;
|
||||||
|
if (elseStmt != null) {
|
||||||
|
toCheck = elseStmt;
|
||||||
|
}
|
||||||
|
if (toCheck instanceof JsEmpty) {
|
||||||
|
needsSemicolon = true;
|
||||||
|
} else {
|
||||||
|
// Must recurse to determine last statement (possible if-else chain).
|
||||||
|
accept(toCheck);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsLabel x, JsContext ctx) {
|
||||||
|
if (x.getStmt() instanceof JsEmpty) {
|
||||||
|
needsSemicolon = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsReturn x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsSwitch x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsThrow x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsTry x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsVars x, JsContext ctx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsWhile x, JsContext ctx) {
|
||||||
|
if (x.getBody() instanceof JsEmpty) {
|
||||||
|
needsSemicolon = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import gnu.trove.THashSet;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not a particular string is a JavaScript keyword or not.
|
||||||
|
*/
|
||||||
|
public class JsReservedIdentifiers {
|
||||||
|
public static final Set<String> reservedGlobalSymbols;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] commonBuiltins = new String[] {
|
||||||
|
// 15.1.1 Value Properties of the Global Object
|
||||||
|
"NaN", "Infinity", "undefined",
|
||||||
|
|
||||||
|
// 15.1.2 Function Properties of the Global Object
|
||||||
|
"eval", "parseInt", "parseFloat", "isNan", "isFinite",
|
||||||
|
|
||||||
|
// 15.1.3 URI Handling Function Properties
|
||||||
|
"decodeURI", "decodeURIComponent",
|
||||||
|
"encodeURI",
|
||||||
|
"encodeURIComponent",
|
||||||
|
|
||||||
|
// 15.1.4 Constructor Properties of the Global Object
|
||||||
|
"Object", "Function", "Array", "String", "Boolean", "Number", "Date",
|
||||||
|
"RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
|
||||||
|
"SyntaxError", "TypeError", "URIError",
|
||||||
|
|
||||||
|
// 15.1.5 Other Properties of the Global Object
|
||||||
|
"Math",
|
||||||
|
|
||||||
|
// 10.1.6 Activation Object
|
||||||
|
"arguments",
|
||||||
|
|
||||||
|
// B.2 Additional Properties (non-normative)
|
||||||
|
"escape", "unescape",
|
||||||
|
|
||||||
|
// Window props (https://developer.mozilla.org/en/DOM/window)
|
||||||
|
"applicationCache", "closed", "Components", "content", "controllers",
|
||||||
|
"crypto", "defaultStatus", "dialogArguments", "directories",
|
||||||
|
"document", "frameElement", "frames", "fullScreen", "globalStorage",
|
||||||
|
"history", "innerHeight", "innerWidth", "length",
|
||||||
|
"location", "locationbar", "localStorage", "menubar",
|
||||||
|
"mozInnerScreenX", "mozInnerScreenY", "mozScreenPixelsPerCssPixel",
|
||||||
|
"name", "navigator", "opener", "outerHeight", "outerWidth",
|
||||||
|
"pageXOffset", "pageYOffset", "parent", "personalbar", "pkcs11",
|
||||||
|
"returnValue", "screen", "scrollbars", "scrollMaxX", "scrollMaxY",
|
||||||
|
"self", "sessionStorage", "sidebar", "status", "statusbar", "toolbar",
|
||||||
|
"top", "window",
|
||||||
|
|
||||||
|
// Window methods (https://developer.mozilla.org/en/DOM/window)
|
||||||
|
"alert", "addEventListener", "atob", "back", "blur", "btoa",
|
||||||
|
"captureEvents", "clearInterval", "clearTimeout", "close", "confirm",
|
||||||
|
"disableExternalCapture", "dispatchEvent", "dump",
|
||||||
|
"enableExternalCapture", "escape", "find", "focus", "forward",
|
||||||
|
"GeckoActiveXObject", "getAttention", "getAttentionWithCycleCount",
|
||||||
|
"getComputedStyle", "getSelection", "home", "maximize", "minimize",
|
||||||
|
"moveBy", "moveTo", "open", "openDialog", "postMessage", "print",
|
||||||
|
"prompt", "QueryInterface", "releaseEvents", "removeEventListener",
|
||||||
|
"resizeBy", "resizeTo", "restore", "routeEvent", "scroll", "scrollBy",
|
||||||
|
"scrollByLines", "scrollByPages", "scrollTo", "setInterval",
|
||||||
|
"setResizeable", "setTimeout", "showModalDialog", "sizeToContent",
|
||||||
|
"stop", "uuescape", "updateCommands", "XPCNativeWrapper",
|
||||||
|
"XPCSafeJSOjbectWrapper",
|
||||||
|
|
||||||
|
// Mozilla Window event handlers, same cite
|
||||||
|
"onabort", "onbeforeunload", "onchange", "onclick", "onclose",
|
||||||
|
"oncontextmenu", "ondragdrop", "onerror", "onfocus", "onhashchange",
|
||||||
|
"onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown",
|
||||||
|
"onmousemove", "onmouseout", "onmouseover", "onmouseup",
|
||||||
|
"onmozorientation", "onpaint", "onreset", "onresize", "onscroll",
|
||||||
|
"onselect", "onsubmit", "onunload",
|
||||||
|
|
||||||
|
// Safari Web Content Guide
|
||||||
|
// http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/SafariWebContent.pdf
|
||||||
|
// WebKit Window member data, from WebKit DOM Reference
|
||||||
|
// (http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/WebKitDOMRef/DOMWindow_idl/Classes/DOMWindow/index.html)
|
||||||
|
// TODO(fredsa) Many, many more functions and member data to add
|
||||||
|
"ontouchcancel", "ontouchend", "ontouchmove", "ontouchstart",
|
||||||
|
"ongesturestart", "ongesturechange", "ongestureend",
|
||||||
|
|
||||||
|
// extra window methods
|
||||||
|
"uneval",
|
||||||
|
|
||||||
|
// keywords https://developer.mozilla.org/en/New_in_JavaScript_1.7,
|
||||||
|
// https://developer.mozilla.org/en/New_in_JavaScript_1.8.1
|
||||||
|
"getPrototypeOf", "let", "yield",
|
||||||
|
|
||||||
|
// "future reserved words"
|
||||||
|
"abstract", "int", "short", "boolean", "interface", "static", "byte",
|
||||||
|
"long", "char", "final", "native", "synchronized", "float", "package",
|
||||||
|
"throws", "goto", "private", "transient", "implements", "protected",
|
||||||
|
"volatile", "double", "public",
|
||||||
|
|
||||||
|
// IE methods
|
||||||
|
// (http://msdn.microsoft.com/en-us/library/ms535873(VS.85).aspx#)
|
||||||
|
"attachEvent", "clientInformation", "clipboardData", "createPopup",
|
||||||
|
"dialogHeight", "dialogLeft", "dialogTop", "dialogWidth",
|
||||||
|
"onafterprint", "onbeforedeactivate", "onbeforeprint",
|
||||||
|
"oncontrolselect", "ondeactivate", "onhelp", "onresizeend",
|
||||||
|
|
||||||
|
// Common browser-defined identifiers not defined in ECMAScript
|
||||||
|
"event", "external", "Debug", "Enumerator", "Global", "Image",
|
||||||
|
"ActiveXObject", "VBArray", "Components",
|
||||||
|
|
||||||
|
// Functions commonly defined on Object
|
||||||
|
"toString", "getClass", "constructor", "prototype", "valueOf",
|
||||||
|
|
||||||
|
// Client-side JavaScript identifiers, which are needed for linkers
|
||||||
|
// that don't ensure GWT's window != $wnd, document != $doc, etc.
|
||||||
|
// Taken from the Rhino book, pg 715
|
||||||
|
"Anchor", "Applet", "Attr", "Canvas", "CanvasGradient",
|
||||||
|
"CanvasPattern", "CanvasRenderingContext2D", "CDATASection",
|
||||||
|
"CharacterData", "Comment", "CSS2Properties", "CSSRule",
|
||||||
|
"CSSStyleSheet", "Document", "DocumentFragment", "DocumentType",
|
||||||
|
"DOMException", "DOMImplementation", "DOMParser", "Element", "Event",
|
||||||
|
"ExternalInterface", "FlashPlayer", "Form", "Frame", "History",
|
||||||
|
"HTMLCollection", "HTMLDocument", "HTMLElement", "IFrame", "Image",
|
||||||
|
"Input", "JSObject", "KeyEvent", "Link", "Location", "MimeType",
|
||||||
|
"MouseEvent", "Navigator", "Node", "NodeList", "Option", "Plugin",
|
||||||
|
"ProcessingInstruction", "Range", "RangeException", "Screen", "Select",
|
||||||
|
"Table", "TableCell", "TableRow", "TableSelection", "Text", "TextArea",
|
||||||
|
"UIEvent", "Window", "XMLHttpRequest", "XMLSerializer",
|
||||||
|
"XPathException", "XPathResult", "XSLTProcessor",
|
||||||
|
|
||||||
|
// These keywords trigger the loading of the java-plugin. For the
|
||||||
|
// next-generation plugin, this results in starting a new Java process.
|
||||||
|
"java", "Packages", "netscape", "sun", "JavaObject", "JavaClass",
|
||||||
|
"JavaArray", "JavaMember",
|
||||||
|
|
||||||
|
// GWT-defined identifiers
|
||||||
|
"$wnd", "$doc", "$entry", "$moduleName", "$moduleBase", "$gwt_version", "$sessionId",
|
||||||
|
|
||||||
|
// Identifiers used by JsStackEmulator; later set to obfuscatable
|
||||||
|
"$stack", "$stackDepth", "$location",
|
||||||
|
};
|
||||||
|
|
||||||
|
reservedGlobalSymbols = new THashSet<String>(commonBuiltins.length);
|
||||||
|
Collections.addAll(reservedGlobalSymbols, commonBuiltins);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsReservedIdentifiers() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsContext;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsProgramFragment;
|
||||||
|
import com.google.dart.compiler.util.TextOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates JavaScript source from an AST.
|
||||||
|
*/
|
||||||
|
public class JsSourceGenerationVisitor extends JsToStringGenerationVisitor {
|
||||||
|
public JsSourceGenerationVisitor(TextOutput out) {
|
||||||
|
super(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsProgram program, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsProgramFragment x, JsContext ctx) {
|
||||||
|
// Descend naturally.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(JsBlock x, JsContext ctx) {
|
||||||
|
printJsBlock(x, false, true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that describes the boolean evaluation of an expression.
|
||||||
|
*/
|
||||||
|
public interface CanBooleanEval {
|
||||||
|
boolean isBooleanFalse();
|
||||||
|
boolean isBooleanTrue();
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by JavaScript objects that accept arguments.
|
||||||
|
*/
|
||||||
|
public interface HasArguments extends JsExpression {
|
||||||
|
|
||||||
|
List<JsExpression> getArguments();
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by JavaScript objects with conditional execution.
|
||||||
|
*/
|
||||||
|
public interface HasCondition {
|
||||||
|
|
||||||
|
JsExpression getCondition();
|
||||||
|
|
||||||
|
void setCondition(JsExpression condition);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.HasSymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by JavaScript objects that have a name.
|
||||||
|
*/
|
||||||
|
public interface HasName extends HasSymbol {
|
||||||
|
JsName getName();
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a javascript expression for array access.
|
||||||
|
*/
|
||||||
|
public final class JsArrayAccess extends JsExpressionImpl {
|
||||||
|
|
||||||
|
private JsExpression arrayExpr;
|
||||||
|
private JsExpression indexExpr;
|
||||||
|
|
||||||
|
public JsArrayAccess() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsArrayAccess(JsExpression arrayExpr, JsExpression indexExpr) {
|
||||||
|
this.arrayExpr = arrayExpr;
|
||||||
|
this.indexExpr = indexExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getArrayExpr() {
|
||||||
|
return arrayExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getIndexExpr() {
|
||||||
|
return indexExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return arrayExpr.hasSideEffects() || indexExpr.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArrayExpr(JsExpression arrayExpr) {
|
||||||
|
this.arrayExpr = arrayExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexExpr(JsExpression indexExpr) {
|
||||||
|
this.indexExpr = indexExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
arrayExpr = v.accept(arrayExpr);
|
||||||
|
indexExpr = v.accept(indexExpr);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.ARRAY_ACCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript expression for array literals.
|
||||||
|
*/
|
||||||
|
public final class JsArrayLiteral extends JsLiteral {
|
||||||
|
private final List<JsExpression> expressions;
|
||||||
|
|
||||||
|
public JsArrayLiteral() {
|
||||||
|
expressions = new SmartList<JsExpression>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsArrayLiteral(List<JsExpression> expressions) {
|
||||||
|
this.expressions = expressions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsExpression> getExpressions() {
|
||||||
|
return expressions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
for (JsExpression expr : expressions) {
|
||||||
|
if (expr.hasSideEffects()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(expressions);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.ARRAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript binary operation.
|
||||||
|
*/
|
||||||
|
public final class JsBinaryOperation extends JsExpressionImpl {
|
||||||
|
private JsExpression arg1;
|
||||||
|
private JsExpression arg2;
|
||||||
|
private final JsBinaryOperator op;
|
||||||
|
|
||||||
|
public JsBinaryOperation(JsBinaryOperator op) {
|
||||||
|
this(op, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBinaryOperation(JsBinaryOperator op, @Nullable JsExpression arg1, @Nullable JsExpression arg2) {
|
||||||
|
this.op = op;
|
||||||
|
this.arg1 = arg1;
|
||||||
|
this.arg2 = arg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getArg1() {
|
||||||
|
return arg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getArg2() {
|
||||||
|
return arg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBinaryOperator getOperator() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return op.isAssignment() || arg1.hasSideEffects() || arg2.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
// Precarious coding, but none of these can have null results.
|
||||||
|
if (op.getPrecedence() > 5) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (op == JsBinaryOperator.OR) {
|
||||||
|
if (arg1 instanceof CanBooleanEval) {
|
||||||
|
if (((CanBooleanEval) arg1).isBooleanTrue()) {
|
||||||
|
assert arg1.isDefinitelyNotNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// AND and OR can return nulls
|
||||||
|
if (op.isAssignment()) {
|
||||||
|
if (op == JsBinaryOperator.ASG) {
|
||||||
|
return arg2.isDefinitelyNotNull();
|
||||||
|
} else {
|
||||||
|
// All other ASG's are math ops.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == JsBinaryOperator.COMMA) {
|
||||||
|
return arg2.isDefinitelyNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
if (op == JsBinaryOperator.AND) {
|
||||||
|
return arg1.isDefinitelyNull();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (op.isAssignment()) {
|
||||||
|
arg1 = v.acceptLvalue(arg1);
|
||||||
|
} else {
|
||||||
|
arg1 = v.accept(arg1);
|
||||||
|
}
|
||||||
|
arg2 = v.accept(arg2);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.BINARY_OP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the operator in a JavaScript binary operation.
|
||||||
|
*/
|
||||||
|
public enum JsBinaryOperator implements JsOperator {
|
||||||
|
/*
|
||||||
|
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
|
||||||
|
* (page 57)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Precedence 15 is for really important things that have their own AST
|
||||||
|
* classes.
|
||||||
|
*
|
||||||
|
* Precedence 14 is for unary operators.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MUL("*", 13, LEFT | INFIX), DIV("/", 13, LEFT | INFIX), MOD("%", 13, LEFT
|
||||||
|
| INFIX),
|
||||||
|
|
||||||
|
ADD("+", 12, LEFT | INFIX), SUB("-", 12, LEFT | INFIX),
|
||||||
|
|
||||||
|
SHL("<<", 11, LEFT | INFIX), SHR(">>", 11, LEFT | INFIX), SHRU(">>>", 11,
|
||||||
|
LEFT | INFIX),
|
||||||
|
|
||||||
|
LT("<", 10, LEFT | INFIX), LTE("<=", 10, LEFT | INFIX), GT(">", 10, LEFT
|
||||||
|
| INFIX), GTE(">=", 10, LEFT | INFIX), INSTANCEOF("instanceof", 10, LEFT
|
||||||
|
| INFIX), INOP("in", 10, LEFT | INFIX),
|
||||||
|
|
||||||
|
EQ("==", 9, LEFT | INFIX), NEQ("!=", 9, LEFT | INFIX), REF_EQ("===", 9, LEFT
|
||||||
|
| INFIX), REF_NEQ("!==", 9, LEFT | INFIX),
|
||||||
|
|
||||||
|
BIT_AND("&", 8, LEFT | INFIX),
|
||||||
|
|
||||||
|
BIT_XOR("^", 7, LEFT | INFIX),
|
||||||
|
|
||||||
|
BIT_OR("|", 6, LEFT | INFIX),
|
||||||
|
|
||||||
|
AND("&&", 5, LEFT | INFIX),
|
||||||
|
|
||||||
|
OR("||", 4, LEFT | INFIX),
|
||||||
|
|
||||||
|
// Precedence 3 is for the condition operator.
|
||||||
|
|
||||||
|
// These assignment operators are right-associative.
|
||||||
|
ASG("=", 2, INFIX), ASG_ADD("+=", 2, INFIX), ASG_SUB("-=", 2, INFIX), ASG_MUL(
|
||||||
|
"*=", 2, INFIX), ASG_DIV("/=", 2, INFIX), ASG_MOD("%=", 2, INFIX), ASG_SHL(
|
||||||
|
"<<=", 2, INFIX), ASG_SHR(">>=", 2, INFIX), ASG_SHRU(">>>=", 2, INFIX), ASG_BIT_AND(
|
||||||
|
"&=", 2, INFIX), ASG_BIT_OR("|=", 2, INFIX), ASG_BIT_XOR("^=", 2, INFIX),
|
||||||
|
|
||||||
|
COMMA(",", 1, LEFT | INFIX);
|
||||||
|
|
||||||
|
private final int mask;
|
||||||
|
private final int precedence;
|
||||||
|
private final String symbol;
|
||||||
|
|
||||||
|
private JsBinaryOperator(String symbol, int precedence, int mask) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
this.precedence = precedence;
|
||||||
|
this.mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPrecedence() {
|
||||||
|
return precedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAssignment() {
|
||||||
|
return getPrecedence() == ASG.getPrecedence();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeyword() {
|
||||||
|
return this == INSTANCEOF || this == INOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeftAssociative() {
|
||||||
|
return (mask & LEFT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrecedenceLessThan(JsOperator other) {
|
||||||
|
return precedence < other.getPrecedence();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidInfix() {
|
||||||
|
return (mask & INFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidPostfix() {
|
||||||
|
return (mask & POSTFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidPrefix() {
|
||||||
|
return (mask & PREFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript block statement.
|
||||||
|
*/
|
||||||
|
public class JsBlock extends JsNodeImpl implements JsStatement {
|
||||||
|
private final List<JsStatement> statements;
|
||||||
|
|
||||||
|
public JsBlock() {
|
||||||
|
this(new ArrayList<JsStatement>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock(JsStatement statement) {
|
||||||
|
this(Collections.singletonList(statement));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock(JsStatement... statements) {
|
||||||
|
this(Arrays.asList(statements));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock(List<JsStatement> statements) {
|
||||||
|
this.statements = statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsStatement> getStatements() {
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return statements.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGlobalBlock() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(statements);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the JavaScript break statement.
|
||||||
|
*/
|
||||||
|
public final class JsBreak extends JsContinue {
|
||||||
|
public JsBreak() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBreak(JsNameRef label) {
|
||||||
|
super(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (label != null) {
|
||||||
|
v.accept(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the JavaScript case statement.
|
||||||
|
*/
|
||||||
|
public final class JsCase extends JsSwitchMember {
|
||||||
|
|
||||||
|
private JsExpression caseExpr;
|
||||||
|
|
||||||
|
public JsCase() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getCaseExpr() {
|
||||||
|
return caseExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaseExpr(JsExpression caseExpr) {
|
||||||
|
this.caseExpr = caseExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
caseExpr = v.accept(caseExpr);
|
||||||
|
v.acceptWithInsertRemove(statements);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.CASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript catch clause.
|
||||||
|
*/
|
||||||
|
public class JsCatch extends JsNodeImpl implements HasCondition {
|
||||||
|
|
||||||
|
protected final JsCatchScope scope;
|
||||||
|
private JsBlock body;
|
||||||
|
private JsExpression condition;
|
||||||
|
private JsParameter param;
|
||||||
|
|
||||||
|
public JsCatch(JsScope parent, String ident) {
|
||||||
|
super();
|
||||||
|
assert (parent != null);
|
||||||
|
scope = new JsCatchScope(parent, ident);
|
||||||
|
param = new JsParameter(scope.findName(ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsExpression getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsParameter getParameter() {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsScope getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(JsBlock body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCondition(JsExpression condition) {
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
param = v.accept(param);
|
||||||
|
if (condition != null) {
|
||||||
|
condition = v.accept(condition);
|
||||||
|
}
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.CATCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A special scope used only for catch blocks. It only holds a single symbol:
|
||||||
|
* the catch argument's name.
|
||||||
|
*/
|
||||||
|
public class JsCatchScope extends JsScope {
|
||||||
|
private final JsName name;
|
||||||
|
|
||||||
|
public JsCatchScope(JsScope parent, String ident) {
|
||||||
|
super(parent, "Catch scope");
|
||||||
|
name = new JsName(this, ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName declareName(String identifier) {
|
||||||
|
// Declare into parent scope!
|
||||||
|
return getParent().declareName(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasOwnName(@NotNull String name) {
|
||||||
|
return findOwnName(name) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JsName findOwnName(String ident) {
|
||||||
|
return name.getIdent().equals(ident) ? name : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript conditional expression.
|
||||||
|
*/
|
||||||
|
public final class JsConditional extends JsExpressionImpl {
|
||||||
|
private JsExpression testExpr;
|
||||||
|
private JsExpression elseExpr;
|
||||||
|
private JsExpression thenExpr;
|
||||||
|
|
||||||
|
public JsConditional() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsConditional(JsExpression testExpr, JsExpression thenExpr, JsExpression elseExpr) {
|
||||||
|
this.testExpr = testExpr;
|
||||||
|
this.thenExpr = thenExpr;
|
||||||
|
this.elseExpr = elseExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getElseExpression() {
|
||||||
|
return elseExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getTestExpression() {
|
||||||
|
return testExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getThenExpression() {
|
||||||
|
return thenExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return testExpr.hasSideEffects() || thenExpr.hasSideEffects() || elseExpr.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return thenExpr.isDefinitelyNotNull() && elseExpr.isDefinitelyNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return thenExpr.isDefinitelyNull() && elseExpr.isDefinitelyNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElseExpression(JsExpression elseExpr) {
|
||||||
|
this.elseExpr = elseExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestExpression(JsExpression testExpr) {
|
||||||
|
this.testExpr = testExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThenExpression(JsExpression thenExpr) {
|
||||||
|
this.thenExpr = thenExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
testExpr = v.accept(testExpr);
|
||||||
|
thenExpr = v.accept(thenExpr);
|
||||||
|
elseExpr = v.accept(elseExpr);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.CONDITIONAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context in which a JsNode visitation occurs. This represents the set of
|
||||||
|
* possible operations a JsVisitor subclass can perform on the currently visited
|
||||||
|
* node.
|
||||||
|
*/
|
||||||
|
public interface JsContext {
|
||||||
|
|
||||||
|
boolean canInsert();
|
||||||
|
|
||||||
|
boolean canRemove();
|
||||||
|
|
||||||
|
void insertAfter(JsVisitable node);
|
||||||
|
|
||||||
|
void insertBefore(JsVisitable node);
|
||||||
|
|
||||||
|
boolean isLvalue();
|
||||||
|
|
||||||
|
void removeMe();
|
||||||
|
|
||||||
|
void replaceMe(JsVisitable node);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the JavaScript continue statement.
|
||||||
|
*/
|
||||||
|
public class JsContinue extends JsNodeImpl implements JsStatement {
|
||||||
|
protected final JsNameRef label;
|
||||||
|
|
||||||
|
public JsContinue() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsContinue(@Nullable JsNameRef label) {
|
||||||
|
super();
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (label != null) {
|
||||||
|
v.accept(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript debugger statement.
|
||||||
|
*/
|
||||||
|
public class JsDebugger extends JsNodeImpl implements JsStatement {
|
||||||
|
|
||||||
|
public JsDebugger() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.DEBUGGER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the default option in a JavaScript swtich statement.
|
||||||
|
*/
|
||||||
|
public final class JsDefault extends JsSwitchMember {
|
||||||
|
|
||||||
|
public JsDefault() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(statements);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript do..while statement.
|
||||||
|
*/
|
||||||
|
public class JsDoWhile extends JsWhile {
|
||||||
|
public JsDoWhile() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsDoWhile(JsExpression condition, JsStatement body) {
|
||||||
|
super(condition, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.DO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
condition = v.accept(condition);
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an empty statement in JavaScript.
|
||||||
|
*/
|
||||||
|
public class JsEmpty extends JsNodeImpl implements JsStatement {
|
||||||
|
// Interned by JsProgram
|
||||||
|
JsEmpty() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public final class JsExprStmt extends JsNodeImpl implements JsStatement {
|
||||||
|
private JsExpression expr;
|
||||||
|
|
||||||
|
public JsExprStmt(JsExpression expr) {
|
||||||
|
super();
|
||||||
|
this.expr = expr;
|
||||||
|
this.setSourceInfo(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getExpression() {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
expr = v.accept(expr);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.EXPRESSION_STMT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.HasSourceInfo;
|
||||||
|
import com.google.dart.compiler.common.SourceInfo;
|
||||||
|
|
||||||
|
public interface JsExpression extends JsNode, SourceInfo, HasSourceInfo, JsVisitable {
|
||||||
|
/**
|
||||||
|
* Determines whether the expression can cause side effects.
|
||||||
|
*/
|
||||||
|
boolean hasSideEffects();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the target expression is definitely not null.
|
||||||
|
*/
|
||||||
|
boolean isDefinitelyNotNull();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the target expression is definitely null.
|
||||||
|
*/
|
||||||
|
boolean isDefinitelyNull();
|
||||||
|
|
||||||
|
boolean isLeaf();
|
||||||
|
|
||||||
|
JsStatement makeStmt();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
abstract class JsExpressionImpl extends JsNodeImpl implements JsExpression {
|
||||||
|
protected JsExpressionImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not this expression is a leaf, such as a
|
||||||
|
* {@link JsNameRef}, {@link JsLiteral.JsBooleanLiteral}, and so on. Leaf expressions
|
||||||
|
* never need to be parenthesized.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isLeaf() {
|
||||||
|
// Conservatively say that it isn't a leaf.
|
||||||
|
// Individual subclasses can speak for themselves if they are a leaf.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsStatement makeStmt() {
|
||||||
|
return new JsExprStmt(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.SourceInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A <code>for</code> statement. If specified at all, the initializer part is
|
||||||
|
* either a declaration of one or more variables, in which case
|
||||||
|
* {@link #getInitVars()} is used, or an expression, in which case
|
||||||
|
* {@link #getInitExpr()} is used. In the latter case, the comma operator is
|
||||||
|
* often used to create a compound expression.
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* Note that any of the parts of the <code>for</code> loop header can be
|
||||||
|
* <code>null</code>, although the body will never be null.
|
||||||
|
*/
|
||||||
|
public class JsFor extends JsNodeImpl implements JsStatement {
|
||||||
|
private JsStatement body;
|
||||||
|
private JsExpression condition;
|
||||||
|
private JsExpression incrExpr;
|
||||||
|
private JsExpression initExpr;
|
||||||
|
private JsVars initVars;
|
||||||
|
|
||||||
|
public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpr) {
|
||||||
|
this.initVars = initVars;
|
||||||
|
this.incrExpr = incrementExpr;
|
||||||
|
this.condition = condition;
|
||||||
|
initExpr = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsFor(JsExpression initExpr, JsExpression condition, JsExpression incrementExpr) {
|
||||||
|
this.initExpr = initExpr;
|
||||||
|
this.incrExpr = incrementExpr;
|
||||||
|
this.condition = condition;
|
||||||
|
initVars = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getIncrExpr() {
|
||||||
|
return incrExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getInitExpr() {
|
||||||
|
return initExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVars getInitVars() {
|
||||||
|
return initVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(JsStatement body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
assert (!(initExpr != null && initVars != null));
|
||||||
|
|
||||||
|
if (initExpr != null) {
|
||||||
|
initExpr = v.accept(initExpr);
|
||||||
|
}
|
||||||
|
else if (initVars != null) {
|
||||||
|
initVars = v.accept(initVars);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition != null) {
|
||||||
|
condition = v.accept(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incrExpr != null) {
|
||||||
|
incrExpr = v.accept(incrExpr);
|
||||||
|
}
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsFor setSourceRef(SourceInfo info) {
|
||||||
|
super.setSourceRef(info);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.FOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript for..in statement.
|
||||||
|
*/
|
||||||
|
public class JsForIn extends JsNodeImpl implements JsStatement {
|
||||||
|
|
||||||
|
private JsStatement body;
|
||||||
|
private JsExpression iterExpr;
|
||||||
|
private JsExpression objExpr;
|
||||||
|
|
||||||
|
// Optional: the name of a new iterator variable to introduce
|
||||||
|
private final JsName iterVarName;
|
||||||
|
|
||||||
|
public JsForIn() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsForIn(JsName iterVarName) {
|
||||||
|
this.iterVarName = iterVarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getIterExpr() {
|
||||||
|
return iterExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsName getIterVarName() {
|
||||||
|
return iterVarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getObjExpr() {
|
||||||
|
return objExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(JsStatement body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIterExpr(JsExpression iterExpr) {
|
||||||
|
this.iterExpr = iterExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjExpr(JsExpression objExpr) {
|
||||||
|
this.objExpr = objExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (iterExpr != null) {
|
||||||
|
iterExpr = v.acceptLvalue(iterExpr);
|
||||||
|
}
|
||||||
|
objExpr = v.accept(objExpr);
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.FOR_IN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.SourceInfo;
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class JsFunction extends JsLiteral implements HasName {
|
||||||
|
private JsBlock body;
|
||||||
|
private List<JsParameter> params;
|
||||||
|
private final JsScope scope;
|
||||||
|
private JsName name;
|
||||||
|
|
||||||
|
public JsFunction(JsScope parentScope) {
|
||||||
|
this(parentScope, (JsName) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsFunction(JsScope parentScope, JsBlock body) {
|
||||||
|
this(parentScope, (JsName) null);
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsFunction(JsScope parentScope, @Nullable JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
this.scope = new JsScope(parentScope, name == null ? null : name.getIdent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsParameter> getParameters() {
|
||||||
|
if (params == null) {
|
||||||
|
params = new SmartList<JsParameter>();
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsScope getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
// If there's a name, the name is assigned to.
|
||||||
|
return name != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(JsBlock body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(@Nullable JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(params);
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsFunction setSourceRef(SourceInfo info) {
|
||||||
|
super.setSourceRef(info);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.FUNCTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represnts a JavaScript block in the global scope.
|
||||||
|
*/
|
||||||
|
public class JsGlobalBlock extends JsBlock {
|
||||||
|
|
||||||
|
public JsGlobalBlock() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGlobalBlock() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript if statement.
|
||||||
|
*/
|
||||||
|
public final class JsIf extends JsNodeImpl implements JsStatement {
|
||||||
|
private JsExpression ifExpression;
|
||||||
|
private JsStatement thenStatement;
|
||||||
|
private JsStatement elseStatement;
|
||||||
|
|
||||||
|
public JsIf() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsIf(JsExpression ifExpression, JsStatement thenStatement, JsStatement elseStatement) {
|
||||||
|
this.ifExpression = ifExpression;
|
||||||
|
this.thenStatement = thenStatement;
|
||||||
|
this.elseStatement = elseStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsIf(JsExpression ifExpression, JsStatement thenStatement) {
|
||||||
|
this.ifExpression = ifExpression;
|
||||||
|
this.thenStatement = thenStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getElseStatement() {
|
||||||
|
return elseStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getIfExpression() {
|
||||||
|
return ifExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getThenStatement() {
|
||||||
|
return thenStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElseStatement(JsStatement elseStmt) {
|
||||||
|
this.elseStatement = elseStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIfExpression(JsExpression ifExpr) {
|
||||||
|
this.ifExpression = ifExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThenStatement(JsStatement thenStmt) {
|
||||||
|
this.thenStatement = thenStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
ifExpression = v.accept(ifExpression);
|
||||||
|
thenStatement = v.accept(thenStatement);
|
||||||
|
if (elseStatement != null) {
|
||||||
|
elseStatement = v.accept(elseStatement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.IF;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript invocation.
|
||||||
|
*/
|
||||||
|
public final class JsInvocation extends JsExpressionImpl implements HasArguments {
|
||||||
|
private final List<JsExpression> arguments;
|
||||||
|
private JsExpression qualifier;
|
||||||
|
|
||||||
|
public JsInvocation() {
|
||||||
|
arguments = new SmartList<JsExpression>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsInvocation(JsExpression qualifier, List<JsExpression> arguments) {
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsInvocation(JsExpression qualifier, JsExpression arg) {
|
||||||
|
this(qualifier, Collections.singletonList(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsInvocation(JsExpression qualifier, JsExpression... arguments) {
|
||||||
|
this(qualifier, Arrays.asList(arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsInvocation(JsExpression qualifier) {
|
||||||
|
this();
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JsExpression> getArguments() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getQualifier() {
|
||||||
|
return qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQualifier(JsExpression qualifier) {
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
qualifier = v.accept(qualifier);
|
||||||
|
v.acceptList(arguments);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.INVOKE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript label statement.
|
||||||
|
*/
|
||||||
|
public class JsLabel extends JsNodeImpl implements JsStatement, HasName {
|
||||||
|
|
||||||
|
private final JsName label;
|
||||||
|
|
||||||
|
private JsStatement stmt;
|
||||||
|
|
||||||
|
public JsLabel(JsName label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName getName() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getStmt() {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStmt(JsStatement stmt) {
|
||||||
|
this.stmt = stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
stmt = v.accept(stmt);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.LABEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public abstract class JsLiteral extends JsExpressionImpl implements CanBooleanEval {
|
||||||
|
public static final JsValueLiteral THIS = new JsThisRef();
|
||||||
|
public static final JsNameRef UNDEFINED = new JsNameRef("undefined");
|
||||||
|
|
||||||
|
public static final JsNullLiteral NULL = new JsNullLiteral();
|
||||||
|
|
||||||
|
public static final JsBooleanLiteral TRUE = new JsBooleanLiteral(true);
|
||||||
|
public static final JsBooleanLiteral FALSE = new JsBooleanLiteral(false);
|
||||||
|
|
||||||
|
public static JsBooleanLiteral getBoolean(boolean truth) {
|
||||||
|
return truth ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class JsThisRef extends JsValueLiteral {
|
||||||
|
private JsThisRef() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.THIS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class JsBooleanLiteral extends JsValueLiteral {
|
||||||
|
private final boolean value;
|
||||||
|
|
||||||
|
// Should be interned by JsProgram
|
||||||
|
private JsBooleanLiteral(boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.BOOLEAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract base class for named JavaScript objects.
|
||||||
|
*/
|
||||||
|
public class JsName implements Symbol {
|
||||||
|
private final JsScope enclosing;
|
||||||
|
private final String ident;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ident the unmangled ident to use for this name
|
||||||
|
*/
|
||||||
|
JsName(JsScope enclosing, String ident) {
|
||||||
|
this.enclosing = enclosing;
|
||||||
|
this.ident = ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdent() {
|
||||||
|
return ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef makeRef() {
|
||||||
|
return new JsNameRef(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ident.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(obj instanceof JsName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JsName other = (JsName) obj;
|
||||||
|
return ident.equals(other.ident) && enclosing == other.enclosing;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a JavaScript expression that references a name.
|
||||||
|
*/
|
||||||
|
public final class JsNameRef extends JsExpressionImpl implements CanBooleanEval, HasName {
|
||||||
|
private String ident;
|
||||||
|
private JsName name;
|
||||||
|
private JsExpression qualifier;
|
||||||
|
|
||||||
|
public JsNameRef(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef(String ident) {
|
||||||
|
this.ident = ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef(String ident, JsExpression qualifier) {
|
||||||
|
this.ident = ident;
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef(String ident, String qualifier) {
|
||||||
|
this(ident, new JsNameRef(qualifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNameRef(JsName name, JsExpression qualifier) {
|
||||||
|
this.name = name;
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdent() {
|
||||||
|
return (name == null) ? ident : name.getIdent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getQualifier() {
|
||||||
|
return qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
if (qualifier == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!qualifier.isDefinitelyNotNull()) {
|
||||||
|
// Could trigger NPE.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return qualifier.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return isDefinitelyNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
if (name != null) {
|
||||||
|
return (JsLiteral.UNDEFINED.getName() == name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeaf() {
|
||||||
|
if (qualifier == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resolve(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
this.ident = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQualifier(JsExpression qualifier) {
|
||||||
|
this.qualifier = qualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (qualifier != null) {
|
||||||
|
qualifier = v.accept(qualifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.NAME_REF;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the JavaScript new expression.
|
||||||
|
*/
|
||||||
|
public final class JsNew extends JsExpressionImpl implements HasArguments {
|
||||||
|
private final List<JsExpression> arguments;
|
||||||
|
private JsExpression ctorExpression;
|
||||||
|
|
||||||
|
public JsNew(JsExpression ctorExpression) {
|
||||||
|
this(ctorExpression, new SmartList<JsExpression>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNew(JsExpression ctorExpression, List<JsExpression> arguments) {
|
||||||
|
this.ctorExpression = ctorExpression;
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JsExpression> getArguments() {
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getConstructorExpression() {
|
||||||
|
return ctorExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
// Sadly, in JS it can be!
|
||||||
|
// TODO: analysis could probably determine most instances cannot be null.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
ctorExpression = v.accept(ctorExpression);
|
||||||
|
v.acceptList(arguments);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.NEW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public interface JsNode extends JsVisitable {
|
||||||
|
NodeKind getKind();
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.JsSourceGenerationVisitor;
|
||||||
|
import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
|
||||||
|
import com.google.dart.compiler.common.AbstractNode;
|
||||||
|
import com.google.dart.compiler.common.SourceInfo;
|
||||||
|
import com.google.dart.compiler.util.TextOutputImpl;
|
||||||
|
|
||||||
|
abstract class JsNodeImpl extends AbstractNode implements JsNode {
|
||||||
|
protected JsNodeImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Causes source generation to delegate to the one visitor
|
||||||
|
public final String toSource() {
|
||||||
|
TextOutputImpl out = new TextOutputImpl();
|
||||||
|
JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
|
||||||
|
v.accept(this);
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Causes source generation to delegate to the one visitor
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
TextOutputImpl out = new TextOutputImpl();
|
||||||
|
JsToStringGenerationVisitor v = new JsToStringGenerationVisitor(out);
|
||||||
|
v.accept(this);
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceInfo getSourceInfo() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNode setSourceRef(SourceInfo info) {
|
||||||
|
if (info != null) {
|
||||||
|
this.setSourceInfo(info);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public final class JsNullLiteral extends JsValueLiteral {
|
||||||
|
JsNullLiteral() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public abstract class JsNumberLiteral extends JsValueLiteral {
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class JsDoubleLiteral extends JsNumberLiteral {
|
||||||
|
public final double value;
|
||||||
|
|
||||||
|
JsDoubleLiteral(double value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return value == 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return value != 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class JsIntLiteral extends JsNumberLiteral {
|
||||||
|
public final int value;
|
||||||
|
|
||||||
|
JsIntLiteral(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return value == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return value != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class JsObjectLiteral extends JsLiteral {
|
||||||
|
private final List<JsPropertyInitializer> properties;
|
||||||
|
|
||||||
|
private final boolean multiline;
|
||||||
|
|
||||||
|
public JsObjectLiteral() {
|
||||||
|
this(new SmartList<JsPropertyInitializer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsObjectLiteral(boolean multiline) {
|
||||||
|
this(new SmartList<JsPropertyInitializer>(), multiline);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMultiline() {
|
||||||
|
return multiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsObjectLiteral(List<JsPropertyInitializer> properties) {
|
||||||
|
this(properties, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsObjectLiteral(List<JsPropertyInitializer> properties, boolean multiline) {
|
||||||
|
this.properties = properties;
|
||||||
|
this.multiline = multiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsPropertyInitializer> getPropertyInitializers() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
for (JsPropertyInitializer prop : properties) {
|
||||||
|
if (prop.hasSideEffects()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(properties);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.OBJECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public interface JsOperator {
|
||||||
|
int INFIX = 0x02;
|
||||||
|
int LEFT = 0x01;
|
||||||
|
int POSTFIX = 0x04;
|
||||||
|
int PREFIX = 0x08;
|
||||||
|
|
||||||
|
int getPrecedence();
|
||||||
|
|
||||||
|
String getSymbol();
|
||||||
|
|
||||||
|
boolean isKeyword();
|
||||||
|
|
||||||
|
boolean isLeftAssociative();
|
||||||
|
|
||||||
|
boolean isPrecedenceLessThan(JsOperator other);
|
||||||
|
|
||||||
|
boolean isValidInfix();
|
||||||
|
|
||||||
|
boolean isValidPostfix();
|
||||||
|
|
||||||
|
boolean isValidPrefix();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript parameter.
|
||||||
|
*/
|
||||||
|
public final class JsParameter extends JsNodeImpl implements HasName {
|
||||||
|
private final JsName name;
|
||||||
|
|
||||||
|
public JsParameter(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript postfix operation.
|
||||||
|
*/
|
||||||
|
public final class JsPostfixOperation extends JsUnaryOperation {
|
||||||
|
|
||||||
|
public JsPostfixOperation(JsUnaryOperator op) {
|
||||||
|
this(op, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsPostfixOperation(JsUnaryOperator op, JsExpression arg) {
|
||||||
|
super(op, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
super.traverse(v, ctx);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.POSTFIX_OP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript prefix operation.
|
||||||
|
*/
|
||||||
|
public final class JsPrefixOperation extends JsUnaryOperation implements CanBooleanEval {
|
||||||
|
|
||||||
|
public JsPrefixOperation(JsUnaryOperator op) {
|
||||||
|
this(op, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsPrefixOperation(JsUnaryOperator op, JsExpression arg) {
|
||||||
|
super(op, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
if (getOperator() == JsUnaryOperator.VOID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
|
||||||
|
CanBooleanEval eval = (CanBooleanEval) getArg();
|
||||||
|
return eval.isBooleanTrue();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
if (getOperator() == JsUnaryOperator.NOT && getArg() instanceof CanBooleanEval) {
|
||||||
|
CanBooleanEval eval = (CanBooleanEval) getArg();
|
||||||
|
return eval.isBooleanFalse();
|
||||||
|
}
|
||||||
|
if (getOperator() == JsUnaryOperator.TYPEOF) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
if (getOperator() == JsUnaryOperator.TYPEOF) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return getOperator() != JsUnaryOperator.VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return getOperator() == JsUnaryOperator.VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
super.traverse(v, ctx);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.PREFIX_OP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import gnu.trove.TDoubleObjectHashMap;
|
||||||
|
import gnu.trove.THashMap;
|
||||||
|
import gnu.trove.TIntObjectHashMap;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsDoubleLiteral;
|
||||||
|
import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript program.
|
||||||
|
*/
|
||||||
|
public final class JsProgram extends JsNodeImpl {
|
||||||
|
private final JsEmpty emptyStmt;
|
||||||
|
|
||||||
|
private JsProgramFragment[] fragments;
|
||||||
|
|
||||||
|
private final TDoubleObjectHashMap<JsDoubleLiteral> doubleLiteralMap = new TDoubleObjectHashMap<JsDoubleLiteral>();
|
||||||
|
private final TIntObjectHashMap<JsIntLiteral> intLiteralMap = new TIntObjectHashMap<JsIntLiteral>();
|
||||||
|
|
||||||
|
private final JsRootScope rootScope;
|
||||||
|
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
|
||||||
|
private final JsScope topScope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a JavaScript program object.
|
||||||
|
*/
|
||||||
|
public JsProgram(String unitId) {
|
||||||
|
rootScope = new JsRootScope(this);
|
||||||
|
topScope = new JsScope(rootScope, "Global", unitId);
|
||||||
|
setFragmentCount(1);
|
||||||
|
|
||||||
|
emptyStmt = new JsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsEmpty getEmptyStmt() {
|
||||||
|
return emptyStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getFragmentBlock(int fragment) {
|
||||||
|
if (fragment < 0 || fragment >= fragments.length) {
|
||||||
|
throw new IllegalArgumentException("Invalid fragment: " + fragment);
|
||||||
|
}
|
||||||
|
return fragments[fragment].getGlobalBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getGlobalBlock() {
|
||||||
|
return getFragmentBlock(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNumberLiteral getNumberLiteral(double value) {
|
||||||
|
JsDoubleLiteral literal = doubleLiteralMap.get(value);
|
||||||
|
if (literal == null) {
|
||||||
|
literal = new JsDoubleLiteral(value);
|
||||||
|
doubleLiteralMap.put(value, literal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsNumberLiteral getNumberLiteral(int value) {
|
||||||
|
JsIntLiteral literal = intLiteralMap.get(value);
|
||||||
|
if (literal == null) {
|
||||||
|
literal = new JsIntLiteral(value);
|
||||||
|
intLiteralMap.put(value, literal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the quasi-mythical root scope. This is not the same as the top scope;
|
||||||
|
* all unresolvable identifiers wind up here, because they are considered
|
||||||
|
* external to the program.
|
||||||
|
*/
|
||||||
|
public JsRootScope getRootScope() {
|
||||||
|
return rootScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the top level scope. This is the scope of all the statements in the
|
||||||
|
* main program.
|
||||||
|
*/
|
||||||
|
public JsScope getScope() {
|
||||||
|
return topScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or retrieves a JsStringLiteral from an interned object pool.
|
||||||
|
*/
|
||||||
|
public JsStringLiteral getStringLiteral(String value) {
|
||||||
|
JsStringLiteral literal = stringLiteralMap.get(value);
|
||||||
|
if (literal == null) {
|
||||||
|
literal = new JsStringLiteral(value);
|
||||||
|
stringLiteralMap.put(value, literal);
|
||||||
|
}
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFragmentCount(int fragments) {
|
||||||
|
this.fragments = new JsProgramFragment[fragments];
|
||||||
|
for (int i = 0; i < fragments; i++) {
|
||||||
|
this.fragments[i] = new JsProgramFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, @Nullable JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
for (JsProgramFragment fragment : fragments) {
|
||||||
|
v.accept(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.PROGRAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One independently loadable fragment of a {@link JsProgram}.
|
||||||
|
*/
|
||||||
|
public class JsProgramFragment extends JsNodeImpl {
|
||||||
|
|
||||||
|
private final JsGlobalBlock globalBlock;
|
||||||
|
|
||||||
|
public JsProgramFragment() {
|
||||||
|
this.globalBlock = new JsGlobalBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getGlobalBlock() {
|
||||||
|
return globalBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.accept(globalBlock);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.PROGRAM_FRAGMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in object literals to specify property values by name.
|
||||||
|
*/
|
||||||
|
public class JsPropertyInitializer extends JsNodeImpl {
|
||||||
|
private JsExpression labelExpr;
|
||||||
|
private JsExpression valueExpr;
|
||||||
|
|
||||||
|
public JsPropertyInitializer(@NotNull JsExpression labelExpr) {
|
||||||
|
this.labelExpr = labelExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsPropertyInitializer(@NotNull JsExpression labelExpr, @NotNull JsExpression valueExpr) {
|
||||||
|
this(labelExpr);
|
||||||
|
this.valueExpr = valueExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getLabelExpr() {
|
||||||
|
return labelExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getValueExpr() {
|
||||||
|
return valueExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSideEffects() {
|
||||||
|
return labelExpr.hasSideEffects() || valueExpr.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueExpr(@NotNull JsExpression valueExpr) {
|
||||||
|
this.valueExpr = valueExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
labelExpr = v.accept(labelExpr);
|
||||||
|
valueExpr = v.accept(valueExpr);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.PROPERTY_INIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript regular expression.
|
||||||
|
*/
|
||||||
|
public final class JsRegExp extends JsValueLiteral {
|
||||||
|
|
||||||
|
private String flags;
|
||||||
|
private String pattern;
|
||||||
|
|
||||||
|
public JsRegExp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFlags() {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlags(String suffix) {
|
||||||
|
this.flags = suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPattern(String re) {
|
||||||
|
this.pattern = re;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.REGEXP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript return statement.
|
||||||
|
*/
|
||||||
|
public final class JsReturn extends JsNodeImpl implements JsStatement {
|
||||||
|
|
||||||
|
private JsExpression expr;
|
||||||
|
|
||||||
|
public JsReturn() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsReturn(JsExpression expr) {
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getExpr() {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpr(JsExpression expr) {
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (expr != null) {
|
||||||
|
expr = v.accept(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.RETURN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.JsReservedIdentifiers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root scope is the parent of every scope. All identifiers in this scope
|
||||||
|
* are not obfuscatable. This scope is prefilled with reserved global
|
||||||
|
* JavaScript symbols.
|
||||||
|
*/
|
||||||
|
public final class JsRootScope extends JsScope {
|
||||||
|
private final JsProgram program;
|
||||||
|
|
||||||
|
public JsRootScope(JsProgram program) {
|
||||||
|
super("Root");
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsProgram getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JsName findOwnName(String ident) {
|
||||||
|
JsName name = super.findOwnName(ident);
|
||||||
|
if (name == null) {
|
||||||
|
if (JsReservedIdentifiers.reservedGlobalSymbols.contains(ident)) {
|
||||||
|
/*
|
||||||
|
* Lazily add JsNames for reserved identifiers. Since a JsName for a reserved global symbol
|
||||||
|
* must report a legitimate enclosing scope, we can't simply have a shared set of symbol
|
||||||
|
* names.
|
||||||
|
*/
|
||||||
|
name = doCreateName(ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.util.Maps;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scope is a factory for creating and allocating
|
||||||
|
* {@link JsName}s. A JavaScript AST is
|
||||||
|
* built in terms of abstract name objects without worrying about obfuscation,
|
||||||
|
* keyword/identifier blacklisting, and so on.
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* Scopes are associated with
|
||||||
|
* {@link JsFunction}s, but the two are
|
||||||
|
* not equivalent. Functions <i>have</i> scopes, but a scope does not
|
||||||
|
* necessarily have an associated Function. Examples of this include the
|
||||||
|
* {@link JsRootScope} and synthetic
|
||||||
|
* scopes that might be created by a client.
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* Scopes can have parents to provide constraints when allocating actual
|
||||||
|
* identifiers for names. Specifically, names in child scopes are chosen such
|
||||||
|
* that they do not conflict with names in their parent scopes. The ultimate
|
||||||
|
* parent is usually the global scope (see
|
||||||
|
* {@link JsProgram#getRootScope()}),
|
||||||
|
* but parentless scopes are useful for managing names that are always accessed
|
||||||
|
* with a qualifier and could therefore never be confused with the global scope
|
||||||
|
* hierarchy.
|
||||||
|
*/
|
||||||
|
public class JsScope {
|
||||||
|
@Nullable
|
||||||
|
private final String description;
|
||||||
|
private Map<String, JsName> names = Collections.emptyMap();
|
||||||
|
private final JsScope parent;
|
||||||
|
protected int tempIndex = 0;
|
||||||
|
private final String scopeId;
|
||||||
|
|
||||||
|
public JsScope(JsScope parent, @Nullable String description) {
|
||||||
|
this(parent, description, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsScope(JsScope parent) {
|
||||||
|
this(parent, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsScope(JsScope parent, @Nullable String description, @Nullable String scopeId) {
|
||||||
|
assert (parent != null);
|
||||||
|
this.scopeId = scopeId;
|
||||||
|
this.description = description;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JsScope innerScope(@Nullable String scopeName) {
|
||||||
|
return new JsScope(this, scopeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsScope(@Nullable String description) {
|
||||||
|
this.description = description;
|
||||||
|
this.parent = null;
|
||||||
|
this.scopeId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a name object associated with the specified identifier in this scope,
|
||||||
|
* creating it if necessary.<br/>
|
||||||
|
* If the JsName does not exist yet, a new JsName is created. The identifier,
|
||||||
|
* short name, and original name of the newly created JsName are equal to
|
||||||
|
* the given identifier.
|
||||||
|
*
|
||||||
|
* @param identifier An identifier that is unique within this scope.
|
||||||
|
*/
|
||||||
|
public JsName declareName(String identifier) {
|
||||||
|
JsName name = findOwnName(identifier);
|
||||||
|
return name != null ? name : doCreateName(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new variable with an unique ident in this scope.
|
||||||
|
* The generated JsName is guaranteed to have an identifier that does not clash with any existing variables in the scope.
|
||||||
|
* Future declarations of variables might however clash with the temporary
|
||||||
|
* (unless they use this function).
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public JsName declareFreshName(String suggestedName) {
|
||||||
|
String name = suggestedName;
|
||||||
|
int counter = 0;
|
||||||
|
while (hasOwnName(name)) {
|
||||||
|
name = suggestedName + '_' + counter++;
|
||||||
|
}
|
||||||
|
return doCreateName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNextTempName() {
|
||||||
|
// introduced by the compiler
|
||||||
|
return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a temporary variable with an unique name in this scope.
|
||||||
|
* The generated temporary is guaranteed to have an identifier (but not short
|
||||||
|
* name) that does not clash with any existing variables in the scope.
|
||||||
|
* Future declarations of variables might however clash with the temporary.
|
||||||
|
*/
|
||||||
|
public JsName declareTemporary() {
|
||||||
|
return declareFreshName(getNextTempName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to find the name object for the specified ident, searching in this
|
||||||
|
* scope, and if not found, in the parent scopes.
|
||||||
|
*
|
||||||
|
* @return <code>null</code> if the identifier has no associated name
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public final JsName findName(String ident) {
|
||||||
|
JsName name = findOwnName(ident);
|
||||||
|
if (name == null && parent != null) {
|
||||||
|
return parent.findName(ident);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasOwnName(@NotNull String name) {
|
||||||
|
return names.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parent scope of this scope, or <code>null</code> if this is the
|
||||||
|
* root scope.
|
||||||
|
*/
|
||||||
|
public final JsScope getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsProgram getProgram() {
|
||||||
|
assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent";
|
||||||
|
return parent.getProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String toString() {
|
||||||
|
if (parent != null) {
|
||||||
|
return description + "->" + parent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsName doCreateName(String ident) {
|
||||||
|
JsName name = new JsName(this, ident);
|
||||||
|
names = Maps.put(names, ident, name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to find the name object for the specified ident, searching in this
|
||||||
|
* scope only.
|
||||||
|
*
|
||||||
|
* @return <code>null</code> if the identifier has no associated name
|
||||||
|
*/
|
||||||
|
protected JsName findOwnName(String ident) {
|
||||||
|
return names.get(ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public interface JsStatement extends JsNode {
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript string literal expression.
|
||||||
|
*/
|
||||||
|
public final class JsStringLiteral extends JsValueLiteral {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
// These only get created by JsProgram so that they can be interned.
|
||||||
|
JsStringLiteral(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanFalse() {
|
||||||
|
return value.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBooleanTrue() {
|
||||||
|
return value.length() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNotNull() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefinitelyNull() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
v.visit(this, ctx);
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript switch statement.
|
||||||
|
*/
|
||||||
|
public class JsSwitch extends JsNodeImpl implements JsStatement {
|
||||||
|
|
||||||
|
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
|
||||||
|
private JsExpression expr;
|
||||||
|
|
||||||
|
public JsSwitch() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsSwitchMember> getCases() {
|
||||||
|
return cases;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getExpr() {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpr(JsExpression expr) {
|
||||||
|
this.expr = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
expr = v.accept(expr);
|
||||||
|
v.acceptWithInsertRemove(cases);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.SWITCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A member/case in a JavaScript switch object.
|
||||||
|
*/
|
||||||
|
public abstract class JsSwitchMember extends JsNodeImpl {
|
||||||
|
protected final List<JsStatement> statements = new SmartList<JsStatement>();
|
||||||
|
|
||||||
|
protected JsSwitchMember() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsStatement> getStatements() {
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
public class JsThrow extends JsNodeImpl implements JsStatement {
|
||||||
|
private JsExpression expression;
|
||||||
|
|
||||||
|
public JsThrow() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsThrow(JsExpression expression) {
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getExpression() {
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpression(JsExpression expression) {
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
expression = v.accept(expression);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.THROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript <code>try</code> statement.
|
||||||
|
*/
|
||||||
|
public class JsTry extends JsNodeImpl implements JsStatement {
|
||||||
|
private final List<JsCatch> catches;
|
||||||
|
private JsBlock finallyBlock;
|
||||||
|
private JsBlock tryBlock;
|
||||||
|
|
||||||
|
public JsTry() {
|
||||||
|
catches = new SmartList<JsCatch>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsTry(JsBlock tryBlock, List<JsCatch> catches, @Nullable JsBlock finallyBlock) {
|
||||||
|
this.tryBlock = tryBlock;
|
||||||
|
this.catches = catches;
|
||||||
|
this.finallyBlock = finallyBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JsCatch> getCatches() {
|
||||||
|
return catches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getFinallyBlock() {
|
||||||
|
return finallyBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsBlock getTryBlock() {
|
||||||
|
return tryBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFinallyBlock(JsBlock block) {
|
||||||
|
this.finallyBlock = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTryBlock(JsBlock block) {
|
||||||
|
tryBlock = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
tryBlock = v.accept(tryBlock);
|
||||||
|
v.acceptWithInsertRemove(catches);
|
||||||
|
if (finallyBlock != null) {
|
||||||
|
finallyBlock = v.accept(finallyBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.TRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript prefix or postfix operation.
|
||||||
|
*/
|
||||||
|
public abstract class JsUnaryOperation extends JsExpressionImpl {
|
||||||
|
|
||||||
|
private JsExpression arg;
|
||||||
|
|
||||||
|
private final JsUnaryOperator op;
|
||||||
|
|
||||||
|
public JsUnaryOperation(JsUnaryOperator op) {
|
||||||
|
this(op, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
|
||||||
|
super();
|
||||||
|
this.op = op;
|
||||||
|
this.arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getArg() {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsUnaryOperator getOperator() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean hasSideEffects() {
|
||||||
|
return op.isModifying() || arg.hasSideEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArg(JsExpression arg) {
|
||||||
|
this.arg = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (op.isModifying()) {
|
||||||
|
// The delete operator is practically like an assignment of undefined, so
|
||||||
|
// for practical purposes we're treating it as an lvalue.
|
||||||
|
arg = v.acceptLvalue(arg);
|
||||||
|
} else {
|
||||||
|
arg = v.accept(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript unary operator.
|
||||||
|
*/
|
||||||
|
public enum JsUnaryOperator implements JsOperator {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
|
||||||
|
* (page 57)
|
||||||
|
*/
|
||||||
|
BIT_NOT("~", 14, PREFIX), DEC("--", 14, POSTFIX | PREFIX), DELETE("delete", 14, PREFIX), INC(
|
||||||
|
"++", 14, POSTFIX | PREFIX), NEG("-", 14, PREFIX), POS("+", 14, PREFIX),
|
||||||
|
NOT("!", 14, PREFIX), TYPEOF("typeof", 14, PREFIX), VOID("void", 14, PREFIX);
|
||||||
|
|
||||||
|
private final int mask;
|
||||||
|
private final int precedence;
|
||||||
|
private final String symbol;
|
||||||
|
|
||||||
|
private JsUnaryOperator(String symbol, int precedence, int mask) {
|
||||||
|
this.symbol = symbol;
|
||||||
|
this.precedence = precedence;
|
||||||
|
this.mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPrecedence() {
|
||||||
|
return precedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeyword() {
|
||||||
|
return this == DELETE || this == TYPEOF || this == VOID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeftAssociative() {
|
||||||
|
return (mask & LEFT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModifying() {
|
||||||
|
return this == DEC || this == INC || this == DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrecedenceLessThan(JsOperator other) {
|
||||||
|
return precedence < other.getPrecedence();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidInfix() {
|
||||||
|
return (mask & INFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidPostfix() {
|
||||||
|
return (mask & POSTFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidPrefix() {
|
||||||
|
return (mask & PREFIX) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript string literal expression.
|
||||||
|
*/
|
||||||
|
public abstract class JsValueLiteral extends JsLiteral {
|
||||||
|
protected JsValueLiteral() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean hasSideEffects() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean isLeaf() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.common.SourceInfo;
|
||||||
|
import com.google.dart.compiler.common.Symbol;
|
||||||
|
import com.intellij.util.SmartList;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript <code>var</code> statement.
|
||||||
|
*/
|
||||||
|
public class JsVars extends JsNodeImpl implements JsStatement, Iterable<JsVars.JsVar> {
|
||||||
|
private final List<JsVar> vars;
|
||||||
|
|
||||||
|
private final boolean multiline;
|
||||||
|
|
||||||
|
public JsVars() {
|
||||||
|
this(new SmartList<JsVar>(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVars(boolean multiline) {
|
||||||
|
this(new SmartList<JsVar>(), multiline);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVars(List<JsVar> vars, boolean multiline) {
|
||||||
|
this.vars = vars;
|
||||||
|
this.multiline = multiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVars(JsVar var) {
|
||||||
|
this(Collections.singletonList(var), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVars(JsVar... vars) {
|
||||||
|
this(Arrays.asList(vars), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMultiline() {
|
||||||
|
return multiline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A var declared using the JavaScript <code>var</code> statement.
|
||||||
|
*/
|
||||||
|
public static class JsVar extends JsNodeImpl implements HasName {
|
||||||
|
private final JsName name;
|
||||||
|
private JsExpression initExpression;
|
||||||
|
|
||||||
|
public JsVar(JsName name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsVar(JsName name, @Nullable JsExpression initExpression) {
|
||||||
|
this.name = name;
|
||||||
|
this.initExpression = initExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getInitExpression() {
|
||||||
|
return initExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitExpression(JsExpression initExpression) {
|
||||||
|
this.initExpression = initExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
if (initExpression != null) {
|
||||||
|
initExpression = v.accept(initExpression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsVar setSourceRef(SourceInfo info) {
|
||||||
|
super.setSourceRef(info);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.VAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(JsVar var) {
|
||||||
|
vars.add(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addIfHasInitializer(JsVar var) {
|
||||||
|
if (var.getInitExpression() != null) {
|
||||||
|
add(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return vars.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<JsVar> iterator() {
|
||||||
|
return vars.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
v.acceptWithInsertRemove(vars);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.VARS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstracts the idea that a class can be traversed.
|
||||||
|
*/
|
||||||
|
public interface JsVisitable {
|
||||||
|
/**
|
||||||
|
* Causes this object to have the visitor visit itself and its children.
|
||||||
|
*
|
||||||
|
* @param visitor the visitor that should traverse this node
|
||||||
|
* @param ctx the context of an existing traversal
|
||||||
|
*/
|
||||||
|
void traverse(JsVisitor visitor, JsContext ctx);
|
||||||
|
}
|
||||||
@@ -0,0 +1,435 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by nodes that will visit child nodes.
|
||||||
|
*/
|
||||||
|
public class JsVisitor {
|
||||||
|
|
||||||
|
protected static final JsContext LVALUE_CONTEXT = new JsContext() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInsert() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRemove() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertAfter(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertBefore(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLvalue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeMe() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replaceMe(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInsert() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRemove() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertAfter(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertBefore(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLvalue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeMe() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void replaceMe(JsVisitable node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public final <T extends JsVisitable> T accept(T node) {
|
||||||
|
return this.doAccept(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <T extends JsVisitable> void acceptList(List<T> collection) {
|
||||||
|
doAcceptList(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression acceptLvalue(JsExpression expr) {
|
||||||
|
return doAcceptLvalue(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <T extends JsVisitable> void acceptWithInsertRemove(List<T> collection) {
|
||||||
|
doAcceptWithInsertRemove(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean didChange() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsArrayAccess x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsArrayLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsBinaryOperation x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsBlock x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsBreak x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsCase x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsCatch x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsConditional x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsContinue x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsDebugger x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsDefault x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsDoWhile x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsEmpty x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsExprStmt x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsFor x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsForIn x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsFunction x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsIf x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsInvocation x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsLabel x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsNameRef x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsNew x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsNullLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsNumberLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsObjectLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsParameter x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsPostfixOperation x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsPrefixOperation x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsProgram x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsProgramFragment x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsPropertyInitializer x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsRegExp x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsReturn x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsStringLiteral x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsSwitch x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsLiteral.JsThisRef x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsThrow x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsTry x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsVar x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsVars x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endVisit(JsWhile x, JsContext ctx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsArrayAccess x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsArrayLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsBinaryOperation x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsBlock x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsBreak x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsCase x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsCatch x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsConditional x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsContinue x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsDebugger x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsDefault x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsDoWhile x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsEmpty x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsExprStmt x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsFor x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsForIn x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsFunction x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsIf x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsInvocation x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsLabel x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsNameRef x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsNew x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsNullLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsObjectLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsParameter x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsPostfixOperation x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsPrefixOperation x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsProgram x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsProgramFragment x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsRegExp x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsReturn x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsStringLiteral x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsSwitch x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsThrow x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsTry x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsVar x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsVars x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean visit(JsWhile x, JsContext ctx) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends JsVisitable> T doAccept(T node) {
|
||||||
|
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends JsVisitable> void doAcceptList(List<T> collection) {
|
||||||
|
for (T node : collection) {
|
||||||
|
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsExpression doAcceptLvalue(JsExpression expr) {
|
||||||
|
doTraverse(expr, LVALUE_CONTEXT);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
|
||||||
|
for (T node : collection) {
|
||||||
|
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doTraverse(JsVisitable node, JsContext ctx) {
|
||||||
|
node.traverse(this, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A JavaScript <code>while</code> statement.
|
||||||
|
*/
|
||||||
|
public class JsWhile extends JsNodeImpl implements JsStatement {
|
||||||
|
protected JsStatement body;
|
||||||
|
protected JsExpression condition;
|
||||||
|
|
||||||
|
public JsWhile() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsWhile(JsExpression condition, JsStatement body) {
|
||||||
|
this.condition = condition;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsStatement getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsExpression getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(JsStatement body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCondition(JsExpression condition) {
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void traverse(JsVisitor v, JsContext ctx) {
|
||||||
|
if (v.visit(this, ctx)) {
|
||||||
|
condition = v.accept(condition);
|
||||||
|
body = v.accept(body);
|
||||||
|
}
|
||||||
|
v.endVisit(this, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeKind getKind() {
|
||||||
|
return NodeKind.WHILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.backend.js.ast;
|
||||||
|
|
||||||
|
enum NodeKind {
|
||||||
|
ARRAY_ACCESS,
|
||||||
|
ARRAY,
|
||||||
|
BINARY_OP,
|
||||||
|
BLOCK,
|
||||||
|
BOOLEAN,
|
||||||
|
BREAK,
|
||||||
|
CASE,
|
||||||
|
CATCH,
|
||||||
|
CONDITIONAL,
|
||||||
|
CONTINUE,
|
||||||
|
DEBUGGER,
|
||||||
|
DEFAULT,
|
||||||
|
DO,
|
||||||
|
EMPTY,
|
||||||
|
EXPRESSION_STMT,
|
||||||
|
FOR,
|
||||||
|
FOR_IN,
|
||||||
|
FUNCTION,
|
||||||
|
IF,
|
||||||
|
INVOKE,
|
||||||
|
LABEL,
|
||||||
|
NAME_REF,
|
||||||
|
NEW,
|
||||||
|
NULL,
|
||||||
|
NUMBER,
|
||||||
|
OBJECT,
|
||||||
|
PARAMETER,
|
||||||
|
POSTFIX_OP,
|
||||||
|
PREFIX_OP,
|
||||||
|
PROGRAM,
|
||||||
|
PROGRAM_FRAGMENT,
|
||||||
|
PROPERTY_INIT,
|
||||||
|
REGEXP,
|
||||||
|
RETURN,
|
||||||
|
STRING,
|
||||||
|
SWITCH,
|
||||||
|
THIS,
|
||||||
|
THROW,
|
||||||
|
TRY,
|
||||||
|
VARS,
|
||||||
|
VAR,
|
||||||
|
WHILE
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.Source;
|
||||||
|
|
||||||
|
public class AbstractNode implements SourceInfo, HasSourceInfo {
|
||||||
|
protected SourceInfo sourceInfo;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Source getSource() {
|
||||||
|
return sourceInfo.getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLine() {
|
||||||
|
return sourceInfo.getLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumn() {
|
||||||
|
return sourceInfo.getColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStart() {
|
||||||
|
return sourceInfo.getStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLength() {
|
||||||
|
return sourceInfo.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceInfo getSourceInfo() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSourceInfo(SourceInfo info) {
|
||||||
|
sourceInfo = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setSourceLocation(Source source, int line, int column, int startPosition, int length) {
|
||||||
|
sourceInfo = new SourceInfoImpl(source, line, column, startPosition, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setSourceRange(int startPosition, int length) {
|
||||||
|
//Preconditions.checkArgument(startPosition != -1 && length >= 0 || startPosition == -1 && length == 0);
|
||||||
|
//sourceInfo.sourceStart = startPosition;
|
||||||
|
//sourceInfo.sourceLength = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.Source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract view of a class that has source info.
|
||||||
|
*/
|
||||||
|
public interface HasSourceInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the source info associated with this object.
|
||||||
|
*/
|
||||||
|
SourceInfo getSourceInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the source info associated with this object. May only be called once.
|
||||||
|
* @param info
|
||||||
|
*/
|
||||||
|
void setSourceInfo(SourceInfo info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the source range of the original source file where the source fragment
|
||||||
|
* corresponding to this node was found.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Each node in the subtree (other than the contrived nodes) carries source
|
||||||
|
* range(s) information relating back to positions in the given source (the
|
||||||
|
* given source itself is not remembered with the AST). The source range
|
||||||
|
* usually begins at the first character of the first token corresponding to
|
||||||
|
* the node; leading whitespace and comments are <b>not</b> included. The
|
||||||
|
* source range usually extends through the last character of the last token
|
||||||
|
* corresponding to the node; trailing whitespace and comments are <b>not</b>
|
||||||
|
* included. There are a handful of exceptions (including the various body
|
||||||
|
* declarations). Source ranges nest properly: the source range for a child is
|
||||||
|
* always within the source range of its parent, and the source ranges of
|
||||||
|
* sibling nodes never overlap.
|
||||||
|
*
|
||||||
|
* @param source the associated source
|
||||||
|
* @param line the 1-based line index, or <code>-1</code>, if no source
|
||||||
|
* location is available
|
||||||
|
* @param column the 1-based column index, or <code>-1</code>, if no source
|
||||||
|
* location is available
|
||||||
|
* @param startPosition a 0-based character index, or <code>-1</code>, if no
|
||||||
|
* source location is available
|
||||||
|
* @param length a (possibly 0) length, or <code>-1</code>, if no source
|
||||||
|
* location is available
|
||||||
|
* @see SourceInfo#getStart()
|
||||||
|
* @see SourceInfo#getLength()
|
||||||
|
*/
|
||||||
|
void setSourceLocation(Source source, int line, int column, int startPosition, int length);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author johnlenz@google.com (John Lenz)
|
||||||
|
*/
|
||||||
|
public interface HasSymbol {
|
||||||
|
/**
|
||||||
|
* @return Return the original user visible name for a Object represented
|
||||||
|
* in a source map.
|
||||||
|
*/
|
||||||
|
Symbol getSymbol();
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.Source;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks file and line information for AST nodes.
|
||||||
|
*/
|
||||||
|
public interface SourceInfo extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The source code provider.
|
||||||
|
*/
|
||||||
|
Source getSource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A 1-based line number into the original source file indicating
|
||||||
|
* where the source fragment begins.
|
||||||
|
*/
|
||||||
|
int getLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A 1-based column number into the original source file indicating
|
||||||
|
* where the source fragment begins.
|
||||||
|
*/
|
||||||
|
int getColumn();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the character index into the original source file indicating
|
||||||
|
* where the source fragment corresponding to this node begins.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
||||||
|
*
|
||||||
|
* @return the 0-based character index, or <code>-1</code>
|
||||||
|
* if no source startPosition information is recorded for this node
|
||||||
|
* @see #getLength()
|
||||||
|
* @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
|
||||||
|
*/
|
||||||
|
int getStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length in characters of the original source file indicating
|
||||||
|
* where the source fragment corresponding to this node ends.
|
||||||
|
* <p>
|
||||||
|
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
||||||
|
*
|
||||||
|
* @return a (possibly 0) length, or <code>0</code>
|
||||||
|
* if no source source position information is recorded for this node
|
||||||
|
* @see #getStart()
|
||||||
|
* @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
|
||||||
|
*/
|
||||||
|
int getLength();
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.Source;
|
||||||
|
|
||||||
|
public class SourceInfoImpl implements SourceInfo {
|
||||||
|
protected Source source = null;
|
||||||
|
protected int line = -1;
|
||||||
|
protected int column = -1;
|
||||||
|
protected int start = -1;
|
||||||
|
protected int length = -1;
|
||||||
|
|
||||||
|
public SourceInfoImpl(Source source, int line, int column, int start, int length) {
|
||||||
|
this.source = source;
|
||||||
|
this.line = line;
|
||||||
|
this.column = column;
|
||||||
|
this.start = start;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Source getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumn() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author johnlenz@google.com (John Lenz)
|
||||||
|
*/
|
||||||
|
public interface Symbol {
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.util;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author johnlenz@google.com (John Lenz)
|
||||||
|
*/
|
||||||
|
public final class AstUtil {
|
||||||
|
private AstUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsNameRef newQualifiedNameRef(String name) {
|
||||||
|
JsNameRef node = null;
|
||||||
|
int endPos;
|
||||||
|
int startPos = 0;
|
||||||
|
do {
|
||||||
|
endPos = name.indexOf('.', startPos);
|
||||||
|
String part = (endPos == -1
|
||||||
|
? name.substring(startPos)
|
||||||
|
: name.substring(startPos, endPos));
|
||||||
|
node = new JsNameRef(part, node);
|
||||||
|
startPos = endPos + 1;
|
||||||
|
}
|
||||||
|
while (endPos != -1);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a sequence of expressions (using the binary sequence operator).
|
||||||
|
*
|
||||||
|
* @param exprs - expressions to add to sequence
|
||||||
|
* @return a sequence of expressions.
|
||||||
|
*/
|
||||||
|
public static JsBinaryOperation newSequence(JsExpression... exprs) {
|
||||||
|
if (exprs.length < 2) {
|
||||||
|
throw new RuntimeException("newSequence expects at least two arguments");
|
||||||
|
}
|
||||||
|
JsExpression result = exprs[exprs.length - 1];
|
||||||
|
for (int i = exprs.length - 2; i >= 0; i--) {
|
||||||
|
result = new JsBinaryOperation(JsBinaryOperator.COMMA, exprs[i], result);
|
||||||
|
}
|
||||||
|
return (JsBinaryOperation) result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for operating on memory-efficient lists. All lists of size 0
|
||||||
|
* or 1 are assumed to be immutable. All lists of size greater than 1 are
|
||||||
|
* assumed to be mutable.
|
||||||
|
*/
|
||||||
|
public class Lists {
|
||||||
|
private Lists() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> add(List<T> list, int index, T toAdd) {
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
// Empty -> Singleton
|
||||||
|
if (index != 0) {
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
}
|
||||||
|
return Collections.singletonList(toAdd);
|
||||||
|
case 1: {
|
||||||
|
// Singleton -> ArrayList
|
||||||
|
List<T> result = new ArrayList<T>(2);
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
result.add(toAdd);
|
||||||
|
result.add(list.get(0));
|
||||||
|
return result;
|
||||||
|
case 1:
|
||||||
|
result.add(list.get(0));
|
||||||
|
result.add(toAdd);
|
||||||
|
return result;
|
||||||
|
default:
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ArrayList
|
||||||
|
list.add(index, toAdd);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> add(List<T> list, T toAdd) {
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
// Empty -> Singleton
|
||||||
|
return Collections.singletonList(toAdd);
|
||||||
|
case 1: {
|
||||||
|
// Singleton -> ArrayList
|
||||||
|
List<T> result = new ArrayList<T>(2);
|
||||||
|
result.add(list.get(0));
|
||||||
|
result.add(toAdd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ArrayList
|
||||||
|
list.add(toAdd);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> addAll(List<T> list, int index, List<T> toAdd) {
|
||||||
|
switch (toAdd.size()) {
|
||||||
|
case 0:
|
||||||
|
// No-op.
|
||||||
|
return list;
|
||||||
|
case 1:
|
||||||
|
// Add one element.
|
||||||
|
return add(list, index, toAdd.get(0));
|
||||||
|
default:
|
||||||
|
// True list merge, result >= 2.
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
if (index != 0) {
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
}
|
||||||
|
return new ArrayList<T>(toAdd);
|
||||||
|
case 1: {
|
||||||
|
List<T> result = new ArrayList<T>(1 + toAdd.size());
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
result.addAll(toAdd);
|
||||||
|
result.add(list.get(0));
|
||||||
|
return result;
|
||||||
|
case 1:
|
||||||
|
result.add(list.get(0));
|
||||||
|
result.addAll(toAdd);
|
||||||
|
return result;
|
||||||
|
default:
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
list.addAll(index, toAdd);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> addAll(List<T> list, List<T> toAdd) {
|
||||||
|
switch (toAdd.size()) {
|
||||||
|
case 0:
|
||||||
|
// No-op.
|
||||||
|
return list;
|
||||||
|
case 1:
|
||||||
|
// Add one element.
|
||||||
|
return add(list, toAdd.get(0));
|
||||||
|
default:
|
||||||
|
// True list merge, result >= 2.
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
return new ArrayList<T>(toAdd);
|
||||||
|
case 1: {
|
||||||
|
List<T> result = new ArrayList<T>(1 + toAdd.size());
|
||||||
|
result.add(list.get(0));
|
||||||
|
result.addAll(toAdd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
list.addAll(toAdd);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> addAll(List<T> list, T... toAdd) {
|
||||||
|
switch (toAdd.length) {
|
||||||
|
case 0:
|
||||||
|
// No-op.
|
||||||
|
return list;
|
||||||
|
case 1:
|
||||||
|
// Add one element.
|
||||||
|
return add(list, toAdd[0]);
|
||||||
|
default:
|
||||||
|
// True list merge, result >= 2.
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
return new ArrayList<T>(Arrays.asList(toAdd));
|
||||||
|
case 1: {
|
||||||
|
List<T> result = new ArrayList<T>(1 + toAdd.length);
|
||||||
|
result.add(list.get(0));
|
||||||
|
result.addAll(Arrays.asList(toAdd));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
list.addAll(Arrays.asList(toAdd));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> create() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> create(Collection<T> collection) {
|
||||||
|
switch (collection.size()) {
|
||||||
|
case 0:
|
||||||
|
return create();
|
||||||
|
default:
|
||||||
|
return new ArrayList<T>(collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> create(List<T> list) {
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
return create();
|
||||||
|
case 1:
|
||||||
|
return create(list.get(0));
|
||||||
|
default:
|
||||||
|
return new ArrayList<T>(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> create(T item) {
|
||||||
|
return Collections.singletonList(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> create(T... items) {
|
||||||
|
switch (items.length) {
|
||||||
|
case 0:
|
||||||
|
return create();
|
||||||
|
case 1:
|
||||||
|
return create(items[0]);
|
||||||
|
default:
|
||||||
|
return new ArrayList<T>(Arrays.asList(items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> remove(List<T> list, int toRemove) {
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
// Empty
|
||||||
|
throw newIndexOutOfBounds(list, toRemove);
|
||||||
|
case 1:
|
||||||
|
// Singleton -> Empty
|
||||||
|
if (toRemove == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
} else {
|
||||||
|
throw newIndexOutOfBounds(list, toRemove);
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
// ArrayList -> Singleton
|
||||||
|
switch (toRemove) {
|
||||||
|
case 0:
|
||||||
|
return Collections.singletonList(list.get(1));
|
||||||
|
case 1:
|
||||||
|
return Collections.singletonList(list.get(0));
|
||||||
|
default:
|
||||||
|
throw newIndexOutOfBounds(list, toRemove);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ArrayList
|
||||||
|
list.remove(toRemove);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> set(List<T> list, int index, T e) {
|
||||||
|
switch (list.size()) {
|
||||||
|
case 0:
|
||||||
|
// Empty
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
case 1:
|
||||||
|
// Singleton
|
||||||
|
if (index == 0) {
|
||||||
|
return Collections.singletonList(e);
|
||||||
|
} else {
|
||||||
|
throw newIndexOutOfBounds(list, index);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// ArrayList
|
||||||
|
list.set(index, e);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Comparable<? super T>> List<T> sort(List<T> list) {
|
||||||
|
if (list.size() > 1) {
|
||||||
|
Collections.sort(list);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> sort(List<T> list, Comparator<? super T> sort) {
|
||||||
|
if (list.size() > 1) {
|
||||||
|
Collections.sort(list, sort);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> IndexOutOfBoundsException newIndexOutOfBounds(List<T> list, int index) {
|
||||||
|
return new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.util;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for operating on memory-efficient maps. All maps of size 0 or
|
||||||
|
* 1 are assumed to be immutable. All maps of size greater than 1 are assumed to
|
||||||
|
* be mutable.
|
||||||
|
*/
|
||||||
|
public class Maps {
|
||||||
|
private Maps() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> Map<K, V> put(Map<K, V> map, K key, V value) {
|
||||||
|
switch (map.size()) {
|
||||||
|
case 0:
|
||||||
|
// Empty -> Singleton
|
||||||
|
return Collections.singletonMap(key, value);
|
||||||
|
case 1: {
|
||||||
|
if (map.containsKey(key)) {
|
||||||
|
return Collections.singletonMap(key, value);
|
||||||
|
}
|
||||||
|
// Singleton -> HashMap
|
||||||
|
Map<K, V> result = new HashMap<K, V>();
|
||||||
|
result.put(map.keySet().iterator().next(), map.values().iterator().next());
|
||||||
|
result.put(key, value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// HashMap
|
||||||
|
map.put(key, value);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used for printing text output.
|
||||||
|
*/
|
||||||
|
public interface TextOutput {
|
||||||
|
int getPosition();
|
||||||
|
|
||||||
|
int getLine();
|
||||||
|
|
||||||
|
int getColumn();
|
||||||
|
|
||||||
|
void indentIn();
|
||||||
|
|
||||||
|
void indentOut();
|
||||||
|
|
||||||
|
void newline();
|
||||||
|
|
||||||
|
void newlineOpt();
|
||||||
|
|
||||||
|
void print(char c);
|
||||||
|
void print(int v);
|
||||||
|
void print(double v);
|
||||||
|
|
||||||
|
void print(char[] s);
|
||||||
|
|
||||||
|
void print(CharSequence s);
|
||||||
|
|
||||||
|
void printOpt(char c);
|
||||||
|
|
||||||
|
void printOpt(char[] s);
|
||||||
|
|
||||||
|
void printOpt(String s);
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.google.dart.compiler.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract base type to build TextOutput implementations.
|
||||||
|
*/
|
||||||
|
public class TextOutputImpl implements TextOutput {
|
||||||
|
private final boolean compact;
|
||||||
|
private int identLevel = 0;
|
||||||
|
private final static int indentGranularity = 2;
|
||||||
|
private char[][] indents = new char[][] {new char[0]};
|
||||||
|
private boolean justNewlined;
|
||||||
|
private final StringBuilder out;
|
||||||
|
private int position = 0;
|
||||||
|
private int line = 0;
|
||||||
|
private int column = 0;
|
||||||
|
|
||||||
|
public TextOutputImpl() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextOutputImpl(boolean compact) {
|
||||||
|
this.compact = compact;
|
||||||
|
this.out = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumn() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void indentIn() {
|
||||||
|
++identLevel;
|
||||||
|
if (identLevel >= indents.length) {
|
||||||
|
// Cache a new level of indentation string.
|
||||||
|
char[] newIndentLevel = new char[identLevel * indentGranularity];
|
||||||
|
Arrays.fill(newIndentLevel, ' ');
|
||||||
|
char[][] newIndents = new char[indents.length + 1][];
|
||||||
|
System.arraycopy(indents, 0, newIndents, 0, indents.length);
|
||||||
|
newIndents[identLevel] = newIndentLevel;
|
||||||
|
indents = newIndents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void indentOut() {
|
||||||
|
--identLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newline() {
|
||||||
|
out.append('\n');
|
||||||
|
position++;
|
||||||
|
line++;
|
||||||
|
column = 0;
|
||||||
|
justNewlined = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newlineOpt() {
|
||||||
|
if (!compact) {
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(double value) {
|
||||||
|
maybeIndent();
|
||||||
|
int oldLength = out.length();
|
||||||
|
out.append(value);
|
||||||
|
movePosition(out.length() - oldLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(int value) {
|
||||||
|
maybeIndent();
|
||||||
|
int oldLength = out.length();
|
||||||
|
out.append(value);
|
||||||
|
movePosition(out.length() - oldLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(char c) {
|
||||||
|
maybeIndent();
|
||||||
|
out.append(c);
|
||||||
|
movePosition(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void movePosition(int l) {
|
||||||
|
position += l;
|
||||||
|
column += l;
|
||||||
|
justNewlined = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(char[] s) {
|
||||||
|
maybeIndent();
|
||||||
|
printAndCount(s);
|
||||||
|
justNewlined = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void print(CharSequence s) {
|
||||||
|
maybeIndent();
|
||||||
|
printAndCount(s);
|
||||||
|
justNewlined = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printOpt(char c) {
|
||||||
|
if (!compact) {
|
||||||
|
maybeIndent();
|
||||||
|
out.append(c);
|
||||||
|
position++;
|
||||||
|
column++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printOpt(char[] s) {
|
||||||
|
if (!compact) {
|
||||||
|
maybeIndent();
|
||||||
|
printAndCount(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printOpt(String s) {
|
||||||
|
if (!compact) {
|
||||||
|
maybeIndent();
|
||||||
|
printAndCount(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeIndent() {
|
||||||
|
if (justNewlined && !compact) {
|
||||||
|
printAndCount(indents[identLevel]);
|
||||||
|
justNewlined = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printAndCount(CharSequence charSequence) {
|
||||||
|
position += charSequence.length();
|
||||||
|
column += charSequence.length();
|
||||||
|
out.append(charSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printAndCount(char[] chars) {
|
||||||
|
position += chars.length;
|
||||||
|
column += chars.length;
|
||||||
|
out.append(chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user