From: César Natarén Date: Sat, 20 Aug 2005 00:04:20 +0000 (-0000) Subject: 2005-08-19 Cesar Lopez Nataren X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=c6e7c1f670a888ca1435747ac7efeba68729a613;p=mono.git 2005-08-19 Cesar Lopez Nataren * 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 --- diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayLiteral.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayLiteral.cs index 1391eefc48d..904f7db9126 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayLiteral.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayLiteral.cs @@ -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++; diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog b/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog index 345714b4279..3afcc2aff90 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog @@ -1,3 +1,53 @@ +2005-08-19 Cesar Lopez Nataren + + * 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 * ScriptObject.cs: Added settable _proto for __proto__. This isn't diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs index 391a5b76a9a..b34696dd951 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/CodeGenerator.cs @@ -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 (); - } } } } diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Equality.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Equality.cs index d8d5b84de6f..33bedcdd7a6 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Equality.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Equality.cs @@ -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")); diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs index 0fce2a00623..bbfdbb35675 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Literal.cs @@ -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); } } diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/NumericUnary.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/NumericUnary.cs index cb19d129525..a27fcdf2c4d 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/NumericUnary.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/NumericUnary.cs @@ -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] diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Parser.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Parser.cs index 4338602f207..14a6683b05b 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Parser.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Parser.cs @@ -101,6 +101,19 @@ namespace Microsoft.JScript { return new Decompiler (); } + /// + /// Test if n is between the range stablished by min and max + /// + private bool InRangeOf (double n, double min, double max) + { + return min <= n && n <= max; + } + + private bool HasNoDecimals (double v) + { + return Math.Round (v) == v; + } + /// /// Build a parse tree from a given source_string /// @@ -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) { diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Relational.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Relational.cs index 9c2e744e3d8..6d2ac76761f 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Relational.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Relational.cs @@ -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")); diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs index f2505bbc318..55afd66b76a 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs @@ -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 []) diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/Statement.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/Statement.cs index 6b2b30d3dce..d58d9084c0e 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/Statement.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/Statement.cs @@ -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) diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs index 48505b6fdec..6b1212a6387 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs @@ -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")); } } diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/VariableDeclaration.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/VariableDeclaration.cs index 3084af1cfcb..a66c76e5182 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/VariableDeclaration.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/VariableDeclaration.cs @@ -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; diff --git a/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs b/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs index ebb20c16696..927f70c9edc 100644 --- a/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs +++ b/mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs @@ -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;