Browse Source

Merged mcs.

newNRvisualizers
Mike Krüger 14 years ago
parent
commit
cfcaca8e03
  1. 4
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  2. 14
      ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs
  3. 151
      ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs
  4. 2
      ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs
  5. 17
      ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs
  6. 7187
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs
  7. 47
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay
  8. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs
  9. 13
      ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
  10. 4
      ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs
  11. 12
      ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs
  12. 6
      ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs
  13. 100
      ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs

4
ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -1431,12 +1431,12 @@ namespace ICSharpCode.NRefactory.CSharp
result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ForStatement.Roles.Semicolon); result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ForStatement.Roles.Semicolon);
if (forStatement.Test != null) if (forStatement.Test != null)
result.AddChild ((Expression)forStatement.Test.Accept (this), ForStatement.Roles.Condition); result.AddChild ((Expression)forStatement.Test.Accept (this), ForStatement.Roles.Condition);
if (location != null) if (location != null && location.Count >= 3)
result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForStatement.Roles.Semicolon); result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForStatement.Roles.Semicolon);
AddStatementOrList (result, forStatement.Increment, ForStatement.IteratorRole); AddStatementOrList (result, forStatement.Increment, ForStatement.IteratorRole);
if (location != null) if (location != null && location.Count >= 4)
result.AddChild (new CSharpTokenNode (Convert (location [3]), 1), ForStatement.Roles.RPar); result.AddChild (new CSharpTokenNode (Convert (location [3]), 1), ForStatement.Roles.RPar);
if (forStatement.Statement != null) if (forStatement.Statement != null)

14
ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs

