+2003-07-22 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (invocation_expression): Moved
+ `OPEN_PARENS expression CLOSE_PARENS unary_expression' here from
+ `cast_expression', but create a InvocationOrCast which later
+ resolves to either an Invocation or a Cast.
+
+ * ecore.cs (ExpressionStatement.ResolveStatement): New virtual
+ method; call this before EmitStatement() to make sure that this
+ expression can be used as a statement.
+
+ * expression.cs (InvocationOrCast): New class; resolves to either
+ an Invocation or a Cast.
+
+ * statement.cs (StatementExpression): Call ResolveStatement() on
+ the ExpressionStatement before emitting it.
+
2003-07-21 Martin Baulig <martin@ximian.com>
* expression.cs (Invocation.VerifyArgumentsCompat): Check whether
Location l = f.Location;
FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
fe.InstanceExpression = instance_expr;
- Expression a = new Assign (fe, e, l);
+ ExpressionStatement a = new Assign (fe, e, l);
- a = a.Resolve (ec);
+ a = a.ResolveStatement (ec);
if (a == null)
return false;
- if (a is ExpressionStatement)
- ((ExpressionStatement) a).EmitStatement (ec);
- else {
- throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
- }
+ a.EmitStatement (ec);
}
return true;
}
$$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
}
- ;
+ | OPEN_PARENS expression CLOSE_PARENS unary_expression
+ {
+ $$ = new InvocationOrCast ((Expression) $2, (Expression) $4, lexer.Location);
+ }
+ ;
opt_argument_list
: /* empty */ { $$ = null; }
;
cast_expression
- : OPEN_PARENS expression CLOSE_PARENS unary_expression
- {
- $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
- }
- | OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
+ : OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
{
$$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
}
/// </summary>
public abstract class ExpressionStatement : Expression {
+ public virtual ExpressionStatement ResolveStatement (EmitContext ec)
+ {
+ Expression e = Resolve (ec);
+ if (e == null)
+ return null;
+
+ ExpressionStatement es = e as ExpressionStatement;
+ if (es == null)
+ Error (201, "Only assignment, call, increment, decrement and new object " +
+ "expressions can be used as a statement");
+
+ return es;
+ }
+
/// <summary>
/// Requests the expression to be emitted in a `statement'
/// context. This means that no new value is left on the
}
}
+ public class InvocationOrCast : ExpressionStatement
+ {
+ Expression expr;
+ Expression argument;
+
+ public InvocationOrCast (Expression expr, Expression argument, Location loc)
+ {
+ this.expr = expr;
+ this.argument = argument;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // First try to resolve it as a cast.
+ //
+ type = ec.DeclSpace.ResolveType (expr, true, loc);
+ if (type != null) {
+ Cast cast = new Cast (new TypeExpr (type, loc), argument, loc);
+ return cast.Resolve (ec);
+ }
+
+ //
+ // This can either be a type or a delegate invocation.
+ // Let's just resolve it and see what we'll get.
+ //
+ expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+ if (expr == null)
+ return null;
+
+ //
+ // Ok, so it's a Cast.
+ //
+ if (expr.eclass == ExprClass.Type) {
+ Cast cast = new Cast (new TypeExpr (expr.Type, loc), argument, loc);
+ return cast.Resolve (ec);
+ }
+
+ //
+ // It's a delegate invocation.
+ //
+ if (!TypeManager.IsDelegateType (expr.Type)) {
+ Error (149, "Method name expected");
+ return null;
+ }
+
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (argument, Argument.AType.Expression));
+ DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+ return invocation.Resolve (ec);
+ }
+
+ void error201 ()
+ {
+ Error (201, "Only assignment, call, increment, decrement and new object " +
+ "expressions can be used as a statement");
+ }
+
+ public override ExpressionStatement ResolveStatement (EmitContext ec)
+ {
+ //
+ // First try to resolve it as a cast.
+ //
+ type = ec.DeclSpace.ResolveType (expr, true, loc);
+ if (type != null) {
+ error201 ();
+ return null;
+ }
+
+ //
+ // This can either be a type or a delegate invocation.
+ // Let's just resolve it and see what we'll get.
+ //
+ expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+ if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+ error201 ();
+ return null;
+ }
+
+ //
+ // It's a delegate invocation.
+ //
+ if (!TypeManager.IsDelegateType (expr.Type)) {
+ Error (149, "Method name expected");
+ return null;
+ }
+
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (argument, Argument.AType.Expression));
+ DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+ return invocation.ResolveStatement (ec);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new Exception ("Cannot happen");
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ throw new Exception ("Cannot happen");
+ }
+ }
+
//
// This class is used to "disable" the code generation for the
// temporary variable when initializing value types.