/// <summary>
        /// Generates CIL for the in operator.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateIn(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            if (optimizationInfo.RootExpression == this)
            {
                // Return isn't in use. Do nothing.
                Left.GenerateCode(generator, optimizationInfo);
                Right.GenerateCode(generator, optimizationInfo);
                generator.Pop();
                generator.Pop();
                return;
            }

            // Dynamic resolve required (The 'Evaluate' method above diverts away otherwise).

            // Engine required:
            EmitHelpers.LoadEngine(generator);

            // Emit the object:
            Right.GenerateCode(generator, optimizationInfo);

            // Emit the left-hand side expression and convert it to a string.
            Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToString(generator, Left.GetResultType(optimizationInfo));

            // Property name is now on the stack too.

            // Emit the property test:
            generator.Call(ReflectionHelpers.Object_HasProperty);
        }
Example #2
0
        /// <summary>
        /// Generates CIL for an assignment 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>
        /// <param name="target"> The target to modify. </param>
        private void GenerateAssignment(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target)
        {
            // Load the value to assign.
            var rhs = GetOperand(1);

            // Potentially transferring a constant here.
            // Note that all of the others affect the source value in some way
            // so this is the only one which can potentially transfer a constant like this.
            object constValue = target.GetConstantValue();

            // Store the value.
            target.GenerateSet(generator, optimizationInfo, optimizationInfo.RootExpression != this, rhs.GetResultType(optimizationInfo), delegate(bool two)
            {
                // Generate the code:

                if (constValue != null)
                {
                    // Straight emit the constant value (Note that it could be a function - it handles that for us):
                    EmitHelpers.EmitValue(generator, constValue);
                }
                else
                {
                    rhs.GenerateCode(generator, optimizationInfo);
                }

                if (two)
                {
                    // Duplicate the value so it remains on the stack afterwards.
                    generator.Duplicate();
                }
            }, optimizationInfo.StrictMode);
        }
Example #3
0
        /// <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)
        {
            // Setup the method info.
            // this.context.SetupMethod(optimizationInfo);

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <FunctionMethodGenerator>();
            }
            optimizationInfo.NestedFunctions.Add(context);

            // Add all the nested methods to the parent list.
            // Note: it's used to compute which variables are being hoisted.
            if (this.context.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            if (HoistValues != null)
            {
                // Script engine:
                EmitHelpers.LoadEngine(generator);

                // Method ID:
                generator.LoadInt64(context.MethodID);

                generator.LoadInt32(HoistValues.Count);

                // Hoist vars array:
                generator.NewArray(typeof(object));

                // Load each one:
                for (int i = 0; i < HoistValues.Count; i++)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);

                    // Load the variable value:
                    Type type = HoistValues[i].Get(generator);

                    // Box if necessary:
                    EmitConversion.ToAny(generator, type);

                    generator.StoreArrayElement(typeof(object));
                }

                generator.NewObject(ReflectionHelpers.HoistFunctionReference_Constructor);
            }
            else
            {
                // body
                generator.LoadInt64(context.MethodID);
                generator.Call(ReflectionHelpers.MethodLookup_Load);
            }
        }
Example #4
0
        /// <summary>
        /// Generates code to push the "this" value for a function call.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        public void GenerateThis(ILGenerator generator)
        {
            // Optimization: if there are no with scopes, simply emit undefined.
            bool scopeChainHasWithScope = false;
            var  scope = this.Scope;

            do
            {
                if (scope is ObjectScope && ((ObjectScope)scope).ProvidesImplicitThisValue == true)
                {
                    scopeChainHasWithScope = true;
                    break;
                }
                scope = scope.ParentScope;
            } while (scope != null);

            if (scopeChainHasWithScope == false)
            {
                // No with scopes in the scope chain, use undefined as the "this" value.
                EmitHelpers.EmitUndefined(generator);
                return;
            }

            scope = this.Scope;

            do
            {
                DeclarativeScope dScope = scope as DeclarativeScope;

                if (dScope != null)
                {
                    if (dScope.HasDeclaredVariable(this.Name))
                    {
                        // The variable exists but declarative scopes always produce undefined for
                        // the "this" value.
                        EmitHelpers.EmitUndefined(generator);
                        break;
                    }
                }
                else
                {
                    // Object scope - what object type is it for?
                    Prototype proto = (scope as ObjectScope).ScopePrototype;

                    _Variable = proto.GetProperty(Name);

                    if (_Variable != null)
                    {
                        // Output a get now:
                        _Variable.Get(generator);

                        break;
                    }
                }

                scope = scope.ParentScope;
            } while (scope != null);
        }
