/// <remarks> /// 7.5.2: Simple Names. /// /// Local Variables and Parameters are handled at /// parse time, so they never occur as SimpleNames. /// /// The `intermediate' flag is used by MemberAccess only /// and it is used to inform us that it is ok for us to /// avoid the static check, because MemberAccess might end /// up resolving the Name as a Type name and the access as /// a static type access. /// /// ie: Type Type; .... { Type.GetType (""); } /// /// Type is both an instance variable and a Type; Type.GetType /// is the static method not an instance method of type. /// </remarks> Expression DoSimpleNameResolve(ResolveContext ec, Expression right_side, bool intermediate) { Expression e = null; // // Stage 1: Performed by the parser (binding to locals or parameters). // Block current_block = ec.CurrentBlock; if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ e = new LocalVariableReference (ec.CurrentBlock, Name, loc); if (right_side != null) { e = e.ResolveLValue (ec, right_side); } else { if (intermediate) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { e = e.Resolve (ec, ResolveFlags.VariableOrValue); } } else { e = e.Resolve (ec, ResolveFlags.VariableOrValue); } } if (HasTypeArguments && e != null) e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0); return e; } e = current_block.Toplevel.GetParameterReference (Name, loc); if (e != null) { if (right_side != null) e = e.ResolveLValue (ec, right_side); else e = e.Resolve (ec); if (HasTypeArguments && e != null) e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0); return e; } } // // Stage 2: Lookup members // int arity = HasTypeArguments ? Arity : -1; // TypeSpec almost_matched_type = null; // IList<MemberSpec> almost_matched = null; for (TypeSpec lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) { e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, arity, BindingRestriction.NoOverrides, loc); if (e != null) { PropertyExpr pe = e as PropertyExpr; if (pe != null) { // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not, // it doesn't know which accessor to check permissions against if (pe.PropertyInfo.Kind == MemberKind.Property && pe.IsAccessibleFrom (ec.CurrentType, right_side != null)) break; } else if (e is EventExpr) { if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType)) break; } else if (HasTypeArguments && e is TypeExpression) { e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false); break; } else { break; } e = null; } /* if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = lookup_ds; almost_matched = new List<MemberSpec>(almost_matched_members); } */ } if (e == null) { /* if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = ec.CurrentType; almost_matched = new List<MemberSpec> (almost_matched_members); } */ e = ResolveAsTypeStep (ec, true); } if (e == null) { if (current_block != null) { IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name); if (ikv != null) { LocalInfo li = ikv as LocalInfo; // Supress CS0219 warning if (li != null) li.Used = true; Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name); return null; } } if (RootContext.EvalMode){ FieldInfo fi = Evaluator.LookupField (Name); if (fi != null) return new FieldExpr (Import.CreateField (fi, null), loc).Resolve (ec); } /* if (almost_matched != null) almost_matched_members = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.CurrentType; */ string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name; return Error_MemberLookupFailed (ec, ec.CurrentType, null, ec.CurrentType, Name, arity, type_name, MemberKind.All, BindingRestriction.AccessibleOnly); } if (e is MemberExpr) { MemberExpr me = (MemberExpr) e; Expression left; if (me.IsInstance) { if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) { // // Note that an MemberExpr can be both IsInstance and IsStatic. // An unresolved MethodGroupExpr can contain both kinds of methods // and each predicate is true if the MethodGroupExpr contains // at least one of that kind of method. // /* if (!me.IsStatic && (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) { Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ()); return null; } */ // // Pass the buck to MemberAccess and Invocation. // left = EmptyExpression.Null; } else { left = ec.GetThis (loc); } } else { left = new TypeExpression (ec.CurrentType, loc); } me = me.ResolveMemberAccess (ec, left, loc, null); if (me == null) return null; if (HasTypeArguments) { if (!targs.Resolve (ec)) return null; me.SetTypeArguments (ec, targs); } if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) { ec.Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type)); return null; } return (right_side != null) ? me.DoResolveLValue (ec, right_side) : me.Resolve (ec); } return e; }
/// <remarks> /// 7.5.2: Simple Names. /// /// Local Variables and Parameters are handled at /// parse time, so they never occur as SimpleNames. /// /// The `intermediate' flag is used by MemberAccess only /// and it is used to inform us that it is ok for us to /// avoid the static check, because MemberAccess might end /// up resolving the Name as a Type name and the access as /// a static type access. /// /// ie: Type Type; .... { Type.GetType (""); } /// /// Type is both an instance variable and a Type; Type.GetType /// is the static method not an instance method of type. /// </remarks> Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate) { Expression e = null; // // Stage 1: Performed by the parser (binding to locals or parameters). // Block current_block = ec.CurrentBlock; if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc); if (right_side != null) { return var.ResolveLValue (ec, right_side, loc); } else { ResolveFlags rf = ResolveFlags.VariableOrValue; if (intermediate) rf |= ResolveFlags.DisableFlowAnalysis; return var.Resolve (ec, rf); } } Expression expr = current_block.Toplevel.GetParameterReference (Name, loc); if (expr != null) { if (right_side != null) return expr.ResolveLValue (ec, right_side, loc); return expr.Resolve (ec); } } // // Stage 2: Lookup members // Type almost_matched_type = null; ArrayList almost_matched = null; for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) { // either RootDeclSpace or GenericMethod if (lookup_ds.TypeBuilder == null) continue; e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc); if (e != null) { PropertyExpr pe = e as PropertyExpr; if (pe != null) { AParametersCollection param = TypeManager.GetParameterData (pe.PropertyInfo); // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not, // it doesn't know which accessor to check permissions against if (param.IsEmpty && pe.IsAccessibleFrom (ec.ContainerType, right_side != null)) break; } else if (e is EventExpr) { if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType)) break; } else if (targs != null && e is TypeExpression) { e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false); break; } else { break; } e = null; } if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = lookup_ds.TypeBuilder; almost_matched = (ArrayList) almost_matched_members.Clone (); } } if (e == null) { if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = ec.ContainerType; almost_matched = (ArrayList) almost_matched_members.Clone (); } e = ResolveAsTypeStep (ec, true); } if (e == null) { if (current_block != null) { IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name); if (ikv != null) { LocalInfo li = ikv as LocalInfo; // Supress CS0219 warning if (li != null) li.Used = true; Error_VariableIsUsedBeforeItIsDeclared (Name); return null; } } if (RootContext.EvalMode){ FieldInfo fi = Evaluator.LookupField (Name); if (fi != null) return new FieldExpr (fi, loc).Resolve (ec); } if (almost_matched != null) almost_matched_members = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.ContainerType; return Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name, ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags); } if (e is MemberExpr) { MemberExpr me = (MemberExpr) e; Expression left; if (me.IsInstance) { if (ec.IsStatic || ec.IsInFieldInitializer) { // // Note that an MemberExpr can be both IsInstance and IsStatic. // An unresolved MethodGroupExpr can contain both kinds of methods // and each predicate is true if the MethodGroupExpr contains // at least one of that kind of method. // if (!me.IsStatic && (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) { Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ()); return null; } // // Pass the buck to MemberAccess and Invocation. // left = EmptyExpression.Null; } else { left = ec.GetThis (loc); } } else { left = new TypeExpression (ec.ContainerType, loc); } me = me.ResolveMemberAccess (ec, left, loc, null); if (me == null) return null; if (targs != null) { if (!targs.Resolve (ec)) return null; me.SetTypeArguments (targs); } if (!me.IsStatic && (me.InstanceExpression != null) && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) { Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type)); return null; } return (right_side != null) ? me.DoResolveLValue (ec, right_side) : me.DoResolve (ec); } return e; }
public override FullNamedExpression ResolveAsTypeStep(IMemberContext ec, bool silent) { int errors = ec.Compiler.Report.Errors; FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false); if (fne != null) { if (HasTypeArguments && fne.Type != null && TypeManager.IsGenericType (fne.Type)) { GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } return fne; } if (!HasTypeArguments && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3 && RootContext.MetadataCompatibilityVersion > MetadataVersion.v2) { if (!PredefinedAttributes.Get.Dynamic.IsDefined) { ec.Compiler.Report.Error (1980, Location, "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?", PredefinedAttributes.Get.Dynamic.GetSignatureForError ()); } return new DynamicTypeExpr (loc); } if (silent || errors != ec.Compiler.Report.Errors) return null; Error_TypeOrNamespaceNotFound (ec); return null; }
protected virtual bool DoResolveType () { if (!IsGeneric) return true; if (PartialContainer != this) throw new InternalErrorException (); TypeExpr current_type = null; if (CurrentTypeParameters != null) { foreach (TypeParameter type_param in CurrentTypeParameters) { if (!type_param.Resolve (this)) { error = true; return false; } } if (partial_parts != null) { foreach (TypeContainer part in partial_parts) UpdateTypeParameterConstraints (part); } } for (int i = 0; i < TypeParameters.Length; ++i) { // // FIXME: Same should be done for delegates // TODO: Quite ugly way how to propagate constraints to // nested types // if (nested_gen_params != null && i < nested_gen_params.Length) { TypeParameters [i].SetConstraints (nested_gen_params [i]); } else { if (!TypeParameters [i].DefineType (this)) { error = true; return false; } } } // TODO: Very strange, why not simple make generic type from // current type parameters current_type = new GenericTypeExpr (this, Location); current_type = current_type.ResolveAsTypeTerminal (this, false); if (current_type == null) { error = true; return false; } currentType = current_type.Type; return true; }
public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { FullNamedExpression fne = ec.GenericDeclContainer.LookupGeneric (Name, loc); if (fne != null) return fne.ResolveAsTypeStep (ec, silent); int errors = Report.Errors; fne = ec.DeclContainer.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false); if (fne != null) { if (fne.Type == null) return fne; FullNamedExpression nested = ResolveNested (ec, fne.Type); if (nested != null) return nested.ResolveAsTypeStep (ec, false); if (targs != null) { GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } return fne; } if (silent || errors != Report.Errors) return null; Error_TypeOrNamespaceNotFound (ec); return 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; } } }
protected override bool DoDefineMembers () { if (!base.DoDefineMembers ()) return false; Location loc = Location; var equals_parameters = ParametersCompiled.CreateFullyResolved ( new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object); Method equals = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), equals_parameters, null); equals_parameters[0].Resolve (equals, 0); Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); TypeExpr current_type; if (CurrentTypeParameters != null) { var targs = new TypeArguments (); for (int i = 0; i < CurrentTypeParameters.Count; ++i) { targs.Add (new TypeParameterExpr (CurrentTypeParameters[i], Location)); } current_type = new GenericTypeExpr (Definition, targs, loc); } else { current_type = new TypeExpression (Definition, loc); } var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc); equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other)); var other_variable = new LocalVariableReference (li_other, loc); MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); Expression rs_equals = null; Expression string_concat = new StringConstant (Compiler.BuiltinTypes, "{", loc); Expression rs_hashcode = new IntConstant (Compiler.BuiltinTypes, -2128831035, loc); for (int i = 0; i < parameters.Count; ++i) { var p = parameters [i]; var f = (Field) Members [i * 2]; MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( system_collections_generic, "EqualityComparer", new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc), "Default", loc); Arguments arguments_equal = new Arguments (2); arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); Expression field_equal = new Invocation (new MemberAccess (equality_comparer, "Equals", loc), arguments_equal); Arguments arguments_hashcode = new Arguments (1); arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, "GetHashCode", loc), arguments_hashcode); IntConstant FNV_prime = new IntConstant (Compiler.BuiltinTypes, 16777619, loc); rs_hashcode = new Binary (Binary.Operator.Multiply, new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode), FNV_prime); Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality, new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc))), new Invocation (new MemberAccess ( new MemberAccess (new This (f.Location), f.Name), "ToString"), null), new StringConstant (Compiler.BuiltinTypes, string.Empty, loc), loc); if (rs_equals == null) { rs_equals = field_equal; string_concat = new Binary (Binary.Operator.Addition, string_concat, new Binary (Binary.Operator.Addition, new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc), field_to_string)); continue; } // // Implementation of ToString () body using string concatenation // string_concat = new Binary (Binary.Operator.Addition, new Binary (Binary.Operator.Addition, string_concat, new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc)), field_to_string); rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal); } string_concat = new Binary (Binary.Operator.Addition, string_concat, new StringConstant (Compiler.BuiltinTypes, " }", loc)); // // Equals (object obj) override // var other_variable_assign = new TemporaryVariableReference (li_other, loc); equals_block.AddStatement (new StatementExpression ( new SimpleAssign (other_variable_assign, new As (equals_block.GetParameterReference (0, loc), current_type, loc), loc))); Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc)); if (rs_equals != null) equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals); equals_block.AddStatement (new Return (equals_test, loc)); equals.Block = equals_block; equals.Define (); Members.Add (equals); // // GetHashCode () override // Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform // distribution with larger hash sizes. // // const int FNV_prime = 16777619; // int hash = (int) 2166136261; // foreach (int d in data) // hash = (hash ^ d) * FNV_prime; // hash += hash << 13; // hash ^= hash >> 7; // hash += hash << 3; // hash ^= hash >> 17; // hash += hash << 5; ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc); Block hashcode_block = new Block (hashcode_top, loc, loc); hashcode_top.AddStatement (new Unchecked (hashcode_block, loc)); var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc); hashcode_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_hash.Type, loc), li_hash)); LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc); hashcode_block.AddStatement (new StatementExpression ( new SimpleAssign (hash_variable_assign, rs_hashcode))); var hash_variable = new LocalVariableReference (li_hash, loc); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc))))); hashcode_block.AddStatement (new Return (hash_variable, loc)); hashcode.Block = hashcode_top; hashcode.Define (); Members.Add (hashcode); // // ToString () override // ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); tostring_block.AddStatement (new Return (string_concat, loc)); tostring.Block = tostring_block; tostring.Define (); Members.Add (tostring); return true; }
Expression DoResolve (ResolveContext ec, Expression right_side) { if (type != null) throw new Exception (); // // Resolve the expression with flow analysis turned off, we'll do the definite // assignment checks later. This is because we don't know yet what the expression // will resolve to - it may resolve to a FieldExpr and in this case we must do the // definite assignment check on the actual field and not on the whole struct. // SimpleName original = expr as SimpleName; Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis); if (expr_resolved == null) return null; string LookupIdentifier = MemberName.MakeName (Name, targs); Namespace ns = expr_resolved as Namespace; if (ns != null) { FullNamedExpression retval = ns.Lookup (ec.Compiler, LookupIdentifier, loc); if (retval == null) ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, ec.Report); else if (targs != null) retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (ec, false); return retval; } Type expr_type = expr_resolved.Type; if (TypeManager.IsDynamicType (expr_type)) { Arguments args = new Arguments (2); args.Add (new Argument (expr_resolved.Resolve (ec))); if (right_side != null) args.Add (new Argument (right_side)); return new DynamicMemberBinder (right_side != null, Name, args, loc).Resolve (ec); } if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_type == TypeManager.null_type || expr_type == InternalType.AnonymousMethod) { Unary.Error_OperatorCannotBeApplied (ec, loc, ".", expr_type); return null; } Constant c = expr_resolved as Constant; if (c != null && c.GetValue () == null) { ec.Report.Warning (1720, 1, loc, "Expression will always cause a `{0}'", "System.NullReferenceException"); } if (targs != null) { if (!targs.Resolve (ec)) return null; } Expression member_lookup; member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, expr_type, expr_type, Name, loc); if (member_lookup == null && targs != null) { member_lookup = MemberLookup (ec.Compiler, ec.CurrentType, expr_type, expr_type, LookupIdentifier, loc); } if (member_lookup == null) { ExprClass expr_eclass = expr_resolved.eclass; // // Extension methods are not allowed on all expression types // if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable || expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess || expr_eclass == ExprClass.EventAccess) { ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc); if (ex_method_lookup != null) { ex_method_lookup.ExtensionExpression = expr_resolved; if (targs != null) { ex_method_lookup.SetTypeArguments (ec, targs); } return ex_method_lookup.DoResolve (ec); } } expr = expr_resolved; member_lookup = Error_MemberLookupFailed (ec, ec.CurrentType, expr_type, expr_type, Name, null, AllMemberTypes, AllBindingFlags); if (member_lookup == null) return null; } TypeExpr texpr = member_lookup as TypeExpr; if (texpr != null) { if (!(expr_resolved is TypeExpr) && (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) { ec.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", Name, member_lookup.GetSignatureForError ()); return null; } if (!texpr.CheckAccessLevel (ec.MemberContext)) { ec.Report.SymbolRelatedToPreviousError (member_lookup.Type); ErrorIsInaccesible (loc, TypeManager.CSharpName (member_lookup.Type), ec.Report); return null; } GenericTypeExpr ct = expr_resolved as GenericTypeExpr; if (ct != null) { // // When looking up a nested type in a generic instance // via reflection, we always get a generic type definition // and not a generic instance - so we have to do this here. // // See gtest-172-lib.cs and gtest-172.cs for an example. // TypeArguments nested_targs; if (HasTypeArguments) { nested_targs = ct.TypeArguments.Clone (); nested_targs.Add (targs); } else { nested_targs = ct.TypeArguments; } ct = new GenericTypeExpr (member_lookup.Type, nested_targs, loc); return ct.ResolveAsTypeStep (ec, false); } return member_lookup; } MemberExpr me = (MemberExpr) member_lookup; me = me.ResolveMemberAccess (ec, expr_resolved, loc, original); if (me == null) return null; if (targs != null) { me.SetTypeArguments (ec, targs); } if (original != null && !TypeManager.IsValueType (expr_type)) { if (me.IsInstance) { LocalVariableReference var = expr_resolved as LocalVariableReference; if (var != null && !var.VerifyAssigned (ec)) return null; } } // The following DoResolve/DoResolveLValue will do the definite assignment // check. if (right_side != null) return me.DoResolveLValue (ec, right_side); else return me.DoResolve (ec); }
public FullNamedExpression ResolveNamespaceOrType (IMemberContext rc, bool silent) { FullNamedExpression expr_resolved = expr.ResolveAsTypeStep (rc, silent); if (expr_resolved == null) return null; string LookupIdentifier = MemberName.MakeName (Name, targs); Namespace ns = expr_resolved as Namespace; if (ns != null) { FullNamedExpression retval = ns.Lookup (rc.Compiler, LookupIdentifier, loc); if (retval == null && !silent) ns.Error_NamespaceDoesNotExist (loc, LookupIdentifier, rc.Compiler.Report); else if (targs != null) retval = new GenericTypeExpr (retval.Type, targs, loc).ResolveAsTypeStep (rc, silent); return retval; } TypeExpr tnew_expr = expr_resolved.ResolveAsTypeTerminal (rc, false); if (tnew_expr == null) return null; Type expr_type = tnew_expr.Type; if (TypeManager.IsGenericParameter (expr_type)) { rc.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'", tnew_expr.GetSignatureForError ()); return null; } Expression member_lookup = MemberLookup (rc.Compiler, rc.CurrentType, expr_type, expr_type, LookupIdentifier, MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc); if (member_lookup == null) { if (silent) return null; Error_IdentifierNotFound (rc, expr_resolved, LookupIdentifier); return null; } TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (rc, false); if (texpr == null) return null; TypeArguments the_args = targs; Type declaring_type = texpr.Type.DeclaringType; if (TypeManager.HasGenericArguments (declaring_type) && !TypeManager.IsGenericTypeDefinition (expr_type)) { while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) { expr_type = expr_type.BaseType; } TypeArguments new_args = new TypeArguments (); foreach (Type decl in TypeManager.GetTypeArguments (expr_type)) new_args.Add (new TypeExpression (TypeManager.TypeToCoreType (decl), loc)); if (targs != null) new_args.Add (targs); the_args = new_args; } if (the_args != null) { GenericTypeExpr ctype = new GenericTypeExpr (texpr.Type, the_args, loc); return ctype.ResolveAsTypeStep (rc, false); } return texpr; }
protected bool CheckConstraint (IResolveContext ec, Type ptype, Expression expr, Type ctype) { if (TypeManager.HasGenericArguments (ctype)) { Type[] types = TypeManager.GetTypeArguments (ctype); TypeArguments new_args = new TypeArguments (); for (int i = 0; i < types.Length; i++) { Type t = types [i]; if (t.IsGenericParameter) { int pos = t.GenericParameterPosition; t = atypes [pos]; } new_args.Add (new TypeExpression (t, loc)); } TypeExpr ct = new GenericTypeExpr (ctype, new_args, loc); if (ct.ResolveAsTypeStep (ec, false) == null) return false; ctype = ct.Type; } else if (ctype.IsGenericParameter) { int pos = ctype.GenericParameterPosition; if (ctype.DeclaringMethod == null) { // FIXME: Implement return true; } else { ctype = atypes [pos]; } } if (Convert.ImplicitStandardConversionExists (expr, ctype)) return true; Report_SymbolRelatedToPreviousError (); Report.SymbolRelatedToPreviousError (expr.Type); if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) { Report.Error (313, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. " + "The nullable type `{0}' never satisfies interface constraint of type `{3}'", TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype), GetSignatureForError (), TypeManager.CSharpName (ctype)); } else { Report.Error (309, loc, "The type `{0}' must be convertible to `{1}' in order to " + "use it as parameter `{2}' in the generic type or method `{3}'", TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype), TypeManager.CSharpName (ptype), GetSignatureForError ()); } return false; }
public override Expression DoResolve (EmitContext ec) { AnonymousTypeClass anonymous_type; if (!ec.IsAnonymousMethodAllowed) { Report.Error (836, loc, "Anonymous types cannot be used in this expression"); return null; } if (parameters == null) { anonymous_type = CreateAnonymousType (EmptyParameters); return new New (new TypeExpression (anonymous_type.TypeBuilder, loc), null, loc).Resolve (ec); } bool error = false; ArrayList arguments = new ArrayList (parameters.Count); TypeExpression [] t_args = new TypeExpression [parameters.Count]; for (int i = 0; i < parameters.Count; ++i) { Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec); if (e == null) { error = true; continue; } arguments.Add (new Argument (e)); t_args [i] = new TypeExpression (e.Type, e.Location); } if (error) return null; anonymous_type = CreateAnonymousType (parameters); if (anonymous_type == null) return null; GenericTypeExpr te = new GenericTypeExpr (anonymous_type.TypeBuilder, new TypeArguments (t_args), loc); return new New (te, arguments, loc).Resolve (ec); }
TypeExpr CreateSiteType(EmitContext ec, Arguments arguments, int dyn_args_count, bool is_statement) { int default_args = is_statement ? 1 : 2; var module = ec.MemberContext.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); 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 = TypeManager.object_type; } targs [i + 1] = new TypeExpression(t, loc); } TypeExpr del_type = null; if (!has_ref_out_argument) { string d_name = is_statement ? "Action" : "Func"; TypeExpr te = null; Namespace type_ns = module.GlobalRootNamespace.GetNamespace("System", true); if (type_ns != null) { te = type_ns.LookupType(module.Compiler, d_name, dyn_args_count + default_args, true, Location.Null); } if (te != null) { if (!is_statement) { targs [targs.Length - 1] = new TypeExpression(type, loc); } del_type = new GenericTypeExpr(te.Type, new TypeArguments(targs), loc); } } // // Create custom delegate when no appropriate predefined one is found // if (del_type == null) { TypeSpec rt = is_statement ? TypeManager.void_type : 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.Types == null ? 0 : site.Types.Count; if (site.Mutator != null) { rt = site.Mutator.Mutate(rt); } for (int i = 1; i < dyn_args_count + 1; ++i) { var t = targs[i]; if (site.Mutator != null) { t.Type = site.Mutator.Mutate(t.Type); } p[i] = new Parameter(t, "p" + i.ToString("X"), arguments[i - 1].Modifier, null, loc); } Delegate d = new Delegate(site.NamespaceEntry, site, new TypeExpression(rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName("Container" + index.ToString("X")), new ParametersCompiled(p), null); d.CreateType(); d.DefineType(); d.Define(); d.Emit(); var inflated = site.AddDelegate(d); del_type = new TypeExpression(inflated, loc); } TypeExpr site_type = new GenericTypeExpr(module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments(del_type), loc); return(site_type); }
public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent) { int errors = ec.Compiler.Report.Errors; FullNamedExpression fne = ec.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false); if (fne != null) { if (fne.Type == null) return fne; FullNamedExpression nested = ResolveNested (fne.Type); if (nested != null) return nested.ResolveAsTypeStep (ec, false); if (targs != null) { if (TypeManager.IsGenericType (fne.Type)) { GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } Namespace.Error_TypeArgumentsCannotBeUsed (fne, loc); } return fne; } if (!HasTypeArguments && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) return new DynamicTypeExpr (loc); if (silent || errors != ec.Compiler.Report.Errors) return null; Error_TypeOrNamespaceNotFound (ec); return null; }
TypeExpr CreateSiteType (EmitContext ec, Arguments arguments, int dyn_args_count, bool is_statement) { int default_args = is_statement ? 1 : 2; bool has_ref_out_argument = false; var targs = new TypeExpression[dyn_args_count + default_args]; targs [0] = new TypeExpression (TypeManager.call_site_type, loc); 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; targs [i + 1] = new TypeExpression (a.Type, loc); } TypeExpr del_type = null; if (!has_ref_out_argument) { string d_name = is_statement ? "Action" : "Func"; TypeSpec t = TypeManager.CoreLookupType (ec.MemberContext.Compiler, "System", d_name, dyn_args_count + default_args, MemberKind.Delegate, false); if (t != null) { if (!is_statement) targs [targs.Length - 1] = new TypeExpression (type, loc); del_type = new GenericTypeExpr (t, new TypeArguments (targs), loc); } } // // Create custom delegate when no appropriate predefined one is found // if (del_type == null) { TypeSpec rt = is_statement ? TypeManager.void_type : 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.Types == null ? 0 : site.Types.Count; if (site.Mutator != null) rt = site.Mutator.Mutate (rt); for (int i = 1; i < dyn_args_count + 1; ++i) { var t = targs[i]; if (site.Mutator != null) t.Type = site.Mutator.Mutate (t.Type); p[i] = new Parameter (t, "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); } Delegate d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName ("Container" + index.ToString ("X")), new ParametersCompiled (p), null); d.CreateType (); d.DefineType (); d.Define (); d.Emit (); var inflated = site.AddDelegate (d); del_type = new TypeExpression (inflated, loc); } TypeExpr site_type = new GenericTypeExpr (TypeManager.generic_call_site_type, new TypeArguments (del_type), loc); return site_type; }
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) { TypeParameter[] 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, Location.Null); } 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.Types == null ? 0 : site.Types.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.NamespaceEntry, site, new TypeExpression(rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName("Container" + index.ToString("X")), new ParametersCompiled(p), null); d.CreateType(); d.DefineType(); d.Define(); d.Emit(); site.AddDelegate(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.Select(l => l.Type).ToArray()); del_type_instance_access = new TypeExpression(MemberCache.GetMember(dt, d.CurrentType), loc); } FullNamedExpression instanceAccessExprType = new GenericTypeExpr(module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments(del_type_instance_access), loc); BlockContext bc = new BlockContext(ec.MemberContext, null, ec.BuiltinTypes.Void); instanceAccessExprType = instanceAccessExprType.ResolveAsType(bc); if (instanceAccessExprType == 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.Select(l => l.Type).ToArray()); } // When site container already exists the inflated version has to be // updated manually to contain newly created field if (gt is InflatedTypeSpec && site_container.Fields.Count > 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); 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(instanceAccessExprType, "Create"), args))); 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) { 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); } SymbolWriter.CloseCompilerGeneratedBlock(ec); }
public override Expression DoResolve (ResolveContext ec) { if (ec.HasSet (ResolveContext.Options.ConstantScope)) { ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression"); return null; } if (parameters == null) { anonymous_type = CreateAnonymousType (ec, EmptyParameters); RequestedType = new TypeExpression (anonymous_type.TypeBuilder, loc); return base.DoResolve (ec); } bool error = false; Arguments = new Arguments (parameters.Count); TypeExpression [] t_args = new TypeExpression [parameters.Count]; for (int i = 0; i < parameters.Count; ++i) { Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec); if (e == null) { error = true; continue; } Arguments.Add (new Argument (e)); t_args [i] = new TypeExpression (e.Type, e.Location); } if (error) return null; anonymous_type = CreateAnonymousType (ec, parameters); if (anonymous_type == null) return null; RequestedType = new GenericTypeExpr (anonymous_type.TypeBuilder, new TypeArguments (t_args), loc); return base.DoResolve (ec); }
TypeExpr CreateSiteType(EmitContext ec, Arguments arguments, int dyn_args_count, bool is_statement) { int default_args = is_statement ? 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); 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 = TypeManager.object_type; targs [i + 1] = new TypeExpression (t, loc); } TypeExpr del_type = null; if (!has_ref_out_argument) { string d_name = is_statement ? "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, true, Location.Null); } if (te != null) { if (!is_statement) targs [targs.Length - 1] = new TypeExpression (type, loc); del_type = new GenericTypeExpr (te.Type, new TypeArguments (targs), loc); } } // // Create custom delegate when no appropriate predefined one is found // if (del_type == null) { TypeSpec rt = is_statement ? TypeManager.void_type : 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.Types == null ? 0 : site.Types.Count; if (site.Mutator != null) rt = site.Mutator.Mutate (rt); for (int i = 1; i < dyn_args_count + 1; ++i) { var t = targs[i]; if (site.Mutator != null) t.Type = site.Mutator.Mutate (t.Type); p[i] = new Parameter (t, "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); } Delegate d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName ("Container" + index.ToString ("X")), new ParametersCompiled (p), null); d.CreateType (); d.DefineType (); d.Define (); d.Emit (); var inflated = site.AddDelegate (d); del_type = new TypeExpression (inflated, loc); } TypeExpr site_type = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc); return site_type; }
void DefineOverrides () { Location loc = Location; Method equals = new Method (this, null, TypeManager.system_boolean_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), Mono.CSharp.ParametersCompiled.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null); Method tostring = new Method (this, null, TypeManager.system_string_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.Parameters, loc); TypeExpr current_type; if (IsGeneric) current_type = new GenericTypeExpr (this, loc); else current_type = new TypeExpression (TypeBuilder, loc); equals_block.AddVariable (current_type, "other", loc); LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc); MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); Expression rs_equals = null; Expression string_concat = new StringConstant ("{", loc); Expression rs_hashcode = new IntConstant (-2128831035, loc); for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i]; Field f = (Field) Fields [i]; MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( system_collections_generic, "EqualityComparer", new TypeArguments (new SimpleName (TypeParameters [i].Name, loc)), loc), "Default", loc); Arguments arguments_equal = new Arguments (2); arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); Expression field_equal = new Invocation (new MemberAccess (equality_comparer, "Equals", loc), arguments_equal); Arguments arguments_hashcode = new Arguments (1); arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, "GetHashCode", loc), arguments_hashcode); IntConstant FNV_prime = new IntConstant (16777619, loc); rs_hashcode = new Binary (Binary.Operator.Multiply, new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode), FNV_prime); Expression field_to_string = new Conditional (new Binary (Binary.Operator.Inequality, new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc)), new Invocation (new MemberAccess ( new MemberAccess (new This (f.Location), f.Name), "ToString"), null), new StringConstant (string.Empty, loc)); if (rs_equals == null) { rs_equals = field_equal; string_concat = new Binary (Binary.Operator.Addition, string_concat, new Binary (Binary.Operator.Addition, new StringConstant (" " + p.Name + " = ", loc), field_to_string)); continue; } // // Implementation of ToString () body using string concatenation // string_concat = new Binary (Binary.Operator.Addition, new Binary (Binary.Operator.Addition, string_concat, new StringConstant (", " + p.Name + " = ", loc)), field_to_string); rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal); } string_concat = new Binary (Binary.Operator.Addition, string_concat, new StringConstant (" }", loc)); // // Equals (object obj) override // LocalVariableReference other_variable_assign = new LocalVariableReference (equals_block, "other", loc); equals_block.AddStatement (new StatementExpression ( new SimpleAssign (other_variable_assign, new As (equals_block.GetParameterReference ("obj", loc), current_type, loc), loc))); Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc)); if (rs_equals != null) equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals); equals_block.AddStatement (new Return (equals_test, loc)); equals.Block = equals_block; equals.Define (); AddMethod (equals); // // GetHashCode () override // Method hashcode = new Method (this, null, TypeManager.system_int32_expr, Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform // distribution with larger hash sizes. // // const int FNV_prime = 16777619; // int hash = (int) 2166136261; // foreach (int d in data) // hash = (hash ^ d) * FNV_prime; // hash += hash << 13; // hash ^= hash >> 7; // hash += hash << 3; // hash ^= hash >> 17; // hash += hash << 5; ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc); Block hashcode_block = new Block (hashcode_top); hashcode_top.AddStatement (new Unchecked (hashcode_block)); hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc); LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc); LocalVariableReference hash_variable_assign = new LocalVariableReference (hashcode_block, "hash", loc); hashcode_block.AddStatement (new StatementExpression ( new SimpleAssign (hash_variable_assign, rs_hashcode))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc))))); hashcode_block.AddStatement (new Return (hash_variable, loc)); hashcode.Block = hashcode_top; hashcode.Define (); AddMethod (hashcode); // // ToString () override // ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); tostring_block.AddStatement (new Return (string_concat, loc)); tostring.Block = tostring_block; tostring.Define (); AddMethod (tostring); }
TypeExpr CreateSiteType(CompilerContext ctx, Arguments arguments, int dyn_args_count, bool is_statement) { int default_args = is_statement ? 1 : 2; bool has_ref_out_argument = false; FullNamedExpression[] targs = new FullNamedExpression[dyn_args_count + default_args]; targs [0] = new TypeExpression (TypeManager.call_site_type, loc); for (int i = 0; i < dyn_args_count; ++i) { TypeSpec arg_type; Argument a = arguments [i]; if (a.Type == TypeManager.null_type) arg_type = TypeManager.object_type; else arg_type = a.Type; if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) has_ref_out_argument = true; targs [i + 1] = new TypeExpression (arg_type, loc); } TypeExpr del_type = null; if (!has_ref_out_argument) { string d_name = is_statement ? "Action" : "Func"; TypeSpec t = TypeManager.CoreLookupType (ctx, "System", d_name, dyn_args_count + default_args, MemberKind.Delegate, false); if (t != null) { if (!is_statement) targs [targs.Length - 1] = new TypeExpression (type, loc); del_type = new GenericTypeExpr (t, new TypeArguments (targs), loc); } } // // Create custom delegate when no appropriate predefined one is found // if (del_type == null) { TypeSpec rt = is_statement ? TypeManager.void_type : type; Parameter[] p = new Parameter [dyn_args_count + 1]; p[0] = new Parameter (targs [0], "p0", Parameter.Modifier.NONE, null, loc); 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); TypeContainer parent = CreateSiteContainer (); Delegate d = new Delegate (parent.NamespaceEntry, parent, new TypeExpression (rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName ("Container" + container_counter++.ToString ("X")), new ParametersCompiled (ctx, p), null); d.CreateType (); d.DefineType (); d.Define (); d.Emit (); parent.AddDelegate (d); del_type = new TypeExpression (d.Definition, loc); } TypeExpr site_type = new GenericTypeExpr (TypeManager.generic_call_site_type, new TypeArguments (del_type), loc); return site_type; }
// // Initializes all hoisted variables // public void EmitStoreyInstantiation (EmitContext ec) { // There can be only one instance variable for each storey type if (Instance != null) throw new InternalErrorException (); SymbolWriter.OpenCompilerGeneratedBlock (ec.ig); // // Create an instance of storey type // Expression storey_type_expr; if (is_generic) { // // Use current method type parameter (MVAR) for top level storey only. All // nested storeys use class type parameter (VAR) // TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ? ec.CurrentAnonymousMethod.Storey.TypeParameters : ec.CurrentTypeParameters; TypeArguments targs = new TypeArguments (); if (tparams.Length < CountTypeParameters) { TypeParameter[] parent_tparams = ec.MemberContext.CurrentTypeDefinition.TypeParameters; for (int i = 0; i < parent_tparams.Length; ++i) targs.Add (new TypeParameterExpr (parent_tparams[i], Location)); } for (int i = 0; i < tparams.Length; ++i) targs.Add (new TypeParameterExpr (tparams[i], Location)); storey_type_expr = new GenericTypeExpr (TypeBuilder, targs, Location); } else { storey_type_expr = new TypeExpression (TypeBuilder, Location); } ResolveContext rc = new ResolveContext (this); Expression e = new New (storey_type_expr, null, Location).Resolve (rc); e.Emit (ec); Instance = new LocalTemporary (storey_type_expr.Type); Instance.Store (ec); EmitHoistedFieldsInitialization (ec); SymbolWriter.DefineScopeVariable (ID, Instance.Builder); SymbolWriter.CloseCompilerGeneratedBlock (ec.ig); }
TypeExpr CreateStoreyTypeExpression (EmitContext ec) { // // Create an instance of storey type // TypeExpr storey_type_expr; if (CurrentTypeParameters != null) { // // Use current method type parameter (MVAR) for top level storey only. All // nested storeys use class type parameter (VAR) // var tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ? ec.CurrentAnonymousMethod.Storey.CurrentTypeParameters : ec.CurrentTypeParameters; TypeArguments targs = new TypeArguments (); // // Use type parameter name instead of resolved type parameter // specification to resolve to correctly nested type parameters // for (int i = 0; i < tparams.Count; ++i) targs.Add (new SimpleName (tparams [i].Name, Location)); // new TypeParameterExpr (tparams[i], Location)); storey_type_expr = new GenericTypeExpr (Definition, targs, Location); } else { storey_type_expr = new TypeExpression (CurrentType, Location); } return storey_type_expr; }
TypeExpr CreateSiteType(CompilerContext ctx, bool isStatement, int dyn_args_count) { int default_args = isStatement ? 1 : 2; bool has_ref_out_argument = false; FullNamedExpression[] targs = new FullNamedExpression[dyn_args_count + default_args]; targs [0] = new TypeExpression(TypeManager.call_site_type, loc); for (int i = 0; i < dyn_args_count; ++i) { Type arg_type; Argument a = arguments [i]; if (a.Type == TypeManager.null_type) { arg_type = TypeManager.object_type; } else { arg_type = TypeManager.TypeToReflectionType(a.Type); } if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) { has_ref_out_argument = true; } targs [i + 1] = new TypeExpression(arg_type, loc); } TypeExpr del_type = null; if (!has_ref_out_argument) { string d_name = isStatement ? "Action`" : "Func`"; Type t = TypeManager.CoreLookupType(ctx, "System", d_name + (dyn_args_count + default_args), Kind.Delegate, false); if (t != null) { if (!isStatement) { targs[targs.Length - 1] = new TypeExpression(TypeManager.TypeToReflectionType(type), loc); } del_type = new GenericTypeExpr(t, new TypeArguments(targs), loc); } } // No appropriate predefined delegate found if (del_type == null) { Type rt = isStatement ? TypeManager.void_type : type; Parameter[] p = new Parameter [dyn_args_count + 1]; p[0] = new Parameter(targs [0], "p0", Parameter.Modifier.NONE, null, loc); 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); } TypeContainer parent = CreateSiteContainer(); Delegate d = new Delegate(parent.NamespaceEntry, parent, new TypeExpression(rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName("Container" + container_counter++.ToString("X")), new ParametersCompiled(p), null); d.DefineType(); d.Define(); parent.AddDelegate(d); del_type = new TypeExpression(d.TypeBuilder, loc); } TypeExpr site_type = new GenericTypeExpr(TypeManager.generic_call_site_type, new TypeArguments(del_type), loc); return(site_type); }