Switch to compiler-tester
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / expression.cs
1 //
2 // expression.cs: Everything related to expressions
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, 2004 Cesar Lopez Nataren
8 // (C) 2005, Novell Inc. (http://novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Text;
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using Microsoft.JScript.Vsa;
38
39 namespace Microsoft.JScript {
40         
41         public abstract class Exp : AST {
42                 internal bool no_effect;
43                 internal abstract bool Resolve (IdentificationTable context, bool no_effect);
44         }
45         
46         internal class Unary : UnaryOp {
47
48                 internal Unary (AST parent, JSToken oper)
49                 {               
50                         this.parent = parent;
51                         this.oper = oper;
52                 }
53
54                 public override string ToString ()
55                 {
56                         StringBuilder sb = new StringBuilder ();
57                         
58                         if (oper != JSToken.None)
59                                 sb.Append (oper + " ");
60                         
61                         if (operand != null)
62                                 sb.Append (operand.ToString ());
63                         
64                         return sb.ToString ();
65                 }
66
67                 internal override bool Resolve (IdentificationTable context)
68                 {
69                         bool r = false;                
70                         
71                         if (operand is Exp)
72                                 if (oper != JSToken.Increment && oper != JSToken.Decrement)
73                                         r = ((Exp) operand).Resolve (context, no_effect);
74                         r = ((AST) operand).Resolve (context);                  
75                         return r;
76                 }
77
78                 internal override bool Resolve (IdentificationTable context, bool no_effect)
79                 {
80                         this.no_effect = no_effect;
81                         return Resolve (context);
82                 }
83
84                 internal override void Emit (EmitContext ec)
85                 {
86                         if (operand != null)
87                                 operand.Emit (ec);
88                         if (oper != JSToken.Minus)
89                                 emit_unary_op (ec);
90                 }
91
92                 internal void emit_unary_op (EmitContext ec)
93                 {
94                         ILGenerator ig = ec.ig;
95                         switch (oper) {
96                         case JSToken.Typeof:
97                                 ig.Emit (OpCodes.Call, typeof (Typeof).GetMethod ("JScriptTypeof"));
98                                 break;
99                         }
100                 }
101         }
102
103         internal class Binary : BinaryOp, IAssignable {
104
105                 bool assign, late_bind = false;
106                 AST right_side;
107
108                 internal Binary (AST parent, AST left, JSToken op)
109                         : this (parent, left, null, op)
110                 {
111                 }
112                 
113                 internal Binary (AST parent, AST left, AST right, JSToken op)
114                         : base (left, right, op)
115                 {
116                         this.parent = parent;
117                 }
118                 
119                 public override string ToString ()
120                 {
121                         StringBuilder sb = new StringBuilder ();
122                         sb.Append (left.ToString () + " ");
123                         
124                         if (op != JSToken.None)
125                                 sb.Append (op + " ");
126                         
127                         if (right != null)
128                                 sb.Append (right.ToString ());
129
130                         return sb.ToString ();
131                 }
132
133                 internal bool AccessField {
134                         get { return op == JSToken.AccessField; }
135                 }
136
137                 internal override bool Resolve (IdentificationTable context)
138                 {
139                         bool r = true;
140                         if (left != null)
141                                 r &= left.Resolve (context);
142                         if (right != null) 
143                                 if (op == JSToken.AccessField && right is IAccesible) {
144                                         r &= ((IAccesible) right).ResolveFieldAccess (left);
145                                         if (!r)
146                                                 late_bind = true;
147                                 } else
148                                         r &= right.Resolve (context);
149                         return r;
150                 }
151
152                 internal override bool Resolve (IdentificationTable context, bool no_effect)
153                 {
154                         this.no_effect = no_effect;
155                         return Resolve (context);
156                 }
157                 
158                 public bool ResolveAssign (IdentificationTable context, AST right_side)
159                 {
160                         if (op == JSToken.LeftBracket || op == JSToken.AccessField) {
161                                 this.no_effect = false;
162                                 this.assign = true;
163                                 this.right_side = right_side;
164                                 return Resolve (context);
165                         } else 
166                                 throw new Exception ("error JS5008: Illegal assignment");
167                 }
168
169                 internal MemberInfo Binding {
170                         get { 
171                                 return SemanticAnalyser.get_member (left, right);
172                         }
173                 }
174
175                 internal override void Emit (EmitContext ec)
176                 {
177                         ILGenerator ig = ec.ig;                 
178                         if (op == JSToken.None) {
179                                 if (left != null)
180                                         left.Emit (ec);
181                         } else if (op == JSToken.LogicalAnd || op == JSToken.LogicalOr)
182                                 emit_jumping_code (ec);
183                         else if (op == JSToken.LeftBracket) {
184                                 if (!assign)
185                                         get_default_this (ig);
186                                 if (left != null)
187                                         left.Emit (ec);
188                                 emit_array_access (ec);                         
189                         } else if (op == JSToken.AccessField) {
190                                 if (late_bind)
191                                         emit_late_binding (ec);
192                                 else
193                                         emit_access (left, right, ec);
194                         } else {
195                                 emit_operator (ig);
196                                 if (left != null)
197                                         left.Emit (ec);
198                                 if (right != null)
199                                         right.Emit (ec);                               
200                                 emit_op_eval (ig);
201                         }
202                         if (no_effect)
203                                 ig.Emit (OpCodes.Pop);
204                 }
205
206                 void emit_access (AST obj, AST prop_name, EmitContext ec)
207                 {
208                         MemberInfo minfo = SemanticAnalyser.get_member (obj, prop_name);        
209                         ILGenerator ig = ec.ig;
210                         MemberTypes minfo_type = minfo.MemberType;
211
212                         switch (minfo_type) {
213                         case MemberTypes.Field:
214                                 FieldInfo finfo = (FieldInfo) minfo;
215                                 object value = finfo.GetValue (finfo);
216                                 Type type = value.GetType ();
217                                 if (type == typeof (double))
218                                         ig.Emit (OpCodes.Ldc_R8, (double) value);
219                                 break;
220                         case MemberTypes.Property:
221                                 PropertyInfo property = (PropertyInfo) minfo;
222                                 Type decl_type = property.DeclaringType;
223                                 Type t = null;
224                                 
225                                 if (decl_type == typeof (RegExpConstructor)) {
226                                         t = typeof (GlobalObject);
227                                 }
228                                 ig.Emit (OpCodes.Call, t.GetProperty (FieldName (decl_type)).GetGetMethod ());
229
230                                 CodeGenerator.load_engine (InFunction, ig);
231                                 ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToObject2"));
232                                 ig.Emit (OpCodes.Castclass, decl_type);
233                                 
234                                 ig.Emit (OpCodes.Call, decl_type.GetProperty (property.Name).GetGetMethod ());
235                                 break;
236                         default:
237                                 throw new NotImplementedException ();
238                         }
239                         emit_box (ig, minfo);
240                 }                       
241
242                 void emit_box (ILGenerator ig, MemberInfo info)
243                 {
244                         MemberTypes member_type = info.MemberType;
245                         Type type = null;
246
247                         switch (member_type) {
248                         case MemberTypes.Field:
249                                 type = ((FieldInfo) info).FieldType;
250                                 break;
251                         }
252                         if (type != null)
253                                 ig.Emit (OpCodes.Box, type);
254                 }
255
256                 private string FieldName (Type type)
257                 {
258                         if (type == typeof (RegExpConstructor))
259                                 return "RegExp";
260                         throw new NotImplementedException ();
261                 }
262
263                 void emit_late_binding (EmitContext ec)                 
264                 {
265                         LocalBuilder local_lb = init_late_binding (ec);
266                         emit_late_get_or_set (ec, local_lb);
267                 }
268
269                 LocalBuilder init_late_binding (EmitContext ec)
270                 {
271                         ILGenerator ig = ec.ig;
272                         Type lb_type = typeof (LateBinding);
273
274                         LocalBuilder local = ig.DeclareLocal (lb_type);
275                         
276                         string prop_name = (right as Identifier).name.Value;
277                         ig.Emit (OpCodes.Ldstr, prop_name);
278                         ig.Emit (OpCodes.Newobj, lb_type.GetConstructor (new Type [] {typeof (string)}));
279                         ig.Emit (OpCodes.Stloc, local);                 
280
281                         return local;
282                 }
283                 
284                 void emit_late_get_or_set (EmitContext ec, LocalBuilder local)
285                 {
286                         ILGenerator ig = ec.ig;
287
288                         ig.Emit (OpCodes.Ldloc, local);
289                         ig.Emit (OpCodes.Dup);
290
291                         left.Emit (ec);
292
293                         CodeGenerator.load_engine (InFunction, ec.ig);
294                         ig.Emit (OpCodes.Call , typeof (Convert).GetMethod ("ToObject"));
295
296                         Type lb_type = typeof (LateBinding);
297                         ig.Emit (OpCodes.Stfld, lb_type.GetField ("obj"));
298
299                         if (assign) {
300                                 right_side.Emit (ec);
301                                 ig.Emit (OpCodes.Call, lb_type.GetMethod ("SetValue"));
302                         } else
303                                 ig.Emit (OpCodes.Call, lb_type.GetMethod ("GetNonMissingValue"));
304                 }
305                 
306                 internal void get_default_this (ILGenerator ig)
307                 {
308                         if (InFunction)
309                                 ig.Emit (OpCodes.Ldarg_1);
310                         else {
311                                 ig.Emit (OpCodes.Ldarg_0);
312                                 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
313                         }
314                        
315                         ig.Emit (OpCodes.Call, typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("ScriptObjectStackTop"));
316                         Type iact_obj = typeof (IActivationObject);
317                         ig.Emit (OpCodes.Castclass, iact_obj);
318                         ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetDefaultThisObject"));
319                 }
320
321                 internal void emit_array_access (EmitContext ec)
322                 {
323                         ILGenerator ig = ec.ig;
324                         ig.Emit (OpCodes.Ldc_I4_1);
325                         ig.Emit (OpCodes.Newarr, typeof (object));
326                         ig.Emit (OpCodes.Dup);
327                         ig.Emit (OpCodes.Ldc_I4_0);
328                         if (right != null)
329                                 right.Emit (ec);
330                         ig.Emit (OpCodes.Stelem_Ref);                   
331
332                         if (assign) {
333                                 if (right_side != null)
334                                         right_side.Emit (ec);
335                                 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("SetIndexedPropertyValueStatic"));
336                         } else {
337                                 ig.Emit (OpCodes.Ldc_I4_0);
338                                 ig.Emit (OpCodes.Ldc_I4_1);
339
340                                 if (InFunction)
341                                         ig.Emit (OpCodes.Ldarg_1);
342                                 else {
343                                         ig.Emit (OpCodes.Ldarg_0);
344                                         ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
345                                 }
346                                 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
347                         }
348                 }
349
350                 internal void emit_op_eval (ILGenerator ig)
351                 {
352                         switch (op) {
353                         case JSToken.Plus:
354                                 ig.Emit (OpCodes.Callvirt, typeof (Plus).GetMethod ("EvaluatePlus"));
355                                 break;
356                         case JSToken.Minus:
357                         case JSToken.Divide:
358                         case JSToken.Modulo:
359                         case JSToken.Multiply:
360                                 ig.Emit (OpCodes.Call, typeof (NumericBinary).GetMethod ("EvaluateNumericBinary"));
361                                 break;
362                         case JSToken.BitwiseAnd:
363                         case JSToken.BitwiseXor:
364                         case JSToken.BitwiseOr:
365                         case JSToken.LeftShift:
366                         case JSToken.RightShift:
367                         case JSToken.UnsignedRightShift:
368                                 ig.Emit (OpCodes.Call, typeof (BitwiseBinary).GetMethod ("EvaluateBitwiseBinary"));
369                                          break;
370                         }                       
371                 }
372
373                 internal void emit_jumping_code (EmitContext ec)
374                 {
375                         ILGenerator ig = ec.ig;
376                         Type t = typeof (bool);
377                         Label false_label = ig.DefineLabel ();
378                         Label exit_label = ig.DefineLabel ();
379                         CodeGenerator.fall_true (ec, this, false_label);
380                         ig.Emit (OpCodes.Ldc_I4_1);                     
381                         ig.Emit (OpCodes.Box, t);                       
382                         ig.Emit (OpCodes.Br, exit_label);
383                         ig.MarkLabel (false_label);
384                         ig.Emit (OpCodes.Ldc_I4_0);                     
385                         ig.Emit (OpCodes.Box, t);                       
386                         ig.MarkLabel (exit_label);
387                 }
388
389                 internal void emit_operator (ILGenerator ig)
390                 {
391                         LocalBuilder local_builder = null;
392                         Type t = null;
393                         
394                         if (op == JSToken.Plus) {
395                                 t = typeof (Plus);
396                                 local_builder = ig.DeclareLocal (t);                            
397                                 ig.Emit (OpCodes.Newobj, t.GetConstructor (new Type [] {}));
398                                 ig.Emit (OpCodes.Stloc, local_builder);
399                                 ig.Emit (OpCodes.Ldloc, local_builder);
400                                 return;
401                         } else if (op == JSToken.Minus) {
402                                 t = typeof (NumericBinary);
403                                 local_builder = ig.DeclareLocal (t);
404                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 47);
405                         } else if (op == JSToken.LeftShift) {
406                                 t = typeof (BitwiseBinary);
407                                 local_builder = ig.DeclareLocal (t);
408                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 61);
409                         } else if (op == JSToken.RightShift) {
410                                 t = typeof (BitwiseBinary);
411                                 local_builder = ig.DeclareLocal (t);
412                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 62);
413                         } else if (op == JSToken.UnsignedRightShift) {
414                                 t = typeof (BitwiseBinary);
415                                 local_builder = ig.DeclareLocal (t);
416                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 63);
417                         } else if (op == JSToken.Multiply) {
418                                 t = typeof (NumericBinary);
419                                 local_builder = ig.DeclareLocal (t);
420                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 64);
421                         } else if (op == JSToken.Divide) {
422                                 t = typeof (NumericBinary);
423                                 local_builder = ig.DeclareLocal (t);
424                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 65);
425                         } else if (op == JSToken.Modulo) {
426                                 t = typeof (NumericBinary);
427                                 local_builder = ig.DeclareLocal (t);
428                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 66);
429                         } else if (op == JSToken.BitwiseOr) {
430                                 t = typeof (BitwiseBinary);
431                                 local_builder = ig.DeclareLocal (t);
432                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 50);
433                         } else if (op == JSToken.BitwiseXor) {
434                                 t = typeof (BitwiseBinary);
435                                 local_builder = ig.DeclareLocal (t);
436                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 51);                          
437                         } else if (op == JSToken.BitwiseAnd) {
438                                 t = typeof (BitwiseBinary);
439                                 local_builder = ig.DeclareLocal (t);
440                                 ig.Emit (OpCodes.Ldc_I4_S, (byte) 52);
441                         }
442                         ig.Emit (OpCodes.Newobj, t.GetConstructor (new Type [] {typeof (int)}));
443                         ig.Emit (OpCodes.Stloc, local_builder);
444                         ig.Emit (OpCodes.Ldloc, local_builder);
445                 }
446         }
447
448         internal class Conditional : Exp {
449
450                 AST cond_exp, true_exp, false_exp;
451
452                 internal Conditional (AST parent, AST expr, AST  trueExpr, AST falseExpr)
453                 {
454                         this.cond_exp = expr;
455                         this.true_exp = trueExpr;
456                         this.false_exp = falseExpr;
457                 }
458                 
459                 public override string ToString ()
460                 {
461                         StringBuilder sb = new StringBuilder ();
462
463                         if (cond_exp != null)
464                                 sb.Append (cond_exp.ToString () + " ");
465                         if (true_exp != null)
466                                 sb.Append (true_exp.ToString () + " ");
467                         if (false_exp != null)
468                                 sb.Append (false_exp.ToString ());
469
470                         return sb.ToString ();
471                 }
472
473                 internal override bool Resolve (IdentificationTable context)
474                 {
475                         bool r = true;
476                         if (cond_exp != null)
477                                 r &= cond_exp.Resolve (context);
478                         if (true_exp != null)
479                                 r &= true_exp.Resolve (context);
480                         if (false_exp != null)
481                                 r &= false_exp.Resolve (context);
482                         return r;
483                 }
484
485                 internal override bool Resolve (IdentificationTable context, bool no_effect)
486                 {
487                         this.no_effect = no_effect;
488                         return Resolve (context);
489                 }
490
491                 internal override void Emit (EmitContext ec)
492                 {
493                         ILGenerator ig = ec.ig;
494                         Label false_label = ig.DefineLabel ();
495                         Label merge_label = ig.DefineLabel ();
496                         CodeGenerator.fall_true (ec, cond_exp, false_label);
497                         if (true_exp != null)
498                                 true_exp.Emit (ec);
499                         ig.Emit (OpCodes.Br, merge_label);
500                         ig.MarkLabel (false_label);
501                         if (false_exp != null)
502                                 false_exp.Emit (ec);
503                         ig.MarkLabel (merge_label);
504                         if (no_effect)
505                                 ig.Emit (OpCodes.Pop);
506                 }
507         }
508
509         internal interface ICallable {
510                 void AddArg (AST arg);
511         }
512         
513         internal class Call : Exp, ICallable {
514                 
515                 internal AST member_exp;                
516                 internal Args args;
517                 internal object binding;
518                 internal Type bind_type;
519
520                 internal Call (AST parent, AST exp)
521                 {
522                         this.parent = parent;
523                         this.member_exp = exp;
524                         this.args = new Args ();
525                 }
526                 
527                 public override string ToString ()
528                 {
529                         StringBuilder sb = new StringBuilder ();
530                         if (member_exp != null)
531                                 sb.Append (member_exp.ToString () + " ");
532                         if (args != null)
533                                 sb.Append (args.ToString ());
534                         return sb.ToString ();
535                 }
536
537                 public void AddArg (AST arg)
538                 {
539                         args.Add (arg);
540                 }
541
542                 internal override bool Resolve (IdentificationTable context)
543                 {
544                         bool r = true;
545                         int n = -1;
546
547                         if (member_exp != null) {
548                                 if (member_exp is Identifier) {
549                                         member_exp.Resolve (context);
550                                         binding = context.Get ((member_exp as Identifier).name);
551                                         bind_type = binding.GetType ();
552
553                                         if (bind_type == typeof (BuiltIn)) {
554                                                 BuiltIn built_in = binding as BuiltIn;
555                                                 if (!built_in.IsFunction)
556                                                         throw new Exception ("error JS5002 A: function expected.");
557                                                 if (IsGlobalObjectMethod (built_in)) {
558                                                         //
559                                                         // If a method contains an eval invocation
560                                                         // we must generate proper code for accessing 
561                                                         // the local vars in the StackFrame.
562                                                         //
563                                                         if (((Identifier) member_exp).name.Value == "eval") {
564                                                                 Function cont_func = GetContainerFunction;
565                                                                 if (cont_func != null)
566                                                                         SemanticAnalyser.AddMethodWithEval (cont_func.func_obj.name);
567                                                         }
568                                                         args.params_info = built_in.Parameters;
569                                                         n = built_in.NumOfArgs;
570                                                 }
571                                         } else if (bind_type == typeof (FunctionDeclaration) || bind_type == typeof (FunctionExpression)) {
572                                                 args.func = (Function) binding;
573                                                 n = (binding as Function).NumOfArgs;
574                                         }
575                                 } else if (member_exp is Binary) {
576                                         member_exp.Resolve (context);
577                                         Binary bin = (Binary) member_exp;
578                                         if (bin.AccessField)
579                                                 binding = bin.Binding;
580                                         if (binding is MethodInfo) {
581                                                 MethodInfo method_info = (MethodInfo) binding;
582                                                 args.has_var_args (method_info);
583                                                 args.params_info = method_info.GetParameters ();
584                                                 if (args.params_info != null)
585                                                         n = args.params_info.Length;
586                                                 else n = 0;
587                                         }
588                                 } else
589                                         r &= member_exp.Resolve (context);
590                 
591                                 if (args != null) {
592                                         args.DesiredNumOfArgs = n;
593                                         r &= args.Resolve (context);
594                                 }
595                         } else
596                                 throw new Exception ("Call.Resolve, member_exp can't be null");
597                         return r;
598                 }
599
600                 internal override bool Resolve (IdentificationTable context, bool no_effect)
601                 {
602                         this.no_effect = no_effect;
603                         return Resolve (context);
604                 }
605
606                 internal override void Emit (EmitContext ec)
607                 {
608                         if (bind_type == typeof (BuiltIn)) {
609                                 BuiltIn b = binding as BuiltIn;
610                                 if (b.IsPrint) {
611                                         emit_print_stm (ec);
612                                         return;
613                                 } else if (IsGlobalObjectMethod (binding)) {
614                                         bool eval = IsEval (binding);
615                                         bool in_func = InFunction;
616                                         
617                                         if (eval && in_func)
618                                                 CodeGenerator.load_local_vars (ec.ig, in_func);
619                                         
620                                         args.Emit (ec);
621
622                                         if (eval) {
623 #if (!NET_1_0)
624                                                 ec.ig.Emit (OpCodes.Ldnull);
625 #endif
626                                                 CodeGenerator.load_engine (in_func, ec.ig);
627                                         }
628                                         member_exp.Emit (ec);
629                                         
630                                         if (eval && no_effect && in_func)
631                                                 ec.ig.Emit (OpCodes.Pop);
632
633                                         if (eval && in_func) {
634                                                 set_local_vars (ec.ig);
635                                                 return;
636                                         }
637                                 } else if (IsConstructorProperty (binding)) {
638                                         member_exp.Emit (ec);
639                                         EmitBuiltInArgs (ec);
640                                         EmitInvoke (ec);                                        
641                                 }
642                         } else if (bind_type == typeof (FunctionDeclaration) || bind_type == typeof (FunctionExpression)) {
643                                 Function function = binding as Function;
644                                 MethodBuilder method = (MethodBuilder) TypeManager.Get (function.func_obj.name);
645                                 
646                                 if (SemanticAnalyser.MethodContainsEval (function.func_obj.name) ||
647                                     SemanticAnalyser.MethodReferenceOutterScopeVar (function.func_obj.name) ||
648                                     SemanticAnalyser.MethodVarsUsedNested (function.func_obj.name)) {
649                                         if (InFunction)
650                                                 CodeGenerator.load_local_vars (ec.ig, true);
651                                         emit_late_call (ec);
652                                         if (no_effect)
653                                                 ec.ig.Emit (OpCodes.Pop);
654                                         if (InFunction)
655                                                 set_local_vars (ec.ig);
656                                         return;
657                                 } else {
658                                         emit_func_call (method, ec);
659                                         return;
660                                 }
661                         } else if (binding is MemberInfo) {
662                                 MemberInfo minfo = (MemberInfo) binding;
663                                 MemberTypes member_type = minfo.MemberType;
664                                 ILGenerator ig = ec.ig;                         
665                                 
666                                 if (member_type == MemberTypes.Method) {
667                                         args.Emit (ec);
668                                         MethodInfo method = (MethodInfo) minfo;
669                                         ig.Emit (OpCodes.Call, method);
670                                         Type return_type = method.ReturnType;
671                                         if (return_type != typeof (void))
672                                                 ig.Emit (OpCodes.Box, return_type);
673                                 } else
674                                         throw new NotImplementedException ();
675                         } else
676                                 emit_late_call (ec);
677                         
678                         if (no_effect)
679                                 ec.ig.Emit (OpCodes.Pop);                       
680                 }
681
682                 internal void emit_print_stm (EmitContext ec)
683                 {
684                         ILGenerator ig = ec.ig;
685                         
686                         if (args == null || args.Size == 0) {
687                                 ig.Emit (OpCodes.Ldstr, "");
688                                 ig.Emit (OpCodes.Call, typeof (ScriptStream).GetMethod ("WriteLine"));
689                                 return;
690                         }
691
692                         Type script_stream = typeof (ScriptStream);
693                         MethodInfo write = script_stream.GetMethod ("Write");
694                         MethodInfo writeline = script_stream.GetMethod ("WriteLine");
695                         MethodInfo to_string = typeof (Convert).GetMethod ("ToString",
696                                                                            new Type [] { typeof (object), typeof (bool) });
697                         AST ast;
698                         int n = args.Size - 1;
699
700                         for (int i = 0; i <= n; i++) {
701                                 ast = args.get_element (i);                             
702                                 ast.Emit (ec);
703                                 
704                                 if (ast is StringLiteral)
705                                         ;
706                                 else {
707                                         ig.Emit (OpCodes.Ldc_I4_1);
708                                         ig.Emit (OpCodes.Call, to_string);
709                                 }
710                                         
711                                 if (i == n)
712                                         ig.Emit (OpCodes.Call, writeline);
713                                 else
714                                         ig.Emit (OpCodes.Call, write);
715                         }
716                         
717                 }
718
719                 void emit_late_call (EmitContext ec)
720                 {
721                         ILGenerator ig = ec.ig;
722
723                         if (member_exp is Binary) {
724                                 Binary bin = member_exp as Binary;
725                                 if (bin.right is Identifier) {
726                                         Identifier rside = bin.right as Identifier;
727                                         Type lb_type = typeof (LateBinding);
728                                 
729                                         LocalBuilder lb = ig.DeclareLocal (lb_type);
730
731                                         ig.Emit (OpCodes.Ldstr, rside.name.Value);
732                                         ig.Emit (OpCodes.Newobj , lb_type.GetConstructor (new Type [] {typeof (string)}));
733                                         ig.Emit (OpCodes.Stloc, lb);
734                                         init_late_binding (ec, lb);
735                                         setup_late_call_args (ec);
736                                         ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("Call"));
737                                 } else {
738                                         bin.left.Emit (ec);
739                                         member_exp.Emit (ec);
740                                         setup_late_call_args (ec);
741                                         ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
742                                 }
743                         } else {                                
744                                 get_global_scope_or_this (ec.ig);
745                                 member_exp.Emit (ec);
746                                 setup_late_call_args (ec);
747                                 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
748                         }
749                 }
750
751                 internal void get_global_scope_or_this (ILGenerator ig)
752                 {
753                         if (InFunction)
754                                 ig.Emit (OpCodes.Ldarg_1);
755                         else {
756                                 ig.Emit (OpCodes.Ldarg_0);
757                                 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
758                         }
759
760                         ig.Emit (OpCodes.Call, typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("ScriptObjectStackTop"));
761                         Type iact_obj = typeof (IActivationObject);
762                         ig.Emit (OpCodes.Castclass, iact_obj);
763
764                         //
765                         //FIXME: when is each of them (GetGlobalScope | GetDefaultThisObject?
766                         //
767                         // ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetGlobalScope"));
768                         ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetDefaultThisObject"));
769                 }
770
771                 void init_late_binding (EmitContext ec, LocalBuilder local)
772                 {
773                         ILGenerator ig = ec.ig;
774
775                         ig.Emit (OpCodes.Ldloc, local);
776                         ig.Emit (OpCodes.Dup);
777                         
778                         AST left = (member_exp as Binary).left;
779                         left.Emit (ec);
780                         
781                         ig.Emit (OpCodes.Ldarg_0);
782                         ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
783                         ig.Emit (OpCodes.Call , typeof (Convert).GetMethod ("ToObject"));
784
785                         Type lb_type = typeof (LateBinding);
786
787                         ig.Emit (OpCodes.Stfld, lb_type.GetField ("obj"));
788                 }
789
790                 void setup_late_call_args (EmitContext ec)
791                 {
792                         ILGenerator ig = ec.ig;
793                         int n = args.Size;
794
795                         ig.Emit (OpCodes.Ldc_I4, n);
796                         ig.Emit (OpCodes.Newarr, typeof (object));
797                         
798                         for (int i = 0; i < n; i++) {
799                                 ig.Emit (OpCodes.Dup);
800                                 ig.Emit (OpCodes.Ldc_I4, i);
801                                 args.get_element (i).Emit (ec);
802                                 ig.Emit (OpCodes.Stelem_Ref);
803                         }
804
805                         ig.Emit (OpCodes.Ldc_I4_0);
806                         ig.Emit (OpCodes.Ldc_I4_0);
807
808                         if (InFunction)
809                                 ig.Emit (OpCodes.Ldarg_1);
810                         else {
811                                 ig.Emit (OpCodes.Ldarg_0);
812                                 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
813                         }
814                 }
815
816                 void emit_func_call (MethodBuilder mb, EmitContext ec)
817                 {
818                         ILGenerator ig = ec.ig;
819                         CodeGenerator.load_engine (InFunction, ig);
820                         ig.Emit (OpCodes.Call, typeof (VsaEngine).GetMethod ("ScriptObjectStackTop"));
821                         Type iact_obj = typeof (IActivationObject);
822                         ig.Emit (OpCodes.Castclass, iact_obj);
823                         ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetDefaultThisObject"));
824
825                         CodeGenerator.load_engine (InFunction, ig);
826
827                         args.Emit (ec);
828
829                         ig.Emit (OpCodes.Call, mb);
830
831                         if (!return_void (mb) && no_effect)
832                                 ig.Emit (OpCodes.Pop);
833                 }
834
835                 bool return_void (MethodBuilder mb)
836                 {
837                         return mb.ReturnType == typeof (void);
838                 }
839
840                 void EmitBuiltInArgs (EmitContext ec)
841                 {
842                         if (member_exp.ToString () == "Date")
843                                 return;
844
845                         ILGenerator ig = ec.ig;
846                         int n = args.Size;
847                         
848                         if (n >= 1 && (member_exp.ToString () == "String" || member_exp.ToString () == "Boolean" || member_exp.ToString () == "Number")) {
849                                 args.get_element (0).Emit (ec);
850                                 return;
851                         }
852
853                         ig.Emit (OpCodes.Ldc_I4, n);
854                         ig.Emit (OpCodes.Newarr, typeof (object));
855                         for (int i = 0; i < n; i++) {
856                                 ig.Emit (OpCodes.Dup);
857                                 ig.Emit (OpCodes.Ldc_I4, i);
858                                 args.get_element (i).Emit (ec);
859                                 ig.Emit (OpCodes.Stelem_Ref);
860                         }
861                 }
862
863                 void EmitInvoke (EmitContext ec)
864                 {
865                         ILGenerator ig = ec.ig;
866                         string name = member_exp.ToString ();
867                         Type type = null;
868                         bool boolean = false;
869                         bool number = false;
870
871                         switch (name) {
872                         case "Object":
873                                 type = typeof (ObjectConstructor);
874                                 break;
875                         case "Function":
876                                 type = typeof (FunctionConstructor);
877                                 break;
878                         case "Array":
879                                 type = typeof (ArrayConstructor);
880                                 break;
881                         case "String":
882                                 type = typeof (StringConstructor);
883                                 break;
884                         case "Boolean":
885                                 type = typeof (BooleanConstructor);
886                                 boolean = true;
887                                 break;
888                         case "Number":
889                                 type = typeof (NumberConstructor);
890                                 number = true;
891                                 break;
892                         case "Date":
893                                 type = typeof (DateConstructor);
894                                 break;
895                         case "RegExp":
896                                 type = typeof (RegExpConstructor);
897                                 break;
898                         case "Error":
899                         case "EvalError":
900                         case "RangeError":
901                         case "ReferenceError":
902                         case "SyntaxError":
903                         case "TypeError":
904                         case "URIError":
905                                 type = typeof (ErrorConstructor);
906                                 break;
907                         }
908                         ig.Emit (OpCodes.Call, type.GetMethod ("Invoke"));
909                         if (boolean)
910                                 ig.Emit (OpCodes.Box, typeof (Boolean));
911                         if (number)
912                                 ig.Emit (OpCodes.Box, typeof (Double));
913                 }
914
915                 bool IsConstructorProperty (object binding)
916                 {
917                         if (!(binding is BuiltIn))
918                                 return false;
919
920                         string name = (binding as BuiltIn).Name;
921                         
922                         return (name == "Object" || name == "Function" || name == "Array" || name == "String" || name == "Boolean" || name == "Number" || name == "Date" || name == "RegExp" || name == "Error" || name == "EvalError" || name == "RangeError" || name == "ReferenceError" || name == "SyntaxError" || name == "TypeError" || name == "URIError");
923                 }
924
925                 bool IsGlobalObjectMethod (object binding)
926                 {
927                         if (binding == null || binding.GetType () != typeof (BuiltIn))
928                                 return false;
929                         
930                         BuiltIn bind = binding as BuiltIn;
931                         switch (bind.Name) {
932                         case "eval":
933                         case "parseInt":
934                         case "parseFloat":
935                         case "isNaN":
936                         case "isFinite":
937                         case "decodeURI":
938                         case "decodeURIComponent":
939                         case "encodeURI":
940                         case "encodeURIComponent":
941                         case "escape":
942                         case "unescape":
943                                 return true;
944                         default:
945                                 return false;
946                         }
947                 }
948
949                 bool IsEval (object binding)
950                 {
951                         if (binding == null || binding.GetType () != typeof (BuiltIn))
952                                 return false;
953                         BuiltIn bind = (BuiltIn) binding;
954                         return bind.Name == "eval";
955                 }
956
957                 internal void set_local_vars (ILGenerator ig)
958                 {
959                         int n = 0;
960                         Type stack_frame = typeof (StackFrame);
961
962                         CodeGenerator.load_engine (InFunction, ig);
963
964                         ig.Emit (OpCodes.Call, typeof (VsaEngine).GetMethod ("ScriptObjectStackTop"));
965                         ig.Emit (OpCodes.Castclass, stack_frame);
966                         ig.Emit (OpCodes.Ldfld, stack_frame.GetField ("localVars"));
967
968                         object [] locals = TypeManager.CurrentLocals;
969                         n = locals != null ? locals.Length : 0;
970                         object local = null;
971
972                         for (int i = 0; i < n; i++) {
973                                 local = locals [i];
974                                 if (local is LocalBuilder) {
975                                         ig.Emit (OpCodes.Dup);
976                                         ig.Emit (OpCodes.Ldc_I4, i);
977                                         ig.Emit (OpCodes.Ldelem_Ref);
978                                         ig.Emit (OpCodes.Stloc, (LocalBuilder) local);
979                                 }
980                         }
981                         ig.Emit (OpCodes.Pop);
982                 }
983         }
984
985         interface IAccesible {
986                 bool ResolveFieldAccess (AST parent);
987         }
988
989         internal class Identifier : Exp, IAssignable, IAccesible {
990                 
991                 internal Symbol name;
992                 internal AST binding;
993                 internal bool assign;
994                 AST right_side;
995                 
996                 int lexical_difference;
997                 const int MINIMUM_DIFFERENCE = 1;
998                 bool no_field;
999                 LocalBuilder local_builder;
1000
1001                 internal Identifier (AST parent, string id)
1002                 {
1003                         this.parent = parent;
1004                         this.name = Symbol.CreateSymbol (id);
1005                 }
1006
1007                 bool NeedParents {
1008                         get { return lexical_difference >= MINIMUM_DIFFERENCE && no_field; }
1009                 }
1010
1011                 public override string ToString ()
1012                 {
1013                         return name.Value;
1014                 }
1015
1016                 internal override bool Resolve (IdentificationTable context)
1017                 {
1018                         bool contained = context.Contains (this.name);
1019                         if (contained) {
1020                                 binding = (AST) context.Get (this.name);
1021                                 if (binding is VariableDeclaration) {
1022                                         VariableDeclaration decl = (VariableDeclaration) binding;
1023                                         lexical_difference = context.depth - decl.lexical_depth;
1024                                         no_field = decl.lexical_depth != 0;
1025                                         if (no_field && lexical_difference > 0 && !context.CatchScope) {
1026                                                 Function container_func = GetContainerFunction;
1027                                                 SemanticAnalyser.AddMethodReferenceOutterScopeVar (container_func.func_obj.name, decl);
1028                                                 context.Enter (Symbol.CreateSymbol (decl.id), decl);
1029                                                 SemanticAnalyser.AddMethodVarsUsedNested (decl.GetContainerFunction.func_obj.name, decl);
1030                                         }
1031                                 }
1032                         } else
1033                                 throw new Exception ("variable not found: " +  name);
1034                         return true;
1035                 }
1036
1037                 internal override bool Resolve (IdentificationTable context, bool no_effect)
1038                 {
1039                         this.no_effect = no_effect;
1040                         return Resolve (context);
1041                 }
1042
1043                 public bool ResolveAssign (IdentificationTable context, AST right_side)
1044                 {
1045                         this.assign = true;
1046                         this.no_effect = false;
1047                         this.right_side = right_side;
1048                         if (name.Value != String.Empty)                 
1049                                 return Resolve (context);
1050                         return true;
1051                 }
1052
1053                 //
1054                 // Throws an exception if parent is a native object
1055                 // and does not contains name as member.
1056                 // Returns true if parent contains name as member. 
1057                 // Returns false if parent is not a native object,
1058                 // this indicate that late binding code must get generated.
1059                 //
1060                 public bool ResolveFieldAccess (AST parent)
1061                 {
1062                         if (parent is Identifier) {
1063                                 Identifier p = parent as Identifier;
1064                                 return is_static_property (p.name.Value, name.Value);
1065                         }
1066                         //
1067                         // Return false so late binding will take place
1068                         //
1069                         return false;
1070                 }
1071
1072                 //
1073                 // If obj_name is a native object, search in its
1074                 // constructor if contains a prop_name, otherwise return
1075                 // false letting late binding taking place
1076                 //
1077                 bool is_static_property (string obj_name, string prop_name)
1078                 {
1079                         bool native_obj = SemanticAnalyser.is_js_object (obj_name);
1080
1081                         if (!native_obj)
1082                                 return false;
1083
1084                         bool contains_method;
1085                         contains_method = SemanticAnalyser.object_contains (
1086                                            SemanticAnalyser.map_to_ctr (obj_name), prop_name);
1087                         if (!contains_method)
1088                                 throw new Exception ("error: JS0438: Object " + obj_name + " doesn't support this property or method:" + prop_name);
1089                         return true;
1090                 }
1091
1092                 internal override void Emit (EmitContext ec)
1093                 {
1094                         ILGenerator ig = ec.ig;
1095                         if (assign && right_side != null)
1096                                 right_side.Emit (ec);
1097                         if (binding is FormalParam) {
1098                                 FormalParam f = binding as FormalParam;
1099                                 if (assign)
1100                                         ig.Emit (OpCodes.Starg, (short) f.pos);
1101                                 else
1102                                         ig.Emit (OpCodes.Ldarg_S, f.pos);
1103                         } else if (binding is VariableDeclaration || binding is Try || binding is Catch) {
1104                                 if (NeedParents) {
1105                                         CodeGenerator.emit_parents (InFunction, lexical_difference, ig);
1106                                         store_stack_frame_into_locals (ec.ig);
1107                                         if (this.local_builder != null)
1108                                                 if (assign)
1109                                                         ig.Emit (OpCodes.Stloc, local_builder);
1110                                                 else
1111                                                         ig.Emit (OpCodes.Ldloc, local_builder);
1112                                 } else {
1113                                         FieldInfo field_info = extract_field_info (binding);
1114                                         LocalBuilder local_builder = extract_local_builder (binding);
1115                                 
1116                                         if (field_info != null) {
1117                                                 if (assign)
1118                                                         ig.Emit (OpCodes.Stsfld, field_info);
1119                                                 else
1120                                                         ig.Emit (OpCodes.Ldsfld, field_info);
1121                                         } else if (local_builder != null) {
1122                                                 if (assign)
1123                                                         ig.Emit (OpCodes.Stloc, local_builder);
1124                                                 else
1125                                                         ig.Emit (OpCodes.Ldloc, local_builder);
1126                                         }
1127                                 }
1128                         } else if (binding is BuiltIn)
1129                                 binding.Emit (ec);
1130                         else if (binding is FunctionDeclaration)
1131                                 load_script_func (ec, (FunctionDeclaration) binding);
1132                         else if (binding == null) // it got referenced before was declared and initialized
1133                                 Console.WriteLine ("id = {0}, Identifier.Emit, binding == null? {1}", name.Value, binding == null);
1134                         else
1135                                 Console.WriteLine ("Identifier.Emit, binding.GetType = {0}", binding.GetType ());
1136
1137                         if (!assign && no_effect)
1138                                 ig.Emit (OpCodes.Pop);                          
1139                 }
1140
1141                 internal void EmitStore (EmitContext ec)
1142                 {
1143                         ILGenerator ig = ec.ig;
1144
1145                         if (binding is FormalParam) {
1146                                 FormalParam f = binding as FormalParam;
1147                                 ig.Emit (OpCodes.Starg, (short) f.pos);
1148                         } else if (binding is VariableDeclaration || binding is Try) {
1149                                 FieldInfo fb = extract_field_info (binding);
1150                                 LocalBuilder local = extract_local_builder (binding);
1151                                 if (fb == null)
1152                                         ig.Emit (OpCodes.Stloc, local);
1153                                 else
1154                                         ig.Emit (OpCodes.Stsfld, fb);                                   
1155                         }
1156                 }
1157
1158                 internal void EmitLoad (EmitContext ec)
1159                 {
1160                         ILGenerator ig = ec.ig;
1161
1162                         if (binding is FormalParam) {
1163                                 FormalParam f = binding as FormalParam;
1164                                 ig.Emit (OpCodes.Ldarg_S, f.pos);
1165                         } else if (binding is VariableDeclaration || binding is Try) {
1166                                 FieldInfo fb = extract_field_info (binding);
1167                                 LocalBuilder local = extract_local_builder (binding);
1168                                 if (fb == null)
1169                                         ig.Emit (OpCodes.Ldloc, local);
1170                                 else
1171                                         ig.Emit (OpCodes.Ldsfld, fb);
1172                         }
1173                 }
1174
1175                 void load_script_func (EmitContext ec, FunctionDeclaration binding)
1176                 {
1177                         object bind = TypeManager.Get (binding.func_obj.name);
1178                                                        
1179                         if (bind != null) {
1180                                 if (bind is MethodBuilder) {
1181                                         TypeBuilder type = ec.type_builder;
1182                                         if (binding.InFunction) {
1183                                                 LocalBuilder local_meth = (LocalBuilder) TypeManager.GetLocalScriptFunction (binding.func_obj.name);
1184                                                 ec.ig.Emit (OpCodes.Ldloc, local_meth);
1185                                         } else {
1186                                                 FieldInfo method = type.GetField (binding.func_obj.name);
1187                                                 ec.ig.Emit (OpCodes.Ldsfld, method);
1188                                         }
1189                                 } else if (bind is LocalBuilder)
1190                                         ec.ig.Emit (OpCodes.Ldloc, (LocalBuilder) bind);
1191                                 else throw new Exception ("load_script_func");
1192                         }
1193                 }
1194
1195                 internal FieldInfo extract_field_info (AST a)
1196                 {
1197                         FieldInfo r = null;
1198
1199                         if (a is VariableDeclaration)
1200                                 r = ((VariableDeclaration) a).field_info;
1201                         else if (a is Try)
1202                                 r = ((Try) a).field_info;
1203                         else if (a is Catch)
1204                                 r = ((Catch) a).field_info;
1205                         return r;
1206                 }
1207                 
1208                 internal LocalBuilder extract_local_builder (AST a)
1209                 {
1210                         LocalBuilder r = null;
1211                         if (a is VariableDeclaration)
1212                                 r = ((VariableDeclaration) a).local_builder;
1213                         else if (a is Try)
1214                                 r = ((Try) a).local_builder;
1215                         else if (a is Catch)
1216                                 r = ((Catch) a).local_builder;
1217                         return r;
1218                 }
1219                 
1220                 //
1221                 // FIXME: Only must store the extern variables which are used.
1222                 //
1223                 internal void store_stack_frame_into_locals (ILGenerator ig)
1224                 {
1225                         ig.Emit (OpCodes.Dup);
1226
1227                         Type stack_frame = typeof (StackFrame);
1228                         ig.Emit (OpCodes.Castclass, stack_frame);
1229                         ig.Emit (OpCodes.Ldfld, stack_frame.GetField ("localVars"));
1230                         
1231                         DictionaryEntry [] locals = TypeManager.LocalsAtDepth (((VariableDeclaration) binding).lexical_depth);
1232
1233                         int i = 0;
1234                         LocalBuilder local = null;
1235
1236                         foreach (DictionaryEntry entry in locals) {
1237                                 if (entry.Value is LocalBuilder) {
1238                                         local = ig.DeclareLocal (typeof (object));
1239                                         if (entry.Key == name.Value)
1240                                                 this.local_builder = local;
1241                                         ig.Emit (OpCodes.Dup);
1242                                         ig.Emit (OpCodes.Ldc_I4, i++);
1243                                         ig.Emit (OpCodes.Ldelem_Ref);
1244                                         ig.Emit (OpCodes.Stloc, (LocalBuilder) local);
1245                                 }
1246                         }
1247                         ig.Emit (OpCodes.Pop);
1248
1249                         //
1250                         // FIXME: what does it determine this?
1251                         //
1252                         ig.Emit (OpCodes.Call, typeof (ScriptObject).GetMethod ("GetParent"));
1253                         ig.Emit (OpCodes.Pop);                  
1254                 }
1255         }
1256
1257         internal class Args : AST {
1258
1259                 internal ArrayList elems;
1260                 int num_of_args = -1;
1261                 internal Function func;
1262                 internal bool is_print;
1263                 internal ParameterInfo [] params_info;
1264                 internal bool late_bind = false;
1265                 internal bool var_args = false;
1266                 
1267                 internal Args ()
1268                 {
1269                         elems = new ArrayList ();
1270                 }
1271
1272                 internal void Add (AST e)
1273                 {
1274                         elems.Add (e);
1275                 }
1276                 
1277                 internal int DesiredNumOfArgs {
1278                         set { 
1279                                 if (!(value < 0))
1280                                         num_of_args = value; 
1281                         }
1282                 }
1283                 
1284                 internal bool IsPrint {
1285                         set { is_print = value; }
1286                 }
1287
1288                 internal void has_var_args (MethodInfo minfo)
1289                 {
1290                         JSFunctionAttribute [] custom_attrs = (JSFunctionAttribute []) 
1291                                 minfo.GetCustomAttributes (typeof (JSFunctionAttribute), true);
1292
1293                         foreach (JSFunctionAttribute attr in custom_attrs)
1294                                 if (attr.GetAttributeValue () == JSFunctionAttributeEnum.HasVarArgs) {
1295                                         var_args = true;
1296                                         return;
1297                                 }
1298                         var_args = false;
1299                 }
1300
1301                 internal override bool Resolve (IdentificationTable context)
1302                 {
1303                         int n = elems.Count;
1304                         AST tmp;
1305                         bool r = true;
1306
1307                         if (!is_print && !var_args &&  num_of_args >= 0 && n > num_of_args)
1308                                 Console.WriteLine ("warning JS1148: There are too many arguments. The extra arguments will be ignored");
1309                         for (int i = 0; i < n; i++) {
1310                                 tmp = (AST) elems [i];
1311                                 r &= tmp.Resolve (context);
1312                         }
1313                         return r;
1314                 }
1315
1316                 internal AST get_element (int i)
1317                 {
1318                         if (i >= 0 && i < elems.Count)
1319                                 return (AST) elems [i];
1320                         else
1321                                 return null;
1322                 }
1323
1324                 internal int Size {
1325                         get { return elems.Count; }
1326                 }
1327
1328                 internal override void Emit (EmitContext ec)
1329                 {
1330                         int n;
1331                         ILGenerator ig = ec.ig;
1332
1333                         if (var_args) {
1334                                 n = elems.Count;
1335                                 ig.Emit (OpCodes.Ldc_I4, n);
1336                                 ig.Emit (OpCodes.Newarr, typeof (object));
1337                                 for (int i = 0; i < n; i++) {
1338                                         ig.Emit (OpCodes.Dup);
1339                                         ig.Emit (OpCodes.Ldc_I4, i);
1340                                         get_element (i).Emit (ec);
1341                                         ig.Emit (OpCodes.Stelem_Ref);
1342                                 }
1343                         } else {
1344                                 n = elems.Count;
1345                                 if (num_of_args < 0)
1346                                         num_of_args = n;
1347                                 AST ast;
1348                                 for (int j = 0; j < n && j < num_of_args; j++) {
1349                                         ast = get_element (j);
1350                                         ast.Emit (ec);
1351                                         if (!late_bind && params_info != null)
1352                                                 force_strong_type (ig, ast, params_info [j]);
1353                                 }
1354                                 int missing = 0;
1355                                 if (func != null) 
1356                                         missing = func.NumOfArgs - n;
1357                                 else if (params_info != null)
1358                                         missing = params_info.Length - n;
1359
1360                                 for (int k = 0; k < missing; k++)
1361                                         ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
1362                         }
1363                 }
1364
1365                 internal void force_strong_type (ILGenerator ig, AST ast, ParameterInfo pinfo)
1366                 {
1367                         Type param_type = pinfo.ParameterType;
1368                         if (ast.GetType () == typeof (NumericLiteral)) {
1369                                 if (param_type == typeof (double))
1370                                         ig.Emit (OpCodes.Conv_R8);
1371                                 else if (param_type == typeof (object))
1372                                         ;
1373                                 else throw new NotImplementedException ();
1374                         } else {
1375
1376                                 if (param_type == typeof (double))
1377                                         ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber", new Type [] {typeof (object)}));
1378                                 else if (param_type == typeof (string)) {
1379                                         ig.Emit (OpCodes.Ldc_I4_1);
1380                                         ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToString", new Type [] {typeof (object), typeof (bool)}));
1381                                 } else if (param_type == typeof (object))
1382                                         ;
1383                                 else throw new NotImplementedException ();
1384                         }                       
1385                 }
1386         }
1387
1388         internal class Expression : Exp {
1389
1390                 internal ArrayList exprs;
1391
1392                 internal int Size {
1393                         get { return exprs.Count; }
1394                 }
1395
1396                 internal Expression (AST parent)
1397                 {
1398                         this.parent = parent;
1399                         exprs = new ArrayList ();
1400                 }
1401
1402                 internal void Add (AST a)
1403                 {
1404                         exprs.Add (a);
1405                 }
1406
1407                 public override string ToString ()
1408                 {
1409                         int size = exprs.Count;         
1410
1411                         if (size > 0) {
1412                                 int i;
1413                                 StringBuilder sb = new StringBuilder ();
1414
1415                                 for (i = 0; i < size; i++)
1416                                         sb.Append (exprs [i].ToString ());
1417
1418                                 sb.Append ("\n");
1419                                 return sb.ToString ();
1420
1421                         } else return String.Empty;
1422                 }
1423
1424                 internal override bool Resolve (IdentificationTable context)
1425                 {
1426                         int i, n;
1427                         object e;
1428                         bool r = true;
1429                         
1430                         n = exprs.Count - 1;
1431
1432                         for (i = 0; i < n; i++) {
1433                                 e = exprs [i];
1434                                 if (e is Exp)
1435                                         r &= ((Exp) e).Resolve (context, true);
1436                                 else
1437                                         r &= ((AST) e).Resolve (context);
1438                         }
1439                         e = exprs [n];
1440                         if (e is Exp)
1441                                 if (e is Assign)
1442                                         r &= ((Assign) e).Resolve (context);
1443                                 else
1444                                         r &= ((Exp) e).Resolve (context, no_effect);
1445                         else 
1446                                 ((AST) e).Resolve (context);
1447
1448                         return r;
1449                 }
1450
1451                 internal override bool Resolve (IdentificationTable context, bool no_effect)
1452                 {
1453                         this.no_effect = no_effect;
1454                         return Resolve (context);
1455                 }
1456
1457                 internal override void Emit (EmitContext ec)
1458                 {
1459                         int i, n = exprs.Count;
1460                         AST exp;
1461
1462                         for (i = 0; i < n; i++) {
1463                                 exp = (AST) exprs [i];
1464                                 exp.Emit (ec);
1465                         }
1466                 }
1467         }
1468
1469         internal class Assign : BinaryOp {
1470
1471                 internal bool is_embedded;
1472
1473                 internal Assign (AST parent, AST left, AST right, JSToken op, bool is_embedded)
1474                         : base (left, right, op)
1475                 {
1476                         this.parent = parent;
1477                         this.is_embedded = is_embedded;
1478                 }
1479
1480                 //
1481                 // after calling Resolve, left contains all the 
1482                 // information about the assignment
1483                 //
1484                 internal override bool Resolve (IdentificationTable context)
1485                 {                                               
1486                         bool r;
1487
1488                         if (left is IAssignable)
1489                                 r = ((IAssignable) left).ResolveAssign (context, right);
1490                         else
1491                                 throw new Exception ("(" + line_number + ",0): error JS5008: Illegal assignment");
1492                         if (right is Exp)
1493                                 r &=((Exp) right).Resolve (context, false);
1494                         else
1495                                 r &= right.Resolve (context);
1496                         return r;
1497                 }
1498
1499                 internal override bool Resolve (IdentificationTable context, bool no_effect)
1500                 {
1501                         return true;
1502                 }
1503
1504                 internal override void Emit (EmitContext ec)
1505                 {
1506                         if (op == JSToken.Assign) {
1507                                 if (is_embedded) {
1508                                         Console.WriteLine ("embedded assignments not supported yet");
1509                                         Environment.Exit (-1);
1510                                 } 
1511                                 left.Emit (ec);
1512                         } else {
1513                                 ILGenerator ig = ec.ig;
1514                                 Type type = null;
1515                                 LocalBuilder local = null;
1516                                 LocalBuilder aux = ig.DeclareLocal (typeof (object));
1517                                 
1518                                 switch (op) {
1519                                 case JSToken.PlusAssign:
1520                                         type = typeof (Plus);
1521                                         local = ig.DeclareLocal (type);
1522                                         ig.Emit (OpCodes.Newobj, type.GetConstructor (new Type [] {}));
1523                                         ig.Emit (OpCodes.Stloc, local);
1524                                         if (left is Identifier)
1525                                                 ((Identifier) left).EmitLoad (ec);
1526                                         ig.Emit (OpCodes.Stloc, aux);
1527                                         ig.Emit (OpCodes.Ldloc, local);
1528                                         ig.Emit (OpCodes.Ldloc, aux);
1529                                         if (right != null)
1530                                                 right.Emit (ec);
1531                                         ig.Emit (OpCodes.Call, type.GetMethod ("EvaluatePlus"));
1532                                         if (left is Identifier)
1533                                                 ((Identifier) left).EmitStore (ec);
1534                                         return;
1535                                 case JSToken.MinusAssign:
1536                                 case JSToken.MultiplyAssign:
1537                                 case JSToken.DivideAssign:
1538                                 case JSToken.ModuloAssign:
1539                                         type = typeof (NumericBinary);
1540                                         break;
1541                                 case JSToken.BitwiseAndAssign:
1542                                 case JSToken.BitwiseOrAssign:
1543                                 case JSToken.BitwiseXorAssign:
1544                                 case JSToken.LeftShiftAssign:
1545                                 case JSToken.RightShiftAssign:
1546                                 case JSToken.UnsignedRightShiftAssign:
1547                                         type = typeof (BitwiseBinary);
1548                                         break;                         
1549                                 }
1550                                 local = ig.DeclareLocal (type);
1551                                 load_parameter (ig, op);
1552
1553                                 ig.Emit (OpCodes.Newobj, type.GetConstructor (new Type [] {typeof (int)}));
1554                                 ig.Emit (OpCodes.Stloc, local);
1555
1556                                 if (left is Identifier)
1557                                         ((Identifier) left).EmitLoad (ec);
1558
1559                                 ig.Emit (OpCodes.Stloc, aux);
1560                                 ig.Emit (OpCodes.Ldloc, local);
1561                                 ig.Emit (OpCodes.Ldloc, aux);
1562
1563                                 if (right != null)
1564                                         right.Emit (ec);
1565
1566                                 emit_evaluation (op, type, ig);
1567                                 
1568                                 if (left is Identifier)
1569                                         ((Identifier) left).EmitStore (ec);
1570                         }
1571                 }
1572
1573                 void load_parameter (ILGenerator ig, JSToken op)
1574                 {
1575                         switch (op) {
1576                         case JSToken.MinusAssign: 
1577                                 ig.Emit (OpCodes.Ldc_I4_S, 47);
1578                                 break;
1579                         case JSToken.BitwiseOrAssign:
1580                                 ig.Emit (OpCodes.Ldc_I4_S, 50);
1581                                 break;
1582                         case JSToken.BitwiseXorAssign:
1583                                 ig.Emit (OpCodes.Ldc_I4_S, 51);
1584                                 break;
1585                         case JSToken.BitwiseAndAssign:
1586                                 ig.Emit (OpCodes.Ldc_I4_S, 52);
1587                                 break;
1588                         case JSToken.LeftShiftAssign:
1589                                 ig.Emit (OpCodes.Ldc_I4_S, 61);
1590                                 break;
1591                         case JSToken.RightShiftAssign:
1592                                 ig.Emit (OpCodes.Ldc_I4_S, 62);
1593                                 break;                          
1594                         case JSToken.UnsignedRightShiftAssign:
1595                                 ig.Emit (OpCodes.Ldc_I4_S, 63);
1596                                 break;
1597                         case JSToken.MultiplyAssign:
1598                                 ig.Emit (OpCodes.Ldc_I4_S, 64);
1599                                 break;
1600                         case JSToken.DivideAssign:
1601                                 ig.Emit (OpCodes.Ldc_I4_S, 65);
1602                                 break;
1603                         case JSToken.ModuloAssign:
1604                                 ig.Emit (OpCodes.Ldc_I4_S, 66);
1605                                 break;
1606                         default:
1607                                 throw new NotImplementedException ();
1608                         }
1609                 }
1610
1611                 void emit_evaluation (JSToken op, Type type, ILGenerator ig)
1612                 {
1613                         switch (op) {
1614                         case JSToken.MinusAssign:
1615                         case JSToken.MultiplyAssign:
1616                         case JSToken.DivideAssign:
1617                         case JSToken.ModuloAssign:
1618                                 ig.Emit (OpCodes.Call, type.GetMethod ("EvaluateNumericBinary"));
1619                                 break;
1620                         case JSToken.BitwiseAndAssign:
1621                         case JSToken.BitwiseOrAssign:
1622                         case JSToken.BitwiseXorAssign:
1623                         case JSToken.LeftShiftAssign:
1624                         case JSToken.RightShiftAssign:
1625                         case JSToken.UnsignedRightShiftAssign:
1626                                 ig.Emit (OpCodes.Call, type.GetMethod ("EvaluateBitwiseBinary"));
1627                                 break;
1628                         default:
1629                                 throw new NotImplementedException ();
1630                         }
1631
1632                 }
1633
1634                 public override string ToString ()
1635                 {
1636                         string l = left.ToString ();
1637                         string r = right.ToString ();
1638                         return l + " " + op.ToString () + " " + r;
1639                 }
1640         }
1641
1642         internal class New : AST, ICallable {
1643
1644                 AST exp;
1645                 Args args;
1646                 bool late_bind = false;
1647
1648                 internal New (AST parent, AST exp)
1649                 {
1650                         this.parent = parent;
1651                         this.exp = exp;
1652                         this.args = new Args ();
1653                 }
1654
1655                 public void AddArg (AST arg)
1656                 {
1657                         args.Add (arg);
1658                 }
1659                 
1660                 internal override bool Resolve (IdentificationTable context)
1661                 {
1662                         bool r = true;
1663
1664                         if (exp != null && exp.GetType () == typeof (Identifier)) {
1665                                 Identifier id = (Identifier) exp;
1666                                 late_bind = !SemanticAnalyser.is_js_object (id.name.Value);
1667                         } 
1668                         exp.Resolve (context);
1669
1670                         if (args != null)
1671                                 r &= args.Resolve (context);
1672                         return r;
1673                 }
1674
1675                 internal override void Emit (EmitContext ec)
1676                 {
1677                         ILGenerator ig = ec.ig;
1678
1679                         if (exp != null) {
1680                                 if (late_bind) {                                        
1681                                         CodeGenerator.emit_get_default_this (ec.ig);
1682                                         exp.Emit (ec);
1683
1684                                         ig.Emit (OpCodes.Ldc_I4, args.Size);
1685                                         ig.Emit (OpCodes.Newarr, typeof (object));
1686
1687                                         for (int i = 0; i < args.Size; i++) {
1688                                                 ig.Emit (OpCodes.Dup);
1689                                                 ig.Emit (OpCodes.Ldc_I4, i);
1690                                                 args.get_element (i).Emit (ec);
1691                                                 ig.Emit (OpCodes.Stelem_Ref);
1692                                         }
1693                                         
1694                                         ig.Emit (OpCodes.Ldc_I4_1);
1695                                         ig.Emit (OpCodes.Ldc_I4_0);
1696
1697                                         ig.Emit (OpCodes.Ldarg_0);
1698                                         ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
1699
1700                                         ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
1701                                 } else {
1702                                         if (exp != null)
1703                                                 exp.Emit (ec);
1704                                         if (args != null)
1705                                                 emit_args (ec);
1706                                         emit_create_instance (ec);
1707                                 }
1708                         }
1709                 }
1710                 
1711                 void emit_create_instance (EmitContext ec)
1712                 {
1713                         if (exp is Identifier) {
1714                                 ILGenerator ig = ec.ig;
1715                                 Type type = null;
1716                                 switch ((exp as Identifier).name.Value) {
1717                                 case "Array":                                   
1718                                         type = typeof (ArrayConstructor);
1719                                         break;
1720                                 case "Date":
1721                                         type = typeof (DateConstructor);
1722                                         break;
1723                                 case "Number":
1724                                         type = typeof (NumberConstructor);
1725                                         break;
1726                                 case "Object":
1727                                         type = typeof (ObjectConstructor);
1728                                         break;
1729                                 case "RegExp":
1730                                         type = typeof (RegExpConstructor);
1731                                         break;
1732                                 case "String":
1733                                         type = typeof (StringConstructor);
1734                                         break;
1735                                 case "Boolean":
1736                                         type = typeof (BooleanConstructor);
1737                                         break;
1738                                 case "Function":
1739                                         type = typeof (FunctionConstructor);
1740                                         break;
1741                                 }
1742                                 if (type != null)
1743                                         ig.Emit (OpCodes.Call, type.GetMethod ("CreateInstance"));
1744                         }
1745                 }
1746                 
1747                 void emit_args (EmitContext ec)
1748                 {
1749                         ILGenerator ig = ec.ig;
1750                         int n = args.Size;
1751                         ig.Emit (OpCodes.Ldc_I4, args.Size);
1752                         ig.Emit (OpCodes.Newarr, typeof (object));
1753
1754                         for (int i = 0; i < n; i++) {
1755                                 ig.Emit (OpCodes.Dup);
1756                                 ig.Emit (OpCodes.Ldc_I4, i);
1757                                 args.get_element (i).Emit (ec);
1758                                 ig.Emit (OpCodes.Stelem_Ref);
1759                         }
1760                 }
1761         }
1762         
1763         internal interface IAssignable {
1764                 bool ResolveAssign (IdentificationTable context, AST right_side);
1765         }
1766
1767         internal class BuiltIn : AST {
1768                 string name;
1769                 bool allowed_as_ctr;
1770                 bool allowed_as_func;
1771
1772                 internal BuiltIn (string name, bool allowed_as_ctr, bool allowed_as_func)
1773                 {
1774                         this.name = name;
1775                         this.allowed_as_ctr = allowed_as_ctr;
1776                         this.allowed_as_func = allowed_as_func;
1777                 }
1778
1779                 internal override bool Resolve (IdentificationTable context)
1780                 {
1781                         return true;
1782                 }
1783                 
1784                 internal string Name {
1785                         get { return name; }
1786                 }
1787                 
1788                 internal bool IsConstructor {
1789                         get { return allowed_as_ctr; }
1790                 }
1791
1792                 internal bool IsFunction {
1793                         get { return allowed_as_func; }
1794                 }
1795
1796                 internal bool IsPrint {
1797                         get { return String.Equals (name, "print"); }
1798                 }
1799                 internal int NumOfArgs {
1800                         get {
1801                                 if (name == "print")
1802                                         return -1;
1803
1804                                 Type global_object = typeof (GlobalObject);
1805                                 MethodInfo method = global_object.GetMethod (name);
1806                                 return method.GetParameters ().Length;
1807                         }
1808                 }
1809
1810                 internal ParameterInfo [] Parameters {
1811                         get {
1812                                 Type global_obj = typeof (GlobalObject);
1813                                 return global_obj.GetMethod (name).GetParameters ();
1814                         }
1815                 }
1816
1817                 internal override void Emit (EmitContext ec)
1818                 {
1819                         ILGenerator ig = ec.ig;
1820                         Type go = typeof (GlobalObject);
1821                         switch (name) {
1822                         /* value properties of the Global Object */
1823                         case "NaN":
1824                                 ig.Emit (OpCodes.Ldc_R8, Double.NaN);
1825                                 ig.Emit (OpCodes.Box, typeof (Double));
1826                                 break;                          
1827                         case "Infinity":
1828                                 ig.Emit (OpCodes.Ldc_R8, Double.PositiveInfinity);
1829                                 // FIXME: research when not to generate the Boxing
1830                                 ig.Emit (OpCodes.Box, typeof (Double));
1831                                 break;
1832                         case "undefined":
1833                                 ig.Emit (OpCodes.Ldnull);
1834                                 break;
1835                         case "null":
1836                                 ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
1837                                 break;
1838                                 
1839                         /* function properties of the Global Object */
1840                         case "eval":
1841                                 Type [] method_args = null;
1842 #if NET_1_0
1843                                 method_args = new Type [] {typeof (object), typeof (VsaEngine)};
1844 #else
1845                                 method_args = new Type [] {typeof (object), typeof (object), typeof (VsaEngine)};
1846 #endif
1847                                 ig.Emit (OpCodes.Call, typeof (Eval).GetMethod ("JScriptEvaluate", method_args));
1848                                 break;
1849                         case "parseInt":                                
1850                                 ig.Emit (OpCodes.Call, go.GetMethod ("parseInt"));
1851                                 ig.Emit (OpCodes.Box, typeof (Double));
1852                                 break;
1853                         case "parseFloat":
1854                                 ig.Emit (OpCodes.Call, go.GetMethod ("parseFloat"));
1855                                 ig.Emit (OpCodes.Box, typeof (Double));
1856                                 break;
1857                         case "isNaN":
1858                                 ig.Emit (OpCodes.Call, go.GetMethod ("isNaN"));
1859                                 ig.Emit (OpCodes.Box, typeof (bool));
1860                                 break;
1861                         case "isFinite":
1862                                 ig.Emit (OpCodes.Call, go.GetMethod ("isFinite"));
1863                                 ig.Emit (OpCodes.Box, typeof (bool));
1864                                 break;
1865                         case "decodeURI":
1866                                 ig.Emit (OpCodes.Call, go.GetMethod ("decodeURI"));
1867                                 break;
1868                         case "decodeURIComponent":
1869                                 ig.Emit (OpCodes.Call, go.GetMethod ("decodeURIComponent"));
1870                                 break;
1871                         case "encodeURI":
1872                                 ig.Emit (OpCodes.Call, go.GetMethod ("encodeURI"));
1873                                 break;
1874                         case "encodeURIComponent":
1875                                 ig.Emit (OpCodes.Call, go.GetMethod ("encodeURIComponent"));
1876                                 break;
1877                         case "escape":
1878                                 ig.Emit (OpCodes.Call, go.GetMethod ("escape"));
1879                                 break;
1880                         case "unescape":
1881                                 ig.Emit (OpCodes.Call, go.GetMethod ("unescape"));
1882                                 break;
1883                         /* constructor properties of the Global object */
1884                         case "Object":
1885                                 ig.Emit (OpCodes.Call, go.GetProperty ("Object").GetGetMethod ());
1886                                 break;
1887                         case "Function":
1888                                 ig.Emit (OpCodes.Call, go.GetProperty ("Function").GetGetMethod ());
1889                                 break;
1890                         case "Array":
1891                                 ig.Emit (OpCodes.Call, go.GetProperty ("Array").GetGetMethod ());
1892                                 break;
1893                         case "String":
1894                                 ig.Emit (OpCodes.Call, go.GetProperty ("String").GetGetMethod ());
1895                                 break;
1896                         case "Boolean":
1897                                 ig.Emit (OpCodes.Call, go.GetProperty ("Boolean").GetGetMethod ());
1898                                 break;
1899                         case "Number":
1900                                 ig.Emit (OpCodes.Call, go.GetProperty ("Number").GetGetMethod ());
1901                                 break;
1902                         case "Date":
1903                                 ig.Emit (OpCodes.Call, go.GetProperty ("Date").GetGetMethod ());
1904                                 break;
1905                         case "RegExp":
1906                                 ig.Emit (OpCodes.Call, go.GetProperty ("RegExp").GetGetMethod ());
1907                                 break;
1908                         case "Error":
1909                                 ig.Emit (OpCodes.Call, go.GetProperty ("Error").GetGetMethod ());
1910                                 break;
1911                         case "EvalError":
1912                                 ig.Emit (OpCodes.Call, go.GetProperty ("EvalError").GetGetMethod ());
1913                                 break;
1914                         case "RangeError":
1915                                 ig.Emit (OpCodes.Call, go.GetProperty ("RangeError").GetGetMethod ());
1916                                 break;
1917
1918                         case "ReferenceError":
1919                                 ig.Emit (OpCodes.Call, go.GetProperty ("ReferenceError").GetGetMethod ());
1920                                 break;
1921
1922                         case "SyntaxError":
1923                                 ig.Emit (OpCodes.Call, go.GetProperty ("SyntaxError").GetGetMethod ());
1924                                 break;
1925
1926                         case "TypeError":
1927                                 ig.Emit (OpCodes.Call, go.GetProperty ("TypeError").GetGetMethod ());
1928                                 break;
1929
1930                         case "URIError":
1931                                 ig.Emit (OpCodes.Call, go.GetProperty ("URIError").GetGetMethod ());
1932                                 break;
1933                         /* other properties of the Global object */
1934                         case "Math":
1935                                 ig.Emit (OpCodes.Call, go.GetProperty ("Math").GetGetMethod ());
1936                                 break;
1937                         default:
1938                                 throw new Exception ("This is BuiltIn " + name);
1939                         }
1940                 }
1941         }
1942 }