2003/11/10 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / argument.cs
1 //
2 // argument.cs: Arguments representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 #define USE_OLD
11
12 namespace Mono.MonoBASIC {
13         using System;
14         using System.Collections;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Text;
18
19         
20         /// <summary>
21         ///   Used for arguments to New(), Invocation()
22         /// </summary>
23         public class Argument {
24                 public enum AType : byte {
25                         Expression,
26                         Ref,
27                         Out,
28                         NoArg
29                 };
30
31                 public AType ArgType;
32                 public Expression Expr;
33                 
34                 public Argument (Expression expr, AType type)
35                 {
36                         this.Expr = expr;
37                         this.ArgType = type;
38                 }
39
40                 public Type Type {
41                         get {
42                                 if (ArgType == AType.Ref || ArgType == AType.Out)
43                                         return TypeManager.LookupType (Expr.Type.ToString () + "&");
44                                 else
45                                         return Expr.Type;
46                         }
47                 }
48
49                 public Parameter.Modifier GetParameterModifier ()
50                 {
51                         switch (ArgType) {
52                         case AType.Out:
53                                 return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF;
54
55                         case AType.Ref:
56                                 return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
57
58                         default:
59                                 return Parameter.Modifier.NONE;
60                         }
61                 }
62
63                 public static string FullDesc (Argument a)
64                 {
65                         return (a.ArgType == AType.Ref ? "ref " :
66                                 (a.ArgType == AType.Out ? "out " : "")) +
67                                 TypeManager.MonoBASIC_Name (a.Expr.Type);
68                 }
69
70                 public bool ResolveMethodGroup (EmitContext ec, Location loc)
71                 {
72                         // FIXME: csc doesn't report any error if you try to use `ref' or
73                         //        `out' in a delegate creation expression.
74                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
75                         if (Expr == null)
76                                 return false;
77
78                         return true;
79                 }
80
81                 public bool Resolve (EmitContext ec, Location loc)
82                 {
83                         // Optional void arguments - MyCall (1,,2) - are resolved later
84                         // in VerifyArgsCompat
85                         if (ArgType == AType.NoArg || ArgType == AType.Ref) 
86                         {
87                                 return true;                            
88                         }
89 /*
90                         if (ArgType == AType.Ref) {
91                                 Expr = Expr.Resolve (ec);
92                                 if (Expr == null)
93                                         return false;
94
95                                 Expr = Expr.ResolveLValue (ec, Expr);
96                         } else */if (ArgType == AType.Out)
97                                 Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
98                         else
99                                 Expr = Expr.Resolve (ec);
100
101
102                         if (Expr == null)
103                                 return false;
104
105                         if (ArgType == AType.Expression)
106                                 return true;
107
108                         if (Expr.eclass != ExprClass.Variable){
109                                 //
110                                 // We just probe to match the CSC output
111                                 //
112                                 if (Expr.eclass == ExprClass.PropertyAccess ||
113                                     Expr.eclass == ExprClass.IndexerAccess){
114                                         Report.Error (
115                                                 206, loc,
116                                                 "A property or indexer can not be passed as an out or ref " +
117                                                 "parameter");
118                                 } else {
119                                         Report.Error (
120                                                 1510, loc,
121                                                 "An lvalue is required as an argument to out or ref");
122                                 }
123                                 return false;
124                         }
125                                 
126                         return true;
127                 }
128
129                 public void Emit (EmitContext ec)
130                 {
131                         //
132                         // Ref and Out parameters need to have their addresses taken.
133                         //
134                         // ParameterReferences might already be references, so we want
135                         // to pass just the value
136                         //
137                         if (ArgType == AType.Ref || ArgType == AType.Out){
138                                 AddressOp mode = AddressOp.Store;
139
140                                 if (ArgType == AType.Ref)
141                                         mode |= AddressOp.Load;
142                                 
143                                 if (Expr is ParameterReference){
144                                         ParameterReference pr = (ParameterReference) Expr;
145
146                                         if (pr.is_ref)
147                                                 pr.EmitLoad (ec);
148                                         else {
149                                                 
150                                                 pr.AddressOf (ec, mode);
151                                         }
152                                 } else
153                                         ((IMemoryLocation)Expr).AddressOf (ec, mode);
154                         } else
155                                 Expr.Emit (ec);
156                 }
157         }
158 }