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; }
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; }