2005-08-19 Cesar Lopez Nataren <cnataren@novell.com>
authorCésar Natarén <cesar@mono-cvs.ximian.com>
Sat, 20 Aug 2005 00:04:20 +0000 (00:04 -0000)
committerCésar Natarén <cesar@mono-cvs.ximian.com>
Sat, 20 Aug 2005 00:04:20 +0000 (00:04 -0000)
* SemanticAnalyser.cs: Added ArrayLiteral, StringLiteral,
BooleanConstant, ByteConstant, ShortConstant, IntConstant,
LongConstant, FloatConstant, DoubleConstant to the
prototypes. Added methods IsNumericConstant, NeedsToBoolean.

* Parser.cs: Added methods InRangeOf, HasNoDecimals which help on
building the property AST node depending on how big and precise
the number is.

* CodeGenerator.cs: (emit_get_default_this) Receives an extra
argument which indicates if we are inside a method, use
load_engine. Added method EmitBox, EmitConv, GetBoxType

* Literal.cs: Add abstract class Constant. Renamed BooleanLiteral
to BooleanConstant. Delete NumericLiteral, handle the number code
generation properly categorizing in ByteConstant, ShortConstant,
IntConstant, LongConstant, FloatConstant and DoubleConstant which
inherit from NumericConstant. (ObjectLiteral) Handle boxing issue.

* Statement.cs, Relational.cs: (If) Handle boxing issue.

* VariableDeclaration.cs: Handle the boxing issue when
we have initializers.

* Equality.cs, StrictEquality.cs: Handle the boxing issue before invoking
EvaluateEquality, JScriptStrictEquals.

* ArrayLiteral.cs: Implement ICanLookupPrototype so we can
optimize access to methods through the prototype and not
generating IL code that uses late binding. Handle the boxing
issue.

* expression.cs: (Unary.Emit) Nuke emit_unary_op. Take care of
properly boxing the operands of methods that evaluate the unary
operators at runtime. Fix the minus logic for IL generation, add
method emit_non_numeric_unary. Optimize the numeric
cases. (Binary) Add LateBinding internal
property. (Binary.emit_late_get_or_set, emit_array_access,
Conditional.Emit, Call.Emit, emit_print_stm, emit_late_call,
setup_late_call_args, EmitBuiltInArgs, Identifier.Emit, Args.Emit,
Expression.Emit, Assign.Emit, New.Emit)
Take care of properly boxing the built in .NET
values. (force_strong_type) Change the type from ParameterInfo to
object, take care specifically. (Expression) Add Last internal
property. In general, the point is that value types like integers,
booleans, etc... do not have to generate a box operation, the user
of the arg must handle that.

svn path=/trunk/mcs/; revision=48584

13 files changed:
mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayLiteral.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog
mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Equality.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/NumericUnary.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Parser.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Relational.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Statement.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/VariableDeclaration.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs

