Example #1
0
        /// <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);
        }