@ -1070,11 +1070,11 @@ namespace Mono.CSharp {
using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
if (body != null) { if (body != null) {
if (is_async) { if (Block.IsAsync) {
AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc); AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc);
} }
am = body.Compatible (ec, body, is_async); am = body.Compatible (ec, body);
} else { } else {
am = null; am = null;
} }
@ -1135,7 +1135,7 @@ namespace Mono.CSharp {
// lambda, this also means no variable capturing between this // lambda, this also means no variable capturing between this
// and parent scope // and parent scope
// //
am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async); am = body.Compatible (ec, ec.CurrentAnonymousMethod);
// //
// Quote nested expression tree // Quote nested expression tree
@ -1156,7 +1156,7 @@ namespace Mono.CSharp {
am = CreateExpressionTree (ec, delegate_type); am = CreateExpressionTree (ec, delegate_type);
} }
} else { } else {
if (is_async) { if (Block.IsAsync) {
var rt = body.ReturnType; var rt = body.ReturnType;
if (rt.Kind != MemberKind.Void && if (rt.Kind != MemberKind.Void &&
rt != ec.Module.PredefinedTypes.Task.TypeSpec && rt != ec.Module.PredefinedTypes.Task.TypeSpec &&
@ -1402,10 +1402,10 @@ namespace Mono.CSharp {
public AnonymousExpression Compatible (ResolveContext ec) public AnonymousExpression Compatible (ResolveContext ec)
{ {
return Compatible (ec, this, false); return Compatible (ec, this);
} }
public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync) public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
{ {
if (block.Resolved) if (block.Resolved)
return this; return this;
@ -1446,7 +1446,7 @@ namespace Mono.CSharp {
// If e is synchronous the inferred return type is T // If e is synchronous the inferred return type is T
// If e is asynchronous the inferred return type is Task<T> // If e is asynchronous the inferred return type is Task<T>
// //
if (isAsync && ReturnType != null) { if (block.IsAsync && ReturnType != null) {
ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType });
} }
} }

151
ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs

@ -76,11 +76,6 @@ namespace Mono.CSharp
var bc = (BlockContext) rc; var bc = (BlockContext) rc;
if (!bc.CurrentBlock.ParametersBlock.IsAsync) {
// TODO: Should check for existence of await type but
// what to do with it
}
stmt = new AwaitStatement (expr, loc); stmt = new AwaitStatement (expr, loc);
if (!stmt.Resolve (bc)) if (!stmt.Resolve (bc))
return null; return null;
@ -253,12 +248,11 @@ namespace Mono.CSharp
// //
ec.AssertEmptyStack (); ec.AssertEmptyStack ();
var args = new Arguments (1);
var storey = (AsyncTaskStorey) machine_initializer.Storey; var storey = (AsyncTaskStorey) machine_initializer.Storey;
var fe_cont = new FieldExpr (storey.Continuation, loc); var cont_field = storey.EmitContinuationInitialization (ec);
fe_cont.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
args.Add (new Argument (fe_cont)); var args = new Arguments (1);
args.Add (new Argument (cont_field));
if (IsDynamic) { if (IsDynamic) {
var rc = new ResolveContext (ec.MemberContext); var rc = new ResolveContext (ec.MemberContext);
@ -456,7 +450,7 @@ namespace Mono.CSharp
} }
} }
if (!block.IsAsync) { if (!block.HasAwait) {
host.Compiler.Report.Warning (1998, 1, loc, host.Compiler.Report.Warning (1998, 1, loc,
"Async block lacks `await' operator and will run synchronously"); "Async block lacks `await' operator and will run synchronously");
} }
@ -539,6 +533,8 @@ namespace Mono.CSharp
PropertySpec task; PropertySpec task;
LocalVariable hoisted_return; LocalVariable hoisted_return;
int locals_captured; int locals_captured;
Dictionary<TypeSpec, List<StackField>> stack_fields;
TypeSpec action;
public AsyncTaskStorey (IMemberContext context, AsyncInitializer initializer, TypeSpec type) public AsyncTaskStorey (IMemberContext context, AsyncInitializer initializer, TypeSpec type)
: base (initializer.OriginalBlock, initializer.Host,context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async") : base (initializer.OriginalBlock, initializer.Host,context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async")
@ -554,12 +550,6 @@ namespace Mono.CSharp
} }
} }
public Field Continuation {
get {
return continuation;
}
}
public LocalVariable HoistedReturn { public LocalVariable HoistedReturn {
get { get {
return hoisted_return; return hoisted_return;
@ -585,24 +575,42 @@ namespace Mono.CSharp
return AddCapturedVariable ("$awaiter" + awaiters++.ToString ("X"), type); return AddCapturedVariable ("$awaiter" + awaiters++.ToString ("X"), type);
} }
public Field AddCapturedLocalVariable (TypeSpec type) public StackField AddCapturedLocalVariable (TypeSpec type)
{ {
if (mutator != null) if (mutator != null)
type = mutator.Mutate (type); type = mutator.Mutate (type);
var field = AddCompilerGeneratedField ("<s>$" + locals_captured++.ToString ("X"), new TypeExpression (type, Location), true); List<StackField> existing_fields = null;
if (stack_fields == null) {
stack_fields = new Dictionary<TypeSpec, List<StackField>> ();
} else if (stack_fields.TryGetValue (type, out existing_fields)) {
foreach (var f in existing_fields) {
if (f.CanBeReused) {
f.CanBeReused = false;
return f;
}
}
}
const Modifiers mod = Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE;
var field = new StackField (this, new TypeExpression (type, Location), mod, new MemberName ("<s>$" + locals_captured++.ToString ("X"), Location));
AddField (field);
field.Define (); field.Define ();
if (existing_fields == null) {
existing_fields = new List<StackField> ();
stack_fields.Add (type, existing_fields);
}
existing_fields.Add (field);
return field; return field;
} }
protected override bool DoDefineMembers () protected override bool DoDefineMembers ()
{ {
var action = Module.PredefinedTypes.Action.Resolve (); action = Module.PredefinedTypes.Action.Resolve ();
if (action != null) {
continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true);
continuation.ModFlags |= Modifiers.READONLY;
}
PredefinedType builder_type; PredefinedType builder_type;
PredefinedMember<MethodSpec> bf; PredefinedMember<MethodSpec> bf;
@ -664,30 +672,13 @@ namespace Mono.CSharp
if (!base.DoDefineMembers ()) if (!base.DoDefineMembers ())
return false; return false;
MethodGroupExpr mg;
var block = instance_constructors[0].Block; var block = instance_constructors[0].Block;
// var mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location);
// Initialize continuation with state machine method
//
if (continuation != null) {
var args = new Arguments (1);
mg = MethodGroupExpr.CreatePredefined (StateMachineMethod.Spec, spec, Location);
args.Add (new Argument (mg));
block.AddStatement (
new StatementExpression (new SimpleAssign (
new FieldExpr (continuation, Location),
new NewDelegate (action, args, Location),
Location
)));
}
mg = MethodGroupExpr.CreatePredefined (builder_factory, bt, Location);
block.AddStatement ( block.AddStatement (
new StatementExpression (new SimpleAssign ( new StatementExpression (new SimpleAssign (
new FieldExpr (builder, Location), new FieldExpr (builder, Location),
new Invocation (mg, new Arguments (0)), new Invocation (mg, new Arguments (0)),
Location))); Location)));
if (has_task_return_type) { if (has_task_return_type) {
@ -697,6 +688,54 @@ namespace Mono.CSharp
return true; return true;
} }
public Expression EmitContinuationInitialization (EmitContext ec)
{
//
// When more than 1 awaiter has been used in the block we
// introduce class scope field to cache continuation delegate
//
if (awaiters > 1) {
if (continuation == null) {
continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true);
continuation.Define ();
}
var fexpr = new FieldExpr (continuation, Location);
fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location);
//
// if ($continuation == null)
// $continuation = new Action (MoveNext);
//
fexpr.Emit (ec);
var skip_cont_init = ec.DefineLabel ();
ec.Emit (OpCodes.Brtrue_S, skip_cont_init);
ec.EmitThis ();
EmitActionLoad (ec);
ec.Emit (OpCodes.Stfld, continuation.Spec);
ec.MarkLabel (skip_cont_init);
return fexpr;
}
//
// Otherwise simply use temporary local variable
//
var field = LocalVariable.CreateCompilerGenerated (action, OriginalSourceBlock, Location);
EmitActionLoad (ec);
field.EmitAssign (ec);
return new LocalVariableReference (field, Location);
}
void EmitActionLoad (EmitContext ec)
{
ec.EmitThis ();
ec.Emit (OpCodes.Ldftn, StateMachineMethod.Spec);
ec.Emit (OpCodes.Newobj, (MethodSpec) MemberCache.FindMember (action, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly));
}
public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable) public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable)
{ {
// //
@ -735,4 +774,30 @@ namespace Mono.CSharp
mg.EmitCall (ec, args); mg.EmitCall (ec, args);
} }
} }
class StackField : Field
{
public StackField (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name)
: base (parent, type, mod, name, null)
{
}
public bool CanBeReused { get; set; }
}
class StackFieldExpr : FieldExpr
{
public StackFieldExpr (Field field)
: base (field, Location.Null)
{
}
public override void Emit (EmitContext ec)
{
base.Emit (ec);
var field = (StackField) spec.MemberDefinition;
field.CanBeReused = true;
}
}
} }

