public abstract class CompilerGeneratedClass : Class
{
- protected CompilerGeneratedClass (DeclSpace parent, MemberName name, Modifiers mod)
+ protected CompilerGeneratedClass (TypeContainer parent, MemberName name, Modifiers mod)
: base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED, null)
{
}
protected TypeParameterMutator mutator;
- public HoistedStoreyClass (DeclSpace parent, MemberName name, TypeParameter[] tparams, Modifiers mod)
+ public HoistedStoreyClass (TypeContainer parent, MemberName name, TypeParameter[] tparams, Modifiers mod)
: base (parent, name, mod | Modifiers.PRIVATE)
{
if (tparams != null) {
for (int i = 0; i < type_params.Length; ++i) {
src[i].InflateConstraints (inflator, dst[i]);
}
+
+ mutator = new TypeParameterMutator (tparams, type_params);
}
}
protected HoistedThis hoisted_this;
// Local variable which holds this storey instance
- public LocalTemporary Instance;
+ public Expression Instance;
public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name)
: base (parent, MakeMemberName (host, name, unique_id, tparams, block.StartLocation),
tparams, Modifiers.SEALED)
{
- Parent = parent;
OriginalSourceBlock = block;
ID = unique_id++;
}
protected Field AddCompilerGeneratedField (string name, FullNamedExpression type)
{
- const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED;
+ return AddCompilerGeneratedField (name, type, false);
+ }
+
+ protected Field AddCompilerGeneratedField (string name, FullNamedExpression type, bool privateAccess)
+ {
+ Modifiers mod = Modifiers.COMPILER_GENERATED | (privateAccess ? Modifiers.PRIVATE : Modifiers.INTERNAL);
Field f = new Field (this, type, mod, new MemberName (name, Location), null);
AddField (f);
return f;
SymbolWriter.OpenCompilerGeneratedBlock (ec);
//
- // Create an instance of a storey
+ // Create an instance of this storey
//
- var storey_type_expr = CreateStoreyTypeExpression (ec);
-
ResolveContext rc = new ResolveContext (ec.MemberContext);
rc.CurrentBlock = block;
- Expression e = new New (storey_type_expr, null, Location).Resolve (rc);
- e.Emit (ec);
- Instance = new LocalTemporary (storey_type_expr.Type);
- Instance.Store (ec);
+ var storey_type_expr = CreateStoreyTypeExpression (ec);
+ var source = new New (storey_type_expr, null, Location).Resolve (rc);
+
+ //
+ // When the current context is async (or iterator) lift local storey
+ // instantiation to the currect storey
+ //
+ if (ec.CurrentAnonymousMethod is StateMachineInitializer) {
+ //
+ // Unfortunately, normal capture mechanism could not be used because we are
+ // too late in the pipeline and standart assign cannot be used either due to
+ // recursive nature of GetStoreyInstanceExpression
+ //
+ var field = ec.CurrentAnonymousMethod.Storey.AddCompilerGeneratedField (
+ LocalVariable.GetCompilerGeneratedName (block), storey_type_expr, true);
+
+ field.Define ();
+ field.Emit ();
+
+ var fexpr = new FieldExpr (field, Location);
+ fexpr.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location);
+ fexpr.EmitAssign (ec, source, false, false);
+
+ Instance = fexpr;
+ } else {
+ var local = TemporaryVariableReference.Create (source.Type, block, Location);
+ local.EmitAssign (ec, source);
+
+ Instance = local;
+ }
EmitHoistedFieldsInitialization (rc, ec);
- SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
+ // TODO: Implement properly
+ //SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
+
SymbolWriter.CloseCompilerGeneratedBlock (ec);
}
if (f == null) {
if (am.Storey == this) {
//
- // Access inside of same storey (S -> S)
+ // Access from inside of same storey (S -> S)
//
return new CompilerGeneratedThis (CurrentType, Location);
}
+
//
// External field access
//
this.hv = hv;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return false;
+ }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
return hv.CreateExpressionTree ();
protected override Expression DoResolve (ResolveContext ec)
{
eclass = ExprClass.Value;
- type = ec.Module.PredefinedTypes.Expression.Resolve (Location);
+ type = ec.Module.PredefinedTypes.Expression.Resolve ();
return this;
}
GetFieldExpression (ec).Emit (ec);
}
+ public Expression EmitToField (EmitContext ec)
+ {
+ return GetFieldExpression (ec);
+ }
+
//
// Creates field access expression for hoisted variable
//
GetFieldExpression (ec).Emit (ec, leave_copy);
}
- public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
{
GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false);
}
{
readonly string name;
- public HoistedLocalVariable (AnonymousMethodStorey scope, LocalVariable local, string name)
- : base (scope, name, local.Type)
+ public HoistedLocalVariable (AnonymousMethodStorey storey, LocalVariable local, string name)
+ : base (storey, name, local.Type)
{
this.name = local.Name;
}
+ //
+ // For compiler generated local variables
+ //
+ public HoistedLocalVariable (AnonymousMethodStorey storey, Field field)
+ : base (storey, field)
+ {
+ }
+
public override void EmitSymbolInfo ()
{
SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name);
}
}
- Dictionary<TypeSpec, Expression> compatibles;
+ readonly Dictionary<TypeSpec, Expression> compatibles;
+ readonly bool is_async;
+
public ParametersBlock Block;
- public AnonymousMethodExpression (Location loc)
+ public AnonymousMethodExpression (bool isAsync, Location loc)
{
+ this.is_async = isAsync;
this.loc = loc;
this.compatibles = new Dictionary<TypeSpec, Expression> ();
}
+ #region Properties
+
public override string ExprClassName {
get {
return "anonymous method";
return Parameters != ParametersCompiled.Undefined;
}
}
-
+
+ public bool IsAsync {
+ get {
+ return is_async;
+ }
+ }
+
public ParametersCompiled Parameters {
- get { return Block.Parameters; }
+ get {
+ return Block.Parameters;
+ }
}
+ #endregion
+
//
// Returns true if the body of lambda expression can be implicitly
// converted to the delegate of type `delegate_type'
if (delegate_type.IsDelegate)
return delegate_type;
- if (delegate_type.IsGeneric && delegate_type.GetDefinition () == TypeManager.expression_type) {
+ if (delegate_type.IsExpressionTreeType) {
delegate_type = delegate_type.TypeArguments [0];
if (delegate_type.IsDelegate)
return delegate_type;
return false;
if (!delegate_type.IsDelegate) {
- if (delegate_type.GetDefinition () != TypeManager.expression_type)
+ if (!delegate_type.IsExpressionTreeType)
return false;
delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
}
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
- am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
- if (am != null)
- am = am.Compatible (ec);
+ var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
+ if (body != null) {
+ if (is_async) {
+ AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc);
+ }
+
+ am = body.Compatible (ec, body, is_async);
+ } else {
+ am = null;
+ }
}
if (am == null)
return am.ReturnType;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return false;
+ }
+
//
// Returns AnonymousMethod container if this anonymous method
// expression can be implicitly converted to the delegate type `delegate_type'
// lambda, this also means no variable capturing between this
// and parent scope
//
- am = body.Compatible (ec, ec.CurrentAnonymousMethod);
+ am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async);
//
// Quote nested expression tree
am = CreateExpressionTree (ec, delegate_type);
}
} else {
+ if (is_async) {
+ AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc);
+ }
+
am = body.Compatible (ec);
}
} catch (CompletionResult) {
if (!DoResolveParameters (ec))
return null;
+#if !STATIC
// FIXME: The emitted code isn't very careful about reachability
// so, ensure we have a 'ret' at the end
BlockContext bc = ec as BlockContext;
if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
bc.NeedReturnLabel ();
-
+#endif
return this;
}
public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc)
{
ec.Report.Error (1686, loc,
- "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method or lambda expression",
+ "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method, lambda expression or query expression",
var.Name);
}
ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block;
return CompatibleMethodFactory (return_type, delegate_type, p, b);
-
}
protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b)
//
// Abstract expression for any block which requires variables hoisting
//
- public abstract class AnonymousExpression : Expression
+ public abstract class AnonymousExpression : ExpressionStatement
{
protected class AnonymousMethodMethod : Method
{
{
EmitContext ec = new EmitContext (this, ig, ReturnType);
ec.CurrentAnonymousMethod = AnonymousMethod;
- if (AnonymousMethod.return_label != null) {
- ec.HasReturnLabel = true;
- ec.ReturnLabel = (Label) AnonymousMethod.return_label;
- }
-
return ec;
}
public TypeSpec ReturnType;
- object return_label;
-
protected AnonymousExpression (ParametersBlock block, TypeSpec return_type, Location loc)
{
this.ReturnType = return_type;
public AnonymousExpression Compatible (ResolveContext ec)
{
- return Compatible (ec, this);
+ return Compatible (ec, this, false);
}
- public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
+ public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync)
{
if (block.Resolved)
return this;
bool res = Block.Resolve (ec.CurrentBranching, aec, null);
- if (aec.HasReturnLabel)
- return_label = aec.ReturnLabel;
-
if (am != null && am.ReturnTypeInference != null) {
am.ReturnTypeInference.FixAllTypes (ec);
ReturnType = am.ReturnTypeInference.InferredTypeArguments [0];
am.ReturnTypeInference = null;
+
+ //
+ // If e is synchronous the inferred return type is T
+ // If e is asynchronous the inferred return type is Task<T>
+ //
+ if (isAsync && ReturnType != null) {
+ ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
+ }
}
if (res && errors != ec.Report.Errors)
return res ? this : null;
}
+ public override bool ContainsEmitWithAwait ()
+ {
+ return false;
+ }
+
public void SetHasThisAccess ()
{
ExplicitBlock b = block;
}
public override bool IsIterator {
- get { return false; }
+ get {
+ return false;
+ }
+ }
+
+ public ParametersCompiled Parameters {
+ get {
+ return parameters;
+ }
}
public TypeInferenceContext ReturnTypeInference {
//
if (is_static) {
- ec.Emit (OpCodes.Ldnull);
+ ec.EmitNull ();
} else if (storey != null) {
Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
if (e != null)
e.Emit (ec);
} else {
- ec.Emit (OpCodes.Ldarg_0);
+ ec.EmitThis ();
}
var delegate_method = method.Spec;
}
}
+ public override void EmitStatement (EmitContext ec)
+ {
+ throw new NotImplementedException ();
+ }
+
//
// Look for the best storey for this anonymous method
//
//
public class AnonymousTypeClass : CompilerGeneratedClass
{
- // TODO: Merge with AnonymousTypeParameter
- public class GeneratedParameter : Parameter
- {
- public GeneratedParameter (FullNamedExpression type, AnonymousTypeParameter p)
- : base (type, p.Name, Modifier.NONE, null, p.Location)
- {
- }
- }
-
static int types_counter;
public const string ClassNamePrefix = "<>__AnonType";
public const string SignatureForError = "anonymous type";
readonly IList<AnonymousTypeParameter> parameters;
- private AnonymousTypeClass (DeclSpace parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc)
+ private AnonymousTypeClass (TypeContainer parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc)
: base (parent, name, (parent.Module.Evaluator != null ? Modifiers.PUBLIC : 0) | Modifiers.SEALED)
{
this.parameters = parameters;
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);
t_params[i] = new TypeParameterName (t_args[i].Name, null, p.Location);
- ctor_params[i] = new GeneratedParameter (t_args[i], p);
+ ctor_params[i] = new Parameter (t_args[i], p.Name, Parameter.Modifier.NONE, null, p.Location);
}
all_parameters = new ParametersCompiled (ctor_params);
Location loc = Location;
var equals_parameters = ParametersCompiled.CreateFullyResolved (
- new Parameter (new TypeExpression (Compiler.BuildinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuildinTypes.Object);
+ new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object);
- Method equals = new Method (this, null, new TypeExpression (TypeManager.bool_type, loc),
+ Method equals = new Method (this, null, 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, null, new TypeExpression (TypeManager.string_type, loc),
+ Method tostring = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.String, loc),
Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
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);
+ 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 = Fields [i];
Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
"GetHashCode", loc), arguments_hashcode);
- IntConstant FNV_prime = new IntConstant (16777619, loc);
+ 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 MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc), loc)),
new Invocation (new MemberAccess (
new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
- new StringConstant (string.Empty, loc), loc);
+ 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 (" " + p.Name + " = ", loc),
+ new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc),
field_to_string,
loc),
loc);
string_concat = new Binary (Binary.Operator.Addition,
new Binary (Binary.Operator.Addition,
string_concat,
- new StringConstant (", " + p.Name + " = ", loc),
+ new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc),
loc),
field_to_string,
loc);
string_concat = new Binary (Binary.Operator.Addition,
string_concat,
- new StringConstant (" }", loc),
+ new StringConstant (Compiler.BuiltinTypes, " }", loc),
loc);
//
//
// GetHashCode () override
//
- Method hashcode = new Method (this, null, new TypeExpression (TypeManager.int32_type, loc),
+ Method hashcode = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.Int, loc),
Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN,
new MemberName ("GetHashCode", loc),
Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
Block hashcode_block = new Block (hashcode_top, loc, loc);
hashcode_top.AddStatement (new Unchecked (hashcode_block, loc));
- var li_hash = LocalVariable.CreateCompilerGenerated (TypeManager.int32_type, hashcode_top, 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 (
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 (13, loc), loc), loc)));
+ new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc), loc), loc)));
hashcode_block.AddStatement (new StatementExpression (
new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
- new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc), loc), loc)));
+ new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc), loc), loc)));
hashcode_block.AddStatement (new StatementExpression (
new CompoundAssign (Binary.Operator.Addition, hash_variable,
- new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc), loc), loc)));
+ new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc), loc), loc)));
hashcode_block.AddStatement (new StatementExpression (
new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
- new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc), loc), loc)));
+ new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc), loc), loc)));
hashcode_block.AddStatement (new StatementExpression (
new CompoundAssign (Binary.Operator.Addition, hash_variable,
- new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc), loc), loc)));
+ new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc), loc), loc)));
hashcode_block.AddStatement (new Return (hash_variable, loc));
hashcode.Block = hashcode_top;