/// <summary> /// </summary> /// <param name="static"> /// </param> /// <returns> /// </returns> public CCodeMethodDeclaration CreateInvokeMethod(bool @static = false) { var methodImpl = new MethodImpl { Name = this.invoke.Name, IsVirtual = true, IsOverride = true, ReturnType = this.invoke.ReturnType, ReturnsVoid = this.invoke.ReturnsVoid, Parameters = this.invoke.Parameters, ContainingType = this.GetDelegateType(@static), ReceiverType = this.GetDelegateType(@static) }; // invoke var invokeMethod = new CCodeMethodDeclaration(methodImpl); var operand = @static ? new PointerIndirectionOperator { Operand = new FieldAccess { Field = new FieldImpl { Name = "_memptr" } } } : (Expression) new Access { ReceiverOpt = new FieldAccess { Field = new FieldImpl { Name = "_t", Type = Type } }, Expression = new PointerIndirectionOperator { Operand = new FieldAccess { Field = new FieldImpl { Name = "_memptr" } } } }; var callExpr = new Call { ReceiverOpt = new Parenthesis { Operand = operand, Type = new TypeImpl { } }, Method = new MethodImpl { Name = string.Empty, Parameters = this.invoke.Parameters } }; foreach (var p in this.invoke.Parameters.Select(p => new Parameter { ParameterSymbol = p })) { callExpr.Arguments.Add(p); } // if for multiple delegate var zero = new Literal { Value = ConstantValue.Create(0) }; var invocationCountLocal = new Local { CustomName = "invocationCount", Type = new TypeImpl { SpecialType = SpecialType.System_Int32 } }; var invocationCount = new AssignmentOperator { TypeDeclaration = true, ApplyAutoType = true, Left = invocationCountLocal, Right = new Call { Method = new MethodImpl { Name = "ToInt32", Parameters = ImmutableArray <IParameterSymbol> .Empty }, ReceiverOpt = new FieldAccess { ReceiverOpt = new ThisReference() { Type = new TypeImpl { } }, Field = new FieldImpl { Name = "_invocationCount", Type = new TypeImpl { } }, Type = new TypeImpl { } } } }; var invocationCountStatement = new ExpressionStatement { Expression = invocationCount }; var iLocal = new Local { CustomName = "i", Type = new TypeImpl { SpecialType = SpecialType.System_Int32 } }; var invokeResult = new Local { CustomName = "invokeResult", Type = this.invoke.ReturnType }; // call for 'for' var callExprInstance = new Call { ReceiverOpt = new Cast { Type = Type, CCast = true, Operand = new ArrayAccess { Expression = new Cast { Operand = new FieldAccess { ReceiverOpt = new ThisReference { Type = new TypeImpl { } }, Field = new FieldImpl { Name = "_invocationList", Type = new TypeImpl { } } }, CCast = true, Type = new ArrayTypeImpl { ElementType = new NamedTypeImpl { SpecialType = SpecialType.System_Delegate, IsReferenceType = true } } }, Indices = { iLocal }, Type = new TypeImpl { } } }, Method = new MethodImpl { Name = "Invoke", Parameters = this.invoke.Parameters } }; foreach (var p in this.invoke.Parameters.Select(p => new Parameter { ParameterSymbol = p })) { callExprInstance.Arguments.Add(p); } var block = new Block { Statements = { new ForStatement { InitializationOpt = new AssignmentOperator { ApplyAutoType = true, TypeDeclaration = true, Left = iLocal, Right = zero }, ConditionOpt = new BinaryOperator { Left = iLocal, Right = invocationCountLocal, OperatorKind = BinaryOperatorKind.IntLessThan }, IncrementingOpt = new PrefixUnaryExpression { Value = iLocal, OperatorKind = SyntaxKind.PlusPlusToken }, Statements = new ExpressionStatement { Expression = this.invoke.ReturnsVoid ? (Expression)callExprInstance : (Expression) new AssignmentOperator { Left = invokeResult, Right = callExprInstance } } }, new ReturnStatement { ExpressionOpt = !this.invoke.ReturnsVoid ? invokeResult : null } } }; if (!this.invoke.ReturnsVoid) { block.Statements.Insert(0, new VariableDeclaration { Local = invokeResult }); } var ifInvokeListCountGreaterThen0 = new IfStatement { Condition = new BinaryOperator { Left = invocationCountLocal, Right = zero, OperatorKind = BinaryOperatorKind.IntGreaterThan }, IfStatements = block }; invokeMethod.MethodBodyOpt = new MethodBody(methodImpl) { Statements = { invocationCountStatement, ifInvokeListCountGreaterThen0, this.invoke.ReturnsVoid ? (Statement) new ExpressionStatement { Expression = callExpr } : (Statement) new ReturnStatement { ExpressionOpt = callExpr } } }; return(invokeMethod); }
/// <summary> /// </summary> /// <param name="static"> /// </param> /// <returns> /// </returns> private CCodeMethodDeclaration CreateInvokeMethod(bool @static = false) { var methodImpl = new MethodImpl { Name = this.invoke.Name, IsVirtual = true, IsOverride = true, ReturnType = this.invoke.ReturnType, ReturnsVoid = this.invoke.ReturnsVoid, Parameters = this.invoke.Parameters }; var invokeMethod = new CCodeMethodDeclaration(methodImpl); var operand = @static ? new PointerIndirectionOperator { Operand = new FieldAccess { Field = new FieldImpl { Name = "_memptr" } } } : (Expression) new Access { ReceiverOpt = new FieldAccess { Field = new FieldImpl { Name = "_t", Type = Type } }, Expression = new PointerIndirectionOperator { Operand = new FieldAccess { Field = new FieldImpl { Name = "_memptr" } } } }; var callExpr = new Call { ReceiverOpt = new Parenthesis { Operand = operand, Type = new TypeImpl { } }, Method = new MethodImpl { Name = string.Empty, Parameters = this.invoke.Parameters } }; foreach (var p in this.invoke.Parameters.Select(p => new Parameter { ParameterSymbol = p })) { callExpr.Arguments.Add(p); } var returnStatement = new ReturnStatement { ExpressionOpt = callExpr }; invokeMethod.MethodBodyOpt = new MethodBody(methodImpl) { Statements = { returnStatement } }; return(invokeMethod); }