You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/04/26 05:39:39 UTC
[18/27] fdb with worker support
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/a3765ae5/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerBURM.jbg
----------------------------------------------------------------------
diff --git a/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerBURM.jbg b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerBURM.jbg
new file mode 100644
index 0000000..d8f7dac
--- /dev/null
+++ b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerBURM.jbg
@@ -0,0 +1,269 @@
+package flash.tools.debugger.expression;
+
+header
+{
+ /*
+
+ 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.
+
+ AS3DebuggerBURM.java is a Bottom-Up Rewrite Machine for ActionScript 3.0.
+
+ A BURM recognizes patterns of nodes within an tree (in this case, an
+ abstract syntax tree for AS 3.0 expressions) and performs rule-based reduction
+ on them (in this case producing DebuggerValues).
+
+ AS3DebuggerBURM.java is generated from AS3DebuggerBURM.jbg using JBurg, an open-source
+ Java implementation of a Bottom-Up Rewrite Generator.
+
+ The most important entry point of this class is burm(),
+ which is called by the code generator.
+ */
+
+ import static com.adobe.flash.abc3.ABCConstants.*;
+ import static com.adobe.flash.compiler.tree.ASTNodeID.*;
+
+ import com.adobe.flash.compiler.constants.IASLanguageConstants;
+ import com.adobe.flash.compiler.exceptions.BURMAbortException;
+ import com.adobe.flash.compiler.problems.*;
+ import com.adobe.flash.compiler.internal.semantics.AS3SemanticUtils;
+ import com.adobe.flash.compiler.tree.ASTNodeID;
+ import com.adobe.flash.compiler.tree.as.IASNode;
+ import com.adobe.flash.compiler.tree.as.ITryNode;
+}
+
+INodeType IASNode;
+OpcodeType ASTNodeID;
+
+/*
+ * The I-node type is IASNode, and it has its own adapter.
+ */
+INodeAdapter com.adobe.flash.compiler.internal.codegen.as.IASNodeAdapter;
+
+// Generate Java output.
+Language java;
+
+// Return type of all the reductions
+ReturnType Object;
+
+/**
+ * This is a name to use in an expression context.
+ *
+ * TODO: What type should this be?
+ */
+ReturnType name = Object;
+
+ReturnType decl_name = Object;
+
+/**
+ * Qualified name - this acts the same as a name above, but is built a little differently.
+ */
+ReturnType qualifiedName = Object;
+ReturnType qualifiedNamePart = Object;
+
+/**
+ * This is a name used in a type annotation context, such as 'Foo' in:
+ * var x : Foo;
+ * It is a Binding, as type annotations must always be resolved.
+ * A type_name also allows '*', which can't happen in a general expression context.
+ */
+ReturnType type_name = Object;
+
+/**
+ * This is a name used in a new context, such as 'Foo' in:
+ * new Foo();
+ * We can do additional analysis when the new expression resolves to a Type, which
+ * is why we have a special name for the new expression.
+ */
+ReturnType new_type_name = Object;
+
+ReturnType dottedNamePart = String;
+
+ReturnType non_resolving_identifier = String;
+
+ReturnType runtime_name_expression = Object;
+ReturnType multinameL = Object;
+ReturnType e4x_literal = String;
+
+ReturnType integer_constant = Integer;
+ReturnType uint_constant = Long;
+ReturnType double_constant = Double;
+ReturnType string_constant = String;
+ReturnType boolean_constant = Boolean;
+ReturnType float_constant = Float;
+
+ReturnType numeric_constant = Number;
+
+ReturnType constant_value = Object;
+
+/**
+ * Value to use to indicate a cost that is not feasible
+ */
+JBurg.Constant ERROR_TRAP = 268435456;
+
+{
+ final static boolean NEED_VALUE = true;
+ final static boolean DISCARD_VALUE = false;
+
+
+ /**
+ * The reducer has all the implementation
+ * logic for the rewrite; the BURM constructed
+ * by this specification drives that logic.
+ */
+ AS3DebuggerReducer reducer;
+
+
+ /*
+ * ** Cost functions **
+ * Cost functions are Java code that returns an int value.
+ * The value is used to compute the cost of a particular
+ * candidate reduction. The BURM searches for the lowest
+ * total cost sequence of reductions to transform the input
+ * AST into a value, so low values mean "good cost," higher
+ * values mean "less desirable." The total cost of a reduction
+ * is always strictly less than Integer.MAX_VALUE; a cost of
+ * Integer.MAX_VALUE tells the pattern matcher that the
+ * reduction is not feasible.
+ */
+
+
+ /**
+ * @return "feasible" if the reducer can reduce this to a dotted name.
+ */
+ int isDottedName(IASNode iNode)
+ {
+ return reducer.isDottedName(iNode);
+ }
+
+ /**
+ * @return "feasible" if the reducer can reduce this to a package name.
+ */
+ int isPackageName(IASNode iNode)
+ {
+ return reducer.isPackageName(iNode);
+ }
+
+ /**
+ * @return "feasible" if this node's qualifier is a compile-time constant.
+ */
+ int qualifierIsCompileTimeConstant(IASNode iNode)
+ {
+ return reducer.qualifierIsCompileTimeConstant(iNode);
+ }
+
+ /**
+ * @return "feasible" if this node can be resolved to a compile-time constant.
+ */
+ int isCompileTimeConstant(IASNode iNode)
+ {
+ return reducer.isCompileTimeConstant(iNode);
+ }
+
+ /**
+ * @return "feasible" if this function call node can be resolved to a compile-time constant function.
+ */
+ int isCompileTimeConstantFunction(IASNode iNode)
+ {
+ return reducer.isCompileTimeConstantFunction(iNode);
+ }
+
+ /**
+ * @return "feasible" if this binary node has at least one expression that is
+ * of type "float".
+ */
+ int isFloatBinOp(IASNode iNode)
+ {
+ return reducer.isFloatBinOp(iNode);
+ }
+
+ /**
+ * @return "feasible" if this node is for 'new Array()'.
+ */
+ int isEmptyArrayConstructor(IASNode iNode)
+ {
+ return reducer.isEmptyArrayConstructor(iNode);
+ }
+
+ /**
+ * @return "feasible" if this node is for 'new Object()'.
+ */
+ int isEmptyObjectConstructor(IASNode iNode)
+ {
+ return reducer.isEmptyObjectConstructor(iNode);
+ }
+
+ /**
+ * @return "feasible" if this node resolves to a type definition.
+ */
+ int isKnownType(IASNode iNode)
+ {
+ return reducer.isKnownType(iNode);
+ }
+
+ /**
+ * @return "feasible" if the type parameter resolves to a type definition.
+ */
+ int parameterTypeIsConstant(IASNode iNode)
+ {
+ return reducer.parameterTypeIsConstant(iNode);
+ }
+
+ /**
+ * recordError is a convenience method for error reductions;
+ * it adds a problem to the current set of problems and
+ */
+ Object recordError(ICompilerProblem problem)
+ {
+ return new Object();
+ }
+
+ int isIntLiteral(IASNode iNode)
+ {
+ return reducer.isIntLiteral(iNode);
+ }
+
+ int isUintLiteral(IASNode iNode)
+ {
+ return reducer.isUintLiteral(iNode);
+ }
+
+ int isDoubleLiteral(IASNode iNode)
+ {
+ return reducer.isDoubleLiteral(iNode);
+ }
+
+ int isFloatLiteral(IASNode iNode)
+ {
+ return reducer.isDoubleLiteral(iNode);
+ }
+
+}
+
+/*
+ * Error recovery routine: deduce what we can from the problem
+ * tree, then abort this BURM with an exception that the caller
+ * can catch and ignore.
+ */
+DefaultErrorHandler
+{
+ BURMAbortException.abort();
+}
+
+/*
+ * Patterns and rules are stored in their own, shareable file.
+ */
+JBurg.include "../../compiler/com.adobe.flash.compiler/src/com/adobe/flash/compiler/internal/codegen/as3/AS3Patterns.jbg"
+JBurg.include "AS3DebuggerRules.jbg"
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/a3765ae5/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerCompoundAssignmentRules.jbg
----------------------------------------------------------------------
diff --git a/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerCompoundAssignmentRules.jbg b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerCompoundAssignmentRules.jbg
new file mode 100644
index 0000000..5a6b955
--- /dev/null
+++ b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerCompoundAssignmentRules.jbg
@@ -0,0 +1,28 @@
+/*
+
+ 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.
+
+*/
+
+expression = Pattern compoundAssignToName : 0
+JBurg.Reduction reducer.compoundBinaryAssignmentNameExpr(__p, operand, expr, Op_COMPOUND_ASSIGN);
+
+
+expression = Pattern compoundAssignToMember : 0
+JBurg.Reduction reducer.compoundBinaryAssignmentMemberExpr(__p, stem, member, expr, Op_COMPOUND_ASSIGN);
+
+expression = Pattern compoundAssignToBracket : 0
+JBurg.Reduction reducer.compoundBinaryAssignmentBracketExpr(__p, stem, index, expr, Op_COMPOUND_ASSIGN);
http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/a3765ae5/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerReducer.java
----------------------------------------------------------------------
diff --git a/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerReducer.java b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerReducer.java
new file mode 100644
index 0000000..611c578
--- /dev/null
+++ b/modules/fdbworkers/src/flash/tools/debugger/expression/AS3DebuggerReducer.java
@@ -0,0 +1,1966 @@
+/*
+ * 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 flash.tools.debugger.expression;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import com.adobe.flash.abc3.ABCConstants;
+import com.adobe.flash.compiler.constants.IASLanguageConstants;
+import com.adobe.flash.compiler.definitions.IDefinition;
+import com.adobe.flash.compiler.definitions.ITypeDefinition;
+import com.adobe.flash.compiler.internal.definitions.NamespaceDefinition;
+import com.adobe.flash.compiler.internal.semantics.AS3SemanticUtils;
+import com.adobe.flash.compiler.internal.tree.as.IdentifierNode;
+import com.adobe.flash.compiler.internal.tree.as.MemberAccessExpressionNode;
+import com.adobe.flash.compiler.internal.tree.as.NumericLiteralNode;
+import com.adobe.flash.compiler.internal.tree.as.RegExpLiteralNode;
+import com.adobe.flash.compiler.projects.ICompilerProject;
+import com.adobe.flash.compiler.tree.ASTNodeID;
+import com.adobe.flash.compiler.tree.INumericValue;
+import com.adobe.flash.compiler.tree.as.IASNode;
+import com.adobe.flash.compiler.tree.as.IExpressionNode;
+import com.adobe.flash.compiler.tree.as.IIdentifierNode;
+
+import flash.tools.debugger.IsolateSession;
+import flash.tools.debugger.PlayerDebugException;
+import flash.tools.debugger.Session;
+import flash.tools.debugger.Variable;
+import flash.tools.debugger.VariableType;
+import flash.tools.debugger.concrete.DValue;
+
+/**
+ * Reducer for the debugger - equivalent to the old DebuggerEvaluator
+ */
+public class AS3DebuggerReducer {
+
+ private final ContextStack contextStack;
+ private final ICompilerProject project;
+
+ public static class ContextStack {
+
+ private final List<Context> ctxStckInternal;
+
+ public ContextStack(Context context) {
+ ctxStckInternal = new ArrayList<Context>();
+ pushScope(context);
+ }
+
+ public Context scope(int i) {
+ return ctxStckInternal.get(i);
+ }
+
+ public void pushScope(Context scope) {
+ ctxStckInternal.add(scope);
+ }
+
+ public void popScope() {
+ assert (!ctxStckInternal.isEmpty());
+ ctxStckInternal.remove(ctxStckInternal.size() - 1);
+ }
+
+ public Context scope() {
+ return ctxStckInternal.get(ctxStckInternal.size() - 1);
+ }
+
+ }
+
+ public AS3DebuggerReducer(Context context, ICompilerProject project) {
+ super();
+ this.contextStack = new ContextStack(context);
+ this.project = project;
+ }
+
+ static final int ERROR_TRAP = 268435456;
+
+ private Object callFunction(Context cx, boolean isConstructor,
+ Object function, Object[] args) throws PlayerDebugException {
+ Session session = cx.getSession();
+
+ flash.tools.debugger.Value thisObject = cx.toValue();
+ if (thisObject == null)
+ thisObject = DValue.forPrimitive(null, cx.getIsolateId());
+
+ flash.tools.debugger.Value[] valueArgs = new flash.tools.debugger.Value[args.length];
+ for (int i = 0; i < args.length; ++i) {
+ /**
+ * context.toValue() may return null while
+ * PlayerSession::buildCallFunctionMessage expects the Value to be a
+ * value that depicts null. For example,
+ * xmlVar.childNode[nonexistentornullvar] will run into this case.
+ * (Came to notice via bug FB-25660)
+ */
+ flash.tools.debugger.Value tempValue = cx.toValue(args[i]);
+ if (tempValue == null) {
+ tempValue = DValue.forPrimitive(null, cx.getIsolateId());
+ }
+ valueArgs[i] = tempValue;
+ }
+
+ String functionName;
+ if (function instanceof Variable) {
+ // Sometimes, the function will show up as a Variable. This happens,
+ // for example, if the user wrote "MyClass.myFunction = function() {
+ // ... }";
+ // String.fromCharCode(), for example, is defined that way.
+ functionName = ((Variable) function).getQualifiedName();
+ } else {
+ functionName = function.toString();
+ }
+ IsolateSession workerSession = session.getWorkerSession(cx
+ .getIsolateId());
+ if (isConstructor) {
+ return workerSession.callConstructor(functionName, valueArgs);
+ } else {
+ return workerSession.callFunction(thisObject, functionName,
+ valueArgs);
+ }
+ }
+
+ Object compoundBinaryAssignmentBracketExpr(IASNode iNode, Object stem,
+ Object index, Object r, int opcode) {
+ Object leftVariable = reduce_arrayIndexExpr(iNode, stem, false, index);
+ DebuggerValue operationValue = (DebuggerValue) binaryOp(iNode,
+ leftVariable, r, opcode);
+ return reduce_assignToBracketExpr_to_expression(iNode, stem, index,
+ operationValue, false);
+ }
+
+ Object compoundBinaryAssignmentMemberExpr(IASNode iNode, Object stem,
+ Object member, Object r, int opcode) {
+ Object leftVariable = reduce_memberAccessExpr(iNode, stem, member, -1);
+ DebuggerValue operationValue = (DebuggerValue) binaryOp(iNode,
+ leftVariable, r, opcode);
+ return reduce_assignToMemberExpr_to_expression(iNode, stem, member,
+ operationValue);
+ }
+
+ Object compoundBinaryAssignmentNameExpr(IASNode iNode, Object l, Object r,
+ int opcode) {
+ Object leftVariable = transform_name_to_expression(iNode, l);
+ DebuggerValue operationValue = (DebuggerValue) binaryOp(iNode,
+ leftVariable, r, opcode);
+ return reduce_assignToNameExpr_to_expression(iNode, l, operationValue);
+ }
+
+ /**
+ * 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 instruction sequence with the operator appended.
+ */
+ Object binaryOp(IASNode iNode, Object l, Object r, int opcode) {
+ // REFER : ASC : public Value evaluate(macromedia.asc.util.Context cx,
+ // BinaryExpressionNode node)
+ switch (opcode) {
+ case ABCConstants.OP_add:
+ break;
+ }
+
+ DebuggerValue lhs = (DebuggerValue) l;
+ DebuggerValue rhs = (DebuggerValue) r;
+
+ Context eeContext = contextStack.scope();
+ Session session = eeContext.getSession();
+ switch (opcode) {
+ case ABCConstants.OP_multiply: {
+ // ECMA 11.5
+ double d1 = ECMA.toNumber(session,
+ eeContext.toValue(lhs.debuggerValue));
+ double d2 = ECMA.toNumber(session,
+ eeContext.toValue(rhs.debuggerValue));
+ return new DebuggerValue(new Double(d1 * d2));
+ }
+ case ABCConstants.OP_divide: {
+ // ECMA 11.5
+ double d1 = ECMA.toNumber(session,
+ eeContext.toValue(lhs.debuggerValue));
+ double d2 = ECMA.toNumber(session,
+ eeContext.toValue(rhs.debuggerValue));
+ return new DebuggerValue(new Double(d1 / d2));
+ }
+ case ABCConstants.OP_modulo: {
+ // ECMA 11.5
+ double d1 = ECMA.toNumber(session,
+ eeContext.toValue(lhs.debuggerValue));
+ double d2 = ECMA.toNumber(session,
+ eeContext.toValue(rhs.debuggerValue));
+ return new DebuggerValue(new Double(d1 % d2));
+ }
+ case ABCConstants.OP_add: {
+ // E4X 11.4.1 and ECMA 11.6.1
+ flash.tools.debugger.Value v1 = eeContext
+ .toValue(lhs.debuggerValue);
+ flash.tools.debugger.Value v2 = eeContext
+ .toValue(rhs.debuggerValue);
+
+ boolean isXMLConcat = false;
+
+ if (v1.getType() == VariableType.OBJECT
+ && v2.getType() == VariableType.OBJECT) {
+ String type1 = v1.getTypeName();
+ String type2 = v2.getTypeName();
+ int at;
+ at = type1.indexOf('@');
+ if (at != -1)
+ type1 = type1.substring(0, at);
+ at = type2.indexOf('@');
+ if (at != -1)
+ type2 = type2.substring(0, at);
+
+ if (type1.equals("XML") || type1.equals("XMLList")) //$NON-NLS-1$ //$NON-NLS-2$
+ if (type2.equals("XML") || type2.equals("XMLList")) //$NON-NLS-1$ //$NON-NLS-2$
+ isXMLConcat = true;
+ }
+
+ if (isXMLConcat) {
+ try {
+ IsolateSession workerSession = session.getWorkerSession(v1
+ .getIsolateId());
+ flash.tools.debugger.Value xml1 = workerSession
+ .callFunction(
+ v1,
+ "toXMLString", new flash.tools.debugger.Value[0]); //$NON-NLS-1$
+ flash.tools.debugger.Value xml2 = session.getWorkerSession(
+ v2.getIsolateId()).callFunction(v2,
+ "toXMLString", new flash.tools.debugger.Value[0]); //$NON-NLS-1$
+ String allXML = xml1.getValueAsString()
+ + xml2.getValueAsString();
+ flash.tools.debugger.Value allXMLValue = DValue
+ .forPrimitive(allXML, v1.getIsolateId());
+ flash.tools.debugger.Value retval = workerSession
+ .callConstructor(
+ "XMLList", new flash.tools.debugger.Value[] { allXMLValue }); //$NON-NLS-1$
+ return new DebuggerValue(retval);
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ } else {
+ v1 = ECMA.toPrimitive(session, v1, null,
+ eeContext.getIsolateId());
+ v2 = ECMA.toPrimitive(session, v2, null,
+ eeContext.getIsolateId());
+ if (v1.getType() == VariableType.STRING
+ || v2.getType() == VariableType.STRING) {
+ return new DebuggerValue(ECMA.toString(session, v1)
+ + ECMA.toString(session, v2));
+ } else {
+ return new DebuggerValue(new Double(ECMA.toNumber(session,
+ v1) + ECMA.toNumber(session, v2)));
+ }
+ }
+ }
+ case ABCConstants.OP_subtract: {
+ // ECMA 11.6.2
+ double d1 = ECMA.toNumber(session,
+ eeContext.toValue(lhs.debuggerValue));
+ double d2 = ECMA.toNumber(session,
+ eeContext.toValue(rhs.debuggerValue));
+ return new DebuggerValue(new Double(d1 - d2));
+ }
+ case ABCConstants.OP_lshift: {
+ // ECMA 11.7.1
+ int n1 = ECMA
+ .toInt32(session, eeContext.toValue(lhs.debuggerValue));
+ int n2 = (int) (ECMA.toUint32(session,
+ eeContext.toValue(rhs.debuggerValue)) & 0x1F);
+ return new DebuggerValue(new Double(n1 << n2));
+ }
+ case ABCConstants.OP_rshift: {
+ // ECMA 11.7.1
+ int n1 = ECMA
+ .toInt32(session, eeContext.toValue(lhs.debuggerValue));
+ int n2 = (int) (ECMA.toUint32(session,
+ eeContext.toValue(rhs.debuggerValue)) & 0x1F);
+ return new DebuggerValue(new Double(n1 >> n2));
+ }
+ case ABCConstants.OP_urshift: {
+ // ECMA 11.7.1
+ long n1 = ECMA.toUint32(session,
+ eeContext.toValue(lhs.debuggerValue));
+ long n2 = (ECMA.toUint32(session,
+ eeContext.toValue(rhs.debuggerValue)) & 0x1F);
+ return new DebuggerValue(new Double(n1 >>> n2));
+ }
+ case ABCConstants.OP_lessthan: {
+ // ECMA 11.8.1
+ flash.tools.debugger.Value lessThan = ECMA.lessThan(session,
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue));
+ boolean result;
+ if (lessThan.getType() == VariableType.UNDEFINED) {
+ result = false;
+ } else {
+ result = ECMA.toBoolean(lessThan);
+ }
+ return new DebuggerValue(result);
+ }
+ case ABCConstants.OP_greaterthan: {
+ // ECMA 11.8.2
+ flash.tools.debugger.Value greaterThan = ECMA.lessThan(session,
+ eeContext.toValue(rhs.debuggerValue),
+ eeContext.toValue(lhs.debuggerValue));
+ boolean result;
+ if (greaterThan.getType() == VariableType.UNDEFINED) {
+ result = false;
+ } else {
+ result = ECMA.toBoolean(greaterThan);
+ }
+ return new DebuggerValue(result);
+ }
+ case ABCConstants.OP_lessequals: {
+ // ECMA 11.8.3
+ flash.tools.debugger.Value lessThan = ECMA.lessThan(session,
+ eeContext.toValue(rhs.debuggerValue),
+ eeContext.toValue(lhs.debuggerValue));
+ boolean result;
+ if (lessThan.getType() == VariableType.UNDEFINED) {
+ result = false;
+ } else {
+ result = !ECMA.toBoolean(lessThan);
+ }
+ return new DebuggerValue(result);
+ }
+ case ABCConstants.OP_greaterequals: {
+ // ECMA 11.8.4
+ flash.tools.debugger.Value lessThan = ECMA.lessThan(session,
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue));
+ boolean result;
+ if (lessThan.getType() == VariableType.UNDEFINED) {
+ result = false;
+ } else {
+ result = !ECMA.toBoolean(lessThan);
+ }
+ return new DebuggerValue(result);
+ }
+ case ABCConstants.OP_instanceof: {
+ try {
+ return new DebuggerValue(session.getWorkerSession(
+ eeContext.getIsolateId()).evalInstanceof(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue)));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ case ABCConstants.OP_in: {
+ try {
+ return new DebuggerValue(session.getWorkerSession(
+ eeContext.getIsolateId()).evalIn(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue)));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ case ABCConstants.OP_istypelate: {
+ try {
+ return new DebuggerValue(session.getWorkerSession(
+ eeContext.getIsolateId()).evalIs(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue)));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ case ABCConstants.OP_astypelate: {
+ try {
+ return new DebuggerValue(session.getWorkerSession(
+ eeContext.getIsolateId()).evalAs(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue)));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ case ABCConstants.OP_equals: {
+ // ECMA 11.9.1
+ return new DebuggerValue(new Boolean(ECMA.equals(session,
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+ // ASC3 notequals is a sepearate reducer nequals
+ // case ABCConstants.op_Tokens.NOTEQUALS_TOKEN:
+ // {
+ // // ECMA 11.9.2
+ // return new DebuggerValue(new Boolean(!ECMA.equals(session,
+ // eeContext.toValue(lhs.debuggerValue), eeContext
+ // .toValue(rhs.debuggerValue))));
+ // }
+ case ABCConstants.OP_strictequals: {
+ // ECMA 11.9.4
+ return new DebuggerValue(new Boolean(ECMA.strictEquals(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+ // ASC3 notequals is a sepearate reducer nequals
+ /*
+ * case Tokens.STRICTNOTEQUALS_TOKEN: { // ECMA 11.9.5 return new
+ * DebuggerValue(new
+ * Boolean(!ECMA.strictEquals(eeContext.toValue(lhs.debuggerValue),
+ * eeContext .toValue(rhs.debuggerValue)))); }
+ */
+ case ABCConstants.OP_bitand: {
+ // ECMA 11.10
+ return new DebuggerValue(new Double(ECMA.toInt32(session,
+ eeContext.toValue(lhs.debuggerValue))
+ & ECMA.toInt32(session,
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+ case ABCConstants.OP_bitxor: {
+ // ECMA 11.10
+ return new DebuggerValue(new Double(ECMA.toInt32(session,
+ eeContext.toValue(lhs.debuggerValue))
+ ^ ECMA.toInt32(session,
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+ case ABCConstants.OP_bitor: {
+ // ECMA 11.10
+ return new DebuggerValue(new Double(ECMA.toInt32(session,
+ eeContext.toValue(lhs.debuggerValue))
+ | ECMA.toInt32(session,
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+ /*
+ * ASC3 reduce_logicalAndExpr & reduce_logicalOrExpr sepearate reducers
+ * case Tokens.LOGICALAND_TOKEN: { // ECMA 11.11
+ * flash.tools.debugger.Value result =
+ * eeContext.toValue(lhs.debuggerValue); if (ECMA.toBoolean(result)) {
+ * rhs = (DebuggerValue) node.rhs.evaluate(cx, this); result =
+ * eeContext.toValue(rhs.debuggerValue); } return new
+ * DebuggerValue(result); } case Tokens.LOGICALOR_TOKEN: { // ECMA 11.11
+ * flash.tools.debugger.Value result =
+ * eeContext.toValue(lhs.debuggerValue); if (!ECMA.toBoolean(result)) {
+ * rhs = (DebuggerValue) node.rhs.evaluate(cx, this); result =
+ * eeContext.toValue(rhs.debuggerValue); } return new
+ * DebuggerValue(result); }
+ */
+ // case Tokens.EMPTY_TOKEN:
+ // // do nothing, already been folded
+ // return new DebuggerValue(null);
+ default:
+ //cx.internalError(ASTBuilder.getLocalizationManager().getLocalizedTextString("unrecognizedBinaryOperator")); //$NON-NLS-1$
+ return new DebuggerValue(null);
+ }
+ }
+
+ /**
+ * Resolve a dotted name, e.g., foo.bar.baz
+ */
+ Object dottedName(IASNode iNode, String qualifiers, String base_name) {
+ return qualifiers + "." + base_name;
+ }
+
+ /**
+ * Error trap.
+ */
+ public Object error_namespaceAccess(IASNode iNode, IASNode raw_qualifier,
+ Object qualified_name) {
+ return null;
+ }
+
+ /**
+ * Error trap.
+ */
+ public Object error_reduce_Op_AssignId(IASNode iNode, Object non_lvalue,
+ Object rvalue) {
+ return null;
+ }
+
+ /**
+ * @return the double content of a numeric literal.
+ * @param iNode
+ * - the literal node.
+ */
+ Double getDoubleContent(IASNode iNode) {
+ return AS3SemanticUtils.getDoubleContent(iNode, project);
+ }
+
+ /**
+ * @return the double content of a numeric literal.
+ * @param iNode
+ * - the literal node.
+ */
+ Float getFloatContent(IASNode iNode) {
+ return AS3SemanticUtils.getFloatContent(iNode, project);
+ }
+
+ /**
+ * @return the name of an identifier.
+ * @param iNode
+ * - the IIdentifier node.
+ */
+ String getIdentifierContent(IASNode iNode) {
+ return AS3SemanticUtils.getIdentifierContent(iNode);
+ }
+
+ /**
+ * @return the int content of a numeric literal.
+ * @param iNode
+ * - the literal node.
+ */
+ Integer getIntegerContent(IASNode iNode) {
+ return AS3SemanticUtils.getIntegerContent(iNode, project);
+ }
+
+ /**
+ * @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 the string content of a literal.
+ * @param iNode
+ * - the literal node.
+ */
+ String getStringLiteralContent(IASNode iNode) {
+ return AS3SemanticUtils.getStringLiteralContent(iNode);
+ }
+
+ /**
+ * @return the uint content of a numeric literal.
+ * @param iNode
+ * - the literal node.
+ */
+ Long getUintContent(IASNode iNode) {
+ return AS3SemanticUtils.getUintContent(iNode, project);
+ }
+
+ /*
+ * *******************************
+ * ** Cost/Decision Functions ** *******************************
+ */
+
+ public int isIntLiteral(IASNode iNode) {
+ if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) {
+ INumericValue numericVal = ((NumericLiteralNode) iNode)
+ .getNumericValue(project);
+
+ if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.INT) {
+ return 1;
+ }
+ }
+ return Integer.MAX_VALUE;
+ }
+
+ public int isUintLiteral(IASNode iNode) {
+ if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) {
+ INumericValue numericVal = ((NumericLiteralNode) iNode)
+ .getNumericValue(project);
+
+ if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.UINT) {
+ return 1;
+ }
+ }
+ return Integer.MAX_VALUE;
+ }
+
+ public int isDoubleLiteral(IASNode iNode) {
+ if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) {
+ return 2;
+ }
+ return Integer.MAX_VALUE;
+ }
+
+ public int isFloatLiteral(IASNode iNode) {
+ if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) {
+ INumericValue numericVal = ((NumericLiteralNode) iNode)
+ .getNumericValue(project);
+
+ if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.FLOAT) {
+ return 1;
+ }
+ return Integer.MAX_VALUE;
+ }
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Explore a MemberAccessNode and decide if its stem is a reference to a
+ * package. This method will always return a result greater than what
+ * isPackageName will return, as package name must "win" over dotted name.
+ */
+ 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.
+ * This method will always return a result less than what isDottedName will
+ * return, as package name must "win" over dotted name.
+ */
+ 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;
+ }
+
+ /**
+ * 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) AS3SemanticUtils
+ .getNthChild(iNode, 0);
+ IDefinition def = qualifier.resolve(project);
+
+ int result = def instanceof NamespaceDefinition ? 1 : Integer.MAX_VALUE;
+ return result;
+ }
+
+ /**
+ * @return a feasible cost if a node has a compile-time constant defintion.
+ */
+ int isCompileTimeConstant(IASNode iNode) {
+ if (AS3SemanticUtils.transformNameToConstantValue(iNode, project) != null)
+ return 1;
+ else
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * @return a feasible cost if a node has a compile-time constant defintion.
+ */
+ int isCompileTimeConstantFunction(IASNode iNode) {
+ if (AS3SemanticUtils.isConstantFunction(project, iNode))
+ return 1;
+ else
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * @return a feasible cost if the parameterized type's base and parameter
+ * types are compile-time constants, ERROR_TRAP if not.
+ */
+ int parameterTypeIsConstant(IASNode iNode) {
+ return Math.max(isKnownType(AS3SemanticUtils.getNthChild(iNode, 0)),
+ isKnownType(AS3SemanticUtils.getNthChild(iNode, 1)));
+ }
+
+ /**
+ * @return a feasible cost if the given node is a known type, ERROR_TRAP
+ * otherwise.
+ */
+ int isKnownType(IASNode iNode) {
+ boolean isConstant = false;
+ if (iNode instanceof IExpressionNode) {
+ isConstant = ((IExpressionNode) iNode).resolve(project) instanceof ITypeDefinition;
+ }
+
+ return isConstant ? 1 : ERROR_TRAP;
+ }
+
+ /**
+ * Reduce a function call to a constant value. This is only possible for a
+ * limited set of function calls, and you should call
+ * isCompileTimeConstantFunction first to make sure this is possible.
+ *
+ * @param iNode
+ * the IFunctionCallNode
+ * @param method
+ * the Object of the method to call
+ * @param constant_args
+ * the constant_values used as arguments to the function call
+ * @return A constant value that that would be the result of calling the
+ * function at runtime with the specified arguments
+ */
+ public Object transform_constant_function_to_value(IASNode iNode,
+ Object method, Vector<Object> constant_args) {
+ return null;
+ }
+
+ /**
+ * @return a feasible cost if the node is a BinaryExpression, and the type
+ * of the left or right side of the expressions resolves to "float"
+ */
+ int isFloatBinOp(IASNode iNode) {
+ return 0;
+ }
+
+ /**
+ * @return a feasible cost (1) if the node is for 'new Array()'
+ */
+ int isEmptyArrayConstructor(IASNode iNode) {
+ IIdentifierNode identifierNode = (IIdentifierNode) AS3SemanticUtils
+ .getNthChild(iNode, 1);
+ if (identifierNode.resolve(project) == project
+ .getBuiltinType(IASLanguageConstants.BuiltinType.ARRAY))
+ return 1;
+
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * @return a feasible cost (1) if the node is for 'new Object()'
+ */
+ int isEmptyObjectConstructor(IASNode iNode) {
+ IIdentifierNode identifierNode = (IIdentifierNode) AS3SemanticUtils
+ .getNthChild(iNode, 1);
+ if (identifierNode.resolve(project) == project
+ .getBuiltinType(IASLanguageConstants.BuiltinType.OBJECT))
+ return 1;
+
+ return Integer.MAX_VALUE;
+ }
+
+ /*
+ * *************************
+ * ** Reduction actions ** *************************
+ */
+
+ public Object reduce_arrayIndexExpr(IASNode iNode, Object stem,
+ boolean is_super, Object index) {
+ return reduce_memberAccessExpr(iNode, stem, index, -1);
+ }
+
+ public Object reduce_arrayLiteral(IASNode iNode, Vector<Object> elements) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_assignToBracketExpr_to_expression(IASNode iNode,
+ Object stem, Object index, Object r, boolean is_super) {
+ Context eeContext = contextStack.scope();
+ Context newContext = eeContext
+ .createContext(((DebuggerValue) stem).debuggerValue);
+ contextStack.pushScope(newContext);
+ try {
+ return reduce_assignToNameExpr_to_expression(iNode, index, r);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_assignToMemberExpr_to_expression(IASNode iNode,
+ Object stem, Object member, Object r) {
+ Context eeContext = contextStack.scope();
+ Context newContext = eeContext
+ .createContext(((DebuggerValue) stem).debuggerValue);
+ contextStack.pushScope(newContext);
+ try {
+ return reduce_assignToNameExpr_to_expression(iNode, member, r);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_assignToDescendantsExpr(IASNode iNode, Object stem,
+ Object member, Object r, boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_assignToNameExpr_to_expression(IASNode iNode,
+ Object lvalue, Object r) {
+
+ // ASC : Refer : evaluate(macromedia.asc.util.Context cx,
+ // SetExpressionNode node)
+ Context eeContext = contextStack.scope();
+ DebuggerValue lhs = (DebuggerValue) lvalue;
+ Object variableToAssignTo;
+ // if (node.getMode() == Tokens.LEFTBRACKET_TOKEN || node.getMode() ==
+ // Tokens.EMPTY_TOKEN)
+ {
+ variableToAssignTo = ECMA.toString(eeContext.getSession(),
+ eeContext.toValue(lhs.debuggerValue));
+ }
+ // else
+ // {
+ // variableToAssignTo = rhs.debuggerValue;
+ // }
+
+ DebuggerValue newValue = (DebuggerValue) r;
+
+ try {
+ eeContext.assign(variableToAssignTo,
+ eeContext.toValue(newValue.debuggerValue));
+ } catch (NoSuchVariableException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ return newValue;
+ }
+
+ // Not supported :: //throw error
+ public Object reduce_assignToQualifiedMemberExpr(IASNode iNode,
+ Object stem, Object qualifier, Object member, Object rhs,
+ boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ // Not supported :: //throw error
+ public Object reduce_assignToQualifiedRuntimeMemberExpr(IASNode iNode,
+ Object stem, Object qualifier, Object runtime_member_selector,
+ Object rhs, boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ // Not supported :: //throw error
+ public Object reduce_assignToQualifiedAttributeExpr(IASNode iNode,
+ Object stem, Object qualifier, Object member, Object rhs,
+ boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_assignToRuntimeNameExpr(IASNode iNode, Object lval,
+ Object r, final boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_assignToUnqualifiedRuntimeAttributeExpr(IASNode iNode,
+ Object stem, Object rt_attr, Object rhs, boolean need_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$;
+ }
+
+ public Object reduce_attributeName(IASNode iNode, Object attr_name) {
+ return new DebuggerValue("@"
+ + ((DebuggerValue) attr_name).debuggerValue);
+ }
+
+ public Boolean reduce_booleanLiteral(IASNode iNode) {
+ return AS3SemanticUtils.getBooleanContent(iNode);
+ }
+
+ public String reduce_by_concatenation(IASNode iNode, String first,
+ String second) {
+ return first + "." + second;
+ }
+
+ public Object reduce_commaExpr(IASNode iNode, Object payload_expr,
+ Vector<Object> exprs) {
+ Object result = null;
+ return result;
+ }
+
+ /**
+ * Reduce expression like:<br>
+ * {@code delete o[p]}
+ *
+ * @param iNode
+ * Tree node for the {@code delete} statement.
+ * @param stem
+ * Instructions for creating a {@code DynamicAccessNode}.
+ * @param index
+ * Instructions for initializing the index expression.
+ * @return Instructions for executing a {@code delete} statement.
+ */
+ public Object reduce_deleteBracketExpr(IASNode iNode, Object stem,
+ Object index) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ /**
+ * Reduce E4X expression like:<br>
+ * {@code delete x.@[foo]}
+ *
+ * @param iNode
+ * Tree node for the {@code delete} statement.
+ * @param stem
+ * Instructions for creating a {@code MemberAccessExpressionNode}
+ * .
+ * @param index
+ * Instructions for initializing the array index expression.
+ * @return Instructions for executing a {@code delete} statement.
+ */
+ public Object reduce_deleteAtBracketExpr(IASNode iNode, Object stem,
+ Object index) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_deleteDescendantsExpr(IASNode iNode, Object stem,
+ Object field) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_deleteExprExprExpr(IASNode iNode, Object expr) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_deleteMemberExpr(IASNode iNode, Object stem,
+ Object field) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_deleteRuntimeNameExpr(IASNode iNode, Object stem,
+ Object rt_name) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_deleteNameExpr(IASNode iNode, Object n) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$
+ }
+
+ public Object reduce_e4xFilter(IASNode iNode, Object stem, Object filter) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_embed(IASNode iNode) {
+ Object result = null;
+ return result;
+ }
+
+ /**
+ * Reduce expression like:<br>
+ * {@code a[i]()}
+ *
+ * @param iNode
+ * Tree node for the function call.
+ * @param stem
+ * Instructions for creating a {@code DynamicAccessNode}.
+ * @param index
+ * Instructions for initializing the index expression.
+ * @return Instructions for executing a {@code function call} statement.
+ */
+ public Object reduce_functionAsBracketExpr(IASNode iNode, Object stem,
+ Object index, Vector<Object> args) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_functionAsMemberExpr(IASNode iNode, Object stem,
+ Object method_name, Vector<Object> args) {
+ try {
+ Context context = contextStack.scope();
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ return reduce_functionCall_common(iNode, method_name, args, true,
+ false);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_functionAsRandomExpr(IASNode iNode,
+ Object random_expr, Vector<Object> args) {
+ return reduce_functionCall_common(iNode, random_expr, args, true, false);
+ }
+
+ public Object reduce_functionCallExpr_to_expression(IASNode iNode,
+ Object method_name, Vector<Object> args) {
+ return reduce_functionCall_common(iNode, method_name, args, true, false);
+ }
+
+ private Object reduce_functionCall_common(IASNode iNode,
+ Object method_name, Vector<Object> args, boolean need_result,
+ boolean isConstructor) {
+
+ Context context = contextStack.scope();
+ DebuggerValue func = (DebuggerValue) method_name;
+ try {
+ Object[] argValues = new Object[args.size()];
+ for (int i = 0; i < args.size(); i++) {
+ DebuggerValue dv = (DebuggerValue) args.get(i);
+ argValues[i] = dv.debuggerValue;
+ }
+ return new DebuggerValue(callFunction(context, isConstructor,
+ func.debuggerValue, argValues));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+
+ public Object reduce_functionCallOfSuperclassMethod_to_expression(
+ IASNode iNode, Object stem, Object method_name, Vector<Object> args) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("super")); //$NON-NLS-1$
+ }
+
+ public Object reduce_logicalAndExpr(IASNode iNode, Object l, Object r) {
+ // REFER : ASC : public Value evaluate(macromedia.asc.util.Context cx,
+ // BinaryExpressionNode node)
+ // ECMA 11.11
+ Context eeContext = contextStack.scope();
+ DebuggerValue lhs = (DebuggerValue) l;
+ flash.tools.debugger.Value result = eeContext
+ .toValue(lhs.debuggerValue);
+
+ if (ECMA.toBoolean(result)) {
+ DebuggerValue rhs = null;
+ if (r instanceof DebuggerValue) {
+ rhs = (DebuggerValue) r;
+ } else {
+ rhs = ((UnEvaluatedDebugExpression) r).evaluate(eeContext);
+ }
+
+ result = eeContext.toValue(rhs.debuggerValue);
+ }
+ return new DebuggerValue(result);
+ }
+
+ public Object reduce_logicalNotExpr(IASNode iNode, Object expr) {
+ Context eeContext = contextStack.scope();
+ DebuggerValue arg = (DebuggerValue) expr;
+ // ECMA 11.4.9
+ return new DebuggerValue(new Boolean(!ECMA.toBoolean(eeContext
+ .toValue(arg.debuggerValue))));
+ }
+
+ public Object reduce_logicalOrExpr(IASNode iNode, Object l, Object r) {
+ // REFER : ASC : public Value evaluate(macromedia.asc.util.Context cx,
+ // BinaryExpressionNode node)
+ // ECMA 11.11
+ Context eeContext = contextStack.scope();
+ DebuggerValue lhs = (DebuggerValue) l;
+ flash.tools.debugger.Value result = eeContext
+ .toValue(lhs.debuggerValue);
+
+ if (!ECMA.toBoolean(result)) {
+ DebuggerValue rhs = null;
+ if (rhs instanceof DebuggerValue) {
+ rhs = (DebuggerValue) r;
+ } else {
+ rhs = ((UnEvaluatedDebugExpression) r).evaluate(eeContext);
+ }
+ result = eeContext.toValue(rhs.debuggerValue);
+ }
+ return new DebuggerValue(result);
+ }
+
+ /**
+ * reduce a MemberAccessExpression. This example just concats the stem and
+ * member together
+ */
+ public Object reduce_memberAccessExpr(IASNode iNode, Object stem,
+ Object member, int opcode) {
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context context = contextStack.scope();
+ boolean pushedScope = false;
+ if (lhs != null) {
+ flash.tools.debugger.Value lhsValue = context
+ .toValue(lhs.debuggerValue);
+ if (ECMA.equals(context.getSession(), lhsValue,
+ context.toValue(null)))
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "nullPointerException")); //$NON-NLS-1$
+
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ pushedScope = true;
+ }
+
+ try {
+ DebuggerValue rhs = (DebuggerValue) transform_name_to_expression(
+ iNode, member);
+
+ return rhs;// node.selector.evaluate(cx, this);
+ } finally {
+ if (pushedScope)
+ contextStack.popScope();
+ }
+ // return stem + "." + member;
+ }
+
+ public Object reduce_qualifiedMemberAccessExpr(IASNode iNode, Object stem,
+ Object qualifier, Object member, int opcode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_qualifiedAttributeRuntimeMemberExpr(IASNode iNode,
+ Object stem, Object qualifier, Object runtime_member_selector,
+ int opcode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_qualifiedMemberRuntimeNameExpr(IASNode iNode,
+ Object stem, Object qualifier, Object runtime_member_selector) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$;
+ }
+
+ public Object reduce_qualifiedAttributeExpr(IASNode iNode, Object stem,
+ Object qualifier, Object member, int opcode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_unqualifiedAttributeExpr(IASNode iNode, Object stem,
+ Object rt_attr, int opcode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$ }
+ }
+
+ /**
+ * Reduce runtime attribute expression, such as {@code @[exp]}.
+ *
+ * @param iNode
+ * Node for {@code @[...]}. It is a
+ * {@code ArrayIndexExpressionID(Op_AtID, ...)}.
+ * @param rt_attr
+ * Instructions generated for the runtime name expression.
+ * @return Instructions to get the value of an attribute described with a
+ * runtime name.
+ */
+ public Object reduce_runtimeAttributeExp(IASNode iNode, Object rt_attr) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceAccess(IASNode iNode, IASNode qualifier,
+ Object qualified_name) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceAsName_to_expression(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceAsName_to_multinameL(IASNode iNode,
+ final boolean is_attribute) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceAsName_to_name(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceMultinameL(IASNode iNode,
+ IASNode qualifier_node, Object expr) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceRTQName(IASNode iNode, Object qualifier,
+ Object qualified_name) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_namespaceRTQNameL(IASNode iNode, Object qualifier,
+ Object expr) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_neqExpr(IASNode iNode, Object l, Object r) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_nameToTypeName(Object name, boolean check_name) {
+ return name;
+ }
+
+ public Object reduce_newMemberProperty(IASNode iNode, Object stem,
+ Object member, Vector<Object> args) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_newAsRandomExpr(IASNode iNode, Object random_expr,
+ Vector<Object> args) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_newEmptyArray(IASNode iNode) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_newEmptyObject(IASNode iNode) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_newExpr(IASNode iNode, Object class_Object,
+ Vector<Object> args) {
+
+ return reduce_functionCall_common(iNode, class_Object, args, true, true);
+ }
+
+ public Object reduce_newVectorLiteral(IASNode iNode, Object literal) {
+ return literal;
+ }
+
+ public Object reduce_nilExpr_to_expression(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_nullLiteral_to_constant_value(IASNode iNode) {
+ return new DebuggerValue(null);
+ }
+
+ public Object reduce_nullLiteral_to_object_literal(IASNode iNode) {
+ return new DebuggerValue(null);
+ }
+
+ public Object reduce_objectLiteral(IASNode iNode, Vector<Object> elements) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_objectLiteralElement(IASNode iNode, Object id,
+ Object value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_parameterizedTypeName(IASNode iNode, Object base,
+ Object param) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_parameterizedTypeExpression(IASNode iNode,
+ Object base, Object param) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_postDecBracketExpr(IASNode iNode, Object stem,
+ Object index, boolean need_result) {
+
+ return reduce_postDecMemberExpr(iNode, stem, index, need_result);
+ }
+
+ public Object reduce_postDecMemberExpr(IASNode iNode, Object stem,
+ Object field, boolean need_result) {
+ try {
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context context = contextStack.scope();
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ return reduce_prePostIncDecExpr(iNode, field, true, false);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_postDecNameExpr(IASNode iNode, Object unary,
+ boolean need_result) {
+ return reduce_prePostIncDecExpr(iNode, unary, true, false);
+ }
+
+ public Object reduce_postIncBracketExpr(IASNode iNode, Object stem,
+ Object index, boolean need_result) {
+ return reduce_postIncMemberExpr(iNode, stem, index, need_result);
+ }
+
+ public Object reduce_postIncMemberExpr(IASNode iNode, Object stem,
+ Object field, boolean need_result) {
+ try {
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context context = contextStack.scope();
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ return reduce_prePostIncDecExpr(iNode, field, true, true);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_postIncNameExpr(IASNode iNode, Object unary,
+ boolean need_result) {
+ return reduce_prePostIncDecExpr(iNode, unary, true, true);
+ }
+
+ public Object reduce_preDecBracketExpr(IASNode iNode, Object stem,
+ Object index, boolean need_result) {
+ return reduce_preDecMemberExpr(iNode, stem, index, need_result);
+ }
+
+ public Object reduce_preDecMemberExpr(IASNode iNode, Object stem,
+ Object field, boolean need_result) {
+ try {
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context context = contextStack.scope();
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ return reduce_prePostIncDecExpr(iNode, field, false, false);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_preDecNameExpr(IASNode iNode, Object unary,
+ boolean need_result) {
+ return reduce_prePostIncDecExpr(iNode, unary, false, false);
+ }
+
+ public Object reduce_preIncBracketExpr(IASNode iNode, Object stem,
+ Object index, boolean need_result) {
+ return reduce_preIncMemberExpr(iNode, stem, index, need_result);
+ }
+
+ public Object reduce_preIncMemberExpr(IASNode iNode, Object stem,
+ Object field, boolean need_result) {
+ try {
+ DebuggerValue lhs = (DebuggerValue) stem;
+ Context context = contextStack.scope();
+ Context newContext = context.createContext(lhs.debuggerValue);
+ contextStack.pushScope(newContext);
+ return reduce_prePostIncDecExpr(iNode, field, false, true);
+ } finally {
+ contextStack.popScope();
+ }
+ }
+
+ public Object reduce_preIncNameExpr(IASNode iNode, Object unary,
+ boolean need_result) {
+ return reduce_prePostIncDecExpr(iNode, unary, false, true);
+ }
+
+ public Object reduce_prePostIncDecExpr(IASNode iNode, Object unary,
+ boolean isPostFix, boolean isIncrement) {
+ try {
+ DebuggerValue expr = (DebuggerValue) unary;
+ Context debuggerContext = contextStack.scope();
+ String memberName = ECMA.toString(debuggerContext.getSession(),
+ debuggerContext.toValue(expr.debuggerValue));
+
+ Object lookupResult = debuggerContext.lookup(memberName);
+
+ double before = ECMA.toNumber(debuggerContext.getSession(),
+ debuggerContext.toValue(lookupResult));
+ double after;
+ if (isIncrement) {
+ after = before + 1;
+ } else {
+ after = before - 1;
+ }
+ debuggerContext.assign(memberName,
+ debuggerContext.toValue(new Double(after)));
+
+ Object result;
+ if (isPostFix) {
+ result = new Double(before);
+ } else {
+ result = new Double(after);
+ }
+
+ return new DebuggerValue(result);
+ } catch (NoSuchVariableException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+
+ public Object reduce_regexLiteral(IASNode iNode) {
+ if (iNode instanceof RegExpLiteralNode) {
+ RegExpLiteralNode rgXNode = (RegExpLiteralNode) iNode;
+ String val = rgXNode.getValue(true);
+ String flags;
+ String re;
+ if (val.length() > 0 && val.charAt(0) == '/') {
+ int lastSlash = val.lastIndexOf('/');
+ re = val.substring(1, lastSlash);
+ flags = val.substring(lastSlash + 1);
+ } else {
+ re = val;
+ flags = ""; //$NON-NLS-1$
+ }
+ Context eeContext = contextStack.scope();
+ try {
+ return new DebuggerValue(callFunction(eeContext, true,
+ "RegExp", new Object[] { re, flags })); //$NON-NLS-1$
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ throw new ExpressionEvaluatorException("Unable to resolve regex");
+ }
+
+ public Object reduce_runtimeNameExpression(IASNode iNode, Object expr) {
+ return expr;
+ }
+
+ /**
+ * Reduce an identifier node This just returns the name of the name
+ * currently.
+ */
+ public Object reduce_simpleName(IASNode iNode) {
+ return new DebuggerValue(((IdentifierNode) iNode).getName());
+ }
+
+ public Object reduce_declName(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_strictneqExpr(IASNode iNode, Object l, Object r) {
+ Context eeContext = contextStack.scope();
+ DebuggerValue lhs = (DebuggerValue) l;
+ DebuggerValue rhs = (DebuggerValue) r;
+ // ECMA 11.9.5
+ return new DebuggerValue(new Boolean(!ECMA.strictEquals(
+ eeContext.toValue(lhs.debuggerValue),
+ eeContext.toValue(rhs.debuggerValue))));
+ }
+
+ public Object reduce_superAccess(IASNode iNode, Object qualified_name) {
+ throw new ExpressionEvaluatorException(keywordNotAllowed("super")); //$NON-NLS-1$
+ }
+
+ public Object reduce_ternaryExpr(IASNode iNode, Object test,
+ Object when_true, Object when_false) {
+ DebuggerValue condition = (DebuggerValue) test;
+ Context eeContext = contextStack.scope();
+ boolean b = ECMA.toBoolean(eeContext.toValue(condition.debuggerValue));
+ if (b) {
+ return when_true;
+ } else {
+ return when_false;
+ }
+ }
+
+ public Object reduce_typedVariableExpression(IASNode iNode,
+ Object var_name, Object var_type) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ // transform_name_to_expression
+ public Object reduce_typeof_expr(IASNode iNode, Object operand) {
+ // ECMA 11.4.3
+ Context eeContext = contextStack.scope();
+ DebuggerValue arg = (DebuggerValue) operand;
+ flash.tools.debugger.Value value = eeContext.toValue(arg.debuggerValue);
+ switch (value.getType()) {
+ case VariableType.UNDEFINED:
+ return new DebuggerValue("undefined"); //$NON-NLS-1$
+ case VariableType.NULL:
+ return new DebuggerValue("object"); //$NON-NLS-1$
+ case VariableType.BOOLEAN:
+ return new DebuggerValue("boolean"); //$NON-NLS-1$
+ case VariableType.NUMBER:
+ return new DebuggerValue("number"); //$NON-NLS-1$
+ case VariableType.STRING:
+ return new DebuggerValue("string"); //$NON-NLS-1$
+ case VariableType.OBJECT: {
+ String typeName = value.getTypeName();
+ int at = typeName.indexOf('@');
+ if (at != -1)
+ typeName = typeName.substring(0, at);
+ if (typeName.equals("XML") || typeName.equals("XMLList")) //$NON-NLS-1$ //$NON-NLS-2$
+ return new DebuggerValue("xml"); //$NON-NLS-1$
+ }
+ default:
+ return new DebuggerValue("object"); //$NON-NLS-1$
+ }
+ }
+
+ public Object reduce_typeof_name(IASNode iNode, Object object) {
+ Object exprObject = transform_name_to_expression(iNode, object);
+ return reduce_typeof_expr(iNode, exprObject);
+ }
+
+ public Object reduce_typeNameParameterAsType(IASNode iNode,
+ Object type_param) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_vectorLiteral(IASNode iNode, Object type_param,
+ Vector<Object> elements) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_voidExpr_to_type_name(IASNode node) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_void0Literal_to_constant_value(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_void0Literal_to_object_literal(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_void0Operator(IASNode iNode) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_voidOperator_to_constant_value(IASNode iNode,
+ Object constant_value) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object reduce_voidOperator_to_expression(IASNode iNode, Object expr) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ /**
+ * The enumeration of states that the code generator finds interesting in an
+ * XML literal. There are states here than the reducer, below, doesn't
+ * consider especially interesting; see computeXMLContentStateMatrix() for
+ * their usage.
+ */
+ @SuppressWarnings("unused")
+ private enum XMLContentState {
+ };
+
+ public Object reduce_XMLContent(IASNode iNode, Vector<Object> exprs) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_XMLList(IASNode iNode, Vector<Object> exprs) {
+ Object result = null;
+ return result;
+ }
+
+ public Object reduce_XMLListConst(IASNode iNode, Vector<String> elements) {
+ Object result = null;
+ return result;
+ }
+
+ /*
+ * ******************************
+ * ** Transformation routines ** ******************************
+ */
+
+ public Object transform_boolean_constant(IASNode iNode,
+ Boolean boolean_constant) {
+ Object result = new DebuggerValue(boolean_constant);
+ return result;
+ }
+
+ public Object transform_double_constant(IASNode iNode,
+ Double double_constant) {
+ Object result = new DebuggerValue(double_constant);
+ return result;
+ }
+
+ public Object transform_numeric_constant(IASNode iNode,
+ Number numeric_constant) {
+ Object result = new DebuggerValue(numeric_constant);
+ ;
+ return result;
+ }
+
+ /**
+ * Transform any constant_value into an expression, so we can constant fold
+ * all sorts of expressions.
+ *
+ * @param iNode
+ * the node that generated the constant_value
+ * @param constant_value
+ * the constant value
+ * @return an Object that contains instructions to push the constant_value
+ * onto the stack.
+ */
+ public Object transform_constant_value(IASNode iNode, Object constant_value) {
+ return constant_value;
+ }
+
+ public Object transform_float_constant(IASNode iNode, Float float_constant) {
+ Object result = new DebuggerValue(float_constant);
+ return result;
+ }
+
+ /**
+ * transform a string_constant to a constant_value - essentially a no-op,
+ * but need a reduction so we can assign it a cost
+ */
+ public Object transform_string_constant_to_constant(IASNode iNode,
+ String string_constant) {
+ return string_constant;
+ }
+
+ /**
+ * transform a boolean_constant to a constant_value - essentially a no-op,
+ * but need a reduction so we can assign it a cost
+ */
+ public Object transform_boolean_constant_to_constant(IASNode iNode,
+ Boolean boolean_constant) {
+ return boolean_constant;
+ }
+
+ /**
+ * transform a numeric_constant to a constant_value - essentially a no-op,
+ * but need a reduction so we can assign it a cost
+ */
+ public Object transform_numeric_constant_to_constant(IASNode iNode,
+ Number numeric_constant) {
+ if (numeric_constant instanceof Float) {
+ return new DebuggerValue(new Double((Float) numeric_constant));
+ } else {
+ return new DebuggerValue(new Double((Double) numeric_constant));
+ }
+
+ }
+
+ public Object transform_expression_to_constant_value(IASNode iNode,
+ Object expression) {
+ // return null - something higher up will report any appropriate
+ // diagnostics.
+ return null;
+ }
+
+ public Object transform_integer_constant(IASNode iNode,
+ Integer integer_constant) {
+ DebuggerValue result = new DebuggerValue(new Double(integer_constant));
+ return result;
+ }
+
+ public Object transform_name_to_constant_value(IASNode iNode) {
+ Object result = null;
+ return result;
+ }
+
+ /**
+ * Transform a name into an expression. In the Code generator this generates
+ * code to get the name and put it on the stack, but for the debugger we
+ * probably just want to return the name.
+ */
+ public Object transform_name_to_expression(IASNode iNode, Object name) {
+
+ // ASC REFER : public Value evaluate(macromedia.asc.util.Context cx,
+ // GetExpressionNode node)
+ DebuggerValue identifier = (DebuggerValue) name;
+ Context eeContext = contextStack.scope();
+ String nameStr = ECMA.toString(eeContext.getSession(),
+ eeContext.toValue(identifier.debuggerValue));
+ flash.tools.debugger.Value contextValue = eeContext.toValue();
+ /**
+ * When contextValue is XMLList and a child node has been accessed, the
+ * context used to resolve variables within [] operator will be a
+ * FlashValueContext while rhs.debuggerValue will be a
+ * FlexLocalVariable. The fix for FB-25660 makes sure
+ * FlashValueContext.toValue(o) checks this case and returns
+ * getFlashVariable().getValue(). We still need to check if this Value
+ * is of type Number so that the if check below behaves correctly.
+ */
+ if (contextValue != null && isXMLType(contextValue)
+ && !isNumericIndex(iNode, identifier.debuggerValue, eeContext)) {
+ String function;
+ Object arg;
+
+ if (nameStr.length() > 0 && nameStr.charAt(0) == '@') {
+ // expression is node.@attr, so we call node.attribute("attr")
+ function = "attribute"; //$NON-NLS-1$
+ arg = nameStr.substring(1);
+ } else {
+ arg = identifier.debuggerValue;
+ boolean isDecendentsOpr = (iNode.getNodeID() == ASTNodeID.Op_DescendantsID);
+ if (isDecendentsOpr) {// node.getMode() ==
+ // Tokens.DOUBLEDOT_TOKEN) {
+ // expression is node..tag, so we call
+ // node.descendants("tag")
+ function = "descendants"; //$NON-NLS-1$
+ } else {
+ // expression is node.tag, so we call node.child("tag")
+ function = "child"; //$NON-NLS-1$
+ }
+ }
+
+ try {
+ return new DebuggerValue(callFunction(eeContext, false,
+ function, new Object[] { arg }));
+ } catch (PlayerDebugException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ } else if (contextValue != null
+ && contextValue.getType() == VariableType.STRING
+ && ((DebuggerValue) name).debuggerValue.equals("length")) //$NON-NLS-1$
+ {
+ String valuestr = contextValue.getValueAsString();
+ return new DebuggerValue(new Double(valuestr.length()));
+ } else {
+ Object lookupResult;
+ try {
+ lookupResult = eeContext.lookup(ECMA.toString(
+ eeContext.getSession(),
+ eeContext.toValue(identifier.debuggerValue)));
+ } catch (NoSuchVariableException e) {
+ throw new ExpressionEvaluatorException(e);
+ } catch (PlayerFaultException e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ return new DebuggerValue(lookupResult);
+ }
+ }
+
+ public Object transform_non_resolving_identifier(IASNode iNode,
+ String non_resolving_identifier) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object transform_runtime_name_expression(IASNode iNode,
+ Object runtime_name_expression) {
+ throw new ExpressionEvaluatorException(ASTBuilder
+ .getLocalizationManager().getLocalizedTextString(
+ "unsupportedExpression")); //$NON-NLS-1$
+ }
+
+ public Object transform_string_constant(IASNode iNode,
+ String string_constant) {
+ return new DebuggerValue(string_constant);
+ }
+
+ public Object transform_uint_constant(IASNode iNode, Long uint_constant) {
+ Object result = new DebuggerValue(uint_constant);
+ return result;
+ }
+
+ /**
+ * Generate a unary operator.
+ *
+ * @param operand
+ * - the operand expression.
+ * @param opcode
+ * - the operator's opcode.
+ * @return an Object that applies the operator to the operand.
+ */
+ Object unaryOp(IASNode iNode, Object operand, int opcode) {
+ // REFER ASC public Value evaluate(macromedia.asc.util.Context cx,
+ // UnaryExpressionNode node)
+ DebuggerValue arg = (DebuggerValue) operand;
+ Context eeContext = contextStack.scope();
+ switch (opcode) {
+ case ABCConstants.OP_returnvoid:
+ // ECMA 11.4.2
+ eeContext.toValue(arg.debuggerValue);
+ return new DebuggerValue(flash.tools.debugger.Value.UNDEFINED);
+ case ABCConstants.OP_typeof: {
+ return reduce_typeof_expr(iNode, operand);
+ }
+ case ABCConstants.OP_convert_d:
+ case ABCConstants.OP_unplus: {
+ // ECMA 11.4.6
+ return new DebuggerValue(new Double(ECMA.toNumber(
+ eeContext.getSession(),
+ eeContext.toValue(arg.debuggerValue))));
+ }
+ case ABCConstants.OP_negate: {
+ // ECMA 11.4.7
+ return new DebuggerValue(new Double(-ECMA.toNumber(
+ eeContext.getSession(),
+ eeContext.toValue(arg.debuggerValue))));
+ }
+ case ABCConstants.OP_bitnot: {
+ // ECMA 11.4.8
+ return new DebuggerValue(new Double(~ECMA.toInt32(
+ eeContext.getSession(),
+ eeContext.toValue(arg.debuggerValue))));
+ }
+ case ABCConstants.OP_not: {
+ // ECMA 11.4.9
+ return new DebuggerValue(new Boolean(!ECMA.toBoolean(eeContext
+ .toValue(arg.debuggerValue))));
+ }
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ Object errorPackageName(IASNode iNode, String qualifiers, String base_name) {
+ return null;
+ }
+
+ // myxml[3] or myxml["3"] is handled differently from myxml["childtag"].
+ // This function takes the part in the brackets, and returns true if it
+ // is a number or a string that can be converted to a number.
+ private boolean isNumericIndex(IASNode node, Object index, Context context) {
+ // if (node.getMode() != Tokens.LEFTBRACKET_TOKEN)
+ if (node.getNodeID() != ASTNodeID.ArrayIndexExpressionID)
+ return false; // it is node.member or node..member or whatever, but
+ // not node[member]
+
+ if (index instanceof Double) {
+ return true; // it is node[number]
+ } else if (index instanceof String) {
+ String s = (String) index;
+
+ if (s.length() == 0) {
+ return false;
+ } else {
+ try {
+ Double.parseDouble(s);
+ return true; // it is node["number"]
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ } else if (context != null && index != null) {
+ // Resolve the Value to see if it is a Number
+ flash.tools.debugger.Value value = context.toValue(index);
+ if (value != null && value.getType() == VariableType.NUMBER) {
+ return true;
+ }
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isXMLType(flash.tools.debugger.Value value) {
+ String typename = value.getTypeName();
+ int at = typename.indexOf('@');
+ if (at != -1)
+ typename = typename.substring(0, at);
+ return typename.equals("XML") || typename.equals("XMLList"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private String keywordNotAllowed(String keyword) {
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("keyword", keyword); //$NON-NLS-1$
+ return ASTBuilder.getLocalizationManager().getLocalizedTextString(
+ "keywordNotAllowed", parameters); //$NON-NLS-1$
+ }
+
+ /**
+ * @param expressionNode
+ * @param expression
+ * @return
+ */
+ public Object reduceLazyExpression(final IASNode expressionNode) {
+
+ UnEvaluatedDebugExpression delayedEvaluator = new UnEvaluatedDebugExpression() {
+
+ @Override
+ public DebuggerValue evaluate(Context eeContext) {
+ try {
+ IExpressionEvaluator evalutor = new DebuggerExpressionEvaluator(
+ project);
+
+ return evalutor.evaluate(eeContext, expressionNode);
+ } catch (Exception e) {
+ throw new ExpressionEvaluatorException(e);
+ }
+ }
+ };
+
+ return delayedEvaluator;
+ }
+
+ private static abstract class UnEvaluatedDebugExpression {
+
+ public abstract DebuggerValue evaluate(Context eeContext);
+ }
+
+}