2
ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs

@ -280,7 +280,7 @@ namespace Mono.CSharp
public FieldExpr GetTemporaryField (TypeSpec type) public FieldExpr GetTemporaryField (TypeSpec type)
{ {
var f = AsyncTaskStorey.AddCapturedLocalVariable (type); var f = AsyncTaskStorey.AddCapturedLocalVariable (type);
var fexpr = new FieldExpr (f, Location.Null); var fexpr = new StackFieldExpr (f);
fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null); fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null);
return fexpr; return fexpr;
} }

17
ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs

@ -469,10 +469,19 @@ namespace Mono.CSharp
if (CurrentAnonymousMethod == null) if (CurrentAnonymousMethod == null)
return false; return false;
// FIXME: IsIterator is too aggressive, we should capture only if child //
// block contains yield // Capture only if this or any of child blocks contain yield
if (CurrentAnonymousMethod.IsIterator || CurrentAnonymousMethod is AsyncInitializer) // or it's a parameter
return true; //
if (CurrentAnonymousMethod.IsIterator)
return local.IsParameter || CurrentBlock.Explicit.HasYield;
//
// Capture only if this or any of child blocks contain await
// or it's a parameter
//
if (CurrentAnonymousMethod is AsyncInitializer)
return CurrentBlock.Explicit.HasAwait;
return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original; return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
} }

