public override bool Resolve (BlockContext ec) { expr = expr.Resolve (ec); if (expr == null) return false; Report.Debug (64, "RESOLVE YIELD #1", this, ec, expr, expr.GetType (), ec.CurrentAnonymousMethod, ec.CurrentIterator); if (!CheckContext (ec, loc)) return false; iterator = ec.CurrentIterator; if (expr.Type != iterator.OriginalIteratorType) { expr = Convert.ImplicitConversionRequired ( ec, expr, iterator.OriginalIteratorType, loc); if (expr == null) return false; } if (!ec.CurrentBranching.CurrentUsageVector.IsUnreachable) unwind_protect = ec.CurrentBranching.AddResumePoint (this, loc, out resume_pc); return true; }
public override bool Resolve(BlockContext bc) { if (!CheckContext(bc, loc)) { return(false); } if (bc.HasAny(ResolveContext.Options.TryWithCatchScope)) { bc.Report.Error(1626, loc, "Cannot yield a value in the body of a try block with a catch clause"); } if (bc.HasSet(ResolveContext.Options.CatchScope)) { bc.Report.Error(1631, loc, "Cannot yield a value in the body of a catch clause"); } if (!base.Resolve(bc)) { return(false); } var otype = bc.CurrentIterator.OriginalIteratorType; if (expr.Type != otype) { expr = Convert.ImplicitConversionRequired(bc, expr, otype, loc); if (expr == null) { return(false); } } return(true); }
protected virtual BlockContext CreateBlockContext(ResolveContext rc) { var ctx = new BlockContext(rc, block, ((BlockContext)rc).ReturnType); ctx.CurrentAnonymousMethod = this; return(ctx); }
public override bool Resolve(BlockContext bc) { if (!CheckContext(bc, loc)) { return(false); } if (!base.Resolve(bc)) { return(false); } var otype = bc.CurrentIterator.OriginalIteratorType; if (expr.Type != otype) { expr = Convert.ImplicitConversionRequired(bc, expr, otype, loc); if (expr == null) { return(false); } } return(true); }
public override bool Resolve(BlockContext ec) { expr = expr.Resolve(ec); if (expr == null) { return(false); } Report.Debug(64, "RESOLVE YIELD #1", this, ec, expr, expr.GetType(), ec.CurrentAnonymousMethod, ec.CurrentIterator); if (!CheckContext(ec, loc)) { return(false); } iterator = ec.CurrentIterator; if (expr.Type != iterator.OriginalIteratorType) { expr = Convert.ImplicitConversionRequired( ec, expr, iterator.OriginalIteratorType, loc); if (expr == null) { return(false); } } if (!ec.CurrentBranching.CurrentUsageVector.IsUnreachable) { unwind_protect = ec.CurrentBranching.AddResumePoint(this, loc, out resume_pc); } return(true); }
protected override Expression CreateExpressionTree(ResolveContext ec, TypeSpec delegate_type) { if (ec.IsInProbingMode) { return(this); } BlockContext bc = new BlockContext(ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { CurrentAnonymousMethod = ec.CurrentAnonymousMethod }; Expression args = Parameters.CreateExpressionTree(bc, loc); Expression expr = Block.CreateExpressionTree(ec); if (expr == null) { return(null); } Arguments arguments = new Arguments(2); arguments.Add(new Argument(expr)); arguments.Add(new Argument(args)); return(CreateExpressionFactoryCall(ec, "Lambda", new TypeArguments(new TypeExpression(delegate_type, loc)), arguments)); }
public override bool Resolve(BlockContext ec) { ec.StartFlowBranching(iterator); bool ok = original_block.Resolve(ec); ec.EndFlowBranching(); return(ok); }
public string [] GetCompletions(string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) { return(null); } lock (evaluator_lock){ if (!inited) { Init(); } bool partial_input; CSharpParser parser = ParseString(ParseMode.GetCompletions, input, out partial_input); if (parser == null) { return(null); } Class host = parser.InteractiveResult; var base_class_imported = importer.ImportType(prev_host ?? base_class); var baseclass_list = new List <FullNamedExpression> () { new TypeExpression(base_class_imported, host.Location) }; host.SetBaseTypes(baseclass_list); #if !NET_2_0 var access = AssemblyBuilderAccess.RunAndCollect; #else var access = AssemblyBuilderAccess.Run; #endif var a = new AssemblyDefinitionDynamic(module, "completions"); a.Create(AppDomain.CurrentDomain, access); module.SetDeclaringAssembly(a); // Need to setup MemberCache host.CreateContainer(); // Need to setup base type host.DefineContainer(); var method = host.Members[0] as Method; BlockContext bc = new BlockContext(method, method.Block, ctx.BuiltinTypes.Void); try { method.Block.Resolve(bc, method); } catch (CompletionResult cr) { //Console.WriteLine("got completion from " + cr.StackTrace); prefix = cr.BaseText; return(cr.Result); } } return(null); }
public static VariableInfo Create(BlockContext bc, Parameter parameter) { var info = new VariableInfo(parameter.Name, parameter.Type, bc.AssignmentInfoOffset) { IsParameter = true }; bc.AssignmentInfoOffset += info.Length; return(info); }
public string[] GetCompletions(string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) { return(null); } lock (evaluator_lock) { if (!inited) { Init(); } bool partial_input; CSharpParser parser = ParseString(ParseMode.GetCompletions, input, out partial_input); if (parser == null) { if (CSharpParser.yacc_verbose_flag != 0) { Console.WriteLine("DEBUG: No completions available"); } return(null); } Class parser_result = parser.InteractiveResult; #if NET_4_0 var access = AssemblyBuilderAccess.RunAndCollect; #else var access = AssemblyBuilderAccess.Run; #endif var a = new AssemblyDefinitionDynamic(module, "completions"); a.Create(AppDomain.CurrentDomain, access); module.SetDeclaringAssembly(a); // Need to setup MemberCache parser_result.CreateType(); var method = parser_result.Methods[0] as Method; BlockContext bc = new BlockContext(method, method.Block, ctx.BuiltinTypes.Void); try { method.Block.Resolve(null, bc, method); } catch (CompletionResult cr) { prefix = cr.BaseText; return(cr.Result); } } return(null); }
protected void EmitCall(EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { int dyn_args_count = arguments == null ? 0 : arguments.Count; TypeExpr site_type = CreateSiteType(ec, arguments, dyn_args_count, isStatement); var field = CreateSiteField(ec, site_type); if (field == null) { return; } FieldExpr site_field_expr = new FieldExpr(field, loc); SymbolWriter.OpenCompilerGeneratedBlock(ec); Arguments args = new Arguments(1); args.Add(new Argument(binder)); StatementExpression s = new StatementExpression(new SimpleAssign(site_field_expr, new Invocation(new MemberAccess(site_type, "Create"), args))); BlockContext bc = new BlockContext(ec.MemberContext, null, TypeManager.void_type); if (s.Resolve(bc)) { Statement init = new If(new Binary(Binary.Operator.Equality, site_field_expr, new NullLiteral(loc), loc), s, loc); init.Emit(ec); } args = new Arguments(1 + dyn_args_count); args.Add(new Argument(site_field_expr)); if (arguments != null) { foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add(new Argument(a.Expr, a.ArgType)); continue; } args.Add(a); } } Expression target = new DelegateInvocation(new MemberAccess(site_field_expr, "Target", loc).Resolve(bc), args, loc).Resolve(bc); if (target != null) { target.Emit(ec); } SymbolWriter.CloseCompilerGeneratedBlock(ec); }
public FieldInitializerContext(IMemberContext mc, BlockContext constructorContext) : base(mc, null, constructorContext.ReturnType) { flags |= Options.FieldInitializerScope | Options.ConstructorScope; this.ctor_block = constructorContext.CurrentBlock.Explicit; if (ctor_block.IsCompilerGenerated) { CurrentBlock = ctor_block; } }
public override bool Resolve(BlockContext bc) { if (!base.Resolve(bc)) { return(false); } expr = expr.Resolve(bc); return(expr != null); }
public override bool Resolve(BlockContext bc) { expr = expr.Resolve(bc); if (expr == null) { return(false); } machine_initializer = bc.CurrentAnonymousMethod as T; inside_try_block = bc.CurrentTryBlock; return(true); }
public override bool Resolve(BlockContext ec) { TypeExpression storey_type_expr = new TypeExpression(host.Definition, loc); List <Expression> init = null; if (host.hoisted_this != null) { init = new List <Expression> (host.hoisted_params == null ? 1 : host.HoistedParameters.Count + 1); HoistedThis ht = host.hoisted_this; FieldExpr from = new FieldExpr(ht.Field, loc); from.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); init.Add(new ElementInitializer(ht.Field.Name, from, loc)); } if (host.hoisted_params != null) { if (init == null) { init = new List <Expression> (host.HoistedParameters.Count); } for (int i = 0; i < host.hoisted_params.Count; ++i) { HoistedParameter hp = (HoistedParameter)host.hoisted_params [i]; HoistedParameter hp_cp = (HoistedParameter)host.hoisted_params_copy [i]; FieldExpr from = new FieldExpr(hp_cp.Field, loc); from.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); init.Add(new ElementInitializer(hp.Field.Name, from, loc)); } } if (init != null) { new_storey = new NewInitialize(storey_type_expr, null, new CollectionOrObjectInitializers(init, loc), loc); } else { new_storey = new New(storey_type_expr, null, loc); } new_storey = new_storey.Resolve(ec); if (new_storey != null) { new_storey = Convert.ImplicitConversionRequired(ec, new_storey, host_method.MemberType, loc); } ec.CurrentBranching.CurrentUsageVector.Goto(); return(true); }
protected virtual BlockContext CreateBlockContext(BlockContext bc) { var ctx = new BlockContext(bc, block, bc.ReturnType); ctx.CurrentAnonymousMethod = this; ctx.AssignmentInfoOffset = bc.AssignmentInfoOffset; ctx.EnclosingLoop = bc.EnclosingLoop; ctx.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch; ctx.Switch = bc.Switch; return(ctx); }
protected override BlockContext CreateBlockContext(BlockContext bc) { var ctx = base.CreateBlockContext(bc); var lambda = bc.CurrentAnonymousMethod as LambdaMethod; if (lambda != null) { return_inference = lambda.ReturnTypeInference; } ctx.Set(ResolveContext.Options.TryScope); return(ctx); }
protected override BlockContext CreateBlockContext(BlockContext bc) { var ctx = base.CreateBlockContext(bc); var am = bc.CurrentAnonymousMethod as AnonymousMethodBody; if (am != null) { return_inference = am.ReturnTypeInference; } ctx.Set(ResolveContext.Options.TryScope); return(ctx); }
public override bool Resolve(BlockContext bc) { if (type_expr == null) { if (Initializer == null) { type_expr = new UntypedTypeExpression(loc); } else { type_expr = new VarExpr(loc); } } return(base.Resolve(bc)); }
public ExpressionStatement CreateExpressionTreeVariable(BlockContext ec) { if ((modFlags & Modifier.RefOutMask) != 0) { ec.Report.Error(1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); } expr_tree_variable = TemporaryVariableReference.Create(ResolveParameterExpressionType(ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); expr_tree_variable = (TemporaryVariableReference)expr_tree_variable.Resolve(ec); Arguments arguments = new Arguments(2); arguments.Add(new Argument(new TypeOf(parameter_type, Location))); arguments.Add(new Argument(new StringConstant(ec.BuiltinTypes, Name, Location))); return(new SimpleAssign(ExpressionTreeVariableReference(), Expression.CreateExpressionFactoryCall(ec, "Parameter", null, arguments, Location))); }
public static bool CheckContext(BlockContext bc, Location loc) { if (!bc.CurrentAnonymousMethod.IsIterator) { bc.Report.Error(1621, loc, "The yield statement cannot be used inside anonymous method blocks"); return(false); } if (bc.HasSet(ResolveContext.Options.FinallyScope)) { bc.Report.Error(1625, loc, "Cannot yield in the body of a finally clause"); return(false); } return(true); }
public override bool Resolve(BlockContext bc) { expr = expr.Resolve(bc); if (expr == null) { return(false); } machine_initializer = bc.CurrentAnonymousMethod as T; if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable) { unwind_protect = bc.CurrentBranching.AddResumePoint(this, out resume_pc); } return(true); }
public void EmitCpp(TypeDefinition parent, CppEmitContext cec) { var mc = (IMemberContext)method; method.ParameterInfo.ApplyAttributes(mc, MethodBuilder); ToplevelBlock block = method.Block; if (block != null) { BlockContext bc = new BlockContext(mc, block, method.ReturnType); if (block.Resolve(null, bc, method)) { block.EmitBlockCpp(cec, false, false); } } }
protected override Expression CreateExpressionTree (ResolveContext ec, Type delegate_type) { if (ec.IsInProbingMode) return this; BlockContext bc = new BlockContext (ec.MemberContext, ec.CurrentBlock.Explicit, TypeManager.void_type); Expression args = Parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (delegate_type, loc)), arguments); }
protected override bool DoResolve(BlockContext ec) { // // When delegate returns void, only expression statements can be used // if (ec.ReturnType == TypeManager.void_type) { Expr = Expr.Resolve (ec); if (Expr == null) return false; statement = Expr as ExpressionStatement; if (statement == null) Expr.Error_InvalidExpressionStatement (ec); return true; } return base.DoResolve (ec); }
public override Expression CreateExpressionTree(ResolveContext ec) { BlockContext bc = new BlockContext(ec.MemberContext, Block, ReturnType); Expression args = parameters.CreateExpressionTree(bc, loc); Expression expr = Block.CreateExpressionTree(ec); if (expr == null) { return(null); } Arguments arguments = new Arguments(2); arguments.Add(new Argument(expr)); arguments.Add(new Argument(args)); return(CreateExpressionFactoryCall(ec, "Lambda", new TypeArguments(new TypeExpression(type, loc)), arguments)); }
/// <summary> /// We already know that the statement is unreachable, but we still /// need to resolve it to catch errors. /// </summary> public virtual bool ResolveUnreachable (BlockContext ec, bool warn) { // // This conflicts with csc's way of doing this, but IMHO it's // the right thing to do. // // If something is unreachable, we still check whether it's // correct. This means that you cannot use unassigned variables // in unreachable code, for instance. // if (warn) ec.Report.Warning (162, 2, loc, "Unreachable code detected"); ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); bool ok = Resolve (ec); ec.KillFlowBranching (); return ok; }
protected override Expression DoResolve(ResolveContext ec) { IteratorHost = (IteratorStorey)block.TopBlock.AnonymousMethodStorey; BlockContext ctx = new BlockContext(ec, block, ReturnType); ctx.CurrentAnonymousMethod = this; ctx.StartFlowBranching(this, ec.CurrentBranching); Block.Resolve(ctx); ctx.EndFlowBranching(); var move_next = new IteratorMethod(IteratorHost, new TypeExpression(ec.BuiltinTypes.Bool, loc), Modifiers.PUBLIC, new MemberName("MoveNext", Location)); move_next.Block.AddStatement(new MoveNextMethodStatement(this)); IteratorHost.AddMethod(move_next); eclass = ExprClass.Value; return(this); }
protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) { if (ec.IsInProbingMode) return this; BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { CurrentAnonymousMethod = ec.CurrentAnonymousMethod }; Expression args = Parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (delegate_type, loc)), arguments); }
protected override bool DoResolve(BlockContext ec) { // // When delegate returns void, only expression statements can be used // if (ec.ReturnType.Kind == MemberKind.Void) { Expr = Expr.Resolve(ec); if (Expr == null) { return(false); } if (Expr is ReferenceExpression) { // CSC: should be different error code ec.Report.Error(8149, loc, "By-reference returns can only be used in lambda expressions that return by reference"); return(false); } statement = Expr as ExpressionStatement; if (statement == null) { var reduced = Expr as IReducedExpressionStatement; if (reduced != null) { statement = EmptyExpressionStatement.Instance; } else { Expr.Error_InvalidExpressionStatement(ec); } } return(true); } return(base.DoResolve(ec)); }
public Expression CreateExpressionTree(BlockContext ec, Location loc) { ArrayList initializers = new ArrayList(Count); foreach (Parameter p in FixedParameters) { // // Each parameter expression is stored to local variable // to save some memory when referenced later. // StatementExpression se = new StatementExpression(p.CreateExpressionTreeVariable(ec)); if (se.Resolve(ec)) { ec.CurrentBlock.AddScopeStatement(se); } initializers.Add(p.ExpressionTreeVariableReference()); } return(new ArrayCreation( Parameter.ResolveParameterExpressionType(ec, loc), "[]", initializers, loc)); }
protected override bool DoResolve(BlockContext ec) { // // When delegate returns void, only expression statements can be used // if (ec.ReturnType.Kind == MemberKind.Void) { Expr = Expr.Resolve(ec); if (Expr == null) { return(false); } statement = Expr as ExpressionStatement; if (statement == null) { Expr.Error_InvalidExpressionStatement(ec); } return(true); } return(base.DoResolve(ec)); }
protected override Expression CreateExpressionTree(ResolveContext ec, Type delegate_type) { if (ec.IsInProbingMode) { return(this); } BlockContext bc = new BlockContext(ec.MemberContext, ec.CurrentBlock.Explicit, TypeManager.void_type); Expression args = Parameters.CreateExpressionTree(bc, loc); Expression expr = Block.CreateExpressionTree(ec); if (expr == null) { return(null); } Arguments arguments = new Arguments(2); arguments.Add(new Argument(expr)); arguments.Add(new Argument(args)); return(CreateExpressionFactoryCall(ec, "Lambda", new TypeArguments(new TypeExpression(delegate_type, loc)), arguments)); }
public void ResolveFieldInitializers (BlockContext ec) { if (partial_parts != null) { foreach (TypeContainer part in partial_parts) { part.DoResolveFieldInitializers (ec); } } DoResolveFieldInitializers (ec); }
public void EmitJs (TypeDefinition parent, JsEmitContext jec) { var mc = (IMemberContext) method; method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); ToplevelBlock block = method.Block; if (block != null) { BlockContext bc = new BlockContext (mc, block, method.ReturnType); if (block.Resolve (null, bc, method)) { block.EmitBlockJs (jec, false, false); } } }
public override void EmitJs (JsEmitContext jec) { base.EmitJs (jec); bool is_static = (this.ModFlags & Modifiers.STATIC) != 0; if (!is_static) { jec.Buf.Write ("\tfunction " + this.Parent.MemberName.Name + "(", Location); parameters.EmitJs (jec); jec.Buf.Write (") "); } BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void); bc.Set (ResolveContext.Options.ConstructorScope); bool emitted_block = false; if (block != null) { // // If we use a "this (...)" constructor initializer, then // do not emit field initializers, they are initialized in the other constructor // if (!(Initializer is ConstructorThisInitializer)) Parent.PartialContainer.ResolveFieldInitializers (bc); if (!IsStatic) { if (Initializer == null) { if (Parent.PartialContainer.Kind == MemberKind.Struct) { // // If this is a non-static `struct' constructor and doesn't have any // initializer, it must initialize all of the struct's fields. // block.AddThisVariable (bc); } else if (Parent.PartialContainer.Kind == MemberKind.Class) { Initializer = new GeneratedBaseInitializer (Location); } } if (Initializer != null && !(bc.FileType == SourceFileType.PlayScript && Initializer.IsAsExplicitSuperCall)) { // // mdb format does not support reqions. Try to workaround this by emitting the // sequence point at initializer. Any breakpoint at constructor header should // be adjusted to this sequence point as it's the next one which follows. // block.AddScopeStatement (new StatementExpression (Initializer)); } } if (block.Resolve (null, bc, this)) { block.EmitBlockJs (jec, false, is_static); emitted_block = true; } } if (!is_static) { if (!emitted_block) jec.Buf.Write ("{\n\t}", Location); jec.Buf.Write ("\n"); } block = null; }
public string [] GetCompletions (string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) return null; lock (evaluator_lock){ if (!inited) Init (); bool partial_input; CSharpParser parser = ParseString (ParseMode.GetCompletions, input, out partial_input); if (parser == null){ return null; } Class parser_result = parser.InteractiveResult; #if NET_4_0 var access = AssemblyBuilderAccess.RunAndCollect; #else var access = AssemblyBuilderAccess.Run; #endif var a = new AssemblyDefinitionDynamic (module, "completions"); a.Create (AppDomain.CurrentDomain, access); module.SetDeclaringAssembly (a); // Need to setup MemberCache parser_result.CreateContainer (); var method = parser_result.Members[0] as Method; BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void); try { method.Block.Resolve (null, bc, method); } catch (CompletionResult cr) { prefix = cr.BaseText; return cr.Result; } } return null; }
public override bool Resolve(BlockContext bc) { if (bc.CurrentBlock is Linq.QueryBlock) { bc.Report.Error(1995, loc, "The `await' operator may only be used in a query expression within the first collection expression of the initial `from' clause or within the collection expression of a `join' clause"); return(false); } if (!base.Resolve(bc)) { return(false); } type = expr.Type; Arguments args = new Arguments(0); // // The await expression is of dynamic type // if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { result_type = type; expr = new Invocation(new MemberAccess(expr, "GetAwaiter"), args).Resolve(bc); return(true); } // // Check whether the expression is awaitable // Expression ama = new AwaitableMemberAccess(expr).Resolve(bc); if (ama == null) { return(false); } var errors_printer = new SessionReportPrinter(); var old = bc.Report.SetPrinter(errors_printer); ama = new Invocation(ama, args).Resolve(bc); bc.Report.SetPrinter(old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression(ama.Type)) { bc.Report.Error(1986, expr.Location, "The `await' operand type `{0}' must have suitable GetAwaiter method", expr.Type.GetSignatureForError()); return(false); } var awaiter_type = ama.Type; awaiter_definition = bc.Module.GetAwaiter(awaiter_type); if (!awaiter_definition.IsValidPattern) { Error_WrongAwaiterPattern(bc, awaiter_type); return(false); } if (!awaiter_definition.INotifyCompletion) { bc.Report.Error(4027, loc, "The awaiter type `{0}' must implement interface `{1}'", awaiter_type.GetSignatureForError(), bc.Module.PredefinedTypes.INotifyCompletion.GetSignatureForError()); return(false); } expr = ama; result_type = awaiter_definition.GetResult.ReturnType; return(true); }
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae) { if (block.Resolved) return this; // TODO: Implement clone BlockContext aec = new BlockContext (ec, block, ReturnType); aec.CurrentAnonymousMethod = ae; var am = this as AnonymousMethodBody; if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { am.ReturnTypeInference = new TypeInferenceContext (); } var bc = ec as BlockContext; if (bc != null) { aec.AssignmentInfoOffset = bc.AssignmentInfoOffset; aec.EnclosingLoop = bc.EnclosingLoop; aec.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch; aec.Switch = bc.Switch; } var errors = ec.Report.Errors; bool res = Block.Resolve (aec); if (res && errors == ec.Report.Errors) { MarkReachable (new Reachability ()); if (!CheckReachableExit (ec.Report)) { return null; } if (bc != null) bc.AssignmentInfoOffset = aec.AssignmentInfoOffset; } if (am != null && am.ReturnTypeInference != null) { am.ReturnTypeInference.FixAllTypes (ec); ReturnType = am.ReturnTypeInference.InferredTypeArguments [0]; am.ReturnTypeInference = null; // // If e is synchronous the inferred return type is T // If e is asynchronous and the body of F is either an expression classified as nothing // or a statement block where no return statements have expressions, the inferred return type is Task // If e is async and has an inferred result type T, the inferred return type is Task<T> // if (block.IsAsync && ReturnType != null) { ReturnType = ReturnType.Kind == MemberKind.Void ? ec.Module.PredefinedTypes.Task.TypeSpec : ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); } } if (res && errors != ec.Report.Errors) return null; return res ? this : null; }
public static string [] GetCompletions (string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) return null; lock (evaluator_lock){ if (!inited) Init (); bool partial_input; CSharpParser parser = ParseString (ParseMode.GetCompletions, input, out partial_input); if (parser == null){ if (CSharpParser.yacc_verbose_flag != 0) Console.WriteLine ("DEBUG: No completions available"); return null; } Class parser_result = parser.InteractiveResult as Class; if (parser_result == null){ if (CSharpParser.yacc_verbose_flag != 0) Console.WriteLine ("Do not know how to cope with !Class yet"); return null; } try { RootContext.ResolveTree (); if (ctx.Report.Errors != 0) return null; RootContext.PopulateTypes (); if (ctx.Report.Errors != 0) return null; MethodOrOperator method = null; foreach (MemberCore member in parser_result.Methods){ if (member.Name != "Host") continue; method = (MethodOrOperator) member; break; } if (method == null) throw new InternalErrorException ("did not find the the Host method"); BlockContext bc = new BlockContext (method, method.Block, method.ReturnType); try { method.Block.Resolve (null, bc, method); } catch (CompletionResult cr){ prefix = cr.BaseText; return cr.Result; } } finally { parser.undo.ExecuteUndo (); } } return null; }
public void ResolveFieldInitializers (BlockContext ec) { Debug.Assert (!IsPartialPart); if (ec.IsStatic) { if (initialized_static_fields == null) return; bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize; int i; ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count]; for (i = 0; i < initialized_static_fields.Count; ++i) { FieldInitializer fi = initialized_static_fields [i]; ExpressionStatement s = fi.ResolveStatement (ec); if (s == null) { s = EmptyExpressionStatement.Instance; } else if (!fi.IsSideEffectFree) { has_complex_initializer |= true; } init [i] = s; } for (i = 0; i < initialized_static_fields.Count; ++i) { FieldInitializer fi = initialized_static_fields [i]; // // Need special check to not optimize code like this // static int a = b = 5; // static int b = 0; // if (!has_complex_initializer && fi.IsDefaultInitializer) continue; ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i])); } return; } if (initialized_fields == null) return; for (int i = 0; i < initialized_fields.Count; ++i) { FieldInitializer fi = initialized_fields [i]; ExpressionStatement s = fi.ResolveStatement (ec); if (s == null) continue; // // Field is re-initialized to its default value => removed // if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize) continue; ec.CurrentBlock.AddScopeStatement (new StatementExpression (s)); } }
protected void EmitCall(EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { int dyn_args_count = arguments == null ? 0 : arguments.Count; TypeExpr site_type = CreateSiteType (RootContext.ToplevelTypes.Compiler, arguments, dyn_args_count, isStatement); FieldExpr site_field_expr = new FieldExpr (CreateSiteField (site_type), loc); SymbolWriter.OpenCompilerGeneratedBlock (ec); Arguments args = new Arguments (1); args.Add (new Argument (binder)); StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (site_type, "Create"), args))); BlockContext bc = new BlockContext (ec.MemberContext, null, TypeManager.void_type); if (s.Resolve (bc)) { Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc), loc), s, loc); init.Emit (ec); } args = new Arguments (1 + dyn_args_count); args.Add (new Argument (site_field_expr)); if (arguments != null) { foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add (new Argument (a.Expr, a.ArgType)); continue; } args.Add (a); } } Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); if (target != null) target.Emit (ec); SymbolWriter.CloseCompilerGeneratedBlock (ec); }
public FieldInitializerContext (IMemberContext mc, BlockContext constructorContext) : base (mc, null, constructorContext.ReturnType) { flags |= Options.FieldInitializerScope | Options.ConstructorScope; this.ctor_block = constructorContext.CurrentBlock.Explicit; }
public Expression CreateExpressionTree (BlockContext ec, Location loc) { var initializers = new ArrayInitializer (Count, loc); foreach (Parameter p in FixedParameters) { // // Each parameter expression is stored to local variable // to save some memory when referenced later. // StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec), Location.Null); if (se.Resolve (ec)) { ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ())); ec.CurrentBlock.AddScopeStatement (se); } initializers.Add (p.ExpressionTreeVariableReference ()); } return new ArrayCreation ( Parameter.ResolveParameterExpressionType (ec, loc), initializers, loc); }
public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec) { if ((modFlags & Modifier.RefOutMask) != 0) ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec); Arguments arguments = new Arguments (2); arguments.Add (new Argument (new TypeOf (parameter_type, Location))); arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location))); return new SimpleAssign (ExpressionTreeVariableReference (), Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location)); }
protected override bool DoResolve(BlockContext ec) { iterator = ec.CurrentIterator; return Yield.CheckContext (ec, loc); }
// // Emits the code // public override void Emit () { if (Parent.PartialContainer.IsComImport) { if (!IsDefault ()) { Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor", Parent.GetSignatureForError ()); } // Set as internal implementation and reset block data // to ensure no IL is generated ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall); block = null; } if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder); if (OptAttributes != null) OptAttributes.Emit (); base.Emit (); parameters.ApplyAttributes (this, ConstructorBuilder); BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void); bc.Set (ResolveContext.Options.ConstructorScope); if (block != null) { // // If we use a "this (...)" constructor initializer, then // do not emit field initializers, they are initialized in the other constructor // if (!(Initializer is ConstructorThisInitializer)) Parent.PartialContainer.ResolveFieldInitializers (bc); if (!IsStatic) { if (Initializer == null) { if (Parent.PartialContainer.Kind == MemberKind.Struct) { // // If this is a non-static `struct' constructor and doesn't have any // initializer, it must initialize all of the struct's fields. // block.AddThisVariable (bc); } else if (Parent.PartialContainer.Kind == MemberKind.Class) { Initializer = new GeneratedBaseInitializer (Location); } } if (Initializer != null && !(bc.FileType == SourceFileType.PlayScript && Initializer.IsAsExplicitSuperCall)) { // // mdb format does not support reqions. Try to workaround this by emitting the // sequence point at initializer. Any breakpoint at constructor header should // be adjusted to this sequence point as it's the next one which follows. // block.AddScopeStatement (new StatementExpression (Initializer)); } } if (block.Resolve (null, bc, this)) { debug_builder = Parent.CreateMethodSymbolEntry (); EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder); ec.With (EmitContext.Options.ConstructorScope, true); block.Emit (ec); } } if (declarative_security != null) { foreach (var de in declarative_security) { #if STATIC ConstructorBuilder.__AddDeclarativeSecurity (de); #else ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value); #endif } } block = null; }
public override bool Resolve(BlockContext ec) { ec.StartFlowBranching (iterator); bool ok = original_block.Resolve (ec); ec.EndFlowBranching (); return ok; }
// // Emits the code // public void Emit (TypeDefinition parent) { DefineOverride (parent); var mc = (IMemberContext) method; method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); ToplevelBlock block = method.Block; if (block != null) { BlockContext bc = new BlockContext (mc, block, method.ReturnType); if (block.Resolve (null, bc, method)) { debug_builder = member.Parent.CreateMethodSymbolEntry (); EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder); block.Emit (ec); } } }
public override bool Resolve(BlockContext ec) { return true; }
public void ResolveFieldInitializers (BlockContext ec) { Debug.Assert (!IsPartialPart); if (ec.IsStatic) { if (initialized_static_fields == null) return; bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize; int i; ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count]; for (i = 0; i < initialized_static_fields.Count; ++i) { FieldInitializer fi = initialized_static_fields [i]; ExpressionStatement s = fi.ResolveStatement (ec); if (s == null) { s = EmptyExpressionStatement.Instance; } else if (!fi.IsSideEffectFree) { has_complex_initializer = true; } init [i] = s; } for (i = 0; i < initialized_static_fields.Count; ++i) { FieldInitializer fi = initialized_static_fields [i]; // // Need special check to not optimize code like this // static int a = b = 5; // static int b = 0; // if (!has_complex_initializer && fi.IsDefaultInitializer) continue; ec.AssignmentInfoOffset += fi.AssignmentOffset; ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i])); } return; } if (initialized_fields == null) return; for (int i = 0; i < initialized_fields.Count; ++i) { FieldInitializer fi = initialized_fields [i]; // // Clone before resolving otherwise when field initializer is needed // in more than 1 constructor any resolve after the initial one would // only took the resolved expression which is problem for expressions // that generate extra expressions or code during Resolve phase // var cloned = fi.Clone (new CloneContext ()); ExpressionStatement s = fi.ResolveStatement (ec); if (s == null) { initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null); continue; } // // Field is re-initialized to its default value => removed // if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize) continue; ec.AssignmentInfoOffset += fi.AssignmentOffset; ec.CurrentBlock.AddScopeStatement (new StatementExpression (s)); initialized_fields [i] = (FieldInitializer) cloned; } }
public override bool Resolve(BlockContext ec) { TypeExpression storey_type_expr = new TypeExpression (host.Definition, loc); List<Expression> init = null; if (host.hoisted_this != null) { init = new List<Expression> (host.hoisted_params == null ? 1 : host.HoistedParameters.Count + 1); HoistedThis ht = host.hoisted_this; FieldExpr from = new FieldExpr (ht.Field, loc); from.InstanceExpression = CompilerGeneratedThis.Instance; init.Add (new ElementInitializer (ht.Field.Name, from, loc)); } if (host.hoisted_params != null) { if (init == null) init = new List<Expression> (host.HoistedParameters.Count); for (int i = 0; i < host.hoisted_params.Count; ++i) { HoistedParameter hp = (HoistedParameter) host.hoisted_params [i]; HoistedParameter hp_cp = (HoistedParameter) host.hoisted_params_copy [i]; FieldExpr from = new FieldExpr (hp_cp.Field, loc); from.InstanceExpression = CompilerGeneratedThis.Instance; init.Add (new ElementInitializer (hp.Field.Name, from, loc)); } } if (init != null) { new_storey = new NewInitialize (storey_type_expr, null, new CollectionOrObjectInitializers (init, loc), loc); } else { new_storey = new New (storey_type_expr, null, loc); } new_storey = new_storey.Resolve (ec); if (new_storey != null) new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc); if (TypeManager.int_interlocked_compare_exchange == null) { TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Interlocked", MemberKind.Class, true); if (t != null) { var p = ParametersCompiled.CreateFullyResolved ( new[] { new ParameterData (null, Parameter.Modifier.REF), new ParameterData (null, Parameter.Modifier.NONE), new ParameterData (null, Parameter.Modifier.NONE) }, new[] { TypeManager.int32_type, TypeManager.int32_type, TypeManager.int32_type } ); var f = new MemberFilter ("CompareExchange", 0, MemberKind.Method, p, TypeManager.int32_type); TypeManager.int_interlocked_compare_exchange = TypeManager.GetPredefinedMethod (t, f, loc); } } ec.CurrentBranching.CurrentUsageVector.Goto (); return true; }
// // Emits the code // public void Emit (DeclSpace parent) { if (GenericMethod != null) GenericMethod.EmitAttributes (); var mc = (IMemberContext) method; method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block); ToplevelBlock block = method.Block; if (block != null) { BlockContext bc = new BlockContext (mc, block, method.ReturnType); if (block.Resolve (null, bc, method)) { EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ()); if (!ec.HasReturnLabel && bc.HasReturnLabel) { ec.ReturnLabel = bc.ReturnLabel; ec.HasReturnLabel = true; } block.Emit (ec); } } if (source != null) { method.EmitExtraSymbolInfo (source); source.CloseMethod (); } }
// // Emits the code // public override void Emit () { if (Parent.PartialContainer.IsComImport) { if (!IsDefault ()) { Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor", Parent.GetSignatureForError ()); } ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall); } if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) Compiler.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder); if (OptAttributes != null) OptAttributes.Emit (); base.Emit (); // // If we use a "this (...)" constructor initializer, then // do not emit field initializers, they are initialized in the other constructor // bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) || !(Initializer is ConstructorThisInitializer); BlockContext bc = new BlockContext (this, block, TypeManager.void_type); bc.Set (ResolveContext.Options.ConstructorScope); if (emit_field_initializers) Parent.PartialContainer.ResolveFieldInitializers (bc); if (block != null) { // If this is a non-static `struct' constructor and doesn't have any // initializer, it must initialize all of the struct's fields. if ((Parent.PartialContainer.Kind == MemberKind.Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null)) block.AddThisVariable (bc, Parent, Location); if (block != null && (ModFlags & Modifiers.STATIC) == 0){ if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null) Initializer = new GeneratedBaseInitializer (Location); if (Initializer != null) { block.AddScopeStatement (new StatementExpression (Initializer)); } } } parameters.ApplyAttributes (this, ConstructorBuilder); SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block); if (block != null) { if (block.Resolve (null, bc, this)) { EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType); ec.With (EmitContext.Options.ConstructorScope, true); if (!ec.HasReturnLabel && bc.HasReturnLabel) { ec.ReturnLabel = bc.ReturnLabel; ec.HasReturnLabel = true; } block.Emit (ec); } } if (source != null) source.CloseMethod (); if (declarative_security != null) { foreach (var de in declarative_security) { ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value); } } block = null; }
public override Expression CreateExpressionTree (ResolveContext ec) { BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType); Expression args = parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (type, loc)), arguments); }
public static string [] GetCompletions (string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) return null; lock (evaluator_lock){ if (!inited) Init (); bool partial_input; CSharpParser parser = ParseString (ParseMode.GetCompletions, input, out partial_input); if (parser == null){ if (CSharpParser.yacc_verbose_flag != 0) Console.WriteLine ("DEBUG: No completions available"); return null; } Class parser_result = parser.InteractiveResult; try { var a = new AssemblyDefinitionDynamic (RootContext.ToplevelTypes, "temp"); a.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Run); RootContext.ToplevelTypes.SetDeclaringAssembly (a); RootContext.ToplevelTypes.CreateType (); RootContext.ToplevelTypes.Define (); parser_result.CreateType (); parser_result.Define (); if (ctx.Report.Errors != 0) return null; MethodOrOperator method = null; foreach (MemberCore member in parser_result.Methods){ if (member.Name != "Host") continue; method = (MethodOrOperator) member; break; } if (method == null) throw new InternalErrorException ("did not find the the Host method"); BlockContext bc = new BlockContext (method, method.Block, method.ReturnType); try { method.Block.Resolve (null, bc, method); } catch (CompletionResult cr){ prefix = cr.BaseText; return cr.Result; } } finally { parser.undo.ExecuteUndo (); } } return null; }
public static string [] GetCompletions(string input, out string prefix) { prefix = ""; if (input == null || input.Length == 0) { return(null); } lock (evaluator_lock) { if (!inited) { Init(); } bool partial_input; CSharpParser parser = ParseString(ParseMode.GetCompletions, input, out partial_input); if (parser == null) { if (CSharpParser.yacc_verbose_flag != 0) { Console.WriteLine("DEBUG: No completions available"); } return(null); } Class parser_result = parser.InteractiveResult as Class; if (parser_result == null) { if (CSharpParser.yacc_verbose_flag != 0) { Console.WriteLine("Do not know how to cope with !Class yet"); } return(null); } try { var a = new AssemblyDefinitionDynamic(RootContext.ToplevelTypes, "temp"); a.Create(AppDomain.CurrentDomain, AssemblyBuilderAccess.Run); RootContext.ToplevelTypes.SetDeclaringAssembly(a); RootContext.ToplevelTypes.Define(); if (ctx.Report.Errors != 0) { return(null); } MethodOrOperator method = null; foreach (MemberCore member in parser_result.Methods) { if (member.Name != "Host") { continue; } method = (MethodOrOperator)member; break; } if (method == null) { throw new InternalErrorException("did not find the the Host method"); } BlockContext bc = new BlockContext(method, method.Block, method.ReturnType); try { method.Block.Resolve(null, bc, method); } catch (CompletionResult cr) { prefix = cr.BaseText; return(cr.Result); } } finally { parser.undo.ExecuteUndo(); } } return(null); }
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae) { if (block.Resolved) return this; // TODO: Implement clone BlockContext aec = new BlockContext (ec, block, ReturnType); aec.CurrentAnonymousMethod = ae; ResolveContext.Options flags = 0; var am = this as AnonymousMethodBody; if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { am.ReturnTypeInference = new TypeInferenceContext (); } if (ec.IsInProbingMode) flags |= ResolveContext.Options.ProbingMode; if (ec.HasSet (ResolveContext.Options.FieldInitializerScope)) flags |= ResolveContext.Options.FieldInitializerScope; if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) flags |= ResolveContext.Options.ExpressionTreeConversion; aec.Set (flags); var errors = ec.Report.Errors; bool res = Block.Resolve (ec.CurrentBranching, aec, null); if (am != null && am.ReturnTypeInference != null) { am.ReturnTypeInference.FixAllTypes (ec); ReturnType = am.ReturnTypeInference.InferredTypeArguments [0]; am.ReturnTypeInference = null; // // If e is synchronous the inferred return type is T // If e is asynchronous the inferred return type is Task<T> // if (block.IsAsync && ReturnType != null) { ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); } } if (res && errors != ec.Report.Errors) return null; return res ? this : null; }
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae) { if (block.Resolved) return this; // TODO: Implement clone BlockContext aec = new BlockContext (ec, block, ReturnType); aec.CurrentAnonymousMethod = ae; var am = this as AnonymousMethodBody; if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { am.ReturnTypeInference = new TypeInferenceContext (); } var bc = ec as BlockContext; if (bc != null) aec.FlowOffset = bc.FlowOffset; var errors = ec.Report.Errors; bool res = Block.Resolve (ec.CurrentBranching, aec, null); if (am != null && am.ReturnTypeInference != null) { am.ReturnTypeInference.FixAllTypes (ec); ReturnType = am.ReturnTypeInference.InferredTypeArguments [0]; am.ReturnTypeInference = null; // // If e is synchronous the inferred return type is T // If e is asynchronous the inferred return type is Task<T> // if (block.IsAsync && ReturnType != null) { ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); } } if (res && errors != ec.Report.Errors) return null; return res ? this : null; }
protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { // // This method generates all internal infrastructure for a dynamic call. The // reason why it's quite complicated is the mixture of dynamic and anonymous // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous // methods can generate temporary storey as well (AnonStorey). Handling MVAR // type parameters rewrite is non-trivial in such case as there are various // combinations possible therefore the mutator is not straightforward. Secondly // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit // correct Site field type and its access from EmitContext. // int dyn_args_count = arguments == null ? 0 : arguments.Count; int default_args = isStatement ? 1 : 2; var module = ec.Module; bool has_ref_out_argument = false; var targs = new TypeExpression[dyn_args_count + default_args]; targs[0] = new TypeExpression (module.PredefinedTypes.CallSite.TypeSpec, loc); TypeExpression[] targs_for_instance = null; TypeParameterMutator mutator; var site_container = ec.CreateDynamicSite (); if (context_mvars != null) { TypeParameters tparam; TypeContainer sc = site_container; do { tparam = sc.CurrentTypeParameters; sc = sc.Parent; } while (tparam == null); mutator = new TypeParameterMutator (context_mvars, tparam); if (!ec.IsAnonymousStoreyMutateRequired) { targs_for_instance = new TypeExpression[targs.Length]; targs_for_instance[0] = targs[0]; } } else { mutator = null; } for (int i = 0; i < dyn_args_count; ++i) { Argument a = arguments[i]; if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) has_ref_out_argument = true; var t = a.Type; // Convert any internal type like dynamic or null to object if (t.Kind == MemberKind.InternalCompilerType) t = ec.BuiltinTypes.Object; if (targs_for_instance != null) targs_for_instance[i + 1] = new TypeExpression (t, loc); if (mutator != null) t = t.Mutate (mutator); targs[i + 1] = new TypeExpression (t, loc); } TypeExpr del_type = null; TypeExpr del_type_instance_access = null; if (!has_ref_out_argument) { string d_name = isStatement ? "Action" : "Func"; TypeSpec te = null; Namespace type_ns = module.GlobalRootNamespace.GetNamespace ("System", true); if (type_ns != null) { te = type_ns.LookupType (module, d_name, dyn_args_count + default_args, LookupMode.Normal, loc); } if (te != null) { if (!isStatement) { var t = type; if (t.Kind == MemberKind.InternalCompilerType) t = ec.BuiltinTypes.Object; if (targs_for_instance != null) targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression (t, loc); if (mutator != null) t = t.Mutate (mutator); targs[targs.Length - 1] = new TypeExpression (t, loc); } del_type = new GenericTypeExpr (te, new TypeArguments (targs), loc); if (targs_for_instance != null) del_type_instance_access = new GenericTypeExpr (te, new TypeArguments (targs_for_instance), loc); else del_type_instance_access = del_type; } } // // Create custom delegate when no appropriate predefined delegate has been found // Delegate d; if (del_type == null) { TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type; Parameter[] p = new Parameter[dyn_args_count + 1]; p[0] = new Parameter (targs[0], "p0", Parameter.Modifier.NONE, null, loc); var site = ec.CreateDynamicSite (); int index = site.Containers == null ? 0 : site.Containers.Count; if (mutator != null) rt = mutator.Mutate (rt); for (int i = 1; i < dyn_args_count + 1; ++i) { p[i] = new Parameter (targs[i], "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); } d = new Delegate (site, new TypeExpression (rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName ("Container" + index.ToString ("X")), new ParametersCompiled (p), null); d.CreateContainer (); d.DefineContainer (); d.Define (); d.PrepareEmit (); site.AddTypeContainer (d); // // Add new container to inflated site container when the // member cache already exists // if (site.CurrentType is InflatedTypeSpec && index > 0) site.CurrentType.MemberCache.AddMember (d.CurrentType); del_type = new TypeExpression (d.CurrentType, loc); if (targs_for_instance != null) { del_type_instance_access = null; } else { del_type_instance_access = del_type; } } else { d = null; } var site_type_decl = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc); var field = site_container.CreateCallSiteField (site_type_decl, loc); if (field == null) return; if (del_type_instance_access == null) { var dt = d.CurrentType.DeclaringType.MakeGenericType (module, context_mvars.Types); del_type_instance_access = new TypeExpression (MemberCache.GetMember (dt, d.CurrentType), loc); } var instanceAccessExprType = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type_instance_access), loc); if (instanceAccessExprType.ResolveAsType (ec.MemberContext) == null) return; bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired; TypeSpec gt; if (inflate_using_mvar || context_mvars == null) { gt = site_container.CurrentType; } else { gt = site_container.CurrentType.MakeGenericType (module, context_mvars.Types); } // When site container already exists the inflated version has to be // updated manually to contain newly created field if (gt is InflatedTypeSpec && site_container.AnonymousMethodsCounter > 1) { var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes; var inflator = new TypeParameterInflator (module, gt, tparams, gt.TypeArguments); gt.MemberCache.AddMember (field.InflateMember (inflator)); } FieldExpr site_field_expr = new FieldExpr (MemberCache.GetMember (gt, field), loc); BlockContext bc = new BlockContext (ec.MemberContext, null, ec.BuiltinTypes.Void); Arguments args = new Arguments (1); args.Add (new Argument (binder)); StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args))); using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) { var conditionalAccessReceiver = IsConditionalAccessReceiver; var ca = ec.ConditionalAccess; if (conditionalAccessReceiver) { ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ()) { Statement = isStatement }; // // Emit conditional access expressions before dynamic call // is initialized. It pushes site_field_expr on stack before // the actual instance argument is emited which would cause // jump from non-empty stack. // EmitConditionalAccess (ec); } if (s.Resolve (bc)) { Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc)), s, loc); init.Emit (ec); } args = new Arguments (1 + dyn_args_count); args.Add (new Argument (site_field_expr)); if (arguments != null) { int arg_pos = 1; foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add (new Argument (a.Expr, a.ArgType)); } else { args.Add (a); } if (inflate_using_mvar && a.Type != targs[arg_pos].Type) a.Expr.Type = targs[arg_pos].Type; ++arg_pos; } } var target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, false, loc).Resolve (bc); if (target != null) { target.Emit (ec); } if (conditionalAccessReceiver) { ec.CloseConditionalAccess (!isStatement && type.IsNullableType ? type : null); ec.ConditionalAccess = ca; } } }