Example #5
0
 /// <summary>
 /// Emits a JavaScriptException.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 /// <param name="name"> The type of error to generate. </param>
 /// <param name="message"> The error message. </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>
 /// <param name="line"> The line number of the statement that is currently executing. </param>
 public static void EmitThrow(ILGenerator generator, string name, string message, string path, string function, int line)
 {
     EmitHelpers.LoadEngine(generator);
     generator.LoadString(name);
     generator.LoadString(message);
     generator.LoadInt32(line);
     generator.LoadStringOrNull(path);
     generator.LoadStringOrNull(function);
     generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
     generator.Throw();
 }
Example #6
0
 /// <summary>
 /// Generates CIL for the statement.
 /// </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)
 {
     // Emit code to throw the given value.
     EmitHelpers.LoadEngine(generator);
     this.Value.GenerateCode(generator, optimizationInfo);
     EmitConversion.ToAny(generator, this.Value.GetResultType(optimizationInfo));
     generator.LoadInt32(1);
     generator.LoadStringOrNull(optimizationInfo.Source.Path);
     generator.LoadStringOrNull(optimizationInfo.FunctionName);
     generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Object);
     generator.Throw();
 }
Example #7
0
        /// <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)
        {
            // Parent root:
            Expression rootExpression = optimizationInfo.RootExpression;

            // Get an array of comma-delimited expressions.
            var items = this.Items;
            int max   = items.Count;

            if (max == 0)
            {
                if (rootExpression != this)
                {
                    // Some other expression is using '()' - emit an undefined:
                    EmitHelpers.EmitUndefined(generator);
                }

                return;
            }

            if (rootExpression != this)
            {
                // Some other expression is the root. Return the last one.
                max--;
            }

            for (int i = 0; i < max; i++)
            {
                // Generate the code for the item:
                Expression expr = items[i];

                // Update root - we don't want return values except for the last one:
                optimizationInfo.RootExpression = expr;

                // Generate the code:
                expr.GenerateCode(generator, optimizationInfo);
            }

            // Restore root:
            optimizationInfo.RootExpression = rootExpression;

            if (rootExpression != this)
            {
                // Return the last one

                // Generate code for the last item and return the value.
                items[items.Count - 1].GenerateCode(generator, optimizationInfo);
            }
        }
Example #8
0
        /// <summary>
        /// Pushes the value of the reference onto the stack.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
        public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
        {
            if (Variable == null)
            {
                // It's undefined:
                EmitHelpers.EmitUndefined(generator);

                return;
            }

            if (Variable.IsHoisted(Scope))
            {
                // Hoist the variable:
                Variable = (Scope as DeclarativeScope).Function.Hoist(Variable);
            }

            // Output a get now:
            Variable.Get(generator);
        }
Example #9
0
 /// <summary>
 /// Pops the value on the stack, converts it to a javascript object, 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="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 ToPrototype(ILGenerator generator, Type fromType, string path, string function)
 {
     if (fromType == typeof(Nitrassic.Undefined))
     {
         // Converting from undefined always throws an exception.
         EmitHelpers.EmitThrow(generator, "TypeError", "Undefined cannot be converted to an object", path, function, 1);
     }
     else if (fromType == typeof(Nitrassic.Null))
     {
         // Converting from null always throws an exception.
         EmitHelpers.EmitThrow(generator, "TypeError", "Null cannot be converted to an object", path, function, 1);
     }
     else
     {
         // Otherwise, fall back to calling TypeConverter.ToPrototype()
         ToAny(generator, fromType);
         EmitHelpers.LoadEngine(generator);
         generator.Call(ReflectionHelpers.TypeConverter_ToPrototype);
     }
 }
Example #10
0
        /// <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));
            }
        }
