/// <summary> /// For "new A(...)" generate "{ A a = Alloc(); A..ctor(a); return a; }" where /// "a" is a fresh local. /// </summary> public override void TraverseChildren(ICreateObjectInstance createObjectInstance) { var ctor = createObjectInstance.MethodToCall; var resolvedMethod = ResolveUnspecializedMethodOrThrow(ctor); Bpl.IToken token = createObjectInstance.Token(); var a = this.sink.CreateFreshLocal(createObjectInstance.Type); if (createObjectInstance.Type.TypeCode == PrimitiveTypeCode.IntPtr || createObjectInstance.Type.TypeCode == PrimitiveTypeCode.UIntPtr) { List<Bpl.Expr> args = new List<Bpl.Expr>(); foreach (IExpression e in createObjectInstance.Arguments) { this.Traverse(e); args.Add(TranslatedExpressions.Pop()); } System.Diagnostics.Debug.Assert(args.Count == 1); this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(a), args[0])); } else { // First generate an Alloc() call this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, this.sink.AllocationMethodName, new List<Bpl.Expr>(), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)}))); // Second, generate the call to the appropriate ctor List<Bpl.Expr> inexpr; List<Bpl.IdentifierExpr> outvars; Bpl.IdentifierExpr thisExpr; Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed; var proc = TranslateArgumentsAndReturnProcedure(token, ctor, resolvedMethod, null, createObjectInstance.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed); inexpr.Insert(0, Bpl.Expr.Ident(a)); EmitLineDirective(token); this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, proc.Name, inexpr, outvars)); // Generate an assumption about the dynamic type of the just allocated object sink.GenerateDynamicTypeAssume(this.StmtTraverser.StmtBuilder, token, Bpl.Expr.Ident(a), createObjectInstance.Type); } TranslatedExpressions.Push(Bpl.Expr.Ident(a)); }