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; }
// // Creates a proxy base method call inside this container for hoisted base member calls // public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method) { Method proxy_method; // // One proxy per base method is enough // if (hoisted_base_call_proxies == null) { hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> (); proxy_method = null; } else { hoisted_base_call_proxies.TryGetValue (method, out proxy_method); } if (proxy_method == null) { string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count); MemberName member_name; TypeArguments targs = null; TypeSpec return_type = method.ReturnType; var local_param_types = method.Parameters.Types; if (method.IsGeneric) { // // Copy all base generic method type parameters info // var hoisted_tparams = method.GenericDefinition.TypeParameters; var tparams = new TypeParameters (); targs = new TypeArguments (); targs.Arguments = new TypeSpec[hoisted_tparams.Length]; for (int i = 0; i < hoisted_tparams.Length; ++i) { var tp = hoisted_tparams[i]; var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null); tparams.Add (local_tp); targs.Add (new SimpleName (tp.Name, Location)); targs.Arguments[i] = local_tp.Type; } member_name = new MemberName (name, tparams, Location); // // Mutate any method type parameters from original // to newly created hoisted version // var mutator = new TypeParameterMutator (hoisted_tparams, tparams); return_type = mutator.Mutate (return_type); local_param_types = mutator.Mutate (local_param_types); } else { member_name = new MemberName (name); } var base_parameters = new Parameter[method.Parameters.Count]; for (int i = 0; i < base_parameters.Length; ++i) { var base_param = method.Parameters.FixedParameters[i]; base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location), base_param.Name, base_param.ModFlags, null, Location); base_parameters[i].Resolve (this, i); } var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types); if (method.Parameters.HasArglist) { cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location); cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (); } // Compiler generated proxy proxy_method = new Method (this, new TypeExpression (return_type, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN, member_name, cloned_params, null); var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) { IsCompilerGenerated = true }; var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location); mg.InstanceExpression = new BaseThis (method.DeclaringType, Location); if (targs != null) mg.SetTypeArguments (rc, targs); // Get all the method parameters and pass them as arguments var real_base_call = new Invocation (mg, block.GetAllParametersArguments ()); Statement statement; if (method.ReturnType.Kind == MemberKind.Void) statement = new StatementExpression (real_base_call); else statement = new Return (real_base_call, Location); block.AddStatement (statement); proxy_method.Block = block; members.Add (proxy_method); proxy_method.Define (); proxy_method.PrepareEmit (); hoisted_base_call_proxies.Add (method, proxy_method); } return proxy_method.Spec; }
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; }
void Define_Current(bool is_generic) { TypeExpr type; MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); name = new MemberName (name, "Collections", Location); if (is_generic) { name = new MemberName (name, "Generic", Location); name = new MemberName (name, "IEnumerator", generic_args, Location); type = iterator_type_expr; } else { name = new MemberName (name, "IEnumerator"); type = TypeManager.system_object_expr; } name = new MemberName (name, "Current", Location); ToplevelBlock get_block = new ToplevelBlock (Compiler, Location); get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location)); Accessor getter = new Accessor (get_block, 0, null, null, Location); Property current = new Property ( this, type, Modifiers.DEBUGGER_HIDDEN, name, null, getter, null, false); AddProperty (current); }
public DisposeMethod(IteratorStorey host) : base(host, TypeManager.system_void_expr, Modifiers.PUBLIC, new MemberName ("Dispose", host.Location)) { host.AddMethod (this); Block = new ToplevelBlock (Compiler, host.Iterator.Container, ParametersCompiled.EmptyReadOnlyParameters, Location); Block.AddStatement (new DisposeMethodStatement (host.Iterator)); }
public override void Emit (DeclSpace parent) { if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) { if (parent is Class) { MethodBuilder mb = method_data.MethodBuilder; mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized); } var field_info = ((EventField) method).backing_field; FieldExpr f_expr = new FieldExpr (field_info, Location); if ((method.ModFlags & Modifiers.STATIC) == 0) f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.MemberType, Location); block = new ToplevelBlock (Compiler, ParameterInfo, Location); block.AddStatement (new StatementExpression ( new CompoundAssign (Operation, f_expr, block.GetParameterReference (ParameterInfo[0].Name, Location), Location))); } base.Emit (parent); }
// // Creates a proxy base method call inside this container for hoisted base member calls // public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method) { Method proxy_method; // // One proxy per base method is enough // if (hoisted_base_call_proxies == null) { hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> (); proxy_method = null; } else { hoisted_base_call_proxies.TryGetValue (method, out proxy_method); } if (proxy_method == null) { string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count); var base_parameters = new Parameter[method.Parameters.Count]; for (int i = 0; i < base_parameters.Length; ++i) { var base_param = method.Parameters.FixedParameters[i]; base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location), base_param.Name, base_param.ModFlags, null, Location); base_parameters[i].Resolve (this, i); } var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types); if (method.Parameters.HasArglist) { cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location); cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (Location); } GenericMethod generic_method; MemberName member_name; if (method.IsGeneric) { // // Copy all base generic method type parameters info // var hoisted_tparams = method.GenericDefinition.TypeParameters; var targs = new TypeArguments (); var type_params = new TypeParameter[hoisted_tparams.Length]; for (int i = 0; i < type_params.Length; ++i) { var tp = hoisted_tparams[i]; targs.Add (new TypeParameterName (tp.Name, null, Location)); type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null); } member_name = new MemberName (name, targs, Location); generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params, new TypeExpression (method.ReturnType, Location), cloned_params); } else { member_name = new MemberName (name); generic_method = null; } // Compiler generated proxy proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN, member_name, cloned_params, null); var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location); var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location); mg.InstanceExpression = new BaseThis (method.DeclaringType, Location); // Get all the method parameters and pass them as arguments var real_base_call = new Invocation (mg, block.GetAllParametersArguments ()); Statement statement; if (method.ReturnType == TypeManager.void_type) statement = new StatementExpression (real_base_call); else statement = new Return (real_base_call, Location); block.AddStatement (statement); proxy_method.Block = block; methods.Add (proxy_method); proxy_method.Define (); hoisted_base_call_proxies.Add (method, proxy_method); } return proxy_method.Spec; }
Method GenerateNumberMatcher () { var loc = Location; var parameters = ParametersCompiled.CreateFullyResolved ( new [] { new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc), new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc), }, new [] { Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Bool }); var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc), parameters, null); parameters [0].Resolve (m, 0); parameters [1].Resolve (m, 1); parameters [2].Resolve (m, 2); ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc); m.Block = top_block; // // if (enumType) // return Equals (obj, value); // var equals_args = new Arguments (2); equals_args.Add (new Argument (top_block.GetParameterReference (0, loc))); equals_args.Add (new Argument (top_block.GetParameterReference (1, loc))); var if_type = new If ( top_block.GetParameterReference (2, loc), new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc), loc); top_block.AddStatement (if_type); // // if (obj is Enum || obj == null) // return false; // var if_enum = new If ( new Binary (Binary.Operator.LogicalOr, new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc), new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))), new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc), loc); top_block.AddStatement (if_enum); var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc); var expl_block = new ExplicitBlock (top_block, loc, loc); // // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value)); // var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc); var arguments_gettypecode = new Arguments (1); arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc))); var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode); var arguments_changetype = new Arguments (1); arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc))); arguments_changetype.Add (new Argument (gettypecode)); var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype); expl_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc))); // // return converted.Equals (value) // var equals_arguments = new Arguments (1); equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc))); var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments); expl_block.AddStatement (new Return (equals_invocation, loc)); var catch_block = new ExplicitBlock (top_block, loc, loc); catch_block.AddStatement (new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc)); top_block.AddStatement (new TryCatch (expl_block, new List<Catch> () { new Catch (catch_block, loc) }, loc, false)); m.Define (); m.PrepareEmit (); AddMember (m); return m; }
public static AnonymousTypeClass Create (CompilerContext ctx, TypeContainer parent, IList<AnonymousTypeParameter> parameters, Location loc) { string name = ClassNamePrefix + types_counter++; SimpleName [] t_args = new SimpleName [parameters.Count]; TypeParameterName [] t_params = new TypeParameterName [parameters.Count]; Parameter [] ctor_params = new Parameter [parameters.Count]; for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i]; t_args [i] = new SimpleName ("<" + p.Name + ">__T", p.Location); t_params [i] = new TypeParameterName (t_args [i].Name, null, p.Location); ctor_params [i] = new Parameter (t_args [i], p.Name, 0, null, p.Location); } // // Create generic anonymous type host with generic arguments // named upon properties names // AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace, new MemberName (name, new TypeArguments (t_params), loc), parameters, loc); if (parameters.Count > 0) a_type.SetParameterInfo (null); Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, null, new AnonymousParameters (ctx, ctor_params), null, loc); c.Block = new ToplevelBlock (ctx, c.ParameterInfo, loc); // // Create fields and contructor body with field initialization // bool error = false; for (int i = 0; i < parameters.Count; ++i) { AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i]; Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY, 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 (p.Name, p.Location)))); ToplevelBlock get_block = new ToplevelBlock (ctx, 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.AddProperty (prop); } if (error) return null; a_type.AddConstructor (c); return a_type; }
protected override bool CheckBase() { // Don't check base, the destructor has special syntax var base_type = Parent.PartialContainer.BaseType; if (base_type == null) return true; if (Block != null) { MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.Definition, base_type, MemberKind.Destructor, MetadataName, 0, Location); if (method_expr == null) throw new NotImplementedException (); method_expr.IsBase = true; method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.Definition, Location); ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); new_block.EndLocation = Block.EndLocation; Block finaly_block = new ExplicitBlock (new_block, Location, Location); Block try_block = new Block (new_block, block); // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); block = new_block; } return true; }
// // Reformats this block to be top-level iterator block // public IteratorStorey ChangeToIterator (Iterator iterator, ToplevelBlock source) { IsIterator = true; // Creates block with original statements AddStatement (new IteratorStatement (iterator, new Block (this, source))); source.statements = new List<Statement> (1); source.AddStatement (new Return (iterator, iterator.Location)); source.IsIterator = false; IteratorStorey iterator_storey = new IteratorStorey (iterator); source.am_storey = iterator_storey; return iterator_storey; }
void Define_Current (bool is_generic) { TypeExpr type; MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); name = new MemberName (name, "Collections", Location); if (is_generic) { name = new MemberName (name, "Generic", Location); name = new MemberName (name, "IEnumerator", generic_args, Location); type = iterator_type_expr; } else { name = new MemberName (name, "IEnumerator"); type = new TypeExpression (Compiler.BuiltinTypes.Object, Location); } name = new MemberName (name, "Current", Location); ToplevelBlock get_block = new ToplevelBlock (Compiler, Location); get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location)); Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN, name, null); current.Get = new Property.GetMethod (current, 0, null, Location); current.Get.Block = get_block; AddProperty (current); }
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); }
public override void Emit() { var base_type = Parent.PartialContainer.BaseType; if (base_type != null && Block != null) { var base_dtor = MemberCache.FindMember (base_type, new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec; if (base_dtor == null) throw new NotImplementedException (); MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location); method_expr.InstanceExpression = new BaseThis (base_type, Location); ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); new_block.EndLocation = Block.EndLocation; Block finaly_block = new ExplicitBlock (new_block, Location, Location); Block try_block = new Block (new_block, block); // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); block = new_block; } base.Emit (); }
void Define_Current (bool is_generic) { MemberName left; TypeExpr type; if (is_generic) { left = new MemberName ( "System.Collections.Generic.IEnumerator", generic_args, Location); type = iterator_type_expr; } else { left = new MemberName ("System.Collections.IEnumerator", Location); type = TypeManager.system_object_expr; } MemberName name = new MemberName (left, "Current", Location); ToplevelBlock get_block = new ToplevelBlock (Location); get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location)); Accessor getter = new Accessor (get_block, 0, null, null, Location); Property current = new Property ( this, type, Modifiers.DEBUGGER_HIDDEN, name, null, getter, null, false); AddProperty (current); }
protected override bool CheckBase () { flags |= MethodAttributes.Virtual; if (!base.CheckBase ()) return false; if (Parent.PartialContainer.BaseCache == null) return true; Type base_type = Parent.PartialContainer.BaseCache.Container.Type; if (base_type != null && Block != null) { MethodGroupExpr method_expr = Expression.MethodLookup (Parent.Module.Compiler, Parent.TypeBuilder, base_type, MetadataName, Location); if (method_expr == null) throw new NotImplementedException (); method_expr.IsBase = true; method_expr.InstanceExpression = new CompilerGeneratedThis (Parent.TypeBuilder, Location); ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); new_block.EndLocation = Block.EndLocation; Block finaly_block = new ExplicitBlock (new_block, Location, Location); Block try_block = new Block (new_block, block); // // 0-size arguments to avoid CS0250 error // TODO: Should use AddScopeStatement or something else which emits correct // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); block = new_block; } return true; }