Example #11
0
        /// <summary>
        /// Pushes the value of the reference onto the stack.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to output <c>null</c> instead. </param>
        public void GenerateGet(ILGenerator generator, OptimizationInfo optimizationInfo, bool throwIfUnresolvable)
        {
            if (ResolvedProperty == null)
            {
                // Dynamic access.

                // optimizationInfo.TypeError("Attempted to get a property dynamically. Currently unsupported.");

                // Load the left-hand side:
                var lhs = this.GetOperand(0);

                // -- Begin args for Prototype.GetPropertyValue --

                // Script engine (engine):
                EmitHelpers.LoadEngine(generator);

                // Emit LHS to the stack (thisObj):
                lhs.GenerateCode(generator, optimizationInfo);

                // What type have we now got on the stack? Expected to be just 'object'.
                Type lhsType = lhs.GetResultType(optimizationInfo);

                // Ensure it's boxed (still thisObj):
                EmitConversion.ToAny(generator, lhsType);

                // Load the property name and convert to a string (property).
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, rhs.GetResultType(optimizationInfo));

                // Get the value:
                generator.Call(ReflectionHelpers.Object_GetPropertyValue);

                // Either it's now on the stack, or we threw a null ref.
            }
            else if (isArrayIndex)
            {
                // Array indexer
                // -------------
                // xxx = object[index]

                // Load the left-hand side
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);

                // Load the right-hand side and convert to [theTypeHere] (typically int32).
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);

                // Convert the index:
                EmitConversion.Convert(generator, rhs.GetResultType(optimizationInfo), ResolvedProperty.FirstIndexType);

                // Emit a get for the indexer:
                ResolvedProperty.Get(generator);
            }
            else
            {
                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);

                if (ResolvedProperty != null)
                {
                    if (ResolvedProperty.HasEngine)
                    {
                        // Emit the engine ref:
                        EmitHelpers.LoadEngine(generator);
                    }

                    if (ResolvedProperty.HasAccessor)
                    {
                        // Emit the 'this' obj:
                        lhs.GenerateCode(generator, optimizationInfo);
                    }

                    // Emit a get:
                    ResolvedProperty.Get(generator);
                }
            }
        }
Example #12
0
        /// <summary>
        /// Stores the value on the top of the stack in the reference.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="valueType"> The primitive type of the value that is on the top of the stack. </param>
        /// <param name="throwIfUnresolvable"> <c>true</c> to throw a ReferenceError exception if
        /// the name is unresolvable; <c>false</c> to create a new property instead. </param>
        public void GenerateSet(ILGenerator generator, OptimizationInfo optimizationInfo, bool rIU, Type valueType, SetValueMethod value, bool throwIfUnresolvable)
        {
            if (ResolvedProperty == null)
            {
                // Dynamic property access
                // -----------------------
                // xxx = object.Set(x)

                // Load the left-hand side:
                var lhs = this.GetOperand(0);

                // -- Begin args for Prototype.SetPropertyValue --

                // Script engine (engine):
                EmitHelpers.LoadEngine(generator);

                // Put LHS object onto stack now (thisObj):
                lhs.GenerateCode(generator, optimizationInfo);

                // What type have we now got on the stack? Typically expected to be 'object'.
                Type lhsType = lhs.GetResultType(optimizationInfo);

                // Ensure it's boxed (still thisObj):
                EmitConversion.ToAny(generator, lhsType);

                // Load the property name and convert to a string.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, rhs.GetResultType(optimizationInfo));

                if (rIU)
                {
                    // Output the value now (twice):
                    value(true);

                    // We now have [obj][value][value] on the stack.
                    // Calling the set method would fail (as it'll operate on the duplicated value).
                    // So, we have to pop one off and re-add it after.

                    // In order for SetValue to work, we need to shove the 2nd copy into a temp variable.
                    ILLocalVariable localVar = generator.DeclareVariable(valueType);

                    // Store into the local:
                    generator.StoreVariable(localVar);

                    // Set the value:
                    generator.Call(ReflectionHelpers.Object_SetPropertyValue);

                    // Load from the local:
                    generator.LoadVariable(localVar);
                }
                else
                {
                    // Output the value now:
                    value(false);

                    // Set the value:
                    generator.Call(ReflectionHelpers.Object_SetPropertyValue);
                }
            }
            else if (isArrayIndex)
            {
                // Array indexer
                // -------------
                // object[index] = x

                // Load the left-hand side and convert to an object instance.
                var lhs = this.GetOperand(0);
                lhs.GenerateCode(generator, optimizationInfo);

                // Load the right-hand side and convert to int32/uint32/whatever the indexer function wants.
                var rhs = this.GetOperand(1);
                rhs.GenerateCode(generator, optimizationInfo);

                // Convert the index:
                EmitConversion.Convert(generator, rhs.GetResultType(optimizationInfo), ResolvedProperty.FirstIndexType);

                // Call set:
                ResolvedProperty.Set(generator, optimizationInfo, rIU, valueType, value);
            }
            else
            {
                // Named property modification (e.g. x.property = y)
                // -------------------------------------------------

                if (ResolvedProperty.HasEngine)
                {
                    // Emit the engine ref:
                    EmitHelpers.LoadEngine(generator);
                }

                if (ResolvedProperty.HasAccessor)
                {
                    // Load the left-hand side:
                    var lhs = GetOperand(0);
                    lhs.GenerateCode(generator, optimizationInfo);
                }

                // Target object is now on the stack.

                // Set it:
                ResolvedProperty.Set(generator, optimizationInfo, rIU, valueType, value);
            }
        }
