/// <summary> /// Pops the value on the stack, converts it to the given type, then pushes the result /// onto the stack. /// </summary> /// <param name="generator"> The IL generator. </param> /// <param name="fromType"> The type to convert from. </param> /// <param name="toType"> The type to convert to. </param> /// <param name="path"> The path of the javascript source file that is currently executing. </param> /// <param name="function"> The name of the currently executing function. </param> public static void Convert(ILGenerator generator, Type fromType, Type toType, string path, string function) { // Check that a conversion is actually necessary. if (fromType == toType) { return; } if (toType == typeof(object)) { ToAny(generator, fromType); } else if (toType == typeof(Nitrassic.Undefined)) { generator.Pop(); EmitHelpers.EmitUndefined(generator); } else if (toType == typeof(Nitrassic.Null)) { generator.Pop(); EmitHelpers.EmitNull(generator); } else if (toType == typeof(bool)) { ToBool(generator, fromType); } else if (toType == typeof(long)) { generator.ConvertToInt64(); } else if (toType == typeof(ulong)) { generator.ConvertToUnsignedInt64(); } else if (toType == typeof(int)) { generator.ConvertToInt32(); } else if (toType == typeof(uint)) { generator.ConvertToUnsignedInt32(); } else if (toType == typeof(short)) { generator.ConvertToInt16(); } else if (toType == typeof(ushort)) { generator.ConvertToUnsignedInt16(); } else if (toType == typeof(sbyte)) { generator.ConvertToInt8(); } else if (toType == typeof(byte)) { generator.ConvertToUnsignedInt8(); } else if (toType == typeof(double)) { ToNumber(generator, fromType); } else if (toType == typeof(string)) { ToString(generator, fromType); } else if (toType == typeof(ConcatenatedString)) { ToConcatenatedString(generator, fromType); } else { throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", toType)); } }
/// <summary> /// Generates CIL for the expression. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Literals cannot have side-effects so if a return value is not expected then generate // nothing. if (optimizationInfo.RootExpression == this) { return; } if (this.Value is int) { generator.LoadInt32((int)this.Value); } else if (this.Value is double) { generator.LoadDouble((double)this.Value); } else if (this.Value is string) { generator.LoadString((string)this.Value); } else if (this.Value is bool) { generator.LoadBoolean((bool)this.Value); } else if (this.Value is RegularExpressionLiteral) { // RegExp var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value); var label1 = generator.CreateLabel(); var label2 = generator.CreateLabel(); // if (sharedRegExp == null) { generator.LoadVariable(sharedRegExpVariable); generator.LoadNull(); generator.BranchIfNotEqual(label1); // sharedRegExp = Global.RegExp.OnConstruct(source, flags) EmitHelpers.LoadPrototypes(generator); generator.LoadField(ReflectionHelpers.PrototypeLookup_RegExp); generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern); generator.LoadString(((RegularExpressionLiteral)this.Value).Flags); generator.Call(ReflectionHelpers.RegExp_Construct); generator.Duplicate(); generator.StoreVariable(sharedRegExpVariable); // } else { generator.Branch(label2); generator.DefineLabelPosition(label1); // Global.RegExp.OnConstruct(sharedRegExp, flags) EmitHelpers.LoadPrototypes(generator); generator.LoadField(ReflectionHelpers.PrototypeLookup_RegExp); generator.LoadVariable(sharedRegExpVariable); generator.LoadNull(); generator.Call(ReflectionHelpers.RegExp_Construct); // } generator.DefineLabelPosition(label2); } else if (this.Value == Null.Value) { // Null. EmitHelpers.EmitNull(generator); } else if (this.Value == Undefined.Value) { // Undefined. EmitHelpers.EmitUndefined(generator); } else if (this.Value is List <Expression> ) { // Construct an array literal. var arrayLiteral = (List <Expression>) this.Value; // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[]) // ArrayConstructor EmitHelpers.LoadEngine(generator); // object[] generator.LoadInt32(arrayLiteral.Count); generator.NewArray(typeof(object)); for (int i = 0; i < arrayLiteral.Count; i++) { // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object). // Array generator.Duplicate(); // Index generator.LoadInt32(i); // Value var elementExpression = arrayLiteral[i]; if (elementExpression == null) { generator.LoadNull(); } else { elementExpression.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, elementExpression.GetResultType(optimizationInfo)); } // Store the element value. generator.StoreArrayElement(typeof(object)); } // ArrayConstructor.New(object[]) generator.Call(ReflectionHelpers.Array_New); } else if (this.Value is List <KeyValuePair <Expression, Expression> > ) { // This is an object literal. var properties = (List <KeyValuePair <Expression, Expression> >) this.Value; // We'll generate a prototype and a custom object type for it: Library.Prototype proto = CreatedPrototype; // Create a new object. generator.NewObject(proto.TypeConstructor); foreach (var keyValuePair in properties) { string propertyName = keyValuePair.Key.ToString(); Expression propertyValue = keyValuePair.Value; // Duplicate the object ref: generator.Duplicate(); // Add a new property to the object. Type valueType = propertyValue.GetResultType(optimizationInfo); // Get the property: Library.PropertyVariable pv = proto.GetProperty(propertyName); // Set it: pv.Set(generator, optimizationInfo, false, valueType, delegate(bool two){ if (pv.IsConstant) { // Emit the constant: EmitHelpers.EmitValue(generator, pv.ConstantValue); } else { // Write the value to set now: propertyValue.GenerateCode(generator, optimizationInfo); } // Note: This one always ignores 'two' }); } } else { throw new NotImplementedException("Unknown literal type."); } }