2 // expression.cs: Everything related to expressions
5 // Cesar Lopez Nataren (cesar@ciencias.unam.mx)
7 // (C) 2003, 2004 Cesar Lopez Nataren
8 // (C) 2005, Novell Inc. (http://novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
34 using System.Collections;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 using Microsoft.JScript.Vsa;
39 namespace Microsoft.JScript {
41 public abstract class Exp : AST {
42 internal bool no_effect;
43 internal abstract bool Resolve (IdentificationTable context, bool no_effect);
46 internal class Unary : UnaryOp {
48 internal Unary (AST parent, JSToken oper)
54 public override string ToString ()
56 StringBuilder sb = new StringBuilder ();
58 if (oper != JSToken.None)
59 sb.Append (oper + " ");
62 sb.Append (operand.ToString ());
64 return sb.ToString ();
67 internal override bool Resolve (IdentificationTable context)
72 if (oper != JSToken.Increment && oper != JSToken.Decrement)
73 r = ((Exp) operand).Resolve (context, no_effect);
74 r = ((AST) operand).Resolve (context);
78 internal override bool Resolve (IdentificationTable context, bool no_effect)
80 this.no_effect = no_effect;
81 return Resolve (context);
84 internal override void Emit (EmitContext ec)
88 if (oper != JSToken.Minus)
92 internal void emit_unary_op (EmitContext ec)
94 ILGenerator ig = ec.ig;
97 ig.Emit (OpCodes.Call, typeof (Typeof).GetMethod ("JScriptTypeof"));
103 internal class Binary : BinaryOp, IAssignable {
105 bool assign, late_bind = false;
108 internal Binary (AST parent, AST left, JSToken op)
109 : this (parent, left, null, op)
113 internal Binary (AST parent, AST left, AST right, JSToken op)
114 : base (left, right, op)
116 this.parent = parent;
119 public override string ToString ()
121 StringBuilder sb = new StringBuilder ();
122 sb.Append (left.ToString () + " ");
124 if (op != JSToken.None)
125 sb.Append (op + " ");
128 sb.Append (right.ToString ());
130 return sb.ToString ();
133 internal bool AccessField {
134 get { return op == JSToken.AccessField; }
137 internal override bool Resolve (IdentificationTable context)
141 r &= left.Resolve (context);
143 if (op == JSToken.AccessField && right is IAccesible) {
144 r &= ((IAccesible) right).ResolveFieldAccess (left);
148 r &= right.Resolve (context);
152 internal override bool Resolve (IdentificationTable context, bool no_effect)
154 this.no_effect = no_effect;
155 return Resolve (context);
158 public bool ResolveAssign (IdentificationTable context, AST right_side)
160 if (op == JSToken.LeftBracket || op == JSToken.AccessField) {
161 this.no_effect = false;
163 this.right_side = right_side;
164 return Resolve (context);
166 throw new Exception ("error JS5008: Illegal assignment");
169 internal MemberInfo Binding {
171 return SemanticAnalyser.get_member (left, right);
175 internal override void Emit (EmitContext ec)
177 ILGenerator ig = ec.ig;
178 if (op == JSToken.None) {
181 } else if (op == JSToken.LogicalAnd || op == JSToken.LogicalOr)
182 emit_jumping_code (ec);
183 else if (op == JSToken.LeftBracket) {
185 get_default_this (ig);
188 emit_array_access (ec);
189 } else if (op == JSToken.AccessField) {
191 emit_late_binding (ec);
193 emit_access (left, right, ec);
203 ig.Emit (OpCodes.Pop);
206 void emit_access (AST obj, AST prop_name, EmitContext ec)
208 MemberInfo minfo = SemanticAnalyser.get_member (obj, prop_name);
209 ILGenerator ig = ec.ig;
210 MemberTypes minfo_type = minfo.MemberType;
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);
220 case MemberTypes.Property:
221 PropertyInfo property = (PropertyInfo) minfo;
222 Type decl_type = property.DeclaringType;
225 if (decl_type == typeof (RegExpConstructor)) {
226 t = typeof (GlobalObject);
228 ig.Emit (OpCodes.Call, t.GetProperty (FieldName (decl_type)).GetGetMethod ());
230 CodeGenerator.load_engine (InFunction, ig);
231 ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToObject2"));
232 ig.Emit (OpCodes.Castclass, decl_type);
234 ig.Emit (OpCodes.Call, decl_type.GetProperty (property.Name).GetGetMethod ());
237 throw new NotImplementedException ();
239 emit_box (ig, minfo);
242 void emit_box (ILGenerator ig, MemberInfo info)
244 MemberTypes member_type = info.MemberType;
247 switch (member_type) {
248 case MemberTypes.Field:
249 type = ((FieldInfo) info).FieldType;
253 ig.Emit (OpCodes.Box, type);
256 private string FieldName (Type type)
258 if (type == typeof (RegExpConstructor))
260 throw new NotImplementedException ();
263 void emit_late_binding (EmitContext ec)
265 LocalBuilder local_lb = init_late_binding (ec);
266 emit_late_get_or_set (ec, local_lb);
269 LocalBuilder init_late_binding (EmitContext ec)
271 ILGenerator ig = ec.ig;
272 Type lb_type = typeof (LateBinding);
274 LocalBuilder local = ig.DeclareLocal (lb_type);
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);
284 void emit_late_get_or_set (EmitContext ec, LocalBuilder local)
286 ILGenerator ig = ec.ig;
288 ig.Emit (OpCodes.Ldloc, local);
289 ig.Emit (OpCodes.Dup);
293 CodeGenerator.load_engine (InFunction, ec.ig);
294 ig.Emit (OpCodes.Call , typeof (Convert).GetMethod ("ToObject"));
296 Type lb_type = typeof (LateBinding);
297 ig.Emit (OpCodes.Stfld, lb_type.GetField ("obj"));
300 right_side.Emit (ec);
301 ig.Emit (OpCodes.Call, lb_type.GetMethod ("SetValue"));
303 ig.Emit (OpCodes.Call, lb_type.GetMethod ("GetNonMissingValue"));
306 internal void get_default_this (ILGenerator ig)
309 ig.Emit (OpCodes.Ldarg_1);
311 ig.Emit (OpCodes.Ldarg_0);
312 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
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"));
321 internal void emit_array_access (EmitContext ec)
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);
330 ig.Emit (OpCodes.Stelem_Ref);
333 if (right_side != null)
334 right_side.Emit (ec);
335 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("SetIndexedPropertyValueStatic"));
337 ig.Emit (OpCodes.Ldc_I4_0);
338 ig.Emit (OpCodes.Ldc_I4_1);
341 ig.Emit (OpCodes.Ldarg_1);
343 ig.Emit (OpCodes.Ldarg_0);
344 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
346 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
350 internal void emit_op_eval (ILGenerator ig)
354 ig.Emit (OpCodes.Callvirt, typeof (Plus).GetMethod ("EvaluatePlus"));
359 case JSToken.Multiply:
360 ig.Emit (OpCodes.Call, typeof (NumericBinary).GetMethod ("EvaluateNumericBinary"));
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"));
373 internal void emit_jumping_code (EmitContext ec)
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);
389 internal void emit_operator (ILGenerator ig)
391 LocalBuilder local_builder = null;
394 if (op == JSToken.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);
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);
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);
448 internal class Conditional : Exp {
450 AST cond_exp, true_exp, false_exp;
452 internal Conditional (AST parent, AST expr, AST trueExpr, AST falseExpr)
454 this.cond_exp = expr;
455 this.true_exp = trueExpr;
456 this.false_exp = falseExpr;
459 public override string ToString ()
461 StringBuilder sb = new StringBuilder ();
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 ());
470 return sb.ToString ();
473 internal override bool Resolve (IdentificationTable context)
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);
485 internal override bool Resolve (IdentificationTable context, bool no_effect)
487 this.no_effect = no_effect;
488 return Resolve (context);
491 internal override void Emit (EmitContext ec)
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)
499 ig.Emit (OpCodes.Br, merge_label);
500 ig.MarkLabel (false_label);
501 if (false_exp != null)
503 ig.MarkLabel (merge_label);
505 ig.Emit (OpCodes.Pop);
509 internal interface ICallable {
510 void AddArg (AST arg);
513 internal class Call : Exp, ICallable {
515 internal AST member_exp;
517 internal object binding;
518 internal Type bind_type;
520 internal Call (AST parent, AST exp)
522 this.parent = parent;
523 this.member_exp = exp;
524 this.args = new Args ();
527 public override string ToString ()
529 StringBuilder sb = new StringBuilder ();
530 if (member_exp != null)
531 sb.Append (member_exp.ToString () + " ");
533 sb.Append (args.ToString ());
534 return sb.ToString ();
537 public void AddArg (AST arg)
542 internal override bool Resolve (IdentificationTable context)
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 ();
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)) {
559 // If a method contains an eval invocation
560 // we must generate proper code for accessing
561 // the local vars in the StackFrame.
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);
568 args.params_info = built_in.Parameters;
569 n = built_in.NumOfArgs;
571 } else if (bind_type == typeof (FunctionDeclaration) || bind_type == typeof (FunctionExpression)) {
572 args.func = (Function) binding;
573 n = (binding as Function).NumOfArgs;
575 } else if (member_exp is Binary) {
576 member_exp.Resolve (context);
577 Binary bin = (Binary) member_exp;
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;
589 r &= member_exp.Resolve (context);
592 args.DesiredNumOfArgs = n;
593 r &= args.Resolve (context);
596 throw new Exception ("Call.Resolve, member_exp can't be null");
600 internal override bool Resolve (IdentificationTable context, bool no_effect)
602 this.no_effect = no_effect;
603 return Resolve (context);
606 internal override void Emit (EmitContext ec)
608 if (bind_type == typeof (BuiltIn)) {
609 BuiltIn b = binding as BuiltIn;
613 } else if (IsGlobalObjectMethod (binding)) {
614 bool eval = IsEval (binding);
615 bool in_func = InFunction;
618 CodeGenerator.load_local_vars (ec.ig, in_func);
624 ec.ig.Emit (OpCodes.Ldnull);
626 CodeGenerator.load_engine (in_func, ec.ig);
628 member_exp.Emit (ec);
630 if (eval && no_effect && in_func)
631 ec.ig.Emit (OpCodes.Pop);
633 if (eval && in_func) {
634 set_local_vars (ec.ig);
637 } else if (IsConstructorProperty (binding)) {
638 member_exp.Emit (ec);
639 EmitBuiltInArgs (ec);
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);
646 if (SemanticAnalyser.MethodContainsEval (function.func_obj.name) ||
647 SemanticAnalyser.MethodReferenceOutterScopeVar (function.func_obj.name) ||
648 SemanticAnalyser.MethodVarsUsedNested (function.func_obj.name)) {
650 CodeGenerator.load_local_vars (ec.ig, true);
653 ec.ig.Emit (OpCodes.Pop);
655 set_local_vars (ec.ig);
658 emit_func_call (method, ec);
661 } else if (binding is MemberInfo) {
662 MemberInfo minfo = (MemberInfo) binding;
663 MemberTypes member_type = minfo.MemberType;
664 ILGenerator ig = ec.ig;
666 if (member_type == MemberTypes.Method) {
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);
674 throw new NotImplementedException ();
679 ec.ig.Emit (OpCodes.Pop);
682 internal void emit_print_stm (EmitContext ec)
684 ILGenerator ig = ec.ig;
686 if (args == null || args.Size == 0) {
687 ig.Emit (OpCodes.Ldstr, "");
688 ig.Emit (OpCodes.Call, typeof (ScriptStream).GetMethod ("WriteLine"));
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) });
698 int n = args.Size - 1;
700 for (int i = 0; i <= n; i++) {
701 ast = args.get_element (i);
704 if (ast is StringLiteral)
707 ig.Emit (OpCodes.Ldc_I4_1);
708 ig.Emit (OpCodes.Call, to_string);
712 ig.Emit (OpCodes.Call, writeline);
714 ig.Emit (OpCodes.Call, write);
719 void emit_late_call (EmitContext ec)
721 ILGenerator ig = ec.ig;
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);
729 LocalBuilder lb = ig.DeclareLocal (lb_type);
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"));
739 member_exp.Emit (ec);
740 setup_late_call_args (ec);
741 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
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"));
751 internal void get_global_scope_or_this (ILGenerator ig)
754 ig.Emit (OpCodes.Ldarg_1);
756 ig.Emit (OpCodes.Ldarg_0);
757 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
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);
765 //FIXME: when is each of them (GetGlobalScope | GetDefaultThisObject?
767 // ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetGlobalScope"));
768 ig.Emit (OpCodes.Callvirt, iact_obj.GetMethod ("GetDefaultThisObject"));
771 void init_late_binding (EmitContext ec, LocalBuilder local)
773 ILGenerator ig = ec.ig;
775 ig.Emit (OpCodes.Ldloc, local);
776 ig.Emit (OpCodes.Dup);
778 AST left = (member_exp as Binary).left;
781 ig.Emit (OpCodes.Ldarg_0);
782 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
783 ig.Emit (OpCodes.Call , typeof (Convert).GetMethod ("ToObject"));
785 Type lb_type = typeof (LateBinding);
787 ig.Emit (OpCodes.Stfld, lb_type.GetField ("obj"));
790 void setup_late_call_args (EmitContext ec)
792 ILGenerator ig = ec.ig;
795 ig.Emit (OpCodes.Ldc_I4, n);
796 ig.Emit (OpCodes.Newarr, typeof (object));
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);
805 ig.Emit (OpCodes.Ldc_I4_0);
806 ig.Emit (OpCodes.Ldc_I4_0);
809 ig.Emit (OpCodes.Ldarg_1);
811 ig.Emit (OpCodes.Ldarg_0);
812 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
816 void emit_func_call (MethodBuilder mb, EmitContext ec)
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"));
825 CodeGenerator.load_engine (InFunction, ig);
829 ig.Emit (OpCodes.Call, mb);
831 if (!return_void (mb) && no_effect)
832 ig.Emit (OpCodes.Pop);
835 bool return_void (MethodBuilder mb)
837 return mb.ReturnType == typeof (void);
840 void EmitBuiltInArgs (EmitContext ec)
842 if (member_exp.ToString () == "Date")
845 ILGenerator ig = ec.ig;
848 if (n >= 1 && (member_exp.ToString () == "String" || member_exp.ToString () == "Boolean" || member_exp.ToString () == "Number")) {
849 args.get_element (0).Emit (ec);
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);
863 void EmitInvoke (EmitContext ec)
865 ILGenerator ig = ec.ig;
866 string name = member_exp.ToString ();
868 bool boolean = false;
873 type = typeof (ObjectConstructor);
876 type = typeof (FunctionConstructor);
879 type = typeof (ArrayConstructor);
882 type = typeof (StringConstructor);
885 type = typeof (BooleanConstructor);
889 type = typeof (NumberConstructor);
893 type = typeof (DateConstructor);
896 type = typeof (RegExpConstructor);
901 case "ReferenceError":
905 type = typeof (ErrorConstructor);
908 ig.Emit (OpCodes.Call, type.GetMethod ("Invoke"));
910 ig.Emit (OpCodes.Box, typeof (Boolean));
912 ig.Emit (OpCodes.Box, typeof (Double));
915 bool IsConstructorProperty (object binding)
917 if (!(binding is BuiltIn))
920 string name = (binding as BuiltIn).Name;
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");
925 bool IsGlobalObjectMethod (object binding)
927 if (binding == null || binding.GetType () != typeof (BuiltIn))
930 BuiltIn bind = binding as BuiltIn;
938 case "decodeURIComponent":
940 case "encodeURIComponent":
949 bool IsEval (object binding)
951 if (binding == null || binding.GetType () != typeof (BuiltIn))
953 BuiltIn bind = (BuiltIn) binding;
954 return bind.Name == "eval";
957 internal void set_local_vars (ILGenerator ig)
960 Type stack_frame = typeof (StackFrame);
962 CodeGenerator.load_engine (InFunction, ig);
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"));
968 object [] locals = TypeManager.CurrentLocals;
969 n = locals != null ? locals.Length : 0;
972 for (int i = 0; i < n; 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);
981 ig.Emit (OpCodes.Pop);
985 interface IAccesible {
986 bool ResolveFieldAccess (AST parent);
989 internal class Identifier : Exp, IAssignable, IAccesible {
991 internal Symbol name;
992 internal AST binding;
993 internal bool assign;
996 int lexical_difference;
997 const int MINIMUM_DIFFERENCE = 1;
999 LocalBuilder local_builder;
1001 internal Identifier (AST parent, string id)
1003 this.parent = parent;
1004 this.name = Symbol.CreateSymbol (id);
1008 get { return lexical_difference >= MINIMUM_DIFFERENCE && no_field; }
1011 public override string ToString ()
1016 internal override bool Resolve (IdentificationTable context)
1018 bool contained = context.Contains (this.name);
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);
1033 throw new Exception ("variable not found: " + name);
1037 internal override bool Resolve (IdentificationTable context, bool no_effect)
1039 this.no_effect = no_effect;
1040 return Resolve (context);
1043 public bool ResolveAssign (IdentificationTable context, AST right_side)
1046 this.no_effect = false;
1047 this.right_side = right_side;
1048 if (name.Value != String.Empty)
1049 return Resolve (context);
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.
1060 public bool ResolveFieldAccess (AST parent)
1062 if (parent is Identifier) {
1063 Identifier p = parent as Identifier;
1064 return is_static_property (p.name.Value, name.Value);
1067 // Return false so late binding will take place
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
1077 bool is_static_property (string obj_name, string prop_name)
1079 bool native_obj = SemanticAnalyser.is_js_object (obj_name);
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);
1092 internal override void Emit (EmitContext ec)
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;
1100 ig.Emit (OpCodes.Starg, (short) f.pos);
1102 ig.Emit (OpCodes.Ldarg_S, f.pos);
1103 } else if (binding is VariableDeclaration || binding is Try || binding is Catch) {
1105 CodeGenerator.emit_parents (InFunction, lexical_difference, ig);
1106 store_stack_frame_into_locals (ec.ig);
1107 if (this.local_builder != null)
1109 ig.Emit (OpCodes.Stloc, local_builder);
1111 ig.Emit (OpCodes.Ldloc, local_builder);
1113 FieldInfo field_info = extract_field_info (binding);
1114 LocalBuilder local_builder = extract_local_builder (binding);
1116 if (field_info != null) {
1118 ig.Emit (OpCodes.Stsfld, field_info);
1120 ig.Emit (OpCodes.Ldsfld, field_info);
1121 } else if (local_builder != null) {
1123 ig.Emit (OpCodes.Stloc, local_builder);
1125 ig.Emit (OpCodes.Ldloc, local_builder);
1128 } else if (binding is BuiltIn)
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);
1135 Console.WriteLine ("Identifier.Emit, binding.GetType = {0}", binding.GetType ());
1137 if (!assign && no_effect)
1138 ig.Emit (OpCodes.Pop);
1141 internal void EmitStore (EmitContext ec)
1143 ILGenerator ig = ec.ig;
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);
1152 ig.Emit (OpCodes.Stloc, local);
1154 ig.Emit (OpCodes.Stsfld, fb);
1158 internal void EmitLoad (EmitContext ec)
1160 ILGenerator ig = ec.ig;
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);
1169 ig.Emit (OpCodes.Ldloc, local);
1171 ig.Emit (OpCodes.Ldsfld, fb);
1175 void load_script_func (EmitContext ec, FunctionDeclaration binding)
1177 object bind = TypeManager.Get (binding.func_obj.name);
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);
1186 FieldInfo method = type.GetField (binding.func_obj.name);
1187 ec.ig.Emit (OpCodes.Ldsfld, method);
1189 } else if (bind is LocalBuilder)
1190 ec.ig.Emit (OpCodes.Ldloc, (LocalBuilder) bind);
1191 else throw new Exception ("load_script_func");
1195 internal FieldInfo extract_field_info (AST a)
1199 if (a is VariableDeclaration)
1200 r = ((VariableDeclaration) a).field_info;
1202 r = ((Try) a).field_info;
1203 else if (a is Catch)
1204 r = ((Catch) a).field_info;
1208 internal LocalBuilder extract_local_builder (AST a)
1210 LocalBuilder r = null;
1211 if (a is VariableDeclaration)
1212 r = ((VariableDeclaration) a).local_builder;
1214 r = ((Try) a).local_builder;
1215 else if (a is Catch)
1216 r = ((Catch) a).local_builder;
1221 // FIXME: Only must store the extern variables which are used.
1223 internal void store_stack_frame_into_locals (ILGenerator ig)
1225 ig.Emit (OpCodes.Dup);
1227 Type stack_frame = typeof (StackFrame);
1228 ig.Emit (OpCodes.Castclass, stack_frame);
1229 ig.Emit (OpCodes.Ldfld, stack_frame.GetField ("localVars"));
1231 DictionaryEntry [] locals = TypeManager.LocalsAtDepth (((VariableDeclaration) binding).lexical_depth);
1234 LocalBuilder local = null;
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);
1247 ig.Emit (OpCodes.Pop);
1250 // FIXME: what does it determine this?
1252 ig.Emit (OpCodes.Call, typeof (ScriptObject).GetMethod ("GetParent"));
1253 ig.Emit (OpCodes.Pop);
1257 internal class Args : AST {
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;
1269 elems = new ArrayList ();
1272 internal void Add (AST e)
1277 internal int DesiredNumOfArgs {
1280 num_of_args = value;
1284 internal bool IsPrint {
1285 set { is_print = value; }
1288 internal void has_var_args (MethodInfo minfo)
1290 JSFunctionAttribute [] custom_attrs = (JSFunctionAttribute [])
1291 minfo.GetCustomAttributes (typeof (JSFunctionAttribute), true);
1293 foreach (JSFunctionAttribute attr in custom_attrs)
1294 if (attr.GetAttributeValue () == JSFunctionAttributeEnum.HasVarArgs) {
1301 internal override bool Resolve (IdentificationTable context)
1303 int n = elems.Count;
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);
1316 internal AST get_element (int i)
1318 if (i >= 0 && i < elems.Count)
1319 return (AST) elems [i];
1325 get { return elems.Count; }
1328 internal override void Emit (EmitContext ec)
1331 ILGenerator ig = ec.ig;
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);
1345 if (num_of_args < 0)
1348 for (int j = 0; j < n && j < num_of_args; j++) {
1349 ast = get_element (j);
1351 if (!late_bind && params_info != null)
1352 force_strong_type (ig, ast, params_info [j]);
1356 missing = func.NumOfArgs - n;
1357 else if (params_info != null)
1358 missing = params_info.Length - n;
1360 for (int k = 0; k < missing; k++)
1361 ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
1365 internal void force_strong_type (ILGenerator ig, AST ast, ParameterInfo pinfo)
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))
1373 else throw new NotImplementedException ();
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))
1383 else throw new NotImplementedException ();
1388 internal class Expression : Exp {
1390 internal ArrayList exprs;
1393 get { return exprs.Count; }
1396 internal Expression (AST parent)
1398 this.parent = parent;
1399 exprs = new ArrayList ();
1402 internal void Add (AST a)
1407 public override string ToString ()
1409 int size = exprs.Count;
1413 StringBuilder sb = new StringBuilder ();
1415 for (i = 0; i < size; i++)
1416 sb.Append (exprs [i].ToString ());
1419 return sb.ToString ();
1421 } else return String.Empty;
1424 internal override bool Resolve (IdentificationTable context)
1430 n = exprs.Count - 1;
1432 for (i = 0; i < n; i++) {
1435 r &= ((Exp) e).Resolve (context, true);
1437 r &= ((AST) e).Resolve (context);
1442 r &= ((Assign) e).Resolve (context);
1444 r &= ((Exp) e).Resolve (context, no_effect);
1446 ((AST) e).Resolve (context);
1451 internal override bool Resolve (IdentificationTable context, bool no_effect)
1453 this.no_effect = no_effect;
1454 return Resolve (context);
1457 internal override void Emit (EmitContext ec)
1459 int i, n = exprs.Count;
1462 for (i = 0; i < n; i++) {
1463 exp = (AST) exprs [i];
1469 internal class Assign : BinaryOp {
1471 internal bool is_embedded;
1473 internal Assign (AST parent, AST left, AST right, JSToken op, bool is_embedded)
1474 : base (left, right, op)
1476 this.parent = parent;
1477 this.is_embedded = is_embedded;
1481 // after calling Resolve, left contains all the
1482 // information about the assignment
1484 internal override bool Resolve (IdentificationTable context)
1488 if (left is IAssignable)
1489 r = ((IAssignable) left).ResolveAssign (context, right);
1491 throw new Exception ("(" + line_number + ",0): error JS5008: Illegal assignment");
1493 r &=((Exp) right).Resolve (context, false);
1495 r &= right.Resolve (context);
1499 internal override bool Resolve (IdentificationTable context, bool no_effect)
1504 internal override void Emit (EmitContext ec)
1506 if (op == JSToken.Assign) {
1508 Console.WriteLine ("embedded assignments not supported yet");
1509 Environment.Exit (-1);
1513 ILGenerator ig = ec.ig;
1515 LocalBuilder local = null;
1516 LocalBuilder aux = ig.DeclareLocal (typeof (object));
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);
1531 ig.Emit (OpCodes.Call, type.GetMethod ("EvaluatePlus"));
1532 if (left is Identifier)
1533 ((Identifier) left).EmitStore (ec);
1535 case JSToken.MinusAssign:
1536 case JSToken.MultiplyAssign:
1537 case JSToken.DivideAssign:
1538 case JSToken.ModuloAssign:
1539 type = typeof (NumericBinary);
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);
1550 local = ig.DeclareLocal (type);
1551 load_parameter (ig, op);
1553 ig.Emit (OpCodes.Newobj, type.GetConstructor (new Type [] {typeof (int)}));
1554 ig.Emit (OpCodes.Stloc, local);
1556 if (left is Identifier)
1557 ((Identifier) left).EmitLoad (ec);
1559 ig.Emit (OpCodes.Stloc, aux);
1560 ig.Emit (OpCodes.Ldloc, local);
1561 ig.Emit (OpCodes.Ldloc, aux);
1566 emit_evaluation (op, type, ig);
1568 if (left is Identifier)
1569 ((Identifier) left).EmitStore (ec);
1573 void load_parameter (ILGenerator ig, JSToken op)
1576 case JSToken.MinusAssign:
1577 ig.Emit (OpCodes.Ldc_I4_S, 47);
1579 case JSToken.BitwiseOrAssign:
1580 ig.Emit (OpCodes.Ldc_I4_S, 50);
1582 case JSToken.BitwiseXorAssign:
1583 ig.Emit (OpCodes.Ldc_I4_S, 51);
1585 case JSToken.BitwiseAndAssign:
1586 ig.Emit (OpCodes.Ldc_I4_S, 52);
1588 case JSToken.LeftShiftAssign:
1589 ig.Emit (OpCodes.Ldc_I4_S, 61);
1591 case JSToken.RightShiftAssign:
1592 ig.Emit (OpCodes.Ldc_I4_S, 62);
1594 case JSToken.UnsignedRightShiftAssign:
1595 ig.Emit (OpCodes.Ldc_I4_S, 63);
1597 case JSToken.MultiplyAssign:
1598 ig.Emit (OpCodes.Ldc_I4_S, 64);
1600 case JSToken.DivideAssign:
1601 ig.Emit (OpCodes.Ldc_I4_S, 65);
1603 case JSToken.ModuloAssign:
1604 ig.Emit (OpCodes.Ldc_I4_S, 66);
1607 throw new NotImplementedException ();
1611 void emit_evaluation (JSToken op, Type type, ILGenerator ig)
1614 case JSToken.MinusAssign:
1615 case JSToken.MultiplyAssign:
1616 case JSToken.DivideAssign:
1617 case JSToken.ModuloAssign:
1618 ig.Emit (OpCodes.Call, type.GetMethod ("EvaluateNumericBinary"));
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"));
1629 throw new NotImplementedException ();
1634 public override string ToString ()
1636 string l = left.ToString ();
1637 string r = right.ToString ();
1638 return l + " " + op.ToString () + " " + r;
1642 internal class New : AST, ICallable {
1646 bool late_bind = false;
1648 internal New (AST parent, AST exp)
1650 this.parent = parent;
1652 this.args = new Args ();
1655 public void AddArg (AST arg)
1660 internal override bool Resolve (IdentificationTable context)
1664 if (exp != null && exp.GetType () == typeof (Identifier)) {
1665 Identifier id = (Identifier) exp;
1666 late_bind = !SemanticAnalyser.is_js_object (id.name.Value);
1668 exp.Resolve (context);
1671 r &= args.Resolve (context);
1675 internal override void Emit (EmitContext ec)
1677 ILGenerator ig = ec.ig;
1681 CodeGenerator.emit_get_default_this (ec.ig);
1684 ig.Emit (OpCodes.Ldc_I4, args.Size);
1685 ig.Emit (OpCodes.Newarr, typeof (object));
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);
1694 ig.Emit (OpCodes.Ldc_I4_1);
1695 ig.Emit (OpCodes.Ldc_I4_0);
1697 ig.Emit (OpCodes.Ldarg_0);
1698 ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
1700 ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
1706 emit_create_instance (ec);
1711 void emit_create_instance (EmitContext ec)
1713 if (exp is Identifier) {
1714 ILGenerator ig = ec.ig;
1716 switch ((exp as Identifier).name.Value) {
1718 type = typeof (ArrayConstructor);
1721 type = typeof (DateConstructor);
1724 type = typeof (NumberConstructor);
1727 type = typeof (ObjectConstructor);
1730 type = typeof (RegExpConstructor);
1733 type = typeof (StringConstructor);
1736 type = typeof (BooleanConstructor);
1739 type = typeof (FunctionConstructor);
1743 ig.Emit (OpCodes.Call, type.GetMethod ("CreateInstance"));
1747 void emit_args (EmitContext ec)
1749 ILGenerator ig = ec.ig;
1751 ig.Emit (OpCodes.Ldc_I4, args.Size);
1752 ig.Emit (OpCodes.Newarr, typeof (object));
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);
1763 internal interface IAssignable {
1764 bool ResolveAssign (IdentificationTable context, AST right_side);
1767 internal class BuiltIn : AST {
1769 bool allowed_as_ctr;
1770 bool allowed_as_func;
1772 internal BuiltIn (string name, bool allowed_as_ctr, bool allowed_as_func)
1775 this.allowed_as_ctr = allowed_as_ctr;
1776 this.allowed_as_func = allowed_as_func;
1779 internal override bool Resolve (IdentificationTable context)
1784 internal string Name {
1785 get { return name; }
1788 internal bool IsConstructor {
1789 get { return allowed_as_ctr; }
1792 internal bool IsFunction {
1793 get { return allowed_as_func; }
1796 internal bool IsPrint {
1797 get { return String.Equals (name, "print"); }
1799 internal int NumOfArgs {
1801 if (name == "print")
1804 Type global_object = typeof (GlobalObject);
1805 MethodInfo method = global_object.GetMethod (name);
1806 return method.GetParameters ().Length;
1810 internal ParameterInfo [] Parameters {
1812 Type global_obj = typeof (GlobalObject);
1813 return global_obj.GetMethod (name).GetParameters ();
1817 internal override void Emit (EmitContext ec)
1819 ILGenerator ig = ec.ig;
1820 Type go = typeof (GlobalObject);
1822 /* value properties of the Global Object */
1824 ig.Emit (OpCodes.Ldc_R8, Double.NaN);
1825 ig.Emit (OpCodes.Box, typeof (Double));
1828 ig.Emit (OpCodes.Ldc_R8, Double.PositiveInfinity);
1829 // FIXME: research when not to generate the Boxing
1830 ig.Emit (OpCodes.Box, typeof (Double));
1833 ig.Emit (OpCodes.Ldnull);
1836 ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
1839 /* function properties of the Global Object */
1841 Type [] method_args = null;
1843 method_args = new Type [] {typeof (object), typeof (VsaEngine)};
1845 method_args = new Type [] {typeof (object), typeof (object), typeof (VsaEngine)};
1847 ig.Emit (OpCodes.Call, typeof (Eval).GetMethod ("JScriptEvaluate", method_args));
1850 ig.Emit (OpCodes.Call, go.GetMethod ("parseInt"));
1851 ig.Emit (OpCodes.Box, typeof (Double));
1854 ig.Emit (OpCodes.Call, go.GetMethod ("parseFloat"));
1855 ig.Emit (OpCodes.Box, typeof (Double));
1858 ig.Emit (OpCodes.Call, go.GetMethod ("isNaN"));
1859 ig.Emit (OpCodes.Box, typeof (bool));
1862 ig.Emit (OpCodes.Call, go.GetMethod ("isFinite"));
1863 ig.Emit (OpCodes.Box, typeof (bool));
1866 ig.Emit (OpCodes.Call, go.GetMethod ("decodeURI"));
1868 case "decodeURIComponent":
1869 ig.Emit (OpCodes.Call, go.GetMethod ("decodeURIComponent"));
1872 ig.Emit (OpCodes.Call, go.GetMethod ("encodeURI"));
1874 case "encodeURIComponent":
1875 ig.Emit (OpCodes.Call, go.GetMethod ("encodeURIComponent"));
1878 ig.Emit (OpCodes.Call, go.GetMethod ("escape"));
1881 ig.Emit (OpCodes.Call, go.GetMethod ("unescape"));
1883 /* constructor properties of the Global object */
1885 ig.Emit (OpCodes.Call, go.GetProperty ("Object").GetGetMethod ());
1888 ig.Emit (OpCodes.Call, go.GetProperty ("Function").GetGetMethod ());
1891 ig.Emit (OpCodes.Call, go.GetProperty ("Array").GetGetMethod ());
1894 ig.Emit (OpCodes.Call, go.GetProperty ("String").GetGetMethod ());
1897 ig.Emit (OpCodes.Call, go.GetProperty ("Boolean").GetGetMethod ());
1900 ig.Emit (OpCodes.Call, go.GetProperty ("Number").GetGetMethod ());
1903 ig.Emit (OpCodes.Call, go.GetProperty ("Date").GetGetMethod ());
1906 ig.Emit (OpCodes.Call, go.GetProperty ("RegExp").GetGetMethod ());
1909 ig.Emit (OpCodes.Call, go.GetProperty ("Error").GetGetMethod ());
1912 ig.Emit (OpCodes.Call, go.GetProperty ("EvalError").GetGetMethod ());
1915 ig.Emit (OpCodes.Call, go.GetProperty ("RangeError").GetGetMethod ());
1918 case "ReferenceError":
1919 ig.Emit (OpCodes.Call, go.GetProperty ("ReferenceError").GetGetMethod ());
1923 ig.Emit (OpCodes.Call, go.GetProperty ("SyntaxError").GetGetMethod ());
1927 ig.Emit (OpCodes.Call, go.GetProperty ("TypeError").GetGetMethod ());
1931 ig.Emit (OpCodes.Call, go.GetProperty ("URIError").GetGetMethod ());
1933 /* other properties of the Global object */
1935 ig.Emit (OpCodes.Call, go.GetProperty ("Math").GetGetMethod ());
1938 throw new Exception ("This is BuiltIn " + name);