index 1391eefc48dbaa9ad29db13e10c4302f0448833f..904f7db9126569e7cea892bbe88c2a5f168448a6 100644 (file)
@@ -35,7 +35,7 @@ using System.Reflection.Emit;
 
 namespace Microsoft.JScript {
 
-       public class ArrayLiteral : AST {
+       public class ArrayLiteral : AST, ICanLookupPrototype {
 
                internal ASTList elems;
                int skip_count;
@@ -62,6 +62,17 @@ namespace Microsoft.JScript {
                        return r;
                }
 
+               bool ICanLookupPrototype.ResolveFieldAccess (AST ast)
+               {
+                       if (ast is Identifier) {
+                               Identifier name = (Identifier) ast;
+                               Type prototype = typeof (StringPrototype);
+                               MemberInfo [] members = prototype.GetMember (name.name.Value);
+                               return members.Length > 0;
+                       } else
+                               return false;
+               }
+
                internal override void Emit (EmitContext ec)
                {
                        int i = 0;
@@ -75,9 +86,10 @@ namespace Microsoft.JScript {
                        foreach (AST ast in exps) {
                                ig.Emit (OpCodes.Dup);
                                ig.Emit (OpCodes.Ldc_I4, i);
-                               if (ast != null)
+                               if (ast != null) {
                                        ast.Emit (ec);
-                               else 
+                                       CodeGenerator.EmitBox (ig, ast);
+                               } else 
                                        ig.Emit (OpCodes.Ldsfld, missing);
                                ig.Emit (OpCodes.Stelem_Ref);
                                i++;
index 345714b42790a699affad19d26edb7b5657b869a..3afcc2aff90dd290e515706b5fdbca469258a9b7 100644 (file)
@@ -1,3 +1,53 @@
+2005-08-19  Cesar Lopez Nataren  <cnataren@novell.com>
+
+       * SemanticAnalyser.cs: Added ArrayLiteral, StringLiteral,
+       BooleanConstant, ByteConstant, ShortConstant, IntConstant,
+       LongConstant, FloatConstant, DoubleConstant to the
+       prototypes. Added methods IsNumericConstant, NeedsToBoolean.
+
+       * Parser.cs: Added methods InRangeOf, HasNoDecimals which help on
+       building the property AST node depending on how big and precise
+       the number is.
+
+       * CodeGenerator.cs: (emit_get_default_this) Receives an extra
+       argument which indicates if we are inside a method, use
+       load_engine. Added method EmitBox, EmitConv, GetBoxType
+
+       * Literal.cs: Add abstract class Constant. Renamed BooleanLiteral
+       to BooleanConstant. Delete NumericLiteral, handle the number code
+       generation properly categorizing in ByteConstant, ShortConstant,
+       IntConstant, LongConstant, FloatConstant and DoubleConstant which
+       inherit from NumericConstant. (ObjectLiteral) Handle boxing issue.
+
+       * Statement.cs, Relational.cs: (If) Handle boxing issue.
+
+       * VariableDeclaration.cs: Handle the boxing issue when
+       we have initializers.
+
+       * Equality.cs, StrictEquality.cs: Handle the boxing issue before invoking
+       EvaluateEquality, JScriptStrictEquals.
+
+       * ArrayLiteral.cs: Implement ICanLookupPrototype so we can
+       optimize access to methods through the prototype and not
+       generating IL code that uses late binding. Handle the boxing
+       issue.
+
+       * expression.cs: (Unary.Emit) Nuke emit_unary_op. Take care of
+       properly boxing the operands of methods that evaluate the unary
+       operators at runtime. Fix the minus logic for IL generation, add
+       method emit_non_numeric_unary. Optimize the numeric
+       cases. (Binary) Add LateBinding internal
+       property. (Binary.emit_late_get_or_set, emit_array_access,
+       Conditional.Emit, Call.Emit, emit_print_stm, emit_late_call,
+       setup_late_call_args, EmitBuiltInArgs, Identifier.Emit, Args.Emit,
+       Expression.Emit, Assign.Emit, New.Emit)
+       Take care of properly boxing the built in .NET
+       values. (force_strong_type) Change the type from ParameterInfo to
+       object, take care specifically. (Expression) Add Last internal
+       property. In general, the point is that value types like integers,
+       booleans, etc... do not have to generate a box operation, the user
+       of the arg must handle that.
+
 2005-08-17  Florian Gross  <flgr@ccan.de>
 
        * ScriptObject.cs: Added settable _proto for __proto__. This isn't
index 391a5b76a9a60aad086181afd8f3a041e72abb16..b34696dd9513cae0a9c2b7aabc0b5fe6d1d91a50 100644 (file)
@@ -426,7 +426,7 @@ namespace Microsoft.JScript {
                                        ff_emit_relational (ec, last_exp, lbl);
                                else if (last_exp is Binary)
                                        ff_binary_recursion (ec, last_exp, lbl);
-                               else if (last_exp is Identifier || last_exp is BooleanLiteral)
+                               else if (last_exp is Identifier || last_exp is BooleanConstant)
                                        emit_default_case (ec, last_exp, OpCodes.Brtrue, lbl);
                                else if (last_exp is Equality) 
                                        ff_emit_equality_cond (ec, last_exp, lbl);
@@ -458,7 +458,7 @@ namespace Microsoft.JScript {
                                Expression exp = ast as Expression;
                                int n = exp.exprs.Count - 1;
                                AST tmp = (AST) exp.exprs [n];
-                               if (tmp is Equality || tmp is Relational || tmp is BooleanLiteral)
+                               if (tmp is Equality || tmp is Relational || tmp is BooleanConstant)
                                        return false;
                                else
                                        return true;
@@ -484,10 +484,9 @@ namespace Microsoft.JScript {
                        }
                }
                
-               internal static void emit_get_default_this (ILGenerator ig) 
+               internal static void emit_get_default_this (ILGenerator ig, bool inFunction
                {
-                       ig.Emit (OpCodes.Ldarg_0);
-                       ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+                       CodeGenerator.load_engine (inFunction, ig);
                        ig.Emit (OpCodes.Call, typeof (VsaEngine).GetMethod ("ScriptObjectStackTop"));
                        Type iact_obj = typeof (IActivationObject);
                        ig.Emit (OpCodes.Castclass, iact_obj);
@@ -562,6 +561,71 @@ namespace Microsoft.JScript {
                                ig.Emit (OpCodes.Call, typeof (ScriptObject).GetMethod ("GetParent"));
                }
 
+               internal static void EmitBox (ILGenerator ig, object obj)
+               {
+                       if (obj == null) 
+                               return;
+
+                       Type box_type = GetBoxType (obj);
+
+                       if (box_type == null)
+                               ;
+                       else
+                               ig.Emit (OpCodes.Box, box_type);
+               }
+
+               internal static void EmitConv (ILGenerator ig, Type type)
+               {
+                       TypeCode tc = Type.GetTypeCode (type);
+                       
+                       switch (tc) {
+                       case TypeCode.Double:
+                               ig.Emit (OpCodes.Conv_R8);
+                               break;
+
+                       default:
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               private static Type GetBoxType (object obj)
+               {
+                       if (obj is ByteConstant || obj is ShortConstant || obj is IntConstant)
+                               return typeof (int);
+                       else if (obj is LongConstant)
+                               return typeof (long);
+                       else if (obj is FloatConstant || obj is DoubleConstant)
+                               return typeof (double);
+                       else if (obj is BooleanConstant || obj is StrictEquality || obj is Equality)
+                               return typeof (bool);
+                       else if (obj is Unary) {
+                               Unary unary = (Unary) obj;
+                               JSToken oper = unary.oper;
+                               AST operand = unary.operand;
+                               
+                               if (oper == JSToken.Minus || oper == JSToken.Plus ||
+                                   oper == JSToken.Increment || oper == JSToken.Decrement ||
+                                   oper == JSToken.BitwiseNot)
+                                       return GetBoxType (operand);
+                               else if (oper == JSToken.LogicalNot)
+                                       return typeof (bool);
+                       } else if (obj is Identifier) {
+                               Identifier id = (Identifier) obj;
+                               string name = id.name.Value;
+                               if  (name == "NaN" || name == "Infinity")
+                                       return typeof (double);
+                       } else if (obj is Binary) {
+                               Binary bin = obj as Binary;
+                               if (bin.AccessField && !bin.LateBinding) {
+                                       MemberInfo binding = bin.Binding;
+                                       MemberTypes member_type = binding.MemberType;
+                                       if (member_type == MemberTypes.Property)
+                                               return ((PropertyInfo) binding).PropertyType;
+                               }
+                       }
+                       return null;
+               }
+
                internal static void emit_default_value (ILGenerator ig, ParameterInfo param)
                {
                        Type param_type = param.ParameterType;
@@ -570,10 +634,8 @@ namespace Microsoft.JScript {
                                ig.Emit (OpCodes.Ldc_R8, GlobalObject.NaN);
                        else if (param_type == typeof (object))
                                ig.Emit (OpCodes.Ldsfld, typeof (Missing).GetField ("Value"));
-                       else {
-                               Console.WriteLine ("param_type = " + param_type);
+                       else
                                throw new NotImplementedException ();
-                       }
                }
        }
 }
index d8d5b84de6f6afda38d74a11b924c33e60f3d46b..33bedcdd7a6753bc987017605110d12222994de4 100644 (file)
@@ -176,10 +176,14 @@ namespace Microsoft.JScript {
                                ig.Emit (OpCodes.Ldloc, local_builder);
                        }
 
-                       if (left != null)
+                       if (left != null) {
                                left.Emit (ec);
-                       if (right != null)
+                               CodeGenerator.EmitBox (ig, left);
+                       }
+                       if (right != null) {
                                right.Emit (ec);
+                               CodeGenerator.EmitBox (ig, right);
+                       }
 
                        if (op == JSToken.Equal || op == JSToken.NotEqual) {
                                ig.Emit (OpCodes.Call, typeof (Equality).GetMethod ("EvaluateEquality"));
index 0fce2a00623dd386902d7e5ee3863efcea1ab7ff..bbfdbb35675aa2d691caa58273c21b38836815ba 100644 (file)
@@ -54,28 +54,36 @@ namespace Microsoft.JScript {
                        if (InFunction)
                                ec.ig.Emit (OpCodes.Ldarg_0);
                        else
-                               CodeGenerator.emit_get_default_this (ec.ig);
+                               CodeGenerator.emit_get_default_this (ec.ig, InFunction);
                }
        }
 
-       internal class BooleanLiteral : Exp {
+       internal abstract class Constant : Exp {
 
-               internal bool val;
-
-               internal BooleanLiteral (AST parent, bool val, Location location)
+               internal Constant (AST parent, Location location)
                        : base (parent, location)
                {
-                       this.val = val;
                }
 
-               public override string ToString ()
+               internal override bool Resolve (IdentificationTable context)
                {
-                       return val.ToString ();
+                       return true;
                }
 
-               internal override bool Resolve (IdentificationTable context)
+               internal override bool Resolve (IdentificationTable context, bool no_effect)
                {
-                       return true;
+                       this.no_effect = no_effect;
+                       return Resolve (context);
+               }
+       }
+
+       internal class BooleanConstant : Constant, ICanLookupPrototype {
+               internal bool Value;
+
+               internal BooleanConstant (AST parent, bool val, Location location)
+                       : base (parent, location)
+               {
+                       this.Value = val;
                }
 
                internal override bool Resolve (IdentificationTable context, bool no_effect)
@@ -88,57 +96,196 @@ namespace Microsoft.JScript {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (val)
+                       if (Value)
                                ig.Emit (OpCodes.Ldc_I4_1);
                        else
                                ig.Emit (OpCodes.Ldc_I4_0);
-
-                       ig.Emit (OpCodes.Box, typeof (System.Boolean));
-
+                       
                        if (no_effect)
                                ig.Emit (OpCodes.Pop);
                }
+
+               bool ICanLookupPrototype.ResolveFieldAccess (AST ast)
+               {
+                       if (ast is Identifier) {
+                               Identifier name = (Identifier) ast;
+                               Type prototype = typeof (NumberPrototype);
+                               MemberInfo [] members = prototype.GetMember (name.name.Value);
+                               return members.Length > 0;
+                       } else
+                               return false;
+               }
        }
 
-       internal class NumericLiteral : Exp {
+       internal abstract class NumericConstant : Constant, ICanLookupPrototype {
+               
+               internal NumericConstant (AST parent, Location location)
+                       : base (parent, location)
+               {
+               }
 
-               double val;
+               bool ICanLookupPrototype.ResolveFieldAccess (AST ast)
+               {
+                       if (ast is Identifier) {
+                               Identifier name = (Identifier) ast;
+                               Type prototype = typeof (NumberPrototype);
+                               MemberInfo [] members = prototype.GetMember (name.name.Value);
+                               return members.Length > 0;
+                       } else
+                               return false;
+               }
+       }
 
-               internal NumericLiteral (AST parent, double val, Location location)
+       internal class ByteConstant : NumericConstant {
+               byte Value;
+                       
+               internal ByteConstant (AST parent, byte v, Location location)
                        : base (parent, location)
                {
-                       this.val = val;
+                       Value = v;
                }
 
-               public override string ToString ()
+               internal override void Emit (EmitContext ec)
                {
-                       return val.ToString ();
+                       IntConstant.EmitInt (ec.ig, Value);
                }
+       }
 
-               internal override bool Resolve (IdentificationTable context)
+       internal class ShortConstant : NumericConstant {
+               short Value;
+
+               internal ShortConstant (AST parent, short v, Location location)
+                       : base (parent, location)
                {
-                       return true;
+                       Value = v;
                }
 
-               internal override bool Resolve (IdentificationTable context, bool no_effect)
-               {                       
-                       this.no_effect = no_effect;
-                       return Resolve (context);
+               internal override void Emit (EmitContext ec)
+               {
+                       IntConstant.EmitInt (ec.ig, Value);
+               }
+       }
+
+       internal class IntConstant : NumericConstant {
+               int Value;
+
+               internal IntConstant (AST parent, int v, Location location)
+                       : base (parent, location)
+               {
+                       Value = v;
+               }
+
+               static public void EmitInt (ILGenerator ig, int i)
+               {
+                       switch (i){
+                       case -1:
+                               ig.Emit (OpCodes.Ldc_I4_M1);
+                               break;
+                               
+                       case 0:
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               break;
+                               
+                       case 1:
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               break;
+                               
+                       case 2:
+                               ig.Emit (OpCodes.Ldc_I4_2);
+                               break;
+                               
+                       case 3:
+                               ig.Emit (OpCodes.Ldc_I4_3);
+                               break;
+                               
+                       case 4:
+                               ig.Emit (OpCodes.Ldc_I4_4);
+                               break;
+                               
+                       case 5:
+                               ig.Emit (OpCodes.Ldc_I4_5);
+                               break;
+                               
+                       case 6:
+                               ig.Emit (OpCodes.Ldc_I4_6);
+                               break;
+                               
+                       case 7:
+                               ig.Emit (OpCodes.Ldc_I4_7);
+                               break;
+                               
+                       case 8:
+                               ig.Emit (OpCodes.Ldc_I4_8);
+                               break;
+
+                       default:
+                               if (i >= -128 && i <= 127){
+                                       ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
+                               } else
+                                       ig.Emit (OpCodes.Ldc_I4, i);
+                               break;
+                       }
                }
 
                internal override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       if (parent is Unary && (parent as Unary).oper == JSToken.Minus)
-                               ig.Emit (OpCodes.Ldc_R8, (double) (val * -1));
-                       else
-                               ig.Emit (OpCodes.Ldc_R8, (double) val);
-                       ig.Emit (OpCodes.Box, typeof (System.Double));
-                       if (no_effect)
-                               ig.Emit (OpCodes.Pop);
+                       EmitInt (ec.ig, Value);
                }
        }
 
+       internal class LongConstant : NumericConstant {
+               long Value;
+
+                internal LongConstant (AST parent, long v, Location location)
+                       : base (parent, location)
+                {
+                        Value = v;
+                }
+
+                internal override void Emit (EmitContext ec)
+                {
+                        ILGenerator ig = ec.ig;
+
+                        EmitLong (ig, Value);
+                }
+
+                static internal void EmitLong (ILGenerator ig, long l)
+                {
+                       ig.Emit (OpCodes.Ldc_I8, l);
+                }
+       }
+
+       internal class FloatConstant : NumericConstant {
+               float Value;
+
+                internal FloatConstant (AST parent, float v, Location location)
+                       : base (parent, location)
+                {
+                        Value = v;
+                }
+
+                internal override void Emit (EmitContext ec)
+                {
+                        ec.ig.Emit (OpCodes.Ldc_R4, Value);
+                }
+       }
+
+
+        internal class DoubleConstant : NumericConstant {
+               double Value;
+
+               internal DoubleConstant (AST parent, double v, Location location)
+                       : base (parent, location)
+                {
+                        Value = v;
+                }
+
+               internal override void Emit (EmitContext ec)
+                {
+                        ec.ig.Emit (OpCodes.Ldc_R8, Value);
+                }
+       }
+
        internal class ObjectLiteral : Exp {
                
                internal ArrayList elems;
@@ -207,6 +354,7 @@ namespace Microsoft.JScript {
                {
                        ec.ig.Emit (OpCodes.Ldstr, property_name);
                        exp.Emit (ec);
+                       CodeGenerator.EmitBox (ec.ig, exp);
                }
        }
 
index cb19d1295251e3c15d3ae9436f18f3f9e88b66bd..a27fcdf2c4d2e4cd07757608f58e029ed31c016a 100644 (file)
@@ -5,6 +5,7 @@
 //     Cesar Lopez Nataren (cesar@ciencias.unam.mx)
 //
 // (C) 2003, Cesar Lopez Nataren
+// Copyright (C) 2005, Novell Inc (http://novell.com)
 //
 
 //
@@ -38,7 +39,7 @@ namespace Microsoft.JScript {
                public NumericUnary (int operatorTok)
                        : base (null, null)
                {
-                       throw new NotImplementedException ();
+                       oper = (JSToken) operatorTok;
                }
 
                [DebuggerStepThroughAttribute]
index 4338602f20756e5145d3824074b0a61ef8054827..14a6683b05b596f7c62c96fd2059c94a5cc6412a 100644 (file)
@@ -101,6 +101,19 @@ namespace Microsoft.JScript {
                        return new Decompiler ();
                }
 
+               /// <summary>
+               /// Test if n is between the range stablished by min and max
+               /// </summary>
+               private bool InRangeOf (double n, double min, double max)
+               {
+                       return min <= n && n <= max;
+               }
+
+               private bool HasNoDecimals (double v)
+               {
+                       return Math.Round (v) == v;
+               }
+
                /// <summary>
                ///   Build a parse tree from a given source_string
                /// </summary>
@@ -1366,7 +1379,28 @@ namespace Microsoft.JScript {
                        } else if (tt == Token.NUMBER) {
                                double n = ts.GetNumber;
                                decompiler.AddNumber (n);
-                               return new NumericLiteral (parent, n, new Location (ts.SourceName, ts.LineNumber));
+
+                               Location location = new Location (ts.SourceName, ts.LineNumber);
+
+                               if (HasNoDecimals (n)) {
+                                       if (InRangeOf (n, Byte.MinValue, Byte.MaxValue))
+                                               return new ByteConstant (parent, (byte) n, location);
+                                       else if (InRangeOf (n, Int16.MinValue, Int16.MaxValue))
+                                               return new ShortConstant (parent, (short) n, location);
+                                       else if (InRangeOf (n, Int32.MinValue, Int32.MaxValue))
+                                               return new IntConstant (parent, (int) n, location);
+                                       else if (InRangeOf (n, Int64.MinValue, Int64.MaxValue))
+                                               return new LongConstant (parent, (long) n, location);
+                                       else
+                                               return new DoubleConstant (parent, n, location);
+                               } else {
+                                       if (InRangeOf (n, Single.MinValue, Single.MaxValue))
+                                               return new FloatConstant (parent, (float) n, location);
+                                       else if (InRangeOf (n, Double.MinValue, Double.MaxValue))
+                                               return new DoubleConstant (parent, n, location);
+                                       else
+                                               return new DoubleConstant (parent, n, location);
+                               }
                        } else if (tt == Token.STRING) {
                                string s = ts.GetString;
                                decompiler.AddString (s);
@@ -1391,7 +1425,7 @@ namespace Microsoft.JScript {
                                        v = false;
                                else
                                        v = true;
-                               return new BooleanLiteral (null, v, new Location (ts.SourceName, ts.LineNumber));
+                               return new BooleanConstant (null, v, new Location (ts.SourceName, ts.LineNumber));
                        } else if (tt == Token.RESERVED) {
                                ReportError ("msg.reserved.id");
                        } else if (tt == Token.ERROR) {
index 9c2e744e3d89bc95a59981a4b5e5f78f54521589..6d2ac76761f041821df698d246cdd1027d261110 100644 (file)
@@ -96,10 +96,14 @@ namespace Microsoft.JScript {
                                left.Emit (ec);
                                return;
                        } else if (op == JSToken.Instanceof) {
-                               if (left != null)
+                               if (left != null) {
                                        left.Emit (ec);
-                               if (right != null)
+                                       CodeGenerator.EmitBox (ig, left);
+                               }
+                               if (right != null) {
                                        right.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, right);
+                               }
                                ig.Emit (OpCodes.Call, typeof (Instanceof).GetMethod ("JScriptInstanceof"));
                                ig.Emit (OpCodes.Box, typeof (Boolean));
                                return;
@@ -135,10 +139,14 @@ namespace Microsoft.JScript {
                        ig.Emit (OpCodes.Stloc, loc);
                        ig.Emit (OpCodes.Ldloc, loc);
                        
-                       if (left != null)
+                       if (left != null) {
                                left.Emit (ec);
-                       if (right != null)
+                               CodeGenerator.EmitBox (ig, left);
+                       }
+                       if (right != null) {
                                right.Emit (ec);
+                               CodeGenerator.EmitBox (ig, right);
+                       }
                        
                        ig.Emit (OpCodes.Call, t.GetMethod ("EvaluateRelational"));
 
index f2505bbc318a44b54e9bd3d0a14d409a332806e9..55afd66b76a6df257c3d7b6295ed6a066ceb7489 100644 (file)
@@ -97,7 +97,6 @@ namespace Microsoft.JScript {
                        prototypes.Add (typeof (Closure), typeof (FunctionPrototype));
                        prototypes.Add (typeof (ArrayObject), typeof (ArrayPrototype));
                        prototypes.Add (typeof (StringObject), typeof (StringPrototype));
-                       prototypes.Add (typeof (StringLiteral), typeof (StringPrototype));
                        prototypes.Add (typeof (BooleanObject), typeof (BooleanPrototype));
                        prototypes.Add (typeof (NumberObject), typeof (NumberPrototype));
                        prototypes.Add (typeof (DateObject), typeof (DatePrototype));
@@ -110,6 +109,21 @@ namespace Microsoft.JScript {
                        prototypes.Add (typeof (SyntaxErrorObject), typeof (ErrorPrototype));
                        prototypes.Add (typeof (TypeErrorObject), typeof (ErrorPrototype));
                        prototypes.Add (typeof (URIErrorObject), typeof (ErrorPrototype));
+
+
+                       // literals, used when accessing a method from the prototype
+                       // through the literal
+                       prototypes.Add (typeof (ArrayLiteral), typeof (ArrayPrototype));
+                       prototypes.Add (typeof (StringLiteral), typeof (StringPrototype));
+                       prototypes.Add (typeof (BooleanConstant), typeof (BooleanPrototype));
+
+                       Type number_prototype = typeof (NumberPrototype);
+                       prototypes.Add (typeof (ByteConstant), number_prototype);
+                       prototypes.Add (typeof (ShortConstant), number_prototype);
+                       prototypes.Add (typeof (IntConstant), number_prototype);
+                       prototypes.Add (typeof (LongConstant), number_prototype);
+                       prototypes.Add (typeof (FloatConstant), number_prototype);
+                       prototypes.Add (typeof (DoubleConstant), number_prototype);
                }
 
                internal static string ImplementationName (string name)
@@ -216,7 +230,7 @@ namespace Microsoft.JScript {
                                        obj =  ((Identifier) left).name.Value;
                                        prop_name = ((Identifier) right).name.Value;
                                        target_type = SemanticAnalyser.map_to_ctr (obj);
-                               } else if (left is StringLiteral && right_is_identifier) {
+                               } else if (left is ICanLookupPrototype && right_is_identifier) {
                                        prop_name = ((Identifier) right).name.Value;
                                        target_type = SemanticAnalyser.map_to_prototype (left);
                                }
@@ -300,6 +314,32 @@ namespace Microsoft.JScript {
                        return null;
                }
 
+               internal static bool IsNumericConstant (object o)
+               {
+                       return o is ByteConstant || o is ShortConstant ||
+                               o is IntConstant || o is LongConstant ||
+                               o is FloatConstant || o is DoubleConstant;
+               }
+
+               internal static bool NeedsToBoolean (AST ast)
+               {
+                       if (ast is BooleanConstant || ast is StrictEquality)
+                               return false;
+                       else if (ast is Expression)
+                               return NeedsToBoolean (((Expression) ast).Last);
+                       else if (ast is Unary) {
+                               Unary unary = (Unary) ast;
+                               if (unary.oper != JSToken.LogicalNot)
+                                       return true;
+                               return false;
+                       } else if (ast is Call || ast is Identifier)
+                               return true;
+                       else {
+                               Console.WriteLine ("ast.LineNumber = {0}", ast.Location.LineNumber);
+                               throw new NotImplementedException ();
+                       }
+               }
+
                internal static bool Needs (JSFunctionAttributeEnum targetAttr, MethodInfo method)
                {
                        JSFunctionAttribute [] custom_attrs = (JSFunctionAttribute [])
index 6b2b30d3dce28beae13e9ce5e81eac746ec14095..d58d9084c0ef49d5f846889b9cb6f062fe332135 100644 (file)
@@ -90,8 +90,9 @@ namespace Microsoft.JScript {
                        Label false_lbl = ig.DefineLabel ();
                        Label merge_lbl = ig.DefineLabel ();
                        CodeGenerator.fall_true (ec, cond, false_lbl);
+                       CodeGenerator.EmitBox (ig, cond);
                        if (true_stm != null)
-                               true_stm.Emit (ec);                     
+                               true_stm.Emit (ec);
                        ig.Emit (OpCodes.Br, merge_lbl);
                        ig.MarkLabel (false_lbl);
                        if (false_stm != null)
index 48505b6fdecf69c4d0071c50f7a4371c85954353..6b1212a6387fbbc92522da13ee408d340f796e6a 100644 (file)
@@ -110,10 +110,14 @@ namespace Microsoft.JScript {
 
                internal override void Emit (EmitContext ec)
                {
-                       if (left != null)
+                       if (left != null) {
                                left.Emit (ec);
-                       if (right != null)
+                               CodeGenerator.EmitBox (ec.ig, left);
+                       }
+                       if (right != null) {
                                right.Emit (ec);
+                               CodeGenerator.EmitBox (ec.ig, right);
+                       }
                        ec.ig.Emit (OpCodes.Call, typeof (StrictEquality).GetMethod ("JScriptStrictEquals"));
                }
        }
index 3084af1cfcb74fa8255ab33afc62c7bf9e5e6e7d..a66c76e5182c3ea3efdbf3acaa2ca36bcf0ffb4d 100644 (file)
@@ -115,17 +115,18 @@ namespace Microsoft.JScript {
                                               && parent.GetType () != typeof (FunctionExpression))) {
                                if (val != null) {
                                        val.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, val);
                                        ig.Emit (OpCodes.Stsfld, field_info);
                                }
                        } else {
                                if (val != null) {
                                        val.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, val);
                                        ig.Emit (OpCodes.Stloc, local_builder);
                                }
                        }
                }
 
-
                internal override bool Resolve (IdentificationTable context)
                {
                        bool r = true;
index ebb20c166963ad759f81b77fa65f0fc544ebc36a..927f70c9edc5abf8c4fee8be3da3df7cb3c94810 100644 (file)
@@ -72,11 +72,12 @@ namespace Microsoft.JScript {
                internal override bool Resolve (IdentificationTable context)
                {
                        bool r = false;                
-                       
-                       if (operand is Exp)
+
+                       if (operand is Exp) {
                                if (oper != JSToken.Increment && oper != JSToken.Decrement)
                                        r = ((Exp) operand).Resolve (context, no_effect);
-                       r = ((AST) operand).Resolve (context);                  
+                       } else 
+                               r = operand.Resolve (context);
                        return r;
                }
 
@@ -87,16 +88,9 @@ namespace Microsoft.JScript {
                }
 
                internal override void Emit (EmitContext ec)
-               {
-                       if (!(operand is NumericLiteral) || (oper != JSToken.Minus))
-                               emit_unary_op (ec);
-                       else
-                               operand.Emit (ec);
-               }
-
-               internal void emit_unary_op (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
+
                        switch (oper) {
                        case JSToken.Void:
                                operand.Emit (ec);
@@ -106,6 +100,7 @@ namespace Microsoft.JScript {
 
                        case JSToken.Typeof:
                                operand.Emit (ec);
+                               CodeGenerator.EmitBox (ig, operand);
                                ig.Emit (OpCodes.Call, typeof (Typeof).GetMethod ("JScriptTypeof"));
                                break;
 
@@ -139,29 +134,43 @@ namespace Microsoft.JScript {
                        case JSToken.Plus:
                                operand.Emit (ec);
                                ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber", new Type [] { typeof (object) }));
-                               /* all clear */
+                               //
+                               // FIXME: investigate the real
+                               // discriminate for generating this
+                               // box.
+                               if (!no_effect)
+                                       ig.Emit (OpCodes.Box, typeof (double));
                                break;
 
                        case JSToken.Minus:
-                               operand.Emit (ec);
-                               ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber", new Type [] { typeof (object) }));
-                               ig.Emit (OpCodes.Neg);
+                               if (SemanticAnalyser.IsNumericConstant (operand)) {
+                                       operand.Emit (ec);
+                                       ig.Emit (OpCodes.Neg);
+                               } else if (operand is Identifier && 
+                                          ((Identifier) operand).name.Value == "Infinity")
+                                       ig.Emit (OpCodes.Ldc_R8, Double.NegativeInfinity);
+                               else
+                                       emit_non_numeric_unary (ec, operand, (byte) 47);
                                break;
 
                        case JSToken.BitwiseNot:
-                               operand.Emit (ec);
-                               ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToInt32"));
-                               ig.Emit (OpCodes.Not);
+                               if (SemanticAnalyser.IsNumericConstant (operand)) {
+                                       operand.Emit (ec);
+                                       ig.Emit (OpCodes.Not);
+                               } else
+                                       emit_non_numeric_unary (ec, operand, (byte) 40);
                                break;
 
                        case JSToken.LogicalNot:
                                operand.Emit (ec);
-                               // FIXME: here we can infer the type
-                               // of the operand so that unneeded
-                               // ToBoolean can be avoided
-                               ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToBoolean", new Type [] { typeof (object) }));
-                               ig.Emit (OpCodes.Ldc_I4_1);
-                               ig.Emit (OpCodes.Sub);
+                               if (SemanticAnalyser.NeedsToBoolean (operand)) {
+                                       CodeGenerator.EmitBox (ec.ig, operand);
+                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToBoolean",
+                                                                                  new Type [] { typeof (object), typeof (bool) }));
+                               }
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Ceq);
                                break;
 
                        default:
@@ -169,6 +178,23 @@ namespace Microsoft.JScript {
                                throw new NotImplementedException ();
                        }
                }
+
+               private void emit_non_numeric_unary (EmitContext ec, AST operand, byte oper)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       Type unary_type = typeof (NumericUnary);
+                       LocalBuilder unary_builder = ig.DeclareLocal (unary_type);
+
+                       ig.Emit (OpCodes.Ldc_I4_S, oper);
+                       ig.Emit (OpCodes.Newobj, unary_type.GetConstructor (new Type [] { typeof (int) }));
+                       ig.Emit (OpCodes.Stloc, unary_builder);
+                       ig.Emit (OpCodes.Ldloc, unary_builder);
+
+                       operand.Emit (ec);
+
+                       ig.Emit (OpCodes.Call, unary_type.GetMethod ("EvaluateUnary"));
+               }
        }
 
        internal class Binary : BinaryOp, IAssignable {
@@ -204,6 +230,10 @@ namespace Microsoft.JScript {
                        get { return op == JSToken.AccessField; }
                }
 
+               internal bool LateBinding {
+                       get { return late_bind; }
+               }
+
                internal override bool Resolve (IdentificationTable context)
                {
                        bool found = true;
@@ -269,10 +299,14 @@ namespace Microsoft.JScript {
                                        emit_access (left, right, ec);
                        } else {
                                emit_operator (ig);
-                               if (left != null)
+                               if (left != null) {
                                        left.Emit (ec);
-                               if (right != null)
+                                       CodeGenerator.EmitBox (ig, left);
+                               }
+                               if (right != null) {
                                        right.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, right);
+                               }
                                emit_op_eval (ig);
                        }
                        if (no_effect)
@@ -379,7 +413,7 @@ namespace Microsoft.JScript {
                                ig.Emit (OpCodes.Dup);
                        }                               
                        left.Emit (ec);
-                       
+
                        LocalBuilder local_literal = null;
 
                        //
@@ -406,6 +440,7 @@ namespace Microsoft.JScript {
                                        right_side.Emit (ec);
                                else
                                        ig.Emit (OpCodes.Ldloc, right_obj);
+                               CodeGenerator.EmitBox (ig, right_side);
                                ig.Emit (OpCodes.Call, lb_type.GetMethod ("SetValue"));
                        } else
                                ig.Emit (OpCodes.Call, lb_type.GetMethod ("GetNonMissingValue"));
@@ -413,13 +448,7 @@ namespace Microsoft.JScript {
                
                internal void get_default_this (ILGenerator ig)
                {
-                       if (InFunction)
-                               ig.Emit (OpCodes.Ldarg_1);
-                       else {
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
-                       }
-                      
+                       CodeGenerator.load_engine (InFunction, ig);
                        ig.Emit (OpCodes.Call, typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("ScriptObjectStackTop"));
                        Type iact_obj = typeof (IActivationObject);
                        ig.Emit (OpCodes.Castclass, iact_obj);
@@ -441,26 +470,24 @@ namespace Microsoft.JScript {
                        ig.Emit (OpCodes.Newarr, typeof (object));
                        ig.Emit (OpCodes.Dup);
                        ig.Emit (OpCodes.Ldc_I4_0);
-                       if (right != null)
+                       if (right != null) {
                                right.Emit (ec);
+                               CodeGenerator.EmitBox (ig, right);
+                       }
                        ig.Emit (OpCodes.Stelem_Ref);                   
 
                        if (assign) {
-                               if (right_side != null)
+                               if (right_side != null) {
                                        right_side.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, right_side);
+                               }
                                else
                                        ig.Emit (OpCodes.Ldloc, right_obj);
                                ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("SetIndexedPropertyValueStatic"));
                        } else {
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.Emit (OpCodes.Ldc_I4_1);
-
-                               if (InFunction)
-                                       ig.Emit (OpCodes.Ldarg_1);
-                               else {
-                                       ig.Emit (OpCodes.Ldarg_0);
-                                       ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
-                               }
+                               CodeGenerator.load_engine (InFunction, ig);
                                ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
                        }
                }
@@ -613,12 +640,16 @@ namespace Microsoft.JScript {
                        Label false_label = ig.DefineLabel ();
                        Label merge_label = ig.DefineLabel ();
                        CodeGenerator.fall_true (ec, cond_exp, false_label);
-                       if (true_exp != null)
+                       if (true_exp != null) {
                                true_exp.Emit (ec);
+                               CodeGenerator.EmitBox (ig, true_exp);
+                       }
                        ig.Emit (OpCodes.Br, merge_label);
                        ig.MarkLabel (false_label);
-                       if (false_exp != null)
+                       if (false_exp != null) {
                                false_exp.Emit (ec);
+                               CodeGenerator.EmitBox (ig, false_exp);
+                       }
                        ig.MarkLabel (merge_label);
                        if (no_effect)
                                ig.Emit (OpCodes.Pop);
@@ -780,8 +811,10 @@ namespace Microsoft.JScript {
                                if (member_type == MemberTypes.Method) {
                                        if (member_exp is Binary) {
                                                Binary bin = (Binary) member_exp;
-                                               if (bin.left is StringLiteral && need_this)
+                                               if (bin.left is ICanLookupPrototype && need_this ) {
                                                        bin.left.Emit (ec);
+                                                       CodeGenerator.EmitBox (ig, bin.left);
+                                               }
                                        }                                               
                                        args.Emit (ec);
                                        MethodInfo method = (MethodInfo) minfo;
@@ -823,7 +856,8 @@ namespace Microsoft.JScript {
                        for (int i = 0; i <= n; i++) {
                                ast = args.get_element (i);
                                ast.Emit (ec);
-                               
+                               CodeGenerator.EmitBox (ig, ast);
+
                                if (ast is StringLiteral)
                                        ;
                                else {
@@ -847,6 +881,7 @@ namespace Microsoft.JScript {
                                Binary bin = member_exp as Binary;
                                if (SemanticAnalyser.IsLiteral (bin.left) != null) {
                                        member_exp.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, member_exp);
                                        setup_late_call_args (ec);
                                        ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
                                } else if (bin.right is Identifier) {
@@ -863,13 +898,18 @@ namespace Microsoft.JScript {
                                        ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("Call"));
                                } else {
                                        bin.left.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, bin.left);
+
                                        member_exp.Emit (ec);
+                                       CodeGenerator.EmitBox (ig, member_exp);
+
                                        setup_late_call_args (ec);
                                        ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
                                }
                        } else {
                                get_global_scope_or_this (ec.ig);
                                member_exp.Emit (ec);
+                               CodeGenerator.EmitBox (ig, member_exp);
                                setup_late_call_args (ec);
                                ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
                        }
@@ -909,9 +949,9 @@ namespace Microsoft.JScript {
                        
                        AST left = (member_exp as Binary).left;
                        left.Emit (ec);
-                       
-                       ig.Emit (OpCodes.Ldarg_0);
-                       ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+
+                       CodeGenerator.load_engine (InFunction, ig);
+
                        ig.Emit (OpCodes.Call , typeof (Convert).GetMethod ("ToObject"));
 
                        Type lb_type = typeof (LateBinding);
@@ -923,6 +963,7 @@ namespace Microsoft.JScript {
                {
                        ILGenerator ig = ec.ig;
                        int n = args.Size;
+                       AST ast = null;
 
                        ig.Emit (OpCodes.Ldc_I4, n);
                        ig.Emit (OpCodes.Newarr, typeof (object));
@@ -930,7 +971,9 @@ namespace Microsoft.JScript {
                        for (int i = 0; i < n; i++) {
                                ig.Emit (OpCodes.Dup);
                                ig.Emit (OpCodes.Ldc_I4, i);
-                               args.get_element (i).Emit (ec);
+                               ast = args.get_element (i);
+                               ast.Emit (ec);
+                               CodeGenerator.EmitBox (ig, ast);
                                ig.Emit (OpCodes.Stelem_Ref);
                        }
 
@@ -972,18 +1015,24 @@ namespace Microsoft.JScript {
 
                        ILGenerator ig = ec.ig;
                        int n = args.Size;
+                       AST ast = null;
                        
                        if (n >= 1 && (member_exp.ToString () == "String" || member_exp.ToString () == "Boolean" || member_exp.ToString () == "Number")) {
-                               args.get_element (0).Emit (ec);
+                               ast = args.get_element (0);
+                               ast.Emit (ec);
+                               CodeGenerator.EmitBox (ig, ast);
                                return;
                        }
 
                        ig.Emit (OpCodes.Ldc_I4, n);
                        ig.Emit (OpCodes.Newarr, typeof (object));
+
                        for (int i = 0; i < n; i++) {
                                ig.Emit (OpCodes.Dup);
                                ig.Emit (OpCodes.Ldc_I4, i);
-                               args.get_element (i).Emit (ec);
+                               ast = args.get_element (i);
+                               ast.Emit (ec);
+                               CodeGenerator.EmitBox (ig, ast);
                                ig.Emit (OpCodes.Stelem_Ref);
                        }
                }
@@ -1168,7 +1217,7 @@ namespace Microsoft.JScript {
                                Console.WriteLine ("warning JS1135: Variable '" + name + "' has not been declared");
                        } else
                                throw new Exception (location.SourceName + "(" + location.LineNumber + 
-                                    ",0) : error JS1135: Variable '" + name + "' has not been declared");
+                                            ",0) : error JS1135: Variable '" + name + "' has not been declared");
                        return true;
                }
 
@@ -1231,8 +1280,10 @@ namespace Microsoft.JScript {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (assign && right_side != null && !undeclared)
+                       if (assign && right_side != null && !undeclared) {
                                right_side.Emit (ec);
+                               CodeGenerator.EmitBox (ig, right_side);
+                       }
                        if (binding is FormalParam) {
                                FormalParam f = binding as FormalParam;
                                if (assign)
@@ -1509,6 +1560,12 @@ namespace Microsoft.JScript {
                        get { return BoundToMethod is Function; }
                }
 
+               private bool in_new = false;
+               internal bool InNew {
+                       set { in_new = value; }
+                       get { return in_new; }
+               }
+
                private int expected_args = 0;
                private bool has_this = false;
                private bool var_args = false;
@@ -1555,17 +1612,21 @@ namespace Microsoft.JScript {
                                expected_args = method.GetParameters ().Length;
                        } else if (BoundToMethod is BuiltIn) {
                                BuiltIn built_in = (BuiltIn) BoundToMethod;
-                               if (built_in.IsConstructor)
-                                       expected_args = elems.Count;
+                               if (built_in.IsConstructor || InNew)
+                                       expected_args = (elems == null) ? 0 : elems.Count;
                                else
                                        expected_args = ((BuiltIn) BoundToMethod).NumOfArgs;
                        }
 
-                       int n = Size;
+                       if (elems == null)
+                               return true;
+                       
+                       int n = elems.Count;
 
                        for (int i = 0; i < n; i++) {
                                tmp = (AST) elems [i];
-                               r &= tmp.Resolve (context);
+                               if (tmp != null)
+                                       r &= tmp.Resolve (context);
                        }
                        return r;
                }
@@ -1624,7 +1685,7 @@ namespace Microsoft.JScript {
                                }
                        }
 
-                       if (strong_type)
+                       if (BoundToMethod is MethodInfo)
                                parameters = ((MethodInfo) BoundToMethod).GetParameters ();
 
                        if (has_engine)
@@ -1633,7 +1694,7 @@ namespace Microsoft.JScript {
                        if (var_args) {
                                if (expected_args > 1)
                                        emit_default_args_case (ec, expected_args, strong_type, parameters);
-
+                               
                                ILGenerator ig = ec.ig;
 
                                int remains = elems.Count - expected_args;
@@ -1654,6 +1715,7 @@ namespace Microsoft.JScript {
                                                ig.Emit (OpCodes.Dup);
                                                ig.Emit (OpCodes.Ldc_I4, k);
                                                ast.Emit (ec);
+                                               CodeGenerator.EmitBox (ig, ast);
                                                ig.Emit (OpCodes.Stelem_Ref);
                                        }
                                }
@@ -1684,6 +1746,8 @@ namespace Microsoft.JScript {
                                        ast.Emit (ec);
                                        if (strong_type)
                                                force_strong_type (ig, ast, parameters [j]);
+                                       else
+                                               CodeGenerator.EmitBox (ig, ast);
                                } else {
                                        //
                                        // ast was null and we need
@@ -1697,31 +1761,28 @@ namespace Microsoft.JScript {
                        }
                }
 
-               internal void force_strong_type (ILGenerator ig, AST ast, ParameterInfo pinfo)
+               internal void force_strong_type (ILGenerator ig, AST ast, object obj)
                {
-                       Type param_type = pinfo.ParameterType;
-                       if (ast.GetType () == typeof (NumericLiteral)) {
-                               if (param_type == typeof (double)) {
-                                       ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber", new Type [] { typeof (object) }));
-                                       //ig.Emit (OpCodes.Conv_R8);
-                               } else if (param_type == typeof (object))
-                                       ;
-                               else {
-                                       Console.WriteLine ("#1. ast.GetType = {0}, param_type = {1}", ast.GetType (), param_type);
-                                       throw new NotImplementedException ();
-                               }
-                       } else {
+                       Type param_type = null;
+                       if (obj is ParameterInfo)
+                               param_type = ((ParameterInfo) obj).ParameterType;
+                       else
+                               param_type = obj.GetType ();
+
+                       if (SemanticAnalyser.IsNumericConstant (ast)) {
                                if (param_type == typeof (double))
-                                       ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber", new Type [] {typeof (object)}));
-                               else if (param_type == typeof (string)) {
-                                       ig.Emit (OpCodes.Ldc_I4_1);
-                                       ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToString", new Type [] {typeof (object), typeof (bool)}));
-                               } else if (param_type == typeof (object))
-                                       ;
-                               else {
-                                       Console.WriteLine ("#2. ast.GetType = {0}, param_type = {1}", ast.GetType (), param_type);
+                                       CodeGenerator.EmitConv (ig, param_type);
+                               else if (param_type == typeof (object))
+                                       CodeGenerator.EmitBox (ig, ast);
+                               else
                                        throw new NotImplementedException ();
-                               }
+                       } else {
+                               if (ast is Unary) {
+                                       Unary unary = (Unary) ast;
+                                       force_strong_type (ig, unary.operand, obj);
+                               } else if (param_type == typeof (double))
+                                       ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToNumber",
+                                                                                  new Type [] { typeof (object) }));
                        }
                }
        }
@@ -1745,6 +1806,10 @@ namespace Microsoft.JScript {
                        exprs.Add (a);
                }
 
+               internal AST Last {
+                       get { return (AST) exprs [Size - 1]; }
+               }
+
                public override string ToString ()
                {
                        int size = exprs.Count;         
@@ -1755,10 +1820,7 @@ namespace Microsoft.JScript {
 
                                for (i = 0; i < size; i++)
                                        sb.Append (exprs [i].ToString ());
-
-                               sb.Append ("\n");
                                return sb.ToString ();
-
                        } else return String.Empty;
                }
 
@@ -1803,6 +1865,7 @@ namespace Microsoft.JScript {
                        for (i = 0; i < n; i++) {
                                exp = (AST) exprs [i];
                                exp.Emit (ec);
+                               CodeGenerator.EmitBox (ec.ig, exp);
                        }
                }
        }
@@ -1866,8 +1929,10 @@ namespace Microsoft.JScript {
                                        ig.Emit (OpCodes.Stloc, aux);
                                        ig.Emit (OpCodes.Ldloc, local);
                                        ig.Emit (OpCodes.Ldloc, aux);
-                                       if (right != null)
+                                       if (right != null) {
                                                right.Emit (ec);
+                                               CodeGenerator.EmitBox (ig, right);
+                                       }
                                        ig.Emit (OpCodes.Call, type.GetMethod ("EvaluatePlus"));
                                        if (left is Identifier)
                                                ((Identifier) left).EmitStore (ec);
@@ -2007,8 +2072,10 @@ namespace Microsoft.JScript {
                        } 
                        exp.Resolve (context);
 
-                       if (args != null)
+                       if (args != null) {
+                               args.InNew = true;
                                r &= args.Resolve (context);
+                       }
                        return r;
                }
 
@@ -2017,8 +2084,9 @@ namespace Microsoft.JScript {
                        ILGenerator ig = ec.ig;
 
                        if (exp != null) {
-                               if (late_bind) {                                        
-                                       CodeGenerator.emit_get_default_this (ec.ig);
+                               if (late_bind) {
+                                       AST ast = null;
+                                       CodeGenerator.emit_get_default_this (ec.ig, InFunction);
                                        exp.Emit (ec);
 
                                        ig.Emit (OpCodes.Ldc_I4, args.Size);
@@ -2027,15 +2095,16 @@ namespace Microsoft.JScript {
                                        for (int i = 0; i < args.Size; i++) {
                                                ig.Emit (OpCodes.Dup);
                                                ig.Emit (OpCodes.Ldc_I4, i);
-                                               args.get_element (i).Emit (ec);
+                                               ast = args.get_element (i);
+                                               ast.Emit (ec);
+                                               CodeGenerator.EmitBox (ig, ast);
                                                ig.Emit (OpCodes.Stelem_Ref);
                                        }
-                                       
+
                                        ig.Emit (OpCodes.Ldc_I4_1);
                                        ig.Emit (OpCodes.Ldc_I4_0);
 
-                                       ig.Emit (OpCodes.Ldarg_0);
-                                       ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+                                       CodeGenerator.load_engine (InFunction, ig);
 
                                        ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue"));
                                } else {
@@ -2095,10 +2164,14 @@ namespace Microsoft.JScript {
                        ig.Emit (OpCodes.Ldc_I4, args.Size);
                        ig.Emit (OpCodes.Newarr, typeof (object));
 
+                       AST ast = null;
+
                        for (int i = 0; i < n; i++) {
                                ig.Emit (OpCodes.Dup);
                                ig.Emit (OpCodes.Ldc_I4, i);
-                               args.get_element (i).Emit (ec);
+                               ast = args.get_element (i);
+                               ast.Emit (ec);
+                               CodeGenerator.EmitBox (ig, ast);
                                ig.Emit (OpCodes.Stelem_Ref);
                        }
                }
@@ -2167,16 +2240,16 @@ namespace Microsoft.JScript {
                        /* value properties of the Global Object */
                        case "NaN":
                                ig.Emit (OpCodes.Ldc_R8, Double.NaN);
-                               ig.Emit (OpCodes.Box, typeof (Double));
                                break;                          
+
                        case "Infinity":
                                ig.Emit (OpCodes.Ldc_R8, Double.PositiveInfinity);
-                               // FIXME: research when not to generate the Boxing
-                               ig.Emit (OpCodes.Box, typeof (Double));
                                break;
+
                        case "undefined":
                                ig.Emit (OpCodes.Ldnull);
                                break;
+
                        case "null":
                                ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
                                break;
@@ -2191,71 +2264,92 @@ namespace Microsoft.JScript {
 #endif
                                ig.Emit (OpCodes.Call, typeof (Eval).GetMethod ("JScriptEvaluate", method_args));
                                break;
+
                        case "parseInt":                                
                                ig.Emit (OpCodes.Call, go.GetMethod ("parseInt"));
                                ig.Emit (OpCodes.Box, typeof (Double));
                                break;
+
                        case "parseFloat":
                                ig.Emit (OpCodes.Call, go.GetMethod ("parseFloat"));
                                ig.Emit (OpCodes.Box, typeof (Double));
                                break;
+
                        case "isNaN":
                                ig.Emit (OpCodes.Call, go.GetMethod ("isNaN"));
                                ig.Emit (OpCodes.Box, typeof (bool));
                                break;
+
                        case "isFinite":
                                ig.Emit (OpCodes.Call, go.GetMethod ("isFinite"));
                                ig.Emit (OpCodes.Box, typeof (bool));
                                break;
+
                        case "decodeURI":
                                ig.Emit (OpCodes.Call, go.GetMethod ("decodeURI"));
                                break;
+
                        case "decodeURIComponent":
                                ig.Emit (OpCodes.Call, go.GetMethod ("decodeURIComponent"));
                                break;
+
                        case "encodeURI":
                                ig.Emit (OpCodes.Call, go.GetMethod ("encodeURI"));
                                break;
+
                        case "encodeURIComponent":
                                ig.Emit (OpCodes.Call, go.GetMethod ("encodeURIComponent"));
                                break;
+
                        case "escape":
                                ig.Emit (OpCodes.Call, go.GetMethod ("escape"));
                                break;
+
                        case "unescape":
                                ig.Emit (OpCodes.Call, go.GetMethod ("unescape"));
                                break;
+
                        /* constructor properties of the Global object */
                        case "Object":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Object").GetGetMethod ());
                                break;
+
                        case "Function":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Function").GetGetMethod ());
                                break;
+
                        case "Array":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Array").GetGetMethod ());
                                break;
+
                        case "String":
                                ig.Emit (OpCodes.Call, go.GetProperty ("String").GetGetMethod ());
                                break;
+
                        case "Boolean":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Boolean").GetGetMethod ());
                                break;
+
                        case "Number":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Number").GetGetMethod ());
                                break;
+
                        case "Date":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Date").GetGetMethod ());
                                break;
+
                        case "RegExp":
                                ig.Emit (OpCodes.Call, go.GetProperty ("RegExp").GetGetMethod ());
                                break;
+
                        case "Error":
                                ig.Emit (OpCodes.Call, go.GetProperty ("Error").GetGetMethod ());
                                break;
+
                        case "EvalError":
                                ig.Emit (OpCodes.Call, go.GetProperty ("EvalError").GetGetMethod ());
                                break;
+
                        case "RangeError":
                                ig.Emit (OpCodes.Call, go.GetProperty ("RangeError").GetGetMethod ());
                                break;