7187
ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs

File diff suppressed because it is too large Load Diff

47
ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay

@ -3891,7 +3891,7 @@ unary_expression
report.Error (1992, GetLocation ($1), report.Error (1992, GetLocation ($1),
"The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier"); "The `await' operator can only be used when its containing method or lambda expression is marked with the `async' modifier");
} else { } else {
current_block.ParametersBlock.IsAsync = true; current_block.Explicit.RegisterAsyncAwait ();
} }
$$ = new Await ((Expression) $2, GetLocation ($1)); $$ = new Await ((Expression) $2, GetLocation ($1));
@ -4092,13 +4092,8 @@ conditional_expression
} }
; ;
expression_recover
: expression
| error { $$ = new NullLiteral (GetLocation ($1)); }
;
assignment_expression assignment_expression
: prefixed_unary_expression ASSIGN expression_recover : prefixed_unary_expression ASSIGN expression
{ {
$$ = new SimpleAssign ((Expression) $1, (Expression) $3, GetLocation ($2)); $$ = new SimpleAssign ((Expression) $1, (Expression) $3, GetLocation ($2));
} }
@ -5278,6 +5273,16 @@ for_statement_cont
lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation ($4), GetLocation ($6)); lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2), GetLocation ($4), GetLocation ($6));
$$ = end_block (GetLocation ($2));
}
| opt_for_initializer SEMICOLON error
{
For f = new For ((Statement) $1, null, null, null, GetLocation ($-2));
current_block.AddStatement (f);
lbag.AddStatement (f, current_block.StartLocation, GetLocation ($2));
Error_SyntaxError (yyToken);
$$ = end_block (GetLocation ($2)); $$ = end_block (GetLocation ($2));
} }
| error | error
@ -5440,7 +5445,7 @@ yield_statement
FeatureIsNotAvailable (lt.Location, "iterators"); FeatureIsNotAvailable (lt.Location, "iterators");
} }
current_block.ParametersBlock.TopBlock.IsIterator = true; current_block.Explicit.RegisterIteratorYield ();
$$ = new Yield ((Expression) $3, lt.Location); $$ = new Yield ((Expression) $3, lt.Location);
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4));
} }
@ -5454,7 +5459,7 @@ yield_statement
FeatureIsNotAvailable (lt.Location, "iterators"); FeatureIsNotAvailable (lt.Location, "iterators");
} }
current_block.ParametersBlock.TopBlock.IsIterator = true; current_block.Explicit.RegisterIteratorYield ();
$$ = new YieldBreak (lt.Location); $$ = new YieldBreak (lt.Location);
lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3));
} }
@ -5629,20 +5634,20 @@ using_statement
current_block.AddLocalName (li); current_block.AddLocalName (li);
current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li);
} }
using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS using_initialization CLOSE_PARENS
{ {
$$ = current_variable; $$ = current_variable;
current_variable = null; current_variable = null;
} }
embedded_statement embedded_statement
{ {
if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE)
Warning_EmptyStatement (GetLocation ($10)); Warning_EmptyStatement (GetLocation ($9));
Using u = new Using ((Using.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); Using u = new Using ((Using.VariableDeclaration) $8, (Statement) $9, GetLocation ($1));
lbag.AddStatement (u, GetLocation ($2), GetLocation ($8)); lbag.AddStatement (u, GetLocation ($2), GetLocation ($7));
current_block.AddStatement (u); current_block.AddStatement (u);
$$ = end_block (GetLocation ($8)); $$ = end_block (GetLocation ($7));
} }
| USING open_parens_any expression CLOSE_PARENS embedded_statement | USING open_parens_any expression CLOSE_PARENS embedded_statement
{ {
@ -5655,6 +5660,15 @@ using_statement
} }
; ;
using_initialization
: using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators
| error
{
// It has to be here for the parent to safely restore artificial block
Error_SyntaxError (yyToken);
}
;
using_or_fixed_variable_initializer using_or_fixed_variable_initializer
: /* empty */ : /* empty */
{ {
@ -6695,6 +6709,9 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block)
{ {
AnonymousMethodExpression retval; AnonymousMethodExpression retval;
if (async_block)
anon_block.IsAsync = true;
current_anonymous_method.Block = anon_block; current_anonymous_method.Block = anon_block;
retval = current_anonymous_method; retval = current_anonymous_method;

1
ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs

@ -27,6 +27,7 @@ using IKVM.Reflection.Emit;
#else #else
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
//using Mono.Collections.Generic;
#endif #endif
namespace Mono.CSharp { namespace Mono.CSharp {

13
ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

@ -529,12 +529,12 @@ namespace Mono.CSharp {
// //
// Store the result to temporary field when we // Store the result to temporary field when we
// cannot load this directly // cannot load `this' directly
// //
var field = ec.GetTemporaryField (type); var field = ec.GetTemporaryField (type);
if (needs_temporary) { if (needs_temporary) {
// //
// Create temporary local (we cannot load this before Emit) // Create temporary local (we cannot load `this' before Emit)
// //
var temp = ec.GetTemporaryLocal (type); var temp = ec.GetTemporaryLocal (type);
ec.Emit (OpCodes.Stloc, temp); ec.Emit (OpCodes.Stloc, temp);
@ -841,7 +841,7 @@ namespace Mono.CSharp {
name, was, expected); name, was, expected);
} }
public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc) public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
{ {
string [] valid = new string [4]; string [] valid = new string [4];
int count = 0; int count = 0;
@ -3692,7 +3692,7 @@ namespace Mono.CSharp {
// //
if (p.IsGenericTask || q.IsGenericTask) { if (p.IsGenericTask || q.IsGenericTask) {
var async_am = a.Expr as AnonymousMethodExpression; var async_am = a.Expr as AnonymousMethodExpression;
if (async_am != null && async_am.IsAsync) { if (async_am != null && async_am.Block.IsAsync) {
if (p.IsGenericTask != q.IsGenericTask) { if (p.IsGenericTask != q.IsGenericTask) {
return 0; return 0;
@ -5358,10 +5358,7 @@ namespace Mono.CSharp {
public void Emit (EmitContext ec, bool leave_copy) public void Emit (EmitContext ec, bool leave_copy)
{ {
bool is_volatile = false; bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
is_volatile = true;
spec.MemberDefinition.SetIsUsed (); spec.MemberDefinition.SetIsUsed ();

4
ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs

@ -9176,6 +9176,10 @@ namespace Mono.CSharp
return this; return this;
} }
public override void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
{
}
public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
{ {
} }

12
ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs

@ -158,7 +158,6 @@ namespace Mono.CSharp
} }
Field pc_field; Field pc_field;
int local_name_idx;
StateMachineMethod method; StateMachineMethod method;
protected StateMachine (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) protected StateMachine (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name)
@ -197,11 +196,6 @@ namespace Mono.CSharp
return base.DoDefineMembers (); return base.DoDefineMembers ();
} }
protected override string GetVariableMangledName (LocalVariable local_info)
{
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
} }
class IteratorStorey : StateMachine class IteratorStorey : StateMachine
@ -390,6 +384,7 @@ namespace Mono.CSharp
TypeExpr iterator_type_expr; TypeExpr iterator_type_expr;
Field current_field; Field current_field;
Field disposing_field; Field disposing_field;
int local_name_idx;
TypeExpr enumerator_type; TypeExpr enumerator_type;
TypeExpr enumerable_type; TypeExpr enumerable_type;
@ -563,6 +558,11 @@ namespace Mono.CSharp
base.EmitHoistedParameters (ec, hoisted); base.EmitHoistedParameters (ec, hoisted);
base.EmitHoistedParameters (ec, hoisted_params_copy); base.EmitHoistedParameters (ec, hoisted_params_copy);
} }
protected override string GetVariableMangledName (LocalVariable local_info)
{
return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X");
}
} }
public class StateMachineMethod : Method public class StateMachineMethod : Method

6
ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs

@ -352,6 +352,12 @@ namespace Mono.CSharp.Linq
} }
} }
public bool IsParameter {
get {
return false;
}
}
public Location Location { get; private set; } public Location Location { get; private set; }
public string Name { get; private set; } public string Name { get; private set; }

100
ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs

@ -1299,6 +1299,7 @@ namespace Mono.CSharp {
Block Block { get; } Block Block { get; }
Expression CreateReferenceExpression (ResolveContext rc, Location loc); Expression CreateReferenceExpression (ResolveContext rc, Location loc);
bool IsDeclared { get; } bool IsDeclared { get; }
bool IsParameter { get; }
Location Location { get; } Location Location { get; }
} }
@ -1457,6 +1458,13 @@ namespace Mono.CSharp {
if (Initializer != null) { if (Initializer != null) {
((VarExpr) type_expr).InferType (bc, Initializer); ((VarExpr) type_expr).InferType (bc, Initializer);
type = type_expr.Type; type = type_expr.Type;
} else {
// Set error type to indicate the var was placed correctly but could
// not be infered
//
// var a = missing ();
//
type = InternalType.ErrorType;
} }
} }
@ -1717,6 +1725,12 @@ namespace Mono.CSharp {
} }
} }
bool INamedBlockVariable.IsParameter {
get {
return false;
}
}
public bool IsReadonly { public bool IsReadonly {
get { get {
return (flags & Flags.ReadonlyMask) != 0; return (flags & Flags.ReadonlyMask) != 0;
@ -1907,13 +1921,14 @@ namespace Mono.CSharp {
Unchecked = 1, Unchecked = 1,
HasRet = 8, HasRet = 8,
Unsafe = 16, Unsafe = 16,
IsIterator = 32,
HasCapturedVariable = 64, HasCapturedVariable = 64,
HasCapturedThis = 1 << 7, HasCapturedThis = 1 << 7,
IsExpressionTree = 1 << 8, IsExpressionTree = 1 << 8,
CompilerGenerated = 1 << 9, CompilerGenerated = 1 << 9,
IsAsync = 1 << 10, HasAsyncModifier = 1 << 10,
Resolved = 1 << 11 Resolved = 1 << 11,
YieldBlock = 1 << 12,
AwaitBlock = 1 << 13
} }
public Block Parent; public Block Parent;
@ -2303,6 +2318,12 @@ namespace Mono.CSharp {
} }
} }
public bool HasAwait {
get {
return (flags & Flags.AwaitBlock) != 0;
}
}
public bool HasCapturedThis { public bool HasCapturedThis {
set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; } set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; }
get { get {
@ -2317,6 +2338,12 @@ namespace Mono.CSharp {
} }
} }
public bool HasYield {
get {
return (flags & Flags.YieldBlock) != 0;
}
}
#endregion #endregion
// //
@ -2325,15 +2352,17 @@ namespace Mono.CSharp {
public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec) public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec)
{ {
// //
// An iterator has only 1 storey block // Return same story for iterator and async blocks unless we are
// in nested anonymous method
// //
if (ec.CurrentAnonymousMethod.IsIterator) if (ec.CurrentAnonymousMethod is StateMachineInitializer && ParametersBlock.Original == ec.CurrentAnonymousMethod.Block.Original)
return ec.CurrentAnonymousMethod.Storey; return ec.CurrentAnonymousMethod.Storey;
// //
// When referencing a variable in iterator storey from children anonymous method // When referencing a variable in parent iterator/async storey
// from nested anonymous method
// //
if (ParametersBlock.am_storey is IteratorStorey) { if (ParametersBlock.am_storey is StateMachine) {
return ParametersBlock.am_storey; return ParametersBlock.am_storey;
} }
@ -2420,6 +2449,32 @@ namespace Mono.CSharp {
am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey); am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
} }
public void RegisterAsyncAwait ()
{
var block = this;
while ((block.flags & Flags.AwaitBlock) == 0) {
block.flags |= Flags.AwaitBlock;
if (block.Parent == null)
return;
block = block.Parent.Explicit;
}
}
public void RegisterIteratorYield ()
{
var block = this;
while ((block.flags & Flags.YieldBlock) == 0) {
block.flags |= Flags.YieldBlock;
if (block.Parent == null)
return;
block = block.Parent.Explicit;
}
}
public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock) public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock)
{ {
tryBlock.statements = statements; tryBlock.statements = statements;
@ -2461,6 +2516,12 @@ namespace Mono.CSharp {
} }
} }
public bool IsParameter {
get {
return true;
}
}
public bool IsLocked { public bool IsLocked {
get { get {
return is_locked; return is_locked;
@ -2556,6 +2617,8 @@ namespace Mono.CSharp {
this.parameters = parameters; this.parameters = parameters;
ParametersBlock = this; ParametersBlock = this;
flags |= (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
this.top_block = parent.ParametersBlock.top_block; this.top_block = parent.ParametersBlock.top_block;
ProcessParameters (); ProcessParameters ();
} }
@ -2595,13 +2658,12 @@ namespace Mono.CSharp {
#region Properties #region Properties
public bool IsAsync public bool IsAsync {
{
get { get {
return (flags & Flags.IsAsync) != 0; return (flags & Flags.HasAsyncModifier) != 0;
} }
set { set {
flags = value ? flags | Flags.IsAsync : flags & ~Flags.IsAsync; flags = value ? flags | Flags.HasAsyncModifier : flags & ~Flags.HasAsyncModifier;
} }
} }
@ -2631,7 +2693,7 @@ namespace Mono.CSharp {
public bool Resolved { public bool Resolved {
get { get {
return resolved; return (flags & Flags.Resolved) != 0;
} }
} }
@ -2805,12 +2867,14 @@ namespace Mono.CSharp {
ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation);
pb.EndLocation = EndLocation; pb.EndLocation = EndLocation;
pb.statements = statements; pb.statements = statements;
pb.original = this;
var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable); var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable);
am_storey = new IteratorStorey (iterator); am_storey = new IteratorStorey (iterator);
statements = new List<Statement> (1); statements = new List<Statement> (1);
AddStatement (new Return (iterator, iterator.Location)); AddStatement (new Return (iterator, iterator.Location));
flags &= ~Flags.YieldBlock;
} }
public void WrapIntoAsyncTask (IMemberContext context, TypeContainer host, TypeSpec returnType) public void WrapIntoAsyncTask (IMemberContext context, TypeContainer host, TypeSpec returnType)
@ -2818,6 +2882,7 @@ namespace Mono.CSharp {
ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation);
pb.EndLocation = EndLocation; pb.EndLocation = EndLocation;
pb.statements = statements; pb.statements = statements;
pb.original = this;
var block_type = host.Module.Compiler.BuiltinTypes.Void; var block_type = host.Module.Compiler.BuiltinTypes.Void;
var initializer = new AsyncInitializer (pb, host, block_type); var initializer = new AsyncInitializer (pb, host, block_type);
@ -2827,6 +2892,7 @@ namespace Mono.CSharp {
statements = new List<Statement> (1); statements = new List<Statement> (1);
AddStatement (new StatementExpression (initializer)); AddStatement (new StatementExpression (initializer));
flags &= ~Flags.AwaitBlock;
} }
} }
@ -2873,13 +2939,9 @@ namespace Mono.CSharp {
top_block = this; top_block = this;
} }
public bool IsIterator public bool IsIterator {
{
get { get {
return (flags & Flags.IsIterator) != 0; return HasYield;
}
set {
flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator;
} }
} }

Loading…
Cancel
Save