http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/events/SwfLoadedEvent.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/events/SwfLoadedEvent.java b/debugger/src/main/java/flash/tools/debugger/events/SwfLoadedEvent.java new file mode 100644 index 0000000..0245d93 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/events/SwfLoadedEvent.java @@ -0,0 +1,57 @@ +/* + * 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.events; + +/** + * This event is fired when the player has completed the loading of + * the specified SWF. + */ +public class SwfLoadedEvent extends DebugEvent +{ + /** unique identifier for the SWF */ + public long id; + + /** index of swf in Session.getSwfs() array */ + public int index; + + /** full path name for SWF */ + public String path; + + /** size of the loaded SWF in bytes */ + public long swfSize; + + /** URL of the loaded SWF */ + public String url; + + /** port number related to the URL */ + public long port; + + /** name of host in which the SWF was loaded */ + public String host; + + public SwfLoadedEvent(long sId, int sIndex, String sPath, String sUrl, String sHost, long sPort, long sSwfSize) + { + id = sId; + index = sIndex; + swfSize = sSwfSize; + port = sPort; + path = sPath; + url = sUrl; + host = sHost; + } +}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/events/SwfUnloadedEvent.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/events/SwfUnloadedEvent.java b/debugger/src/main/java/flash/tools/debugger/events/SwfUnloadedEvent.java new file mode 100644 index 0000000..b91e941 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/events/SwfUnloadedEvent.java @@ -0,0 +1,40 @@ +/* + * 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.events; + +/** + * This event is fired when the player has unloaded a swf + */ +public class SwfUnloadedEvent extends DebugEvent +{ + /** unique identifier for the SWF */ + public long id; + + /** index of SWF in Session.getSwfs() array */ + public int index; + + /** full path name for the SWF */ + public String path; + + public SwfUnloadedEvent(long sId, String sPath, int sIndex) + { + id = sId; + index = sIndex; + path = sPath; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/events/TraceEvent.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/events/TraceEvent.java b/debugger/src/main/java/flash/tools/debugger/events/TraceEvent.java new file mode 100644 index 0000000..5f04af8 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/events/TraceEvent.java @@ -0,0 +1,32 @@ +/* + * 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.events; + +/** + * Trace is a special operation by the player that + * allows text strings to be displayed during the + * execution of some ActionScript. + * <p> + * The event provides notification that a trace + * statement was encountered. The info string + * contains the contenxt of the trace message. + */ +public class TraceEvent extends DebugEvent +{ + public TraceEvent(String s) { super(s); } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/expression/AS3DebuggerReducer.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/expression/AS3DebuggerReducer.java b/debugger/src/main/java/flash/tools/debugger/expression/AS3DebuggerReducer.java new file mode 100644 index 0000000..4015b6f --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/expression/AS3DebuggerReducer.java @@ -0,0 +1,2294 @@ +/* + * 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 flash.tools.debugger.*; +import org.apache.flex.abc.ABCConstants; +import org.apache.flex.compiler.constants.IASLanguageConstants; +import org.apache.flex.compiler.definitions.IDefinition; +import org.apache.flex.compiler.definitions.ITypeDefinition; +import org.apache.flex.compiler.internal.definitions.NamespaceDefinition; +import org.apache.flex.compiler.internal.semantics.SemanticUtils; +import org.apache.flex.compiler.internal.tree.as.IdentifierNode; +import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode; +import org.apache.flex.compiler.internal.tree.as.NumericLiteralNode; +import org.apache.flex.compiler.internal.tree.as.RegExpLiteralNode; +import org.apache.flex.compiler.projects.ICompilerProject; +import org.apache.flex.compiler.tree.ASTNodeID; +import org.apache.flex.compiler.tree.as.INumericLiteralNode.INumericValue; +import org.apache.flex.compiler.tree.as.IASNode; +import org.apache.flex.compiler.tree.as.IExpressionNode; +import org.apache.flex.compiler.tree.as.IIdentifierNode; + +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; + + // TODO: IMPORTANT, SET IT TO FALSE BEFORE COMMIT or it won't work in IntelliJ. + private boolean hookallreducercalls = false; + + private void hookforreducercalls(String name) + { + System.out.println(name); + } + + private Object callFunction(Context cx, boolean isConstructor, + Object function, Object[] args) throws PlayerDebugException { + if (hookallreducercalls) + hookforreducercalls("callFunction"); + + 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 ((IsolateController) session).callConstructorWorker(functionName, valueArgs, thisObject.getIsolateId()); + } + else + { + return ((IsolateController) session).callFunctionWorker(thisObject, functionName, valueArgs, thisObject.getIsolateId()); + } + } + + Object compoundBinaryAssignmentBracketExpr(IASNode iNode, Object stem, + Object index, Object r, int opcode) { + if (hookallreducercalls) + hookforreducercalls("compoundBinaryAssignmentBracketExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("compoundBinaryAssignmentMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("compoundBinaryAssignmentNameExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("binaryOp"); + // 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) { + if (hookallreducercalls) + hookforreducercalls("dottedName"); + return qualifiers + "." + base_name; + } + + /** + * Error trap. + */ + public Object error_namespaceAccess(IASNode iNode, IASNode raw_qualifier, + Object qualified_name) { + if (hookallreducercalls) + hookforreducercalls("error_namespaceAccess"); + return null; + } + + /** + * Error trap. + */ + public Object error_reduce_Op_AssignId(IASNode iNode, Object non_lvalue, + Object rvalue) { + if (hookallreducercalls) + hookforreducercalls("error_reduce_Op_AssignId"); + return null; + } + + /** + * @return the double content of a numeric literal. + * @param iNode + * - the literal node. + */ + Double getDoubleContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getDoubleContent"); + return SemanticUtils.getDoubleContent(iNode); + } + + /** + * @return the double content of a numeric literal. + * @param iNode + * - the literal node. + */ + Float getFloatContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getFloatContent"); + //return SemanticUtils.getFloatContent(iNode); + return null; + } + + /** + * @return the name of an identifier. + * @param iNode + * - the IIdentifier node. + */ + String getIdentifierContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getIdentifierContent"); + return SemanticUtils.getIdentifierContent(iNode); + } + + /** + * @return the int content of a numeric literal. + * @param iNode + * - the literal node. + */ + Integer getIntegerContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getIntegerContent"); + return SemanticUtils.getIntegerContent(iNode); + } + + /** + * @return always zero. + * @param iNode + * - the literal node. + */ + Integer getIntegerZeroContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getIntegerZeroContent"); + return 0; + } + + /** + * @return always zero. + * @param iNode + * - the literal node. + */ + Long getIntegerZeroContentAsLong(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getIntegerZeroContentAsLong"); + return 0L; + } + + /** + * @return the string content of a literal. + * @param iNode + * - the literal node. + */ + String getStringLiteralContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getStringLiteralContent"); + return SemanticUtils.getStringLiteralContent(iNode); + } + + /** + * @return the uint content of a numeric literal. + * @param iNode + * - the literal node. + */ + Long getUintContent(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("getUintContent"); + return SemanticUtils.getUintContent(iNode); + } + + /* + * ******************************* + * ** Cost/Decision Functions ** ******************************* + */ + + public int isIntLiteral(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("isIntLiteral"); + if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) { + INumericValue numericVal = ((NumericLiteralNode) iNode) + .getNumericValue(); + + if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.INT) { + return 1; + } + } + return Integer.MAX_VALUE; + } + + public int isUintLiteral(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("isUintLiteral"); + if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) { + INumericValue numericVal = ((NumericLiteralNode) iNode) + .getNumericValue(); + + if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.UINT) { + return 1; + } + } + return Integer.MAX_VALUE; + } + + public int isDoubleLiteral(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("isDoubleLiteral"); + if (iNode.getNodeID() == ASTNodeID.LiteralDoubleID) { + return 2; + } + return Integer.MAX_VALUE; + } + + /* + public int isFloatLiteral(IASNode iNode) { + if (iNode.getNodeID() == ASTNodeID.LiteralNumberID) { + INumericValue numericVal = ((NumericLiteralNode) iNode) + .getNumericValue(); + + if (numericVal.getAssumedType() == IASLanguageConstants.BuiltinType.NUMBER) { + 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) { + if (hookallreducercalls) + hookforreducercalls("isDottedName"); + 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) { + if (hookallreducercalls) + hookforreducercalls("isPackageName"); + 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) { + if (hookallreducercalls) + hookforreducercalls("qualifierIsCompileTimeConstant"); + IdentifierNode qualifier = (IdentifierNode) SemanticUtils + .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 (hookallreducercalls) + hookforreducercalls("isCompileTimeConstant"); + if (SemanticUtils.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 (hookallreducercalls) + hookforreducercalls("isCompileTimeConstantFunction"); + IDefinition def = ((IdentifierNode)iNode).resolve(project); + if (SemanticUtils.isConstDefinition(def)) + 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) { + if (hookallreducercalls) + hookforreducercalls("parameterTypeIsConstant"); + return Math.max(isKnownType(SemanticUtils.getNthChild(iNode, 0)), + isKnownType(SemanticUtils.getNthChild(iNode, 1))); + } + + /** + * @return a feasible cost if the given node is a known type, ERROR_TRAP + * otherwise. + */ + int isKnownType(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("isKnownType"); + 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) { + if (hookallreducercalls) + hookforreducercalls("transform_constant_function_to_value"); + 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) { + if (hookallreducercalls) + hookforreducercalls("isFloatBinOp"); + return 0; + } + + /** + * @return a feasible cost (1) if the node is for 'new Array()' + */ + int isEmptyArrayConstructor(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("isEmptyArrayConstructor"); + IIdentifierNode identifierNode = (IIdentifierNode) SemanticUtils + .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) { + if (hookallreducercalls) + hookforreducercalls("isEmptyObjectConstructor"); + IIdentifierNode identifierNode = (IIdentifierNode) SemanticUtils + .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) { + if (hookallreducercalls) + hookforreducercalls("reduce_arrayIndexExpr"); + return reduce_memberAccessExpr(iNode, stem, index, -1); + } + + public Object reduce_arrayLiteral(IASNode iNode, Vector<Object> elements) { + if (hookallreducercalls) + hookforreducercalls("reduce_arrayLiteral"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToBracketExpr_to_expression"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToMemberExpr_to_expression"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToDescendantsExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_assignToNameExpr_to_expression(IASNode iNode, + Object lvalue, Object r) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToNameExpr_to_expression"); + + // 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToQualifiedMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToQualifiedRuntimeMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToQualifiedAttributeExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_assignToRuntimeNameExpr(IASNode iNode, Object lval, + Object r, final boolean need_value) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToRuntimeNameExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_assignToUnqualifiedRuntimeAttributeExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$; + } + + public Object reduce_attributeName(IASNode iNode, Object attr_name) { + if (hookallreducercalls) + hookforreducercalls("reduce_attributeName"); + return new DebuggerValue("@" + + ((DebuggerValue) attr_name).debuggerValue); + } + + public Boolean reduce_booleanLiteral(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_booleanLiteral"); + return SemanticUtils.getBooleanContent(iNode); + } + + public String reduce_by_concatenation(IASNode iNode, String first, + String second) { + if (hookallreducercalls) + hookforreducercalls("reduce_by_concatenation"); + return first + "." + second; + } + + public Object reduce_commaExpr(IASNode iNode, Object payload_expr, + Vector<Object> exprs) { + if (hookallreducercalls) + hookforreducercalls("reduce_commaExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteBracketExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteAtBracketExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_deleteDescendantsExpr(IASNode iNode, Object stem, + Object field) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteDescendantsExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_deleteExprExprExpr(IASNode iNode, Object expr) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteExprExprExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_deleteMemberExpr(IASNode iNode, Object stem, + Object field) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteMemberExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_deleteRuntimeNameExpr(IASNode iNode, Object stem, + Object rt_name) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteRuntimeNameExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_deleteNameExpr(IASNode iNode, Object n) { + if (hookallreducercalls) + hookforreducercalls("reduce_deleteNameExpr"); + throw new ExpressionEvaluatorException(keywordNotAllowed("delete")); //$NON-NLS-1$ + } + + public Object reduce_e4xFilter(IASNode iNode, Object stem, Object filter) { + if (hookallreducercalls) + hookforreducercalls("reduce_e4xFilter"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_embed(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_embed"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionAsBracketExpr"); + Object result = null; + return result; + } + + public Object reduce_functionAsMemberExpr(IASNode iNode, Object stem, + Object method_name, Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionAsMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionAsRandomExpr"); + return reduce_functionCall_common(iNode, random_expr, args, true, false); + } + + public Object reduce_functionCallExpr_to_expression(IASNode iNode, + Object method_name, Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionCallExpr_to_expression"); + return reduce_functionCall_common(iNode, method_name, args, true, false); + } + + public Object reduce_functionCallSpecial_to_expression(IASNode iNode, + Object method_name, Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionCallSpecial_to_expression"); + IdentifierNode id = (IdentifierNode)method_name; + + Context context = contextStack.scope(); + try { + Object[] argValues = new Object[1]; + for (int i = 0; i < args.size(); i++) { + DebuggerValue dv = (DebuggerValue) args.get(i); + argValues[i] = dv.debuggerValue; + } + return new DebuggerValue(callFunction(context, false, + id.getName(), argValues)); + } catch (PlayerDebugException e) { + throw new ExpressionEvaluatorException(e); + } + } + + private Object reduce_functionCall_common(IASNode iNode, + Object method_name, Vector<Object> args, boolean need_result, + boolean isConstructor) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionCall_common"); + + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_functionCallOfSuperclassMethod_to_expression"); + 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 + if (hookallreducercalls) + hookforreducercalls("reduce_logicalAndExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_logicalNotExpr"); + 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 + if (hookallreducercalls) + hookforreducercalls("reduce_logicalOrExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_memberAccessExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_qualifiedMemberAccessExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_qualifiedAttributeRuntimeMemberExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_qualifiedMemberRuntimeNameExpr(IASNode iNode, + Object stem, Object qualifier, Object runtime_member_selector) { + if (hookallreducercalls) + hookforreducercalls("reduce_qualifiedMemberRuntimeNameExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$; + } + + public Object reduce_qualifiedAttributeExpr(IASNode iNode, Object stem, + Object qualifier, Object member, int opcode) { + if (hookallreducercalls) + hookforreducercalls("reduce_qualifiedAttributeExpr"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_unqualifiedAttributeExpr(IASNode iNode, Object stem, + Object rt_attr, int opcode) { + if (hookallreducercalls) + hookforreducercalls("reduce_unqualifiedAttributeExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_runtimeAttributeExp"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceAccess(IASNode iNode, IASNode qualifier, + Object qualified_name) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceAccess"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceAsName_to_expression(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceAsName_to_expression"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceAsName_to_multinameL(IASNode iNode, + final boolean is_attribute) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceAsName_to_multinameL"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceAsName_to_name(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceAsName_to_name"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceMultinameL(IASNode iNode, + IASNode qualifier_node, Object expr) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceMultinameL"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceRTQName(IASNode iNode, Object qualifier, + Object qualified_name) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceRTQName"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_namespaceRTQNameL(IASNode iNode, Object qualifier, + Object expr) { + if (hookallreducercalls) + hookforreducercalls("reduce_namespaceRTQNameL"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_neqExpr(IASNode iNode, Object l, Object r) { + if (hookallreducercalls) + hookforreducercalls("reduce_neqExpr"); + Object result = null; + return result; + } + + public Object reduce_nameToTypeName(Object name, boolean check_name) { + if (hookallreducercalls) + hookforreducercalls("reduce_nameToTypeName"); + return name; + } + + public Object reduce_newMemberProperty(IASNode iNode, Object stem, + Object member, Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_newMemberProperty"); + Object result = null; + return result; + } + + public Object reduce_newAsRandomExpr(IASNode iNode, Object random_expr, + Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_newAsRandomExpr"); + Object result = null; + return result; + } + + public Object reduce_newEmptyArray(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_newEmptyArray"); + Object result = null; + return result; + } + + public Object reduce_newEmptyObject(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_newEmptyObject"); + Object result = null; + return result; + } + + public Object reduce_newExpr(IASNode iNode, Object class_Object, + Vector<Object> args) { + if (hookallreducercalls) + hookforreducercalls("reduce_newExpr"); + + return reduce_functionCall_common(iNode, class_Object, args, true, true); + } + + public Object reduce_newVectorLiteral(IASNode iNode, Object literal) { + if (hookallreducercalls) + hookforreducercalls("reduce_newVectorLiteral"); + return literal; + } + + public Object reduce_nilExpr_to_expression(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_nilExpr_to_expression"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_nullLiteral_to_constant_value(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_nullLiteral_to_constant_value"); + return new DebuggerValue(null); + } + + public Object reduce_nullLiteral_to_object_literal(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_nullLiteral_to_object_literal"); + return new DebuggerValue(null); + } + + public Object reduce_objectLiteral(IASNode iNode, Vector<Object> elements) { + if (hookallreducercalls) + hookforreducercalls("reduce_objectLiteral"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_objectLiteralElement(IASNode iNode, Object id, + Object value) { + if (hookallreducercalls) + hookforreducercalls("reduce_objectLiteralElement"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_parameterizedTypeName(IASNode iNode, Object base, + Object param) { + if (hookallreducercalls) + hookforreducercalls("reduce_parameterizedTypeName"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_parameterizedTypeExpression(IASNode iNode, + Object base, Object param) { + if (hookallreducercalls) + hookforreducercalls("reduce_parameterizedTypeExpression"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_postDecBracketExpr(IASNode iNode, Object stem, + Object index, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_postDecBracketExpr"); + + return reduce_postDecMemberExpr(iNode, stem, index, need_result); + } + + public Object reduce_postDecMemberExpr(IASNode iNode, Object stem, + Object field, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_postDecMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_postDecNameExpr"); + return reduce_prePostIncDecExpr(iNode, unary, true, false); + } + + public Object reduce_postIncBracketExpr(IASNode iNode, Object stem, + Object index, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_postIncBracketExpr"); + return reduce_postIncMemberExpr(iNode, stem, index, need_result); + } + + public Object reduce_postIncMemberExpr(IASNode iNode, Object stem, + Object field, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_postIncMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_postIncNameExpr"); + return reduce_prePostIncDecExpr(iNode, unary, true, true); + } + + public Object reduce_preDecBracketExpr(IASNode iNode, Object stem, + Object index, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_preDecBracketExpr"); + return reduce_preDecMemberExpr(iNode, stem, index, need_result); + } + + public Object reduce_preDecMemberExpr(IASNode iNode, Object stem, + Object field, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_preDecMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_preDecNameExpr"); + return reduce_prePostIncDecExpr(iNode, unary, false, false); + } + + public Object reduce_preIncBracketExpr(IASNode iNode, Object stem, + Object index, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_preIncBracketExpr"); + return reduce_preIncMemberExpr(iNode, stem, index, need_result); + } + + public Object reduce_preIncMemberExpr(IASNode iNode, Object stem, + Object field, boolean need_result) { + if (hookallreducercalls) + hookforreducercalls("reduce_preIncMemberExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_preIncNameExpr"); + return reduce_prePostIncDecExpr(iNode, unary, false, true); + } + + public Object reduce_prePostIncDecExpr(IASNode iNode, Object unary, + boolean isPostFix, boolean isIncrement) { + if (hookallreducercalls) + hookforreducercalls("reduce_prePostIncDecExpr"); + 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 (hookallreducercalls) + hookforreducercalls("reduce_regexLiteral"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_runtimeNameExpression"); + return expr; + } + + /** + * Reduce an identifier node This just returns the name of the name + * currently. + */ + public Object reduce_simpleName(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_simpleName"); + return new DebuggerValue(((IdentifierNode) iNode).getName()); + } + + public Object reduce_declName(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_declName"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_strictneqExpr(IASNode iNode, Object l, Object r) { + if (hookallreducercalls) + hookforreducercalls("reduce_strictneqExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_superAccess"); + throw new ExpressionEvaluatorException(keywordNotAllowed("super")); //$NON-NLS-1$ + } + + public Object reduce_ternaryExpr(IASNode iNode, Object test, + Object when_true, Object when_false) { + if (hookallreducercalls) + hookforreducercalls("reduce_ternaryExpr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_typedVariableExpression"); + 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 + if (hookallreducercalls) + hookforreducercalls("reduce_typeof_expr"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_typeof_name"); + Object exprObject = transform_name_to_expression(iNode, object); + return reduce_typeof_expr(iNode, exprObject); + } + + public Object reduce_typeNameParameterAsType(IASNode iNode, + Object type_param) { + if (hookallreducercalls) + hookforreducercalls("reduce_typeNameParameterAsType"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_vectorLiteral(IASNode iNode, Object type_param, + Vector<Object> elements) { + if (hookallreducercalls) + hookforreducercalls("reduce_vectorLiteral"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_voidExpr_to_type_name(IASNode node) { + if (hookallreducercalls) + hookforreducercalls("reduce_voidExpr_to_type_name"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_void0Literal_to_constant_value(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_void0Literal_to_constant_value"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_void0Literal_to_object_literal(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_void0Literal_to_object_literal"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_void0Operator(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("reduce_void0Operator"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_voidOperator_to_constant_value(IASNode iNode, + Object constant_value) { + if (hookallreducercalls) + hookforreducercalls("reduce_voidOperator_to_constant_value"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object reduce_voidOperator_to_expression(IASNode iNode, Object expr) { + if (hookallreducercalls) + hookforreducercalls("reduce_voidOperator_to_expression"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduce_XMLContent"); + Object result = null; + return result; + } + + public Object reduce_XMLList(IASNode iNode, Vector<Object> exprs) { + if (hookallreducercalls) + hookforreducercalls("reduce_XMLList"); + Object result = null; + return result; + } + + public Object reduce_XMLListConst(IASNode iNode, Vector<String> elements) { + if (hookallreducercalls) + hookforreducercalls("reduce_XMLListConst"); + Object result = null; + return result; + } + + /* + * ****************************** + * ** Transformation routines ** ****************************** + */ + + public Object transform_boolean_constant(IASNode iNode, + Boolean boolean_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_boolean_constant"); + Object result = new DebuggerValue(boolean_constant); + return result; + } + + public Object transform_double_constant(IASNode iNode, + Double double_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_double_constant"); + Object result = new DebuggerValue(double_constant); + return result; + } + + public Object transform_numeric_constant(IASNode iNode, + Number numeric_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_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) { + if (hookallreducercalls) + hookforreducercalls("transform_constant_value"); + return constant_value; + } + + public Object transform_float_constant(IASNode iNode, Float float_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_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) { + if (hookallreducercalls) + hookforreducercalls("transform_string_constant_to_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) { + if (hookallreducercalls) + hookforreducercalls("transform_boolean_constant_to_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 (hookallreducercalls) + hookforreducercalls("transform_numeric_constant_to_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) { + if (hookallreducercalls) + hookforreducercalls("transform_expression_to_constant_value"); + // return null - something higher up will report any appropriate + // diagnostics. + return null; + } + + public Object transform_integer_constant(IASNode iNode, + Integer integer_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_integer_constant"); + DebuggerValue result = new DebuggerValue(new Double(integer_constant)); + return result; + } + + public Object transform_name_to_constant_value(IASNode iNode) { + if (hookallreducercalls) + hookforreducercalls("transform_name_to_constant_value"); + 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) { + if (hookallreducercalls) + hookforreducercalls("transform_name_to_expression"); + + // 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) { + if (hookallreducercalls) + hookforreducercalls("transform_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) { + if (hookallreducercalls) + hookforreducercalls("transform_runtime_name_expression"); + throw new ExpressionEvaluatorException(ASTBuilder + .getLocalizationManager().getLocalizedTextString( + "unsupportedExpression")); //$NON-NLS-1$ + } + + public Object transform_string_constant(IASNode iNode, + String string_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_string_constant"); + return new DebuggerValue(string_constant); + } + + public Object transform_uint_constant(IASNode iNode, Long uint_constant) { + if (hookallreducercalls) + hookforreducercalls("transform_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) + if (hookallreducercalls) + hookforreducercalls("unaryOp"); + 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) { + if (hookallreducercalls) + hookforreducercalls("errorPackageName"); + 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 (hookallreducercalls) + hookforreducercalls("isNumericIndex"); + // 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) { + if (hookallreducercalls) + hookforreducercalls("isXMLType"); + 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) { + if (hookallreducercalls) + hookforreducercalls("keywordNotAllowed"); + 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) { + if (hookallreducercalls) + hookforreducercalls("reduceLazyExpression"); + + 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); + } + +}