Added DeclarationExtractor logic.

This commit is contained in:
Pavel Talanov
2011-11-10 14:06:15 +04:00
parent da1a1a3727
commit f4b18c277f
11 changed files with 624 additions and 398 deletions
@@ -14,211 +14,225 @@ import java.util.List;
*/
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);
}
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;
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 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 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);
}
/**
* 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;
}
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;
}
/**
* 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;
}
public JsFunction getImpliedExecute() {
return impliedExecute;
}
@Override
public JsName getName() {
return name;
}
@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 List<JsParameter> getParameters() {
return params;
}
}
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);
}
public JsScope getScope() {
return scope;
}
if (v.visit(this, ctx)) {
v.acceptWithInsertRemove(params);
body = v.accept(body);
@Override
public boolean hasSideEffects() {
// If there's a name, the name is assigned to.
return name != null;
}
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 boolean isArtificiallyRescued() {
return artificiallyRescued;
}
}
public void setHoisted() {
hoisted = true;
}
@Override
public boolean isBooleanFalse() {
return false;
}
/** Whether the function has been hoisted */
public boolean isHoisted() {
return hoisted;
}
@Override
public boolean isBooleanTrue() {
return true;
}
/**
* 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 boolean isDefinitelyNotNull() {
return true;
}
@Override
public JsFunction setSourceRef(SourceInfo info) {
super.setSourceRef(info);
return this;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public boolean isConstructor() {
return this.constructor;
}
public boolean isFromDart() {
return fromDart;
}
public boolean setIsConstructor(boolean constructor) {
return this.constructor = constructor;
}
public void setArtificiallyRescued(boolean rescued) {
this.artificiallyRescued = rescued;
}
@Override
public NodeKind getKind() {
return NodeKind.FUNCTION;
}
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);
}
}