2 // ast.cs: Base class for the EcmaScript program tree representation.
5 // Cesar Lopez Nataren (cesar@ciencias.unam.mx)
7 // (C) 2003, Cesar Lopez Nataren
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
32 using System.Collections;
33 using System.Reflection;
34 using System.Reflection.Emit;
36 namespace Microsoft.JScript {
38 public abstract class AST {
42 internal Location location;
43 internal Location Location {
44 get { return location; }
47 internal AST (AST parent, Location location)
50 this.location = location;
54 // Here the actual IL code generation happens.
56 internal abstract void Emit (EmitContext ec);
59 // Perform type checks and associates expressions
60 // with their declarations
62 internal abstract bool Resolve (Environment env);
64 internal bool InLoop {
66 if (parent == null || parent is ScriptBlock)
68 else if (parent is DoWhile || parent is While || parent is For || parent is ForIn)
75 internal bool InSwitch {
79 else if (parent is Switch)
82 return parent.InSwitch;
86 internal bool InFunction {
88 if (parent == null || parent.GetType () == typeof (ScriptBlock))
90 else if (parent is FunctionDeclaration || parent is FunctionExpression)
93 return parent.InFunction;
97 internal Function GetContainerFunction {
101 if (parent is Function)
102 return parent as Function;
103 return parent.GetContainerFunction;
108 internal virtual void PropagateParent (AST parent)
110 this.parent = parent;
114 public abstract class Function : AST
117 bool ignore_dynamic_scope;
118 bool requires_activation;
120 internal string prefix;
121 internal FunctionObject func_obj;
122 internal JSFunctionAttributeEnum func_type;
124 internal object [] locals;
125 internal LocalBuilder local_func;
127 protected bool not_void_return = false;
128 protected ILGenerator ig;
130 internal Function (AST parent, Location location)
131 : base (parent, location)
135 internal bool CheckThis {
136 get { return check_this; }
137 set { check_this = value; }
140 internal bool IgnoreDynamicScope {
141 get { return ignore_dynamic_scope; }
142 set { ignore_dynamic_scope = value; }
145 internal bool RequiresActivation {
146 get { return requires_activation; }
147 set { requires_activation = value; }
150 internal int NumOfArgs {
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");
156 // indicate that at the later stage we
157 // must check the proper number of
158 // args and formal parameters
163 internal void Init (Block body, FormalParameterList p)
165 func_obj.body = body;
166 func_obj.parameters = p;
169 internal void set_prefix ()
171 if (parent != null && InFunction) {
173 tmp = GetContainerFunction;
174 if (tmp.prefix != String.Empty)
175 prefix = tmp.prefix + "." + tmp.func_obj.name;
177 prefix = tmp.func_obj.name;
179 prefix = String.Empty;
182 internal void set_function_type ()
184 if (parent == null || parent.GetType () == typeof (ScriptBlock))
185 func_type = JSFunctionAttributeEnum.ClassicFunction;
186 else if (parent is FunctionDeclaration)
187 func_type = JSFunctionAttributeEnum.NestedFunction;
190 internal void set_custom_attr (MethodBuilder mb)
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);
200 internal void NotVoidReturnHappened (object sender, NotVoidReturnEventArgs args)
202 not_void_return = true;
205 internal Type HandleReturnType {
209 ret_type = typeof (object);
211 ret_type = typeof (void);
216 internal void emit_return_local_field (ILGenerator ig, ConstructorInfo ctr_info, int n)
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);
227 internal string GetName (object ast)
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 ());