Example #13
0
        /// <summary>
        /// Emits the given value.  Only possible for certain types.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="value"> The value to emit. </param>
        public static void EmitValue(ILGenerator generator, object value)
        {
            if (value == null)
            {
                generator.LoadNull();
            }
            else if (value is Nitrassic.Undefined)
            {
                EmitHelpers.EmitUndefined(generator);
            }
            else if (value is System.Reflection.MethodBase)
            {
                generator.LoadToken(value as System.Reflection.MethodBase);
                generator.Call(ReflectionHelpers.MethodBase_GetMethod);
            }
            else if (value is MethodGroup)
            {
                throw new NotImplementedException("Can't emit methodGroups here");
            }
            else if (value is FunctionMethodGenerator)
            {
                // body
                generator.LoadInt64((value as FunctionMethodGenerator).MethodID);
                generator.Call(ReflectionHelpers.MethodLookup_Load);
            }
            else
            {
                switch (Type.GetTypeCode(value.GetType()))
                {
                case TypeCode.Boolean:
                    generator.LoadBoolean((bool)value);
                    break;

                case TypeCode.Byte:
                    generator.LoadInt32((byte)value);
                    break;

                case TypeCode.Char:
                    generator.LoadInt32((char)value);
                    break;

                case TypeCode.Double:
                    generator.LoadDouble((double)value);
                    break;

                case TypeCode.Int16:
                    generator.LoadInt32((short)value);
                    break;

                case TypeCode.Int32:
                    generator.LoadInt32((int)value);
                    break;

                case TypeCode.Int64:
                    generator.LoadInt64((long)value);
                    break;

                case TypeCode.SByte:
                    generator.LoadInt32((sbyte)value);
                    break;

                case TypeCode.Single:
                    generator.LoadDouble((float)value);
                    break;

                case TypeCode.String:
                    generator.LoadString((string)value);
                    break;

                case TypeCode.UInt16:
                    generator.LoadInt32((ushort)value);
                    break;

                case TypeCode.UInt32:
                    generator.LoadInt32((uint)value);
                    break;

                case TypeCode.UInt64:
                    generator.LoadInt64((ulong)value);
                    break;

                case TypeCode.Object:
                case TypeCode.Empty:
                case TypeCode.DateTime:
                case TypeCode.DBNull:
                case TypeCode.Decimal:
                    throw new NotImplementedException(string.Format("Cannot emit the value '{0}' (a " + value.GetType() + ")", value));
                }
            }
        }
Example #14
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </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)
        {
            if (optimizationInfo.IsConstructor)
            {
                return;
            }

            // Emit the return value.
            Type returnType = ReturnType;

            // Determine if this is the last statement in the function.
            BlockStatement hostBlock = optimizationInfo.AbstractSyntaxTree as BlockStatement;

            bool lastStatement;

            if (hostBlock != null && hostBlock.Statements.Count > 0 &&
                hostBlock.Statements[hostBlock.Statements.Count - 1] == this)
            {
                lastStatement = true;
            }
            else
            {
                lastStatement = false;
            }

            // Current return var:
            var returnVar = optimizationInfo.ReturnVariable;

            if (Value != null)
            {
                // Emit the returned value:
                Value.GenerateCode(generator, optimizationInfo);

                // The first return statement initializes the variable that holds the return value.
                if (returnVar == null)
                {
                    if (!lastStatement)
                    {
                        returnVar = generator.DeclareVariable(returnType, "returnValue");
                        optimizationInfo.ReturnVariable = returnVar;
                    }
                }
            }
            else if (returnVar != null)
            {
                // We need to return undefined here, which will require changing the return type to object.

                // No value being set:
                EmitHelpers.EmitUndefined(generator);
            }

            if (returnVar != null)
            {
                // the return type here must be a child type of the return type.
                // If it isn't then this function returns different things.

                // Store the return value in a variable.
                generator.StoreVariable(returnVar);
            }

            // There is no need to jump to the end of the function if this is the last statement.
            if (!lastStatement)
            {
                // The first return statement that needs to branch creates the return label.  This is
                // defined in FunctionmethodGenerator.GenerateCode at the end of the function.
                if (optimizationInfo.ReturnTarget == null)
                {
                    optimizationInfo.ReturnTarget = generator.CreateLabel();
                }

                // Branch to the end of the function.  Note: the return statement might be branching
                // from inside a try { } or finally { } block to outside.  EmitLongJump() handles this.
                optimizationInfo.EmitLongJump(generator, optimizationInfo.ReturnTarget);
            }
        }
