sealed class ThisInitializer : Statement
{
readonly HoistedThis hoisted_this;
+ readonly AnonymousMethodStorey parent;
- public ThisInitializer (HoistedThis hoisted_this)
+ public ThisInitializer (HoistedThis hoisted_this, AnonymousMethodStorey parent)
{
this.hoisted_this = hoisted_this;
+ this.parent = parent;
+ }
+
+ public override bool Resolve (BlockContext bc)
+ {
+ return base.Resolve (bc);
}
protected override void DoEmit (EmitContext ec)
{
- hoisted_this.EmitAssign (ec, new CompilerGeneratedThis (ec.CurrentType, loc), false, false);
+ Expression source = EmptyExpression.Null;
+
+ if (parent == null)
+ source = new CompilerGeneratedThis (ec.CurrentType, loc);
+ else {
+ source = new FieldExpr (parent.HoistedThis.Field, Location.Null) {
+ InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location.Null)
+ };
+ }
+
+ hoisted_this.EmitAssign (ec, source, false, false);
}
protected override void CloneTo (CloneContext clonectx, Statement target)
public Expression Instance;
bool initialize_hoisted_this;
+ AnonymousMethodStorey hoisted_this_parent;
public AnonymousMethodStorey (ExplicitBlock block, TypeDefinition parent, MemberBase host, TypeParameters tparams, string name, MemberKind kind)
: base (parent, MakeMemberName (host, name, parent.Module.CounterAnonymousContainers, tparams, block.StartLocation),
ID = parent.Module.CounterAnonymousContainers++;
}
- public void AddCapturedThisField (EmitContext ec)
+ public void AddCapturedThisField (EmitContext ec, AnonymousMethodStorey parent)
{
TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
Field f = AddCompilerGeneratedField ("$this", type_expr);
hoisted_this = new HoistedThis (this, f);
initialize_hoisted_this = true;
+ hoisted_this_parent = parent;
}
public Field AddCapturedVariable (string name, TypeSpec type)
}
var hoisted = localVariable.HoistedVariant;
- if (hoisted != null && hoisted.Storey != this && hoisted.Storey.Kind == MemberKind.Struct) {
- // TODO: It's too late the field is defined in HoistedLocalVariable ctor
+ if (hoisted != null && hoisted.Storey != this && hoisted.Storey is StateMachine) {
+ //
+ // Variable is already hoisted but we need it in storey which can be shared
+ //
hoisted.Storey.hoisted_locals.Remove (hoisted);
+ hoisted.Storey.Members.Remove (hoisted.Field);
hoisted = null;
}
hoisted_locals.Add (hoisted);
}
- if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit)
+ if (ec.CurrentBlock.Explicit != localVariable.Block.Explicit && !(hoisted.Storey is StateMachine))
hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
}
var hoisted = parameterInfo.Parameter.HoistedVariant;
- if (parameterInfo.Block.StateMachine is AsyncTaskStorey) {
+ if (parameterInfo.Block.StateMachine != null) {
//
// Another storey in same block exists but state machine does not
// have parameter captured. We need to add it there as well to
// Lift captured parameter from value type storey to reference type one. Otherwise
// any side effects would be done on a copy
//
- if (hoisted != null && hoisted.Storey != this && hoisted.Storey.Kind == MemberKind.Struct) {
+ if (hoisted != null && hoisted.Storey != this && hoisted.Storey is StateMachine) {
if (hoisted_local_params == null)
hoisted_local_params = new List<HoistedParameter> ();
// When the current context is async (or iterator) lift local storey
// instantiation to the currect storey
//
- if (ec.CurrentAnonymousMethod is StateMachineInitializer) {
+ if (ec.CurrentAnonymousMethod is StateMachineInitializer && (block.HasYield || block.HasAwait)) {
//
// Unfortunately, normal capture mechanism could not be used because we are
// too late in the pipeline and standart assign cannot be used either due to
// referenced indirectly
//
if (initialize_hoisted_this) {
- rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this));
+ rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this, hoisted_this_parent));
}
//
protected virtual void EmitHoistedParameters (EmitContext ec, List<HoistedParameter> hoisted)
{
foreach (HoistedParameter hp in hoisted) {
+ if (hp == null)
+ continue;
+
//
// Parameters could be proxied via local fields for value type storey
//
public override void Emit (EmitContext ec)
{
ResolveContext rc = new ResolveContext (ec.MemberContext);
- Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc);
+ Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc, false);
// This should never fail
e = e.Resolve (rc);
if (e != null)
this.field = field;
}
+ public Field Field {
+ get {
+ return field;
+ }
+ }
+
public AnonymousMethodStorey Storey {
get {
return storey;
sealed class HoistedFieldAssign : CompilerAssign
{
public HoistedFieldAssign (Expression target, Expression source)
- : base (target, source, source.Location)
+ : base (target, source, target.Location)
{
}
#region Properties
- public Field Field {
- get {
- return field;
- }
- }
+ public bool IsAssigned { get; set; }
public ParameterReference Parameter {
get {
: base (storey, field)
{
}
-
- public Field Field {
- get {
- return field;
- }
- }
}
//
}
}
+ public override bool IsSideEffectFree {
+ get {
+ return true;
+ }
+ }
+
public ParametersCompiled Parameters {
get {
return Block.Parameters;
}
}
+ public ReportPrinter TypeInferenceReportPrinter {
+ get; set;
+ }
+
#endregion
//
{
using (ec.With (ResolveContext.Options.InferReturnType, false)) {
using (ec.Set (ResolveContext.Options.ProbingMode)) {
- return Compatible (ec, delegate_type) != null;
+ var prev = ec.Report.SetPrinter (TypeInferenceReportPrinter ?? new NullReportPrinter ());
+
+ var res = Compatible (ec, delegate_type) != null;
+
+ ec.Report.SetPrinter (prev);
+
+ return res;
}
}
}
return delegate_type;
ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
- GetSignatureForError (), TypeManager.CSharpName (delegate_type));
+ GetSignatureForError (), delegate_type.GetSignatureForError ());
return null;
}
ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
- GetSignatureForError (), TypeManager.CSharpName (delegate_type));
+ GetSignatureForError (), delegate_type.GetSignatureForError ());
return null;
}
- protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters)
+ protected bool VerifyExplicitParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection parameters)
{
- if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode))
+ if (VerifyParameterCompatibility (ec, tic, delegate_type, parameters, ec.IsInProbingMode))
return true;
if (!ec.IsInProbingMode)
ec.Report.Error (1661, loc,
"Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch",
- GetSignatureForError (), TypeManager.CSharpName (delegate_type));
+ GetSignatureForError (), delegate_type.GetSignatureForError ());
return false;
}
- protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
+ protected bool VerifyParameterCompatibility (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
{
if (Parameters.Count != invoke_pd.Count) {
if (ignore_errors)
return false;
ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
- TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
+ delegate_type.GetSignatureForError (), Parameters.Count.ToString ());
return false;
}
return false;
if (p_mod == Parameter.Modifier.NONE)
- ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
- (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags));
+ ec.Report.Error (1677, Parameters[i].Location, "Parameter `{0}' should not be declared with the `{1}' keyword",
+ (i + 1).ToString (), Parameter.GetModifierSignature (Parameters [i].ModFlags));
else
- ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
+ ec.Report.Error (1676, Parameters[i].Location, "Parameter `{0}' must be declared with the `{1}' keyword",
(i+1).ToString (), Parameter.GetModifierSignature (p_mod));
error = true;
}
continue;
TypeSpec type = invoke_pd.Types [i];
+
+ if (tic != null)
+ type = tic.InflateGenericArgument (ec, type);
- // We assume that generic parameters are always inflated
- if (TypeManager.IsGenericParameter (type))
- continue;
-
- if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type)))
- continue;
-
- if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) {
+ if (!TypeSpecComparer.IsEqual (type, Parameters.Types [i])) {
if (ignore_errors)
return false;
- ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
+ ec.Report.Error (1678, Parameters [i].Location, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
(i+1).ToString (),
- TypeManager.CSharpName (Parameters.Types [i]),
- TypeManager.CSharpName (invoke_pd.Types [i]));
+ Parameters.Types [i].GetSignatureForError (),
+ invoke_pd.Types [i].GetSignatureForError ());
error = true;
}
}
//
// Infers type arguments based on explicit arguments
//
- public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type)
+ public bool ExplicitTypeInference (TypeInferenceContext type_inference, TypeSpec delegate_type)
{
if (!HasExplicitParameters)
return false;
if (d_params.Count != Parameters.Count)
return false;
+ var ptypes = Parameters.Types;
+ var dtypes = d_params.Types;
for (int i = 0; i < Parameters.Count; ++i) {
- if (type_inference.ExactInference (Parameters.Types[i], d_params.Types[i]) == 0)
+ if (type_inference.ExactInference (ptypes[i], dtypes[i]) == 0) {
+ //
+ // Continue when 0 (quick path) does not mean inference failure. Checking for
+ // same type handles cases like int -> int
+ //
+ if (ptypes[i] == dtypes[i])
+ continue;
+
return false;
+ }
}
return true;
}
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
+ ReportPrinter prev;
+ if (TypeInferenceReportPrinter != null) {
+ prev = ec.Report.SetPrinter (TypeInferenceReportPrinter);
+ } else {
+ prev = null;
+ }
+
var body = CompatibleMethodBody (ec, tic, null, delegate_type);
if (body != null) {
am = body.Compatible (ec, body);
} else {
am = null;
}
+
+ if (TypeInferenceReportPrinter != null) {
+ ec.Report.SetPrinter (prev);
+ }
}
if (am == null)
}
} else {
am = body.Compatible (ec);
+
+ if (body.DirectMethodGroupConversion != null) {
+ var errors_printer = new SessionReportPrinter ();
+ var old = ec.Report.SetPrinter (errors_printer);
+ var expr = new ImplicitDelegateCreation (delegate_type, body.DirectMethodGroupConversion, loc) {
+ AllowSpecialMethodsInvocation = true
+ }.Resolve (ec);
+ ec.Report.SetPrinter (old);
+ if (expr != null && errors_printer.ErrorsCount == 0)
+ am = expr;
+ }
}
} catch (CompletionResult) {
throw;
return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types);
}
- if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) {
+ if (!VerifyExplicitParameters (ec, tic, delegate_type, delegate_parameters)) {
return null;
}
return null;
}
- b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, loc);
+ b = b.ConvertToAsyncTask (ec, ec.CurrentMemberDefinition.Parent.PartialContainer, p, return_type, delegate_type, loc);
}
- return CompatibleMethodFactory (return_type ?? InternalType.Arglist, delegate_type, p, b);
+ return CompatibleMethodFactory (return_type ?? InternalType.ErrorType, delegate_type, p, b);
}
protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b)
}
}
- protected ParametersBlock block;
+ protected readonly ParametersBlock block;
public TypeSpec ReturnType;
BlockContext aec = new BlockContext (ec, block, ReturnType);
aec.CurrentAnonymousMethod = ae;
- ResolveContext.Options flags = 0;
-
var am = this as AnonymousMethodBody;
if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) {
am.ReturnTypeInference = new TypeInferenceContext ();
}
- if (ec.IsInProbingMode)
- flags |= ResolveContext.Options.ProbingMode;
-
- if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
- flags |= ResolveContext.Options.FieldInitializerScope;
-
- if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion))
- flags |= ResolveContext.Options.ExpressionTreeConversion;
-
- aec.Set (flags);
+ var bc = ec as BlockContext;
+ if (bc != null)
+ aec.FlowOffset = bc.FlowOffset;
var errors = ec.Report.Errors;
get { return "anonymous method"; }
}
+ //
+ // Method-group instance for lambdas which can be replaced with
+ // simple method group call
+ //
+ public MethodGroupExpr DirectMethodGroupConversion {
+ get; set;
+ }
+
public override bool IsIterator {
get {
return false;
}
public override AnonymousMethodStorey Storey {
- get { return storey; }
+ get {
+ return storey;
+ }
}
#endregion
parent = storey = FindBestMethodStorey ();
if (storey == null) {
- var sm = src_block.ParametersBlock.TopBlock.StateMachine;
+ var top_block = src_block.ParametersBlock.TopBlock;
+ var sm = top_block.StateMachine;
- //
- // Remove hoisted this demand when simple instance method is enough
- //
if (src_block.HasCapturedThis) {
- src_block.ParametersBlock.TopBlock.RemoveThisReferenceFromChildrenBlock (src_block);
-
//
- // Special case where parent class is used to emit instance method
- // because currect storey is of value type (async host) and we don't
- // want to create another childer storey to host this reference only
+ // Remove hoisted 'this' request when simple instance method is
+ // enough. No hoisted variables only 'this' and don't need to
+ // propagate this to value type state machine.
//
- if (sm != null && sm.Kind == MemberKind.Struct)
- parent = sm.Parent.PartialContainer;
+ StateMachine sm_parent;
+ var pb = src_block.ParametersBlock;
+ do {
+ sm_parent = pb.StateMachine;
+ pb = pb.Parent == null ? null : pb.Parent.ParametersBlock;
+ } while (sm_parent == null && pb != null);
+
+ if (sm_parent == null) {
+ top_block.RemoveThisReferenceFromChildrenBlock (src_block);
+ } else if (sm_parent.Kind == MemberKind.Struct) {
+ //
+ // Special case where parent class is used to emit instance method
+ // because currect storey is of value type (async host) and we cannot
+ // use ldftn on non-boxed instances either to share mutated state
+ //
+ parent = sm_parent.Parent.PartialContainer;
+ }
+ } else {
+ //
+ // For iterators we can host everything in one class
+ //
+ if (sm is IteratorStorey)
+ parent = storey = sm;
}
-
- //
- // For iterators we can host everything in one class
- //
- if (sm is IteratorStorey)
- parent = storey = sm;
}
modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
//
method = DoCreateMethodHost (ec);
method.Define ();
+ method.PrepareEmit ();
}
bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
// Special case for value type storey where this is not lifted but
// droped off to parent class
//
- for (var b = Block.Parent; b != null; b = b.Parent) {
- if (b.ParametersBlock.StateMachine != null) {
- ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
- break;
- }
- }
+ if (ec.CurrentAnonymousMethod != null && ec.AsyncTaskStorey != null)
+ ec.Emit (OpCodes.Ldfld, ec.AsyncTaskStorey.HoistedThis.Field.Spec);
}
var delegate_method = method.Spec;
public override string GetSignatureForError ()
{
- return TypeManager.CSharpName (type);
+ return type.GetSignatureForError ();
}
}
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);
+ ParametersCompiled.EmptyReadOnlyParameters, null);
ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc);
}
var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc);
- equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other));
+ equals_block.AddStatement (new BlockVariable (new TypeExpression (li_other.Type, loc), li_other));
var other_variable = new LocalVariableReference (li_other, loc);
MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
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, loc),
- FNV_prime, loc);
+ 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), loc)),
+ 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);
string_concat,
new Binary (Binary.Operator.Addition,
new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc),
- field_to_string,
- loc),
- loc);
+ field_to_string));
continue;
}
string_concat = new Binary (Binary.Operator.Addition,
new Binary (Binary.Operator.Addition,
string_concat,
- new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc),
- loc),
- field_to_string,
- loc);
+ new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc)),
+ field_to_string);
- rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal, loc);
+ 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),
- loc);
+ new StringConstant (Compiler.BuiltinTypes, " }", loc));
//
// Equals (object obj) override
new As (equals_block.GetParameterReference (0, loc),
current_type, loc), loc)));
- Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (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, loc);
+ 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 ();
+ equals.PrepareEmit ();
Members.Add (equals);
//
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);
+ ParametersCompiled.EmptyReadOnlyParameters, null);
//
// Modified FNV with good avalanche behavior and uniform
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));
+ hashcode_block.AddStatement (new BlockVariable (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), loc), loc)));
+ 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), loc), loc)));
+ 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), loc), loc)));
+ 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), loc), loc)));
+ 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), loc), loc)));
+ 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 ();
+ hashcode.PrepareEmit ();
Members.Add (hashcode);
//
tostring_block.AddStatement (new Return (string_concat, loc));
tostring.Block = tostring_block;
tostring.Define ();
+ tostring.PrepareEmit ();
Members.Add (tostring);
return true;