public override void Visit(Field f) { var location = LocationsBag.GetMemberLocation(f); var newField = new FieldDeclaration(); AddAttributeSection(newField, f); AddModifiers(newField, location); newField.AddChild(ConvertToType(f.TypeExpression), Roles.Type); var variable = new VariableInitializer(); variable.AddChild(Identifier.Create(f.MemberName.Name, Convert(f.MemberName.Location)), Roles.Identifier); int locationIdx = 0; if (f.Initializer != null) { if (location != null) variable.AddChild(new CSharpTokenNode(Convert(location [locationIdx++]), Roles.Assign), Roles.Assign); variable.AddChild((Expression)f.Initializer.Accept(this), Roles.Expression); } newField.AddChild(variable, Roles.Variable); if (f.Declarators != null) { foreach (var decl in f.Declarators) { var declLoc = LocationsBag.GetLocations(decl); if (declLoc != null) newField.AddChild(new CSharpTokenNode(Convert(declLoc [0]), Roles.Comma), Roles.Comma); variable = new VariableInitializer(); variable.AddChild(Identifier.Create(decl.Name.Value, Convert(decl.Name.Location)), Roles.Identifier); if (decl.Initializer != null) { if (declLoc != null) variable.AddChild(new CSharpTokenNode(Convert(declLoc [1]), Roles.Assign), Roles.Assign); variable.AddChild((Expression)decl.Initializer.Accept(this), Roles.Expression); } newField.AddChild(variable, Roles.Variable); } } if (location != null && location.Count > locationIdx) newField.AddChild(new CSharpTokenNode(Convert(location [locationIdx++]), Roles.Semicolon), Roles.Semicolon); typeStack.Peek().AddChild(newField, Roles.TypeMemberRole); }
public override bool Define () { if (!base.Define ()) return false; MetaType[] required_modifier = null; if ((ModFlags & Modifiers.VOLATILE) != 0) { var mod = Module.PredefinedTypes.IsVolatile.Resolve (); if (mod != null) required_modifier = new MetaType[] { mod.GetMetaInfo () }; } FieldBuilder = Parent.TypeBuilder.DefineField ( Name, member_type.GetMetaInfo (), required_modifier, null, ModifiersExtensions.FieldAttr (ModFlags)); spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags); // // Don't cache inaccessible fields except for struct where we // need them for definitive assignment checks // if ((ModFlags & Modifiers.BACKING_FIELD) == 0 || Parent.Kind == MemberKind.Struct) { Parent.MemberCache.AddMember (spec); } if (initializer != null) { Parent.RegisterFieldForInitialization (this, new FieldInitializer (this, initializer, TypeExpression.Location)); } if (declarators != null) { foreach (var d in declarators) { var f = new Field (Parent, d.GetFieldTypeExpression (this), ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); if (d.Initializer != null) f.initializer = d.Initializer; f.Define (); Parent.PartialContainer.Members.Add (f); } } return true; }
protected override Expression DoResolve (ResolveContext ec) { var expr = base.DoResolve (ec); if (expr == null) return ErrorExpression.Instance; if (ec.IsInProbingMode) return expr; // // Cache any static delegate creation // if (method_group.InstanceExpression != null) return expr; // // Cannot easily cache types with MVAR // if (!HasMvar ()) return expr; // // Create type level cache for a delegate instance // var parent = ec.CurrentMemberDefinition.Parent.PartialContainer; int id = parent.MethodGroupsCounter++; mg_cache = new Field (parent, new TypeExpression (type, loc), Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "mg$cache", id), loc), null); mg_cache.Define (); parent.AddField (mg_cache); return expr; }
public virtual void Visit (Field f) { }
protected HoistedVariable (AnonymousMethodStorey storey, Field field) { this.storey = storey; this.field = field; }
public HoistedThis (AnonymousMethodStorey storey, Field field) : base (storey, field) { }
public static AnonymousTypeClass Create (TypeContainer parent, IList<AnonymousTypeParameter> parameters, Location loc) { string name = ClassNamePrefix + parent.Module.CounterAnonymousTypes++; ParametersCompiled all_parameters; TypeParameters tparams = null; SimpleName[] t_args; if (parameters.Count == 0) { all_parameters = ParametersCompiled.EmptyReadOnlyParameters; t_args = null; } else { t_args = new SimpleName[parameters.Count]; tparams = new TypeParameters (); Parameter[] ctor_params = new Parameter[parameters.Count]; for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = parameters[i]; for (int ii = 0; ii < i; ++ii) { if (parameters[ii].Name == p.Name) { parent.Compiler.Report.Error (833, parameters[ii].Location, "`{0}': An anonymous type cannot have multiple properties with the same name", p.Name); p = new AnonymousTypeParameter (null, "$" + i.ToString (), p.Location); parameters[i] = p; break; } } t_args[i] = new SimpleName ("<" + p.Name + ">__T", p.Location); tparams.Add (new TypeParameter (i, new MemberName (t_args[i].Name, p.Location), null, null, Variance.None)); ctor_params[i] = new Parameter (t_args[i], p.Name, Parameter.Modifier.NONE, null, p.Location); } all_parameters = new ParametersCompiled (ctor_params); } // // Create generic anonymous type host with generic arguments // named upon properties names // AnonymousTypeClass a_type = new AnonymousTypeClass (parent.Module, new MemberName (name, tparams, loc), parameters, loc); Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, null, all_parameters, loc); c.Block = new ToplevelBlock (parent.Module.Compiler, c.ParameterInfo, loc); // // Create fields and constructor body with field initialization // bool error = false; for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = parameters [i]; Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY | Modifiers.DEBUGGER_HIDDEN, new MemberName ("<" + p.Name + ">", p.Location), null); if (!a_type.AddField (f)) { error = true; continue; } c.Block.AddStatement (new StatementExpression ( new SimpleAssign (new MemberAccess (new This (p.Location), f.Name), c.Block.GetParameterReference (i, p.Location)))); ToplevelBlock get_block = new ToplevelBlock (parent.Module.Compiler, p.Location); get_block.AddStatement (new Return ( new MemberAccess (new This (p.Location), f.Name), p.Location)); Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC, new MemberName (p.Name, p.Location), null); prop.Get = new Property.GetMethod (prop, 0, null, p.Location); prop.Get.Block = get_block; a_type.AddMember (prop); } if (error) return null; a_type.AddConstructor (c); return a_type; }
protected Field AddCompilerGeneratedField (string name, FullNamedExpression type, bool privateAccess) { Modifiers mod = Modifiers.COMPILER_GENERATED | (privateAccess ? Modifiers.PRIVATE : Modifiers.INTERNAL); Field f = new Field (this, type, mod, new MemberName (name, Location), null); AddField (f); return f; }
public override void Emit (EmitContext ec) { // // Use same anonymous method implementation for scenarios where same // code is used from multiple blocks, e.g. field initializers // if (method == null) { // // Delay an anonymous method definition to avoid emitting unused code // for unreachable blocks or expression trees // method = DoCreateMethodHost (ec); method.Define (); method.PrepareEmit (); } bool is_static = (method.ModFlags & Modifiers.STATIC) != 0; if (is_static && am_cache == null && !ec.IsStaticConstructor) { // // Creates a field cache to store delegate instance if it's not generic // if (!method.MemberName.IsGeneric) { var parent = method.Parent.PartialContainer; int id = parent.AnonymousMethodsCounter++; var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type; am_cache = new Field (parent, new TypeExpression (cache_type, loc), Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null); am_cache.Define (); parent.AddField (am_cache); } else { // TODO: Implement caching of generated generic static methods // // Idea: // // Some extra class is needed to capture variable generic type // arguments. Maybe we could re-use anonymous types, with a unique // anonymous method id, but they are quite heavy. // // Consider : "() => typeof(T);" // // We need something like // static class Wrap<Tn, Tm, DelegateType> { // public static DelegateType cache; // } // // We then specialize local variable to capture all generic parameters // and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;" // } } Label l_initialized = ec.DefineLabel (); if (am_cache != null) { ec.Emit (OpCodes.Ldsfld, am_cache.Spec); ec.Emit (OpCodes.Brtrue_S, l_initialized); } // // Load method delegate implementation // if (is_static) { ec.EmitNull (); } else if (storey != null) { Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); if (e != null) { e.Emit (ec); } } else { ec.EmitThis (); // // Special case for value type storey where this is not lifted but // droped off to parent class // if (ec.CurrentAnonymousMethod != null && ec.AsyncTaskStorey != null) ec.Emit (OpCodes.Ldfld, ec.AsyncTaskStorey.HoistedThis.Field.Spec); } var delegate_method = method.Spec; if (storey != null && storey.MemberName.IsGeneric) { TypeSpec t = storey.Instance.Type; // // Mutate anonymous method instance type if we are in nested // hoisted generic anonymous method storey // if (ec.IsAnonymousStoreyMutateRequired) { t = storey.Mutator.Mutate (t); } ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ())); } else { if (delegate_method.IsGeneric) { TypeParameterSpec[] tparams; var sm = ec.CurrentAnonymousMethod == null ? null : ec.CurrentAnonymousMethod.Storey as StateMachine; if (sm != null && sm.OriginalTypeParameters != null) { tparams = sm.CurrentTypeParameters.Types; } else { tparams = method.TypeParameters; } delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, tparams); } ec.Emit (OpCodes.Ldftn, delegate_method); } var constructor_method = Delegate.GetConstructor (type); ec.Emit (OpCodes.Newobj, constructor_method); if (am_cache != null) { ec.Emit (OpCodes.Stsfld, am_cache.Spec); ec.MarkLabel (l_initialized); ec.Emit (OpCodes.Ldsfld, am_cache.Spec); } }
public StoreyFieldPair (AnonymousMethodStorey storey, Field field) { this.Storey = storey; this.Field = field; }
public override bool Define() { var mod_flags_src = ModFlags; if (!base.Define ()) return false; if (declarators != null) { if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFIER); var t = new TypeExpression (MemberType, TypeExpression.Location); foreach (var d in declarators) { var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); if (d.Initializer != null) ef.initializer = d.Initializer; ef.Define (); Parent.PartialContainer.Members.Add (ef); } } if (!HasBackingField) { SetIsUsed (); return true; } backing_field = new Field (Parent, new TypeExpression (MemberType, Location), Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), MemberName, null); Parent.PartialContainer.Members.Add (backing_field); backing_field.Initializer = Initializer; backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED; // Call define because we passed fields definition backing_field.Define (); // Set backing field for event fields spec.BackingField = backing_field.Spec; return true; }
public HoistedEvaluatorVariable (Field field) : base (null, field) { }
public PrimaryConstructorAssign (Field field, Parameter parameter) : base (null, null, parameter.Location) { this.field = field; this.parameter = parameter; }