Example #15
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </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)
        {
            // Get the previous root - we'll be changing it:
            Expression prevRoot = optimizationInfo.RootExpression;

            List <string> labels = optimizationInfo.Labels;

            optimizationInfo.Labels = null;

            // Construct a loop expression.
            // var enumerator = TypeUtilities.EnumeratePropertyNames(rhs).GetEnumerator();
            // while (true) {
            //   continue-target:
            //   if (enumerator.MoveNext() == false)
            //	 goto break-target;
            //   lhs = enumerator.Current;
            //
            //   <body statements>
            // }
            // break-target:

            // Call IEnumerable<string> EnumeratePropertyNames(ScriptEngine engine, object obj)
            // optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan);
            EmitHelpers.LoadEngine(generator);
            this.TargetObject.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.TargetObject.GetResultType(optimizationInfo));
            generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames);

            // Store the enumerator in a temporary variable.
            var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <string>));

            generator.StoreVariable(enumerator);

            var breakTarget    = generator.CreateLabel();
            var continueTarget = generator.DefineLabelPosition();

            // Emit debugging information.
            // if (optimizationInfo.DebugDocument != null)
            //  generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan);

            //   if (enumerator.MoveNext() == false)
            //	 goto break-target;
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_MoveNext);
            generator.BranchIfFalse(breakTarget);

            // lhs = enumerator.Current;
            this.Variable.GenerateSet(generator, optimizationInfo, false, typeof(string), delegate(bool two){
                generator.LoadVariable(enumerator);
                generator.Call(ReflectionHelpers.IEnumerator_Current);

                if (two)
                {
                    generator.Duplicate();
                }
            }, false);



            // Emit the body statement(s).
            optimizationInfo.PushBreakOrContinueInfo(labels, breakTarget, continueTarget, false);

            // Mark the body as root:
            Body.SetRoot(optimizationInfo);

            Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.Branch(continueTarget);
            generator.DefineLabelPosition(breakTarget);

            // Restore root:
            optimizationInfo.RootExpression = prevRoot;
        }
Example #16
0
        /// <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)
        {
            // Get the target as a name expression:
            NameExpression nameExpr = Target as NameExpression;

            // Grab if this is a 'new' call:
            bool isConstructor = optimizationInfo.IsConstructCall;

            optimizationInfo.IsConstructCall = false;

            if (ResolvedMethod != null)
            {
                // We have a known method!

                if (UserDefined != null)
                {
                    if (isConstructor)
                    {
                        // Generate code to produce the "this" value.
                        Library.Prototype proto = UserDefined.GetInstancePrototype(optimizationInfo.Engine);

                        // Create the object now:
                        generator.NewObject(proto.TypeConstructor);

                        // Duplicate (which will act as our return value):
                        if (optimizationInfo.RootExpression != this)
                        {
                            generator.Duplicate();
                        }
                    }
                    else
                    {
                        // There are three cases for non-constructor calls.
                        if (this.Target is NameExpression)
                        {
                            // 1. The function is a name expression (e.g. "parseInt()").
                            //	In this case this = scope.ImplicitThisValue, if there is one, otherwise undefined.
                            ((NameExpression)this.Target).GenerateThis(generator);
                        }
                        else if (this.Target is MemberAccessExpression)
                        {
                            // 2. The function is a member access expression (e.g. "Math.cos()").
                            //	In this case this = Math.
                            var baseExpression = ((MemberAccessExpression)this.Target).Base;
                            baseExpression.GenerateCode(generator, optimizationInfo);
                            EmitConversion.ToAny(generator, baseExpression.GetResultType(optimizationInfo));
                        }
                        else
                        {
                            // 3. Neither of the above (e.g. "(function() { return 5 })()")
                            //	In this case this = undefined.
                            EmitHelpers.EmitUndefined(generator);
                        }
                    }
                }

                // Emit the rest of the args:
                EmitArguments(generator, optimizationInfo);

                // Got a return type?
                Type returnType = GetResultType(optimizationInfo);

                // Then the call!
                if (typeof(System.Reflection.ConstructorInfo).IsAssignableFrom(ResolvedMethod.GetType()))
                {
                    // Actual constructor call:
                    generator.NewObject(ResolvedMethod as System.Reflection.ConstructorInfo);
                }
                else
                {
                    // Ordinary method:
                    generator.Call(ResolvedMethod);
                }

                if (isConstructor)
                {
                    // Always a returned value here. Needed?
                    if (optimizationInfo.RootExpression == this)
                    {
                        // Remove the return value:
                        generator.Pop();
                    }
                }
                else
                {
                    if (returnType == typeof(Nitrassic.Undefined))
                    {
                        if (optimizationInfo.RootExpression != this)
                        {
                            // Put undef on the stack:
                            EmitHelpers.EmitUndefined(generator);
                        }
                    }
                    else if (optimizationInfo.RootExpression == this)
                    {
                        // Remove the return value:
                        generator.Pop();
                    }
                }
            }
            else
            {
                // Either runtime resolve it or it's not actually a callable function
                throw new NotImplementedException("A function was called which was not supported (" + ToString() + ")");
            }
        }
