From af7526866cc262e9e9be0364d50da2a32cc9d0b1 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Tue, 22 Jul 2003 19:01:08 +0000 Subject: [PATCH] 2003-07-22 Martin Baulig * 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. svn path=/trunk/mcs/; revision=16537 --- mcs/mcs/ChangeLog | 17 +++++++ mcs/mcs/class.cs | 10 ++-- mcs/mcs/cs-parser.jay | 12 ++--- mcs/mcs/ecore.cs | 14 ++++++ mcs/mcs/expression.cs | 105 ++++++++++++++++++++++++++++++++++++++++++ mcs/mcs/statement.cs | 11 ++--- 6 files changed, 148 insertions(+), 21 deletions(-) diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog index 706c2209be6..ed9262a950f 100755 --- a/mcs/mcs/ChangeLog +++ b/mcs/mcs/ChangeLog @@ -1,3 +1,20 @@ +2003-07-22 Martin Baulig + + * 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 * expression.cs (Invocation.VerifyArgumentsCompat): Check whether diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 5024864c14a..19ee88d1b09 100755 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -553,17 +553,13 @@ namespace Mono.CSharp { 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; diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 0310a7c3305..71a65608256 100755 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -2046,7 +2046,11 @@ invocation_expression } $$ = 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; } @@ -2394,11 +2398,7 @@ unary_expression ; 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); } diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index a7dc5e4a010..c10835bdae4 100755 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -1282,6 +1282,20 @@ namespace Mono.CSharp { /// 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; + } + /// /// Requests the expression to be emitted in a `statement' /// context. This means that no new value is left on the diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index da4ef718e38..966484c26a6 100755 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -5013,6 +5013,111 @@ namespace Mono.CSharp { } } + 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. diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs index 376d82dc17a..e6f8eeee053 100755 --- a/mcs/mcs/statement.cs +++ b/mcs/mcs/statement.cs @@ -544,7 +544,7 @@ namespace Mono.CSharp { } public class StatementExpression : Statement { - Expression expr; + ExpressionStatement expr; public StatementExpression (ExpressionStatement expr, Location l) { @@ -554,7 +554,7 @@ namespace Mono.CSharp { public override bool Resolve (EmitContext ec) { - expr = (Expression) expr.Resolve (ec); + expr = expr.ResolveStatement (ec); return expr != null; } @@ -562,12 +562,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - if (expr is ExpressionStatement) - ((ExpressionStatement) expr).EmitStatement (ec); - else { - expr.Emit (ec); - ig.Emit (OpCodes.Pop); - } + expr.EmitStatement (ec); return false; } -- 2.25.1