* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / ast.cs
1 //
2 // ast.cs: Base class for the EcmaScript program tree representation.
3 //
4 // Author: 
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, Cesar Lopez Nataren
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Collections;
33 using System.Reflection;
34 using System.Reflection.Emit;
35
36 namespace Microsoft.JScript {
37
38         public abstract class AST {
39
40                 internal AST parent;
41
42                 internal Location location;
43                 internal Location Location {
44                         get { return location; }
45                 }
46
47                 internal AST (AST parent, Location location)
48                 {
49                         this.parent = parent;
50                         this.location = location;
51                 }
52
53                 //
54                 // Here the actual IL code generation happens.
55                 //
56                 internal abstract void Emit (EmitContext ec);
57                         
58                 //
59                 // Perform type checks and associates expressions
60                 // with their declarations
61                 //
62                 internal abstract bool Resolve (Environment env);
63
64                 internal bool InLoop {
65                         get {
66                                 if (parent == null || parent is ScriptBlock)
67                                         return false;
68                                 else if (parent is DoWhile || parent is While || parent is For || parent is ForIn)
69                                         return true;
70                                 else
71                                         return parent.InLoop;
72                         }
73                 }
74                 
75                 internal bool InSwitch {
76                         get { 
77                                 if (parent == null)
78                                         return false;
79                                 else if (parent is Switch)
80                                         return true;
81                                 else
82                                         return parent.InSwitch;
83                         }
84                 }
85
86                 internal bool InFunction {
87                         get {
88                                 if (parent == null || parent.GetType () == typeof (ScriptBlock))
89                                         return false;
90                                 else if (parent is FunctionDeclaration || parent is FunctionExpression)
91                                         return true;
92                                 else
93                                         return parent.InFunction;
94                         }
95                 }
96                 
97                 internal Function GetContainerFunction {
98                         get {
99                                 if (parent == null)
100                                         return null;
101                                 if (parent is Function)
102                                         return parent as Function;
103                                 return parent.GetContainerFunction;
104                                 
105                         }
106                 }
107
108                 internal virtual void PropagateParent (AST parent)
109                 {
110                         this.parent = parent;
111                 }
112         }
113
114         public abstract class Function : AST 
115         {
116                 bool check_this;
117                 bool ignore_dynamic_scope;
118                 bool requires_activation;
119
120                 internal string prefix;
121                 internal FunctionObject func_obj;
122                 internal JSFunctionAttributeEnum func_type;
123
124                 internal object [] locals;
125                 internal LocalBuilder local_func;
126                 
127                 protected bool not_void_return = false;
128                 protected ILGenerator ig;
129
130                 internal Function (AST parent, Location location)
131                         : base (parent, location)
132                 {
133                 }
134
135                 internal bool CheckThis {
136                         get { return check_this; }
137                         set { check_this = value; }
138                 }
139
140                 internal bool IgnoreDynamicScope {
141                         get { return ignore_dynamic_scope; }
142                         set { ignore_dynamic_scope = value; }
143                 }
144
145                 internal bool RequiresActivation {
146                         get { return requires_activation; }
147                         set { requires_activation = value; }
148                 }
149
150                 internal int NumOfArgs {
151                         get { 
152                                 if (func_obj != null)
153                                         return func_obj.parameters.size;
154                                 // throw new Exception ("func_obj is null, can't obtain the number of arguments");
155
156                                 // indicate that at the later stage we
157                                 // must check the proper number of
158                                 // args and formal parameters
159                                 return -1;
160                         }
161                 }
162
163                 internal void Init (Block body, FormalParameterList p)
164                 {
165                         func_obj.body = body;
166                         func_obj.parameters = p;
167                 }
168
169                 internal void set_prefix ()
170                 {
171                         if (parent != null && InFunction) {
172                                 Function tmp;
173                                 tmp = GetContainerFunction;
174                                 if (tmp.prefix != String.Empty)
175                                         prefix = tmp.prefix + "." + tmp.func_obj.name;
176                                 else
177                                         prefix = tmp.func_obj.name;
178                         } else
179                                 prefix = String.Empty;
180                 }
181
182                 internal void set_function_type ()
183                 {
184                         if (parent == null || parent.GetType () == typeof (ScriptBlock))
185                                 func_type = JSFunctionAttributeEnum.ClassicFunction;
186                         else if (parent is FunctionDeclaration)
187                                 func_type = JSFunctionAttributeEnum.NestedFunction;
188                 }
189
190                 internal void set_custom_attr (MethodBuilder mb)
191                 {
192                         CustomAttributeBuilder attr_builder;
193                         Type func_attr = typeof (JSFunctionAttribute);
194                         Type [] func_attr_enum = new Type [] {typeof (JSFunctionAttributeEnum)};
195                         attr_builder = new CustomAttributeBuilder (func_attr.GetConstructor (func_attr_enum), 
196                                                                    new object [] {func_type});
197                         mb.SetCustomAttribute (attr_builder);                   
198                 }
199
200                 internal void NotVoidReturnHappened (object sender, NotVoidReturnEventArgs args)
201                 {                       
202                         not_void_return = true;
203                 }
204
205                 internal Type HandleReturnType {
206                         get {
207                                 Type ret_type;
208                                 if (not_void_return)
209                                         ret_type = typeof (object);
210                                 else
211                                         ret_type = typeof (void);
212                                 return ret_type;
213                         }
214                 }
215
216                 internal void emit_return_local_field (ILGenerator ig, ConstructorInfo ctr_info, int n)
217                 {
218                         ig.Emit (OpCodes.Dup);
219                         ig.Emit (OpCodes.Ldc_I4, n);
220                         ig.Emit (OpCodes.Ldstr, "return value");
221                         ig.Emit (OpCodes.Ldtoken, typeof (object));
222                         ig.Emit (OpCodes.Ldc_I4, n);
223                         ig.Emit (OpCodes.Newobj, ctr_info);
224                         ig.Emit (OpCodes.Stelem_Ref);
225                 }
226
227                 internal string GetName (object ast)
228                 {
229                         if (ast is VariableDeclaration)
230                                 return ((VariableDeclaration) ast).id;
231                         else if (ast is FormalParam)
232                                 return ((FormalParam) ast).id;
233                         else if (ast is FunctionDeclaration || ast is FunctionExpression)
234                                 return ((Function) ast).func_obj.name;
235                         else throw new Exception ("GetName unknown type " + ast.GetType ().ToString ());
236                 }
237         }
238 }