Example #17
0
        /// <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)
        {
            // Special-case the delete operator.
            if (this.OperatorType == OperatorType.Delete)
            {
                GenerateDelete(generator, optimizationInfo);
                return;
            }

            // Special-case the typeof operator.
            if (this.OperatorType == OperatorType.Typeof)
            {
                GenerateTypeof(generator, optimizationInfo);
                return;
            }

            // Load the operand onto the stack.
            this.Operand.GenerateCode(generator, optimizationInfo);

            // If we're not using the return value, pop and quit.
            if (optimizationInfo.RootExpression == this)
            {
                // Pop it and quit.
                generator.Pop();
                return;
            }

            // Convert the operand to the correct type.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
            case OperatorType.Minus:
                EmitConversion.ToNumber(generator, this.Operand.GetResultType(optimizationInfo));
                break;

            case OperatorType.BitwiseNot:
                EmitConversion.ToInt32(generator, this.Operand.GetResultType(optimizationInfo));
                break;

            case OperatorType.LogicalNot:
                EmitConversion.ToBool(generator, this.Operand.GetResultType(optimizationInfo));
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
                break;

            case OperatorType.Minus:
                generator.Negate();
                break;

            case OperatorType.BitwiseNot:
                generator.BitwiseNot();
                break;

            case OperatorType.LogicalNot:
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.Void:
                generator.Pop();
                EmitHelpers.EmitUndefined(generator);
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
        /// <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.");
            }
        }
