Merge branch 'master' of ../../KotlinJs
This commit is contained in:
Generated
+1
@@ -0,0 +1 @@
|
||||
k2js
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<defaultAnt bundledAnt="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
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="?*.properties" />
|
||||
<entry name="?*.xml" />
|
||||
<entry name="?*.gif" />
|
||||
<entry name="?*.png" />
|
||||
<entry name="?*.jpeg" />
|
||||
<entry name="?*.jpg" />
|
||||
<entry name="?*.html" />
|
||||
<entry name="?*.dtd" />
|
||||
<entry name="?*.tld" />
|
||||
<entry name="?*.ftl" />
|
||||
<entry name="?*.jet" />
|
||||
<entry name="?*.kt" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing enabled="false" useClasspath="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright 2000-&#36;today.year JetBrains s.r.o. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License." />
|
||||
<option name="keyword" value="Copyright" />
|
||||
<option name="allowReplaceKeyword" value="JetBrains" />
|
||||
<option name="myName" value="apache" />
|
||||
<option name="myLocal" value="true" />
|
||||
</copyright>
|
||||
</component>
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="apache">
|
||||
<module2copyright>
|
||||
<element module="All" copyright="apache" />
|
||||
</module2copyright>
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Pavel.Talanov" />
|
||||
</component>
|
||||
Generated
+5
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="SimplifiableIfStatement" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="TrivialIf" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="guava-10.0.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/translator/lib/guava-10.0.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+36
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="IdProvider" IDEtalkID="C5E9A8C8EEE7359144ADEDA64003CE1D" />
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
<option name="OPTION_INDEX" value="true" />
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true" />
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true" />
|
||||
<option name="OTHER_OPTIONS" value="" />
|
||||
<option name="HEAP_SIZE" />
|
||||
<option name="LOCALE" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
</component>
|
||||
<component name="ProjectResources">
|
||||
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
|
||||
</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>
|
||||
<component name="com.sixrr.metrics.MetricsReloaded">
|
||||
<option name="selectedProfile" value="Lines of code metrics" />
|
||||
<option name="autoscroll" value="false" />
|
||||
<option name="showOnlyWarnings" value="false" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
Generated
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/backend/backend.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/backend/backend.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/cli/cli.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/cli/cli.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/tests/compiler-tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/frontend/frontend.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/frontend/frontend.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/frontend.java/frontend.java.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/frontend.java/frontend.java.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js.ast/js.ast.iml" filepath="$PROJECT_DIR$/js.ast/js.ast.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js.backend/js.backend.iml" filepath="$PROJECT_DIR$/js.backend/js.backend.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js.examples/js.examples.iml" filepath="$PROJECT_DIR$/js.examples/js.examples.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js.tests/js.tests.iml" filepath="$PROJECT_DIR$/js.tests/js.tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js.lib/jslib.iml" filepath="$PROJECT_DIR$/js.lib/jslib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/stdlib/stdlib.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/stdlib/stdlib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../../Kotlin/jet/compiler/util/util.iml" filepath="$PROJECT_DIR$/../../Kotlin/jet/compiler/util/util.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>
|
||||
|
||||
Generated
+1097
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,150 @@
|
||||
Index: compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java (revision 24a2ec5)
|
||||
+++ compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java (revision 4229e867af6d744d3b384dfc515cbf89caf363ae)
|
||||
@@ -173,8 +173,8 @@
|
||||
List<AnnotationDescriptor> result = Lists.newArrayList();
|
||||
for (JetAnnotationEntry annotation : annotations) {
|
||||
AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor();
|
||||
- result.add(annotationDescriptor);
|
||||
- trace.record(BindingContext.ANNOTATION, annotation, annotationDescriptor);
|
||||
+ // result.add(annotationDescriptor);
|
||||
+ // trace.record(BindingContext.ANNOTATION, annotation, annotationDescriptor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Index: idea/src/META-INF/plugin.xml
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- idea/src/META-INF/plugin.xml (revision 24a2ec5)
|
||||
+++ idea/src/META-INF/plugin.xml (revision 4229e867af6d744d3b384dfc515cbf89caf363ae)
|
||||
@@ -1,9 +1,12 @@
|
||||
<idea-plugin version="2">
|
||||
<name>Kotlin</name>
|
||||
<description>Kotlin language support</description>
|
||||
- <version>@snapshot@</version>
|
||||
+ <version>1.0</version>
|
||||
<vendor>JetBrains</vendor>
|
||||
|
||||
+ <application-components>
|
||||
+ </application-components>
|
||||
+
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.jet.plugin.compiler.JetCompilerManager</implementation-class>
|
||||
@@ -28,16 +31,18 @@
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="control alt shift T"/>
|
||||
<add-to-group group-id="CodeMenu" anchor="last"/>
|
||||
</action>
|
||||
- <action id="ConvertJavaToKotlin" class="org.jetbrains.jet.plugin.actions.JavaToKotlinAction"
|
||||
- text="Convert Java File to Kotlin File">
|
||||
- <keyboard-shortcut keymap="$default" first-keystroke="control alt shift J"/>
|
||||
- <add-to-group group-id="CodeMenu" anchor="last"/>
|
||||
- </action>
|
||||
<action id="ToggleJetErrorReporting" class="org.jetbrains.jet.plugin.actions.ToggleErrorReportingAction"
|
||||
text="Toggle Error Reporting">
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="control alt shift E"/>
|
||||
<add-to-group group-id="CodeMenu" anchor="last"/>
|
||||
</action>
|
||||
+
|
||||
+ <action id="Kotlin.TranslateToJs" class="org.jetbrains.jet.plugin.actions.TranslateToJsAction"
|
||||
+ text="Translate current namespace and create js files.">
|
||||
+ <keyboard-shortcut keymap="$default" first-keystroke="control alt shift J"/>
|
||||
+ <add-to-group group-id="CodeMenu" anchor="last"/>
|
||||
+ </action>
|
||||
+
|
||||
</actions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
Index: idea/src/org/jetbrains/jet/plugin/actions/TranslateToJsAction.java
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- idea/src/org/jetbrains/jet/plugin/actions/TranslateToJsAction.java (revision 4229e867af6d744d3b384dfc515cbf89caf363ae)
|
||||
+++ idea/src/org/jetbrains/jet/plugin/actions/TranslateToJsAction.java (revision 4229e867af6d744d3b384dfc515cbf89caf363ae)
|
||||
@@ -0,0 +1,79 @@
|
||||
+package org.jetbrains.jet.plugin.actions;
|
||||
+
|
||||
+import com.intellij.notification.Notification;
|
||||
+import com.intellij.notification.NotificationType;
|
||||
+import com.intellij.notification.Notifications;
|
||||
+import com.intellij.openapi.actionSystem.AnAction;
|
||||
+import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
+import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
+import com.intellij.openapi.application.ApplicationManager;
|
||||
+import com.intellij.openapi.editor.Editor;
|
||||
+import com.intellij.openapi.project.Project;
|
||||
+import com.intellij.openapi.vfs.VirtualFile;
|
||||
+import com.intellij.psi.PsiFile;
|
||||
+import org.jetbrains.jet.lang.psi.JetFile;
|
||||
+import org.jetbrains.k2js.facade.K2JSTranslator;
|
||||
+
|
||||
+/**
|
||||
+ * @author Pavel Talanov
|
||||
+ */
|
||||
+public final class TranslateToJsAction extends AnAction {
|
||||
+
|
||||
+ private static void notifyFailure(Throwable exception) {
|
||||
+ Notifications.Bus.notify(new Notification("JsTranslator", "Translation failed.",
|
||||
+ "Exception: " + exception.getMessage(),
|
||||
+ NotificationType.ERROR));
|
||||
+ }
|
||||
+
|
||||
+ private static void notifySuccess(String outputPath) {
|
||||
+ Notifications.Bus.notify(new Notification("JsTranslator", "Translation successful.",
|
||||
+ "Generated file: " + outputPath,
|
||||
+ NotificationType.INFORMATION));
|
||||
+ }
|
||||
+
|
||||
+ public void actionPerformed(AnActionEvent event) {
|
||||
+
|
||||
+ final PsiFile psiFile = event.getData(LangDataKeys.PSI_FILE);
|
||||
+ if (!(psiFile instanceof JetFile)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Runnable task = new Runnable() {
|
||||
+ @Override
|
||||
+ public void run() {
|
||||
+ try {
|
||||
+ Project project = psiFile.getProject();
|
||||
+ String outputPath = getOutputPath(psiFile);
|
||||
+ K2JSTranslator.translateWithCallToMainAndSaveToFile((JetFile) psiFile,
|
||||
+ outputPath,
|
||||
+ project);
|
||||
+ notifySuccess(outputPath);
|
||||
+ } catch (Throwable e) {
|
||||
+ e.printStackTrace();
|
||||
+ notifyFailure(e);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+ ApplicationManager.getApplication().runWriteAction(task);
|
||||
+ }
|
||||
+
|
||||
+ private static String getOutputPath(PsiFile psiFile) {
|
||||
+ VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
+ assert virtualFile != null : "Internal error: Psi file should correspond to actual virtual file";
|
||||
+ String originalFilePath = virtualFile.getPath();
|
||||
+
|
||||
+ //TODO: make platform independent
|
||||
+ String pathToDir = originalFilePath.substring(0, originalFilePath.lastIndexOf("/") + 1);
|
||||
+ String generatedFileName = ((JetFile) psiFile).getNamespaceHeader().getName() + ".js";
|
||||
+ return pathToDir + generatedFileName;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ @Override
|
||||
+ public void update(AnActionEvent e) {
|
||||
+ Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
+ PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
|
||||
+ e.getPresentation().setEnabled(editor != null && psiFile instanceof JetFile);
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Below is a list of people and organizations that have contributed
|
||||
# to the Dart project. Names should be added to the list like so:
|
||||
#
|
||||
# Name/Organization <email address>
|
||||
|
||||
Google Inc.
|
||||
|
||||
Ola Martin Bini <ola.bini@gmail.com>
|
||||
@@ -0,0 +1,48 @@
|
||||
This license applies to all parts of Dart that are not externally
|
||||
maintained libraries. The external maintained libraries used by
|
||||
Dart are:
|
||||
|
||||
JSCRE - in runtime/third_party/jscre
|
||||
Ant - in third_party/apache_ant
|
||||
Google App Engine for Java SDK - in third_party/appengine-java-sdk
|
||||
args4j - in third_party/args4j
|
||||
Chrome SDK - in third_party/chromesdk
|
||||
Eclipse - in third_party/eclipse
|
||||
gsutil = in third_party/gsutil
|
||||
Guava - in third_party/guava
|
||||
hamcrest - in third_party/hamcrest
|
||||
Httplib2 - in third_party/httplib2
|
||||
Jetty - in third_party/jetty
|
||||
JSON - in third_party/json
|
||||
JUnit - in third_party/junit
|
||||
Ouath - in third_party/oauth2client
|
||||
Python-scss - in third_party/pyscss
|
||||
Rhino - in third_party/rhino
|
||||
|
||||
The libraries may have their own licenses; we recommend you read them,
|
||||
as their terms may differ from the terms below.
|
||||
|
||||
Copyright 2011, the Dart project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,23 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Dart Project.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this
|
||||
section) patent license to make, have made, use, offer to sell, sell,
|
||||
import, transfer, and otherwise run, modify and propagate the contents
|
||||
of this implementation of Dart, where such license applies only to
|
||||
those patent claims, both currently owned by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by
|
||||
this implementation of Dart. This grant does not include claims that
|
||||
would be infringed only as a consequence of further modification of
|
||||
this implementation. If you or your agent or exclusive licensee
|
||||
institute or order or agree to the institution of patent litigation
|
||||
against any entity (including a cross-claim or counterclaim in a
|
||||
lawsuit) alleging that this implementation of Dart or any code
|
||||
incorporated within this implementation of Dart constitutes direct or
|
||||
contributory patent infringement, or inducement of patent
|
||||
infringement, then any patent rights granted to you under this License
|
||||
for this implementation of Dart shall terminate as of the date such
|
||||
litigation is filed.
|
||||
@@ -0,0 +1,13 @@
|
||||
<?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="jdk" jdkName="1.6" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="guava-10.0.1" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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="jdk" jdkName="1.6" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="guava-10.0.1" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* Exception thrown when the compiler encounters an unexpected internal error.
|
||||
*/
|
||||
public class InternalCompilerException extends RuntimeException {
|
||||
|
||||
public InternalCompilerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* 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 java.util.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,232 @@
|
||||
// Copyright 2011, the Dart project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.InternalCompilerException;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Implements actual cloning logic. We rely on the JsExpressions to provide
|
||||
* traversal logic. The {@link #stack} field is used to accumulate
|
||||
* already-cloned JsExpression instances. One gotcha that falls out of this is
|
||||
* that argument lists are on the stack in reverse order, so lists should be
|
||||
* constructed via inserts, rather than appends.
|
||||
*/
|
||||
public class Cloner extends JsVisitor {
|
||||
protected final Stack<JsExpression> stack = new Stack<JsExpression>();
|
||||
private boolean successful = true;
|
||||
|
||||
/**
|
||||
* @param expression
|
||||
* @return Return a clone of the expression tree
|
||||
*/
|
||||
public static JsExpression clone(JsExpression expression) {
|
||||
Cloner c = new Cloner();
|
||||
c.accept(expression);
|
||||
return c.getExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsArrayAccess x, JsContext ctx) {
|
||||
JsArrayAccess newExpression = new JsArrayAccess();
|
||||
newExpression.setIndexExpr(stack.pop());
|
||||
newExpression.setArrayExpr(stack.pop());
|
||||
stack.push(newExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsArrayLiteral x, JsContext ctx) {
|
||||
JsArrayLiteral toReturn = new JsArrayLiteral();
|
||||
List<JsExpression> expressions = toReturn.getExpressions();
|
||||
int size = x.getExpressions().size();
|
||||
while (size-- > 0) {
|
||||
expressions.add(0, stack.pop());
|
||||
}
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsBinaryOperation x, JsContext ctx) {
|
||||
JsBinaryOperation toReturn = new JsBinaryOperation(x.getOperator());
|
||||
toReturn.setArg2(stack.pop());
|
||||
toReturn.setArg1(stack.pop());
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsBooleanLiteral x, JsContext ctx) {
|
||||
stack.push(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsConditional x, JsContext ctx) {
|
||||
JsConditional toReturn = new JsConditional();
|
||||
toReturn.setElseExpression(stack.pop());
|
||||
toReturn.setThenExpression(stack.pop());
|
||||
toReturn.setTestExpression(stack.pop());
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* The only functions that would get be visited are those being used as
|
||||
* first-class objects.
|
||||
*/
|
||||
@Override
|
||||
public void endVisit(JsFunction x, JsContext ctx) {
|
||||
// Set a flag to indicate that we cannot continue, and push a null so
|
||||
// we don't run out of elements on the stack.
|
||||
successful = false;
|
||||
stack.push(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloning the invocation allows us to modify it without damaging other call
|
||||
* sites.
|
||||
*/
|
||||
@Override
|
||||
public void endVisit(JsInvocation x, JsContext ctx) {
|
||||
JsInvocation toReturn = new JsInvocation();
|
||||
List<JsExpression> params = toReturn.getArguments();
|
||||
int size = x.getArguments().size();
|
||||
while (size-- > 0) {
|
||||
params.add(0, stack.pop());
|
||||
}
|
||||
toReturn.setQualifier(stack.pop());
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a deep clone of a JsNameRef. Because JsNameRef chains are shared
|
||||
* throughout the AST, you can't just go and change their qualifiers when
|
||||
* re-writing an invocation.
|
||||
*/
|
||||
@Override
|
||||
public void endVisit(JsNameRef x, JsContext ctx) {
|
||||
JsNameRef toReturn;
|
||||
JsName name = x.getName();
|
||||
if (name != null) {
|
||||
toReturn = new JsNameRef(name);
|
||||
} else {
|
||||
toReturn = new JsNameRef(x.getIdent());
|
||||
}
|
||||
|
||||
if (x.getQualifier() != null) {
|
||||
toReturn.setQualifier(stack.pop());
|
||||
}
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsNew x, JsContext ctx) {
|
||||
int size = x.getArguments().size();
|
||||
List<JsExpression> arguments = new ArrayList<JsExpression>(size);
|
||||
while (size-- > 0) {
|
||||
arguments.add(0, stack.pop());
|
||||
}
|
||||
JsNew toReturn = new JsNew(stack.pop());
|
||||
toReturn.getArguments().addAll(arguments);
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsNullLiteral x, JsContext ctx) {
|
||||
stack.push(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsNumberLiteral x, JsContext ctx) {
|
||||
stack.push(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsObjectLiteral x, JsContext ctx) {
|
||||
JsObjectLiteral toReturn = new JsObjectLiteral();
|
||||
List<JsPropertyInitializer> inits = toReturn.getPropertyInitializers();
|
||||
|
||||
int size = x.getPropertyInitializers().size();
|
||||
while (size-- > 0) {
|
||||
/*
|
||||
* JsPropertyInitializers are the only non-JsExpression objects that we
|
||||
* care about, so we just go ahead and create the objects in the loop,
|
||||
* rather than expecting it to be on the stack and having to perform
|
||||
* narrowing casts at all stack.pop() invocations.
|
||||
*/
|
||||
JsPropertyInitializer newInit = new JsPropertyInitializer();
|
||||
newInit.setValueExpr(stack.pop());
|
||||
newInit.setLabelExpr(stack.pop());
|
||||
|
||||
inits.add(0, newInit);
|
||||
}
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsPostfixOperation x, JsContext ctx) {
|
||||
JsPostfixOperation toReturn = new JsPostfixOperation(x.getOperator());
|
||||
toReturn.setArg(stack.pop());
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsPrefixOperation x, JsContext ctx) {
|
||||
JsPrefixOperation toReturn = new JsPrefixOperation(x.getOperator());
|
||||
toReturn.setArg(stack.pop());
|
||||
stack.push(toReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsRegExp x, JsContext ctx) {
|
||||
stack.push(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsStringLiteral x, JsContext ctx) {
|
||||
stack.push(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsThisRef x, JsContext ctx) {
|
||||
stack.push(new JsThisRef());
|
||||
}
|
||||
|
||||
public JsExpression getExpression() {
|
||||
return (successful && checkStack()) ? stack.peek() : null;
|
||||
}
|
||||
|
||||
private boolean checkStack() {
|
||||
if (stack.size() > 1) {
|
||||
throw new InternalCompilerException("Too many expressions on stack");
|
||||
}
|
||||
|
||||
return stack.size() == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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' toJsAst 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,119 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
|
||||
/**
|
||||
* Determines if an expression statement needs to be surrounded by parentheses.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
* 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) {
|
||||
JsFirstExpressionVisitor visitor = new JsFirstExpressionVisitor();
|
||||
JsExpression expression = statement.getExpression();
|
||||
// Pure function declarations do not need parentheses
|
||||
if (expression instanceof JsFunction) {
|
||||
return false;
|
||||
}
|
||||
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,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;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
|
||||
/**
|
||||
* A namer runs through a program and renames the short names of JsNames.
|
||||
* Namers must assign short names that don't clash and that are valid
|
||||
* JS-identifiers. Nested JsScopes must not shadow JsNames from outer
|
||||
* scopes.
|
||||
* If a JsName is marked as non-obfuscatable then it must retain its short
|
||||
* name.
|
||||
*/
|
||||
public interface JsNamer {
|
||||
/**
|
||||
* GlobalNames the shortNames of all JsNames of the program so that they are valid
|
||||
* JS-identifiers and that there are no clashes and no shadowing.
|
||||
*/
|
||||
public void exec(JsProgram program);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.*;
|
||||
|
||||
/**
|
||||
* Fixes any semantic errors introduced by JS AST gen.
|
||||
*
|
||||
* <ul>
|
||||
* <li>Creating clinit calls can put comma expressions as lvalues; the modifying
|
||||
* operation must be moved inside the comma expression to the last argument.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class JsNormalizer {
|
||||
|
||||
/**
|
||||
* Resolves any unresolved JsNameRefs.
|
||||
*/
|
||||
private static class JsNormalizing extends JsModVisitor {
|
||||
|
||||
@Override
|
||||
public void endVisit(JsBinaryOperation x, JsContext ctx) {
|
||||
maybeShuffleModifyingBinary(x, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsPostfixOperation x, JsContext ctx) {
|
||||
maybeShuffleModifyingUnary(x, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(JsPrefixOperation x, JsContext ctx) {
|
||||
maybeShuffleModifyingUnary(x, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Due to the way clinits are constructed, you can end up with a comma
|
||||
* operation as the argument to a modifying operation, which is illegal.
|
||||
* Juggle things to put the operator inside of the comma expression.
|
||||
*/
|
||||
private void maybeShuffleModifyingBinary(JsBinaryOperation x, JsContext ctx) {
|
||||
JsBinaryOperator myOp = x.getOperator();
|
||||
JsExpression lhs = x.getArg1();
|
||||
|
||||
if (myOp.isAssignment() && (lhs instanceof JsBinaryOperation)) {
|
||||
// Find the rightmost comma operation
|
||||
JsBinaryOperation curLhs = (JsBinaryOperation) lhs;
|
||||
assert (curLhs.getOperator() == JsBinaryOperator.COMMA);
|
||||
while (curLhs.getArg2() instanceof JsBinaryOperation) {
|
||||
curLhs = (JsBinaryOperation) curLhs.getArg2();
|
||||
assert (curLhs.getOperator() == JsBinaryOperator.COMMA);
|
||||
}
|
||||
// curLhs is now the rightmost comma operation; slide our operation in
|
||||
x.setArg1(curLhs.getArg2());
|
||||
curLhs.setArg2(x);
|
||||
// replace myself with the comma expression
|
||||
ctx.replaceMe(lhs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Due to the way clinits are constructed, you can end up with a comma
|
||||
* operation as the argument to a modifying operation, which is illegal.
|
||||
* Juggle things to put the operator inside of the comma expression.
|
||||
*/
|
||||
private void maybeShuffleModifyingUnary(JsUnaryOperation x, JsContext ctx) {
|
||||
JsUnaryOperator myOp = x.getOperator();
|
||||
JsExpression arg = x.getArg();
|
||||
if (myOp.isModifying() && (arg instanceof JsBinaryOperation)) {
|
||||
// Find the rightmost comma operation
|
||||
JsBinaryOperation curArg = (JsBinaryOperation) arg;
|
||||
assert (curArg.getOperator() == JsBinaryOperator.COMMA);
|
||||
while (curArg.getArg2() instanceof JsBinaryOperation) {
|
||||
curArg = (JsBinaryOperation) curArg.getArg2();
|
||||
assert (curArg.getOperator() == JsBinaryOperator.COMMA);
|
||||
}
|
||||
// curArg is now the rightmost comma operation; slide our operation in
|
||||
x.setArg(curArg.getArg2());
|
||||
curArg.setArg2(x);
|
||||
// replace myself with the comma expression
|
||||
ctx.replaceMe(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void exec(JsProgram program) {
|
||||
new JsNormalizer(program).execImpl();
|
||||
}
|
||||
|
||||
private final JsProgram program;
|
||||
|
||||
private JsNormalizer(JsProgram program) {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
private void execImpl() {
|
||||
JsNormalizing normalizer = new JsNormalizing();
|
||||
normalizer.accept(program);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
/**
|
||||
* Indicates inability to parse JavaScript source.
|
||||
*/
|
||||
public class JsParserException extends Exception {
|
||||
|
||||
/**
|
||||
* Represents the location of a parser exception.
|
||||
*/
|
||||
public static class SourceDetail {
|
||||
private final String fileName;
|
||||
private final int line;
|
||||
private final int lineOffset;
|
||||
private final String lineSource;
|
||||
|
||||
public SourceDetail(int line, String lineSource, int lineOffset, String fileName) {
|
||||
this.line = line;
|
||||
this.lineSource = lineSource;
|
||||
this.lineOffset = lineOffset;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public int getLineOffset() {
|
||||
return lineOffset;
|
||||
}
|
||||
|
||||
public String getLineSource() {
|
||||
return lineSource;
|
||||
}
|
||||
}
|
||||
|
||||
private static String createMessageWithDetail(String msg, SourceDetail sourceDetail) {
|
||||
if (sourceDetail == null) {
|
||||
return msg;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(sourceDetail.getFileName());
|
||||
sb.append('(');
|
||||
sb.append(sourceDetail.getLine());
|
||||
sb.append(')');
|
||||
sb.append(": ");
|
||||
sb.append(msg);
|
||||
if (sourceDetail.getLineSource() != null) {
|
||||
sb.append("\n> ");
|
||||
sb.append(sourceDetail.getLineSource());
|
||||
sb.append("\n> ");
|
||||
for (int i = 0, n = sourceDetail.getLineOffset(); i < n; ++i) {
|
||||
sb.append('-');
|
||||
}
|
||||
sb.append('^');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private final SourceDetail sourceDetail;
|
||||
|
||||
public JsParserException(String msg) {
|
||||
this(msg, null);
|
||||
}
|
||||
|
||||
public JsParserException(String msg, int line, String lineSource, int lineOffset, String fileName) {
|
||||
this(msg, new SourceDetail(line, lineSource, lineOffset, fileName));
|
||||
}
|
||||
|
||||
public JsParserException(String msg, SourceDetail sourceDetail) {
|
||||
super(createMessageWithDetail(msg, sourceDetail));
|
||||
this.sourceDetail = sourceDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides additional source detail in some cases.
|
||||
*
|
||||
* @return additional detail regarding the error, or <code>null</code> if no
|
||||
* additional detail is available
|
||||
*/
|
||||
public SourceDetail getSourceDetail() {
|
||||
return sourceDetail;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
|
||||
/**
|
||||
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
|
||||
* 57)
|
||||
*
|
||||
* 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(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 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(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(JsVars.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,122 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
import com.google.dart.compiler.backend.js.ast.JsRootScope;
|
||||
import com.google.dart.compiler.backend.js.ast.JsScope;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A namer that uses short, readable idents to maximize reability.
|
||||
*/
|
||||
public class JsPrettyNamer implements JsNamer {
|
||||
|
||||
public JsPrettyNamer() {
|
||||
this.program = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exec(JsProgram program) {
|
||||
new JsPrettyNamer(program).execImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Communicates to a parent scope all the idents used by all child scopes.
|
||||
*/
|
||||
private Set<String> childIdents = null;
|
||||
|
||||
private final JsProgram program;
|
||||
|
||||
/**
|
||||
* A map containing the next integer to try as an identifier suffix for a
|
||||
* given JsScope.
|
||||
*/
|
||||
private IdentityHashMap<JsScope, HashMap<String, Integer>> startIdentForScope =
|
||||
new IdentityHashMap<JsScope, HashMap<String, Integer>>();
|
||||
|
||||
protected JsPrettyNamer(JsProgram program) {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
private void execImpl() {
|
||||
visit(program.getRootScope());
|
||||
}
|
||||
|
||||
private boolean isLegal(JsScope scope, Set<String> childIdents, String newIdent) {
|
||||
if (JsReservedIdentifiers.isKeyword(newIdent)) {
|
||||
return false;
|
||||
}
|
||||
if (childIdents.contains(newIdent)) {
|
||||
// one of my children already claimed this ident
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Never obfuscate a name into an identifier that conflicts with an existing
|
||||
* unobfuscatable name! It's okay if it conflicts with an existing
|
||||
* obfuscatable name; that name will get obfuscated out of the way.
|
||||
*/
|
||||
return (scope.findExistingUnobfuscatableName(newIdent) == null);
|
||||
}
|
||||
|
||||
private void visit(JsScope scope) {
|
||||
HashMap<String, Integer> startIdent = startIdentForScope.get(scope);
|
||||
if (startIdent == null) {
|
||||
startIdent = new HashMap<String, Integer>();
|
||||
startIdentForScope.put(scope, startIdent);
|
||||
}
|
||||
|
||||
// Save off the childIdents which is currently being computed for my parent.
|
||||
Set<String> myChildIdents = childIdents;
|
||||
|
||||
/*
|
||||
* Visit my children first. Reset childIdents so that my children will get a
|
||||
* clean slate: I do not communicate to my children.
|
||||
*/
|
||||
childIdents = new HashSet<String>();
|
||||
List<JsScope> children = scope.getChildren();
|
||||
for (Iterator<JsScope> it = children.iterator(); it.hasNext();) {
|
||||
visit(it.next());
|
||||
}
|
||||
|
||||
JsRootScope rootScope = program.getRootScope();
|
||||
if (scope == rootScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Visit all my idents.
|
||||
for (Iterator<JsName> it = scope.getAllNames(); it.hasNext();) {
|
||||
JsName name = it.next();
|
||||
if (!name.isObfuscatable()) {
|
||||
// Unobfuscatable names become themselves.
|
||||
name.setShortIdent(name.getIdent());
|
||||
continue;
|
||||
}
|
||||
|
||||
String newIdent = name.getShortIdent();
|
||||
if (!isLegal(scope, childIdents, newIdent)) {
|
||||
String checkIdent;
|
||||
|
||||
// Start searching using a suffix hint stored in the scope.
|
||||
// We still do a search in case there is a collision with
|
||||
// a user-provided identifier
|
||||
Integer s = startIdent.get(newIdent);
|
||||
int suffix = (s == null) ? 0 : s.intValue();
|
||||
do {
|
||||
checkIdent = newIdent + "_" + suffix++;
|
||||
} while (!isLegal(scope, childIdents, checkIdent));
|
||||
startIdent.put(newIdent, suffix);
|
||||
name.setShortIdent(checkIdent);
|
||||
} else {
|
||||
// nothing to do; the short name is already good
|
||||
}
|
||||
childIdents.add(name.getShortIdent());
|
||||
}
|
||||
myChildIdents.addAll(childIdents);
|
||||
childIdents = myChildIdents;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
|
||||
/**
|
||||
* Determines if a statement at the end of a block requires a semicolon.
|
||||
*
|
||||
* 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.getThenStmt();
|
||||
JsStatement elseStmt = x.getElseStmt();
|
||||
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,223 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Determines whether or not a particular string is a JavaScript keyword or not.
|
||||
*/
|
||||
public class JsReservedIdentifiers {
|
||||
|
||||
private static Set<String> javaScriptKeywords;
|
||||
private static Set<String> reservedGlobalSymbols;
|
||||
private static Set<String> reservedPropertySymbols;
|
||||
|
||||
static {
|
||||
javaScriptKeywords = new HashSet<String>();
|
||||
reservedGlobalSymbols = new HashSet<String>();
|
||||
reservedPropertySymbols = new HashSet<String>();
|
||||
initJavaScriptKeywords();
|
||||
initReservedGlobalSymbols();
|
||||
initReservedPropertySymbols();
|
||||
}
|
||||
|
||||
public static boolean isKeyword(String s) {
|
||||
return javaScriptKeywords.contains(s);
|
||||
}
|
||||
|
||||
private static void initJavaScriptKeywords() {
|
||||
String[] keywords = new String[] {
|
||||
// These are current keywords
|
||||
"break", "delete", "function", "return", "typeof", "case", "do", "if", "switch", "var",
|
||||
"catch", "else", "in", "this", "void", "continue", "false", "instanceof", "throw",
|
||||
"while", "debugger", "finally", "new", "true", "with", "default", "for",
|
||||
"null", "try",
|
||||
|
||||
// These are future keywords
|
||||
"abstract", "double", "goto", "native", "static", "boolean", "enum", "implements",
|
||||
"package", "super", "byte", "export", "import", "private", "synchronized", "char",
|
||||
"extends", "int", "protected", "throws", "class", "final", "interface", "public",
|
||||
"transient", "const", "float", "long", "short", "volatile"
|
||||
};
|
||||
|
||||
for (int i = 0; i < keywords.length; i++) {
|
||||
javaScriptKeywords.add(keywords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a set containing all known reserved global identifiers. This set must not be modified.
|
||||
*/
|
||||
public static Set<String> getReservedGlobalSymbols() {
|
||||
return reservedGlobalSymbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the string s can not be used as a global identifier. The check includes
|
||||
* JavaScript keywords (as they must not be used either).
|
||||
* @param s
|
||||
* @return true if the given String must not be used as a global identifier.
|
||||
*/
|
||||
public static boolean isReservedGlobalSymbol(String s) {
|
||||
return isKeyword(s) || reservedGlobalSymbols.contains(s);
|
||||
}
|
||||
|
||||
private static void initReservedGlobalSymbols() {
|
||||
// Section references are from Ecma-262
|
||||
// (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf)
|
||||
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",
|
||||
|
||||
// TODO: prove why this is necessary or remove it
|
||||
"call"
|
||||
};
|
||||
for (int i = 0; i < commonBuiltins.length; i++) {
|
||||
reservedGlobalSymbols.add(commonBuiltins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given string can not be used as property symbol. The check excludes
|
||||
* keywords as JavaScript allow keywords as properties.
|
||||
* @param s
|
||||
* @return true if the given string must not be used as a property.
|
||||
*/
|
||||
public static boolean isReservedPropertySymbol(String s) {
|
||||
return reservedPropertySymbols.contains(s);
|
||||
}
|
||||
|
||||
private static void initReservedPropertySymbols() {
|
||||
// TODO(floitsch): fill in reserved property symbols.
|
||||
reservedPropertySymbols.add("__PROTO__");
|
||||
reservedPropertySymbols.add("prototype");
|
||||
}
|
||||
|
||||
private JsReservedIdentifiers() {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
import com.google.dart.compiler.util.TextOutput;
|
||||
import com.google.dart.compiler.backend.js.ast.JsContext;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgramFragment;
|
||||
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
|
||||
/**
|
||||
* Generates JavaScript source from an AST.
|
||||
*/
|
||||
public class JsSourceGenerationVisitor extends JsToStringGenerationVisitor {
|
||||
|
||||
public JsSourceGenerationVisitor(TextOutput out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(JsProgram x, JsContext ctx) {
|
||||
// Descend naturally.
|
||||
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,21 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js;
|
||||
|
||||
/**
|
||||
* An unchecked wrapper exception to interop with Rhino.
|
||||
*/
|
||||
class UncheckedJsParserException extends RuntimeException {
|
||||
|
||||
private final JsParserException parserException;
|
||||
|
||||
public UncheckedJsParserException(JsParserException parserException) {
|
||||
this.parserException = parserException;
|
||||
}
|
||||
|
||||
public JsParserException getParserException() {
|
||||
return parserException;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* An interface that describes the boolean evaluation of an expression.
|
||||
*/
|
||||
public interface CanBooleanEval {
|
||||
|
||||
boolean isBooleanFalse();
|
||||
|
||||
boolean isBooleanTrue();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implemented by JavaScript objects that accept arguments.
|
||||
*/
|
||||
public interface HasArguments {
|
||||
List<JsExpression> getArguments();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Implemented by JavaScript objects with conditional execution.
|
||||
*/
|
||||
public interface HasCondition {
|
||||
|
||||
JsExpression getCondition();
|
||||
|
||||
void setCondition(JsExpression condition);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 that have a name.
|
||||
*/
|
||||
public interface HasName {
|
||||
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 JsExpression {
|
||||
|
||||
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,67 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript expression for array literals.
|
||||
*/
|
||||
public final class JsArrayLiteral extends JsLiteral {
|
||||
|
||||
private final List<JsExpression> exprs = new ArrayList<JsExpression>();
|
||||
|
||||
public JsArrayLiteral() {
|
||||
super();
|
||||
}
|
||||
|
||||
public List<JsExpression> getExpressions() {
|
||||
return exprs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSideEffects() {
|
||||
for (JsExpression expr : exprs) {
|
||||
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(exprs);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 binary operation.
|
||||
*/
|
||||
public final class JsBinaryOperation extends JsExpression {
|
||||
|
||||
private JsExpression arg1;
|
||||
private JsExpression arg2;
|
||||
private final JsBinaryOperator op;
|
||||
|
||||
public JsBinaryOperation(JsBinaryOperator op) {
|
||||
this(op, null, null);
|
||||
}
|
||||
|
||||
public JsBinaryOperation(JsBinaryOperator op, JsExpression arg1, 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;
|
||||
}
|
||||
|
||||
public void setArg1(JsExpression arg1) {
|
||||
this.arg1 = arg1;
|
||||
}
|
||||
|
||||
public void setArg2(JsExpression arg2) {
|
||||
this.arg2 = arg2;
|
||||
}
|
||||
|
||||
@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,120 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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() {
|
||||
/*
|
||||
* Beware, flaky! Maybe I should have added Yet Another Field to
|
||||
* BinaryOperator?
|
||||
*/
|
||||
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,60 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript block statement.
|
||||
*/
|
||||
public class JsBlock extends JsStatement {
|
||||
|
||||
private final LinkedList<JsStatement> stmts = new LinkedList<JsStatement>();
|
||||
|
||||
public JsBlock() {
|
||||
}
|
||||
|
||||
public JsBlock(JsStatement stmt) {
|
||||
stmts.add(stmt);
|
||||
}
|
||||
|
||||
public List<JsStatement> getStatements() {
|
||||
return stmts;
|
||||
}
|
||||
|
||||
public void addStatement(JsStatement statement) {
|
||||
assert statement != null;
|
||||
stmts.add(statement);
|
||||
}
|
||||
|
||||
public boolean isGlobalBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitor v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptWithInsertRemove(stmts);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.BLOCK;
|
||||
}
|
||||
|
||||
/*Pavel Talanov*/
|
||||
public void addVarDeclaration(JsVars vars) {
|
||||
stmts.offerFirst(vars);
|
||||
}
|
||||
|
||||
public void setStatements(List<JsStatement> statements) {
|
||||
assert this.stmts.isEmpty() : "Already contains statements.";
|
||||
this.stmts.addAll(statements);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript literal boolean expression.
|
||||
*/
|
||||
public final class JsBooleanLiteral extends JsValueLiteral {
|
||||
|
||||
private final boolean value;
|
||||
|
||||
// Should be interned by JsProgram
|
||||
JsBooleanLiteral(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanFalse() {
|
||||
return value == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanTrue() {
|
||||
return value == 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.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript break statement.
|
||||
*/
|
||||
public final class JsBreak extends JsStatement {
|
||||
|
||||
private final JsNameRef label;
|
||||
|
||||
public JsBreak() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public JsBreak(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 boolean unconditionalControlBreak() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.BREAK;
|
||||
}
|
||||
}
|
||||
@@ -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(stmts);
|
||||
}
|
||||
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 JsNode 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.findExistingName(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,75 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* 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");
|
||||
this.name = new JsName(this, ident, ident, ident);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName declareName(String ident) {
|
||||
// Declare into parent scope!
|
||||
return getParent().declareName(ident);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName declareName(String ident, String shortIdent) {
|
||||
// Declare into parent scope!
|
||||
return getParent().declareName(ident, shortIdent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<JsName> getAllNames() {
|
||||
return new Iterator<JsName>() {
|
||||
private boolean didIterate = false;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !didIterate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName next() {
|
||||
if (didIterate) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
didIterate = true;
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsName doCreateName(String ident, String shortIdent, String originalName) {
|
||||
throw new UnsupportedOperationException("Cannot create a name in a catch scope");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName findExistingNameNoRecurse(String ident) {
|
||||
if (name.getIdent().equals(ident)) {
|
||||
return name;
|
||||
} else {
|
||||
return 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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript conditional expression.
|
||||
*/
|
||||
public final class JsConditional extends JsExpression {
|
||||
|
||||
private JsExpression elseExpr;
|
||||
private JsExpression testExpr;
|
||||
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,46 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript continue statement.
|
||||
*/
|
||||
public final class JsContinue extends JsStatement {
|
||||
|
||||
private final JsNameRef label;
|
||||
|
||||
public JsContinue() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public JsContinue(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 boolean unconditionalControlBreak() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@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 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(stmts);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.DEFAULT;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript do..while statement.
|
||||
*/
|
||||
public class JsDoWhile extends JsStatement {
|
||||
|
||||
private JsStatement body;
|
||||
private JsExpression condition;
|
||||
|
||||
public JsDoWhile() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JsDoWhile(JsExpression condition, JsStatement body) {
|
||||
super();
|
||||
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)) {
|
||||
body = v.accept(body);
|
||||
condition = v.accept(condition);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.DO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Represents an empty statement in JavaScript.
|
||||
*/
|
||||
public class JsEmpty extends 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,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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript expression statement.
|
||||
*/
|
||||
public final class JsExprStmt extends 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.EXPR_STMT;
|
||||
}
|
||||
}
|
||||
@@ -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.SourceInfo;
|
||||
|
||||
/**
|
||||
* An abstract base class for all JavaScript expressions.
|
||||
*/
|
||||
public abstract class JsExpression extends JsNode {
|
||||
|
||||
protected JsExpression() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the expression can cause side effects.
|
||||
*/
|
||||
public abstract boolean hasSideEffects();
|
||||
|
||||
/**
|
||||
* True if the target expression is definitely not null.
|
||||
*/
|
||||
public abstract boolean isDefinitelyNotNull();
|
||||
|
||||
/**
|
||||
* True if the target expression is definitely null.
|
||||
*/
|
||||
public abstract boolean isDefinitelyNull();
|
||||
|
||||
/**
|
||||
* Determines whether or not this expression is a leaf, such as a
|
||||
* {@link JsNameRef}, {@link JsBooleanLiteral}, and so on. Leaf expressions
|
||||
* never need to be parenthesized.
|
||||
*/
|
||||
public boolean isLeaf() {
|
||||
// Conservatively say that it isn't a leaf.
|
||||
// Individual subclasses can speak for themselves if they are a leaf.
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsExprStmt makeStmt() {
|
||||
return new JsExprStmt(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsExpression setSourceRef(SourceInfo info) {
|
||||
super.setSourceRef(info);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.google.dart.compiler.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>
|
||||
* 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 JsStatement {
|
||||
|
||||
private JsStatement body;
|
||||
private JsExpression condition;
|
||||
private JsExpression incrExpr;
|
||||
private JsExpression initExpr;
|
||||
private JsVars initVars;
|
||||
|
||||
public JsFor() {
|
||||
super();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setCondition(JsExpression condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public void setIncrExpr(JsExpression incrExpr) {
|
||||
this.incrExpr = incrExpr;
|
||||
}
|
||||
|
||||
public void setInitExpr(JsExpression initExpr) {
|
||||
this.initExpr = initExpr;
|
||||
}
|
||||
|
||||
public void setInitVars(JsVars initVars) {
|
||||
this.initVars = initVars;
|
||||
}
|
||||
|
||||
@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 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,238 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript function expression.
|
||||
*/
|
||||
public final class JsFunction extends JsLiteral implements HasName {
|
||||
|
||||
private static void trace(String title, String code) {
|
||||
System.out.println("---------------------------");
|
||||
System.out.println(title + ":");
|
||||
System.out.println("---------------------------");
|
||||
System.out.println(code);
|
||||
}
|
||||
|
||||
protected JsBlock body;
|
||||
protected final List<JsParameter> params = new ArrayList<JsParameter>();
|
||||
protected final JsScope scope;
|
||||
private boolean artificiallyRescued;
|
||||
private boolean executeOnce;
|
||||
private boolean fromDart;
|
||||
private JsFunction impliedExecute;
|
||||
private JsName name;
|
||||
private boolean trace = false;
|
||||
private boolean traceFirst = true;
|
||||
private boolean hoisted = false;
|
||||
private boolean constructor = false;
|
||||
|
||||
/**
|
||||
* Creates an anonymous function.
|
||||
*/
|
||||
public JsFunction(JsScope parent) {
|
||||
this(parent, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function that is not derived from Dart source.
|
||||
*/
|
||||
public JsFunction(JsScope parent, JsName name) {
|
||||
this(parent, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a named function, possibly derived from Dart source.
|
||||
*/
|
||||
public JsFunction(JsScope parent, JsName name, boolean fromDart) {
|
||||
assert (parent != null);
|
||||
this.fromDart = fromDart;
|
||||
setName(name);
|
||||
String scopeName = (name == null) ? "<anonymous>" : name.getIdent();
|
||||
scopeName = "function " + scopeName;
|
||||
this.scope = new JsScope(parent, scopeName);
|
||||
}
|
||||
|
||||
public JsBlock getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, this indicates that only the first invocation of the function will
|
||||
* have any effects. Subsequent invocations may be considered to be no-op
|
||||
* calls whose return value is ignored.
|
||||
*/
|
||||
public boolean getExecuteOnce() {
|
||||
return executeOnce;
|
||||
}
|
||||
|
||||
public JsFunction getImpliedExecute() {
|
||||
return impliedExecute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setParameters(List<JsParameter> params) {
|
||||
this.params.clear();
|
||||
this.params.addAll(params);
|
||||
}
|
||||
|
||||
public List<JsParameter> getParameters() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public JsScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSideEffects() {
|
||||
// If there's a name, the name is assigned to.
|
||||
return name != null;
|
||||
}
|
||||
|
||||
public boolean isArtificiallyRescued() {
|
||||
return artificiallyRescued;
|
||||
}
|
||||
|
||||
@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 boolean isFromDart() {
|
||||
return fromDart;
|
||||
}
|
||||
|
||||
public void setArtificiallyRescued(boolean rescued) {
|
||||
this.artificiallyRescued = rescued;
|
||||
}
|
||||
|
||||
public void setBody(JsBlock body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public void setExecuteOnce(boolean executeOnce) {
|
||||
this.executeOnce = executeOnce;
|
||||
}
|
||||
|
||||
public void setFromDart(boolean fromDart) {
|
||||
this.fromDart = fromDart;
|
||||
}
|
||||
|
||||
public void setImpliedExecute(JsFunction impliedExecute) {
|
||||
this.impliedExecute = impliedExecute;
|
||||
}
|
||||
|
||||
public void setName(JsName name) {
|
||||
this.name = name;
|
||||
if (name != null) {
|
||||
if (isFromDart()) {
|
||||
name.setStaticRef(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTrace() {
|
||||
this.trace = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitor v, JsContext ctx) {
|
||||
String before = null;
|
||||
if (trace && v instanceof JsModVisitor) {
|
||||
before = this.toSource();
|
||||
if (traceFirst) {
|
||||
traceFirst = false;
|
||||
trace("SCRIPT INITIAL", before);
|
||||
}
|
||||
}
|
||||
if (v.visit(this, ctx)) {
|
||||
v.acceptWithInsertRemove(params);
|
||||
body = v.accept(body);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
if (trace && v instanceof JsModVisitor) {
|
||||
String after = this.toSource();
|
||||
if (!after.equals(before)) {
|
||||
String title = v.getClass().getSimpleName();
|
||||
trace(title, after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setHoisted() {
|
||||
hoisted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the function has been hoisted
|
||||
*/
|
||||
public boolean isHoisted() {
|
||||
return hoisted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebase the function to a new scope.
|
||||
*
|
||||
* @param newScopeParent The scope to add the function to.
|
||||
*/
|
||||
public void rebaseScope(JsScope newScopeParent) {
|
||||
this.scope.rebase(newScopeParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsFunction setSourceRef(SourceInfo info) {
|
||||
super.setSourceRef(info);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isConstructor() {
|
||||
return this.constructor;
|
||||
}
|
||||
|
||||
public boolean setIsConstructor(boolean constructor) {
|
||||
return this.constructor = constructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.FUNCTION;
|
||||
}
|
||||
|
||||
// Pavel Talanov
|
||||
// dummy parameter to distinguish from other constructors
|
||||
private JsFunction(Void dummy, JsScope functionScope) {
|
||||
this.fromDart = false;
|
||||
this.scope = functionScope;
|
||||
}
|
||||
|
||||
public static JsFunction getAnonymousFunctionWithScope(JsScope scope) {
|
||||
return new JsFunction(null, scope);
|
||||
}
|
||||
}
|
||||
@@ -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,65 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 JsStatement {
|
||||
|
||||
private JsExpression ifExpr;
|
||||
private JsStatement thenStmt;
|
||||
private JsStatement elseStmt;
|
||||
|
||||
public JsIf() {
|
||||
}
|
||||
|
||||
public JsIf(JsExpression ifExpr, JsStatement thenStmt, JsStatement elseStmt) {
|
||||
this.ifExpr = ifExpr;
|
||||
this.thenStmt = thenStmt;
|
||||
this.elseStmt = elseStmt;
|
||||
}
|
||||
|
||||
public JsStatement getElseStmt() {
|
||||
return elseStmt;
|
||||
}
|
||||
|
||||
public JsExpression getIfExpr() {
|
||||
return ifExpr;
|
||||
}
|
||||
|
||||
public JsStatement getThenStmt() {
|
||||
return thenStmt;
|
||||
}
|
||||
|
||||
public void setElseStmt(JsStatement elseStmt) {
|
||||
this.elseStmt = elseStmt;
|
||||
}
|
||||
|
||||
public void setIfExpr(JsExpression ifExpr) {
|
||||
this.ifExpr = ifExpr;
|
||||
}
|
||||
|
||||
public void setThenStmt(JsStatement thenStmt) {
|
||||
this.thenStmt = thenStmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitor v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
ifExpr = v.accept(ifExpr);
|
||||
thenStmt = v.accept(thenStmt);
|
||||
if (elseStmt != null) {
|
||||
elseStmt = v.accept(elseStmt);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.IF;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript invocation.
|
||||
*/
|
||||
public final class JsInvocation extends JsExpression implements HasArguments {
|
||||
|
||||
private final List<JsExpression> args = new ArrayList<JsExpression>();
|
||||
private JsExpression qualifier;
|
||||
|
||||
public JsInvocation() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JsExpression> getArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
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(args);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.INVOKE;
|
||||
}
|
||||
|
||||
// Pavel Talanov
|
||||
public void setArguments(List<JsExpression> arguments) {
|
||||
assert this.args.isEmpty() : "Arguments already set.";
|
||||
this.args.addAll(arguments);
|
||||
}
|
||||
|
||||
public void setArguments(JsExpression... arguments) {
|
||||
setArguments(Arrays.asList(arguments));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript label statement.
|
||||
*/
|
||||
public class JsLabel extends JsStatement implements HasName {
|
||||
|
||||
private final JsName label;
|
||||
|
||||
private JsStatement stmt;
|
||||
|
||||
public JsLabel(JsName label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
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,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;
|
||||
|
||||
/**
|
||||
* A JavaScript string literal expression.
|
||||
*/
|
||||
public abstract class JsLiteral extends JsExpression implements CanBooleanEval {
|
||||
|
||||
protected JsLiteral() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.Hack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A visitor for iterating through and modifying an AST.
|
||||
*/
|
||||
public class JsModVisitor extends JsVisitor {
|
||||
|
||||
private class ListContext<T extends JsVisitable> implements JsContext {
|
||||
|
||||
private List<T> collection;
|
||||
private int index;
|
||||
private boolean removed;
|
||||
private boolean replaced;
|
||||
|
||||
@Override
|
||||
public boolean canInsert() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRemove() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertAfter(JsVisitable node) {
|
||||
checkRemoved();
|
||||
collection.add(index + 1, Hack.<T>cast(node));
|
||||
didChange = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertBefore(JsVisitable node) {
|
||||
checkRemoved();
|
||||
collection.add(index++, Hack.<T>cast(node));
|
||||
didChange = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLvalue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMe() {
|
||||
checkState();
|
||||
collection.remove(index--);
|
||||
didChange = removed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceMe(JsVisitable node) {
|
||||
checkState();
|
||||
checkReplacement(collection.get(index), node);
|
||||
collection.set(index, Hack.<T>cast(node));
|
||||
didChange = replaced = true;
|
||||
}
|
||||
|
||||
protected void traverse(List<T> collection) {
|
||||
this.collection = collection;
|
||||
for (index = 0; index < collection.size(); ++index) {
|
||||
removed = replaced = false;
|
||||
doTraverse(collection.get(index), this);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRemoved() {
|
||||
if (removed) {
|
||||
throw new RuntimeException("Node was already removed");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState() {
|
||||
checkRemoved();
|
||||
if (replaced) {
|
||||
throw new RuntimeException("Node was already replaced");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LvalueContext extends NodeContext<JsExpression> {
|
||||
@Override
|
||||
public boolean isLvalue() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class NodeContext<T extends JsVisitable> implements JsContext {
|
||||
private T node;
|
||||
private boolean replaced;
|
||||
|
||||
@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) {
|
||||
if (replaced) {
|
||||
throw new RuntimeException("Node was already replaced");
|
||||
}
|
||||
checkReplacement(this.node, node);
|
||||
this.node = Hack.<T>cast(node);
|
||||
didChange = replaced = true;
|
||||
}
|
||||
|
||||
protected T traverse(T node) {
|
||||
this.node = node;
|
||||
replaced = false;
|
||||
doTraverse(node, this);
|
||||
return this.node;
|
||||
}
|
||||
}
|
||||
|
||||
protected static <T extends JsVisitable> void checkReplacement(T origNode, T newNode) {
|
||||
if (newNode == null) {
|
||||
throw new RuntimeException("Cannot replace with null");
|
||||
}
|
||||
if (newNode == origNode) {
|
||||
throw new RuntimeException("The replacement is the same as the original");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean didChange = false;
|
||||
|
||||
@Override
|
||||
public boolean didChange() {
|
||||
return didChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsVisitable> T doAccept(T node) {
|
||||
return new NodeContext<T>().traverse(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsVisitable> void doAcceptList(List<T> collection) {
|
||||
NodeContext<T> ctx = new NodeContext<T>();
|
||||
for (int i = 0, c = collection.size(); i < c; ++i) {
|
||||
ctx.traverse(collection.get(i));
|
||||
if (ctx.replaced) {
|
||||
collection.set(i, ctx.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsExpression doAcceptLvalue(JsExpression expr) {
|
||||
return new LvalueContext().traverse(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
|
||||
new ListContext<T>().traverse(collection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.io.Serializable;
|
||||
|
||||
/**
|
||||
* An abstract base class for named JavaScript objects.
|
||||
*/
|
||||
public class JsName implements Serializable {
|
||||
private final JsScope enclosing;
|
||||
private final String ident;
|
||||
private boolean isObfuscatable;
|
||||
private String shortIdent;
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* A back-reference to the JsNode that the JsName refers to.
|
||||
*/
|
||||
private JsNode staticRef;
|
||||
|
||||
/**
|
||||
* @param ident the unmangled ident to use for this name
|
||||
*/
|
||||
JsName(JsScope enclosing, String ident, String shortIdent, String originalName) {
|
||||
this.enclosing = enclosing;
|
||||
this.ident = ident;
|
||||
this.shortIdent = shortIdent;
|
||||
if (originalName != null) {
|
||||
this.originalName = originalName;
|
||||
}
|
||||
this.isObfuscatable = true;
|
||||
}
|
||||
|
||||
public JsScope getEnclosing() {
|
||||
return enclosing;
|
||||
}
|
||||
|
||||
public String getIdent() {
|
||||
return ident;
|
||||
}
|
||||
|
||||
public String getShortIdent() {
|
||||
return shortIdent;
|
||||
}
|
||||
|
||||
public String getOriginalName() {
|
||||
return originalName;
|
||||
}
|
||||
|
||||
public JsNode getStaticRef() {
|
||||
return staticRef;
|
||||
}
|
||||
|
||||
public boolean isObfuscatable() {
|
||||
return isObfuscatable;
|
||||
}
|
||||
|
||||
public JsNameRef makeRef() {
|
||||
return new JsNameRef(this);
|
||||
}
|
||||
|
||||
public void setObfuscatable(boolean isObfuscatable) {
|
||||
this.isObfuscatable = isObfuscatable;
|
||||
}
|
||||
|
||||
public void setShortIdent(String shortIdent) {
|
||||
this.shortIdent = shortIdent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should never be called except on immutable stuff.
|
||||
*/
|
||||
public void setStaticRef(JsNode node) {
|
||||
this.staticRef = node;
|
||||
}
|
||||
|
||||
@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,113 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 that references a name.
|
||||
*/
|
||||
public final class JsNameRef extends JsExpression 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 String getIdent() {
|
||||
return (name == null) ? ident : name.getIdent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public JsExpression getQualifier() {
|
||||
return qualifier;
|
||||
}
|
||||
|
||||
public String getShortIdent() {
|
||||
return (name == null) ? ident : name.getShortIdent();
|
||||
}
|
||||
|
||||
@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() {
|
||||
// TODO: look for single-assignment of stuff from Java?
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefinitelyNull() {
|
||||
if (name != null) {
|
||||
return (name.getEnclosing().getProgram().getUndefinedLiteral().getName() == name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
if (qualifier == null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isResolved() {
|
||||
return name != null;
|
||||
}
|
||||
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript new expression.
|
||||
*/
|
||||
public final class JsNew extends JsExpression implements HasArguments {
|
||||
|
||||
private final List<JsExpression> args = new ArrayList<JsExpression>();
|
||||
private JsExpression ctorExpr;
|
||||
|
||||
public JsNew(JsExpression ctorExpr) {
|
||||
this.ctorExpr = ctorExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JsExpression> getArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArguments(List<JsExpression> arguments) {
|
||||
args.clear();
|
||||
args.addAll(arguments);
|
||||
}
|
||||
|
||||
public JsExpression getConstructorExpression() {
|
||||
return ctorExpr;
|
||||
}
|
||||
|
||||
@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)) {
|
||||
ctorExpr = v.accept(ctorExpr);
|
||||
v.acceptList(args);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.NEW;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.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.DefaultTextOutput;
|
||||
|
||||
/**
|
||||
* Base class for all JS AST elements.
|
||||
*/
|
||||
public abstract class JsNode extends AbstractNode implements JsVisitable {
|
||||
|
||||
protected JsNode() {
|
||||
}
|
||||
|
||||
// Causes source generation to delegate to the one visitor
|
||||
public final String toSource() {
|
||||
DefaultTextOutput out = new DefaultTextOutput(false);
|
||||
JsSourceGenerationVisitor v = new JsSourceGenerationVisitor(out);
|
||||
v.accept(this);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
// Causes source generation to delegate to the one visitor
|
||||
@Override
|
||||
public final String toString() {
|
||||
DefaultTextOutput out = new DefaultTextOutput(false);
|
||||
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;
|
||||
}
|
||||
|
||||
public abstract NodeKind getKind();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* A JavaScript null literal.
|
||||
*/
|
||||
public final class JsNullLiteral extends JsValueLiteral {
|
||||
|
||||
// Should only be instantiated in JsProgram
|
||||
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,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;
|
||||
|
||||
/**
|
||||
* Represents a JavaScript literal decimal expression.
|
||||
*/
|
||||
public final class JsNumberLiteral extends JsValueLiteral {
|
||||
|
||||
private final double value;
|
||||
|
||||
// Should be interned by JsProgram
|
||||
JsNumberLiteral(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanFalse() {
|
||||
return value == 0.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanTrue() {
|
||||
return value != 0.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.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 object literal.
|
||||
*/
|
||||
public final class JsObjectLiteral extends JsLiteral {
|
||||
|
||||
private final List<JsPropertyInitializer> props;
|
||||
|
||||
public JsObjectLiteral() {
|
||||
props = new ArrayList<JsPropertyInitializer>();
|
||||
}
|
||||
|
||||
public JsObjectLiteral(List<JsPropertyInitializer> props) {
|
||||
assert props != null;
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public List<JsPropertyInitializer> getPropertyInitializers() {
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSideEffects() {
|
||||
for (JsPropertyInitializer prop : props) {
|
||||
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(props);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.OBJECT;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* A JavaScript operator.
|
||||
*/
|
||||
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,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;
|
||||
|
||||
/**
|
||||
* A JavaScript parameter.
|
||||
*/
|
||||
public final class JsParameter extends JsNode implements HasName {
|
||||
|
||||
private final JsName name;
|
||||
|
||||
public JsParameter(JsName name) {
|
||||
this.name = name;
|
||||
name.setStaticRef(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
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,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.backend.js.ast;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A JavaScript program.
|
||||
*/
|
||||
public final class JsProgram extends JsNode {
|
||||
|
||||
private final JsStatement debuggerStmt;
|
||||
private final JsEmpty emptyStmt;
|
||||
private final JsBooleanLiteral falseLiteral;
|
||||
private JsProgramFragment[] fragments;
|
||||
private final Map<String, JsFunction> indexedFunctions = new HashMap<String, JsFunction>();
|
||||
private final JsNullLiteral nullLiteral;
|
||||
private final Map<Double, JsNumberLiteral> numberLiteralMap =
|
||||
new HashMap<Double, JsNumberLiteral>();
|
||||
private final JsScope objectScope;
|
||||
private final JsRootScope rootScope;
|
||||
private final Map<String, JsStringLiteral> stringLiteralMap =
|
||||
new HashMap<String, JsStringLiteral>();
|
||||
private final JsScope topScope;
|
||||
private final JsBooleanLiteral trueLiteral;
|
||||
|
||||
/**
|
||||
* Constructs a JavaScript program object.
|
||||
*/
|
||||
public JsProgram(String unitId) {
|
||||
rootScope = new JsRootScope(this);
|
||||
topScope = new JsScope(rootScope, "Global", unitId);
|
||||
objectScope = new JsScope(rootScope, "Object");
|
||||
setFragmentCount(1);
|
||||
|
||||
debuggerStmt = new JsDebugger();
|
||||
emptyStmt = new JsEmpty();
|
||||
falseLiteral = new JsBooleanLiteral(false);
|
||||
nullLiteral = new JsNullLiteral();
|
||||
trueLiteral = new JsBooleanLiteral(true);
|
||||
}
|
||||
|
||||
public JsBooleanLiteral getBooleanLiteral(boolean truth) {
|
||||
if (truth) {
|
||||
return getTrueLiteral();
|
||||
}
|
||||
return getFalseLiteral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link JsStatement} to use whenever parsed source include a
|
||||
* <code>debugger</code> statement.
|
||||
*/
|
||||
public JsStatement getDebuggerStmt() {
|
||||
return debuggerStmt;
|
||||
}
|
||||
|
||||
public JsEmpty getEmptyStmt() {
|
||||
return emptyStmt;
|
||||
}
|
||||
|
||||
public JsBooleanLiteral getFalseLiteral() {
|
||||
return falseLiteral;
|
||||
}
|
||||
|
||||
public JsBlock getFragmentBlock(int fragment) {
|
||||
if (fragment < 0 || fragment >= fragments.length) {
|
||||
throw new IllegalArgumentException("Invalid fragment: " + fragment);
|
||||
}
|
||||
return fragments[fragment].getGlobalBlock();
|
||||
}
|
||||
|
||||
public int getFragmentCount() {
|
||||
return this.fragments.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the one and only global block.
|
||||
*/
|
||||
public JsBlock getGlobalBlock() {
|
||||
return getFragmentBlock(0);
|
||||
}
|
||||
|
||||
public JsFunction getIndexedFunction(String name) {
|
||||
return indexedFunctions.get(name);
|
||||
}
|
||||
|
||||
public JsNullLiteral getNullLiteral() {
|
||||
return nullLiteral;
|
||||
}
|
||||
|
||||
public JsNumberLiteral getNumberLiteral(double value) {
|
||||
JsNumberLiteral lit = numberLiteralMap.get(value);
|
||||
if (lit == null) {
|
||||
lit = new JsNumberLiteral(value);
|
||||
numberLiteralMap.put(value, lit);
|
||||
}
|
||||
|
||||
return lit;
|
||||
}
|
||||
|
||||
public JsScope getObjectScope() {
|
||||
return objectScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 lit = stringLiteralMap.get(value);
|
||||
if (lit == null) {
|
||||
lit = new JsStringLiteral(value);
|
||||
stringLiteralMap.put(value, lit);
|
||||
}
|
||||
return lit;
|
||||
}
|
||||
|
||||
public JsBooleanLiteral getTrueLiteral() {
|
||||
return trueLiteral;
|
||||
}
|
||||
|
||||
public JsNameRef getUndefinedLiteral() {
|
||||
return new JsNameRef("$Dart$Null");
|
||||
}
|
||||
|
||||
public void setFragmentCount(int fragments) {
|
||||
this.fragments = new JsProgramFragment[fragments];
|
||||
for (int i = 0; i < fragments; i++) {
|
||||
this.fragments[i] = new JsProgramFragment();
|
||||
}
|
||||
}
|
||||
|
||||
public void setIndexedFunctions(Map<String, JsFunction> indexedFunctions) {
|
||||
this.indexedFunctions.clear();
|
||||
this.indexedFunctions.putAll(indexedFunctions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitor v, 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 JsNode {
|
||||
|
||||
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,56 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Used in object literals to specify property values by name.
|
||||
*/
|
||||
public class JsPropertyInitializer extends JsNode {
|
||||
|
||||
private JsExpression labelExpr;
|
||||
private JsExpression valueExpr;
|
||||
|
||||
public JsPropertyInitializer() {
|
||||
}
|
||||
|
||||
public JsPropertyInitializer(JsExpression labelExpr, JsExpression valueExpr) {
|
||||
this.labelExpr = labelExpr;
|
||||
this.valueExpr = valueExpr;
|
||||
}
|
||||
|
||||
public JsExpression getLabelExpr() {
|
||||
return labelExpr;
|
||||
}
|
||||
|
||||
public JsExpression getValueExpr() {
|
||||
return valueExpr;
|
||||
}
|
||||
|
||||
public boolean hasSideEffects() {
|
||||
return labelExpr.hasSideEffects() || valueExpr.hasSideEffects();
|
||||
}
|
||||
|
||||
public void setLabelExpr(JsExpression labelExpr) {
|
||||
this.labelExpr = labelExpr;
|
||||
}
|
||||
|
||||
public void setValueExpr(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,48 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* A JavaScript return statement.
|
||||
*/
|
||||
public final class JsReturn extends 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 boolean unconditionalControlBreak() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.RETURN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
import com.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 doCreateName(String ident, String shortIdent, String originalName) {
|
||||
JsName name = super.doCreateName(ident, shortIdent, originalName);
|
||||
name.setObfuscatable(false);
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName findExistingNameNoRecurse(String ident) {
|
||||
JsName name = super.findExistingNameNoRecurse(ident);
|
||||
if (name == null) {
|
||||
if (JsReservedIdentifiers.getReservedGlobalSymbols().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, ident, ident);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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.Lists;
|
||||
import com.google.dart.compiler.util.Maps;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
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 implements Serializable {
|
||||
|
||||
private List<JsScope> children = Collections.emptyList();
|
||||
private final String description;
|
||||
private Map<String, JsName> names = Collections.emptyMap();
|
||||
private JsScope parent;
|
||||
protected int tempIndex = 0;
|
||||
private final String scopeId;
|
||||
|
||||
/*
|
||||
* Create a scope with parent.
|
||||
*/
|
||||
public JsScope(JsScope parent, String description) {
|
||||
this(parent, description, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a scope with parent.
|
||||
*/
|
||||
public JsScope(JsScope parent, String description, String scopeId) {
|
||||
assert (parent != null);
|
||||
this.scopeId = scopeId;
|
||||
this.description = description;
|
||||
this.parent = parent;
|
||||
parent.children = Lists.add(parent.children, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebase the function to a new scope.
|
||||
*
|
||||
* @param newParent The scope to add the function to.
|
||||
*/
|
||||
public void rebase(JsScope newParent) {
|
||||
detachFromParent();
|
||||
parent = newParent;
|
||||
parent.children = Lists.add(parent.children, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebase the function's children to a new scope.
|
||||
*
|
||||
* @param newParent
|
||||
*/
|
||||
public void rebaseChildScopes(JsScope newParent) {
|
||||
if (newParent == this) {
|
||||
return;
|
||||
}
|
||||
parent.children = Lists.addAll(parent.children, children);
|
||||
for (JsScope child : children) {
|
||||
child.parent = newParent;
|
||||
}
|
||||
children = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can detach and become parentless.
|
||||
*/
|
||||
protected void detachFromParent() {
|
||||
JsScope oldParent = parent;
|
||||
|
||||
oldParent.children = Lists.remove(
|
||||
parent.children, oldParent.children.indexOf(this));
|
||||
|
||||
parent = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can be parentless.
|
||||
*/
|
||||
protected JsScope(String description) {
|
||||
this.description = description;
|
||||
this.parent = null;
|
||||
this.scopeId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a name object associated with the specified ident in this scope,
|
||||
* creating it if necessary.<br/>
|
||||
* If the JsName does not exist yet, a new JsName is created. The ident,
|
||||
* short name, and original name of the newly created JsName are equal to
|
||||
* the given ident.
|
||||
*
|
||||
* @param ident An identifier that is unique within this scope.
|
||||
*/
|
||||
public JsName declareName(String ident) {
|
||||
JsName name = findExistingNameNoRecurse(ident);
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
return doCreateName(ident, ident, ident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new variable with an unique ident in this scope.
|
||||
* The generated JsName 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
|
||||
* (unless they use this function).
|
||||
*/
|
||||
public JsName declareFreshName(String shortName) {
|
||||
String ident = shortName;
|
||||
int counter = 0;
|
||||
while (findExistingNameNoRecurse(ident) != null) {
|
||||
ident = shortName + "_" + counter++;
|
||||
}
|
||||
return doCreateName(ident, shortName, shortName);
|
||||
}
|
||||
|
||||
String getNextTempName() {
|
||||
// TODO(ngeoffray): Decide on a convention for temporary variables
|
||||
// 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a name object associated with the specified ident in this scope,
|
||||
* creating it if necessary.<br/>
|
||||
* If the JsName does not exist yet, a new JsName is created with the given
|
||||
* ident, short name and original name.
|
||||
*
|
||||
* @param ident An identifier that is unique within this scope.
|
||||
* @param shortIdent A "pretty" name that does not have to be unique.
|
||||
* @throws IllegalArgumentException if ident already exists in this scope but
|
||||
* the requested short name does not match the existing short name.
|
||||
*/
|
||||
public JsName declareName(String ident, String shortIdent) {
|
||||
return declareName(ident, shortIdent, ident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a name object associated with the specified ident in this scope,
|
||||
* creating it if necessary.<br/>
|
||||
* If the JsName does not exist yet, a new JsName is created. The original
|
||||
* name stored in the JsName is equal to the (unmangled) specified originalName.
|
||||
*
|
||||
* @param ident An identifier that is unique within this scope.
|
||||
* @param shortIdent A "pretty" name that does not have to be unique.
|
||||
* @param originalName The original name in the source.
|
||||
* @throws IllegalArgumentException if ident already exists in this scope but
|
||||
* the requested short name does not match the existing short name,
|
||||
* or the original name does not match the existing original name.
|
||||
*/
|
||||
public JsName declareName(String ident, String shortIdent, String originalName) {
|
||||
JsName name = findExistingNameNoRecurse(ident);
|
||||
if (name != null) {
|
||||
if (!name.getShortIdent().equals(shortIdent)
|
||||
|| !nullableEquals(name.getOriginalName(), originalName)) {
|
||||
throw new IllegalArgumentException("Requested short name " + shortIdent
|
||||
+ " conflicts with preexisting short name " + name.getShortIdent() + " for identifier "
|
||||
+ ident);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return doCreateName(ident, shortIdent, originalName);
|
||||
}
|
||||
|
||||
boolean nullableEquals(String s1, String s2) {
|
||||
return (s1 == null) ? (s2 == null) : s1.equals(s2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public final JsName findExistingName(String ident) {
|
||||
JsName name = findExistingNameNoRecurse(ident);
|
||||
if (name == null && parent != null) {
|
||||
return parent.findExistingName(ident);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find an unobfuscatable 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
|
||||
*/
|
||||
public final JsName findExistingUnobfuscatableName(String ident) {
|
||||
JsName name = findExistingNameNoRecurse(ident);
|
||||
if (name != null && name.isObfuscatable()) {
|
||||
name = null;
|
||||
}
|
||||
if (name == null && parent != null) {
|
||||
return parent.findExistingUnobfuscatableName(ident);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for all the names defined by this scope.
|
||||
*/
|
||||
public Iterator<JsName> getAllNames() {
|
||||
return names.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of this scope's child scopes.
|
||||
*/
|
||||
public final List<JsScope> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent scope of this scope, or <code>null</code> if this is the
|
||||
* root scope.
|
||||
*/
|
||||
public final JsScope getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated program.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new name in this scope.
|
||||
*/
|
||||
protected JsName doCreateName(String ident, String shortIdent, String originalName) {
|
||||
JsName name = new JsName(this, ident, shortIdent, originalName);
|
||||
names = Maps.putOrdered(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
|
||||
*/
|
||||
public JsName findExistingNameNoRecurse(String ident) {
|
||||
return names.get(ident);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Checks whether this scope owns this name.
|
||||
*/
|
||||
public boolean ownsName(JsName name) {
|
||||
return names.containsValue(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* Abstract base class for JavaScript statement objects.
|
||||
*/
|
||||
public abstract class JsStatement extends JsNode {
|
||||
|
||||
protected JsStatement() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this statement definitely causes an abrupt change in flow
|
||||
* control.
|
||||
*/
|
||||
public boolean unconditionalControlBreak() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -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 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A member/case in a JavaScript switch object.
|
||||
*/
|
||||
public abstract class JsSwitchMember extends JsNode {
|
||||
|
||||
protected final List<JsStatement> stmts = new ArrayList<JsStatement>();
|
||||
|
||||
protected JsSwitchMember() {
|
||||
super();
|
||||
}
|
||||
|
||||
public List<JsStatement> getStmts() {
|
||||
return stmts;
|
||||
}
|
||||
}
|
||||
@@ -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>this</code> reference.
|
||||
*/
|
||||
public final class JsThisRef extends JsValueLiteral {
|
||||
|
||||
public JsThisRef() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanFalse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefinitelyNotNull() {
|
||||
/*
|
||||
* You'd think that you could get a null this via function.call/apply, but
|
||||
* in fact you can't: they just make this be the window object instead. So
|
||||
* it really can't ever be null.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
package com.google.dart.compiler.backend.js.ast;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>throw</code> statement.
|
||||
*/
|
||||
public class JsThrow extends JsStatement {
|
||||
|
||||
private JsExpression expr;
|
||||
|
||||
public JsThrow() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JsThrow(JsExpression expr) {
|
||||
super();
|
||||
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)) {
|
||||
expr = v.accept(expr);
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unconditionalControlBreak() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.THROW;
|
||||
}
|
||||
}
|
||||
@@ -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.backend.js.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>try</code> statement.
|
||||
*/
|
||||
public class JsTry extends JsStatement {
|
||||
|
||||
private final List<JsCatch> catches = new ArrayList<JsCatch>();
|
||||
private JsBlock finallyBlock;
|
||||
private JsBlock tryBlock;
|
||||
|
||||
public JsTry() {
|
||||
super();
|
||||
}
|
||||
|
||||
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 JsExpression {
|
||||
|
||||
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,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;
|
||||
|
||||
/**
|
||||
* 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,109 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A JavaScript <code>var</code> statement.
|
||||
*/
|
||||
public class JsVars extends JsStatement implements Iterable<JsVars.JsVar> {
|
||||
|
||||
/**
|
||||
* A var declared using the JavaScript <code>var</code> statement.
|
||||
*/
|
||||
public static class JsVar extends JsNode implements HasName {
|
||||
|
||||
private final JsName name;
|
||||
private JsExpression initExpr;
|
||||
|
||||
public JsVar(JsName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public JsVar(JsName name, JsExpression initExpr) {
|
||||
this.name = name;
|
||||
this.initExpr = initExpr;
|
||||
}
|
||||
|
||||
public JsExpression getInitExpr() {
|
||||
return initExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setInitExpr(JsExpression initExpr) {
|
||||
this.initExpr = initExpr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void traverse(JsVisitor v, JsContext ctx) {
|
||||
if (v.visit(this, ctx)) {
|
||||
if (initExpr != null) {
|
||||
initExpr = v.accept(initExpr);
|
||||
}
|
||||
}
|
||||
v.endVisit(this, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsVar setSourceRef(SourceInfo info) {
|
||||
super.setSourceRef(info);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeKind getKind() {
|
||||
return NodeKind.VAR;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<JsVar> vars = new ArrayList<JsVar>();
|
||||
|
||||
public JsVars() {
|
||||
}
|
||||
|
||||
public void add(JsVar var) {
|
||||
vars.add(var);
|
||||
}
|
||||
|
||||
public int getNumVars() {
|
||||
return vars.size();
|
||||
}
|
||||
|
||||
public void insert(JsVar var) {
|
||||
vars.add(var);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return vars.isEmpty();
|
||||
}
|
||||
|
||||
// Iterator returns JsVar objects
|
||||
@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,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;
|
||||
|
||||
/**
|
||||
* 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,430 @@
|
||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this 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 nodes that will visit child nodes.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
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.<T>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(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(JsThisRef x, JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(JsThrow x, JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(JsTry x, JsContext ctx) {
|
||||
}
|
||||
|
||||
public void endVisit(JsVars.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(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 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(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(JsVars.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);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user