public override void InjectYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) { // Store the new value into current var fe = new FieldExpr(((IteratorStorey)storey).CurrentField, loc); fe.InstanceExpression = new CompilerGeneratedThis(storey.CurrentType, loc); fe.EmitAssign(ec, expr, false, false); base.InjectYield(ec, expr, resume_pc, unwind_protect, resume_point); EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); }
public void EmitAwaitOnCompletedDynamic(EmitContext ec, FieldExpr awaiter) { var critical = Module.PredefinedTypes.ICriticalNotifyCompletion; if (!critical.Define()) { throw new NotImplementedException(); } var temp_critical = new LocalTemporary(critical.TypeSpec); var label_critical = ec.DefineLabel(); var label_end = ec.DefineLabel(); // // Special path for dynamic awaiters // // var awaiter = this.$awaiter as ICriticalNotifyCompletion; // if (awaiter == null) { // var completion = (INotifyCompletion) this.$awaiter; // this.$builder.AwaitOnCompleted (ref completion, ref this); // } else { // this.$builder.AwaitUnsafeOnCompleted (ref awaiter, ref this); // } // awaiter.Emit(ec); ec.Emit(OpCodes.Isinst, critical.TypeSpec); temp_critical.Store(ec); temp_critical.Emit(ec); ec.Emit(OpCodes.Brtrue_S, label_critical); var temp = new LocalTemporary(Module.PredefinedTypes.INotifyCompletion.TypeSpec); awaiter.Emit(ec); ec.Emit(OpCodes.Castclass, temp.Type); temp.Store(ec); EmitOnCompleted(ec, temp, false); temp.Release(ec); ec.Emit(OpCodes.Br_S, label_end); ec.MarkLabel(label_critical); EmitOnCompleted(ec, temp_critical, true); ec.MarkLabel(label_end); temp_critical.Release(ec); }
public static Expression AddFiled(string fieldAlias, string tableAlias, string schema, Lexem lexem, ExpressionParser parser) { if (fieldAlias == "*") { if (schema != null) { parser.Collection.Error("Can not use schema in * expression", lexem); } AllColumnExpr a = new AllColumnExpr(); a.Prefix = tableAlias; return(a); } FieldExpr res = new FieldExpr(); res.FieldName = fieldAlias; res.TableAlias = tableAlias; res.Schema = schema; res.Lexem = lexem; return(res); }
public Expression GetResultExpression(EmitContext ec) { var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); // // result = awaiter.GetResult (); // if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); return(new Invocation(new MemberAccess(fe_awaiter, "GetResult"), new Arguments(0)).Resolve(rc)); } var mg_result = MethodGroupExpr.CreatePredefined(awaiter_definition.GetResult, fe_awaiter.Type, loc); mg_result.InstanceExpression = fe_awaiter; return(new GetResultInvocation(mg_result, new Arguments(0))); }
public void EmitAssign(EmitContext ec, FieldExpr field) { stmt.EmitPrologue(ec); field.InstanceExpression.Emit(ec); stmt.Emit(ec); }
// // Creates field access expression for hoisted variable // protected virtual FieldExpr GetFieldExpression (EmitContext ec) { if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) { if (cached_outer_access != null) return cached_outer_access; // // When setting top-level hoisted variable in generic storey // change storey generic types to method generic types (VAR -> MVAR) // if (storey.Instance.Type.IsGenericOrParentIsGeneric) { var fs = MemberCache.GetMember (storey.Instance.Type, field.Spec); cached_outer_access = new FieldExpr (fs, field.Location); } else { cached_outer_access = new FieldExpr (field, field.Location); } cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); return cached_outer_access; } FieldExpr inner_access; if (cached_inner_access != null) { if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access)) inner_access = null; } else { inner_access = null; cached_inner_access = new Dictionary<AnonymousExpression, FieldExpr> (4); } if (inner_access == null) { if (field.Parent.IsGenericOrParentIsGeneric) { var fs = MemberCache.GetMember (field.Parent.CurrentType, field.Spec); inner_access = new FieldExpr (fs, field.Location); } else { inner_access = new FieldExpr (field, field.Location); } inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access); } return inner_access; }
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"; TypeExpr 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.Type, new TypeArguments(targs), loc); if (targs_for_instance != null) { del_type_instance_access = new GenericTypeExpr(te.Type, 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(); site.AddTypeContainer(d); 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)) { 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; } } Expression target = new DelegateInvocation(new MemberAccess(site_field_expr, "Target", loc).Resolve(bc), args, loc).Resolve(bc); if (target != null) { target.Emit(ec); } } }
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"; TypeExpr 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.Type, new TypeArguments (targs), loc); if (targs_for_instance != null) del_type_instance_access = new GenericTypeExpr (te.Type, 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 (); site.AddTypeContainer (d); 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)) { 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; } } Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); if (target != null) target.Emit (ec); } }
void CreateAutomaticProperty () { // Create backing field BackingField = new BackingFieldDeclaration (this, Initializer == null && Set == null); if (!BackingField.Define ()) return; if (Initializer != null) { BackingField.Initializer = Initializer; Parent.RegisterFieldForInitialization (BackingField, new FieldInitializer (BackingField, Initializer, Location)); BackingField.ModFlags |= Modifiers.READONLY; } Parent.PartialContainer.Members.Add (BackingField); FieldExpr fe = new FieldExpr (BackingField, Location); if ((BackingField.ModFlags & Modifiers.STATIC) == 0) fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); // // Create get block but we careful with location to // emit only single sequence point per accessor. This allow // to set a breakpoint on it even with no user code // Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null); Return r = new Return (fe, Get.Location); Get.Block.AddStatement (r); Get.ModFlags |= Modifiers.COMPILER_GENERATED; // Create set block if (Set != null) { Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null); Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null); Set.Block.AddStatement (new StatementExpression (a, Set.Location)); Set.ModFlags |= Modifiers.COMPILER_GENERATED; } }
protected override Expression DoResolve(ResolveContext rc) { target = new FieldExpr(field, loc); source = rc.CurrentBlock.ParametersBlock.GetParameterInfo(parameter).CreateReferenceExpression(rc, loc); return(base.DoResolve(rc)); }
protected override void DoEmit (EmitContext ec) { Expression source; if (parent == null) source = new CompilerGeneratedThis (ec.CurrentType, loc); else { source = new FieldExpr (parent.HoistedThis.Field, Location.Null) { InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null) }; } hoisted_this.EmitAssign (ec, source, false, false); }
void FabricateBodyStatement () { // // Delegate obj1 = backing_field // do { // Delegate obj2 = obj1; // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); // } while ((object)obj1 != (object)obj2) // var field_info = ((EventField) method).backing_field; FieldExpr f_expr = new FieldExpr (field_info, Location); if (!IsStatic) f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location), new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location))); var body = new ExplicitBlock (block, Location, Location); block.AddStatement (new Do (body, cond, Location, Location)); body.AddStatement (new StatementExpression ( new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); var args_oper = new Arguments (2); args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); args_oper.Add (new Argument (block.GetParameterReference (0, Location))); var op_method = GetOperation (Location); var args = new Arguments (3); args.Add (new Argument (f_expr, Argument.AType.Ref)); args.Add (new Argument (new Cast ( new TypeExpression (field_info.MemberType, Location), new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper), Location))); args.Add (new Argument (new LocalVariableReference (obj1, Location))); var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location); if (cas == null) return; body.AddStatement (new StatementExpression (new SimpleAssign ( new LocalVariableReference (obj1, Location), new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); }
public void EmitPrologue(EmitContext ec) { awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type); var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); Label skip_continuation = ec.DefineLabel(); using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) { // // awaiter = expr.GetAwaiter (); // fe_awaiter.EmitAssign(ec, expr, false, false); Expression completed_expr; if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); Arguments dargs = new Arguments(1); dargs.Add(new Argument(fe_awaiter)); completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc); dargs = new Arguments(1); dargs.Add(new Argument(completed_expr)); completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc); } else { var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc); pe.InstanceExpression = fe_awaiter; completed_expr = pe; } completed_expr.EmitBranchable(ec, skip_continuation, true); } base.DoEmit(ec); // // The stack has to be empty before calling await continuation. We handle this // by lifting values which would be left on stack into class fields. The process // is quite complicated and quite hard to test because any expression can possibly // leave a value on the stack. // // Following assert fails when some of expression called before is missing EmitToField // or parent expression fails to find await in children expressions // ec.AssertEmptyStack(); var storey = (AsyncTaskStorey)machine_initializer.Storey; if (IsDynamic) { storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter); } else { storey.EmitAwaitOnCompleted(ec, fe_awaiter); } // Return ok machine_initializer.EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); ec.MarkLabel(skip_continuation); }
// // Creates storey instance expression regardless of currect IP // public Expression GetStoreyInstanceExpression (EmitContext ec) { AnonymousExpression am = ec.CurrentAnonymousMethod; // // Access from original block -> storey // if (am == null) return Instance; // // Access from anonymous method implemented as a static -> storey // if (am.Storey == null) return Instance; Field f = am.Storey.GetReferencedStoreyField (this); if (f == null) { if (am.Storey == this) { // // Access from inside of same storey (S -> S) // return new CompilerGeneratedThis (CurrentType, Location); } // // External field access // return Instance; } // // Storey was cached to local field // FieldExpr f_ind = new FieldExpr (f, Location); f_ind.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location); return f_ind; }
protected virtual void EmitHoistedParameters (EmitContext ec, List<HoistedParameter> hoisted) { foreach (HoistedParameter hp in hoisted) { if (hp == null) continue; // // Parameters could be proxied via local fields for value type storey // if (hoisted_local_params != null) { var local_param = hoisted_local_params.Find (l => l.Parameter.Parameter == hp.Parameter.Parameter); var source = new FieldExpr (local_param.Field, Location); source.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location); hp.EmitAssign (ec, source, false, false); continue; } hp.EmitHoistingAssignment (ec); } }
void EmitHoistedFieldsInitialization (ResolveContext rc, EmitContext ec) { // // Initialize all storey reference fields by using local or hoisted variables // if (used_parent_storeys != null) { foreach (StoreyFieldPair sf in used_parent_storeys) { // // Get instance expression of storey field // Expression instace_expr = GetStoreyInstanceExpression (ec); var fs = sf.Field.Spec; if (TypeManager.IsGenericType (instace_expr.Type)) fs = MemberCache.GetMember (instace_expr.Type, fs); FieldExpr f_set_expr = new FieldExpr (fs, Location); f_set_expr.InstanceExpression = instace_expr; // TODO: CompilerAssign expression SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec)); if (a.Resolve (rc) != null) a.EmitStatement (ec); } } // // Initialize hoisted `this' only once, everywhere else will be // referenced indirectly // if (initialize_hoisted_this) { rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent)); } // // Setting currect anonymous method to null blocks any further variable hoisting // AnonymousExpression ae = ec.CurrentAnonymousMethod; ec.CurrentAnonymousMethod = null; if (hoisted_params != null) { EmitHoistedParameters (ec, hoisted_params); } ec.CurrentAnonymousMethod = ae; }
// // Initializes all hoisted variables // public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block) { // There can be only one instance variable for each storey type if (Instance != null) throw new InternalErrorException (); // // Create an instance of this storey // ResolveContext rc = new ResolveContext (ec.MemberContext); rc.CurrentBlock = block; var storey_type_expr = CreateStoreyTypeExpression (ec); var source = new New (storey_type_expr, null, Location).Resolve (rc); // // When the current context is async (or iterator) lift local storey // instantiation to the currect storey // if (ec.CurrentAnonymousMethod is StateMachineInitializer && (block.HasYield || block.HasAwait)) { // // Unfortunately, normal capture mechanism could not be used because we are // too late in the pipeline and standart assign cannot be used either due to // recursive nature of GetStoreyInstanceExpression // var field = ec.CurrentAnonymousMethod.Storey.AddCompilerGeneratedField ( LocalVariable.GetCompilerGeneratedName (block), storey_type_expr, true); field.Define (); field.Emit (); var fexpr = new FieldExpr (field, Location); fexpr.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location); fexpr.EmitAssign (ec, source, false, false); Instance = fexpr; } else { var local = TemporaryVariableReference.Create (source.Type, block, Location); if (source.Type.IsStruct) { local.LocalInfo.CreateBuilder (ec); } else { local.EmitAssign (ec, source); } Instance = local; } EmitHoistedFieldsInitialization (rc, ec); // TODO: Implement properly //SymbolWriter.DefineScopeVariable (ID, Instance.Builder); }
void CreateAutomaticProperty () { // Create backing field Field field = new BackingField (this); if (!field.Define ()) return; Parent.PartialContainer.Members.Add (field); FieldExpr fe = new FieldExpr (field, Location); if ((field.ModFlags & Modifiers.STATIC) == 0) fe.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); // // Create get block but we careful with location to // emit only single sequence point per accessor. This allow // to set a breakpoint on it even with no user code // Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null); Return r = new Return (fe, Get.Location); Get.Block.AddStatement (r); // Create set block Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location.Null); Assign a = new SimpleAssign (fe, new SimpleName ("value", Location.Null), Location.Null); Set.Block.AddStatement (new StatementExpression (a, Set.Location)); }
protected override Expression DoResolve (ResolveContext rc) { target = new FieldExpr (field, loc); source = rc.CurrentBlock.ParametersBlock.GetParameterInfo (parameter).CreateReferenceExpression (rc, loc); return base.DoResolve (rc); }