Example #19
0
        /// <summary>
        /// Emits the arguments set.
        /// </summary>
        private void EmitArguments(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the args:
            IList <Expression> arguments        = null;
            Expression         argumentsOperand = null;

            if (OperandCount > 1)
            {
                argumentsOperand = this.GetRawOperand(1);
                ListExpression argList = argumentsOperand as ListExpression;

                if (argList != null)
                {
                    // Multiple parameters were recieved.
                    arguments = argList.Items;

                    // Set the operand to null so it doesn't try to emit it as a single arg:
                    argumentsOperand = null;
                }
            }

            int  paraCount       = 0;
            int  parameterOffset = 0;
            bool staticMethod    = false;

            System.Reflection.ParameterInfo[] paraSet = null;
            IList <ArgVariable> argsSet = null;


            if (UserDefined == null)
            {
                // - Is the first arg ScriptEngine?
                // - Does it have thisObj / does it want an instance object?
                paraSet = ResolvedMethod.GetParameters();

                paraCount = paraSet.Length;

                staticMethod = ResolvedMethod.IsStatic || ResolvedMethod.IsConstructor;

                if (paraSet.Length > 0)
                {
                    if (paraSet[0].ParameterType == typeof(ScriptEngine))
                    {
                        // Emit an engine reference now:
                        EmitHelpers.LoadEngine(generator);

                        parameterOffset++;
                    }

                    if (paraSet.Length > parameterOffset && paraSet[parameterOffset].Name == "thisObj")
                    {
                        // It's acting like an instance method.
                        parameterOffset++;
                        staticMethod = false;
                    }
                }

                if (!staticMethod)
                {
                    // Generate the 'this' ref:
                    var baseExpression = ((MemberAccessExpression)this.Target).Base;
                    baseExpression.GenerateCode(generator, optimizationInfo);
                }
            }
            else
            {
                // These are always static.
                paraCount = UserDefined.Arguments.Count;

                argsSet = UserDefined.Arguments;

                // Skip 'this' - it's emitted separately:
                parameterOffset = 1;
            }

            // Next, we're matching params starting from parameterOffset with the args,
            // type casting if needed.
            for (int i = parameterOffset; i < paraCount; i++)
            {
                Expression expression   = null;
                object     defaultValue = null;
                Type       paramType    = null;

                if (paraSet == null)
                {
                    // Get the type:
                    paramType = argsSet[i].Type;
                }
                else
                {
                    // Get the parameter info:
                    var param = paraSet[i];

                    // Get the parameters type:
                    paramType = param.ParameterType;

                    // Get the default value:
                    defaultValue = param.RawDefaultValue;

                    // Is it a params array?
                    if (Attribute.IsDefined(param, typeof(ParamArrayAttribute)))
                    {
                        // It's always an array - get the element type:
                        paramType = paramType.GetElementType();

                        // For each of the remaining args..
                        int offset = i - parameterOffset;

                        int argCount = 0;

                        if (arguments != null)
                        {
                            // Get the full count:
                            argCount = arguments.Count;
                        }
                        else if (argumentsOperand != null)
                        {
                            // Just one arg and it's still hanging around.
                            argCount = offset + 1;
                        }

                        // Define an array:
                        generator.LoadInt32(argCount);
                        generator.NewArray(paramType);

                        for (int a = offset; a < argCount; a++)
                        {
                            if (arguments != null)
                            {
                                // One of many args:
                                expression = arguments[a];
                            }
                            else
                            {
                                // Just one arg:
                                expression = argumentsOperand;
                            }

                            generator.Duplicate();
                            generator.LoadInt32(a - offset);
                            expression.GenerateCode(generator, optimizationInfo);
                            Type res = expression.GetResultType(optimizationInfo);

                            EmitConversion.Convert(generator, res, paramType);
                            generator.StoreArrayElement(paramType);
                        }

                        // All done - can't be anymore.
                        break;
                    }
                }

                if (arguments != null && (i - parameterOffset) <= arguments.Count)
                {
                    // Get one of many args:
                    expression = arguments[i - parameterOffset];
                }
                else if (argumentsOperand != null)
                {
                    // Just the one argument.
                    expression = argumentsOperand;

                    // By setting it to null after, it can't get emitted again
                    // (in the event that this method actually accepts >1 args)
                    argumentsOperand = null;
                }

                if (expression == null)
                {
                    // Emit whatever the default is for the parameters type:
                    if (defaultValue != null)
                    {
                        // Emit the default value:
                        EmitHelpers.EmitValue(generator, defaultValue);
                    }
                    else if (paramType.IsValueType)
                    {
                        // E.g. an integer 0
                        EmitHelpers.EmitValue(generator, Activator.CreateInstance(paramType));
                    }
                    else
                    {
                        // Just a null (a real one):
                        generator.LoadNull();
                    }
                }
                else if (expression is TemplateLiteralExpression)
                {
                    // Tagged template literal.
                    TemplateLiteralExpression templateLiteral = (TemplateLiteralExpression)expression;
                    GenerateTemplateArgumentsArray(generator, optimizationInfo, templateLiteral);
                    return;
                }
                else
                {
                    // Output the arg:
                    expression.GenerateCode(generator, optimizationInfo);

                    // Convert:
                    EmitConversion.Convert(generator, expression.GetResultType(optimizationInfo), paramType);
                }
            }
        }
