switched to using dartc.jar
deleted module js.ast
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
# 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>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
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.
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
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.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?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" />
|
|
||||||
<orderEntry type="library" name="js_libs" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module version="4">
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="guava-10.0.1" level="application" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use 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();
|
|
||||||
}
|
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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);
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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
@@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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();
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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();
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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();
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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();
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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();
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript regular expression.
|
|
||||||
*/
|
|
||||||
public final class JsRegExp extends JsValueLiteral {
|
|
||||||
|
|
||||||
private String flags;
|
|
||||||
private String pattern;
|
|
||||||
|
|
||||||
public JsRegExp() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFlags() {
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPattern() {
|
|
||||||
return pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanFalse() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanTrue() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNotNull() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNull() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFlags(String suffix) {
|
|
||||||
this.flags = suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPattern(String re) {
|
|
||||||
this.pattern = re;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
v.visit(this, ctx);
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.REGEXP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript return statement.
|
|
||||||
*/
|
|
||||||
public final class JsReturn extends JsStatement {
|
|
||||||
|
|
||||||
private JsExpression expr;
|
|
||||||
|
|
||||||
public JsReturn() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsReturn(JsExpression expr) {
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getExpr() {
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpr(JsExpression expr) {
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
if (expr != null) {
|
|
||||||
expr = v.accept(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean unconditionalControlBreak() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.RETURN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.JsReservedIdentifiers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The root scope is the parent of every scope. All identifiers in this scope
|
|
||||||
* are not obfuscatable. This scope is prefilled with reserved global
|
|
||||||
* JavaScript symbols.
|
|
||||||
*/
|
|
||||||
public final class JsRootScope extends JsScope {
|
|
||||||
|
|
||||||
private final JsProgram program;
|
|
||||||
|
|
||||||
public JsRootScope(JsProgram program) {
|
|
||||||
super("Root");
|
|
||||||
this.program = program;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsProgram getProgram() {
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JsName doCreateName(String ident, String shortIdent, String originalName) {
|
|
||||||
JsName name = super.doCreateName(ident, shortIdent, originalName);
|
|
||||||
name.setObfuscatable(false);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsName findExistingNameNoRecurse(String ident) {
|
|
||||||
JsName name = super.findExistingNameNoRecurse(ident);
|
|
||||||
if (name == null) {
|
|
||||||
if (JsReservedIdentifiers.getReservedGlobalSymbols().contains(ident)) {
|
|
||||||
/*
|
|
||||||
* Lazily add JsNames for reserved identifiers. Since a JsName for a reserved global symbol
|
|
||||||
* must report a legitimate enclosing scope, we can't simply have a shared set of symbol
|
|
||||||
* names.
|
|
||||||
*/
|
|
||||||
name = doCreateName(ident, ident, ident);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,308 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.util.Lists;
|
|
||||||
import com.google.dart.compiler.util.Maps;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A scope is a factory for creating and allocating
|
|
||||||
* {@link JsName}s. A JavaScript AST is
|
|
||||||
* built in terms of abstract name objects without worrying about obfuscation,
|
|
||||||
* keyword/identifier blacklisting, and so on.
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* Scopes are associated with
|
|
||||||
* {@link JsFunction}s, but the two are
|
|
||||||
* not equivalent. Functions <i>have</i> scopes, but a scope does not
|
|
||||||
* necessarily have an associated Function. Examples of this include the
|
|
||||||
* {@link JsRootScope} and synthetic
|
|
||||||
* scopes that might be created by a client.
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* Scopes can have parents to provide constraints when allocating actual
|
|
||||||
* identifiers for names. Specifically, names in child scopes are chosen such
|
|
||||||
* that they do not conflict with names in their parent scopes. The ultimate
|
|
||||||
* parent is usually the global scope (see
|
|
||||||
* {@link JsProgram#getRootScope()}),
|
|
||||||
* but parentless scopes are useful for managing names that are always accessed
|
|
||||||
* with a qualifier and could therefore never be confused with the global scope
|
|
||||||
* hierarchy.
|
|
||||||
*/
|
|
||||||
public class JsScope implements Serializable {
|
|
||||||
|
|
||||||
private List<JsScope> children = Collections.emptyList();
|
|
||||||
private final String description;
|
|
||||||
private Map<String, JsName> names = Collections.emptyMap();
|
|
||||||
private JsScope parent;
|
|
||||||
protected int tempIndex = 0;
|
|
||||||
private final String scopeId;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a scope with parent.
|
|
||||||
*/
|
|
||||||
public JsScope(JsScope parent, String description) {
|
|
||||||
this(parent, description, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a scope with parent.
|
|
||||||
*/
|
|
||||||
public JsScope(JsScope parent, String description, String scopeId) {
|
|
||||||
assert (parent != null);
|
|
||||||
this.scopeId = scopeId;
|
|
||||||
this.description = description;
|
|
||||||
this.parent = parent;
|
|
||||||
parent.children = Lists.add(parent.children, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rebase the function to a new scope.
|
|
||||||
*
|
|
||||||
* @param newParent The scope to add the function to.
|
|
||||||
*/
|
|
||||||
public void rebase(JsScope newParent) {
|
|
||||||
detachFromParent();
|
|
||||||
parent = newParent;
|
|
||||||
parent.children = Lists.add(parent.children, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rebase the function's children to a new scope.
|
|
||||||
*
|
|
||||||
* @param newParent
|
|
||||||
*/
|
|
||||||
public void rebaseChildScopes(JsScope newParent) {
|
|
||||||
if (newParent == this) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parent.children = Lists.addAll(parent.children, children);
|
|
||||||
for (JsScope child : children) {
|
|
||||||
child.parent = newParent;
|
|
||||||
}
|
|
||||||
children = Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses can detach and become parentless.
|
|
||||||
*/
|
|
||||||
protected void detachFromParent() {
|
|
||||||
JsScope oldParent = parent;
|
|
||||||
|
|
||||||
oldParent.children = Lists.remove(
|
|
||||||
parent.children, oldParent.children.indexOf(this));
|
|
||||||
|
|
||||||
parent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses can be parentless.
|
|
||||||
*/
|
|
||||||
protected JsScope(String description) {
|
|
||||||
this.description = description;
|
|
||||||
this.parent = null;
|
|
||||||
this.scopeId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a name object associated with the specified ident in this scope,
|
|
||||||
* creating it if necessary.<br/>
|
|
||||||
* If the JsName does not exist yet, a new JsName is created. The ident,
|
|
||||||
* short name, and original name of the newly created JsName are equal to
|
|
||||||
* the given ident.
|
|
||||||
*
|
|
||||||
* @param ident An identifier that is unique within this scope.
|
|
||||||
*/
|
|
||||||
public JsName declareName(String ident) {
|
|
||||||
JsName name = findExistingNameNoRecurse(ident);
|
|
||||||
if (name != null) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return doCreateName(ident, ident, ident);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new variable with an unique ident in this scope.
|
|
||||||
* The generated JsName is guaranteed to have an identifier (but not short
|
|
||||||
* name) that does not clash with any existing variables in the scope.
|
|
||||||
* Future declarations of variables might however clash with the temporary
|
|
||||||
* (unless they use this function).
|
|
||||||
*/
|
|
||||||
public JsName declareFreshName(String shortName) {
|
|
||||||
String ident = shortName;
|
|
||||||
int counter = 0;
|
|
||||||
while (findExistingNameNoRecurse(ident) != null) {
|
|
||||||
ident = shortName + "_" + counter++;
|
|
||||||
}
|
|
||||||
return doCreateName(ident, shortName, shortName);
|
|
||||||
}
|
|
||||||
|
|
||||||
String getNextTempName() {
|
|
||||||
// TODO(ngeoffray): Decide on a convention for temporary variables
|
|
||||||
// introduced by the compiler.
|
|
||||||
return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a temporary variable with an unique name in this scope.
|
|
||||||
* The generated temporary is guaranteed to have an identifier (but not short
|
|
||||||
* name) that does not clash with any existing variables in the scope.
|
|
||||||
* Future declarations of variables might however clash with the temporary.
|
|
||||||
*/
|
|
||||||
public JsName declareTemporary() {
|
|
||||||
return declareFreshName(getNextTempName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a name object associated with the specified ident in this scope,
|
|
||||||
* creating it if necessary.<br/>
|
|
||||||
* If the JsName does not exist yet, a new JsName is created with the given
|
|
||||||
* ident, short name and original name.
|
|
||||||
*
|
|
||||||
* @param ident An identifier that is unique within this scope.
|
|
||||||
* @param shortIdent A "pretty" name that does not have to be unique.
|
|
||||||
* @throws IllegalArgumentException if ident already exists in this scope but
|
|
||||||
* the requested short name does not match the existing short name.
|
|
||||||
*/
|
|
||||||
public JsName declareName(String ident, String shortIdent) {
|
|
||||||
return declareName(ident, shortIdent, ident);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a name object associated with the specified ident in this scope,
|
|
||||||
* creating it if necessary.<br/>
|
|
||||||
* If the JsName does not exist yet, a new JsName is created. The original
|
|
||||||
* name stored in the JsName is equal to the (unmangled) specified originalName.
|
|
||||||
*
|
|
||||||
* @param ident An identifier that is unique within this scope.
|
|
||||||
* @param shortIdent A "pretty" name that does not have to be unique.
|
|
||||||
* @param originalName The original name in the source.
|
|
||||||
* @throws IllegalArgumentException if ident already exists in this scope but
|
|
||||||
* the requested short name does not match the existing short name,
|
|
||||||
* or the original name does not match the existing original name.
|
|
||||||
*/
|
|
||||||
public JsName declareName(String ident, String shortIdent, String originalName) {
|
|
||||||
JsName name = findExistingNameNoRecurse(ident);
|
|
||||||
if (name != null) {
|
|
||||||
if (!name.getShortIdent().equals(shortIdent)
|
|
||||||
|| !nullableEquals(name.getOriginalName(), originalName)) {
|
|
||||||
throw new IllegalArgumentException("Requested short name " + shortIdent
|
|
||||||
+ " conflicts with preexisting short name " + name.getShortIdent() + " for identifier "
|
|
||||||
+ ident);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
return doCreateName(ident, shortIdent, originalName);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean nullableEquals(String s1, String s2) {
|
|
||||||
return (s1 == null) ? (s2 == null) : s1.equals(s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to find the name object for the specified ident, searching in this
|
|
||||||
* scope, and if not found, in the parent scopes.
|
|
||||||
*
|
|
||||||
* @return <code>null</code> if the identifier has no associated name
|
|
||||||
*/
|
|
||||||
public final JsName findExistingName(String ident) {
|
|
||||||
JsName name = findExistingNameNoRecurse(ident);
|
|
||||||
if (name == null && parent != null) {
|
|
||||||
return parent.findExistingName(ident);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to find an unobfuscatable name object for the specified ident,
|
|
||||||
* searching in this scope, and if not found, in the parent scopes.
|
|
||||||
*
|
|
||||||
* @return <code>null</code> if the identifier has no associated name
|
|
||||||
*/
|
|
||||||
public final JsName findExistingUnobfuscatableName(String ident) {
|
|
||||||
JsName name = findExistingNameNoRecurse(ident);
|
|
||||||
if (name != null && name.isObfuscatable()) {
|
|
||||||
name = null;
|
|
||||||
}
|
|
||||||
if (name == null && parent != null) {
|
|
||||||
return parent.findExistingUnobfuscatableName(ident);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator for all the names defined by this scope.
|
|
||||||
*/
|
|
||||||
public Iterator<JsName> getAllNames() {
|
|
||||||
return names.values().iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of this scope's child scopes.
|
|
||||||
*/
|
|
||||||
public final List<JsScope> getChildren() {
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the parent scope of this scope, or <code>null</code> if this is the
|
|
||||||
* root scope.
|
|
||||||
*/
|
|
||||||
public final JsScope getParent() {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the associated program.
|
|
||||||
*/
|
|
||||||
public JsProgram getProgram() {
|
|
||||||
assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent";
|
|
||||||
return parent.getProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String toString() {
|
|
||||||
if (parent != null) {
|
|
||||||
return description + "->" + parent;
|
|
||||||
} else {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new name in this scope.
|
|
||||||
*/
|
|
||||||
protected JsName doCreateName(String ident, String shortIdent, String originalName) {
|
|
||||||
JsName name = new JsName(this, ident, shortIdent, originalName);
|
|
||||||
names = Maps.putOrdered(names, ident, name);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to find the name object for the specified ident, searching in this
|
|
||||||
* scope only.
|
|
||||||
*
|
|
||||||
* @return <code>null</code> if the identifier has no associated name
|
|
||||||
*/
|
|
||||||
public JsName findExistingNameNoRecurse(String ident) {
|
|
||||||
return names.get(ident);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Checks whether this scope owns this name.
|
|
||||||
*/
|
|
||||||
public boolean ownsName(JsName name) {
|
|
||||||
return names.containsValue(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract base class for JavaScript statement objects.
|
|
||||||
*/
|
|
||||||
public abstract class JsStatement extends JsNode {
|
|
||||||
|
|
||||||
protected JsStatement() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this statement definitely causes an abrupt change in flow
|
|
||||||
* control.
|
|
||||||
*/
|
|
||||||
public boolean unconditionalControlBreak() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript string literal expression.
|
|
||||||
*/
|
|
||||||
public final class JsStringLiteral extends JsValueLiteral {
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
// These only get created by JsProgram so that they can be interned.
|
|
||||||
JsStringLiteral(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanFalse() {
|
|
||||||
return value.length() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanTrue() {
|
|
||||||
return value.length() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNotNull() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNull() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
v.visit(this, ctx);
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript switch statement.
|
|
||||||
*/
|
|
||||||
public class JsSwitch extends JsStatement {
|
|
||||||
|
|
||||||
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
|
|
||||||
private JsExpression expr;
|
|
||||||
|
|
||||||
public JsSwitch() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<JsSwitchMember> getCases() {
|
|
||||||
return cases;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getExpr() {
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpr(JsExpression expr) {
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
expr = v.accept(expr);
|
|
||||||
v.acceptWithInsertRemove(cases);
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.SWITCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A member/case in a JavaScript switch object.
|
|
||||||
*/
|
|
||||||
public abstract class JsSwitchMember extends JsNode {
|
|
||||||
|
|
||||||
protected final List<JsStatement> stmts = new ArrayList<JsStatement>();
|
|
||||||
|
|
||||||
protected JsSwitchMember() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<JsStatement> getStmts() {
|
|
||||||
return stmts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript <code>this</code> reference.
|
|
||||||
*/
|
|
||||||
public final class JsThisRef extends JsValueLiteral {
|
|
||||||
|
|
||||||
public JsThisRef() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanFalse() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBooleanTrue() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNotNull() {
|
|
||||||
/*
|
|
||||||
* You'd think that you could get a null this via function.call/apply, but
|
|
||||||
* in fact you can't: they just make this be the window object instead. So
|
|
||||||
* it really can't ever be null.
|
|
||||||
*/
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefinitelyNull() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
v.visit(this, ctx);
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.THIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript <code>throw</code> statement.
|
|
||||||
*/
|
|
||||||
public class JsThrow extends JsStatement {
|
|
||||||
|
|
||||||
private JsExpression expr;
|
|
||||||
|
|
||||||
public JsThrow() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsThrow(JsExpression expr) {
|
|
||||||
super();
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getExpr() {
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpr(JsExpression expr) {
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
expr = v.accept(expr);
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean unconditionalControlBreak() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.THROW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript <code>try</code> statement.
|
|
||||||
*/
|
|
||||||
public class JsTry extends JsStatement {
|
|
||||||
|
|
||||||
private final List<JsCatch> catches = new ArrayList<JsCatch>();
|
|
||||||
private JsBlock finallyBlock;
|
|
||||||
private JsBlock tryBlock;
|
|
||||||
|
|
||||||
public JsTry() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<JsCatch> getCatches() {
|
|
||||||
return catches;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsBlock getFinallyBlock() {
|
|
||||||
return finallyBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsBlock getTryBlock() {
|
|
||||||
return tryBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFinallyBlock(JsBlock block) {
|
|
||||||
this.finallyBlock = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTryBlock(JsBlock block) {
|
|
||||||
tryBlock = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
tryBlock = v.accept(tryBlock);
|
|
||||||
v.acceptWithInsertRemove(catches);
|
|
||||||
if (finallyBlock != null) {
|
|
||||||
finallyBlock = v.accept(finallyBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.TRY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript prefix or postfix operation.
|
|
||||||
*/
|
|
||||||
public abstract class JsUnaryOperation extends JsExpression {
|
|
||||||
|
|
||||||
private JsExpression arg;
|
|
||||||
|
|
||||||
private final JsUnaryOperator op;
|
|
||||||
|
|
||||||
public JsUnaryOperation(JsUnaryOperator op) {
|
|
||||||
this(op, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
|
|
||||||
super();
|
|
||||||
this.op = op;
|
|
||||||
this.arg = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getArg() {
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsUnaryOperator getOperator() {
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean hasSideEffects() {
|
|
||||||
return op.isModifying() || arg.hasSideEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setArg(JsExpression arg) {
|
|
||||||
this.arg = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (op.isModifying()) {
|
|
||||||
// The delete operator is practically like an assignment of undefined, so
|
|
||||||
// for practical purposes we're treating it as an lvalue.
|
|
||||||
arg = v.acceptLvalue(arg);
|
|
||||||
} else {
|
|
||||||
arg = v.accept(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript unary operator.
|
|
||||||
*/
|
|
||||||
public enum JsUnaryOperator implements JsOperator {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition
|
|
||||||
* (page 57)
|
|
||||||
*/
|
|
||||||
BIT_NOT("~", 14, PREFIX), DEC("--", 14, POSTFIX | PREFIX), DELETE("delete", 14, PREFIX), INC(
|
|
||||||
"++", 14, POSTFIX | PREFIX), NEG("-", 14, PREFIX), POS("+", 14, PREFIX),
|
|
||||||
NOT("!", 14, PREFIX), TYPEOF("typeof", 14, PREFIX), VOID("void", 14, PREFIX);
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
private final int precedence;
|
|
||||||
private final String symbol;
|
|
||||||
|
|
||||||
private JsUnaryOperator(String symbol, int precedence, int mask) {
|
|
||||||
this.symbol = symbol;
|
|
||||||
this.precedence = precedence;
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPrecedence() {
|
|
||||||
return precedence;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSymbol() {
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isKeyword() {
|
|
||||||
return this == DELETE || this == TYPEOF || this == VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLeftAssociative() {
|
|
||||||
return (mask & LEFT) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isModifying() {
|
|
||||||
return this == DEC || this == INC || this == DELETE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPrecedenceLessThan(JsOperator other) {
|
|
||||||
return precedence < other.getPrecedence();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidInfix() {
|
|
||||||
return (mask & INFIX) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidPostfix() {
|
|
||||||
return (mask & POSTFIX) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidPrefix() {
|
|
||||||
return (mask & PREFIX) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript string literal expression.
|
|
||||||
*/
|
|
||||||
public abstract class JsValueLiteral extends JsLiteral {
|
|
||||||
|
|
||||||
protected JsValueLiteral() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean hasSideEffects() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.common.SourceInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript <code>var</code> statement.
|
|
||||||
*/
|
|
||||||
public class JsVars extends JsStatement implements Iterable<JsVars.JsVar> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A var declared using the JavaScript <code>var</code> statement.
|
|
||||||
*/
|
|
||||||
public static class JsVar extends JsNode implements HasName {
|
|
||||||
|
|
||||||
private final JsName name;
|
|
||||||
private JsExpression initExpr;
|
|
||||||
|
|
||||||
public JsVar(JsName name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsVar(JsName name, JsExpression initExpr) {
|
|
||||||
this.name = name;
|
|
||||||
this.initExpr = initExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getInitExpr() {
|
|
||||||
return initExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsName getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInitExpr(JsExpression initExpr) {
|
|
||||||
this.initExpr = initExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
if (initExpr != null) {
|
|
||||||
initExpr = v.accept(initExpr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsVar setSourceRef(SourceInfo info) {
|
|
||||||
super.setSourceRef(info);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.VAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<JsVar> vars = new ArrayList<JsVar>();
|
|
||||||
|
|
||||||
public JsVars() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(JsVar var) {
|
|
||||||
vars.add(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumVars() {
|
|
||||||
return vars.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insert(JsVar var) {
|
|
||||||
vars.add(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return vars.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterator returns JsVar objects
|
|
||||||
@Override
|
|
||||||
public Iterator<JsVar> iterator() {
|
|
||||||
return vars.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
v.acceptWithInsertRemove(vars);
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.VARS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstracts the idea that a class can be traversed.
|
|
||||||
*/
|
|
||||||
public interface JsVisitable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Causes this object to have the visitor visit itself and its children.
|
|
||||||
*
|
|
||||||
* @param visitor the visitor that should traverse this node
|
|
||||||
* @param ctx the context of an existing traversal
|
|
||||||
*/
|
|
||||||
void traverse(JsVisitor visitor, JsContext ctx);
|
|
||||||
}
|
|
||||||
@@ -1,430 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implemented by nodes that will visit child nodes.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class JsVisitor {
|
|
||||||
|
|
||||||
protected static final JsContext LVALUE_CONTEXT = new JsContext() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canInsert() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertAfter(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertBefore(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLvalue() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeMe() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replaceMe(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canInsert() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canRemove() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertAfter(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertBefore(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLvalue() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeMe() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replaceMe(JsVisitable node) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public final <T extends JsVisitable> T accept(T node) {
|
|
||||||
return this.<T>doAccept(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <T extends JsVisitable> void acceptList(List<T> collection) {
|
|
||||||
doAcceptList(collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression acceptLvalue(JsExpression expr) {
|
|
||||||
return doAcceptLvalue(expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final <T extends JsVisitable> void acceptWithInsertRemove(List<T> collection) {
|
|
||||||
doAcceptWithInsertRemove(collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean didChange() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsArrayAccess x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsArrayLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsBinaryOperation x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsBlock x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsBooleanLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsBreak x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsCase x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsCatch x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsConditional x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsContinue x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsDebugger x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsDefault x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsDoWhile x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsEmpty x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsExprStmt x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsFor x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsForIn x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsFunction x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsIf x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsInvocation x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsLabel x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsNameRef x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsNew x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsNullLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsNumberLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsObjectLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsParameter x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsPostfixOperation x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsPrefixOperation x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsProgram x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsProgramFragment x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsPropertyInitializer x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsRegExp x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsReturn x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsStringLiteral x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsSwitch x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsThisRef x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsThrow x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsTry x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsVars.JsVar x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsVars x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endVisit(JsWhile x, JsContext ctx) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsArrayAccess x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsArrayLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsBinaryOperation x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsBlock x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsBooleanLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsBreak x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsCase x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsCatch x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsConditional x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsContinue x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsDebugger x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsDefault x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsDoWhile x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsEmpty x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsExprStmt x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsFor x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsForIn x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsFunction x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsIf x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsInvocation x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsLabel x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsNameRef x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsNew x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsNullLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsNumberLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsObjectLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsParameter x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsPostfixOperation x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsPrefixOperation x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsProgram x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsProgramFragment x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsRegExp x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsReturn x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsStringLiteral x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsSwitch x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsThisRef x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsThrow x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsTry x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsVars.JsVar x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsVars x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean visit(JsWhile x, JsContext ctx) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T extends JsVisitable> T doAccept(T node) {
|
|
||||||
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T extends JsVisitable> void doAcceptList(List<T> collection) {
|
|
||||||
for (T node : collection) {
|
|
||||||
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JsExpression doAcceptLvalue(JsExpression expr) {
|
|
||||||
doTraverse(expr, LVALUE_CONTEXT);
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <T extends JsVisitable> void doAcceptWithInsertRemove(List<T> collection) {
|
|
||||||
for (T node : collection) {
|
|
||||||
doTraverse(node, UNMODIFIABLE_CONTEXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void doTraverse(JsVisitable node, JsContext ctx) {
|
|
||||||
node.traverse(this, ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A JavaScript <code>while</code> statement.
|
|
||||||
*/
|
|
||||||
public class JsWhile extends JsStatement {
|
|
||||||
|
|
||||||
private JsStatement body;
|
|
||||||
private JsExpression condition;
|
|
||||||
|
|
||||||
public JsWhile() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsWhile(JsExpression condition, JsStatement body) {
|
|
||||||
this.condition = condition;
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsStatement getBody() {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsExpression getCondition() {
|
|
||||||
return condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBody(JsStatement body) {
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCondition(JsExpression condition) {
|
|
||||||
this.condition = condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void traverse(JsVisitor v, JsContext ctx) {
|
|
||||||
if (v.visit(this, ctx)) {
|
|
||||||
condition = v.accept(condition);
|
|
||||||
body = v.accept(body);
|
|
||||||
}
|
|
||||||
v.endVisit(this, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeKind getKind() {
|
|
||||||
return NodeKind.WHILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.backend.js.ast;
|
|
||||||
|
|
||||||
public enum NodeKind {
|
|
||||||
ARRAY_ACCESS,
|
|
||||||
ARRAY,
|
|
||||||
BINARY_OP,
|
|
||||||
BLOCK,
|
|
||||||
BOOLEAN,
|
|
||||||
BREAK,
|
|
||||||
CASE,
|
|
||||||
CATCH,
|
|
||||||
CONDITIONAL,
|
|
||||||
CONTINUE,
|
|
||||||
DEBUGGER,
|
|
||||||
DEFAULT,
|
|
||||||
DO,
|
|
||||||
EMPTY,
|
|
||||||
EXPR_STMT,
|
|
||||||
FOR,
|
|
||||||
FOR_IN,
|
|
||||||
FUNCTION,
|
|
||||||
IF,
|
|
||||||
INVOKE,
|
|
||||||
LABEL,
|
|
||||||
NAME_REF,
|
|
||||||
NEW,
|
|
||||||
NULL,
|
|
||||||
NUMBER,
|
|
||||||
OBJECT,
|
|
||||||
PARAMETER,
|
|
||||||
POSTFIX_OP,
|
|
||||||
PREFIX_OP,
|
|
||||||
PROGRAM,
|
|
||||||
PROGRAM_FRAGMENT,
|
|
||||||
PROPERTY_INIT,
|
|
||||||
REGEXP,
|
|
||||||
RETURN,
|
|
||||||
STRING,
|
|
||||||
SWITCH,
|
|
||||||
THIS,
|
|
||||||
THROW,
|
|
||||||
TRY,
|
|
||||||
VARS,
|
|
||||||
VAR,
|
|
||||||
WHILE
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.common;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.Source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract base class for nodes that carry source information.
|
|
||||||
*/
|
|
||||||
public class AbstractNode implements SourceInfo, HasSourceInfo {
|
|
||||||
|
|
||||||
// TODO(johnlenz): All this source location data is wasteful.
|
|
||||||
// Move it into a com.google.dart.compiler.backend.common object, that can be shared between the ASTs
|
|
||||||
// or something.
|
|
||||||
protected Source source = null;
|
|
||||||
protected int sourceLine = -1;
|
|
||||||
protected int sourceColumn = -1;
|
|
||||||
protected int sourceStart = -1;
|
|
||||||
protected int sourceLength = -1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Source getSource() {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceLine() {
|
|
||||||
return sourceLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceColumn() {
|
|
||||||
return sourceColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceStart() {
|
|
||||||
return sourceStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSourceLength() {
|
|
||||||
return sourceLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourceInfo getSourceInfo() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSourceInfo(SourceInfo info) {
|
|
||||||
source = info.getSource();
|
|
||||||
sourceStart = info.getSourceStart();
|
|
||||||
sourceLength = info.getSourceLength();
|
|
||||||
sourceLine = info.getSourceLine();
|
|
||||||
sourceColumn = info.getSourceColumn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void setSourceLocation(
|
|
||||||
Source source, int line, int column, int startPosition, int length) {
|
|
||||||
assert (startPosition != -1 && length >= 0
|
|
||||||
|| startPosition == -1 && length == 0);
|
|
||||||
this.source = source;
|
|
||||||
this.sourceLine = line;
|
|
||||||
this.sourceColumn = column;
|
|
||||||
this.sourceStart = startPosition;
|
|
||||||
this.sourceLength = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setSourceRange(int startPosition, int length) {
|
|
||||||
assert (startPosition != -1 && length >= 0
|
|
||||||
|| startPosition == -1 && length == 0);
|
|
||||||
this.sourceStart = startPosition;
|
|
||||||
this.sourceLength = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.common;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.Source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract view of a class that has source info.
|
|
||||||
*/
|
|
||||||
public interface HasSourceInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the source info associated with this object.
|
|
||||||
*/
|
|
||||||
SourceInfo getSourceInfo();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the source info associated with this object. May only be called once.
|
|
||||||
* @param info
|
|
||||||
*/
|
|
||||||
void setSourceInfo(SourceInfo info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the source range of the original source file where the source fragment
|
|
||||||
* corresponding to this node was found.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Each node in the subtree (other than the contrived nodes) carries source
|
|
||||||
* range(s) information relating back to positions in the given source (the
|
|
||||||
* given source itself is not remembered with the AST). The source range
|
|
||||||
* usually begins at the first character of the first token corresponding to
|
|
||||||
* the node; leading whitespace and comments are <b>not</b> included. The
|
|
||||||
* source range usually extends through the last character of the last token
|
|
||||||
* corresponding to the node; trailing whitespace and comments are <b>not</b>
|
|
||||||
* included. There are a handful of exceptions (including the various body
|
|
||||||
* declarations). Source ranges nest properly: the source range for a child is
|
|
||||||
* always within the source range of its parent, and the source ranges of
|
|
||||||
* sibling nodes never overlap.
|
|
||||||
*
|
|
||||||
* @param source the associated source
|
|
||||||
* @param line the 1-based line index, or <code>-1</code>, if no source
|
|
||||||
* location is available
|
|
||||||
* @param column the 1-based column index, or <code>-1</code>, if no source
|
|
||||||
* location is available
|
|
||||||
* @param startPosition a 0-based character index, or <code>-1</code>, if no
|
|
||||||
* source location is available
|
|
||||||
* @param length a (possibly 0) length, or <code>-1</code>, if no source
|
|
||||||
* location is available
|
|
||||||
* @see SourceInfo#getSourceStart()
|
|
||||||
* @see SourceInfo#getSourceLength()
|
|
||||||
*/
|
|
||||||
void setSourceLocation(Source source, int line, int column, int startPosition, int length);
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.common;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instead of Strings, we use GlobalNames to abstract the underlying representation.
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>GlobalNames are globally unique and use identity for equality.</li>
|
|
||||||
* <li>GlobalNames are interned, so all references to the same name use the same
|
|
||||||
* bytes.</li>
|
|
||||||
* </ul>
|
|
||||||
* TODO(scottb): use byte[] instead of char[] when the parser is rewritten
|
|
||||||
* to parse byte[].
|
|
||||||
*/
|
|
||||||
public final class Name implements Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The encoding this class uses when converting between chars and bytes.
|
|
||||||
*/
|
|
||||||
public static final Charset CHARSET = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
private static final NameFactory factory = new NameFactory();
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 0L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Name corresponding to the data. An internal reference to
|
|
||||||
* <code>data</code> is kept for efficiency, do NOT mutate data after calling
|
|
||||||
* this method.
|
|
||||||
*/
|
|
||||||
public static Name of(char[] data) {
|
|
||||||
return factory.of(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Name corresponding to the data. An internal copy of the data is
|
|
||||||
* made.
|
|
||||||
*/
|
|
||||||
public static Name of(char[] data, int offset, int length) {
|
|
||||||
return factory.of(data, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int computeHashCode(char[] data, int offset, int length) {
|
|
||||||
// Effective Java Item 9.
|
|
||||||
int result = 89;
|
|
||||||
for (int i = offset, end = offset + length; i < end; ++i) {
|
|
||||||
result *= 31;
|
|
||||||
result += data[i];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
final char[] data;
|
|
||||||
|
|
||||||
private final transient int hashCode;
|
|
||||||
|
|
||||||
Name(char[] data, int hashCode) {
|
|
||||||
this.data = data;
|
|
||||||
this.hashCode = hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always compares based on identity.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return this == obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hashCode of the underlying data.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a String to represent the internal data.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.valueOf(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write my data into a {@link java.io.OutputStream} using the encoding specified in
|
|
||||||
* {@link #CHARSET}.
|
|
||||||
*/
|
|
||||||
public void writeBytesTo(OutputStream out) throws IOException {
|
|
||||||
// TODO(scottb): avoid allocating the String.
|
|
||||||
out.write(new String(data).getBytes(CHARSET));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write my character data into a {@link java.io.PrintStream}.
|
|
||||||
*/
|
|
||||||
public void writeCharsTo(PrintStream out) {
|
|
||||||
out.print(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write my character data into a {@link java.io.Writer}.
|
|
||||||
*/
|
|
||||||
public void writeCharsTo(Writer writer) throws IOException {
|
|
||||||
writer.write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace with the canonical instance.
|
|
||||||
*/
|
|
||||||
private Object readResolve() {
|
|
||||||
return Name.of(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.common;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
|
|
||||||
import java.lang.ref.ReferenceQueue;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the life cycle, uniqueness, and object identity invariants of
|
|
||||||
* {@link Name}.
|
|
||||||
*/
|
|
||||||
final class NameFactory {
|
|
||||||
/*
|
|
||||||
* TODO: does this actually save memory in practice? For each interned Name,
|
|
||||||
* we use:
|
|
||||||
*
|
|
||||||
* 1) The data array (n bytes).
|
|
||||||
*
|
|
||||||
* 2) The Name object (2 fields)
|
|
||||||
*
|
|
||||||
* 3) The RealKey (1 field + 4 fields from Reference).
|
|
||||||
*
|
|
||||||
* 4) ConcurrentMap.Entry (4 fields)
|
|
||||||
*
|
|
||||||
* Of course, a Map is really much heavier than we need, all we really need is
|
|
||||||
* a Set where you can retrieve an object already in the Set. A bare linear
|
|
||||||
* probe hash table of RealKey would let us get rid of the Entry object.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The whole point of this class is to cheaply create a light-weight key that
|
|
||||||
* doesn't need to make its own copy of the data. This object is constructed
|
|
||||||
* with equality semantics to {com.google.dart.compiler.backend.common.NameFactory.RealKey}, for doing cheap map lookups.
|
|
||||||
*/
|
|
||||||
private static final class FakeKey {
|
|
||||||
private final char[] data;
|
|
||||||
private final int hashCode;
|
|
||||||
private final int length;
|
|
||||||
private final int offset;
|
|
||||||
|
|
||||||
public FakeKey(char[] data, int hashCode) {
|
|
||||||
this(data, 0, data.length, hashCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FakeKey(char[] data, int offset, int length, int hashCode) {
|
|
||||||
this.data = data;
|
|
||||||
this.offset = offset;
|
|
||||||
this.length = length;
|
|
||||||
this.hashCode = hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
/*
|
|
||||||
* NOTE: this ONLY WORKS for comparisons to RealKey. But that's all we
|
|
||||||
* need since we only store real keys in the map.
|
|
||||||
*/
|
|
||||||
Name name = ((RealKey) obj).get();
|
|
||||||
if (name == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return equalsName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equalsName(Name name) {
|
|
||||||
if (this.length != name.data.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int itMine = this.offset;
|
|
||||||
int itTheirs = 0;
|
|
||||||
int endMine = this.offset + this.length;
|
|
||||||
while (itMine < endMine) {
|
|
||||||
if (this.data[itMine++] != name.data[itTheirs++]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "FakeKey(" + String.valueOf(data, offset, length) + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapted from {@link com.google.common.collect.Interners#newWeakInterner()}.
|
|
||||||
*/
|
|
||||||
private static final class RealKey extends WeakReference<Name> {
|
|
||||||
/**
|
|
||||||
* Must store the hashCode locally so we can be removed from
|
|
||||||
* {com.google.dart.compiler.backend.common.NameFactory#map} after our referent is cleared.
|
|
||||||
*/
|
|
||||||
private final int hashCode;
|
|
||||||
|
|
||||||
public RealKey(Name name, ReferenceQueue<Name> queue) {
|
|
||||||
super(name, queue);
|
|
||||||
hashCode = name.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == this) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj instanceof FakeKey) {
|
|
||||||
Name referent = get();
|
|
||||||
if (referent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return ((FakeKey) obj).equalsName(referent);
|
|
||||||
}
|
|
||||||
if (obj instanceof RealKey) {
|
|
||||||
Name referent = get();
|
|
||||||
if (referent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Name otherReferent = ((RealKey) obj).get();
|
|
||||||
if (otherReferent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Arrays.equals(referent.data, otherReferent.data);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
Name referent = get();
|
|
||||||
return "RealKey(" + referent + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ConcurrentMap<Object, RealKey> map = new MapMaker().makeMap();
|
|
||||||
private final ReferenceQueue<Name> queue = new ReferenceQueue<Name>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Name corresponding to the data. An internal reference to
|
|
||||||
* <code>data</code> may be kept.
|
|
||||||
*/
|
|
||||||
public Name of(char[] data) {
|
|
||||||
cleanUp();
|
|
||||||
int hashCode = Name.computeHashCode(data, 0, data.length);
|
|
||||||
FakeKey fakeKey = new FakeKey(data, hashCode);
|
|
||||||
Name result = get(fakeKey);
|
|
||||||
if (result == null) {
|
|
||||||
result = put(new Name(data, hashCode));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Name corresponding to the data. An internal copy of the data is
|
|
||||||
* made.
|
|
||||||
*/
|
|
||||||
public Name of(char[] data, int offset, int length) {
|
|
||||||
cleanUp();
|
|
||||||
int hashCode = Name.computeHashCode(data, offset, length);
|
|
||||||
FakeKey fakeKey = new FakeKey(data, offset, length, hashCode);
|
|
||||||
Name result = get(fakeKey);
|
|
||||||
if (result == null) {
|
|
||||||
char[] copy = new char[length];
|
|
||||||
System.arraycopy(data, offset, copy, 0, length);
|
|
||||||
result = put(new Name(copy, hashCode));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
void cleanUp() {
|
|
||||||
RealKey item;
|
|
||||||
while ((item = (RealKey) queue.poll()) != null) {
|
|
||||||
map.remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
WeakReference<Name> getRefFor(Name name) {
|
|
||||||
return map.get(new FakeKey(name.data, name.hashCode()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
int numEntries() {
|
|
||||||
return map.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Name get(FakeKey fakeKey) {
|
|
||||||
RealKey realKey = map.get(fakeKey);
|
|
||||||
if (realKey != null) {
|
|
||||||
return realKey.get();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Name put(Name name) {
|
|
||||||
RealKey realKey = new RealKey(name, queue);
|
|
||||||
while (true) {
|
|
||||||
RealKey sneakyRef = map.putIfAbsent(realKey, realKey);
|
|
||||||
if (sneakyRef == null) {
|
|
||||||
return name;
|
|
||||||
} else {
|
|
||||||
Name canonical = sneakyRef.get();
|
|
||||||
if (canonical != null) {
|
|
||||||
return canonical;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.common;
|
|
||||||
import com.google.dart.compiler.Source;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks file and line information for AST nodes.
|
|
||||||
*/
|
|
||||||
public interface SourceInfo extends Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The source code provider.
|
|
||||||
*/
|
|
||||||
Source getSource();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return A 1-based line number into the original source file indicating
|
|
||||||
* where the source fragment begins.
|
|
||||||
*/
|
|
||||||
int getSourceLine();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return A 1-based column number into the original source file indicating
|
|
||||||
* where the source fragment begins.
|
|
||||||
*/
|
|
||||||
int getSourceColumn();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the character index into the original source file indicating
|
|
||||||
* where the source fragment corresponding to this node begins.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
|
||||||
*
|
|
||||||
* @return the 0-based character index, or <code>-1</code>
|
|
||||||
* if no source startPosition information is recorded for this node
|
|
||||||
* @see #getSourceLength()
|
|
||||||
* @see HasSourceInfo#setSourceLocation(com.google.dart.compiler.Source, int, int, int, int)
|
|
||||||
*/
|
|
||||||
int getSourceStart();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the length in characters of the original source file indicating
|
|
||||||
* where the source fragment corresponding to this node ends.
|
|
||||||
* <p>
|
|
||||||
* The parser supplies useful well-defined source ranges to the nodes it creates.
|
|
||||||
*
|
|
||||||
* @return a (possibly 0) length, or <code>0</code>
|
|
||||||
* if no source source position information is recorded for this node
|
|
||||||
* @see #getSourceStart()
|
|
||||||
* @see HasSourceInfo#setSourceLocation(com.google.dart.compiler.Source, int, int, int, int)
|
|
||||||
*/
|
|
||||||
int getSourceLength();
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstract base type to build TextOutput implementations.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractTextOutput implements TextOutput {
|
|
||||||
private final boolean compact;
|
|
||||||
private int identLevel = 0;
|
|
||||||
private int indentGranularity = 2;
|
|
||||||
private char[][] indents = new char[][] {new char[0]};
|
|
||||||
private boolean justNewlined;
|
|
||||||
private PrintWriter out;
|
|
||||||
private int position = 0;
|
|
||||||
private int line = 0;
|
|
||||||
private int column = 0;
|
|
||||||
|
|
||||||
protected AbstractTextOutput(boolean compact) {
|
|
||||||
this.compact = compact;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLine() {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getColumn() {
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void indentIn() {
|
|
||||||
++identLevel;
|
|
||||||
if (identLevel >= indents.length) {
|
|
||||||
// Cache a new level of indentation string.
|
|
||||||
//
|
|
||||||
char[] newIndentLevel = new char[identLevel * indentGranularity];
|
|
||||||
Arrays.fill(newIndentLevel, ' ');
|
|
||||||
char[][] newIndents = new char[indents.length + 1][];
|
|
||||||
System.arraycopy(indents, 0, newIndents, 0, indents.length);
|
|
||||||
newIndents[identLevel] = newIndentLevel;
|
|
||||||
indents = newIndents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void indentOut() {
|
|
||||||
--identLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newline() {
|
|
||||||
out.print('\n');
|
|
||||||
position++;
|
|
||||||
line++;
|
|
||||||
column = 0;
|
|
||||||
justNewlined = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void newlineOpt() {
|
|
||||||
if (!compact) {
|
|
||||||
newline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void print(char c) {
|
|
||||||
maybeIndent();
|
|
||||||
out.print(c);
|
|
||||||
position++;
|
|
||||||
column++;
|
|
||||||
justNewlined = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void print(char[] s) {
|
|
||||||
maybeIndent();
|
|
||||||
printAndCount(s);
|
|
||||||
justNewlined = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void print(String s) {
|
|
||||||
maybeIndent();
|
|
||||||
printAndCount(s.toCharArray());
|
|
||||||
justNewlined = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Why don't the "Opt" methods update "justNewLined"?
|
|
||||||
public void printOpt(char c) {
|
|
||||||
if (!compact) {
|
|
||||||
maybeIndent();
|
|
||||||
out.print(c);
|
|
||||||
position += 1;
|
|
||||||
column++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printOpt(char[] s) {
|
|
||||||
if (!compact) {
|
|
||||||
maybeIndent();
|
|
||||||
printAndCount(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printOpt(String s) {
|
|
||||||
if (!compact) {
|
|
||||||
maybeIndent();
|
|
||||||
printAndCount(s.toCharArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setPrintWriter(PrintWriter out) {
|
|
||||||
this.out = out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeIndent() {
|
|
||||||
if (justNewlined && !compact) {
|
|
||||||
printAndCount(indents[identLevel]);
|
|
||||||
justNewlined = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printAndCount(char[] chars) {
|
|
||||||
position += chars.length;
|
|
||||||
column += chars.length;
|
|
||||||
out.print(chars);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,404 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.InternalCompilerException;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
|
||||||
import com.google.dart.compiler.common.SourceInfo;
|
|
||||||
import com.sun.istack.internal.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author johnlenz@google.com (John Lenz)
|
|
||||||
*/
|
|
||||||
public class AstUtil {
|
|
||||||
|
|
||||||
public static JsInvocation newInvocation(
|
|
||||||
JsExpression target, JsExpression... params) {
|
|
||||||
JsInvocation invoke = new JsInvocation();
|
|
||||||
invoke.setQualifier(target);
|
|
||||||
for (JsExpression expr : params) {
|
|
||||||
invoke.getArguments().add(expr);
|
|
||||||
}
|
|
||||||
return invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsInvocation newInvocation(
|
|
||||||
JsExpression target, List<JsExpression> params) {
|
|
||||||
JsInvocation invoke = new JsInvocation();
|
|
||||||
invoke.setQualifier(target);
|
|
||||||
for (JsExpression expr : params) {
|
|
||||||
invoke.getArguments().add(expr);
|
|
||||||
}
|
|
||||||
return invoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef newQualifiedNameRef(String name) {
|
|
||||||
JsNameRef node = null;
|
|
||||||
int endPos = -1;
|
|
||||||
int startPos = 0;
|
|
||||||
do {
|
|
||||||
endPos = name.indexOf('.', startPos);
|
|
||||||
String part = (endPos == -1
|
|
||||||
? name.substring(startPos)
|
|
||||||
: name.substring(startPos, endPos));
|
|
||||||
node = newNameRef(node, part);
|
|
||||||
startPos = endPos + 1;
|
|
||||||
} while (endPos != -1);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef newNameRef(JsExpression qualifier, String prop) {
|
|
||||||
JsNameRef nameRef = new JsNameRef(prop);
|
|
||||||
if (qualifier != null) {
|
|
||||||
nameRef.setQualifier(qualifier);
|
|
||||||
}
|
|
||||||
return nameRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef nameref(SourceInfo info, JsName qualifier, JsName prop) {
|
|
||||||
JsNameRef nameRef = new JsNameRef(prop);
|
|
||||||
if (qualifier != null) {
|
|
||||||
nameRef.setQualifier(qualifier.makeRef());
|
|
||||||
}
|
|
||||||
nameRef.setSourceRef(info);
|
|
||||||
return nameRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef newNameRef(JsExpression qualifier, JsName prop) {
|
|
||||||
JsNameRef nameRef = new JsNameRef(prop);
|
|
||||||
if (qualifier != null) {
|
|
||||||
nameRef.setQualifier(qualifier);
|
|
||||||
}
|
|
||||||
return nameRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef newPrototypeNameRef(JsExpression qualifier) {
|
|
||||||
return newNameRef(qualifier, "prototype");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsArrayAccess newArrayAccess(JsExpression target, JsExpression key) {
|
|
||||||
JsArrayAccess arr = new JsArrayAccess();
|
|
||||||
arr.setArrayExpr(target);
|
|
||||||
arr.setIndexExpr(key);
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBlock newBlock(JsStatement... stmts) {
|
|
||||||
JsBlock jsBlock = new JsBlock();
|
|
||||||
for (JsStatement stmt : stmts) {
|
|
||||||
jsBlock.getStatements().add(stmt);
|
|
||||||
}
|
|
||||||
return jsBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a sequence of expressions (using the binary sequence operator).
|
|
||||||
*
|
|
||||||
* @param exprs - expressions to add to sequence
|
|
||||||
* @return a sequence of expressions.
|
|
||||||
*/
|
|
||||||
public static JsBinaryOperation newSequence(JsExpression... exprs) {
|
|
||||||
if (exprs.length < 2) {
|
|
||||||
throw new InternalCompilerException("newSequence expects at least two arguments");
|
|
||||||
}
|
|
||||||
JsExpression result = exprs[exprs.length - 1];
|
|
||||||
for (int i = exprs.length - 2; i >= 0; i--) {
|
|
||||||
result = new JsBinaryOperation(JsBinaryOperator.COMMA, exprs[i], result);
|
|
||||||
}
|
|
||||||
return (JsBinaryOperation) result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure a valid LHS
|
|
||||||
public static JsBinaryOperation newAssignment(
|
|
||||||
JsNameRef nameRef, JsExpression expr) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.ASG, nameRef, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation newAssignment(
|
|
||||||
JsArrayAccess target, JsExpression expr) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.ASG, target, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsVars newVar(SourceInfo info, JsName name, JsExpression expr) {
|
|
||||||
JsVars.JsVar var = new JsVars.JsVar(name).setSourceRef(info);
|
|
||||||
var.setInitExpr(expr);
|
|
||||||
JsVars vars = new JsVars();
|
|
||||||
vars.add(var);
|
|
||||||
return vars;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsVars newVar(JsName name, JsExpression expr) {
|
|
||||||
JsVars.JsVar var = new JsVars.JsVar(name);
|
|
||||||
if (expr != null) {
|
|
||||||
var.setInitExpr(expr);
|
|
||||||
}
|
|
||||||
JsVars vars = new JsVars();
|
|
||||||
vars.add(var);
|
|
||||||
return vars;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsSwitch newSwitch(
|
|
||||||
JsExpression expr, JsSwitchMember... cases) {
|
|
||||||
JsSwitch jsSwitch = new JsSwitch();
|
|
||||||
jsSwitch.setExpr(expr);
|
|
||||||
for (JsSwitchMember jsCase : cases) {
|
|
||||||
jsSwitch.getCases().add(jsCase);
|
|
||||||
}
|
|
||||||
return jsSwitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsCase newCase(JsExpression expr, JsStatement... stmts) {
|
|
||||||
JsCase jsCase = new JsCase();
|
|
||||||
jsCase.setCaseExpr(expr);
|
|
||||||
for (JsStatement stmt : stmts) {
|
|
||||||
jsCase.getStmts().add(stmt);
|
|
||||||
}
|
|
||||||
return jsCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsDefault newDefaultCase(JsStatement... stmts) {
|
|
||||||
JsDefault jsCase = new JsDefault();
|
|
||||||
for (JsStatement stmt : stmts) {
|
|
||||||
jsCase.getStmts().add(stmt);
|
|
||||||
}
|
|
||||||
return jsCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsFunction newFunction(
|
|
||||||
JsScope scope, JsName name, List<JsParameter> params, JsBlock body) {
|
|
||||||
JsFunction fn = new JsFunction(scope);
|
|
||||||
if (name != null) {
|
|
||||||
fn.setName(name);
|
|
||||||
}
|
|
||||||
if (params != null) {
|
|
||||||
for (JsParameter param : params) {
|
|
||||||
fn.getParameters().add(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn.setBody(body);
|
|
||||||
return fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsInvocation call(SourceInfo src, JsExpression target, JsExpression... params) {
|
|
||||||
return (JsInvocation) newInvocation(target, params).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation comma(SourceInfo src, JsExpression op1, JsExpression op2) {
|
|
||||||
return (JsBinaryOperation) new JsBinaryOperation(JsBinaryOperator.COMMA, op1, op2)
|
|
||||||
.setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef nameref(SourceInfo src, String name) {
|
|
||||||
return (JsNameRef) new JsNameRef(name).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef nameref(SourceInfo src, JsName qualifier, String prop) {
|
|
||||||
return nameref(src, qualifier.makeRef().setSourceRef(src), prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef nameref(SourceInfo src, JsExpression qualifier, String prop) {
|
|
||||||
return (JsNameRef) newNameRef(qualifier, prop).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression assign(SourceInfo src, JsNameRef op1, JsExpression op2) {
|
|
||||||
return newAssignment(op1, op2).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression neq(SourceInfo src, JsExpression op1, JsExpression op2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.NEQ, op1, op2).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression not(SourceInfo src, JsExpression op1) {
|
|
||||||
return new JsPrefixOperation(JsUnaryOperator.NOT, op1).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression preinc(SourceInfo src, JsExpression op1) {
|
|
||||||
return new JsPrefixOperation(JsUnaryOperator.INC, op1).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression and(SourceInfo src, JsExpression op1, JsExpression op2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.AND, op1, op2).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression in(SourceInfo src, JsExpression propName, JsExpression obj) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.INOP, propName, obj).setSourceRef(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Pavel Talanov
|
|
||||||
public static JsPropertyInitializer newNamedMethod(JsName name, JsFunction function) {
|
|
||||||
JsNameRef methodName = name.makeRef();
|
|
||||||
return new JsPropertyInitializer(methodName, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsStatement convertToStatement(JsNode jsNode) {
|
|
||||||
assert (jsNode instanceof JsExpression) || (jsNode instanceof JsStatement)
|
|
||||||
: "Unexpected node of type: " + jsNode.getClass().toString();
|
|
||||||
if (jsNode instanceof JsExpression) {
|
|
||||||
return new JsExprStmt((JsExpression) jsNode);
|
|
||||||
}
|
|
||||||
return (JsStatement) jsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBlock convertToBlock(JsNode jsNode) {
|
|
||||||
if (jsNode instanceof JsBlock) {
|
|
||||||
return (JsBlock) jsNode;
|
|
||||||
}
|
|
||||||
JsStatement jsStatement = convertToStatement(jsNode);
|
|
||||||
return new JsBlock(jsStatement);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression convertToExpression(JsNode jsNode) {
|
|
||||||
assert jsNode instanceof JsExpression : "Unexpected node of type: " + jsNode.getClass().toString();
|
|
||||||
return (JsExpression) jsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsNameRef thisQualifiedReference(JsName name) {
|
|
||||||
JsNameRef result = name.makeRef();
|
|
||||||
result.setQualifier(new JsThisRef());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBlock newBlock(List<JsStatement> statements) {
|
|
||||||
JsBlock result = new JsBlock();
|
|
||||||
result.setStatements(statements);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsPrefixOperation negated(JsExpression expression) {
|
|
||||||
return new JsPrefixOperation(JsUnaryOperator.NOT, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsStatement newAssignmentStatement(JsNameRef nameRef, JsExpression expr) {
|
|
||||||
return convertToStatement(new JsBinaryOperation(JsBinaryOperator.ASG, nameRef, expr));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression extractExpressionFromStatement(JsStatement statement) {
|
|
||||||
assert statement instanceof JsExprStmt : "Cannot extract expression from statement: " + statement;
|
|
||||||
return (((JsExprStmt) statement).getExpression());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation and(JsExpression op1, JsExpression op2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.AND, op1, op2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation or(JsExpression op1, JsExpression op2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO refactor
|
|
||||||
public static void setQualifier(JsExpression selector, JsExpression receiver) {
|
|
||||||
if (selector instanceof JsInvocation) {
|
|
||||||
setQualifier(((JsInvocation) selector).getQualifier(), receiver);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (selector instanceof JsNameRef) {
|
|
||||||
JsNameRef nameRef = (JsNameRef) selector;
|
|
||||||
JsExpression qualifier = nameRef.getQualifier();
|
|
||||||
if (qualifier == null) {
|
|
||||||
nameRef.setQualifier(receiver);
|
|
||||||
} else {
|
|
||||||
setQualifier(qualifier, receiver);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Set qualifier should be applied only to JsInvocation or JsNameRef instances");
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: look for should-be-usages
|
|
||||||
public static JsNameRef qualified(JsName selector, JsExpression qualifier) {
|
|
||||||
JsNameRef reference = selector.makeRef();
|
|
||||||
AstUtil.setQualifier(reference, qualifier);
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation equals(JsExpression arg1, JsExpression arg2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.EQ, arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation notEqual(JsExpression arg1, JsExpression arg2) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.NEQ, arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression equalsTrue(JsExpression expression, JsProgram program) {
|
|
||||||
return equals(expression, program.getTrueLiteral());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsExpression assignment(JsExpression left, JsExpression right) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.ASG, left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation sum(JsExpression left, JsExpression right) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.ADD, left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation subtract(JsExpression left, JsExpression right) {
|
|
||||||
return new JsBinaryOperation(JsBinaryOperator.SUB, left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsPrefixOperation not(JsExpression expression) {
|
|
||||||
return new JsPrefixOperation(JsUnaryOperator.NOT, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsBinaryOperation typeof(JsExpression expression, JsStringLiteral string) {
|
|
||||||
return equals(new JsPrefixOperation(JsUnaryOperator.TYPEOF, expression), string);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface Mutator {
|
|
||||||
public JsNode mutate(JsNode node);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: move somewhere
|
|
||||||
//TODO: refactor and review
|
|
||||||
public static JsNode mutateLastExpression(JsNode node, Mutator mutator) {
|
|
||||||
if (node instanceof JsBlock) {
|
|
||||||
JsBlock block = (JsBlock) node;
|
|
||||||
List<JsStatement> statements = block.getStatements();
|
|
||||||
|
|
||||||
if (statements.isEmpty()) return block;
|
|
||||||
|
|
||||||
int size = statements.size();
|
|
||||||
statements.set(size - 1,
|
|
||||||
AstUtil.convertToStatement(mutateLastExpression(statements.get(size - 1), mutator)));
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
if (node instanceof JsIf) {
|
|
||||||
JsIf ifExpr = (JsIf) node;
|
|
||||||
ifExpr.setThenStmt(AstUtil.convertToStatement(mutateLastExpression(ifExpr.getThenStmt(), mutator)));
|
|
||||||
JsStatement elseStmt = ifExpr.getElseStmt();
|
|
||||||
if (elseStmt != null) {
|
|
||||||
ifExpr.setElseStmt(AstUtil.convertToStatement(mutateLastExpression(elseStmt, mutator)));
|
|
||||||
}
|
|
||||||
return ifExpr;
|
|
||||||
}
|
|
||||||
if (node instanceof JsExprStmt) {
|
|
||||||
return AstUtil.convertToStatement(mutateLastExpression(((JsExprStmt) node).getExpression(), mutator));
|
|
||||||
}
|
|
||||||
return mutator.mutate(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static final class SaveLastExpressionMutator implements Mutator {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final JsExpression toAssign;
|
|
||||||
|
|
||||||
public SaveLastExpressionMutator(@NotNull JsExpression toAssign) {
|
|
||||||
this.toAssign = toAssign;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsNode mutate(JsNode node) {
|
|
||||||
if (!(node instanceof JsExpression)) {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
return AstUtil.assignment(toAssign, (JsExpression) node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapts {@link TextOutput} to an internal text buffer.
|
|
||||||
*/
|
|
||||||
public class DefaultTextOutput extends AbstractTextOutput {
|
|
||||||
|
|
||||||
private final StringWriter sw = new StringWriter();
|
|
||||||
private final PrintWriter out;
|
|
||||||
|
|
||||||
public DefaultTextOutput(boolean compact) {
|
|
||||||
super(compact);
|
|
||||||
setPrintWriter(out = new PrintWriter(sw));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
out.flush();
|
|
||||||
if (sw != null) {
|
|
||||||
return sw.toString();
|
|
||||||
} else {
|
|
||||||
return super.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility to hack around untypable (or yet to be) code.
|
|
||||||
*/
|
|
||||||
public class Hack {
|
|
||||||
public static <T> T cast(Object o) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T t = (T) o;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,291 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for operating on memory-efficient lists. All lists of size 0
|
|
||||||
* or 1 are assumed to be immutable. All lists of size greater than 1 are
|
|
||||||
* assumed to be mutable.
|
|
||||||
*/
|
|
||||||
public class Lists {
|
|
||||||
|
|
||||||
private static final Class<?> MULTI_LIST_CLASS = ArrayList.class;
|
|
||||||
private static final Class<?> SINGLETON_LIST_CLASS = Collections.singletonList(null).getClass();
|
|
||||||
|
|
||||||
public static <T> List<T> add(List<T> list, int index, T toAdd) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty -> Singleton
|
|
||||||
if (index != 0) {
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
}
|
|
||||||
return Collections.singletonList(toAdd);
|
|
||||||
case 1: {
|
|
||||||
// Singleton -> ArrayList
|
|
||||||
List<T> result = new ArrayList<T>(2);
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
result.add(toAdd);
|
|
||||||
result.add(list.get(0));
|
|
||||||
return result;
|
|
||||||
case 1:
|
|
||||||
result.add(list.get(0));
|
|
||||||
result.add(toAdd);
|
|
||||||
return result;
|
|
||||||
default:
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// ArrayList
|
|
||||||
list.add(index, toAdd);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> add(List<T> list, T toAdd) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty -> Singleton
|
|
||||||
return Collections.singletonList(toAdd);
|
|
||||||
case 1: {
|
|
||||||
// Singleton -> ArrayList
|
|
||||||
List<T> result = new ArrayList<T>(2);
|
|
||||||
result.add(list.get(0));
|
|
||||||
result.add(toAdd);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// ArrayList
|
|
||||||
list.add(toAdd);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> addAll(List<T> list, int index, List<T> toAdd) {
|
|
||||||
switch (toAdd.size()) {
|
|
||||||
case 0:
|
|
||||||
// No-op.
|
|
||||||
return list;
|
|
||||||
case 1:
|
|
||||||
// Add one element.
|
|
||||||
return add(list, index, toAdd.get(0));
|
|
||||||
default:
|
|
||||||
// True list merge, result >= 2.
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
if (index != 0) {
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
}
|
|
||||||
return new ArrayList<T>(toAdd);
|
|
||||||
case 1: {
|
|
||||||
List<T> result = new ArrayList<T>(1 + toAdd.size());
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
result.addAll(toAdd);
|
|
||||||
result.add(list.get(0));
|
|
||||||
return result;
|
|
||||||
case 1:
|
|
||||||
result.add(list.get(0));
|
|
||||||
result.addAll(toAdd);
|
|
||||||
return result;
|
|
||||||
default:
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
list.addAll(index, toAdd);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> addAll(List<T> list, List<T> toAdd) {
|
|
||||||
switch (toAdd.size()) {
|
|
||||||
case 0:
|
|
||||||
// No-op.
|
|
||||||
return list;
|
|
||||||
case 1:
|
|
||||||
// Add one element.
|
|
||||||
return add(list, toAdd.get(0));
|
|
||||||
default:
|
|
||||||
// True list merge, result >= 2.
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
return new ArrayList<T>(toAdd);
|
|
||||||
case 1: {
|
|
||||||
List<T> result = new ArrayList<T>(1 + toAdd.size());
|
|
||||||
result.add(list.get(0));
|
|
||||||
result.addAll(toAdd);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
list.addAll(toAdd);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> addAll(List<T> list, T... toAdd) {
|
|
||||||
switch (toAdd.length) {
|
|
||||||
case 0:
|
|
||||||
// No-op.
|
|
||||||
return list;
|
|
||||||
case 1:
|
|
||||||
// Add one element.
|
|
||||||
return add(list, toAdd[0]);
|
|
||||||
default:
|
|
||||||
// True list merge, result >= 2.
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
return new ArrayList<T>(Arrays.asList(toAdd));
|
|
||||||
case 1: {
|
|
||||||
List<T> result = new ArrayList<T>(1 + toAdd.length);
|
|
||||||
result.add(list.get(0));
|
|
||||||
result.addAll(Arrays.asList(toAdd));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
list.addAll(Arrays.asList(toAdd));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> create() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> create(Collection<T> collection) {
|
|
||||||
switch (collection.size()) {
|
|
||||||
case 0:
|
|
||||||
return create();
|
|
||||||
default:
|
|
||||||
return new ArrayList<T>(collection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> create(List<T> list) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
return create();
|
|
||||||
case 1:
|
|
||||||
return create(list.get(0));
|
|
||||||
default:
|
|
||||||
return new ArrayList<T>(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> create(T item) {
|
|
||||||
return Collections.singletonList(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> create(T... items) {
|
|
||||||
switch (items.length) {
|
|
||||||
case 0:
|
|
||||||
return create();
|
|
||||||
case 1:
|
|
||||||
return create(items[0]);
|
|
||||||
default:
|
|
||||||
return new ArrayList<T>(Arrays.asList(items));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> normalize(List<T> list) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
return create();
|
|
||||||
case 1: {
|
|
||||||
if (list.getClass() == SINGLETON_LIST_CLASS) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
return create(list.get(0));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if (list.getClass() == MULTI_LIST_CLASS) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
return new ArrayList<T>(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> normalizeUnmodifiable(List<T> list) {
|
|
||||||
if (list.size() < 2) {
|
|
||||||
return normalize(list);
|
|
||||||
} else {
|
|
||||||
List<T> copy = new ArrayList<T>(list.size());
|
|
||||||
Collections.copy(copy, list);
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> remove(List<T> list, int toRemove) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty
|
|
||||||
throw newIndexOutOfBounds(list, toRemove);
|
|
||||||
case 1:
|
|
||||||
// Singleton -> Empty
|
|
||||||
if (toRemove == 0) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
} else {
|
|
||||||
throw newIndexOutOfBounds(list, toRemove);
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
// ArrayList -> Singleton
|
|
||||||
switch (toRemove) {
|
|
||||||
case 0:
|
|
||||||
return Collections.singletonList(list.get(1));
|
|
||||||
case 1:
|
|
||||||
return Collections.singletonList(list.get(0));
|
|
||||||
default:
|
|
||||||
throw newIndexOutOfBounds(list, toRemove);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// ArrayList
|
|
||||||
list.remove(toRemove);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> set(List<T> list, int index, T e) {
|
|
||||||
switch (list.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
case 1:
|
|
||||||
// Singleton
|
|
||||||
if (index == 0) {
|
|
||||||
return Collections.singletonList(e);
|
|
||||||
} else {
|
|
||||||
throw newIndexOutOfBounds(list, index);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// ArrayList
|
|
||||||
list.set(index, e);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Comparable<? super T>> List<T> sort(List<T> list) {
|
|
||||||
if (list.size() > 1) {
|
|
||||||
Collections.sort(list);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> sort(List<T> list, Comparator<? super T> sort) {
|
|
||||||
if (list.size() > 1) {
|
|
||||||
Collections.sort(list, sort);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> IndexOutOfBoundsException newIndexOutOfBounds(List<T> list, int index) {
|
|
||||||
return new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for operating on memory-efficient maps. All maps of size 0 or
|
|
||||||
* 1 are assumed to be immutable. All maps of size greater than 1 are assumed to
|
|
||||||
* be mutable.
|
|
||||||
*/
|
|
||||||
public class Maps {
|
|
||||||
|
|
||||||
private static final Class<?> MULTI_MAP_CLASS = HashMap.class;
|
|
||||||
private static final Class<?> SINGLETON_MAP_CLASS =
|
|
||||||
Collections.singletonMap(null, null).getClass();
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> create() {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> create(K key, V value) {
|
|
||||||
return Collections.singletonMap(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> normalize(Map<K, V> map) {
|
|
||||||
switch (map.size()) {
|
|
||||||
case 0:
|
|
||||||
return create();
|
|
||||||
case 1: {
|
|
||||||
if (map.getClass() == SINGLETON_MAP_CLASS) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
K key = map.keySet().iterator().next();
|
|
||||||
return create(key, map.get(key));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if (map.getClass() == MULTI_MAP_CLASS) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
return new HashMap<K, V>(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> normalizeUnmodifiable(Map<K, V> map) {
|
|
||||||
if (map.size() < 2) {
|
|
||||||
return normalize(map);
|
|
||||||
} else {
|
|
||||||
// TODO: implement an UnmodifiableHashMap?
|
|
||||||
return Collections.unmodifiableMap(normalize(map));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> put(Map<K, V> map, K key, V value) {
|
|
||||||
switch (map.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty -> Singleton
|
|
||||||
return Collections.singletonMap(key, value);
|
|
||||||
case 1: {
|
|
||||||
if (map.containsKey(key)) {
|
|
||||||
return create(key, value);
|
|
||||||
}
|
|
||||||
// Singleton -> HashMap
|
|
||||||
Map<K, V> result = new HashMap<K, V>();
|
|
||||||
result.put(map.keySet().iterator().next(), map.values().iterator().next());
|
|
||||||
result.put(key, value);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// HashMap
|
|
||||||
map.put(key, value);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> putAll(Map<K, V> map, Map<K, V> toAdd) {
|
|
||||||
switch (toAdd.size()) {
|
|
||||||
case 0:
|
|
||||||
// No-op.
|
|
||||||
return map;
|
|
||||||
case 1: {
|
|
||||||
// Add one element.
|
|
||||||
K key = toAdd.keySet().iterator().next();
|
|
||||||
return put(map, key, toAdd.get(key));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// True list merge, result >= 2.
|
|
||||||
switch (map.size()) {
|
|
||||||
case 0:
|
|
||||||
return new HashMap<K, V>(toAdd);
|
|
||||||
case 1: {
|
|
||||||
HashMap<K, V> result = new HashMap<K, V>();
|
|
||||||
K key = map.keySet().iterator().next();
|
|
||||||
result.put(key, map.get(key));
|
|
||||||
result.putAll(toAdd);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
map.putAll(toAdd);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A variation of the put method which uses a LinkedHashMap.
|
|
||||||
*/
|
|
||||||
public static <K, V> Map<K, V> putOrdered(Map<K, V> map, K key, V value) {
|
|
||||||
switch (map.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty -> Singleton
|
|
||||||
return Collections.singletonMap(key, value);
|
|
||||||
case 1: {
|
|
||||||
if (map.containsKey(key)) {
|
|
||||||
return create(key, value);
|
|
||||||
}
|
|
||||||
// Singleton -> LinkedHashMap
|
|
||||||
Map<K, V> result = new LinkedHashMap<K, V>();
|
|
||||||
result.put(map.keySet().iterator().next(), map.values().iterator().next());
|
|
||||||
result.put(key, value);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// LinkedHashMap
|
|
||||||
map.put(key, value);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K, V> Map<K, V> remove(Map<K, V> map, K key) {
|
|
||||||
switch (map.size()) {
|
|
||||||
case 0:
|
|
||||||
// Empty
|
|
||||||
return map;
|
|
||||||
case 1:
|
|
||||||
// Singleton -> Empty
|
|
||||||
if (map.containsKey(key)) {
|
|
||||||
return create();
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
case 2:
|
|
||||||
// HashMap -> Singleton
|
|
||||||
if (map.containsKey(key)) {
|
|
||||||
map.remove(key);
|
|
||||||
key = map.keySet().iterator().next();
|
|
||||||
return create(key, map.get(key));
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
default:
|
|
||||||
// IdentityHashMap
|
|
||||||
map.remove(key);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods for obtaining relative paths from files and translating
|
|
||||||
* relative paths into files.
|
|
||||||
*/
|
|
||||||
public class Paths {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Answer the relative path from baseFile to relFile
|
|
||||||
*
|
|
||||||
* @param baseFile the base file (not <code>null</code>) from which the
|
|
||||||
* desired path starts
|
|
||||||
* @param relFile the file referenced by the desired relative path (not
|
|
||||||
* <code>null</code>)
|
|
||||||
* @return a relative path (not <code>null</code>)
|
|
||||||
*/
|
|
||||||
public static String relativePathFor(File baseFile, File relFile) {
|
|
||||||
String baseFilePath = baseFile.getPath().replace(File.separatorChar, '/');
|
|
||||||
String relFilePath = relFile.getPath().replace(File.separatorChar, '/');
|
|
||||||
int baseFilePathLen = baseFilePath.length();
|
|
||||||
int relFilePathLen = relFilePath.length();
|
|
||||||
|
|
||||||
// Find the com.google.dart.compiler.backend.common path elements
|
|
||||||
int index = 0;
|
|
||||||
while (index < baseFilePathLen - 1 && index < relFilePathLen - 1) {
|
|
||||||
if (baseFilePath.charAt(index) != relFilePath.charAt(index)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
while (index >= 0
|
|
||||||
&& (baseFilePath.charAt(index) != '/' || relFilePath.charAt(index) != '/')) {
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
int commonStart = index;
|
|
||||||
|
|
||||||
// Build a path up from the base file
|
|
||||||
StringBuilder relPath = new StringBuilder(baseFilePathLen + relFilePathLen
|
|
||||||
- commonStart * 2);
|
|
||||||
index = commonStart + 1;
|
|
||||||
while (true) {
|
|
||||||
index = baseFilePath.indexOf('/', index);
|
|
||||||
if (index == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
relPath.append("../");
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
relPath.append(relFilePath.substring(commonStart + 1));
|
|
||||||
return relPath.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Answer the file relative to the specified file
|
|
||||||
*
|
|
||||||
* @param baseFile the base file (not <code>null</code>)
|
|
||||||
* @param relPath the path to the desired file relative to baseFile
|
|
||||||
* @return the file (not <code>null</code>)
|
|
||||||
*/
|
|
||||||
public static File relativePathToFile(File baseFile, String relPath) {
|
|
||||||
if (relPath.startsWith("/")) {
|
|
||||||
return new File(relPath);
|
|
||||||
}
|
|
||||||
File parentFile = baseFile.getParentFile();
|
|
||||||
String name;
|
|
||||||
if (parentFile == null) {
|
|
||||||
name = ".";
|
|
||||||
} else {
|
|
||||||
name = parentFile.getPath().replace(File.separatorChar, '/');
|
|
||||||
}
|
|
||||||
name = URI.create(name + "/" + relPath).normalize().getPath();
|
|
||||||
return new File(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a collection of paths, return a collection of files
|
|
||||||
*
|
|
||||||
* @param a collection of paths to various files (not <code>null</code>,
|
|
||||||
* contains no <code>null</code>s)
|
|
||||||
* @return a collection of files (not <code>null</code>, contains no
|
|
||||||
* <code>null</code>s)
|
|
||||||
*/
|
|
||||||
public static List<File> toFiles(List<String> filePaths) {
|
|
||||||
List<File> files = new ArrayList<File>();
|
|
||||||
for (String path : filePaths) {
|
|
||||||
files.add(new File(path));
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
|
||||||
// BSD-style license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package com.google.dart.compiler.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface used for printing text output.
|
|
||||||
*/
|
|
||||||
public interface TextOutput {
|
|
||||||
|
|
||||||
int getPosition();
|
|
||||||
|
|
||||||
int getLine();
|
|
||||||
|
|
||||||
int getColumn();
|
|
||||||
|
|
||||||
void indentIn();
|
|
||||||
|
|
||||||
void indentOut();
|
|
||||||
|
|
||||||
void newline();
|
|
||||||
|
|
||||||
void newlineOpt();
|
|
||||||
|
|
||||||
void print(char c);
|
|
||||||
|
|
||||||
void print(char[] s);
|
|
||||||
|
|
||||||
void print(String s);
|
|
||||||
|
|
||||||
void printOpt(char c);
|
|
||||||
|
|
||||||
void printOpt(char[] s);
|
|
||||||
|
|
||||||
void printOpt(String s);
|
|
||||||
}
|
|
||||||
@@ -17,9 +17,11 @@
|
|||||||
package org.jetbrains.k2js.translate.context;
|
package org.jetbrains.k2js.translate.context;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
import com.google.dart.compiler.util.AstUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.addVarDeclaration;
|
||||||
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
|
||||||
|
|
||||||
public class DynamicContext {
|
public class DynamicContext {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -66,8 +68,8 @@ public class DynamicContext {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
|
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
|
||||||
JsName temporaryName = blockScope.declareTemporary();
|
JsName temporaryName = blockScope.declareTemporary();
|
||||||
JsVars temporaryDeclaration = AstUtil.newVar(temporaryName, null);
|
JsVars temporaryDeclaration = newVar(temporaryName, /*no init expression in var statement*/ null);
|
||||||
jsBlock().addVarDeclaration(temporaryDeclaration);
|
addVarDeclaration(jsBlock(), temporaryDeclaration);
|
||||||
return new TemporaryVariable(temporaryName, initExpression);
|
return new TemporaryVariable(temporaryName, initExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import com.google.dart.compiler.backend.js.ast.JsScope;
|
|||||||
import com.google.dart.compiler.util.AstUtil;
|
import com.google.dart.compiler.util.AstUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -71,7 +73,8 @@ public final class Namer {
|
|||||||
public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter) {
|
public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter) {
|
||||||
if (isGetter) {
|
if (isGetter) {
|
||||||
return getNameForGetter(propertyName);
|
return getNameForGetter(propertyName);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return getNameForSetter(propertyName);
|
return getNameForSetter(propertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,17 +142,17 @@ public final class Namer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsNameRef createMethodReference(@NotNull JsName name) {
|
private static JsNameRef createMethodReference(@NotNull JsName name) {
|
||||||
JsNameRef qualifier = name.makeRef();
|
JsNameRef qualifier = name.makeRef();
|
||||||
JsNameRef reference = AstUtil.newQualifiedNameRef("create");
|
JsNameRef reference = AstUtil.newQualifiedNameRef("create");
|
||||||
AstUtil.setQualifier(reference, qualifier);
|
setQualifier(reference, qualifier);
|
||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsNameRef kotlin(@NotNull JsNameRef reference) {
|
private JsNameRef kotlin(@NotNull JsNameRef reference) {
|
||||||
JsNameRef kotlinReference = kotlinName.makeRef();
|
JsNameRef kotlinReference = kotlinName.makeRef();
|
||||||
AstUtil.setQualifier(reference, kotlinReference);
|
setQualifier(reference, kotlinReference);
|
||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user