Merge branch 'master' of ../jet-contrib
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
+16
@@ -0,0 +1,16 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="k2js:jar">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/k2js_jar</output-path>
|
||||
<root id="archive" name="k2js.jar">
|
||||
<element id="module-output" name="backend" />
|
||||
<element id="module-output" name="frontend" />
|
||||
<element id="module-output" name="frontend.java" />
|
||||
<element id="module-output" name="stdlib" />
|
||||
<element id="module-output" name="translator" />
|
||||
<element id="module-output" name="js" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/translator/lib/js.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/translator/lib/guava-10.0.1.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$PROJECT_DIR$/../../Kotlin/jet/lib/asm-util-3.3.1.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
Generated
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="?*.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
+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>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+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
+22
@@ -0,0 +1,22 @@
|
||||
<?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$/examplesForWebDemo/examplesForWebDemo.iml" filepath="$PROJECT_DIR$/examplesForWebDemo/examplesForWebDemo.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/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$/../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/js.iml" filepath="$PROJECT_DIR$/js/js.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jslib/jslib.iml" filepath="$PROJECT_DIR$/jslib/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$/translator/translator.iml" filepath="$PROJECT_DIR$/translator/translator.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/translatorTests/translatorTests.iml" filepath="$PROJECT_DIR$/translatorTests/translatorTests.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="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -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="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="jslib" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
{
|
||||
var classes = function () {
|
||||
var Vector = Kotlin.Class.create({initialize:function (x, y) {
|
||||
this.$x = x;
|
||||
this.$y = y;
|
||||
}, get_x:function () {
|
||||
return this.$x;
|
||||
}, get_y:function () {
|
||||
return this.$y;
|
||||
}, plus:function (v) {
|
||||
{
|
||||
return creatures.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y());
|
||||
}
|
||||
}, minus:function () {
|
||||
{
|
||||
return creatures.v_0(-this.get_x(), -this.get_y());
|
||||
}
|
||||
}, minus$0:function (v) {
|
||||
{
|
||||
return creatures.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y());
|
||||
}
|
||||
}, times:function (koef) {
|
||||
{
|
||||
return creatures.v_0(this.get_x() * koef, this.get_y() * koef);
|
||||
}
|
||||
}, distanceTo:function (v) {
|
||||
{
|
||||
return Math.sqrt(this.minus$0(v).get_sqr());
|
||||
}
|
||||
}, rotatedBy:function (theta) {
|
||||
{
|
||||
var sin = Math.sin(theta);
|
||||
var cos = Math.cos(theta);
|
||||
return creatures.v_0(this.get_x() * cos - this.get_y() * sin, this.get_x() * sin + this.get_y() * cos);
|
||||
}
|
||||
}, isInRect:function (topLeft, size) {
|
||||
{
|
||||
return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y();
|
||||
}
|
||||
}, get_sqr:function () {
|
||||
{
|
||||
return this.get_x() * this.get_x() + this.get_y() * this.get_y();
|
||||
}
|
||||
}, get_normalized:function () {
|
||||
{
|
||||
return this.times(1 / Math.sqrt(this.get_sqr()));
|
||||
}
|
||||
}
|
||||
});
|
||||
var RadialGradientGenerator = Kotlin.Class.create({initialize:function (context) {
|
||||
this.$context = context;
|
||||
this.$gradients = new Kotlin.ArrayList;
|
||||
this.$current = 0;
|
||||
{
|
||||
this.newColorStops([
|
||||
[0, '#F59898'],
|
||||
[0.5, '#F57373'],
|
||||
[1, '#DB6B6B']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0.39, 'rgb(140,167,209)'],
|
||||
[0.7, 'rgb(104,139,209)'],
|
||||
[0.85, 'rgb(67,122,217)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(255,222,255)'],
|
||||
[0.5, 'rgb(255,185,222)'],
|
||||
[1, 'rgb(230,154,185)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(255,209,114)'],
|
||||
[0.5, 'rgb(255,174,81)'],
|
||||
[1, 'rgb(241,145,54)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(132,240,135)'],
|
||||
[0.5, 'rgb(91,240,96)'],
|
||||
[1, 'rgb(27,245,41)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(250,147,250)'],
|
||||
[0.5, 'rgb(255,80,255)'],
|
||||
[1, 'rgb(250,0,217)']
|
||||
]);
|
||||
}
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_gradients:function () {
|
||||
return this.$gradients;
|
||||
}, get_current:function () {
|
||||
return this.$current;
|
||||
}, set_current:function (tmp$0) {
|
||||
this.$current = tmp$0;
|
||||
}, newColorStops:function (colorStops) {
|
||||
{
|
||||
this.get_gradients().add(colorStops);
|
||||
}
|
||||
}, getNext:function () {
|
||||
{
|
||||
var result = this.get_gradients().get(this.get_current());
|
||||
this.set_current((this.get_current() + 1) % this.get_gradients().size());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
var CanvasState = Kotlin.Class.create({initialize:function (canvas) {
|
||||
this.$canvas = canvas;
|
||||
this.$width = this.get_canvas().width;
|
||||
this.$height = this.get_canvas().height;
|
||||
this.$context = getContext();
|
||||
this.$valid = false;
|
||||
this.$shapes = new Kotlin.ArrayList;
|
||||
this.$selection = null;
|
||||
this.$dragOff = new creatures.Vector_0(0, 0);
|
||||
this.$interval = 1000 / 30;
|
||||
{
|
||||
var tmp$4;
|
||||
var tmp$3;
|
||||
var tmp$2;
|
||||
var tmp$1;
|
||||
var tmp$0_0;
|
||||
$(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) {
|
||||
{
|
||||
var tmp$0;
|
||||
tmp$0_0.set_valid(false);
|
||||
tmp$0_0.set_selection(null);
|
||||
var mousePos = tmp$0_0.mousePos_0(it);
|
||||
{
|
||||
tmp$0 = tmp$0_0.get_shapes().iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
if (shape.contains(mousePos)) {
|
||||
tmp$0_0.set_dragOff(mousePos.minus$0(shape.get_pos()));
|
||||
shape.set_selected(true);
|
||||
tmp$0_0.set_selection(shape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mousemove((tmp$1 = this , function (it) {
|
||||
{
|
||||
if (tmp$1.get_selection() != null) {
|
||||
Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus$0(tmp$1.get_dragOff()));
|
||||
tmp$1.set_valid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mouseup((tmp$2 = this , function (it) {
|
||||
{
|
||||
if (tmp$2.get_selection() != null) {
|
||||
Kotlin.sure(tmp$2.get_selection()).set_selected(false);
|
||||
}
|
||||
tmp$2.set_selection(null);
|
||||
tmp$2.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).dblclick((tmp$3 = this , function (it) {
|
||||
{
|
||||
var newCreature = new creatures.Creature_0(tmp$3.mousePos_0(it), tmp$3);
|
||||
tmp$3.addShape(newCreature);
|
||||
tmp$3.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
setInterval((tmp$4 = this , function () {
|
||||
{
|
||||
tmp$4.draw();
|
||||
}
|
||||
}
|
||||
), this.get_interval());
|
||||
}
|
||||
}, get_canvas:function () {
|
||||
return this.$canvas;
|
||||
}, get_width:function () {
|
||||
return this.$width;
|
||||
}, set_width:function (tmp$0) {
|
||||
this.$width = tmp$0;
|
||||
}, get_height:function () {
|
||||
return this.$height;
|
||||
}, set_height:function (tmp$0) {
|
||||
this.$height = tmp$0;
|
||||
}, get_size:function () {
|
||||
{
|
||||
return creatures.v_0(this.get_width(), this.get_height());
|
||||
}
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_valid:function () {
|
||||
return this.$valid;
|
||||
}, set_valid:function (tmp$0) {
|
||||
this.$valid = tmp$0;
|
||||
}, get_shapes:function () {
|
||||
return this.$shapes;
|
||||
}, set_shapes:function (tmp$0) {
|
||||
this.$shapes = tmp$0;
|
||||
}, get_selection:function () {
|
||||
return this.$selection;
|
||||
}, set_selection:function (tmp$0) {
|
||||
this.$selection = tmp$0;
|
||||
}, get_dragOff:function () {
|
||||
return this.$dragOff;
|
||||
}, set_dragOff:function (tmp$0) {
|
||||
this.$dragOff = tmp$0;
|
||||
}, get_interval:function () {
|
||||
return this.$interval;
|
||||
}, mousePos_0:function (e) {
|
||||
{
|
||||
var offset = new creatures.Vector_0(0, 0);
|
||||
var element = this.get_canvas();
|
||||
while (element != null) {
|
||||
var el = Kotlin.sure(element);
|
||||
offset = offset.plus(new creatures.Vector_0(el.offsetLeft, el.offsetTop));
|
||||
element = el.offsetParent;
|
||||
}
|
||||
return (new creatures.Vector_0(e.pageX, e.pageY)).minus$0(offset);
|
||||
}
|
||||
}, addShape:function (shape) {
|
||||
{
|
||||
this.get_shapes().add(shape);
|
||||
this.set_valid(false);
|
||||
}
|
||||
}, clear:function () {
|
||||
{
|
||||
this.get_context().fillStyle = '#FFFFFF';
|
||||
this.get_context().fillRect(0, 0, this.get_width(), this.get_height());
|
||||
this.get_context().strokeStyle = '#000000';
|
||||
this.get_context().lineWidth = 4;
|
||||
this.get_context().strokeRect(0, 0, this.get_width(), this.get_height());
|
||||
}
|
||||
}, draw:function () {
|
||||
{
|
||||
var tmp$0;
|
||||
if (this.get_valid())
|
||||
return;
|
||||
this.clear();
|
||||
{
|
||||
tmp$0 = creatures.reversed(this.get_shapes()).iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
shape.draw(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
creatures.get_Kotlin().draw(this);
|
||||
this.set_valid(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
var Shape = Kotlin.Class.create({initialize:function () {
|
||||
this.$selected = false;
|
||||
}, draw:function (state) {
|
||||
}, contains:function (mousePos) {
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_selected:function () {
|
||||
return this.$selected;
|
||||
}, set_selected:function (tmp$0) {
|
||||
this.$selected = tmp$0;
|
||||
}, shadowed:function (receiver, shadowOffset, alpha, render) {
|
||||
{
|
||||
receiver.save();
|
||||
receiver.shadowColor = 'rgba(100, 100, 100, ' + alpha + ')';
|
||||
receiver.shadowBlur = 5;
|
||||
receiver.shadowOffsetX = shadowOffset.get_x();
|
||||
receiver.shadowOffsetY = shadowOffset.get_y();
|
||||
render.call(receiver);
|
||||
receiver.restore();
|
||||
}
|
||||
}, fillPath:function (receiver, constructPath) {
|
||||
{
|
||||
receiver.beginPath();
|
||||
constructPath.call(receiver);
|
||||
receiver.closePath();
|
||||
receiver.fill();
|
||||
}
|
||||
}
|
||||
});
|
||||
var Creature = Kotlin.Class.create(Shape, {initialize:function (pos, state) {
|
||||
this.$pos = pos;
|
||||
this.$state = state;
|
||||
this.super_init();
|
||||
this.$shadowOffset = creatures.v_0(-5, 5);
|
||||
this.$colorStops = creatures.get_gradientGenerator().getNext();
|
||||
this.$relSize = 0.05;
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_state:function () {
|
||||
return this.$state;
|
||||
}, get_shadowOffset:function () {
|
||||
return this.$shadowOffset;
|
||||
}, get_colorStops:function () {
|
||||
return this.$colorStops;
|
||||
}, get_relSize:function () {
|
||||
return this.$relSize;
|
||||
}, get_radius:function () {
|
||||
{
|
||||
return this.get_state().get_width() * this.get_relSize();
|
||||
}
|
||||
}, get_position:function () {
|
||||
var tmp$0;
|
||||
if (this.get_selected())
|
||||
tmp$0 = this.get_pos().minus$0(this.get_shadowOffset());
|
||||
else
|
||||
tmp$0 = this.get_pos();
|
||||
{
|
||||
return tmp$0;
|
||||
}
|
||||
}, get_directionToLogo:function () {
|
||||
{
|
||||
return creatures.get_Kotlin().get_centre().minus$0(this.get_position()).get_normalized();
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return this.get_pos().distanceTo(mousePos) < this.get_radius();
|
||||
}
|
||||
}, circlePath:function (receiver, position, rad) {
|
||||
{
|
||||
receiver.arc(position.get_x(), position.get_y(), rad, 0, 2 * Math.PI, false);
|
||||
}
|
||||
}, fillCircle:function (receiver, position, rad) {
|
||||
{
|
||||
var tmp$0;
|
||||
this.fillPath(receiver, (tmp$0 = this , function () {
|
||||
{
|
||||
tmp$0.circlePath(receiver, position, rad);
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
if (!this.get_selected()) {
|
||||
this.drawCreature(context);
|
||||
}
|
||||
else {
|
||||
this.drawCreatureWithShadow(context);
|
||||
}
|
||||
}
|
||||
}, drawCreature:function (context) {
|
||||
{
|
||||
var tmp$0;
|
||||
context.fillStyle = this.getGradient(context);
|
||||
this.fillPath(context, (tmp$0 = this , function () {
|
||||
{
|
||||
tmp$0.tailPath(context);
|
||||
tmp$0.circlePath(this, tmp$0.get_position(), tmp$0.get_radius());
|
||||
}
|
||||
}
|
||||
));
|
||||
this.drawEye(context);
|
||||
}
|
||||
}, getGradient:function (context) {
|
||||
{
|
||||
var tmp$0;
|
||||
var gradientCentre = this.get_position().plus(this.get_directionToLogo().times(this.get_radius() / 4));
|
||||
var gradient = context.createRadialGradient(gradientCentre.get_x(), gradientCentre.get_y(), 1, gradientCentre.get_x(), gradientCentre.get_y(), 2 * this.get_radius());
|
||||
{
|
||||
tmp$0 = Kotlin.arrayIterator(this.get_colorStops());
|
||||
while (tmp$0.hasNext()) {
|
||||
var colorStop = tmp$0.next();
|
||||
{
|
||||
gradient.addColorStop(colorStop[0], colorStop[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return gradient;
|
||||
}
|
||||
}, tailPath:function (context) {
|
||||
{
|
||||
var tailDirection = this.get_directionToLogo().minus();
|
||||
var tailPos = this.get_position().plus(tailDirection.times(this.get_radius()).times(1));
|
||||
var tailSize = this.get_radius() * 1.6;
|
||||
var angle = Math.PI / 6;
|
||||
var p1 = tailPos.plus(tailDirection.rotatedBy(angle).times(tailSize));
|
||||
var p2 = tailPos.plus(tailDirection.rotatedBy(-angle).times(tailSize));
|
||||
var middlePoint = this.get_position().plus(tailDirection.times(this.get_radius()).times(1));
|
||||
context.moveTo(tailPos.get_x(), tailPos.get_y());
|
||||
context.lineTo(p1.get_x(), p1.get_y());
|
||||
context.quadraticCurveTo(middlePoint.get_x(), middlePoint.get_y(), p2.get_x(), p2.get_y());
|
||||
context.lineTo(tailPos.get_x(), tailPos.get_y());
|
||||
}
|
||||
}, drawEye:function (context) {
|
||||
{
|
||||
var eyePos = this.get_directionToLogo().times(this.get_radius()).times(0.6).plus(this.get_position());
|
||||
var eyeRadius = this.get_radius() / 3;
|
||||
var eyeLidRadius = eyeRadius / 2;
|
||||
context.fillStyle = '#FFFFFF';
|
||||
this.fillCircle(context, eyePos, eyeRadius);
|
||||
context.fillStyle = '#000000';
|
||||
this.fillCircle(context, eyePos, eyeLidRadius);
|
||||
}
|
||||
}, drawCreatureWithShadow:function (context) {
|
||||
{
|
||||
var tmp$0_0;
|
||||
this.shadowed(context, this.get_shadowOffset(), 0.7, (tmp$0_0 = this , function () {
|
||||
{
|
||||
var tmp$0;
|
||||
context.fillStyle = tmp$0_0.getGradient(context);
|
||||
tmp$0_0.fillPath(this, (tmp$0 = tmp$0_0 , function () {
|
||||
{
|
||||
tmp$0.tailPath(context);
|
||||
tmp$0.circlePath(context, tmp$0.get_position(), tmp$0.get_radius());
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
));
|
||||
this.drawEye(context);
|
||||
}
|
||||
}
|
||||
});
|
||||
var Logo = Kotlin.Class.create(Shape, {initialize:function (pos) {
|
||||
this.$pos = pos;
|
||||
this.super_init();
|
||||
this.$relSize = 0.25;
|
||||
this.$shadowOffset = creatures.v_0(-3, 3);
|
||||
this.$imageSize = creatures.v_0(377, 393);
|
||||
this.$size = this.get_imageSize().times(this.get_relSize());
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_relSize:function () {
|
||||
return this.$relSize;
|
||||
}, get_shadowOffset:function () {
|
||||
return this.$shadowOffset;
|
||||
}, get_imageSize:function () {
|
||||
return this.$imageSize;
|
||||
}, get_size:function () {
|
||||
return this.$size;
|
||||
}, set_size:function (tmp$0) {
|
||||
this.$size = tmp$0;
|
||||
}, get_position:function () {
|
||||
var tmp$0;
|
||||
if (this.get_selected())
|
||||
tmp$0 = this.get_pos().minus$0(this.get_shadowOffset());
|
||||
else
|
||||
tmp$0 = this.get_pos();
|
||||
{
|
||||
return tmp$0;
|
||||
}
|
||||
}, drawLogo:function (state) {
|
||||
{
|
||||
this.set_size(this.get_imageSize().times(state.get_size().get_x() / this.get_imageSize().get_x()).times(this.get_relSize()));
|
||||
state.get_context().drawImage(getKotlinLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_position().get_x(), this.get_position().get_y(), this.get_size().get_x(), this.get_size().get_y());
|
||||
}
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
if (this.get_selected()) {
|
||||
var tmp$0;
|
||||
this.shadowed(context, this.get_shadowOffset(), 0.2, (tmp$0 = this , function () {
|
||||
{
|
||||
tmp$0.drawLogo(state);
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
else {
|
||||
this.drawLogo(state);
|
||||
}
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return mousePos.isInRect(this.get_pos(), this.get_size());
|
||||
}
|
||||
}, get_centre:function () {
|
||||
{
|
||||
return this.get_pos().plus(this.get_size().times(0.5));
|
||||
}
|
||||
}
|
||||
});
|
||||
return {Shape_0:Shape, Logo_0:Logo, Creature_0:Creature, RadialGradientGenerator_0:RadialGradientGenerator, CanvasState_0:CanvasState, Vector_0:Vector};
|
||||
}
|
||||
();
|
||||
var creatures = Kotlin.Namespace.create({initialize:function () {
|
||||
creatures.$Kotlin = new creatures.Logo_0(creatures.v_0(300, 100));
|
||||
creatures.$gradientGenerator = new creatures.RadialGradientGenerator_0(getContext());
|
||||
}, get_Kotlin:function () {
|
||||
return creatures.$Kotlin;
|
||||
}, get_gradientGenerator:function () {
|
||||
return creatures.$gradientGenerator;
|
||||
}, v_0:function (x, y) {
|
||||
{
|
||||
return new creatures.Vector_0(x, y);
|
||||
}
|
||||
}, main:function () {
|
||||
{
|
||||
var state = new creatures.CanvasState_0(getCanvas());
|
||||
state.addShape(creatures.get_Kotlin());
|
||||
state.addShape(new creatures.Creature_0(state.get_size().times(0.25), state));
|
||||
state.addShape(new creatures.Creature_0(state.get_size().times(0.75), state));
|
||||
setTimeout(function () {
|
||||
{
|
||||
state.set_valid(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}, reversed:function (receiver) {
|
||||
{
|
||||
var result = new Kotlin.ArrayList;
|
||||
var i = receiver.size();
|
||||
while (i > 0) {
|
||||
result.add(receiver.get(--i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}, classes);
|
||||
creatures.initialize();
|
||||
}
|
||||
|
||||
var args = [];
|
||||
creatures.main(args);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
In this example strange creatures are watching the kotlin logo. You can drag'n'drop them as well as the logo.
|
||||
Doubleclick to add more creatures but be careful. They may be watching you!
|
||||
*/
|
||||
package creatures
|
||||
// importing some of the API defined
|
||||
import jquery.*
|
||||
import html5.*
|
||||
import java.util.ArrayList
|
||||
import js.*
|
||||
import js.Math
|
||||
import js.setInterval
|
||||
import html5.getCanvas
|
||||
import html5.getKotlinLogo
|
||||
import jquery.jq
|
||||
import js.setTimeout
|
||||
import java.util.List
|
||||
|
||||
|
||||
abstract class Shape() {
|
||||
|
||||
abstract fun draw(state : CanvasState)
|
||||
// these two abstract methods defines that our shapes can be dragged
|
||||
abstract fun contains(mousePos : Vector) : Boolean
|
||||
abstract var pos : Vector
|
||||
|
||||
var selected : Boolean = false
|
||||
|
||||
// a couple of helper extension methods we'll be using in the derived classes
|
||||
fun Context.shadowed(shadowOffset : Vector, alpha : Double, render : Context.() -> Unit) {
|
||||
save()
|
||||
shadowColor = "rgba(100, 100, 100, $alpha)"
|
||||
shadowBlur = 5.0
|
||||
shadowOffsetX = shadowOffset.x
|
||||
shadowOffsetY = shadowOffset.y
|
||||
render()
|
||||
restore()
|
||||
}
|
||||
|
||||
fun Context.fillPath(constructPath : Context.() -> Unit) {
|
||||
beginPath()
|
||||
constructPath()
|
||||
closePath()
|
||||
fill()
|
||||
}
|
||||
}
|
||||
|
||||
val Kotlin = Logo(v(300.0, 100.0))
|
||||
|
||||
class Logo(override var pos : Vector) : Shape()
|
||||
{
|
||||
val relSize : Double = 0.25
|
||||
val shadowOffset = v(-3.0, 3.0)
|
||||
val imageSize = v(377.0, 393.0)
|
||||
var size : Vector = imageSize * relSize
|
||||
// get-only properties like this saves you lots of typing and are very expressive
|
||||
val position : Vector
|
||||
get() = if (selected) pos - shadowOffset else pos
|
||||
|
||||
|
||||
fun drawLogo(state : CanvasState) {
|
||||
size = imageSize * (state.size.x / imageSize.x) * relSize
|
||||
// getKotlinLogo() is a 'magic' function here defined only for purposes of demonstration but in fact it just find an element containing the logo
|
||||
state.context.drawImage(getKotlinLogo(), 0.0, 0.0, imageSize.x, imageSize.y, position.x, position.y, size.x, size.y)
|
||||
}
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context
|
||||
if (selected) {
|
||||
// using helper we defined in Shape class
|
||||
context.shadowed(shadowOffset, 0.2) {
|
||||
drawLogo(state)
|
||||
}
|
||||
} else {
|
||||
drawLogo(state)
|
||||
}
|
||||
}
|
||||
|
||||
override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, size)
|
||||
|
||||
val centre : Vector
|
||||
get() = pos + size * 0.5
|
||||
}
|
||||
|
||||
val gradientGenerator = RadialGradientGenerator(getContext())
|
||||
|
||||
class Creature(override var pos : Vector, val state : CanvasState) : Shape() {
|
||||
|
||||
val shadowOffset = v(-5.0, 5.0)
|
||||
val colorStops = gradientGenerator.getNext()
|
||||
val relSize = 0.05
|
||||
// these properties have no backing fields and in java/javascript they could be represented as little helper functions
|
||||
val radius : Double
|
||||
get() = state.width * relSize
|
||||
val position : Vector
|
||||
get() = if (selected) pos - shadowOffset else pos
|
||||
val directionToLogo : Vector
|
||||
get() = (Kotlin.centre - position).normalized
|
||||
|
||||
//notice how the infix call can make some expressions extremely expressive
|
||||
override fun contains(mousePos : Vector) = pos distanceTo mousePos < radius
|
||||
|
||||
// defining more nice extension functions
|
||||
fun Context.circlePath(position : Vector, rad : Double) {
|
||||
arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false)
|
||||
}
|
||||
|
||||
//notice we can use an extension function we just defined inside another extension function
|
||||
fun Context.fillCircle(position : Vector, rad : Double) {
|
||||
fillPath {
|
||||
circlePath(position, rad)
|
||||
}
|
||||
}
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context
|
||||
if (!selected) {
|
||||
drawCreature(context)
|
||||
} else {
|
||||
drawCreatureWithShadow(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun drawCreature(context : Context) {
|
||||
context.fillStyle = getGradient(context)
|
||||
context.fillPath {
|
||||
tailPath(context)
|
||||
circlePath(position, radius)
|
||||
}
|
||||
drawEye(context)
|
||||
}
|
||||
|
||||
fun getGradient(context : Context) : CanvasGradient {
|
||||
val gradientCentre = position + directionToLogo * (radius / 4)
|
||||
val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius)
|
||||
for (colorStop in colorStops) {
|
||||
gradient.addColorStop(colorStop._1, colorStop._2)
|
||||
}
|
||||
return gradient
|
||||
}
|
||||
|
||||
fun tailPath(context : Context) {
|
||||
val tailDirection = -directionToLogo
|
||||
val tailPos = position + tailDirection * radius * 1.0
|
||||
val tailSize = radius * 1.6
|
||||
val angle = Math.PI / 6.0
|
||||
val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize
|
||||
val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize
|
||||
val middlePoint = position + tailDirection * radius * 1.0
|
||||
context.moveTo(tailPos.x, tailPos.y)
|
||||
context.lineTo(p1.x, p1.y)
|
||||
context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y)
|
||||
context.lineTo(tailPos.x, tailPos.y)
|
||||
}
|
||||
|
||||
fun drawEye(context : Context) {
|
||||
val eyePos = directionToLogo * radius * 0.6 + position
|
||||
val eyeRadius = radius / 3
|
||||
val eyeLidRadius = eyeRadius / 2
|
||||
context.fillStyle = "#FFFFFF"
|
||||
context.fillCircle(eyePos, eyeRadius)
|
||||
context.fillStyle = "#000000"
|
||||
context.fillCircle(eyePos, eyeLidRadius)
|
||||
}
|
||||
|
||||
fun drawCreatureWithShadow(context : Context) {
|
||||
context.shadowed(shadowOffset, 0.7) {
|
||||
context.fillStyle = getGradient(context)
|
||||
fillPath {
|
||||
tailPath(context)
|
||||
context.circlePath(position, radius)
|
||||
}
|
||||
}
|
||||
drawEye(context)
|
||||
}
|
||||
}
|
||||
|
||||
class CanvasState(val canvas : Canvas) {
|
||||
var width = canvas.width
|
||||
var height = canvas.height
|
||||
val size : Vector
|
||||
get() = v(width, height)
|
||||
val context = getContext()
|
||||
var valid = false
|
||||
var shapes = ArrayList<Shape>()
|
||||
var selection : Shape? = null
|
||||
var dragOff = Vector()
|
||||
val interval = 1000 / 30
|
||||
|
||||
{
|
||||
jq(canvas).mousedown {
|
||||
valid = false
|
||||
selection = null
|
||||
val mousePos = mousePos(it)
|
||||
for (shape in shapes) {
|
||||
if (mousePos in shape) {
|
||||
dragOff = mousePos - shape.pos
|
||||
shape.selected = true
|
||||
selection = shape
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mousemove {
|
||||
if (selection != null) {
|
||||
selection.sure().pos = mousePos(it) - dragOff
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mouseup {
|
||||
if (selection != null) {
|
||||
selection.sure().selected = false
|
||||
}
|
||||
selection = null
|
||||
valid = false
|
||||
}
|
||||
|
||||
jq(canvas).dblclick {
|
||||
val newCreature = Creature(mousePos(it), this @CanvasState)
|
||||
addShape(newCreature)
|
||||
valid = false
|
||||
}
|
||||
|
||||
setInterval({
|
||||
draw()
|
||||
}, interval)
|
||||
}
|
||||
|
||||
fun mousePos(e : MouseEvent) : Vector {
|
||||
var offset = Vector()
|
||||
var element : DomElement? = canvas
|
||||
while (element != null) {
|
||||
val el : DomElement = element.sure()
|
||||
offset += Vector(el.offsetLeft, el.offsetTop)
|
||||
element = el.offsetParent
|
||||
}
|
||||
return Vector(e.pageX, e.pageY) - offset
|
||||
}
|
||||
|
||||
fun addShape(shape : Shape) {
|
||||
shapes.add(shape)
|
||||
valid = false
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
context.fillStyle = "#FFFFFF"
|
||||
context.fillRect(0.0, 0.0, width, height)
|
||||
context.strokeStyle = "#000000"
|
||||
context.lineWidth = 4.0
|
||||
context.strokeRect(0.0, 0.0, width, height)
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
if (valid) return
|
||||
|
||||
clear()
|
||||
for (shape in shapes.reversed()) {
|
||||
shape.draw(this)
|
||||
}
|
||||
Kotlin.draw(this)
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
|
||||
class RadialGradientGenerator(val context : Context) {
|
||||
val gradients = ArrayList<Array<#(Double, String)>>()
|
||||
var current = 0
|
||||
|
||||
fun newColorStops(vararg colorStops : #(Double, String)) {
|
||||
gradients.add(colorStops)
|
||||
}
|
||||
|
||||
{
|
||||
newColorStops(#(0.0, "#F59898"), #(0.5, "#F57373"), #(1.0, "#DB6B6B"))
|
||||
newColorStops(#(0.39, "rgb(140,167,209)"), #(0.7, "rgb(104,139,209)"), #(0.85, "rgb(67,122,217)"))
|
||||
newColorStops(#(0.0, "rgb(255,222,255)"), #(0.5, "rgb(255,185,222)"), #(1.0, "rgb(230,154,185)"))
|
||||
newColorStops(#(0.0, "rgb(255,209,114)"), #(0.5, "rgb(255,174,81)"), #(1.0, "rgb(241,145,54)"))
|
||||
newColorStops(#(0.0, "rgb(132,240,135)"), #(0.5, "rgb(91,240,96)"), #(1.0, "rgb(27,245,41)"))
|
||||
newColorStops(#(0.0, "rgb(250,147,250)"), #(0.5, "rgb(255,80,255)"), #(1.0, "rgb(250,0,217)"))
|
||||
}
|
||||
|
||||
fun getNext() : Array<#(Double, String)> {
|
||||
val result = gradients.get(current)
|
||||
current = (current + 1) % gradients.size()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun v(x : Double, y : Double) = Vector(x, y)
|
||||
|
||||
class Vector(val x : Double = 0.0, val y : Double = 0.0) {
|
||||
fun plus(v : Vector) = v(x + v.x, y + v.y)
|
||||
fun minus() = v(-x, -y)
|
||||
fun minus(v : Vector) = v(x - v.x, y - v.y)
|
||||
fun times(koef : Double) = v(x * koef, y * koef)
|
||||
fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr)
|
||||
fun rotatedBy(theta : Double) : Vector {
|
||||
val sin = Math.sin(theta)
|
||||
val cos = Math.cos(theta)
|
||||
return v(x * cos - y * sin, x * sin + y * cos)
|
||||
}
|
||||
|
||||
fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
|
||||
(y >= topLeft.y) && (y <= topLeft.y + size.y)
|
||||
|
||||
val sqr : Double
|
||||
get() = x * x + y * y
|
||||
val normalized : Vector
|
||||
get() = this * (1.0 / Math.sqrt(sqr))
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val state = CanvasState(getCanvas())
|
||||
state.addShape(Kotlin)
|
||||
state.addShape(Creature(state.size * 0.25, state))
|
||||
state.addShape(Creature(state.size * 0.75, state))
|
||||
setTimeout({
|
||||
state.valid = false
|
||||
})
|
||||
}
|
||||
|
||||
fun <T> List<T>.reversed() : List<T> {
|
||||
val result = ArrayList<T>()
|
||||
var i = size()
|
||||
while (i > 0) {
|
||||
result.add(get(--i))
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
|
||||
|
||||
<canvas width="600" height="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../../../translator/testFiles/kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../../../translator/testFiles/canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="creatures.js" type="text/javascript"></script>
|
||||
<img src="kotlinlogo.png" hidden=true/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
{
|
||||
var classes = function () {
|
||||
var FancyLines = Kotlin.Class.create({initialize:function () {
|
||||
this.$context = getContext();
|
||||
this.$height = getCanvas().height;
|
||||
this.$width = getCanvas().width;
|
||||
this.$x = this.get_width() * Math.random();
|
||||
this.$y = this.get_height() * Math.random();
|
||||
this.$hue = 0;
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_height:function () {
|
||||
return this.$height;
|
||||
}, get_width:function () {
|
||||
return this.$width;
|
||||
}, get_x:function () {
|
||||
return this.$x;
|
||||
}, set_x:function (tmp$0) {
|
||||
this.$x = tmp$0;
|
||||
}, get_y:function () {
|
||||
return this.$y;
|
||||
}, set_y:function (tmp$0) {
|
||||
this.$y = tmp$0;
|
||||
}, get_hue:function () {
|
||||
return this.$hue;
|
||||
}, set_hue:function (tmp$0) {
|
||||
this.$hue = tmp$0;
|
||||
}, line:function () {
|
||||
{
|
||||
this.get_context().save();
|
||||
this.get_context().beginPath();
|
||||
this.get_context().lineWidth = 20 * Math.random();
|
||||
this.get_context().moveTo(this.get_x(), this.get_y());
|
||||
this.set_x(this.get_width() * Math.random());
|
||||
this.set_y(this.get_height() * Math.random());
|
||||
this.get_context().bezierCurveTo(this.get_width() * Math.random(), this.get_height() * Math.random(), this.get_width() * Math.random(), this.get_height() * Math.random(), this.get_x(), this.get_y());
|
||||
this.set_hue(this.get_hue() + Math.random() * 10);
|
||||
this.get_context().strokeStyle = 'hsl(' + this.get_hue() + ', 50%, 50%)';
|
||||
this.get_context().shadowColor = 'white';
|
||||
this.get_context().shadowBlur = 10;
|
||||
this.get_context().stroke();
|
||||
this.get_context().restore();
|
||||
}
|
||||
}, blank:function () {
|
||||
{
|
||||
this.get_context().fillStyle = 'rgba(255,255,1,0.1)';
|
||||
this.get_context().fillRect(0, 0, this.get_width(), this.get_height());
|
||||
}
|
||||
}, run:function () {
|
||||
{
|
||||
var tmp$1;
|
||||
var tmp$0;
|
||||
setInterval((tmp$0 = this , function () {
|
||||
{
|
||||
tmp$0.line();
|
||||
}
|
||||
}
|
||||
), 40);
|
||||
setInterval((tmp$1 = this , function () {
|
||||
{
|
||||
tmp$1.blank();
|
||||
}
|
||||
}
|
||||
), 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
return {FancyLines_0:FancyLines};
|
||||
}
|
||||
();
|
||||
var fancylines = Kotlin.Namespace.create({initialize:function () {
|
||||
}, main:function () {
|
||||
{
|
||||
$(function () {
|
||||
{
|
||||
(new fancylines.FancyLines_0).run();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}, classes);
|
||||
fancylines.initialize();
|
||||
}
|
||||
|
||||
var args = [];
|
||||
fancylines.main(args);
|
||||
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas height="450" width="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../../../translator/testFiles/kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../../../translator/testFiles/canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="fancylines.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
This example is based on example from html5 canvas2D docs:
|
||||
http://www.w3.org/TR/2dcontext/
|
||||
Note that only a subset of the api is supported for now.
|
||||
*/
|
||||
|
||||
package fancylines
|
||||
|
||||
import js.*;
|
||||
import html5.*;
|
||||
import jquery.*;
|
||||
|
||||
fun main() {
|
||||
//jq is a name for JQuery function
|
||||
jq {
|
||||
FancyLines().run();
|
||||
}
|
||||
}
|
||||
|
||||
class FancyLines() {
|
||||
// we use two 'magic' functions here getContext() and getCanvas()
|
||||
val context = getContext();
|
||||
val height = getCanvas().height;
|
||||
val width = getCanvas().width;
|
||||
var x = width * Math.random();
|
||||
var y = height * Math.random();
|
||||
var hue = 0;
|
||||
|
||||
fun line() {
|
||||
context.save();
|
||||
|
||||
context.beginPath();
|
||||
|
||||
context.lineWidth = 20.0 * Math.random();
|
||||
context.moveTo(x, y);
|
||||
|
||||
x = width * Math.random();
|
||||
y = height * Math.random();
|
||||
|
||||
context.bezierCurveTo(width * Math.random(), height * Math.random(),
|
||||
width * Math.random(), height * Math.random(), x, y);
|
||||
|
||||
hue += Math.random() * 10;
|
||||
|
||||
context.strokeStyle = "hsl($hue, 50%, 50%)";
|
||||
|
||||
context.shadowColor = "white";
|
||||
context.shadowBlur = 10.0;
|
||||
|
||||
context.stroke();
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
fun blank() {
|
||||
context.fillStyle = "rgba(255,255,1,0.1)";
|
||||
context.fillRect(0.0, 0.0, width, height);
|
||||
}
|
||||
|
||||
fun run() {
|
||||
setInterval({line()}, 40);
|
||||
setInterval({blank()}, 100);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
{
|
||||
var classes = function () {
|
||||
var HelloKotlin = Kotlin.Class.create({initialize:function () {
|
||||
this.$relX = 0.2 + 0.2 * Math.random();
|
||||
this.$relY = 0.4 + 0.2 * Math.random();
|
||||
this.$relXVelocity = this.randomVelocity();
|
||||
this.$relYVelocity = this.randomVelocity();
|
||||
this.$message = 'Hello, Kotlin!';
|
||||
this.$textHeightInPixels = 60;
|
||||
{
|
||||
hello.get_context().font = 'bold ' + this.get_textHeightInPixels() + 'px Georgia, serif';
|
||||
}
|
||||
this.$textWidthInPixels = hello.get_context().measureText(this.get_message()).width;
|
||||
}, get_relX:function () {
|
||||
return this.$relX;
|
||||
}, set_relX:function (tmp$0) {
|
||||
this.$relX = tmp$0;
|
||||
}, get_relY:function () {
|
||||
return this.$relY;
|
||||
}, set_relY:function (tmp$0) {
|
||||
this.$relY = tmp$0;
|
||||
}, get_absX:function () {
|
||||
{
|
||||
return this.get_relX() * hello.get_width();
|
||||
}
|
||||
}, get_absY:function () {
|
||||
{
|
||||
return this.get_relY() * hello.get_height();
|
||||
}
|
||||
}, get_relXVelocity:function () {
|
||||
return this.$relXVelocity;
|
||||
}, set_relXVelocity:function (tmp$0) {
|
||||
this.$relXVelocity = tmp$0;
|
||||
}, get_relYVelocity:function () {
|
||||
return this.$relYVelocity;
|
||||
}, set_relYVelocity:function (tmp$0) {
|
||||
this.$relYVelocity = tmp$0;
|
||||
}, get_message:function () {
|
||||
return this.$message;
|
||||
}, get_textHeightInPixels:function () {
|
||||
return this.$textHeightInPixels;
|
||||
}, get_textWidthInPixels:function () {
|
||||
return this.$textWidthInPixels;
|
||||
}, draw:function () {
|
||||
{
|
||||
hello.get_context().save();
|
||||
this.move();
|
||||
hello.get_context().shadowColor = '#000000';
|
||||
hello.get_context().shadowBlur = 5;
|
||||
hello.get_context().shadowOffsetX = -4;
|
||||
hello.get_context().shadowOffsetY = 4;
|
||||
hello.get_context().fillStyle = 'rgb(242,160,110)';
|
||||
hello.get_context().fillText(this.get_message(), this.get_absX(), this.get_absY());
|
||||
hello.get_context().restore();
|
||||
}
|
||||
}, move:function () {
|
||||
{
|
||||
var relTextWidth = this.get_textWidthInPixels() / hello.get_width();
|
||||
if (this.get_relX() > 1 - relTextWidth - this.get_abs(this.get_relXVelocity()) || this.get_relX() < this.get_abs(this.get_relXVelocity())) {
|
||||
this.set_relXVelocity(this.get_relXVelocity() * -1);
|
||||
}
|
||||
var relTextHeight = this.get_textHeightInPixels() / hello.get_height();
|
||||
if (this.get_relY() > 1 - this.get_abs(this.get_relYVelocity()) || this.get_relY() < this.get_abs(this.get_relYVelocity()) + relTextHeight) {
|
||||
this.set_relYVelocity(this.get_relYVelocity() * -1);
|
||||
}
|
||||
this.set_relX(this.get_relX() + this.get_relXVelocity());
|
||||
this.set_relY(this.get_relY() + this.get_relYVelocity());
|
||||
}
|
||||
}, randomVelocity:function () {
|
||||
var tmp$0;
|
||||
if (Math.random() < 0.5)
|
||||
tmp$0 = 1;
|
||||
else
|
||||
tmp$0 = -1;
|
||||
{
|
||||
return 0.03 * Math.random() * tmp$0;
|
||||
}
|
||||
}, get_abs:function (receiver) {
|
||||
var tmp$0;
|
||||
if (receiver > 0)
|
||||
tmp$0 = receiver;
|
||||
else
|
||||
tmp$0 = -receiver;
|
||||
{
|
||||
return tmp$0;
|
||||
}
|
||||
}
|
||||
});
|
||||
return {HelloKotlin_0:HelloKotlin};
|
||||
}
|
||||
();
|
||||
var hello = Kotlin.Namespace.create({initialize:function () {
|
||||
hello.$context = getContext();
|
||||
hello.$height = getCanvas().height;
|
||||
hello.$width = getCanvas().width;
|
||||
}, get_context:function () {
|
||||
return hello.$context;
|
||||
}, get_height:function () {
|
||||
return hello.$height;
|
||||
}, get_width:function () {
|
||||
return hello.$width;
|
||||
}, renderBackground:function () {
|
||||
{
|
||||
hello.get_context().save();
|
||||
hello.get_context().fillStyle = '#5C7EED';
|
||||
hello.get_context().fillRect(0, 0, hello.get_width(), hello.get_height());
|
||||
hello.get_context().restore();
|
||||
}
|
||||
}, main:function () {
|
||||
{
|
||||
var interval = 50;
|
||||
var logos = Kotlin.arrayFromFun(3, function (it) {
|
||||
{
|
||||
return new hello.HelloKotlin_0;
|
||||
}
|
||||
}
|
||||
);
|
||||
$(function () {
|
||||
{
|
||||
setInterval(function () {
|
||||
{
|
||||
var tmp$0;
|
||||
hello.renderBackground();
|
||||
{
|
||||
tmp$0 = Kotlin.arrayIterator(logos);
|
||||
while (tmp$0.hasNext()) {
|
||||
var logo = tmp$0.next();
|
||||
{
|
||||
logo.draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, interval);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}, classes);
|
||||
hello.initialize();
|
||||
}
|
||||
|
||||
var args = [];
|
||||
hello.main(args);
|
||||
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas height="450" width="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../../../translator/testFiles/kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../../../translator/testFiles/canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="hello.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
This example is just simple text floating around. If u are using chrome, there is a bug that spoil the visuals.
|
||||
*/
|
||||
package hello
|
||||
|
||||
import js.*
|
||||
import html5.*
|
||||
import jquery.*
|
||||
|
||||
val context = getContext()
|
||||
val height = getCanvas().height
|
||||
val width = getCanvas().width
|
||||
|
||||
// class representing a floating text
|
||||
class HelloKotlin() {
|
||||
var relX = 0.2 + 0.2 * Math.random()
|
||||
var relY = 0.4 + 0.2 * Math.random()
|
||||
|
||||
val absX : Double
|
||||
get() = (relX * width)
|
||||
val absY : Double
|
||||
get() = (relY * height)
|
||||
|
||||
var relXVelocity = randomVelocity()
|
||||
var relYVelocity = randomVelocity()
|
||||
|
||||
|
||||
val message = "Hello, Kotlin!"
|
||||
val textHeightInPixels = 60
|
||||
{
|
||||
context.font = "bold ${textHeightInPixels}px Georgia, serif"
|
||||
}
|
||||
val textWidthInPixels = context.measureText(message).width
|
||||
|
||||
fun draw() {
|
||||
context.save()
|
||||
move()
|
||||
// if you using chrome chances are good you wont see the shadow
|
||||
context.shadowColor = "#000000"
|
||||
context.shadowBlur = 5.0
|
||||
context.shadowOffsetX = -4.0
|
||||
context.shadowOffsetY = 4.0
|
||||
context.fillStyle = "rgb(242,160,110)"
|
||||
context.fillText(message, absX, absY)
|
||||
context.restore()
|
||||
}
|
||||
|
||||
fun move() {
|
||||
val relTextWidth = textWidthInPixels / width
|
||||
if (relX > (1.0 - relTextWidth - relXVelocity.abs) || relX < relXVelocity.abs) {
|
||||
relXVelocity *= -1
|
||||
}
|
||||
val relTextHeight = textHeightInPixels / height
|
||||
if (relY > (1.0 - relYVelocity.abs) || relY < relYVelocity.abs + relTextHeight) {
|
||||
relYVelocity *= -1
|
||||
}
|
||||
relX += relXVelocity
|
||||
relY += relYVelocity
|
||||
}
|
||||
|
||||
fun randomVelocity() = 0.03 * Math.random() * (if (Math.random() < 0.5) 1 else -1)
|
||||
|
||||
|
||||
val Double.abs : Double
|
||||
get() = if (this > 0) this else -this
|
||||
}
|
||||
|
||||
fun renderBackground() {
|
||||
context.save()
|
||||
context.fillStyle = "#5C7EED"
|
||||
context.fillRect(0.0, 0.0, width, height)
|
||||
context.restore()
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val interval = 50
|
||||
// we pass a literal that constructs a new HelloKotlin object
|
||||
val logos = Array(3) {
|
||||
HelloKotlin()
|
||||
}
|
||||
jq {
|
||||
setInterval({
|
||||
renderBackground()
|
||||
for (logo in logos) {
|
||||
logo.draw()
|
||||
}
|
||||
}, interval)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
{
|
||||
var classes = function () {
|
||||
var Vector = Kotlin.Class.create({initialize:function (x, y) {
|
||||
this.$x = x;
|
||||
this.$y = y;
|
||||
}, get_x:function () {
|
||||
return this.$x;
|
||||
}, set_x:function (tmp$0) {
|
||||
this.$x = tmp$0;
|
||||
}, get_y:function () {
|
||||
return this.$y;
|
||||
}, set_y:function (tmp$0) {
|
||||
this.$y = tmp$0;
|
||||
}, plus:function (v) {
|
||||
{
|
||||
return interactive.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y());
|
||||
}
|
||||
}, minus:function (v) {
|
||||
{
|
||||
return interactive.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y());
|
||||
}
|
||||
}, times:function (coef) {
|
||||
{
|
||||
return interactive.v_0(this.get_x() * coef, this.get_y() * coef);
|
||||
}
|
||||
}, distanceTo:function (v) {
|
||||
{
|
||||
return Math.sqrt(this.minus(v).get_sqr());
|
||||
}
|
||||
}, isInRect:function (topLeft, size) {
|
||||
{
|
||||
return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y();
|
||||
}
|
||||
}, get_sqr:function () {
|
||||
{
|
||||
return this.get_x() * this.get_x() + this.get_y() * this.get_y();
|
||||
}
|
||||
}
|
||||
});
|
||||
var CanvasState = Kotlin.Class.create({initialize:function (canvas) {
|
||||
this.$canvas = canvas;
|
||||
this.$width = this.get_canvas().width;
|
||||
this.$height = this.get_canvas().height;
|
||||
this.$context = getContext();
|
||||
this.$valid = false;
|
||||
this.$shapes = new Kotlin.ArrayList;
|
||||
this.$selection = null;
|
||||
this.$dragOff = new interactive.Vector_0(0, 0);
|
||||
this.$interval = 1000 / 30;
|
||||
this.$size = 20;
|
||||
{
|
||||
var tmp$4;
|
||||
var tmp$3;
|
||||
var tmp$2;
|
||||
var tmp$1;
|
||||
var tmp$0_0;
|
||||
$(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) {
|
||||
{
|
||||
var tmp$0;
|
||||
tmp$0_0.set_valid(false);
|
||||
tmp$0_0.set_selection(null);
|
||||
var mousePos = tmp$0_0.mousePos_0(it);
|
||||
{
|
||||
tmp$0 = tmp$0_0.get_shapes().iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
if (shape.contains(mousePos)) {
|
||||
tmp$0_0.set_dragOff(mousePos.minus(shape.get_pos()));
|
||||
shape.set_selected(true);
|
||||
tmp$0_0.set_selection(shape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mousemove((tmp$1 = this , function (it) {
|
||||
{
|
||||
if (tmp$1.get_selection() != null) {
|
||||
Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus(tmp$1.get_dragOff()));
|
||||
tmp$1.set_valid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mouseup((tmp$2 = this , function (it) {
|
||||
{
|
||||
if (tmp$2.get_selection() != null) {
|
||||
Kotlin.sure(tmp$2.get_selection()).set_selected(false);
|
||||
}
|
||||
tmp$2.set_selection(null);
|
||||
tmp$2.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).dblclick((tmp$3 = this , function (it) {
|
||||
{
|
||||
var redTransparentCircle = new interactive.Circle_0(tmp$3.mousePos_0(it), tmp$3.get_size(), 'rgba(200, 100, 100, 0.3)');
|
||||
tmp$3.addShape(redTransparentCircle);
|
||||
tmp$3.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
interactive.doWithPeriod(this.get_interval(), (tmp$4 = this , function () {
|
||||
{
|
||||
tmp$4.draw();
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}, get_canvas:function () {
|
||||
return this.$canvas;
|
||||
}, get_width:function () {
|
||||
return this.$width;
|
||||
}, get_height:function () {
|
||||
return this.$height;
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_valid:function () {
|
||||
return this.$valid;
|
||||
}, set_valid:function (tmp$0) {
|
||||
this.$valid = tmp$0;
|
||||
}, get_shapes:function () {
|
||||
return this.$shapes;
|
||||
}, set_shapes:function (tmp$0) {
|
||||
this.$shapes = tmp$0;
|
||||
}, get_selection:function () {
|
||||
return this.$selection;
|
||||
}, set_selection:function (tmp$0) {
|
||||
this.$selection = tmp$0;
|
||||
}, get_dragOff:function () {
|
||||
return this.$dragOff;
|
||||
}, set_dragOff:function (tmp$0) {
|
||||
this.$dragOff = tmp$0;
|
||||
}, get_interval:function () {
|
||||
return this.$interval;
|
||||
}, get_size:function () {
|
||||
return this.$size;
|
||||
}, mousePos_0:function (e) {
|
||||
{
|
||||
var offset = new interactive.Vector_0(0, 0);
|
||||
var element = this.get_canvas();
|
||||
while (element != null) {
|
||||
var el = Kotlin.sure(element);
|
||||
offset = offset.plus(new interactive.Vector_0(el.offsetLeft, el.offsetTop));
|
||||
element = el.offsetParent;
|
||||
}
|
||||
return (new interactive.Vector_0(e.pageX, e.pageY)).minus(offset);
|
||||
}
|
||||
}, addShape:function (shape) {
|
||||
{
|
||||
this.get_shapes().add(shape);
|
||||
this.set_valid(false);
|
||||
}
|
||||
}, clear:function () {
|
||||
{
|
||||
this.get_context().fillStyle = '#FFFFFF';
|
||||
this.get_context().fillRect(0, 0, this.get_width(), this.get_height());
|
||||
this.get_context().strokeStyle = '#000000';
|
||||
this.get_context().lineWidth = 4;
|
||||
this.get_context().strokeRect(0, 0, this.get_width(), this.get_height());
|
||||
}
|
||||
}, draw:function () {
|
||||
{
|
||||
var tmp$0;
|
||||
if (this.get_valid())
|
||||
return;
|
||||
this.clear();
|
||||
{
|
||||
tmp$0 = this.get_shapes().iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
shape.draw(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.set_valid(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
var Shape = Kotlin.Class.create({initialize:function () {
|
||||
this.$selected = false;
|
||||
}, draw:function (state) {
|
||||
}, contains:function (mousePos) {
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_selected:function () {
|
||||
return this.$selected;
|
||||
}, set_selected:function (tmp$0) {
|
||||
this.$selected = tmp$0;
|
||||
}
|
||||
});
|
||||
var JB = Kotlin.Class.create(Shape, {initialize:function (pos, relSize) {
|
||||
this.$pos = pos;
|
||||
this.$relSize = relSize;
|
||||
this.super_init();
|
||||
this.$imageSize = interactive.v_0(704, 254);
|
||||
this.$canvasSize = this.get_imageSize().times(this.get_relSize());
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_relSize:function () {
|
||||
return this.$relSize;
|
||||
}, set_relSize:function (tmp$0) {
|
||||
this.$relSize = tmp$0;
|
||||
}, get_imageSize:function () {
|
||||
return this.$imageSize;
|
||||
}, get_canvasSize:function () {
|
||||
return this.$canvasSize;
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
context.drawImage(getKotlinLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_pos().get_x(), this.get_pos().get_y(), this.get_canvasSize().get_x(), this.get_canvasSize().get_y());
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return mousePos.isInRect(this.get_pos(), this.get_canvasSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
var Rectangle = Kotlin.Class.create(Shape, {initialize:function (pos, size) {
|
||||
this.$pos = pos;
|
||||
this.$size = size;
|
||||
this.super_init();
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_size:function () {
|
||||
return this.$size;
|
||||
}, set_size:function (tmp$0) {
|
||||
this.$size = tmp$0;
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
context.fillStyle = 'rgba(0,255,0,.6)';
|
||||
context.fillRect(this.get_pos().get_x(), this.get_pos().get_y(), this.get_size().get_x(), this.get_size().get_y());
|
||||
if (this.get_selected()) {
|
||||
context.strokeStyle = '#FF0000';
|
||||
context.lineWidth = 2;
|
||||
context.strokeRect(this.get_pos().get_x(), this.get_pos().get_y(), this.get_size().get_x(), this.get_size().get_y());
|
||||
}
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return mousePos.isInRect(this.get_pos(), this.get_size());
|
||||
}
|
||||
}
|
||||
});
|
||||
var Circle = Kotlin.Class.create(Shape, {initialize:function (pos, radius, fillColor) {
|
||||
this.$pos = pos;
|
||||
this.$radius = radius;
|
||||
this.$fillColor = fillColor;
|
||||
this.super_init();
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_radius:function () {
|
||||
return this.$radius;
|
||||
}, set_radius:function (tmp$0) {
|
||||
this.$radius = tmp$0;
|
||||
}, get_fillColor:function () {
|
||||
return this.$fillColor;
|
||||
}, set_fillColor:function (tmp$0) {
|
||||
this.$fillColor = tmp$0;
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
context.shadowColor = 'white';
|
||||
context.shadowBlur = 10;
|
||||
context.fillStyle = this.get_fillColor();
|
||||
context.beginPath();
|
||||
context.arc(this.get_pos().get_x(), this.get_pos().get_y(), this.get_radius(), 0, 2 * Math.PI, false);
|
||||
context.closePath();
|
||||
context.fill();
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return this.get_pos().distanceTo(mousePos) < this.get_radius();
|
||||
}
|
||||
}
|
||||
});
|
||||
return {Shape_0:Shape, JB_0:JB, Rectangle_0:Rectangle, Circle_0:Circle, CanvasState_0:CanvasState, Vector_0:Vector};
|
||||
}
|
||||
();
|
||||
var interactive = Kotlin.Namespace.create({initialize:function () {
|
||||
interactive.$state = new interactive.CanvasState_0(getCanvas());
|
||||
}, get_state:function () {
|
||||
return interactive.$state;
|
||||
}, doWithPeriod:function (period, f) {
|
||||
{
|
||||
setInterval(f, period);
|
||||
}
|
||||
}, v_0:function (x, y) {
|
||||
{
|
||||
return new interactive.Vector_0(x, y);
|
||||
}
|
||||
}, main:function () {
|
||||
{
|
||||
var state = new interactive.CanvasState_0(getCanvas());
|
||||
state.addShape(new interactive.JB_0(interactive.v_0(1, 1), 0.3));
|
||||
setTimeout(function () {
|
||||
{
|
||||
state.set_valid(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}, classes);
|
||||
interactive.initialize();
|
||||
}
|
||||
|
||||
var args = [];
|
||||
interactive.main(args);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -0,0 +1,183 @@
|
||||
package interactive;
|
||||
|
||||
import jquery.*;
|
||||
import html5.*;
|
||||
import java.util.ArrayList;
|
||||
import js.*;
|
||||
import js.Math;
|
||||
import js.setInterval
|
||||
import html5.getCanvas
|
||||
import html5.getKotlinLogo
|
||||
import jquery.jq
|
||||
import js.setTimeout
|
||||
|
||||
val state = CanvasState(getCanvas());
|
||||
|
||||
fun doWithPeriod(period : Int, f : ()->Unit) {
|
||||
setInterval(f, period);
|
||||
}
|
||||
|
||||
abstract class Shape() {
|
||||
abstract fun draw(state : CanvasState);
|
||||
abstract fun contains(mousePos : Vector) : Boolean;
|
||||
abstract var pos : Vector;
|
||||
var selected : Boolean = false;
|
||||
}
|
||||
|
||||
class Circle(override var pos : Vector,
|
||||
var radius : Double = 1.0,
|
||||
var fillColor : String = "#AAAAAA") : Shape() {
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context;
|
||||
context.shadowColor = "white";
|
||||
context.shadowBlur = 10.0;
|
||||
context.fillStyle = fillColor;
|
||||
context.beginPath();
|
||||
context.arc(pos.x, pos.y, radius, 0.0, 2 * Math.PI, false);
|
||||
context.closePath();
|
||||
context.fill();
|
||||
}
|
||||
|
||||
override fun contains(mousePos : Vector) = pos.distanceTo(mousePos) < radius;
|
||||
}
|
||||
|
||||
class Rectangle(override var pos : Vector,
|
||||
var size : Vector) : Shape()
|
||||
{
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context;
|
||||
context.fillStyle = "rgba(0,255,0,.6)";
|
||||
context.fillRect(pos.x, pos.y, size.x, size.y);
|
||||
if (selected) {
|
||||
context.strokeStyle = "#FF0000"
|
||||
context.lineWidth = 2.0;
|
||||
context.strokeRect(pos.x, pos.y, size.x, size.y)
|
||||
}
|
||||
}
|
||||
|
||||
override fun contains(mousePos : Vector) = mousePos.isInRect(pos, size);
|
||||
}
|
||||
|
||||
class JB(override var pos : Vector,
|
||||
var relSize : Double = 0.3) : Shape()
|
||||
{
|
||||
|
||||
val imageSize = v(704.0, 254.0)
|
||||
val canvasSize = imageSize * relSize
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context;
|
||||
context.drawImage(getKotlinLogo(), 0.0, 0.0, imageSize.x, imageSize.y, pos.x, pos.y, canvasSize.x, canvasSize.y)
|
||||
}
|
||||
|
||||
override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, canvasSize)
|
||||
}
|
||||
|
||||
class CanvasState(val canvas : Canvas) {
|
||||
val width = canvas.width;
|
||||
val height = canvas.height;
|
||||
val context = getContext();
|
||||
var valid = false;
|
||||
var shapes = ArrayList<Shape>();
|
||||
var selection : Shape? = null;
|
||||
var dragOff = Vector();
|
||||
val interval = 1000 / 30;
|
||||
val size = 20.0;
|
||||
|
||||
{
|
||||
jq(canvas).mousedown {
|
||||
valid = false;
|
||||
selection = null;
|
||||
val mousePos = mousePos(it);
|
||||
for (shape in shapes) {
|
||||
if (mousePos in shape) {
|
||||
dragOff = mousePos - shape.pos;
|
||||
shape.selected = true;
|
||||
selection = shape;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mousemove {
|
||||
if (selection != null) {
|
||||
selection.sure().pos = mousePos(it) - dragOff;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mouseup {
|
||||
if (selection != null) {
|
||||
selection.sure().selected = false;
|
||||
}
|
||||
selection = null;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
jq(canvas).dblclick {
|
||||
val redTransparentCircle = Circle(mousePos(it), size, "rgba(200, 100, 100, 0.3)");
|
||||
addShape(redTransparentCircle);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
doWithPeriod(interval) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
fun mousePos(e : MouseEvent) : Vector {
|
||||
var offset = Vector();
|
||||
var element : DomElement? = canvas;
|
||||
while (element != null) {
|
||||
val el : DomElement = element.sure();
|
||||
offset += Vector(el.offsetLeft, el.offsetTop);
|
||||
element = el.offsetParent;
|
||||
}
|
||||
return Vector(e.pageX, e.pageY) - offset;
|
||||
}
|
||||
|
||||
fun addShape(shape : Shape) {
|
||||
shapes.add(shape);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
context.fillStyle = "#FFFFFF"
|
||||
context.fillRect(0.0, 0.0, width, height)
|
||||
context.strokeStyle = "#000000"
|
||||
context.lineWidth = 4.0;
|
||||
context.strokeRect(0.0, 0.0, width, height)
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
if (valid) return
|
||||
|
||||
clear();
|
||||
for (shape in shapes) {
|
||||
shape.draw(this);
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
fun v(x : Double, y : Double) = Vector(x, y);
|
||||
|
||||
class Vector(var x : Double = 0.0, var y : Double = 0.0) {
|
||||
fun plus(v : Vector) = v(x + v.x, y + v.y);
|
||||
fun minus(v : Vector) = v(x - v.x, y - v.y);
|
||||
fun times(coef : Double) = v(x * coef, y * coef);
|
||||
fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr);
|
||||
fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
|
||||
(y >= topLeft.y) && (y <= topLeft.y + size.y)
|
||||
val sqr : Double
|
||||
get() = x * x + y * y;
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val state = CanvasState(getCanvas());
|
||||
state.addShape(JB(v(1.0, 1.0)));
|
||||
setTimeout({
|
||||
state.valid = false
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas height="450" width="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../../../translator/testFiles/kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../../../translator/testFiles/canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="interactive.js" type="text/javascript"></script>
|
||||
<img src="jbLogo.png" hidden=true/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas height="450" width="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="tutorial.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
// By Simon Sarris
|
||||
// www.simonsarris.com
|
||||
// sarris@acm.org
|
||||
//
|
||||
// Last update December 2011
|
||||
//
|
||||
// Free to use and distribute at will
|
||||
// So long as you are nice to people, etc
|
||||
|
||||
// Constructor for Shape objects to hold data for all drawn objects.
|
||||
// For now they will just be defined as rectangles.
|
||||
function Shape(x, y, w, h, fill) {
|
||||
// This is a very simple and unsafe constructor. All we're doing is checking if the values exist.
|
||||
// "x || 0" just means "if there is a value for x, use that. Otherwise use 0."
|
||||
// But we aren't checking anything else! We could put "Lalala" for the value of x
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.w = w || 1;
|
||||
this.h = h || 1;
|
||||
this.fill = fill || '#AAAAAA';
|
||||
}
|
||||
|
||||
// Draws this shape to a given context
|
||||
Shape.prototype.draw = function (ctx) {
|
||||
ctx.fillStyle = this.fill;
|
||||
ctx.fillRect(this.x, this.y, this.w, this.h);
|
||||
}
|
||||
|
||||
// Determine if a point is inside the shape's bounds
|
||||
Shape.prototype.contains = function (mx, my) {
|
||||
// All we have to do is make sure the Mouse X,Y fall in the area between
|
||||
// the shape's X and (X + Height) and its Y and (Y + Height)
|
||||
return (this.x <= mx) && (this.x + this.w >= mx) &&
|
||||
(this.y <= my) && (this.y + this.h >= my);
|
||||
}
|
||||
|
||||
function CanvasState(canvas) {
|
||||
// **** First some setup! ****
|
||||
|
||||
this.canvas = canvas;
|
||||
this.width = canvas.width;
|
||||
this.height = canvas.height;
|
||||
this.ctx = canvas.getContext('2d');
|
||||
// This complicates things a little but but fixes mouse co-ordinate problems
|
||||
// when there's a border or padding. See getMouse for more detail
|
||||
// if (document.defaultView && document.defaultView.getComputedStyle) {
|
||||
// this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
|
||||
// this.stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
|
||||
// this.styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
|
||||
// this.styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
|
||||
// }
|
||||
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
|
||||
// They will mess up mouse coordinates and this fixes that
|
||||
var html = document.body.parentNode;
|
||||
this.htmlTop = html.offsetTop;
|
||||
this.htmlLeft = html.offsetLeft;
|
||||
|
||||
// **** Keep track of state! ****
|
||||
|
||||
this.valid = false; // when set to false, the canvas will redraw everything
|
||||
this.shapes = []; // the collection of things to be drawn
|
||||
this.dragging = false; // Keep track of when we are dragging
|
||||
// the current selected object. In the future we could turn this into an array for multiple selection
|
||||
this.selection = null;
|
||||
this.dragoffx = 0; // See mousedown and mousemove events for explanation
|
||||
this.dragoffy = 0;
|
||||
|
||||
// **** Then events! ****
|
||||
|
||||
// This is an example of a closure!
|
||||
// Right here "this" means the CanvasState. But we are making events on the Canvas itself,
|
||||
// and when the events are fired on the canvas the variable "this" is going to mean the canvas!
|
||||
// Since we still want to use this particular CanvasState in the events we have to save a reference to it.
|
||||
// This is our reference!
|
||||
var myState = this;
|
||||
|
||||
//fixes a problem where double clicking causes text to get selected on the canvas
|
||||
canvas.addEventListener('selectstart', function (e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}, false);
|
||||
// Up, down, and move are for dragging
|
||||
canvas.addEventListener('mousedown', function (e) {
|
||||
var mouse = myState.getMouse(e);
|
||||
var mx = mouse.x;
|
||||
var my = mouse.y;
|
||||
var shapes = myState.shapes;
|
||||
var l = shapes.length;
|
||||
for (var i = l - 1; i >= 0; i--) {
|
||||
if (shapes[i].contains(mx, my)) {
|
||||
var mySel = shapes[i];
|
||||
// Keep track of where in the object we clicked
|
||||
// so we can move it smoothly (see mousemove)
|
||||
myState.dragoffx = mx - mySel.x;
|
||||
myState.dragoffy = my - mySel.y;
|
||||
myState.dragging = true;
|
||||
myState.selection = mySel;
|
||||
myState.valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// havent returned means we have failed to select anything.
|
||||
// If there was an object selected, we deselect it
|
||||
if (myState.selection) {
|
||||
myState.selection = null;
|
||||
myState.valid = false; // Need to clear the old selection border
|
||||
}
|
||||
}, true);
|
||||
canvas.addEventListener('mousemove', function (e) {
|
||||
if (myState.dragging) {
|
||||
var mouse = myState.getMouse(e);
|
||||
// We don't want to drag the object by its top-left corner, we want to drag it
|
||||
// from where we clicked. Thats why we saved the offset and use it here
|
||||
myState.selection.x = mouse.x - myState.dragoffx;
|
||||
myState.selection.y = mouse.y - myState.dragoffy;
|
||||
myState.valid = false; // Something's dragging so we must redraw
|
||||
}
|
||||
}, true);
|
||||
canvas.addEventListener('mouseup', function (e) {
|
||||
myState.dragging = false;
|
||||
}, true);
|
||||
// double click for making new shapes
|
||||
canvas.addEventListener('dblclick', function (e) {
|
||||
var mouse = myState.getMouse(e);
|
||||
myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
|
||||
}, true);
|
||||
|
||||
// **** Options! ****
|
||||
|
||||
this.selectionColor = '#CC0000';
|
||||
this.selectionWidth = 2;
|
||||
this.interval = 30;
|
||||
setInterval(function () {
|
||||
myState.draw();
|
||||
}, myState.interval);
|
||||
}
|
||||
|
||||
CanvasState.prototype.addShape = function (shape) {
|
||||
this.shapes.push(shape);
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
CanvasState.prototype.clear = function () {
|
||||
this.ctx.clearRect(0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
// While draw is called as often as the INTERVAL variable demands,
|
||||
// It only ever does something if the canvas gets invalidated by our code
|
||||
CanvasState.prototype.draw = function () {
|
||||
// if our state is invalid, redraw and validate!
|
||||
if (!this.valid) {
|
||||
var ctx = this.ctx;
|
||||
var shapes = this.shapes;
|
||||
this.clear();
|
||||
|
||||
// ** Add stuff you want drawn in the background all the time here **
|
||||
|
||||
// draw all shapes
|
||||
var l = shapes.length;
|
||||
for (var i = 0; i < l; i++) {
|
||||
var shape = shapes[i];
|
||||
// We can skip the drawing of elements that have moved off the screen:
|
||||
if (shape.x > this.width || shape.y > this.height ||
|
||||
shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
|
||||
shapes[i].draw(ctx);
|
||||
}
|
||||
|
||||
// draw selection
|
||||
// right now this is just a stroke along the edge of the selected Shape
|
||||
if (this.selection != null) {
|
||||
ctx.strokeStyle = this.selectionColor;
|
||||
ctx.lineWidth = this.selectionWidth;
|
||||
var mySel = this.selection;
|
||||
ctx.strokeRect(mySel.x, mySel.y, mySel.w, mySel.h);
|
||||
}
|
||||
|
||||
// ** Add stuff you want drawn on top all the time here **
|
||||
|
||||
this.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Creates an object with x and y defined, set to the mouse position relative to the state's canvas
|
||||
// If you wanna be super-correct this can be tricky, we have to worry about padding and borders
|
||||
CanvasState.prototype.getMouse = function (e) {
|
||||
var element = this.canvas, offsetX = 0, offsetY = 0, mx, my;
|
||||
|
||||
// Compute the total offset
|
||||
if (element.offsetParent !== undefined) {
|
||||
do {
|
||||
offsetX += element.offsetLeft;
|
||||
offsetY += element.offsetTop;
|
||||
} while ((element = element.offsetParent));
|
||||
}
|
||||
|
||||
// Add padding and border style widths to offset
|
||||
// Also add the <html> offsets in case there's a position:fixed bar
|
||||
// offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
|
||||
// offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;
|
||||
|
||||
mx = e.pageX - offsetX;
|
||||
my = e.pageY - offsetY;
|
||||
|
||||
// We return a simple javascript object (a hash) with x and y defined
|
||||
return {x:mx, y:my};
|
||||
}
|
||||
|
||||
// If you dont want to use <body onLoad='init()'>
|
||||
// You could uncomment this init() reference and place the script reference inside the body tag
|
||||
init();
|
||||
|
||||
function init() {
|
||||
var s = new CanvasState(getCanvas());
|
||||
s.addShape(new Shape(40, 40, 50, 50)); // The default is gray
|
||||
s.addShape(new Shape(60, 140, 40, 60, 'lightskyblue'));
|
||||
// Lets make some partially transparent
|
||||
s.addShape(new Shape(80, 150, 60, 30, 'rgba(127, 255, 212, .5)'));
|
||||
s.addShape(new Shape(125, 80, 30, 80, 'rgba(245, 222, 179, .7)'));
|
||||
}
|
||||
|
||||
// Now go make something amazing!
|
||||
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
|
||||
{
|
||||
var classes = function () {
|
||||
var Vector = Kotlin.Class.create({initialize:function (x, y) {
|
||||
this.$x = x;
|
||||
this.$y = y;
|
||||
}, get_x:function () {
|
||||
return this.$x;
|
||||
}, get_y:function () {
|
||||
return this.$y;
|
||||
}, plus:function (v) {
|
||||
{
|
||||
return interactive2.v_0(this.get_x() + v.get_x(), this.get_y() + v.get_y());
|
||||
}
|
||||
}, minus:function () {
|
||||
{
|
||||
return interactive2.v_0(-this.get_x(), -this.get_y());
|
||||
}
|
||||
}, minus$0:function (v) {
|
||||
{
|
||||
return interactive2.v_0(this.get_x() - v.get_x(), this.get_y() - v.get_y());
|
||||
}
|
||||
}, times:function (coef) {
|
||||
{
|
||||
return interactive2.v_0(this.get_x() * coef, this.get_y() * coef);
|
||||
}
|
||||
}, distanceTo:function (v) {
|
||||
{
|
||||
return Math.sqrt(this.minus$0(v).get_sqr());
|
||||
}
|
||||
}, rotatedBy:function (theta) {
|
||||
{
|
||||
var sin = Math.sin(theta);
|
||||
var cos = Math.cos(theta);
|
||||
return interactive2.v_0(this.get_x() * cos - this.get_y() * sin, this.get_x() * sin + this.get_y() * cos);
|
||||
}
|
||||
}, isInRect:function (topLeft, size) {
|
||||
{
|
||||
return this.get_x() >= topLeft.get_x() && this.get_x() <= topLeft.get_x() + size.get_x() && this.get_y() >= topLeft.get_y() && this.get_y() <= topLeft.get_y() + size.get_y();
|
||||
}
|
||||
}, get_sqr:function () {
|
||||
{
|
||||
return this.get_x() * this.get_x() + this.get_y() * this.get_y();
|
||||
}
|
||||
}, get_normalized:function () {
|
||||
{
|
||||
return this.times(1 / Math.sqrt(this.get_sqr()));
|
||||
}
|
||||
}
|
||||
});
|
||||
var RadialGradientGenerator = Kotlin.Class.create({initialize:function (context) {
|
||||
this.$context = context;
|
||||
this.$gradients = new Kotlin.ArrayList;
|
||||
this.$current = 0;
|
||||
{
|
||||
this.newColorStops([
|
||||
[0, '#F59898'],
|
||||
[0.5, '#F57373'],
|
||||
[1, '#DB6B6B']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0.39, 'rgb(140,167,209)'],
|
||||
[0.7, 'rgb(104,139,209)'],
|
||||
[0.85, 'rgb(67,122,217)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(255,222,255)'],
|
||||
[0.5, 'rgb(255,185,222)'],
|
||||
[1, 'rgb(230,154,185)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(255,209,114)'],
|
||||
[0.5, 'rgb(255,174,81)'],
|
||||
[1, 'rgb(241,145,54)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(132,240,135)'],
|
||||
[0.5, 'rgb(91,240,96)'],
|
||||
[1, 'rgb(27,245,41)']
|
||||
]);
|
||||
this.newColorStops([
|
||||
[0, 'rgb(250,147,250)'],
|
||||
[0.5, 'rgb(255,80,255)'],
|
||||
[1, 'rgb(250,0,217)']
|
||||
]);
|
||||
}
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_gradients:function () {
|
||||
return this.$gradients;
|
||||
}, get_current:function () {
|
||||
return this.$current;
|
||||
}, set_current:function (tmp$0) {
|
||||
this.$current = tmp$0;
|
||||
}, newColorStops:function (colorStops) {
|
||||
{
|
||||
this.get_gradients().add(colorStops);
|
||||
}
|
||||
}, getNext:function () {
|
||||
{
|
||||
var result = this.get_gradients().get(this.get_current());
|
||||
this.set_current((this.get_current() + 1) % this.get_gradients().size());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
var CanvasState = Kotlin.Class.create({initialize:function (canvas) {
|
||||
this.$canvas = canvas;
|
||||
this.$width = this.get_canvas().width;
|
||||
this.$height = this.get_canvas().height;
|
||||
this.$context = getContext();
|
||||
this.$valid = false;
|
||||
this.$shapes = new Kotlin.ArrayList;
|
||||
this.$selection = null;
|
||||
this.$dragOff = new interactive2.Vector_0(0, 0);
|
||||
this.$interval = 1000 / 30;
|
||||
{
|
||||
var tmp$4;
|
||||
var tmp$3;
|
||||
var tmp$2;
|
||||
var tmp$1;
|
||||
var tmp$0_0;
|
||||
$(this.get_canvas()).mousedown((tmp$0_0 = this , function (it) {
|
||||
{
|
||||
var tmp$0;
|
||||
tmp$0_0.set_valid(false);
|
||||
tmp$0_0.set_selection(null);
|
||||
var mousePos = tmp$0_0.mousePos_0(it);
|
||||
{
|
||||
tmp$0 = tmp$0_0.get_shapes().iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
if (shape.contains(mousePos)) {
|
||||
tmp$0_0.set_dragOff(mousePos.minus$0(shape.get_pos()));
|
||||
shape.set_selected(true);
|
||||
tmp$0_0.set_selection(shape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mousemove((tmp$1 = this , function (it) {
|
||||
{
|
||||
if (tmp$1.get_selection() != null) {
|
||||
Kotlin.sure(tmp$1.get_selection()).set_pos(tmp$1.mousePos_0(it).minus$0(tmp$1.get_dragOff()));
|
||||
tmp$1.set_valid(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).mouseup((tmp$2 = this , function (it) {
|
||||
{
|
||||
if (tmp$2.get_selection() != null) {
|
||||
Kotlin.sure(tmp$2.get_selection()).set_selected(false);
|
||||
}
|
||||
tmp$2.set_selection(null);
|
||||
tmp$2.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
$(this.get_canvas()).dblclick((tmp$3 = this , function (it) {
|
||||
{
|
||||
var redTransparentCircle = new interactive2.Creature_0(tmp$3.mousePos_0(it), tmp$3);
|
||||
tmp$3.addShape(redTransparentCircle);
|
||||
tmp$3.set_valid(false);
|
||||
}
|
||||
}
|
||||
));
|
||||
interactive2.doWithPeriod(this.get_interval(), (tmp$4 = this , function () {
|
||||
{
|
||||
tmp$4.draw();
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}, get_canvas:function () {
|
||||
return this.$canvas;
|
||||
}, get_width:function () {
|
||||
return this.$width;
|
||||
}, get_height:function () {
|
||||
return this.$height;
|
||||
}, get_context:function () {
|
||||
return this.$context;
|
||||
}, get_valid:function () {
|
||||
return this.$valid;
|
||||
}, set_valid:function (tmp$0) {
|
||||
this.$valid = tmp$0;
|
||||
}, get_shapes:function () {
|
||||
return this.$shapes;
|
||||
}, set_shapes:function (tmp$0) {
|
||||
this.$shapes = tmp$0;
|
||||
}, get_selection:function () {
|
||||
return this.$selection;
|
||||
}, set_selection:function (tmp$0) {
|
||||
this.$selection = tmp$0;
|
||||
}, get_dragOff:function () {
|
||||
return this.$dragOff;
|
||||
}, set_dragOff:function (tmp$0) {
|
||||
this.$dragOff = tmp$0;
|
||||
}, get_interval:function () {
|
||||
return this.$interval;
|
||||
}, mousePos_0:function (e) {
|
||||
{
|
||||
var offset = new interactive2.Vector_0(0, 0);
|
||||
var element = this.get_canvas();
|
||||
while (element != null) {
|
||||
var el = Kotlin.sure(element);
|
||||
offset = offset.plus(new interactive2.Vector_0(el.offsetLeft, el.offsetTop));
|
||||
element = el.offsetParent;
|
||||
}
|
||||
return (new interactive2.Vector_0(e.pageX, e.pageY)).minus$0(offset);
|
||||
}
|
||||
}, addShape:function (shape) {
|
||||
{
|
||||
this.get_shapes().add(shape);
|
||||
this.set_valid(false);
|
||||
}
|
||||
}, clear:function () {
|
||||
{
|
||||
this.get_context().fillStyle = '#FFFFFF';
|
||||
this.get_context().fillRect(0, 0, this.get_width(), this.get_height());
|
||||
this.get_context().strokeStyle = '#000000';
|
||||
this.get_context().lineWidth = 4;
|
||||
this.get_context().strokeRect(0, 0, this.get_width(), this.get_height());
|
||||
}
|
||||
}, draw:function () {
|
||||
{
|
||||
var tmp$0;
|
||||
if (this.get_valid())
|
||||
return;
|
||||
this.clear();
|
||||
{
|
||||
tmp$0 = this.get_shapes().iterator();
|
||||
while (tmp$0.hasNext()) {
|
||||
var shape = tmp$0.next();
|
||||
{
|
||||
shape.draw(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.set_valid(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
var Shape = Kotlin.Class.create({initialize:function () {
|
||||
this.$selected = false;
|
||||
}, draw:function (state) {
|
||||
}, contains:function (mousePos) {
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_selected:function () {
|
||||
return this.$selected;
|
||||
}, set_selected:function (tmp$0) {
|
||||
this.$selected = tmp$0;
|
||||
}
|
||||
});
|
||||
var Creature = Kotlin.Class.create(Shape, {initialize:function (pos, state) {
|
||||
this.$pos = pos;
|
||||
this.$state = state;
|
||||
this.super_init();
|
||||
this.$shadowOffset = interactive2.v_0(-5, 5);
|
||||
this.$colorStops = interactive2.get_gradientGenerator().getNext();
|
||||
this.$relSize = 0.05;
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_state:function () {
|
||||
return this.$state;
|
||||
}, set_state:function (tmp$0) {
|
||||
this.$state = tmp$0;
|
||||
}, get_shadowOffset:function () {
|
||||
return this.$shadowOffset;
|
||||
}, get_colorStops:function () {
|
||||
return this.$colorStops;
|
||||
}, get_relSize:function () {
|
||||
return this.$relSize;
|
||||
}, get_radius:function () {
|
||||
{
|
||||
return this.get_state().get_width() * this.get_relSize();
|
||||
}
|
||||
}, get_position:function () {
|
||||
var tmp$0;
|
||||
if (this.get_selected())
|
||||
tmp$0 = this.get_pos().minus$0(this.get_shadowOffset());
|
||||
else
|
||||
tmp$0 = this.get_pos();
|
||||
{
|
||||
return tmp$0;
|
||||
}
|
||||
}, get_directionToLogo:function () {
|
||||
{
|
||||
return interactive2.get_JB().get_centre().minus$0(this.get_position()).get_normalized();
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return this.get_pos().distanceTo(mousePos) < this.get_radius();
|
||||
}
|
||||
}, fillCircle:function (receiver, position, rad) {
|
||||
{
|
||||
receiver.beginPath();
|
||||
receiver.arc(position.get_x(), position.get_y(), rad, 0, 2 * Math.PI, false);
|
||||
receiver.closePath();
|
||||
receiver.fill();
|
||||
}
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
if (!this.get_selected()) {
|
||||
this.drawCreature(context);
|
||||
}
|
||||
else {
|
||||
this.drawCreatureWithShadow(context);
|
||||
}
|
||||
}
|
||||
}, drawCreature:function (context) {
|
||||
{
|
||||
context.fillStyle = this.getGradient(context);
|
||||
this.fillCircle(context, this.get_position(), this.get_radius());
|
||||
this.drawEye(context);
|
||||
this.drawTail(context);
|
||||
}
|
||||
}, getGradient:function (context) {
|
||||
{
|
||||
var tmp$0;
|
||||
var gradientCentre = this.get_position().plus(this.get_directionToLogo().times(this.get_radius() / 4));
|
||||
var gradient = context.createRadialGradient(gradientCentre.get_x(), gradientCentre.get_y(), 1, gradientCentre.get_x(), gradientCentre.get_y(), 2 * this.get_radius());
|
||||
{
|
||||
tmp$0 = Kotlin.arrayIterator(this.get_colorStops());
|
||||
while (tmp$0.hasNext()) {
|
||||
var colorStop = tmp$0.next();
|
||||
{
|
||||
gradient.addColorStop(colorStop[0], colorStop[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return gradient;
|
||||
}
|
||||
}, drawTail:function (context) {
|
||||
{
|
||||
var tailDirection = this.get_directionToLogo().minus();
|
||||
var tailPos = this.get_position().plus(tailDirection.times(this.get_radius()).times(0.7));
|
||||
var tailSize = this.get_radius() * 1.6;
|
||||
var angle = Math.PI / 6;
|
||||
var p1 = tailPos.plus(tailDirection.rotatedBy(angle).times(tailSize));
|
||||
var p2 = tailPos.plus(tailDirection.rotatedBy(-angle).times(tailSize));
|
||||
context.fillStyle = this.getGradient(context);
|
||||
context.beginPath();
|
||||
context.moveTo(tailPos.get_x(), tailPos.get_y());
|
||||
context.lineTo(p1.get_x(), p1.get_y());
|
||||
var middlePoint = this.get_position().plus(tailDirection.times(this.get_radius()).times(1));
|
||||
context.quadraticCurveTo(middlePoint.get_x(), middlePoint.get_y(), p2.get_x(), p2.get_y());
|
||||
context.lineTo(tailPos.get_x(), tailPos.get_y());
|
||||
context.closePath();
|
||||
context.fill();
|
||||
}
|
||||
}, drawEye:function (context) {
|
||||
{
|
||||
var eyePos = this.get_directionToLogo().times(this.get_radius()).times(0.6).plus(this.get_position());
|
||||
var eyeRadius = this.get_radius() / 3;
|
||||
var eyeLidRadius = eyeRadius / 2;
|
||||
context.fillStyle = '#FFFFFF';
|
||||
this.fillCircle(context, eyePos, eyeRadius);
|
||||
context.fillStyle = '#000000';
|
||||
this.fillCircle(context, eyePos, eyeLidRadius);
|
||||
}
|
||||
}, drawCreatureWithShadow:function (context) {
|
||||
{
|
||||
context.save();
|
||||
this.setShadow(context);
|
||||
context.fillStyle = this.getGradient(context);
|
||||
this.fillCircle(context, this.get_position(), this.get_radius());
|
||||
context.restore();
|
||||
this.drawEye(context);
|
||||
this.drawTail(context);
|
||||
}
|
||||
}, setShadow:function (context) {
|
||||
{
|
||||
context.shadowColor = 'rgba(100, 100, 100, 0.7)';
|
||||
context.shadowBlur = 5;
|
||||
context.shadowOffsetX = this.get_shadowOffset().get_x();
|
||||
context.shadowOffsetY = this.get_shadowOffset().get_y();
|
||||
}
|
||||
}
|
||||
});
|
||||
var Logo = Kotlin.Class.create(Shape, {initialize:function (pos, relSize) {
|
||||
this.$pos = pos;
|
||||
this.$relSize = relSize;
|
||||
this.super_init();
|
||||
this.$imageSize = interactive2.v_0(704, 254);
|
||||
this.$canvasSize = this.get_imageSize().times(this.get_relSize());
|
||||
}, get_pos:function () {
|
||||
return this.$pos;
|
||||
}, set_pos:function (tmp$0) {
|
||||
this.$pos = tmp$0;
|
||||
}, get_relSize:function () {
|
||||
return this.$relSize;
|
||||
}, set_relSize:function (tmp$0) {
|
||||
this.$relSize = tmp$0;
|
||||
}, get_imageSize:function () {
|
||||
return this.$imageSize;
|
||||
}, get_canvasSize:function () {
|
||||
return this.$canvasSize;
|
||||
}, draw:function (state) {
|
||||
{
|
||||
var context = state.get_context();
|
||||
context.drawImage(getKotlinLogo(), 0, 0, this.get_imageSize().get_x(), this.get_imageSize().get_y(), this.get_pos().get_x(), this.get_pos().get_y(), this.get_canvasSize().get_x(), this.get_canvasSize().get_y());
|
||||
}
|
||||
}, contains:function (mousePos) {
|
||||
{
|
||||
return mousePos.isInRect(this.get_pos(), this.get_canvasSize());
|
||||
}
|
||||
}, get_centre:function () {
|
||||
{
|
||||
return this.get_pos().plus(this.get_canvasSize().times(0.5));
|
||||
}
|
||||
}
|
||||
});
|
||||
return {Shape_0:Shape, Logo_0:Logo, Creature_0:Creature, RadialGradientGenerator_0:RadialGradientGenerator, CanvasState_0:CanvasState, Vector_0:Vector};
|
||||
}
|
||||
();
|
||||
var interactive2 = Kotlin.Namespace.create({initialize:function () {
|
||||
interactive2.$gradientGenerator = new interactive2.RadialGradientGenerator_0(getContext());
|
||||
interactive2.$JB = new interactive2.Logo_0(interactive2.v_0(20, 20), 0.3);
|
||||
}, get_gradientGenerator:function () {
|
||||
return interactive2.$gradientGenerator;
|
||||
}, get_JB:function () {
|
||||
return interactive2.$JB;
|
||||
}, doWithPeriod:function (period, f) {
|
||||
{
|
||||
setInterval(f, period);
|
||||
}
|
||||
}, v_0:function (x, y) {
|
||||
{
|
||||
return new interactive2.Vector_0(x, y);
|
||||
}
|
||||
}, main:function () {
|
||||
{
|
||||
var state = new interactive2.CanvasState_0(getCanvas());
|
||||
state.addShape(interactive2.get_JB());
|
||||
setTimeout(function () {
|
||||
{
|
||||
state.set_valid(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}, classes);
|
||||
interactive2.initialize();
|
||||
}
|
||||
|
||||
var args = [];
|
||||
interactive2.main(args);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -0,0 +1,280 @@
|
||||
package interactive2;
|
||||
|
||||
import jquery.*;
|
||||
import html5.*;
|
||||
import java.util.ArrayList;
|
||||
import js.*;
|
||||
import js.Math;
|
||||
import js.setInterval
|
||||
import html5.getCanvas
|
||||
import html5.getKotlinLogo
|
||||
import jquery.jq
|
||||
import js.setTimeout
|
||||
|
||||
val gradientGenerator = RadialGradientGenerator(getContext())
|
||||
val JB = Logo(v(20.0, 20.0))
|
||||
|
||||
fun doWithPeriod(period : Int, f : ()->Unit) {
|
||||
setInterval(f, period);
|
||||
}
|
||||
|
||||
abstract class Shape() {
|
||||
abstract fun draw(state : CanvasState);
|
||||
abstract fun contains(mousePos : Vector) : Boolean;
|
||||
abstract var pos : Vector;
|
||||
var selected : Boolean = false;
|
||||
}
|
||||
|
||||
class Logo(override var pos : Vector,
|
||||
var relSize : Double = 0.3)
|
||||
: Shape()
|
||||
{
|
||||
val imageSize = v(704.0, 254.0)
|
||||
val canvasSize = imageSize * relSize
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context;
|
||||
context.drawImage(getKotlinLogo(), 0.0, 0.0, imageSize.x, imageSize.y, pos.x, pos.y, canvasSize.x, canvasSize.y)
|
||||
}
|
||||
|
||||
override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, canvasSize)
|
||||
|
||||
val centre : Vector
|
||||
get() = pos + canvasSize * 0.5
|
||||
}
|
||||
|
||||
class Creature(override var pos : Vector,
|
||||
var state : CanvasState) : Shape() {
|
||||
|
||||
val shadowOffset = v(-5.0, 5.0)
|
||||
val colorStops = gradientGenerator.getNext()
|
||||
val relSize = 0.05;
|
||||
val radius : Double
|
||||
get() = state.width * relSize;
|
||||
|
||||
val position : Vector
|
||||
get() = if (selected) pos - shadowOffset else pos
|
||||
|
||||
val directionToLogo : Vector
|
||||
get() = (JB.centre - position).normalized
|
||||
|
||||
override fun contains(mousePos : Vector) = pos.distanceTo(mousePos) < radius;
|
||||
|
||||
fun Context.fillCircle(position : Vector, rad : Double) {
|
||||
beginPath();
|
||||
arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false);
|
||||
closePath();
|
||||
fill()
|
||||
}
|
||||
|
||||
override fun draw(state : CanvasState) {
|
||||
val context = state.context;
|
||||
if (!selected) {
|
||||
drawCreature(context)
|
||||
} else {
|
||||
drawCreatureWithShadow(context)
|
||||
}
|
||||
}
|
||||
|
||||
fun drawCreature(context : Context) {
|
||||
context.fillStyle = getGradient(context);
|
||||
context.fillCircle(position, radius)
|
||||
drawEye(context)
|
||||
drawTail(context)
|
||||
}
|
||||
|
||||
fun getGradient(context : Context) : CanvasGradient {
|
||||
val gradientCentre = position + directionToLogo * (radius / 4)
|
||||
val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius)
|
||||
for (colorStop in colorStops) {
|
||||
gradient.addColorStop(colorStop._1, colorStop._2)
|
||||
}
|
||||
return gradient;
|
||||
}
|
||||
|
||||
fun drawTail(context : Context) {
|
||||
val tailDirection = -directionToLogo;
|
||||
val tailPos = position + tailDirection * radius * 0.7
|
||||
val tailSize = radius * 1.6
|
||||
val angle = Math.PI / 6.0;
|
||||
val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize
|
||||
val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize
|
||||
context.fillStyle = getGradient(context)
|
||||
context.beginPath()
|
||||
context.moveTo(tailPos.x, tailPos.y)
|
||||
context.lineTo(p1.x, p1.y)
|
||||
val middlePoint = position + tailDirection * radius * 1.0
|
||||
context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y)
|
||||
context.lineTo(tailPos.x, tailPos.y)
|
||||
context.closePath()
|
||||
context.fill()
|
||||
}
|
||||
|
||||
fun drawEye(context : Context) {;
|
||||
val eyePos = directionToLogo * radius * 0.6 + position;
|
||||
val eyeRadius = radius / 3;
|
||||
val eyeLidRadius = eyeRadius / 2;
|
||||
context.fillStyle = "#FFFFFF";
|
||||
context.fillCircle(eyePos, eyeRadius)
|
||||
context.fillStyle = "#000000"
|
||||
context.fillCircle(eyePos, eyeLidRadius)
|
||||
}
|
||||
|
||||
fun drawCreatureWithShadow(context : Context) {
|
||||
context.save()
|
||||
setShadow(context)
|
||||
context.fillStyle = getGradient(context)
|
||||
context.fillCircle(position, radius)
|
||||
context.restore();
|
||||
drawEye(context)
|
||||
drawTail(context)
|
||||
}
|
||||
|
||||
fun setShadow(context : Context) {
|
||||
context.shadowColor = "rgba(100, 100, 100, 0.7)";
|
||||
context.shadowBlur = 5.0;
|
||||
context.shadowOffsetX = shadowOffset.x;
|
||||
context.shadowOffsetY = shadowOffset.y;
|
||||
}
|
||||
}
|
||||
|
||||
class CanvasState(val canvas : Canvas) {
|
||||
val width = canvas.width;
|
||||
val height = canvas.height;
|
||||
val context = getContext();
|
||||
var valid = false;
|
||||
var shapes = ArrayList<Shape>();
|
||||
var selection : Shape? = null;
|
||||
var dragOff = Vector();
|
||||
val interval = 1000 / 30;
|
||||
|
||||
{
|
||||
jq(canvas).mousedown {
|
||||
valid = false;
|
||||
selection = null;
|
||||
val mousePos = mousePos(it);
|
||||
for (shape in shapes) {
|
||||
if (mousePos in shape) {
|
||||
dragOff = mousePos - shape.pos;
|
||||
shape.selected = true;
|
||||
selection = shape;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mousemove {
|
||||
if (selection != null) {
|
||||
selection.sure().pos = mousePos(it) - dragOff;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
jq(canvas).mouseup {
|
||||
if (selection != null) {
|
||||
selection.sure().selected = false;
|
||||
}
|
||||
selection = null;
|
||||
valid = false;
|
||||
}
|
||||
|
||||
jq(canvas).dblclick {
|
||||
val redTransparentCircle = Creature(mousePos(it), this @CanvasState);
|
||||
addShape(redTransparentCircle);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
doWithPeriod(interval) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
fun mousePos(e : MouseEvent) : Vector {
|
||||
var offset = Vector();
|
||||
var element : DomElement? = canvas;
|
||||
while (element != null) {
|
||||
val el : DomElement = element.sure();
|
||||
offset += Vector(el.offsetLeft, el.offsetTop);
|
||||
element = el.offsetParent;
|
||||
}
|
||||
return Vector(e.pageX, e.pageY) - offset;
|
||||
}
|
||||
|
||||
fun addShape(shape : Shape) {
|
||||
shapes.add(shape);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
context.fillStyle = "#FFFFFF"
|
||||
context.fillRect(0.0, 0.0, width, height)
|
||||
context.strokeStyle = "#000000"
|
||||
context.lineWidth = 4.0;
|
||||
context.strokeRect(0.0, 0.0, width, height)
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
if (valid) return
|
||||
|
||||
clear();
|
||||
for (shape in shapes) {
|
||||
shape.draw(this);
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
class RadialGradientGenerator(val context : Context) {
|
||||
val gradients = ArrayList<Array<#(Double, String)>>();
|
||||
var current = 0
|
||||
|
||||
fun newColorStops(vararg colorStops : #(Double, String)) {
|
||||
gradients.add(colorStops)
|
||||
}
|
||||
|
||||
{
|
||||
newColorStops(#(0.0, "#F59898"), #(0.5, "#F57373"), #(1.0, "#DB6B6B"))
|
||||
newColorStops(#(0.39, "rgb(140,167,209)"), #(0.7, "rgb(104,139,209)"), #(0.85, "rgb(67,122,217)"))
|
||||
newColorStops(#(0.0, "rgb(255,222,255)"), #(0.5, "rgb(255,185,222)"), #(1.0, "rgb(230,154,185)"))
|
||||
newColorStops(#(0.0, "rgb(255,209,114)"), #(0.5, "rgb(255,174,81)"), #(1.0, "rgb(241,145,54)"))
|
||||
newColorStops(#(0.0, "rgb(132,240,135)"), #(0.5, "rgb(91,240,96)"), #(1.0, "rgb(27,245,41)"))
|
||||
newColorStops(#(0.0, "rgb(250,147,250)"), #(0.5, "rgb(255,80,255)"), #(1.0, "rgb(250,0,217)"))
|
||||
}
|
||||
|
||||
fun getNext() : Array<#(Double, String)> {
|
||||
val result = gradients.get(current)
|
||||
current = (current + 1) % gradients.size()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun v(x : Double, y : Double) = Vector(x, y);
|
||||
|
||||
class Vector(val x : Double = 0.0, val y : Double = 0.0) {
|
||||
fun plus(v : Vector) = v(x + v.x, y + v.y);
|
||||
fun minus() = v(-x, -y)
|
||||
fun minus(v : Vector) = v(x - v.x, y - v.y)
|
||||
fun times(coef : Double) = v(x * coef, y * coef)
|
||||
fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr)
|
||||
fun rotatedBy(theta : Double) : Vector {
|
||||
val sin = Math.sin(theta)
|
||||
val cos = Math.cos(theta)
|
||||
return v(x * cos - y * sin, x * sin + y * cos)
|
||||
}
|
||||
|
||||
fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
|
||||
(y >= topLeft.y) && (y <= topLeft.y + size.y)
|
||||
|
||||
val sqr : Double
|
||||
get() = x * x + y * y
|
||||
val normalized : Vector
|
||||
get() = this * (1.0 / Math.sqrt(sqr))
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val state = CanvasState(getCanvas());
|
||||
state.addShape(JB);
|
||||
setTimeout({
|
||||
state.valid = false
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
~ Copyright 2000-2012 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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Canvas demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<canvas height="450" width="800"></canvas>
|
||||
<script src="http://code.jquery.com/jquery-latest.js"></script>
|
||||
<script src="../../../../translator/testFiles/kotlin_lib.js" type="text/javascript"></script>
|
||||
<script src="../../../../translator/testFiles/canvas_helper.js" type="text/javascript"></script>
|
||||
<script src="interactive2.js" type="text/javascript"></script>
|
||||
<img src="jbLogo.png" hidden=true/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>
|
||||
+48
@@ -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.
|
||||
+23
@@ -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,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;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user