Example #20
0
        /// <summary>
        /// Generates CIL for the logical operators.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateLogical(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If either evaluates statically to 0 then we also know the correct return type.
            object leftEval = Left.Evaluate();

            if (leftEval != null)
            {
                // RHS only.

                bool leftTrue = TypeConverter.ToBoolean(leftEval);

                // a && b
                // If a is false, don't do anything with b.
                // If a is true, emit b.
                // a || b
                // If a is false, emit b. If it's true, emit a.

                if (OperatorType == OperatorType.LogicalAnd && !leftTrue)
                {
                    // Don't evaluate the RHS. Just emit a 'false' if one is needed.
                    if (optimizationInfo.RootExpression != this)
                    {
                        // Emit the false:
                        generator.LoadBoolean(false);
                    }
                }
                else if (OperatorType == OperatorType.LogicalOr && leftTrue)
                {
                    // Emit the left object only.
                    if (optimizationInfo.RootExpression != this)
                    {
                        // Load it:
                        EmitHelpers.EmitValue(generator, leftEval);
                    }
                }
                else if (optimizationInfo.RootExpression == this)
                {
                    // Emitting b (no return type required).

                    // Right will be the root instead.
                    optimizationInfo.RootExpression = Right;
                    Right.GenerateCode(generator, optimizationInfo);
                    optimizationInfo.RootExpression = this;
                }
                else
                {
                    // Emitting b (return type required).

                    // Output required.
                    Right.GenerateCode(generator, optimizationInfo);
                }

                return;
            }

            // Evaluate B, just in case we're doing RHS only:
            object rightEval = Right.Evaluate();

            // Get the statically-determined types of the left and right operands.
            Type leftType  = this.Left.GetResultType(optimizationInfo);
            Type rightType = rightEval == null?this.Right.GetResultType(optimizationInfo) : rightEval.GetType();

            // Load the left-hand side operand.
            this.Left.GenerateCode(generator, optimizationInfo);

            // Make sure the output type is consistant.
            if (leftType != rightType)
            {
                if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                {
                    EmitConversion.ToNumber(generator, leftType);
                    leftType = typeof(double);
                }
                else
                {
                    EmitConversion.ToAny(generator, leftType);
                    leftType = typeof(object);
                }
            }

            // If this is an OR, we might be using the value currently on the stack if it's true.
            // So, duplicate:
            if (OperatorType == OperatorType.LogicalOr && optimizationInfo.RootExpression != this)
            {
                generator.Duplicate();
            }

            // Convert to a boolean:
            EmitConversion.ToBool(generator, leftType);

            // If this is an AND, we might be using the value currently on the stack if it's false.
            // So, duplicate:
            if (OperatorType == OperatorType.LogicalAnd && optimizationInfo.RootExpression != this)
            {
                generator.Duplicate();
            }

            // Stack contains:
            // OR: "left, (bool)left"
            // AND: "(bool)left, (bool)left"

            var endOfIf = generator.CreateLabel();

            if (this.OperatorType == OperatorType.LogicalAnd)
            {
                generator.BranchIfFalse(endOfIf);
            }
            else
            {
                generator.BranchIfTrue(endOfIf);
            }

            if (optimizationInfo.RootExpression == this)
            {
                // Right hand side will now be the root (output is not in use).
                optimizationInfo.RootExpression = Right;

                Right.GenerateCode(generator, optimizationInfo);

                // Restore:
                optimizationInfo.RootExpression = this;
            }
            else
            {
                // Stack contains "left" which we don't need if we fall through here. Pop it off:
                generator.Pop();

                // Output is in use.
                Right.GenerateCode(generator, optimizationInfo);

                // Make sure the output type is consistant.
                if (leftType != rightType)
                {
                    if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                    {
                        EmitConversion.ToNumber(generator, rightType);
                    }
                    else
                    {
                        EmitConversion.ToAny(generator, rightType);
                    }
                }
            }

            // Define the label used above.
            generator.DefineLabelPosition(endOfIf);
        }
Example #21
0
        /// <summary>
        /// Generates CIL for the instanceof operator.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateInstanceOf(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            if (optimizationInfo.RootExpression == this)
            {
                Left.GenerateCode(generator, optimizationInfo);
                Right.GenerateCode(generator, optimizationInfo);
                generator.Pop();
                generator.Pop();
                return;
            }

            // Emit the left-hand side expression and convert it to an object.
            this.Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Left.GetResultType(optimizationInfo));

            // Store the left-hand side expression in a temporary variable.
            var temp = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(temp);

            // Emit the right-hand side expression.
            this.Right.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Right.GetResultType(optimizationInfo));

            // Check the right-hand side is a function - if not, throw an exception.
            generator.IsInstance(typeof(Library.FunctionInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var rightValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(rightValue);
            EmitHelpers.LoadEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The instanceof operator expected a function, but found '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(rightValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.LoadInt32(1);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.LoadStringOrNull(optimizationInfo.FunctionName);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(rightValue);

            // Emit the engine for FunctionInstance_HasInstance:
            EmitHelpers.LoadEngine(generator);

            // Load the left-hand side expression from the temporary variable.
            generator.LoadVariable(temp);

            // Call FunctionInstance.HasInstance(object)
            generator.Call(ReflectionHelpers.FunctionInstance_HasInstance);

            // Allow the temporary variable to be reused.
            generator.ReleaseTemporaryVariable(temp);
        }