return s;
}
+ public virtual Expression CreateExpressionTree (EmitContext ec)
+ {
+ Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
+ return null;
+ }
+
public Statement PerformClone ()
{
CloneContext clonectx = new CloneContext ();
//
// Dead code elimination
//
- if (expr is BoolConstant){
- bool take = ((BoolConstant) expr).Value;
+ if (expr is Constant){
+ bool take = !((Constant) expr).IsDefaultValue;
if (take){
if (!TrueStatement.Resolve (ec))
Label end;
//
- // If we're a boolean expression, Resolve() already
+ // If we're a boolean constant, Resolve() already
// eliminated dead code for us.
//
- if (expr is BoolConstant){
- bool take = ((BoolConstant) expr).Value;
+ if (expr is Constant){
+
+ //
+ // Simple bool constant
+ //
+ if (expr is BoolConstant) {
+ bool take = ((BoolConstant) expr).Value;
- if (take)
+ if (take)
+ TrueStatement.Emit (ec);
+ else if (FalseStatement != null)
+ FalseStatement.Emit (ec);
+
+ return;
+ }
+
+ //
+ // Bool constant with side-effects
+ //
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Pop);
+
+ if (TrueStatement != null)
TrueStatement.Emit (ec);
- else if (FalseStatement != null)
+ if (FalseStatement != null)
FalseStatement.Emit (ec);
return;
Statement.Emit (ec);
ig.MarkLabel (ec.LoopBegin);
+ ec.Mark (loc, true);
expr.EmitBranchable (ec, while_loop, true);
ec.LoopEnd = old_end;
}
+ public override void Emit (EmitContext ec)
+ {
+ DoEmit (ec);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
While target = (While) t;
if (Expr.Type != ec.ReturnType) {
if (ec.InferReturnType) {
+ //
+ // void cannot be used in contextual return
+ //
+ if (Expr.Type == TypeManager.void_type)
+ return false;
+
ec.ReturnType = Expr.Type;
} else {
Expr = Convert.ImplicitConversionRequired (
{
Throw target = (Throw) t;
- target.expr = expr.Clone (clonectx);
+ if (expr != null)
+ target.expr = expr.Clone (clonectx);
}
}
public void EmitSymbolInfo (EmitContext ec, string name)
{
if (builder != null)
- ec.DefineLocalVariable (name, builder);
+ ec.DefineLocalVariable (Name, builder);
}
public bool IsThisAssigned (EmitContext ec)
//
// Labels. (label, block) pairs.
//
- Hashtable labels;
+ HybridDictionary labels;
//
// Keeps track of (name, type) pairs
//
// Keeps track of constants
- Hashtable constants;
+ HybridDictionary constants;
//
// Temporary variables.
//
Block switch_block;
+ // TODO: merge with scope_initializers
ExpressionStatement scope_init;
+ ArrayList scope_initializers;
ArrayList anonymous_children;
this.EndLocation = end;
this.loc = start;
this_id = id++;
- statements = new ArrayList ();
+ statements = new ArrayList (4);
}
public Block CreateSwitchBlock (Location start)
void AddChild (Block b)
{
if (children == null)
- children = new ArrayList ();
+ children = new ArrayList (1);
children.Add (b);
}
Toplevel.CheckError158 (name, target.loc);
if (labels == null)
- labels = new Hashtable ();
+ labels = new HybridDictionary();
labels.Add (name, target);
return true;
return false;
if (constants == null)
- constants = new Hashtable ();
+ constants = new HybridDictionary();
constants.Add (name, value);
}
return null;
}
+
+ //
+ // It should be used by expressions which require to
+ // register a statement during resolve process.
+ //
+ public void AddScopeStatement (StatementExpression s)
+ {
+ if (scope_initializers == null)
+ scope_initializers = new ArrayList ();
+
+ scope_initializers.Add (s);
+ }
public void AddStatement (Statement s)
{
LocalInfo vi = (LocalInfo) de.Value;
Type variable_type = vi.VariableType;
- if (variable_type == null)
+ if (variable_type == null) {
+ if (vi.Type is VarExpr)
+ Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
+
continue;
+ }
Expression cv = (Expression) constants [name];
if (cv == null)
}
if (temporary_variables != null) {
- foreach (LocalInfo vi in temporary_variables)
- vi.ResolveVariable (ec);
+ for (int i = 0; i < temporary_variables.Count; i++)
+ ((LocalInfo)temporary_variables[i]).ResolveVariable(ec);
}
if (children != null){
- foreach (Block b in children)
- b.EmitMeta (ec);
+ for (int i = 0; i < children.Count; i++)
+ ((Block)children[i]).EmitMeta(ec);
}
}
//
if (!s.Resolve (ec)) {
+ ok = false;
if (ec.IsInProbingMode)
- return false;
+ break;
- ok = false;
statements [ix] = EmptyStatement.Value;
continue;
}
Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
ec.CurrentBranching, statement_count, num_statements);
- if (!ok)
- return false;
-
while (ec.CurrentBranching is FlowBranchingLabeled)
ec.EndFlowBranching ();
ec.CurrentBlock = this;
- bool emit_debug_info = (CodeGen.SymbolWriter != null);
- bool is_lexical_block = this == Explicit && Parent != null;
+ bool emit_debug_info = SymbolWriter.HasSymbolWriter;
+ bool is_lexical_block = (this == Explicit) && (Parent != null) &&
+ ((flags & Flags.IsIterator) == 0);
+
+ bool omit_debug_info = ec.OmitDebuggingInfo;
if (emit_debug_info) {
if (is_lexical_block)
ec.BeginScope ();
}
- ec.Mark (StartLocation, true);
- if (scope_init != null)
+
+ if ((scope_init != null) || (scope_initializers != null))
+ SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
+
+ if (scope_init != null) {
+ ec.OmitDebuggingInfo = true;
scope_init.EmitStatement (ec);
+ ec.OmitDebuggingInfo = omit_debug_info;
+ }
+ if (scope_initializers != null) {
+ ec.OmitDebuggingInfo = true;
+ foreach (StatementExpression s in scope_initializers)
+ s.Emit (ec);
+ ec.OmitDebuggingInfo = omit_debug_info;
+ }
+
+ if ((scope_init != null) || (scope_initializers != null))
+ SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
+
+ ec.Mark (StartLocation, true);
DoEmit (ec);
- ec.Mark (EndLocation, true);
if (emit_debug_info) {
+ EmitSymbolInfo (ec);
+
if (is_lexical_block)
ec.EndScope ();
+ }
- if (variables != null) {
- foreach (DictionaryEntry de in variables) {
- string name = (string) de.Key;
- LocalInfo vi = (LocalInfo) de.Value;
+ ec.CurrentBlock = prev_block;
+ }
- vi.EmitSymbolInfo (ec, name);
- }
+ protected virtual void EmitSymbolInfo (EmitContext ec)
+ {
+ if (variables != null) {
+ foreach (DictionaryEntry de in variables) {
+ string name = (string) de.Key;
+ LocalInfo vi = (LocalInfo) de.Value;
+
+ vi.EmitSymbolInfo (ec, name);
}
}
-
- ec.CurrentBlock = prev_block;
}
public override string ToString ()
this.Explicit = this;
}
- Hashtable known_variables;
+ public bool IsIterator {
+ get { return (flags & Flags.IsIterator) != 0; }
+ }
+
+ HybridDictionary known_variables;
// <summary>
// Marks a variable with name @name as being used in this or a child block.
internal void AddKnownVariable (string name, IKnownVariable info)
{
if (known_variables == null)
- known_variables = new Hashtable ();
+ known_variables = new HybridDictionary();
known_variables [name] = info;
set { flags |= Flags.HasVarargs; }
}
- public bool IsIterator {
- get { return (flags & Flags.IsIterator) != 0; }
- }
-
//
// The parameters for the block.
//
return root_scope;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ return ((Statement) statements [0]).CreateExpressionTree (ec);
+ }
+
public void CreateIteratorHost (RootScopeInfo root)
{
Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope);
public override void EmitMeta (EmitContext ec)
{
+ // Avoid declaring an IL variable for this_variable since it is not accessed
+ // from the generated IL
+ if (this_variable != null)
+ Variables.Remove ("this");
base.EmitMeta (ec);
parameters.ResolveVariable (this);
}
+ protected override void EmitSymbolInfo (EmitContext ec)
+ {
+ if ((AnonymousContainer != null) && (AnonymousContainer.Scope != null))
+ SymbolWriter.DefineScopeVariable (AnonymousContainer.Scope.ID);
+
+ base.EmitSymbolInfo (ec);
+ }
+
public void MakeIterator (Iterator iterator)
{
flags |= Flags.IsIterator;
- Block block = new ExplicitBlock (this, StartLocation, EndLocation);
+ Block block = new ExplicitBlock (this, flags, StartLocation, EndLocation);
foreach (Statement stmt in statements)
block.AddStatement (stmt);
statements.Clear ();
return true;
}
- public void Erorr_AlreadyOccurs (Type switch_type, SwitchLabel collision_with)
+ public void Error_AlreadyOccurs (Type switch_type, SwitchLabel collision_with)
{
string label;
if (converted == null)
//
Expression SwitchGoverningType (EmitContext ec, Expression expr)
{
- Type t = TypeManager.DropGenericTypeArguments (expr.Type);
+ Type t = expr.Type;
if (t == TypeManager.byte_type ||
t == TypeManager.sbyte_type ||
t == TypeManager.char_type ||
t == TypeManager.string_type ||
t == TypeManager.bool_type ||
- t.IsSubclassOf (TypeManager.enum_type))
+ TypeManager.IsEnumType (t))
return expr;
if (allowed_types == null){
foreach (SwitchLabel sl in ss.Labels){
if (sl.Label == null){
if (default_section != null){
- sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]);
+ sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]);
error = true;
}
default_section = ss;
try {
Elements.Add (key, sl);
} catch (ArgumentException) {
- sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]);
+ sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]);
error = true;
}
}
Type compare_type;
if (TypeManager.IsEnumType (SwitchType))
- compare_type = TypeManager.EnumToUnderlying (SwitchType);
+ compare_type = TypeManager.GetEnumUnderlyingType (SwitchType);
else
compare_type = SwitchType;
}
bool first = true;
+ bool ok = true;
foreach (SwitchSection ss in Sections){
if (!first)
ec.CurrentBranching.CreateSibling (
// one single section - mark all the others as
// unreachable.
ec.CurrentBranching.CurrentUsageVector.Goto ();
- if (!ss.Block.ResolveUnreachable (ec, true))
- return false;
+ if (!ss.Block.ResolveUnreachable (ec, true)) {
+ ok = false;
+ }
} else {
if (!ss.Block.Resolve (ec))
- return false;
+ ok = false;
}
}
Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching);
- return true;
+ if (TypeManager.string_isinterned_string == null) {
+ TypeManager.string_isinterned_string = TypeManager.GetPredefinedMethod (TypeManager.string_type,
+ "IsInterned", loc, TypeManager.string_type);
+ }
+
+ return ok;
}
protected override void DoEmit (EmitContext ec)
temp = new TemporaryVariable (t, loc);
temp.Resolve (ec);
+
+ if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
+ Type monitor_type = TypeManager.CoreLookupType ("System.Threading", "Monitor", Kind.Class, true);
+ TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod (
+ monitor_type, "Enter", loc, TypeManager.object_type);
+ TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod (
+ monitor_type, "Exit", loc, TypeManager.object_type);
+ }
return ok;
}
return false;
}
- TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false);
- if (texpr == null)
+ TypeExpr texpr = type.ResolveAsContextualType (ec, false);
+ if (texpr == null) {
+ if (type is VarExpr)
+ Report.Error (821, type.Location, "A fixed statement cannot use an implicitly typed local variable");
+
return false;
+ }
expr_type = texpr.Type;
// fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0])
//
converted = new Conditional (new Binary (Binary.Operator.LogicalOr,
- new Binary (Binary.Operator.Equality, e, new NullConstant (loc)),
+ new Binary (Binary.Operator.Equality, e, new NullLiteral (loc)),
new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))),
NullPointer.Null,
converted);
type = te.Type;
- if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
+ if (type != TypeManager.exception_type && !TypeManager.IsSubclassOf (type, TypeManager.exception_type)){
Error (155, "The type caught or thrown must be derived from System.Exception");
return false;
}
Type resolved_type = c.CatchType;
for (int ii = 0; ii < last_index; ++ii) {
- if (resolved_type == prev_catches [ii] || resolved_type.IsSubclassOf (prev_catches [ii])) {
+ if (resolved_type == prev_catches [ii] || TypeManager.IsSubclassOf (resolved_type, prev_catches [ii])) {
Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prev_catches [ii].FullName);
return false;
}
// So, ensure there's some IL code after the finally block.
ec.NeedReturnLabel ();
+ if (TypeManager.void_dispose_void == null) {
+ TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
+ TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes);
+ }
+
return ok;
}
{
Using target = (Using) t;
- if (expression_or_block is Expression)
+ if (expression_or_block is Expression) {
target.expression_or_block = ((Expression) expression_or_block).Clone (clonectx);
- else
- target.expression_or_block = ((Statement) expression_or_block).Clone (clonectx);
+ } else {
+ DictionaryEntry de = (DictionaryEntry) expression_or_block;
+ ArrayList var_list = (ArrayList) de.Value;
+ ArrayList target_var_list = new ArrayList (var_list.Count);
+
+ foreach (DictionaryEntry de_variable in var_list)
+ target_var_list.Add (new DictionaryEntry (
+ ((Expression) de_variable.Key).Clone (clonectx),
+ ((Expression) de_variable.Value).Clone (clonectx)));
+
+ target.expression_or_block = new DictionaryEntry (
+ ((Expression) de.Key).Clone (clonectx),
+ target_var_list);
+ }
target.Statement = Statement.Clone (clonectx);
}
// way I could do this without a goto
//
+ if (TypeManager.bool_movenext_void == null) {
+ TypeManager.bool_movenext_void = TypeManager.GetPredefinedMethod (
+ TypeManager.ienumerator_type, "MoveNext", loc, Type.EmptyTypes);
+ }
+
+ if (TypeManager.ienumerator_getcurrent == null) {
+ TypeManager.ienumerator_getcurrent = TypeManager.GetPredefinedProperty (
+ TypeManager.ienumerator_type, "Current", loc, TypeManager.object_type);
+ }
+
#if GMCS_SOURCE
//
// Prefer a generic enumerator over a non-generic one.
if (is_disposable) {
ResolveFinally (branching);
ec.EndFlowBranching ();
+
+ if (TypeManager.void_dispose_void == null) {
+ TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
+ TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes);
+ }
} else
emit_finally = true;