private void VisitChildren(Expr pExpr) { Debug.Assert(pExpr != null); Expr exprRet; switch (pExpr.Kind) { case ExpressionKind.List: // Lists are a special case. We treat a list not as a // binary node but rather as a node with n children. ExprList list = (ExprList)pExpr; while (true) { list.OptionalElement = Visit(list.OptionalElement); Expr nextNode = list.OptionalNextListNode; if (nextNode == null) { return; } if (!(nextNode is ExprList next)) { list.OptionalNextListNode = Visit(nextNode); return; } list = next; } case ExpressionKind.Assignment: exprRet = Visit((pExpr as ExprAssignment).LHS); Debug.Assert(exprRet != null); (pExpr as ExprAssignment).LHS = exprRet; exprRet = Visit((pExpr as ExprAssignment).RHS); Debug.Assert(exprRet != null); (pExpr as ExprAssignment).RHS = exprRet; break; case ExpressionKind.ArrayIndex: exprRet = Visit((pExpr as ExprArrayIndex).Array); Debug.Assert(exprRet != null); (pExpr as ExprArrayIndex).Array = exprRet; exprRet = Visit((pExpr as ExprArrayIndex).Index); Debug.Assert(exprRet != null); (pExpr as ExprArrayIndex).Index = exprRet; break; case ExpressionKind.UnaryOp: case ExpressionKind.True: case ExpressionKind.False: case ExpressionKind.Inc: case ExpressionKind.Dec: case ExpressionKind.LogicalNot: case ExpressionKind.Negate: case ExpressionKind.UnaryPlus: case ExpressionKind.BitwiseNot: case ExpressionKind.Addr: case ExpressionKind.DecimalNegate: case ExpressionKind.DecimalInc: case ExpressionKind.DecimalDec: exprRet = Visit((pExpr as ExprUnaryOp).Child); Debug.Assert(exprRet != null); (pExpr as ExprUnaryOp).Child = exprRet; break; case ExpressionKind.UserLogicalOp: exprRet = Visit((pExpr as ExprUserLogicalOp).TrueFalseCall); Debug.Assert(exprRet != null); (pExpr as ExprUserLogicalOp).TrueFalseCall = exprRet; exprRet = Visit((pExpr as ExprUserLogicalOp).OperatorCall); Debug.Assert(exprRet != null); (pExpr as ExprUserLogicalOp).OperatorCall = exprRet as ExprCall; exprRet = Visit((pExpr as ExprUserLogicalOp).FirstOperandToExamine); Debug.Assert(exprRet != null); (pExpr as ExprUserLogicalOp).FirstOperandToExamine = exprRet; break; case ExpressionKind.TypeOf: break; case ExpressionKind.Cast: exprRet = Visit((pExpr as ExprCast).Argument); Debug.Assert(exprRet != null); (pExpr as ExprCast).Argument = exprRet; break; case ExpressionKind.UserDefinedConversion: exprRet = Visit((pExpr as ExprUserDefinedConversion).UserDefinedCall); Debug.Assert(exprRet != null); (pExpr as ExprUserDefinedConversion).UserDefinedCall = exprRet; break; case ExpressionKind.ZeroInit: break; case ExpressionKind.MemberGroup: // The object expression. NULL for a static invocation. exprRet = Visit((pExpr as ExprMemberGroup).OptionalObject); (pExpr as ExprMemberGroup).OptionalObject = exprRet; break; case ExpressionKind.Call: exprRet = Visit((pExpr as ExprCall).OptionalArguments); (pExpr as ExprCall).OptionalArguments = exprRet; exprRet = Visit((pExpr as ExprCall).MemberGroup); Debug.Assert(exprRet != null); (pExpr as ExprCall).MemberGroup = exprRet as ExprMemberGroup; break; case ExpressionKind.Property: exprRet = Visit((pExpr as ExprProperty).OptionalArguments); (pExpr as ExprProperty).OptionalArguments = exprRet; exprRet = Visit((pExpr as ExprProperty).MemberGroup); Debug.Assert(exprRet != null); (pExpr as ExprProperty).MemberGroup = exprRet as ExprMemberGroup; break; case ExpressionKind.Field: exprRet = Visit((pExpr as ExprField).OptionalObject); (pExpr as ExprField).OptionalObject = exprRet; break; case ExpressionKind.Constant: // Used for when we zeroinit 0 parameter constructors for structs/enums. exprRet = Visit((pExpr as ExprConstant).OptionalConstructorCall); (pExpr as ExprConstant).OptionalConstructorCall = exprRet; break; /************************************************************************************************* * TYPEEXPRs defined: * * The following exprs are used to represent the results of type binding, and are defined as follows: * * TYPEARGUMENTS - This wraps the type arguments for a class. It contains the TypeArray* which is * associated with the AggregateType for the instantiation of the class. * * TYPEORNAMESPACE - This is the base class for this set of Exprs. When binding a type, the result * must be a type or a namespace. This Expr encapsulates that fact. The lhs member is the Expr * tree that was bound to resolve the type or namespace. * * TYPEORNAMESPACEERROR - This is the error class for the type or namespace exprs when we don't know * what to bind it to. * * The following two exprs all have a TYPEORNAMESPACE child, which is their fundamental type: * POINTERTYPE - This wraps the sym for the pointer type. * NULLABLETYPE - This wraps the sym for the nullable type. * * CLASS - This represents an instantiation of a class. * * NSPACE - This represents a namespace, which is the intermediate step when attempting to bind * a qualified name. * * ALIAS - This represents an alias * *************************************************************************************************/ case ExpressionKind.Multi: exprRet = Visit((pExpr as ExprMulti).Left); Debug.Assert(exprRet != null); (pExpr as ExprMulti).Left = exprRet; exprRet = Visit((pExpr as ExprMulti).Operator); Debug.Assert(exprRet != null); (pExpr as ExprMulti).Operator = exprRet; break; case ExpressionKind.Concat: exprRet = Visit((pExpr as ExprConcat).FirstArgument); Debug.Assert(exprRet != null); (pExpr as ExprConcat).FirstArgument = exprRet; exprRet = Visit((pExpr as ExprConcat).SecondArgument); Debug.Assert(exprRet != null); (pExpr as ExprConcat).SecondArgument = exprRet; break; case ExpressionKind.ArrayInit: exprRet = Visit((pExpr as ExprArrayInit).OptionalArguments); (pExpr as ExprArrayInit).OptionalArguments = exprRet; exprRet = Visit((pExpr as ExprArrayInit).OptionalArgumentDimensions); (pExpr as ExprArrayInit).OptionalArgumentDimensions = exprRet; break; case ExpressionKind.Local: case ExpressionKind.Class: case ExpressionKind.MultiGet: case ExpressionKind.Wrap: case ExpressionKind.NoOp: case ExpressionKind.FieldInfo: case ExpressionKind.MethodInfo: break; default: pExpr.AssertIsBin(); exprRet = Visit((pExpr as ExprBinOp).OptionalLeftChild); (pExpr as ExprBinOp).OptionalLeftChild = exprRet; exprRet = Visit((pExpr as ExprBinOp).OptionalRightChild); (pExpr as ExprBinOp).OptionalRightChild = exprRet; break; } }
protected virtual Expr VisitLIST(ExprList pExpr) { return(VisitEXPR(pExpr)); }
private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr) { Debug.Assert(expr != null); PREDEFMETH pdm; switch (expr.Kind) { case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE_USER_DEFINED; break; case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO_USER_DEFINED; break; case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT_USER_DEFINED; break; case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT_USER_DEFINED; break; case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR_USER_DEFINED; break; case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR_USER_DEFINED; break; case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND_USER_DEFINED; break; case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO_USER_DEFINED; break; case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE_USER_DEFINED; break; case ExpressionKind.StringEq: case ExpressionKind.StringNotEq: case ExpressionKind.DelegateEq: case ExpressionKind.DelegateNotEq: case ExpressionKind.Eq: case ExpressionKind.NotEq: case ExpressionKind.GreaterThanOrEqual: case ExpressionKind.GreaterThan: case ExpressionKind.LessThanOrEqual: case ExpressionKind.LessThan: return(GenerateUserDefinedComparisonOperator(expr)); case ExpressionKind.DelegateSubtract: case ExpressionKind.Subtract: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_SUBTRACT_USER_DEFINED; break; case ExpressionKind.DelegateAdd: case ExpressionKind.Add: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED; break; case ExpressionKind.Multiply: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_MULTIPLY_USER_DEFINED; break; default: throw Error.InternalCompilerError(); } Expr p1 = expr.OptionalLeftChild; Expr p2 = expr.OptionalRightChild; Expr udcall = expr.OptionalUserDefinedCall; if (udcall != null) { Debug.Assert(udcall.Kind == ExpressionKind.Call || udcall.Kind == ExpressionKind.UserLogicalOp); if (udcall is ExprCall ascall) { ExprList args = (ExprList)ascall.OptionalArguments; Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List); p1 = args.OptionalElement; p2 = args.OptionalNextListNode; } else { ExprUserLogicalOp userLogOp = udcall as ExprUserLogicalOp; Debug.Assert(userLogOp != null); ExprList args = (ExprList)userLogOp.OperatorCall.OptionalArguments; Debug.Assert(args.OptionalNextListNode.Kind != ExpressionKind.List); p1 = ((ExprWrap)args.OptionalElement).OptionalExpression; p2 = args.OptionalNextListNode; } } p1 = Visit(p1); p2 = Visit(p2); FixLiftedUserDefinedBinaryOperators(expr, ref p1, ref p2); Expr methodInfo = GetExprFactory().CreateMethodInfo(expr.UserDefinedCallMethod); Expr call = GenerateCall(pdm, p1, p2, methodInfo); // Delegate add/subtract generates a call to Combine/Remove, which returns System.Delegate, // not the operand delegate CType. We must cast to the delegate CType. if (expr.Kind == ExpressionKind.DelegateSubtract || expr.Kind == ExpressionKind.DelegateAdd) { Expr pTypeOf = CreateTypeOf(expr.Type); return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, pTypeOf)); } return(call); }