Esempio n. 1
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 we have allocated an IL variable, use it.
            var variableInfo = Scope.FindStaticVariable(Name);

            if (variableInfo != null && variableInfo.Store != null)
            {
                generator.LoadVariable(variableInfo.Store);
                if (variableInfo.Keyword != KeywordToken.Var)
                {
                    var afterIf = generator.CreateLabel();
                    generator.Duplicate();
                    generator.BranchIfNotNull(afterIf);
                    EmitHelpers.EmitThrow(generator, ErrorType.ReferenceError, $"Cannot access '{Name}' before initialization.");
                    generator.DefineLabelPosition(afterIf);
                }
                return;
            }

            // Fallback: call RuntimeScope.GetValue() or RuntimeScope.GetValueNoThrow().
            Scope.GenerateReference(generator, optimizationInfo);
            generator.LoadString(Name);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.Call(throwIfUnresolvable ? ReflectionHelpers.RuntimeScope_GetValue : ReflectionHelpers.RuntimeScope_GetValueNoThrow);
        }
Esempio n. 2
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>
        public void GenerateSet(ILGenerator generator, OptimizationInfo optimizationInfo, PrimitiveType valueType)
        {
            // TODO: Optimize this.
            //
            // ++ or --
            // GenerateReference
            // DuplicateReference
            // GenerateGet
            // ToNumber
            // if (postfix) Dup/Store in variable
            // Increment/Decrement
            // if (prefix) Dup/Store in variable
            // GenerateSet
            // Load variable
            //
            // +=
            // GenerateReference
            // DuplicateReference
            // GenerateGet
            // Dup/Store in variable
            // GenerateSet
            // Load variable
            //
            // for (in/of)
            // GenerateReference
            // LoadVariable(enumerator)
            // GenerateGet
            // GenerateSet
            //
            // =
            // GenerateReference
            // target.GenerateGet
            // Dup/Store in variable
            // GenerateSet
            // Load variable

            // If we have allocated an IL variable, use it.
            var variableInfo = Scope.FindStaticVariable(Name);

            if (variableInfo != null && variableInfo.Store != null)
            {
                EmitConversion.Convert(generator, valueType, variableInfo.Type);
                generator.StoreVariable(variableInfo.Store);
                return;
            }

            // Fallback: call RuntimeScope.SetValue() or RuntimeScope.SetValueStrict().
            var temp = generator.CreateTemporaryVariable(valueType);

            generator.StoreVariable(temp);
            Scope.GenerateReference(generator, optimizationInfo);
            generator.LoadString(Name);
            generator.LoadVariable(temp);
            EmitConversion.ToAny(generator, valueType);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.Call(optimizationInfo.StrictMode ? ReflectionHelpers.RuntimeScope_SetValueStrict : ReflectionHelpers.RuntimeScope_SetValue);
            generator.ReleaseTemporaryVariable(temp);
        }
Esempio n. 3
0
        /// <summary>
        /// Deletes the reference and pushes <c>true</c> if the delete succeeded, or <c>false</c>
        /// if the delete failed.
        /// </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 void GenerateDelete(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Deleting a variable is not allowed in strict mode.
            if (optimizationInfo.StrictMode == true)
            {
                throw new SyntaxErrorException($"Cannot delete {Name} because deleting a variable or argument is not allowed in strict mode", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName);
            }

            // If we have allocated an IL variable, then always return false, as we don't support
            // optimizing deletable variables.
            var variableInfo = Scope.FindStaticVariable(Name);

            if (variableInfo != null && variableInfo.Store != null)
            {
                generator.LoadBoolean(false);
                return;
            }

            Scope.GenerateReference(generator, optimizationInfo);
            generator.LoadString(Name);
            generator.Call(ReflectionHelpers.RuntimeScope_Delete);
        }
Esempio n. 4
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)
        {
            // Generate a new method.
            this.context.GenerateCode();

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

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            string prefix = null;

            if (Name.IsGetter)
            {
                prefix = "get ";
            }
            else if (Name.IsSetter)
            {
                prefix = "set ";
            }
            if (Name.HasStaticName)
            {
                generator.LoadString(prefix + Name.StaticName);
            }
            else
            {
                // Compute the name at runtime.
                if (prefix != null)
                {
                    generator.LoadString(prefix);
                }
                Name.ComputedName.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, Name.ComputedName.ResultType);
                if (prefix != null)
                {
                    generator.CallStatic(ReflectionHelpers.String_Concat_String_String);
                }
            }

            // argumentNames
            generator.LoadInt32(this.Arguments.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Arguments.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.Arguments[i].Name);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            Scope.GenerateReference(generator, optimizationInfo);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);

            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // container
            if (ContainerVariable != null)
            {
                generator.LoadVariable(ContainerVariable);
            }
            else
            {
                generator.LoadNull();
            }

            // CreateFunction(ObjectInstance prototype, string name, IList<string> argumentNames,
            //   RuntimeScope scope, Func<Scope, object, object[], object> body,
            //   bool strictMode, FunctionInstance container)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateFunction);
        }