You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/13 20:55:59 UTC
[07/51] [partial] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - - Check-In of the migrated
project to make error analysis easier
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGeneratingReducer.java
----------------------------------------------------------------------
diff --git a/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGeneratingReducer.java b/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGeneratingReducer.java
deleted file mode 100644
index 6bc7bd4..0000000
--- a/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGeneratingReducer.java
+++ /dev/null
@@ -1,11683 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.flex.compiler.internal.as.codegen;
-
-import static org.apache.flex.abc.ABCConstants.*;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.text.SimpleDateFormat;
-import java.util.TreeSet;
-import java.util.Vector;
-
-import org.apache.flex.abc.ABCConstants;
-import org.apache.flex.abc.instructionlist.InstructionList;
-import org.apache.flex.abc.semantics.ECMASupport;
-import org.apache.flex.abc.semantics.Instruction;
-import org.apache.flex.abc.semantics.MethodBodyInfo;
-import org.apache.flex.abc.semantics.MethodInfo;
-import org.apache.flex.abc.semantics.Name;
-import org.apache.flex.abc.semantics.Namespace;
-import org.apache.flex.abc.semantics.Nsset;
-import org.apache.flex.abc.semantics.PooledValue;
-import org.apache.flex.abc.visitors.IMethodBodyVisitor;
-import org.apache.flex.abc.visitors.IMethodVisitor;
-import org.apache.flex.abc.visitors.ITraitsVisitor;
-import org.apache.flex.compiler.common.ASModifier;
-import org.apache.flex.compiler.common.DependencyType;
-import org.apache.flex.compiler.constants.IASLanguageConstants;
-import org.apache.flex.compiler.constants.IASLanguageConstants.BuiltinType;
-import org.apache.flex.compiler.definitions.IAccessorDefinition;
-import org.apache.flex.compiler.definitions.IAppliedVectorDefinition;
-import org.apache.flex.compiler.definitions.IClassDefinition;
-import org.apache.flex.compiler.definitions.IDefinition;
-import org.apache.flex.compiler.definitions.IFunctionDefinition;
-import org.apache.flex.compiler.definitions.IGetterDefinition;
-import org.apache.flex.compiler.definitions.IInterfaceDefinition;
-import org.apache.flex.compiler.definitions.INamespaceDefinition;
-import org.apache.flex.compiler.definitions.IParameterDefinition;
-import org.apache.flex.compiler.definitions.ISetterDefinition;
-import org.apache.flex.compiler.definitions.ITypeDefinition;
-import org.apache.flex.compiler.definitions.IVariableDefinition;
-import org.apache.flex.compiler.definitions.metadata.IMetaTag;
-import org.apache.flex.compiler.definitions.references.INamespaceReference;
-import org.apache.flex.compiler.definitions.references.IReference;
-import org.apache.flex.compiler.exceptions.DuplicateLabelException;
-import org.apache.flex.compiler.filespecs.IFileSpecification;
-import org.apache.flex.compiler.internal.definitions.AmbiguousDefinition;
-import org.apache.flex.compiler.internal.definitions.AppliedVectorDefinition;
-import org.apache.flex.compiler.internal.definitions.ClassDefinition;
-import org.apache.flex.compiler.internal.definitions.DefinitionBase;
-import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
-import org.apache.flex.compiler.internal.definitions.GetterDefinition;
-import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
-import org.apache.flex.compiler.internal.definitions.MemberedDefinition;
-import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
-import org.apache.flex.compiler.internal.definitions.PackageDefinition;
-import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
-import org.apache.flex.compiler.internal.definitions.SetterDefinition;
-import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase;
-import org.apache.flex.compiler.internal.definitions.VariableDefinition;
-import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter;
-import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.AccessValue;
-import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.ClassificationValue;
-import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.SearchScopeValue;
-import org.apache.flex.compiler.internal.legacy.ASScopeUtils;
-import org.apache.flex.compiler.internal.legacy.MemberedDefinitionUtils;
-import org.apache.flex.compiler.internal.projects.CompilerProject;
-import org.apache.flex.compiler.internal.scopes.ASFileScope;
-import org.apache.flex.compiler.internal.scopes.ASProjectScope;
-import org.apache.flex.compiler.internal.scopes.ASScope;
-import org.apache.flex.compiler.internal.scopes.ASScopeBase;
-import org.apache.flex.compiler.internal.scopes.CatchScope;
-import org.apache.flex.compiler.internal.semantics.SemanticUtils;
-import org.apache.flex.compiler.internal.tree.as.BaseDefinitionNode;
-import org.apache.flex.compiler.internal.tree.as.BaseVariableNode;
-import org.apache.flex.compiler.internal.tree.as.ExpressionNodeBase;
-import org.apache.flex.compiler.internal.tree.as.ForLoopNode;
-import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
-import org.apache.flex.compiler.internal.tree.as.FunctionNode;
-import org.apache.flex.compiler.internal.tree.as.FunctionObjectNode;
-import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
-import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
-import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
-import org.apache.flex.compiler.internal.tree.as.NamespaceNode;
-import org.apache.flex.compiler.internal.tree.as.NodeBase;
-import org.apache.flex.compiler.internal.tree.as.ParameterNode;
-import org.apache.flex.compiler.internal.tree.as.SwitchNode;
-import org.apache.flex.compiler.internal.tree.as.VariableExpressionNode;
-import org.apache.flex.compiler.internal.tree.as.VariableNode;
-import org.apache.flex.compiler.problems.CodegenInternalProblem;
-import org.apache.flex.compiler.problems.CodegenProblem;
-import org.apache.flex.compiler.problems.CompilerProblem;
-import org.apache.flex.compiler.problems.DuplicateLabelProblem;
-import org.apache.flex.compiler.problems.DuplicateNamespaceDefinitionProblem;
-import org.apache.flex.compiler.problems.ICompilerProblem;
-import org.apache.flex.compiler.problems.InvalidLvalueProblem;
-import org.apache.flex.compiler.problems.InvalidOverrideProblem;
-import org.apache.flex.compiler.problems.PackageCannotBeUsedAsValueProblem;
-import org.apache.flex.compiler.problems.UnknownNamespaceProblem;
-import org.apache.flex.compiler.problems.VoidTypeProblem;
-import org.apache.flex.compiler.projects.ICompilerProject;
-import org.apache.flex.compiler.scopes.IASScope;
-import org.apache.flex.compiler.tree.ASTNodeID;
-import org.apache.flex.compiler.tree.as.IASNode;
-import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
-import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
-import org.apache.flex.compiler.tree.as.ICatchNode;
-import org.apache.flex.compiler.tree.as.IClassNode;
-import org.apache.flex.compiler.tree.as.IExpressionNode;
-import org.apache.flex.compiler.tree.as.IForLoopNode;
-import org.apache.flex.compiler.tree.as.IFunctionCallNode;
-import org.apache.flex.compiler.tree.as.IFunctionNode;
-import org.apache.flex.compiler.tree.as.IIdentifierNode;
-import org.apache.flex.compiler.tree.as.IImportNode;
-import org.apache.flex.compiler.tree.as.ILiteralNode;
-import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
-import org.apache.flex.compiler.tree.as.INumericLiteralNode;
-import org.apache.flex.compiler.tree.as.IObjectLiteralValuePairNode;
-import org.apache.flex.compiler.tree.as.IParameterNode;
-import org.apache.flex.compiler.tree.as.IRegExpLiteralNode;
-import org.apache.flex.compiler.tree.as.IScopedNode;
-import org.apache.flex.compiler.tree.as.ITryNode;
-import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
-import org.apache.flex.compiler.tree.as.IVariableNode;
-import org.apache.flex.compiler.tree.as.IWhileLoopNode;
-import org.apache.flex.compiler.tree.as.IWithNode;
-import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode;
-import org.apache.flex.compiler.units.ICompilationUnit;
-import org.apache.flex.compiler.units.ICompilationUnit.Operation;
-
-/**
- * JSGeneratingReducer is modeled after from ABCGeneratingReducer and called by
- * the generated CmcJSEmitter (see cmc-js.jbg). This is the "meat" of FalconJS.
- * This implementation is part of FalconJS. For more details on FalconJS see
- * org.apache.flex.compiler.JSDriver
- */
-@SuppressWarnings("nls")
-public class JSGeneratingReducer
-{
- /**
- * A very high cost, used to trap errors but otherwise well outside normal
- * bounds.
- */
- static final int ERROR_TRAP = 268435456;
-
- private static final Name NAME_Vector = new Name(IASLanguageConstants.Vector);
-
- /**
- * A struct for the decoded pieces of a catch block.
- */
- public class CatchPrototype
- {
- Name catchType;
- Name catchVarName;
- String catchBody;
- }
-
- /**
- * ConditionalFragment holds the disparate elements of a conditional
- * statement fragment.
- */
- public class ConditionalFragment
- {
- IASNode site;
- String condition;
- String statement;
-
- // private Label statementLabel = null;
-
- /**
- * Construct a ConditionalFragment with a single statement.
- */
- ConditionalFragment(IASNode site, String condition, String statement)
- {
- this.site = site;
- this.condition = condition;
- this.statement = statement;
- }
-
- /**
- * Construct a ConditionalFragment with a list of statements, coalescing
- * them into a composite statement.
- */
- ConditionalFragment(IASNode site, String condition, Vector<String> statements)
- {
- this.site = site;
- this.condition = condition;
- this.statement = createInstruction(site);
-
- for (String stmt : statements)
- {
- this.statement += stmt;
- }
- }
-
- /**
- * @return the label of the fragment's condition, or its statement label
- * if it's the default alternative.
- */
- /*
- * Label getLabel() { if ( !this.isUnconditionalAlternative() ) return
- * this.condition.getLabel(); else return getStatementLabel(); }
- */
-
- /**
- * Cache and return the label of this conditional fragment's statement
- * so it can be retrieved after the statement's been added to the
- * overall conditional statement and this.statement is invalidated.
- */
- /*
- * Label getStatementLabel() { if ( null == this.statementLabel )
- * this.statementLabel = this.statement.getLabel(); return
- * this.statementLabel; }
- */
-
- /**
- * @return true if this is an unconditional alternative, i.e. a default
- * case or the last else in an if/else if/else.
- */
- boolean isUnconditionalAlternative()
- {
- return null == this.condition;
- }
- }
-
- /**
- * The RuntimeMultiname class holds the components of the various types of
- * runtime multiname, and puts them together in the right order to generate
- * the names and instruction sequences to jamble up the AVM. Only some
- * permutations of the compile-time/runtime qualifier::name possibilities
- * are valid: Name::expression generates MultinameL expression::expression
- * generates RTQnameL expression::name generates RTQname (name::name is a
- * plain Multiname)
- */
- public class RuntimeMultiname
- {
- /**
- * The compile-time qualifier of a MultinameL. compileTimeName isn't
- * valid (this would be a compile-time constant Multiname).
- */
- Name compileTimeQualifier;
-
- /**
- * The runtime qualifier of a RTQname or RTQNameL. Compile-time and
- * runtime names are valid.
- */
- String runtimeQualifier;
-
- /**
- * The compile-time constant name of a RTQName. compileTimeQualifier
- * isn't valid (this would be a compile-time constant Multiname).
- */
- Name compileTimeName;
-
- /**
- * The runtime name of a MultinameL or RTQnameL.
- */
- String runtimeName;
-
- /**
- * Construct a RTQnameL-type runtime name.
- *
- * @param qualifier - the runtime qualifier.
- * @param name - the runtime name.
- */
- RuntimeMultiname(String qualifier, String runtime_name)
- {
- this.runtimeQualifier = qualifier;
- this.runtimeName = runtime_name;
- }
-
- /**
- * Construct a RTQname-type runtime name.
- *
- * @param qualifier - the runtime qualifier.
- * @param name - the compile-time name.
- */
- RuntimeMultiname(String qualifier, Name name)
- {
- this.runtimeQualifier = qualifier;
- this.compileTimeName = name;
- }
-
- /**
- * Construct a MultinameL-type runtime name.
- *
- * @param qualifier - the Multiname. Note this is the only kind of
- * runtime name that receives a qualifying name.
- * @param nameL - the runtime expression that yields the base name.
- */
- RuntimeMultiname(Name qualifier, String nameL)
- {
- assert (qualifier.getKind() == CONSTANT_MultinameL || qualifier.getKind() == CONSTANT_MultinameLA) : "Bad qualifier kind " + qualifier.getKind() + " on name " + qualifier.toString();
- this.compileTimeQualifier = qualifier;
- this.runtimeName = nameL;
- }
-
- /**
- * Assemble the ingredients into an expression.
- *
- * @param opcode - one of OP_getproperty or OP_setproperty.
- * @param rhs - the value of a setproperty call. Passed to this routine
- * because there may be name-specific instructions before and after the
- * value.
- */
- private String generateGetOrSet(IASNode iNode, int opcode, String rhs)
- {
- // TODO: Optimize InstructionList size.
- String result = createInstruction(iNode);
-
- // Note: numerous microoptimization opportunities here
- // to avoid storing values in temps by creative use of
- // OP_dup and OP_swap, especially in getproperty gen.
-
- if (this.compileTimeQualifier != null && this.runtimeName != null)
- {
- result += runtimeName;
- if (rhs != null)
- result += rhs;
-
- /*
- * // Generate MultinameL type code. Binding name_temp =
- * currentScope.allocateTemp(); result.addAll(this.runtimeName);
- * result.addInstruction(OP_dup);
- * result.addInstruction(name_temp.setlocal()); //
- * findprop(MultinameL) consumes a name from the value stack.
- * result.addInstruction(OP_findpropstrict,
- * this.compileTimeQualifier);
- * result.addInstruction(name_temp.getlocal()); if ( rhs != null
- * ) result.addAll(rhs); // get/setprop(MultinameL) consumes a
- * name from the value stack. result.addInstruction(opcode,
- * this.compileTimeQualifier);
- */
-
- }
- else if (this.runtimeQualifier != null && this.runtimeName != null)
- {
- /*
- * // Generate RTQnameL type code. Binding name_temp =
- * currentScope.allocateTemp(); Binding qual_temp =
- * currentScope.allocateTemp(); Name rtqnl = new
- * Name(CONSTANT_RTQnameL, null, null);
- * result.addAll(getRuntimeName(iNode));
- * result.addInstruction(name_temp.setlocal());
- * result.addAll(getRuntimeQualifier(iNode));
- * result.addInstruction(OP_dup);
- * result.addInstruction(qual_temp.setlocal());
- * result.addInstruction(name_temp.getlocal()); //
- * findprop(RTQNameL) consumes namespace and name from the value
- * stack. result.addInstruction(OP_findpropstrict, rtqnl);
- * result.addInstruction(qual_temp.getlocal());
- * result.addInstruction(name_temp.getlocal()); if ( rhs != null
- * ) result.addAll(rhs); // get/setprop(RTQNameL) consumes
- * namespace and name from the value stack.
- * result.addInstruction(opcode, rtqnl);
- * result.addAll(currentScope.releaseTemp(name_temp));
- */
-
- result += getRuntimeName(iNode);
- if (rhs != null)
- result += rhs;
- }
- else
- {
- // Last valid combination generates a RTQname.
- assert (this.runtimeQualifier != null && this.compileTimeName != null) : "Unknown runtime name configuration: " + this.toString();
-
- result += getRuntimeName(iNode);
- if (rhs != null)
- result += rhs;
-
- /*
- * Name rtqn = new Name(CONSTANT_RTQname, null,
- * this.compileTimeName.getBaseName());
- * result.addAll(getRuntimeQualifier(iNode));
- * result.addInstruction(OP_dup); // findprop(RTQName) consumes
- * a namespace from the value stack.
- * result.addInstruction(OP_findpropstrict, rtqn);
- * result.addInstruction(OP_swap); if ( rhs != null )
- * result.addAll(rhs); // get/setprop(RTQName) consumes a
- * namespace from the value stack. result.addInstruction(opcode,
- * rtqn);
- */
- }
-
- return result;
- }
-
- /**
- * Generate the InstructionList that expresses this RuntimeName's
- * qualifier.
- *
- * @param iNode - an IASNode to contribute debug info to the result
- * InstructionList.
- * @return the runtime qualifier setup instructions.
- */
- public String getRuntimeQualifier(IASNode iNode)
- {
- assert (hasRuntimeQualifier());
- String result = createInstruction(iNode);
-
- result += this.runtimeQualifier;
-
- /*
- * // Ensure the last instruction is an OP_coerce to Namespace.
- * Instruction last = result.lastElement(); if ( last.getOpcode() !=
- * OP_coerce || last.getOperandCount() == 0 || !
- * namespaceType.equals(last.getOperand(0)) ) {
- * result.addInstruction(OP_coerce, namespaceType); }
- */
- return result;
- }
-
- /**
- * @return true if this RuntimeName has a runtime qualifier.
- */
- public boolean hasRuntimeQualifier()
- {
- return this.runtimeQualifier != null;
- }
-
- /**
- * @return true if this RuntimeName has a runtime name.
- */
- public boolean hasRuntimeName()
- {
- return this.runtimeName != null;
- }
-
- /**
- * Generate the InstructionList that expresses this RuntimeName's name.
- *
- * @param iNode - an IASNode to contribute debug info to the result
- * InstructionList.
- * @return the runtime name setup instructions.
- */
- public String getRuntimeName(IASNode iNode)
- {
- assert (hasRuntimeName());
-
- String result = createInstructionList(iNode);
-
- /*
- * result.addAll(replicate(this.runtimeName)); if (
- * result.lastElement().getOpcode() != OP_coerce_s)
- * result.addInstruction(OP_coerce_s);
- */
-
- result += this.runtimeName;
-
- return result;
- }
-
- /**
- * Generate the runtime name appropriate to this qualifier/name
- * combination.
- *
- * @return the runtime name appropriate to this qualifier/name
- * combination.
- */
- public Name generateName()
- {
- Name result;
-
- if (this.compileTimeQualifier != null)
- {
- result = this.compileTimeQualifier;
- }
- else if (this.runtimeQualifier != null && this.runtimeName != null)
- {
- result = new Name(CONSTANT_RTQnameL, null, null);
- }
- else
- {
- // Last valid combination generates a RTQname.
- assert (this.runtimeQualifier != null && this.compileTimeName != null) : "Unknown runtime name configuration: " + this.toString();
-
- result = new Name(CONSTANT_RTQname, null, this.compileTimeName.getBaseName());
- }
-
- return result;
- }
-
- /**
- * Convenience method generates an assignment
- *
- * @param value - the value to set.
- * @return the instruction sequence to set a the given multiname's
- * value.
- */
- String generateAssignment(IASNode iNode, String value)
- {
- return generateGetOrSet(iNode, OP_setproperty, value);
- }
-
- /**
- * Convenience method generates an r-value.
- *
- * @return the instruction sequence to look up the given multiname.
- */
- String generateRvalue(IASNode iNode)
- {
- return generateGetOrSet(iNode, OP_getproperty, null);
- }
-
- /**
- * Diagnostic toString() method, used primarily to debug the assertion
- * in generate().
- */
- @Override
- public String toString()
- {
- return "\n\t" + compileTimeQualifier + ",\n\t" + runtimeQualifier + ",\n\t" + compileTimeName + ",\n\t" + runtimeName;
- }
- }
-
- /**
- * The current LexicalScope. Set by the caller, changes during reduction
- * when a scoped construct such as an embedded function or a with statement
- * is encountered.
- */
- private LexicalScope currentScope;
-
- /**
- * Strings sent by the caller to be added to a function definition. Usually
- * these are field initialization expressions in a constructor.
- */
- // private String instanceInitializers;
-
- /**
- * A shared name for the Namespace type.
- */
- public static final Name namespaceType = new Name("Namespace");
-
- /**
- * A shared name for the XML type.
- */
- public static final Name xmlType = new Name("XML");
-
- /**
- * A shared name for the XMLList type.
- */
- public static final Name xmlListType = new Name("XMLList");
-
- /**
- * A shared name for the RegExp type.
- */
- public static final Name regexType = new Name("RegExp");
-
- /**
- * A shared name for the void type.
- */
- public static final Name voidType = new Name("void");
-
- /**
- * Generate code to push a numeric constant.
- */
- public static void pushNumericConstant(long value, String result_list)
- {
- // do nothing
- // result_list.pushNumericConstant(value);
- }
-
- /**
- * Active labeled control-flow region's substatements. Populated by the
- * labeledStmt Prologue, and winnowed by the labeledStmt reduction's
- * epilogue.
- */
- private Set<IASNode> labeledNodes = new HashSet<IASNode>();
-
- /**
- * @return the currently active collection of problems.
- */
- public Collection<ICompilerProblem> getProblems()
- {
- return currentScope.getProblems();
- }
-
- /**
- * Generate a binary operator.
- *
- * @param l - the left-hand operand.
- * @param r - the right-hand operand.
- * @param opcode - the operator's opcode.
- * @return the combined String sequence with the operator appended.
- */
- String binaryOp(IASNode iNode, String l, String r, int opcode)
- {
- checkBinaryOp(iNode, opcode);
-
- switch (opcode)
- {
- // Binary logical operators.
- case OP_istypelate:
- return reduce_istypeExprLate(iNode, l, r);
- case OP_astypelate:
- return reduce_astypeExprLate(iNode, l, r);
- case OP_instanceof:
- return reduce_instanceofExpr(iNode, l, r);
- case OP_in:
- return reduce_inExpr(iNode, l, r);
- }
-
- if (l == null)
- l = "null";
- if (r == null)
- r = "null";
- final String operator = opToString(iNode, opcode);
- String result = createInstruction(iNode, l.length() + r.length() + 1);
- result += binaryOp(l.toString(), r.toString(), operator);
- return result;
-
- /*
- * String result = createInstruction(iNode, l.size() + r.size() + 1);
- * result.addAll(l); result.addAll(r); result.addInstruction(opcode);
- * return result;
- */
- }
-
- public void checkBinaryOp(IASNode iNode, int opcode)
- {
- currentScope.getMethodBodySemanticChecker().checkBinaryOperator(iNode, opcode);
- }
-
- public String conditionalJump(IASNode iNode, String l, String r, int opcode)
- {
- return binaryOp(iNode, l, r, opcode);
- }
-
- String binaryOp(String l, String r, String operator)
- {
- if (l == null)
- l = "null";
- if (r == null)
- r = "null";
- String result = "(" + stripTabs(stripNS(l.toString())) + " " + operator + " " + stripTabs(stripNS(r.toString())) + ")";
- return result;
- }
-
- /**
- * Resolve a dotted name, e.g., foo.bar.baz
- */
- Binding dottedName(IASNode iNode, String qualifiers, String base_name)
- {
- if (iNode instanceof IdentifierNode)
- {
- return currentScope.resolveName((IdentifierNode)iNode);
- }
- else if (iNode instanceof ExpressionNodeBase)
- {
- ExpressionNodeBase expr = (ExpressionNodeBase)iNode;
- ICompilerProject project = currentScope.getProject();
- Name n = expr.getMName(project);
-
- if (n == null)
- {
- currentScope.addProblem(new CodegenInternalProblem(iNode, "Unable to resove member name: " + iNode.toString()));
- n = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, qualifiers)), base_name);
- }
-
- return currentScope.getBinding(iNode, n, expr.resolve(project));
- }
-
- //else
- currentScope.addProblem(new CodegenInternalProblem(iNode, "Unable to resove to a dotted name: " + iNode.toString()));
- return new Binding(iNode, new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, qualifiers)), base_name), null);
- }
-
- /**
- * Resolve a dotted name, e.g., foo.bar.baz, where the whole dotted name is
- * a package this is an error, and a diagnostic will be emitted
- */
- Binding errorPackageName(IASNode iNode, String qualifiers, String base_name)
- {
- currentScope.addProblem(new PackageCannotBeUsedAsValueProblem(iNode, qualifiers + "." + base_name));
- return new Binding(iNode, new Name(qualifiers + "." + base_name), null);
- }
-
- /**
- * Common routine used by reductions that need an empty list.
- *
- * @param iNode - the current AST node.
- */
- public String createInstruction(IASNode iNode)
- {
- return createInstruction(iNode, 0);
- }
-
- /**
- * Common routine used by reductions that need an empty list.
- *
- * @param iNode - the current AST node.
- * @param capacity - requested capacity of the new list. May be adjusted to
- * accomodate debug Strings.
- */
- public String createInstruction(IASNode iNode, int capacity)
- {
- String result = "";
-
- String file_name = iNode.getSourcePath();
-
- if (file_name == null)
- {
- // Fall back on the file specification.
- // This may also be null (or assert if it's feeling moody),
- // in which case the file name remains null and file/line
- // processing noops.
- try
- {
- IFileSpecification fs = iNode.getFileSpecification();
- if (fs != null)
- file_name = fs.getPath();
- }
- catch (Throwable no_fs)
- {
- // No file specification available, probably
- // because this node is some kind of syntho.
- }
- }
-
- // Note: getLine() uses zero-based counting.
- int line_num = iNode.getLine() + 1;
-
- // Adjust the capacity requirement if debug
- // Strings are to be emitted.
- if (currentScope.emitFile(file_name))
- capacity++;
- if (currentScope.emitLine(line_num))
- capacity++;
-
- // If the required capacity is less than three
- // Strings, the String can hold
- // them organically. Specifying a capacity to
- // the String ctor causes it to allocate
- // a separate ArrayList.
- if (capacity > 3)
- result = new String(/* capacity */);
- else
- result = new String();
-
- if (currentScope.emitFile(file_name))
- {
- // result.addInstruction(OP_debugfile, file_name);
- currentScope.setDebugFile(file_name);
- }
-
- if (currentScope.emitLine(line_num))
- {
- // result.addInstruction(OP_debugline, line_num);
- currentScope.setDebugLine(line_num);
- }
-
- return result;
- }
-
- /**
- * Error trap.
- */
- public Binding error_namespaceAccess(IASNode iNode, IASNode raw_qualifier, Binding qualified_name)
- {
- String qualifier = ((IdentifierNode)raw_qualifier).getName();
-
- // TODO: In some circumstances, the namespace qualifier
- // may be an invalid attribute on a declaration.
- currentScope.addProblem(new UnknownNamespaceProblem(raw_qualifier, qualifier));
-
- return qualified_name;
- }
-
- /**
- * Error trap.
- */
- public String error_reduce_Op_AssignId(IASNode iNode, String non_lvalue, String rvalue)
- {
- currentScope.addProblem(new InvalidLvalueProblem(iNode));
- return createInstruction(iNode);
- }
-
- /**
- * Generate access to a named entity.
- *
- * @param name - the entity's name.
- * @return an instruction sequence to access the entity.
- */
- String generateAccess(IASNode iNode, Binding name)
- {
- StringBuilder result = new StringBuilder();
- generateAccess(iNode, name, result);
- return result.toString();
- }
-
- /**
- * Generate access to a named entity.
- *
- * @param name - the entity's name.
- * @param result - the instruction sequence to generate into.
- */
- void generateAccess(IASNode iNode, Binding binding, StringBuilder result)
- {
- if (binding.isLocal())
- {
- final String name = bindingToString(iNode, binding, false, false);
- result.append(name);
- }
- else
- {
- assert (binding.getName() != null) : "non-local Binding " + binding + " must have a name";
- currentScope.getMethodBodySemanticChecker().checkGetProperty(binding);
- // generateAccess( iNode, binding.getName(), result);
- final String name = bindingToString(iNode, binding, true, true);
- result.append(name);
- }
- }
-
- /**
- * Generate access to a named entity.
- *
- * @param name - the entity's name.
- * @param result - the instruction sequence to generate into.
- */
- void generateAccess(IASNode iNode, Name name, StringBuilder result)
- {
- final String str = nameToString(iNode, name, true, true);
- result.append(str);
-
- /*
- * if ( name.isTypeName() ) { generateAccess(name.getTypeNameBase(),
- * result); generateTypeNameParameter(name.getTypeNameParameter(),
- * result); result.addInstruction(OP_applytype, 1); } else {
- * result.addInstruction(OP_findpropstrict, name);
- * result.addInstruction(OP_getproperty, name); }
- */
- }
-
- /**
- * Generate code to assign to a named entity.
- *
- * @param target - the entity to be assigned to.
- * @param rvalue - the value to assign.
- * @return an String sequence that stores the given rvalue in the target.
- */
- String generateAssignment(IASNode iNode, Binding target, String rvalue)
- {
- return generateAssignment(iNode, target, rvalue, false);
- }
-
- /**
- * Generate code to assign to a named entity.
- *
- * @param target - the entity to be assigned to.
- * @param rvalue - the value to assign.
- * @param need_value - when true, leave a DUP of the rvalue on the stack.
- * @return an String sequence that stores the given rvalue in the target,
- * and leaves a DUP of the rvalue on the stack if need_value is set.
- */
- String generateAssignment(IASNode iNode, Binding target, String rvalue, boolean need_value)
- {
- String result = createInstruction(iNode, rvalue.length() + 4);
-
- result += rvalue;
-
- /*
- * result.addAll(rvalue); if ( need_value )
- * result.addInstruction(OP_dup); if ( target.isLocal() ) { if (
- * target.getDefinition() != null ) { ITypeDefinition type =
- * target.getDefinition
- * ().resolveType(currentScope.getDefinitionCache()); if ( type != null
- * && type != ClassDefinition.getAnyTypeClassDefinition() ) {
- * result.addInstruction(OP_coerce,
- * ((DefinitionBase)type).getMName(currentScope.getProject())); } }
- * result.addInstruction(target.setlocal()); } else {
- * result.addInstruction(OP_findproperty, target.getName());
- * result.addInstruction(OP_swap); result.addInstruction(OP_setproperty,
- * target.getName()); }
- */
- return result;
- }
-
- /**
- * Generate a catch block.
- *
- * @param catch_proto - the catch block's prototype.
- */
- /*
- * String generateCatchBlock( Label try_start, Label try_end, CatchPrototype
- * catch_proto) { String scope_reinit =
- * currentScope.getFlowManager().getScopeStackReinit(); String current_catch
- * = new String(catch_proto.catchBody.size() + scope_reinit.size() + 15); //
- * Common prologue code. current_catch.addInstruction(OP_getlocal0);
- * current_catch.addInstruction(OP_pushscope); if(
- * currentScope.needsActivation() ) { // Restore the activation object.
- * current_catch
- * .addInstruction(currentScope.getActivationStorage().getlocal());
- * current_catch.addInstruction(OP_pushscope); } // Re-establish enclosing
- * exception scopes. current_catch.addAll(scope_reinit); int handler_number
- * = currentScope.getMethodBodyVisitor().visitException(try_start, try_end,
- * current_catch.getLabel(), catch_proto.catchType,
- * catch_proto.catchVarName); Binding exception_storage =
- * currentScope.getFlowManager().getFinallyContext().getExceptionStorage();
- * current_catch.addInstruction(OP_newcatch, handler_number);
- * current_catch.addInstruction(OP_dup); if ( exception_storage != null ) {
- * current_catch.addInstruction(exception_storage.setlocal());
- * current_catch.addInstruction(OP_dup); }
- * current_catch.addInstruction(OP_pushscope);
- * current_catch.addInstruction(OP_swap);
- * current_catch.addInstruction(OP_setslot, 1);
- * current_catch.addAll(catch_proto.catchBody); if (
- * current_catch.canFallThrough() || current_catch.hasPendingLabels() ) {
- * current_catch.addInstruction(OP_popscope); } return current_catch; }
- */
-
- /**
- * Generate a compound assignment statement.
- */
- String generateCompoundAssignment(IASNode iNode, Binding operand, String expr, int opcode, boolean need_value)
- {
- String result = createInstruction(iNode, expr.length() + (operand.isLocal() ? 4 : 8));
- /*
- * if ( operand.isLocal() ) { result.addInstruction(operand.getlocal());
- * result.addAll(expr); result.addInstruction(opcode); if ( need_value )
- * result.addInstruction(OP_dup);
- * result.addInstruction(operand.setlocal()); } else { Binding
- * value_temp = null; result.addInstruction(OP_findpropstrict,
- * operand.getName()); result.addInstruction(OP_dup);
- * result.addInstruction(OP_getproperty, operand.getName());
- * result.addAll(expr); result.addInstruction(opcode); if ( need_value )
- * { value_temp = currentScope.allocateTemp();
- * result.addInstruction(OP_dup);
- * result.addInstruction(value_temp.setlocal()); }
- * result.addInstruction(OP_setproperty, operand.getName()); if (
- * need_value ) { result.addInstruction(value_temp.getlocal());
- * result.addInstruction(value_temp.kill()); } }
- */
- final String op = opToString(iNode, opcode);
- final String methodName = bindingToString(iNode, operand, true, true);
- if (methodName.contains("."))
- {
- final String stem = methodName.substring(0, methodName.lastIndexOf("."));
- final String member = getBasenameFromBinding(operand);
- result += resolveSetterName(iNode, stem, makeMemberBinding(iNode, stem, member), op + "=", expr, false, true);
- }
- else
- {
- result += binaryOp(methodName, expr, op + "=");
- }
-
- if (need_value)
- result = "(" + result + ")";
- else
- result += ";" + endl();
-
- return result;
- }
-
- String generateCompoundBracketAssignment(IASNode iNode, String stem, String index, String expr, int opcode, boolean need_value)
- {
- String result = createInstruction(iNode, stem.length() * 2 + index.length() + expr.length() + 11);
-
- /*
- * // Although ASC evaluates the stem twice, it only evaluates the index
- * once. // TODO: Inspect the index expression for side effects so the
- * temp can be // elided in most cases. Binding index_temp =
- * currentScope.allocateTemp(); result.addAll(index);
- * result.addInstruction(index_temp.setlocal());
- * result.addAll(replicate(stem));
- * result.addInstruction(index_temp.getlocal());
- * result.addInstruction(OP_getproperty); result.addAll(expr);
- * result.addInstruction(opcode); Binding value_temp =
- * currentScope.allocateTemp();
- * result.addInstruction(value_temp.setlocal()); result.addAll(stem);
- * result.addInstruction(index_temp.getlocal());
- * result.addInstruction(value_temp.getlocal());
- * result.addInstruction(OP_setproperty); if ( need_value )
- * result.addInstruction(value_temp.getlocal());
- * result.addAll(currentScope.releaseTemp(value_temp));
- * result.addAll(currentScope.releaseTemp(index_temp));
- */
-
- // String result = binaryOp(stem + "[" + index + "]", expr, opcode + "=");
- final String op = opToString(iNode, opcode);
- result += resolveSetterName(iNode, stem, makeMemberBinding(iNode, stem, index), op + "=", expr, true, true);
- if (need_value)
- result = "(" + result + ")";
- else
- result += ";" + endl();
- return result;
- }
-
- String generateCompoundMemberAssignment(IASNode iNode, String stem, Binding member, String expr, int fetch_opcode, int assign_opcode, boolean need_value)
- {
- String result = createInstruction(iNode, stem.length() * 2 + expr.length() + 5);
-
- /*
- * // TODO: Depending on the resolution of ASC-4159 and // the
- * corresponding Falcon backwards compatibility // issue, cache the stem
- * expression in a local to avoid // multiple evaluations.
- * result.addAll(replicate(stem)); result.addInstruction(fetch_opcode,
- * member.getName()); result.addAll(expr);
- * result.addInstruction(assign_opcode); if ( need_value ) {
- * result.addInstruction(OP_dup); } result.addAll(stem);
- * result.addInstruction(OP_swap); result.addInstruction(OP_setproperty,
- * member.getName());
- */
-
- // String result = binaryOp(stem + "." + getBasenameFromBinding( member ), expr, opcode + "=");
- final String op = opToString(iNode, assign_opcode);
- result += resolveSetterName(iNode, stem, member, op + "=", expr, false, true);
- if (need_value)
- result = "(" + result + ")";
- else
- result += ";" + endl();
- return result;
- }
-
- String generateCompoundAssignmentToRuntimeName(IASNode iNode, RuntimeMultiname name, String expr, int opcode, boolean need_value)
- {
- String rhs = opToString(iNode, opcode) + "= " + expr;
-
- return name.generateAssignment(iNode, rhs);
- }
-
- /**
- * Generate a compound logical assignment expression to a named lvalue.
- *
- * @param iNode - the assignment operator (root of the subtree).
- * @param lvalue - the lvalue's name.
- * @param expr - the expression to assign.
- * @param is_and - true if the expression is &&=, false if it's ||=.
- * @param need_value - true if the expression's not used in a void context.
- */
- String generateCompoundLogicalAssignment(IASNode iNode, Binding lvalue, String expr, boolean is_and, boolean need_value)
- {
- String result = createInstructionList(iNode);
-
- /*
- * Label tail = new Label(); int failure_test = is_and? OP_iffalse :
- * OP_iftrue; if ( lvalue.isLocal() ) { // Fetch and test the current
- * value. result.addInstruction(lvalue.getlocal()); // The current value
- * may not be the result value, // but for now assume it is. if (
- * need_value ) result.addInstruction( OP_dup); result.addInstruction(
- * failure_test, tail ); // Test succeeded: reset the value, but first
- * // pop the value speculatively dup'd above. if ( need_value )
- * result.addInstruction(OP_pop); result.addAll(expr); if ( need_value )
- * result.addInstruction(OP_dup);
- * result.addInstruction(lvalue.setlocal()); } else { // Fetch,
- * speculatively dup, and test the current value.
- * result.addInstruction(OP_findpropstrict, lvalue.getName());
- * result.addInstruction(OP_getproperty, lvalue.getName()); if (
- * need_value ) result.addInstruction(OP_dup);
- * result.addInstruction(failure_test, tail); if ( need_value )
- * result.addInstruction(OP_pop); result.addAll(expr); if ( need_value )
- * { result.addInstruction(OP_dup); }
- * result.addInstruction(OP_findpropstrict, lvalue.getName());
- * result.addInstruction(OP_swap); result.addInstruction(OP_setproperty,
- * lvalue.getName()); } result.labelNext(tail);
- */
-
- final String lvalStr = bindingToString(iNode, lvalue, true, true);
- result += lvalStr + " = (" + lvalStr + ") ";
- if (is_and)
- result += "&& ";
- else
- result += "|| ";
- result += "(" + expr + ");\n";
-
- return result;
- }
-
- /**
- * Generate compound logical assignment to a runtime name, e.g., n::x ||=
- * foo;
- *
- * @param iNode - the root of the assignment subtree.
- * @param name - the runtime name.
- * @param expr - the second operand of the implied binary expression.
- * @param is_and - true if the result is set to the second operand iff the
- * first operand is true.
- * @param need_value - true if the value of the assignment is required.
- */
- String generateCompoundLogicalRuntimeNameAssignment(IASNode iNode, RuntimeMultiname name, String expr, boolean is_and, boolean need_value)
- {
- return (is_and) ?
- String.format("%s &&= %s", name.generateRvalue(iNode), expr)
- :
- String.format("%s ||= %s", name.generateRvalue(iNode), expr);
- }
-
- /**
- * Generate a compound logical assignment expression to a a[i] type lvalue.
- *
- * @param iNode - the assignment operator (root of the subtree).
- * @param stem - the expression that generates the lvalue's stem, e.g., a in
- * a[i]
- * @param index - the index expression.
- * @param expr - the expression to assign.
- * @param is_and - true if the expression is &&=, false if it's ||=.
- * @param need_value - true if the expression's not used in a void context.
- */
- String generateCompoundLogicalBracketAssignment(IASNode iNode, String stem, String index, String expr, boolean is_and, boolean need_value)
- {
- String result = createInstructionList(iNode);
-
- /*
- * String result = createInstructionList(iNode, stem.size() * 2 +
- * index.size() + expr.size() + 11 ); Label tail = new Label(); int
- * failure_test = is_and? OP_iffalse : OP_iftrue; // Although ASC
- * evaluates the stem twice, it only evaluates the index once. // TODO:
- * Inspect the index expression for side effects so the temp can be //
- * elided in most cases. Binding index_temp =
- * currentScope.allocateTemp(); result.addAll(index);
- * result.addInstruction(index_temp.setlocal());
- * result.addAll(replicate(stem));
- * result.addInstruction(index_temp.getlocal()); result.addAll(stem);
- * result.addInstruction(index_temp.getlocal());
- * result.addInstruction(OP_getproperty); // Assume this is the result.
- * result.addInstruction(OP_dup); result.addInstruction(failure_test,
- * tail); // Pop the speculative result and assign the correct one.
- * result.addInstruction(OP_pop); result.addAll(expr);
- * result.labelNext(tail); Binding value_temp = null; if ( need_value )
- * { value_temp = currentScope.allocateTemp();
- * result.addInstruction(OP_dup);
- * result.addInstruction(value_temp.setlocal()); }
- * result.addInstruction(OP_setproperty); if ( need_value ) {
- * result.addInstruction(value_temp.getlocal());
- * result.addAll(currentScope.releaseTemp(value_temp)); }
- * result.addAll(currentScope.releaseTemp(index_temp));
- */
-
- currentScope.addProblem(new JSUnsupportedFeatureProblem(iNode, "logical bracket assignment"));
- return result;
- }
-
- /**
- * Generate a compound logical assignment expression to a foo.bar type
- * lvalue
- *
- * @param iNode - the assignment operator (root of the subtree).
- * @param stem - the expression that generates the lvalue's stem, e.g., a in
- * a[i]
- * @param index - the index expression.
- * @param expr - the expression to assign.
- * @param is_and - true if the expression is &&=, false if it's ||=.
- * @param need_value - true if the expression's not used in a void context.
- */
- String generateCompoundLogicalMemberAssignment(IASNode iNode, String stem, Binding member, String expr, int fetch_opcode, boolean is_and, boolean need_value)
- {
- String result = createInstructionList(iNode);
-
- /*
- * Label tail = new Label(); int failure_test = is_and? OP_iffalse :
- * OP_iftrue; result.addAll(replicate(stem)); result.addAll(stem);
- * result.addInstruction(OP_getproperty, member.getName()); // Assume
- * this is the result. result.addInstruction(OP_dup);
- * result.addInstruction(failure_test, tail);
- * result.addInstruction(OP_pop); result.addAll(expr);
- * result.labelNext(tail); Binding value_temp = null; if ( need_value )
- * { value_temp = currentScope.allocateTemp();
- * result.addInstruction(OP_dup);
- * result.addInstruction(value_temp.setlocal()); }
- * result.addInstruction(OP_setproperty, member.getName()); if (
- * need_value ) { result.addInstruction(value_temp.getlocal());
- * result.addAll(currentScope.releaseTemp(value_temp)); }
- */
-
- currentScope.addProblem(new JSUnsupportedFeatureProblem(iNode, "logical member assignment"));
- return result;
-
- }
-
- /**
- * Generate a for/in or for each/in loop.
- *
- * @param iNode - the for/in or for/each node.
- * @param opcode - OP_nextname or OP_nextvalue.
- * @param it - the name of the iterator variable, e.g., v in for (v in foo)
- * {f(v);}.
- * @param base - the source of names/values, e.g., foo in for (v in foo)
- * {f(v);}.
- * @param body - the loop body, e.g., {f(v);} in for (v in foo) {f(v);}.
- */
- private String generateForKeyOrValueLoop(IASNode iNode, int opcode, Binding it, String base, String body)
- {
- /*
- * String result = new String(body.size() + base.size() + 15); Label
- * test = new Label(); Label loop = new Label(); // Set up the object
- * and index registers. LexicalScope.Hasnext2Wrapper hasnext =
- * currentScope.hasnext2(); result.addInstruction(OP_pushbyte, 0);
- * result.addInstruction(hasnext.index_temp.setlocal());
- * result.addAll(base); result.addInstruction(OP_coerce_a);
- * result.addInstruction(hasnext.stem_temp.setlocal()); // Go to the
- * loop test. result.addInstruction(OP_jump, test); // Top of loop
- * processing. result.addInstruction(OP_label);
- * result.labelCurrent(loop); String nextvalue = new String(3);
- * result.addInstruction(hasnext.stem_temp.getlocal());
- * result.addInstruction(hasnext.index_temp.getlocal());
- * nextvalue.addInstruction(opcode);
- * result.addAll(generateAssignment(iNode, it, nextvalue));
- * result.addAll(body); // Loop test. // It needs its own list so the
- * continue target // can be properly resolved; this label is always //
- * attached to the head of an String. String test_list = new String(1);
- * test_list.addInstruction(hasnext.String);
- * test_list.labelCurrent(test);
- * currentScope.getFlowManager().resolveContinueLabel(test_list);
- * test_list.addInstruction(OP_iftrue, loop); result.addAll(test_list);
- * result.addAll(hasnext.release());
- */
-
- String result = new String();
- return result;
- }
-
- HashMap<IASNode, Boolean> nestedFunctions = new HashMap<IASNode, Boolean>();
-
- /**
- * generateFunctionBody() wrapper suitable for calling from the BURM. See
- * JBurg ENHRQ <N> : the grammar that accepts the BURM's parameters to a
- * JBurg.Reduction routine doesn't grok function calls, so the BURM cannot
- * call generateFunctionBody(body, name.getName());
- */
- String generateFunctionBody(IASNode iNode, String function_body, Binding return_type)
- {
- return generateFunctionBody(iNode, function_body, return_type != null ? return_type.getName() : null);
- }
-
- /**
- * Generate boilerplate function prolog/epilog code.
- *
- * @param block - the actual CFG.
- * @param return_type - the function's return type. Not presently used.
- */
- String generateFunctionBody(IASNode iNode, String function_body, Name return_type)
- {
- currentScope.getMethodInfo().setReturnType(return_type);
- String result = "";
- final String methodName = getMethodName();
- final Boolean isAnonymousFunction = isAnonymousFunction(methodName);
- final Boolean isCtor = methodName != null && methodName.equals(getCurrentClassName());
-
- if (return_type != null)
- usedTypes.add(getBasenameFromName(return_type));
-
- final Boolean isNestedFunction = nestedFunctions.containsKey(iNode);
-
- /*
- * !isAnonymousFunction is necessary. AS and JS are different in the way
- * "this" is being treated in anonymous functions. i.e. public function
- * whoIsThis() : void { const localFunction : Function = funciton():void
- * { this.callMe(); }; } In this example this.callMe() refers to the
- * callMe method of the class. In JS "this" refers to the local
- * function! By supressing "var self = this;" for anonymous functions
- * we'll emulate the AS behavior. The JS result then looks like this:
- * tests.Test.whoIsThis.prototype = function() { var self = this; const
- * localFunction : Function = funciton():void { // NOT EMITTED: var self
- * = this; self.callMe(); }; };
- */
- if (//!JSSharedData.m_useSelfParameter && !isAnonymousFunction &&
- /* TODO: !needsSelfParameter(createFullClassName(false)) && */ !isNestedFunction && function_body.contains("self."))
- {
- // final Binding fullClassName = makeBinding(createFullClassName(false));
- // this.registerLocalVariable(currentScope, makeBinding("self"), fullClassName, fullClassName);
-
- final Binding fullClassName = new Binding(iNode, makeName(createFullClassName(false)), null);
- this.registerLocalVariable(currentScope, new Binding(iNode, makeName("self"), null), fullClassName, fullClassName);
- result += indentBlock("/** @type {" + createFullClassName(true) + "} */" + endl(), 1);
- result += indentBlock("var self = this;" + endl(), 1);
- }
-
- // Constructor-specific processing: add the instance initializers,
- // add a constructsuper call if none exists.
- if (haveAPrioriInstructions() && !isAnonymousFunction)
- {
- result += indentBlock(aPrioriInstructions, 1);
-
- // If this is a constructor and there's no explicit
- // super() call, synthesize one.
- // Note that this may be a semantic error if the
- // superclass' constructor needs arguments.
- /*
- * if ( isCtor && !block.contains("super(") ) { // Call the
- * superclass' constructor after the instance // init instructions;
- * this doesn't seem like an abstractly // correct sequence, but
- * it's what ASC does. result += "" // TODO: //
- * result.addInstruction(OP_getlocal0); //
- * result.addInstruction(OP_constructsuper, 0); }
- */
- }
-
- if (!function_body.isEmpty())
- result += indentBlock(function_body, 1);
-
- // popIndent();
- // result += indent() + "}";
- return result;
- }
-
- private IFunctionNode getFunctionNodeFromNode(IASNode iNode)
- {
- IFunctionNode fn = null;
- if (iNode instanceof FunctionObjectNode)
- {
- FunctionObjectNode afn = (FunctionObjectNode)iNode;
- fn = afn.getFunctionNode();
- }
- else if (iNode instanceof IFunctionNode)
- {
- fn = (IFunctionNode)iNode;
- }
-
- if (fn == null)
- currentScope.addProblem(new JSInternalCompilerProblem(iNode, "cannot extract function node"));
-
- return fn;
- }
-
- private IFunctionDefinition getFunctionDefinitionFromNode(IASNode iNode)
- {
- final IFunctionNode fn = getFunctionNodeFromNode(iNode);
- return fn.getDefinition();
- }
-
- /**
- * Generate a named nested function.
- *
- * @param func_name - the function's name.
- * @param return_type - the function's return type.
- * @param function_body - the body of the function.
- * @pre the function's lexical scope must be at the top of the lexical scope
- * stack, with the declaring function's lexical scope under it.
- * @post the nested function's MethodInfo is filled in, the function body is
- * attached to its MethodBodyInfo, and the declaring function's
- * initialization sequence gets code to declare the function.
- */
- private String generateNestedFunction(IASNode iNode, Binding func_name, Name return_type, String function_body)
- {
- nestedFunctions.put(iNode, true);
-
- final Boolean isAnonymousFunction = func_name == null && iNode instanceof FunctionObjectNode;
-
- // only the outer function of a nested function should be converted to
- final Boolean convertLocalVarsToMembers = !isAnonymousFunction && convertLocalVarsToMembers(iNode);
-
- String result = "";
- if (!isAnonymousFunction)
- {
- currentScope.setFunctionName(getBasenameFromBinding(func_name));
- result = generateFunctionBody(iNode, function_body, new Binding(iNode, return_type, null));
- }
-
- currentScope.generateNestedFunction(null);
- // Pull the nested function's MethodInfo out of its scope before we pop it.
- MethodInfo nested_method_info = currentScope.getMethodInfo();
-
- currentScope = currentScope.popFrame();
-
- // Intiialize the nested function; add a variable
- // to the containing function scope and add
- // newfunction/setproperty logic to the containing
- // function's hoisted initialization instructions.
- if (!isAnonymousFunction && !convertLocalVarsToMembers)
- currentScope.makeVariable(func_name);
-
- /*
- * String init_insns = currentScope.getHoistedInitInstructions();
- * init_insns.addInstruction(OP_findproperty, func_name); //
- * Optimization: declare the function at global scope // (in a utility
- * namespace) and only new it once.
- * init_insns.addInstruction(OP_newfunction, nested_method_info);
- * init_insns.addInstruction(OP_setproperty, func_name);
- */
-
- {
- final FunctionNode fn = (FunctionNode)getFunctionNodeFromNode(iNode);
-
- // Workaround for Falcon bug.
- // In theory, just using
- // MethodInfo mi = currentScope.methodInfo;
- // should work. But in 307387 the parameter names and types are empty.
- // currentScope.methodInfo does contain the default values, because
- // reduce_optionalParameter got called
- if (!nested_method_info.hasParamNames())
- {
- MethodInfo miRepaired = JSGenerator.createMethodInfo(this, getEmitter(), currentScope, fn);
- final Vector<PooledValue> defaultValues = nested_method_info.getDefaultValues();
- for (PooledValue pv : defaultValues)
- {
- miRepaired.addDefaultValue(pv);
- }
- nested_method_info = miRepaired;
- }
-
- String[] chunk = null;
- try
- {
- // chunk = emitParameters(currentScope.getProject(), fn.getDefinition());
- chunk = emitParameters(nested_method_info);
- }
- catch (Exception e)
- {
-
- }
-
- final String a_priori_insns = chunk[0];
- final String params = chunk[1];
- final String baseName = getBasenameFromBinding(func_name);
-
- // String result = generateFunction((IFunctionNode)__p, null, n, block, return_type );
- result = "";
-
- /*
- * internal compiler error generated with optimize enabled compiling
- * as3_enumerate.fla and fails to release the JS file
- * http://watsonexp.corp.adobe.com/#bug=3047880 We have to emit
- * something, otherwise you'd get:
- * @type {function(, , )} as that happened in as3_enumerate
- * MainTimeline. In the original MainTimeline.as change() is a local
- * function with untyped parameters: function change(identifier,
- * object, correct) which gets promoted to a method via
- * [ConvertLocalVarsToMembers] of frame0(). It seems that there are
- * two bugs: 1. JSDoc comments for functions with untyped parameters
- * should use "*" instead:
- * @type {function(*, *, *)} 2. JSDoc comments for promoted local
- * functions should be omitted. The change below addresses #2.
- */
-
- // JSDoc
- if (!convertLocalVarsToMembers)
- result += getJSDocForFunction(nested_method_info);
-
- /*
- * @@@ if( !isAnonymousFunction && convertLocalVarsToMembers ) {
- * result += getCurrentFullClassName() + ".prototype." + baseName +
- * " = "; }
- */
-
- // support for [ConvertLocalVarsToMembers]
- if (convertLocalVarsToMembers)
- {
- result += "\n";
- if (a_priori_insns != null && !a_priori_insns.isEmpty())
- result += a_priori_insns + "\n";
-
- if (!JSSharedData.m_useSelfParameter &&
- /*
- * TODO: !needsSelfParameter(createFullClassName(false))
- * &&
- */function_body.contains(JSSharedData.THIS) &&
- !function_body.contains("var " + JSSharedData.THIS))
- {
- // final Binding fullClassName = makeBinding(createFullClassName(false));
- // this.registerLocalVariable(currentScope, makeBinding("self"), fullClassName, fullClassName);
-
- final Binding fullClassName = new Binding(iNode, makeName(createFullClassName(false)), null);
- this.registerLocalVariable(currentScope, new Binding(iNode, makeName("self"), null), fullClassName, fullClassName);
- result += indentBlock("/** @type {" + createFullClassName(true) + "} */" + endl(), 1);
- result += indentBlock("var " + JSSharedData.THIS + " = this;" + endl(), 1);
- }
-
- result += function_body;
-
- final JSEmitter emitter = getEmitter();
- final FunctionNode func = (FunctionNode)iNode;
- final ITraitsVisitor itraits = emitter.getCurrentClassVisitor().visitInstanceTraits();
- itraits.visitMethodTrait(DirectiveProcessor.functionTraitKind(func, TRAIT_Method), getNameFromBinding(func_name), 0, nested_method_info);
-
- IMethodVisitor mv = emitter.visitMethod(nested_method_info);
- mv.visit();
-
- MethodBodyInfo mbi = new MethodBodyInfo();
- mbi.setMethodInfo(nested_method_info);
-
- IMethodBodyVisitor mbv = mv.visitBody(mbi);
- mbv.visit();
-
- InstructionList insns = new InstructionList();
- insns.addInstruction(JSSharedData.OP_JS, result);
-
- mbv.visitInstructionList(insns);
-
- mbv.visitEnd();
- mv.visitEnd();
-
- result = "";
-
- /*
- * internal compiler error generated with optimize enabled
- * compiling as3_enumerate.fla and fails to release the JS file
- * We have to emit something, otherwise you'd get:
- * @type {function(, , )} as that happened in as3_enumerate
- * MainTimeline. In the original MainTimeline.as change() is a
- * local function with untyped parameters: function
- * change(identifier, object, correct) which gets promoted to a
- * method via [ConvertLocalVarsToMembers] of frame0(). It seems
- * that there are two bugs: 1. JSDoc comments for functions with
- * untyped parameters should use "*" instead:
- * @type {function(*, *, *)} 2. JSDoc comments for promoted
- * local functions should be omitted. The change below addresses
- * #2.
- */
- // result += getJSDocForFunction(nested_method_info);
-
- this.registerConvertedMember(baseName);
-
- // result += "\nvar " + baseName + " /* : Function */ = " + JSSharedData.THIS + "." + baseName + ";\n";
- }
- else
- {
- if (isAnonymousFunction)
- result += "function";
- else
- result += "\nfunction " + baseName;
-
- result += "(" + params + ")";
-
- final Name retType = nested_method_info.getReturnType();
- if (retType != null)
- result += " /* : " + getBasenameFromName(retType) + " */";
- else
- result += " /* : void */";
-
- result += indent() + "\n";
- result += indent() + "{\n";
- if (a_priori_insns != null && !a_priori_insns.isEmpty())
- result += indentBlock(a_priori_insns, 1) + "\n";
- result += indentBlock(function_body, 1);
- result += indent() + "}";
- if (!isAnonymousFunction)
- result += "\n";
- }
- }
-
- // nested functions use "self" to get at instance vars
- if (result.contains("this."))
- {
- result = result.replace("this.", "self.");
- }
- return result;
- }
-
- /**
- * Generate a try/catch/finally (or try/finally) compound statement.
- *
- * @param try_stmt - the body of the try block.
- * @param catch_blocks - associated catch blocks. May be null if no catch
- * blocks are present.
- * @param finally_stmt - the body of the finally block.
- */
- String generateTryCatchFinally(IASNode iNode, String try_stmt, Vector<CatchPrototype> catch_blocks, String finally_stmt)
- {
- /*
- * // TODO: Optimize these String sizes. String normal_flow_fixup = new
- * String(); String catch_insns = new String(); String final_catch = new
- * String(); String finally_insns = new String(); String final_throw =
- * new String(); ExceptionHandlingContext finally_context =
- * currentScope.getFlowManager().getFinallyContext(); Label
- * final_catch_target = final_catch.getLabel(); // We need a local to
- * store the caught exception. Binding exception_storage =
- * finally_context.getExceptionStorage(); Collection<Label>
- * pending_normal_control_flow = try_stmt.stripPendingLabels(); if (
- * try_stmt.canFallThrough() || pending_normal_control_flow != null ) {
- * normal_flow_fixup.addInstruction(OP_jump,
- * finally_context.finallyBlock); } else { // Extend the region past a
- * terminating // throw statement to give the AVM a // little buffer to
- * figure out its // exception-handling regions.
- * normal_flow_fixup.addInstruction(OP_nop); } Label try_start =
- * try_stmt.getLabel(); Label try_end =
- * normal_flow_fixup.getLastLabel(); Label finally_region_end = null; if
- * ( null == catch_blocks ) { finally_region_end = try_end; } else { for
- * ( CatchPrototype catch_proto: catch_blocks ) { String catch_body =
- * generateCatchBlock(try_start, try_end, catch_proto); boolean
- * is_last_catch = catch_proto.equals(catch_blocks.lastElement()); if (
- * catch_body.canFallThrough() ) { // Signal the finally block that this
- * execution succeeded. catch_body.addInstruction(OP_pushbyte, 0);
- * catch_body.addInstruction(OP_coerce_a);
- * catch_body.addInstruction(finally_context
- * .finallyReturnStorage.setlocal()); catch_body.addInstruction(OP_jump,
- * finally_context.finallyBlock); } else if ( is_last_catch ) { //
- * Extend the region past a terminating throw // insn to give the AVM a
- * little buffer. catch_body.addInstruction(OP_nop); } if (
- * is_last_catch ) finally_region_end = catch_body.getLastLabel();
- * catch_insns.addAll(catch_body); } } // Set up the exception handler
- * for the finally block.
- * currentScope.getMethodBodyVisitor().visitException(try_start,
- * finally_region_end, final_catch_target, null, null); // The final
- * catch block only needs to save the // caught exception for a rethrow.
- * final_catch.addInstruction(OP_getlocal0);
- * final_catch.addInstruction(OP_pushscope); if(
- * currentScope.needsActivation() ) { // Restore the activation object
- * final_catch
- * .addInstruction(currentScope.getActivationStorage().getlocal());
- * final_catch.addInstruction(OP_pushscope); }
- * final_catch.addAll(currentScope
- * .getFlowManager().getScopeStackReinit());
- * final_catch.addInstruction(exception_storage.setlocal()); // Signal
- * the finally epilog that this execution failed // and should rethrow.
- * final_catch.addInstruction(OP_pushbyte,
- * currentScope.getFlowManager().getFinallyAlternativesSize() + 1);
- * final_catch.addInstruction(OP_coerce_a);
- * final_catch.addInstruction(finally_context
- * .finallyReturnStorage.setlocal()); // falls through //
- * final_catch.addInstruction(OP_jump, finally_head);
- * finally_insns.addInstruction
- * (finally_context.finallyReturnStorage.getlocal());
- * finally_insns.addInstruction(OP_convert_i);
- * finally_insns.addInstruction
- * (finally_context.finallyReturnStorage.kill());
- * finally_insns.addAll(currentScope
- * .getFlowManager().getFinallySwitch()); // Label the start of the
- * final set of Strings. if (!finally_stmt.isEmpty()) {
- * finally_stmt.labelFirst(finally_context.finallyBlock); } else // This
- * is just an expedient for this degenerate finally.
- * finally_insns.labelFirst(finally_context.finallyBlock);
- * final_throw.addInstruction(exception_storage.getlocal());
- * final_throw.labelCurrent(finally_context.finallyDoRethrow);
- * final_throw.addInstruction(OP_throw); // Assemble the statement.
- * String result = new String(); // Initialize the finally return
- * storage location to appease // legacy verifiers. // TODO: This could
- * travel on the value stack. // See:
- * http://bugs.adobe.com/jira/browse/CMP-104
- * result.addInstruction(OP_pushbyte, 0);
- * result.addInstruction(OP_coerce_a);
- * result.addInstruction(finally_context
- * .finallyReturnStorage.setlocal()); result.addAll(try_stmt); // Send
- * all "next statement" type control flow into the finally block.
- * result.addAllPendingLabels(pending_normal_control_flow);
- * result.addAll(normal_flow_fixup); result.addAll(catch_insns);
- * result.addAll(final_catch); result.addAll(finally_stmt);
- * result.addAll(finally_insns); result.addAll(final_throw); for (
- * ExceptionHandlingContext.FinallyReturn retblock:
- * finally_context.finallyReturns )
- * result.addAll(retblock.getStrings()); // TODO: Need more analysis of
- * how this temp travels through // the system before it can be safely
- * released. For now // just leak it.
- * //result.addAll(currentScope.releaseTemp(exception_storage)); //
- * TODO: Removing a hanging kill exposed a latent bug // in
- * hasPendingLabels() and end-of-routine processing. // Give the CG a
- * harmless String that will generate // a returnvoid if this is the
- * last statement in the routine. result.addInstruction(OP_nop); //
- * Fallthrough out of the finally block.
- * result.labelNext(finally_context.finallyDoFallthrough);
- */
-
- // statement = Pattern tryCatchFinallyStmt
- String result = "";
-
- // Do nothing if the try statement's empty.
- if (try_stmt.length() == 0)
- return result;
-
- result = indent() + "try" + endl();
- result += indent() + "{" + endl();
- result += indentBlock(try_stmt, 1);
- result += indent() + "}" + endl();
-
- if (catch_blocks != null)
- {
- for (CatchPrototype catch_proto : (Vector<CatchPrototype>)catch_blocks)
- {
- final Binding nameBinding = new Binding(iNode, catch_proto.catchVarName, null);
- Binding typeBinding;
- if (catch_proto.catchType == null)
- typeBinding = new Binding(iNode, makeName("*"), null);
- else
- typeBinding = new Binding(iNode, catch_proto.catchType, null);
-
- registerLocalVariable(currentScope, nameBinding, typeBinding, typeBinding);
-
- result += indent() + "catch(";
- if (catch_proto.catchType != null)
- {
- final StringBuilder sb = new StringBuilder();
- if (!nameToJSDocType(iNode, typeBinding.getName(), sb))
- m_needsSecondPass = true;
- result += "/** @type {" + sb.toString() + "}*/ ";
- }
- result += getBasenameFromName(catch_proto.catchVarName);
- if (catch_proto.catchType != null)
- result += " /* : " + getBasenameFromBinding(typeBinding) + "*/";
- result += ")" + endl();
- result += indent() + "{" + endl();
-
- if (catch_proto.catchBody.length() > 0)
- result += indentBlock(catch_proto.catchBody, 1);
-
- // boolean is_last_catch = catch_proto.equals(catch_blocks.lastElement());
- //if( !is_last_catch && canFallThrough(catch_body) )
- // catch_body.addInstruction(OP_jump, catch_tail);
-
- result += indent() + "}" + endl();
- }
- }
-
- if (finally_stmt != null && finally_stmt.length() != 0)
- {
- result += indent() + "finally" + endl();
- result += indent() + "{" + endl();
- result += indentBlock(finally_stmt, 1);
- result += indent() + "}" + endl();
- }
-
- return result;
- }
-
- public String reduce_typeNameParameter(IASNode iNode, Binding param_name)
- {
- StringBuilder result = new StringBuilder();
-
- generateTypeNameParameter(iNode, param_name.getName(), result);
-
- return result.toString();
- }
-
- /**
- * Generate the String sequence that designates the parameter of a
- * parameterized type, e.g., String in Vector.<String> or * in
- * Vector.<*>.
- *
- * @param name - the type parameter's name. May be null in the * case.
- * @param result - the String sequence to generate into.
- */
- void generateTypeNameParameter(IASNode iNode, Name param_name, StringBuilder result)
- {
- if (param_name == null || param_name.couldBeAnyType())
- result.append("null");
- else
- generateAccess(iNode, param_name, result);
- }
-
- /**
- * Find the specified break target.
- *
- * @param criterion - the search criterion.
- * @throws UnknownControlFlowTargetException if the criterion is not on the
- * control-flow stack.
- */
- /*
- * private String getBreakTarget(Object criterion) throws
- * UnknownControlFlowTargetException { return
- * currentScope.getFlowManager().getBreakTarget(criterion); }
- */
-
- /**
- * Find the specified continue label.
- *
- * @param criterion - the search criterion.
- * @throws UnknownControlFlowTargetException if the criterion is not on the
- * control-flow stack.
- */
- /*
- * private String getContinueLabel(Object criterion) throws
- * UnknownControlFlowTargetException { return
- * currentScope.getFlowManager().getContinueLabel(criterion); }
- */
-
- /**
- * @return the double content of a numeric literal.
- * @param iNode - the literal node.
- */
- Double getDoubleContent(IASNode iNode)
- {
- return new Double(((INumericLiteralNode)iNode).getNumericValue().toNumber());
- }
-
- /**
- * @return the name of an identifier.
- * @param iNode - the IIdentifier node.
- */
- String getIdentifierContent(IASNode iNode)
- {
- return ((IIdentifierNode)iNode).getName();
- }
-
- /**
- * @return the int content of a numeric literal.
- * @param iNode - the literal node.
- */
- Integer getIntegerContent(IASNode iNode)
- {
- return new Integer(((INumericLiteralNode)iNode).getNumericValue().toInt32());
- }
-
- /**
- * @return always zero.
- * @param iNode - the literal node.
- */
- Integer getIntegerZeroContent(IASNode iNode)
- {
- return 0;
- }
-
- /**
- * @return always zero.
- * @param iNode - the literal node.
- */
- Long getIntegerZeroContentAsLong(IASNode iNode)
- {
- return 0L;
- }
-
- /**
- * @return a node cast to MXMLEventSpecifierNode type.
- * @param iNode - the MXMLEventSpecifierNode node.
- */
- IMXMLEventSpecifierNode getMXMLEventSpecifierContent(IASNode iNode)
- {
- return (IMXMLEventSpecifierNode)iNode;
- }
-
- /**
- * Find all active exception handling blocks or scopes, and set up finally
- * return sequences and/or popscopes.
- *
- * @param original - the original control-flow sequence.
- * @param criterion - the search criterion that identifies the boundary of
- * the region to be exited.
- * @return a control-flow sequence that is either the original sequence or
- * the start of a trampoline of finally blocks, popscopes, and whatever else
- * is necessary to exit the control-flow region.
- * @throws UnknownControlFlowTargetException if the criterion is not on the
- * control-flow stack.
- */
- /*
- * private String getNonLocalControlFlow(String original, Object criterion)
- * throws UnknownControlFlowTargetException { return
- * currentScope.getFlowManager().getNonLocalControlFlow(original,
- * criterion); }
- */
-
- /**
- * @return a parameter's definition.
- * @param iNode - the parameter node.
- */
- IDefinition getParameterContent(IASNode iNode)
- {
- return (((IParameterNode)iNode).getDefinition());
- }
-
- /**
- * @return the string content of a literal.
- * @param iNode - the literal node.
- */
- String getStringLiteralContent(IASNode iNode)
- {
- // Literals.
- // Pattern stringLiteral
- // LiteralStringID(void);
- String s = ((ILiteralNode)iNode).getValue();
- if (s == null || s.length() == 0)
- return "''";
-
- s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__");
- s = s.replaceAll("\r", "__CR_PLACEHOLDER__");
- s = s.replaceAll("\t", "__TAB_PLACEHOLDER__");
- s = s.replaceAll("\f", "__FORMFEED_PLACEHOLDER__");
- s = s.replaceAll("\b", "__BACKSPACE_PLACEHOLDER__");
- s = s.replaceAll("\\\\\"", "__QUOTE_PLACEHOLDER__");
- s = s.replaceAll("\\\\", "__ESCAPE_PLACEHOLDER__");
- s = "\"" + s.replaceAll("\"", "\\\\\"") + "\"";
- s = s.replaceAll("__ESCAPE_PLACEHOLDER__", "\\\\\\\\");
- s = s.replaceAll("__QUOTE_PLACEHOLDER__", "\\\\\"");
- s = s.replaceAll("__BACKSPACE_PLACEHOLDER__", "\\\\b");
- s = s.replaceAll("__FORMFEED_PLACEHOLDER__", "\\\\f");
- s = s.replaceAll("__TAB_PLACEHOLDER__", "\\\\t");
- s = s.replaceAll("__CR_PLACEHOLDER__", "\\\\r");
- s = s.replaceAll("__NEWLINE_PLACEHOLDER__", "\\\\n");
-
- // Note: we don't try to preserve \ u NNNN or \ x NN escape codes, since the actual Unicode chars can appear
- // inside the literal just fine (unless they translate to one of the above chars, e.g. CR, in which case
- // the above substitutions will occur.
-
- return s;
- }
-
- /**
- * @return the uint content of a numeric literal.
- * @param iNode - the literal node.
- */
- Long getUintContent(IASNode iNode)
- {
- return new Long(((INumericLiteralNode)iNode).getNumericValue().toUint32());
- }
-
- /**
- * @return the Boolean content of a BOOLEAN literal.
- * @param iNode - the literal node.
- */
- boolean getBooleanContent(IASNode iNode)
- {
- return SemanticUtils.getBooleanContent(iNode);
- }
-
- /**
- * @return true if a priori Strings are present.
- */
- /*
- * private boolean haveinstanceInitializers() { return instanceInitializers
- * != null; }
- */
-
- /*
- * *******************************
- * ** Cost/Decision Functions ** *******************************
- */
-
- /**
- * Explore a MemberAccessNode and decide if its stem is a reference to a
- * package.
- */
- int isDottedName(IASNode n)
- {
- int result = Integer.MAX_VALUE;
-
- if (n instanceof MemberAccessExpressionNode)
- {
- MemberAccessExpressionNode ma = (MemberAccessExpressionNode)n;
-
- if (ma.stemIsPackage())
- // This needs to be greater than the value returned from isPackageName,
- // so that isPackageName wins
- result = 2;
- }
-
- return result;
- }
-
- /**
- * Explore a MemberAccessNode and decide if it is a reference to a package.
- */
- int isPackageName(IASNode n)
- {
- int result = Integer.MAX_VALUE;
-
- if (n instanceof MemberAccessExpressionNode)
- {
- MemberAccessExpressionNode ma = (MemberAccessExpressionNode)n;
-
- if (ma.isPackageReference())
- // This needs to be less than the value returned from isDottedName,
- // so that isPackageName wins
- result = 1;
- }
-
- return result;
- }
-
- /**
- * Check if the given AST (the root AST of a looping construct) is in the
- * set of active labeled control-flow contexts. If it is, then its
- * control-flow context is being managed by the labeledStatement production
- * that's reducing the loop's LabeledStatementNode, and the loop should use
- * that context so that the labeled context's continue label is resolved to
- * the correct top-of-loop location.
- *
- * @param loop_node - the AST at the root of the loop.
- * @return true if loop_node is known to be the substatment of a labeled
- * statement.
- */
- private boolean isLabeledSubstatement(IASNode loop_node)
- {
- return labeledNodes.contains(loop_node);
- }
-
- /**
- * Get the definition associated with a node's qualifier and decide if the
- * qualifier is a compile-time constant.
- *
- * @param iNode - the node to check.
- * @pre - the node has an IdentifierNode 0th child.
- * @return an attractive cost if the child has a known namespace, i.e., it's
- * a compile-time constant qualifier.
- */
- int qualifierIsCompileTimeConstant(IASNode iNode)
- {
- IdentifierNode qualifier = (IdentifierNode)SemanticUtils.getNthChild(iNode, 0);
- IDefinition def = qualifier.resolve(currentScope.getProject());
-
- int result = def instanceof NamespaceDefinition ? 1 : Integer.MAX_VALUE;
- return result;
- }
-
- /**
- * Get the definition associated with a node's qualifier and decide if the
- * qualifier is an interface name.
- *
- * @param iNode - the node to check.
- * @pre - the node has an IdentifierNode 0th child.
- * @return an attractive cost if the child is an interface.
- */
- int qualifierIsInterface(IASNode iNode)
- {
- IdentifierNode qualifier = (IdentifierNode)SemanticUtils.getNthChild(iNode, 0);
- IDefinition def = qualifier.resolve(currentScope.getProject());
-
- int result = def instanceof InterfaceDefinition ? 1 : Integer.MAX_VALUE;
- return result;
-
- }
-
- /**
- * @return a feasible cost if a node has a compile-time constant defintion.
- */
- int isCompileTimeConstant(IASNode iNode)
- {
- if (SemanticUtils.transformNameToConstantValue(iNode, currentScope.getProject()) != null)
- return 1;
- else
- return Integer.MAX_VALUE;
- }
-
- /**
- * @return a feasible cost if the function call node is a call to a constant
- * function.
- */
- int isCompileTimeConstantFunction(IASNode iNode)
- {
- //if ( SemanticUtils.isConstantFunction(currentScope.getProject(), iNode) )
- // return 1;
- // else
- return Integer.MAX_VALUE;
- }
-
- /**
- * @return a feasible cost if a parameterized type's base and parameter
- * types are resolved types, ERROR_TRAP if not.
- */
- int parameterTypeIsConstant(IASNode iNode)
- {
- return Math.max(
- isKnownType(SemanticUtils.getNthChild(iNode, 0)),
- isKnownType(SemanticUtils.getNthChild(iNode, 1))
- );
- }
-
- /**
- * @return a feasible cost if the type's parameter is a resolved type,
- * ERROR_TRAP if not.
- */
- int isKnownType(IASNode iNode)
- {
- boolean isConstant = false;
-
- if (iNode instanceof IExpressionNode)
- {
- IExpressionNode qualifier = (IExpressionNode)iNode;
- isConstant = qualifier.resolve(currentScope.getProject()) instanceof ITypeDefinition;
- }
-
- return isConstant ? 1 : ERROR_TRAP;
- }
-
- public Object transform_constant_function_to_value(IASNode iNode, Binding method, Vector<Object> constant_args)
- {
- assert false : "attempting to reduce a non-constant function as a constant. " +
- "isCompileTimeConstantFunction Should have guarded against this";
-
- return null;
- }
-
- /**
- * Check a Binding to decide if its referent is statically known to be a
- * Namespace.
- *
- * @param b - the Binding to check.
- * @return true if the given Binding refers to a namespace.
- */
- /*
- * private boolean isNamespace(Binding b) { return b.getDefinition()
- * instanceof NamespaceDefinition; }
- */
-
- /**
- * Check a Binding to see if it's (often incorrectly) defined as the
- * ANY_TYPE.
- *
- * @param b - the Binding to check.
- * @return true if the Binding's definition is the ANY_TYPE definition.
- */
- /*
- * private boolean isAnyType(Binding b) { return b.getDefinition() ==
- * ClassDefinition.getAnyTypeClassDefinition(); }
- */
-
- /**
- * @return a feasible cost (1) if the node is for 'new Array()'
- */
- int isEmptyArrayConstructor(IASNode iNode)
- {
- ICompilerProject project = currentScope.ge
<TRUNCATED>