예제 #1
0
        public override Object Visit(CompoundExpression node, Object obj)
        {
            CompoundExpression clonedCompoundExpression = new CompoundExpression(node.Location);

            for (int i = 0; i < node.ExpressionCount; i++)
            {
                clonedCompoundExpression.AddExpression((Expression)node.GetExpressionElement(i).Accept(this, obj));
            }
            return(clonedCompoundExpression);
        }
        private MethodDefinition CreateMethod(string fullMethodIndentificator, string originalMethodIndentificator, MethodDefinition originalMethodDefinition, TypeExpression[] args, BaseCallExpression node)
        {
            if (!specilizedMethods.ContainsKey(fullMethodIndentificator))
            {
                String methodIndentificator     = fullMethodIndentificator.Replace(originalMethodDefinition.FullName, originalMethodDefinition.Identifier);
                List <MethodDefinition> methods = new List <MethodDefinition>();
                foreach (TypeExpression[] listOfArgs in GetTypes(args))
                {
                    String           currentMethodIdentificator = MethodIndentificator(originalMethodDefinition.FullName, listOfArgs);
                    MethodDefinition md;
                    if (currentMethodIdentificator.Equals(originalMethodIndentificator))
                    {
                        md = originalMethodDefinition;
                    }
                    else
                    {
                        md = SpecilizeMethod(currentMethodIdentificator, originalMethodDefinition, listOfArgs);
                    }
                    if (md != null && !methods.Any(m => m.ILTypeExpression.Equals(md.ILTypeExpression)))
                    {
                        methods.Add(md);
                    }
                }

                MethodType originalMethodType = (MethodType)originalMethodDefinition.TypeExpr;
                isCurrentMethodDynamic = IsCurrentMethodDynamic(originalMethodType);
                MethodType newMethodType = new MethodType(originalMethodType.Return);
                Location   location      = originalMethodDefinition.IdentifierExp.Location;
                SingleIdentifierExpression newSingleIdentifierExpression = new SingleIdentifierExpression(methodIndentificator, location);
                Block newBlock = new Block(location);

                IList <InvocationExpression> invocations     = new List <InvocationExpression>();
                IList <CastExpression>       castExpressions = new List <CastExpression>();
                int methodsCount = 0;
                foreach (var methodDefinition in methods)
                {
                    MethodType           methodType         = (MethodType)methodDefinition.TypeExpr;
                    IList <IsExpression> isExpressions      = new List <IsExpression>();
                    CompoundExpression   compoundExpression = new CompoundExpression(location);

                    for (int i = 0; i < methodDefinition.ParametersInfo.Count; i++)
                    {
                        SingleIdentifierExpression identifier = new SingleIdentifierExpression(methodDefinition.ParametersInfo[i].Identifier, location);
                        identifier.IndexOfSSA = 0;
                        if (args[i] is UnionType || (args[i] is TypeVariable && ((TypeVariable)args[i]).Substitution is UnionType))
                        {
                            IsExpression isExpression = new IsExpression(identifier,
                                                                         methodType.GetParameter(i).Freeze().ILType(), location);
                            isExpression.TypeExpr = methodType.GetParameter(i).Freeze();
                            isExpressions.Add(isExpression);

                            CastExpression castExpression = new CastExpression(isExpression.TypeExpr.ILType(),
                                                                               identifier, location);
                            castExpressions.Add(castExpression);
                            castExpression.CastType = isExpression.TypeExpr;
                            compoundExpression.AddExpression(castExpression);
                        }
                        else
                        {
                            compoundExpression.AddExpression(identifier);
                        }
                    }

                    Expression condition = isExpressions[0];
                    if (isExpressions.Count > 1)
                    {
                        for (int i = 1; i < isExpressions.Count; i++)
                        {
                            condition = new LogicalExpression(condition, isExpressions[i], LogicalOperator.And, location);
                        }
                    }

                    InvocationExpression invocationExpression = new InvocationExpression(methodDefinition.IdentifierExp, compoundExpression, location);
                    invocations.Add(invocationExpression);
                    ReturnStatement returnStatement = new ReturnStatement(invocationExpression, location);
                    if (++methodsCount < methods.Count || isCurrentMethodDynamic)
                    {
                        IfElseStatement ifElseStatement = new IfElseStatement(condition, returnStatement, location);
                        newBlock.AddStatement(ifElseStatement);
                    }
                    else if (!isCurrentMethodDynamic)
                    {
                        newBlock.AddStatement(returnStatement);
                    }
                }
                //If there is any dynamic union type then it is necessary invoke the original method
                if (isCurrentMethodDynamic)
                {
                    CompoundExpression compoundExpression = new CompoundExpression(location);
                    foreach (var parameter in originalMethodDefinition.ParametersInfo)
                    {
                        SingleIdentifierExpression identifier = new SingleIdentifierExpression(parameter.Identifier, location);
                        identifier.IndexOfSSA = 0;
                        compoundExpression.AddExpression(identifier);
                    }
                    newBlock.AddStatement(new ReturnStatement(new InvocationExpression(new SingleIdentifierExpression(originalMethodDefinition.Identifier, location), compoundExpression, location), location));
                }

                MethodDefinition newMethodDefinition = new MethodDefinition(newSingleIdentifierExpression, newBlock,
                                                                            originalMethodDefinition.ReturnTypeInfo, originalMethodDefinition.ParametersInfo,
                                                                            originalMethodDefinition.ModifiersInfo, location);

                newMethodDefinition.FullName            = fullMethodIndentificator;
                newMethodType.MemberInfo                = new AccessModifier(originalMethodType.MemberInfo.Modifiers, newSingleIdentifierExpression.Identifier, newMethodType, false);
                newMethodType.MemberInfo.Class          = originalMethodType.MemberInfo.Class;
                newMethodType.MemberInfo.TypeDefinition = originalMethodType.MemberInfo.TypeDefinition;

                for (int i = 0; i < originalMethodType.ParameterListCount; i++)
                {
                    newMethodType.AddParameter(args[i].Simplify());
                }

                newMethodType.ASTNode        = newMethodDefinition;
                newMethodDefinition.TypeExpr = newMethodType;
                newMethodDefinition.TypeExpr.BuildFullName();
                newMethodDefinition.TypeExpr.BuildTypeExpressionString(4);

                TypeDefinition originalTypeDefinition = newMethodType.MemberInfo.TypeDefinition;
                originalTypeDefinition.AddMethod(newMethodDefinition);
                UserType originalClass = newMethodType.MemberInfo.Class;

                originalClass.AddMember(methodIndentificator, newMethodType.MemberInfo);
                newMethodDefinition.Accept(new VisitorSymbolIdentification(null), null);
                bool previousDynamism = DynVarOptions.Instance.EverythingDynamic;
                DynVarOptions.Instance.EverythingDynamic = false;
                newMethodDefinition.Accept(visitorTypeInference, null);
                DynVarOptions.Instance.EverythingDynamic = previousDynamism;
                foreach (var invocation in invocations)
                {
                    if (invocation.ActualMethodCalled is UnionType)
                    {
                        invocation.ActualMethodCalled = ((UnionType)invocation.ActualMethodCalled).TypeSet[1];
                    }
                }
                foreach (var castExpression in castExpressions)
                {
                    ((SingleIdentifierExpression)castExpression.Expression).FrozenTypeExpression = new ClassType("System.Object");
                    castExpression.Expression.ExpressionType = new ClassType("System.Object");
                }


                specilizedMethods.Add(fullMethodIndentificator, newMethodDefinition);
                return(newMethodDefinition);
            }
            return(specilizedMethods[fullMethodIndentificator]);
        }