Пример #1
0
        private bool ParseNewExpression(TokenReader reader, out Expression expression)
        {
            expression = null;
            Token start = reader.Peek();
            if (!this.Expect(reader, Keyword.New))
            {
                return false;
            }

            TypeReference typeRef = null;
            if (!this.ParseTypeReference(reader, out typeRef))
            {
                return false;
            }

            List<Expression> args = new List<Expression>();
            Token tok = reader.Peek();
            if (tok.Is(Keyword.LeftParen))
            {
                reader.Read();
                tok = reader.Peek();
                while (tok != null && !tok.Is(Keyword.RightParen))
                {
                    Expression arg = null;
                    if (!this.ParseExpression(reader, out arg))
                    {
                        return false;
                    }

                    args.Add(arg);
                    tok = reader.Peek();
                    if (!tok.Is(Keyword.Comma))
                    {
                        break;
                    }
                    else
                    {
                        tok = reader.Read();
                    }
                }

                if (!this.Expect(reader, Keyword.RightParen))
                {
                    return false;
                }
            }

            expression = new NewExpression(start, typeRef, args);
            return true;
        }
Пример #2
0
        private bool TryEmitNewExpression(
            NewExpression newExpr, 
            CompilerContext context, 
            Scope scope, 
            MethodImpl method, 
            out TypeDefinition valueType)
        {
            valueType = null;
            TypeDefinition objectType = null;
            if (!this.TryResolveTypeReference(context, newExpr.Type, out objectType))
            {
                valueType = null;
                return false;
            }

            if (!objectType.IsClass && newExpr.ConstructorArguments.Count() > 0)
            {
                log.Write(new Message(
                    newExpr.Start.Path,
                    newExpr.Start.Line,
                    newExpr.Start.Column,
                    Severity.Error,
                    Properties.Resources.CodeGenerator_ConstructorArgumentsAreOnlySupportedOnClassTypes));
                return false;
            }

            valueType = context.GetPointerType(objectType);

            if (!this.TryEmitAllocCall(newExpr.Start, context, scope, method, objectType.Size))
            {
                return false;
            }

            MethodInfo constructor = null;
            int argSize = 0;
            if (objectType.IsClass)
            {
                int nullTestStart = method.Statements.Count;
                List<TypeDefinition> argTypes = new List<TypeDefinition>();
                foreach (Expression arg in newExpr.ConstructorArguments.Reverse())
                {
                    TypeDefinition argType = null;
                    if (!this.TryEmitExpression(arg, context, scope, method, out argType))
                    {
                        return false;
                    }

                    this.PushResult(method, argType);
                    argSize += ((argType.Size + 3) / 4) * 4;
                    argTypes.Insert(0, argType);
                }

                if (!context.TryFindConstructor(objectType, argTypes, out constructor))
                {
                    // ok to have no default constructor
                    if (argTypes.Count > 0)
                    {
                        string message = string.Format(
                            System.Globalization.CultureInfo.CurrentCulture,
                            Properties.Resources.CodeGenerator_CannotFindConstructor,
                            objectType.FullName);
                        log.Write(new Message(
                            newExpr.Start.Path,
                            newExpr.Start.Line,
                            newExpr.Start.Column,
                            Severity.Error,
                            message));
                        return false;
                    }
                }

                if (constructor != null)
                {
                    LocalVariable tempPtr = scope.DefineTempVariable(valueType);
                    string jumpLabel = method.Module.GetNextJumpLabel();
                    List<AsmStatement> saveAlloc = new List<AsmStatement>();
                    saveAlloc.Add(new AsmStatement { Instruction = string.Format("mov _{0}$[ebp],eax", tempPtr.Name) });
                    saveAlloc.Add(new AsmStatement { Instruction = "test eax,eax" });
                    saveAlloc.Add(new AsmStatement { Instruction = "jz " + jumpLabel });
                    method.Statements.InsertRange(nullTestStart, saveAlloc);
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,_{0}$[ebp]", tempPtr.Name) });
                    method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                    method.Module.AddProto(constructor);
                    method.Statements.Add(new AsmStatement { Instruction = "call " + constructor.MangledName });
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("add esp,{0}", argSize + 4) });
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,_{0}$[ebp]", tempPtr.Name), Label = jumpLabel });
                }
            }

            return true;
        }