Example #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);
        }
Example #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);
        }
Example #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);
        }