Exemple #1
0
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="keyword"> The keyword that was used to declare the variable (var, let or
        /// const). </param>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="hoistedFunction"> The function value to hoist to the top of the scope.
        /// Should be <c>null</c> for everything except function declarations. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal void DeclareVariable(KeywordToken keyword, string name, FunctionExpression hoistedFunction = null)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            // If variables cannot be declared in the scope, try the parent scope instead.
            var declarationScope = this;

            if (keyword == KeywordToken.Var)
            {
                while (declarationScope != null && (declarationScope.Type == ScopeType.Block || declarationScope.Type == ScopeType.With))
                {
                    declarationScope = declarationScope.ParentScope;
                }
            }

            if (declarationScope != null && !declarationScope.variables.ContainsKey(name))
            {
                // This is a local variable that has not been declared before.
                var variable = new DeclaredVariable()
                {
                    Scope   = declarationScope,
                    Index   = declarationScope.variables.Count,
                    Keyword = keyword,
                    Name    = name,
                };
                declarationScope.variables.Add(name, variable);
            }

            if (hoistedFunction != null)
            {
                var hoistedScope = this;
                while (hoistedScope != null && hoistedScope.Type == ScopeType.Block)
                {
                    hoistedScope = hoistedScope.ParentScope;
                }
                if (hoistedScope.hoistedFunctions == null)
                {
                    hoistedScope.hoistedFunctions = new Dictionary <string, FunctionExpression>();
                }
                hoistedScope.hoistedFunctions[name] = hoistedFunction;
            }
        }
Exemple #2
0
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="valueAtTopOfScope"> The value of the variable at the top of the scope.
        /// Can be <c>null</c> to indicate the variable does not need initializing. </param>
        /// <param name="writable"> <c>true</c> if the variable can be modified; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <param name="deletable"> <c>true</c> if the variable can be deleted; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal virtual DeclaredVariable DeclareVariable(string name, Expression valueAtTopOfScope = null, bool writable = true, bool deletable = false)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            // If variables cannot be declared in the scope, try the parent scope instead.
            if (this.CanDeclareVariables == false)
            {
                if (this.ParentScope == null)
                {
                    throw new InvalidOperationException("Invalid scope chain.");
                }
                return(this.ParentScope.DeclareVariable(name, valueAtTopOfScope, writable, deletable));
            }

            DeclaredVariable variable;

            this.variables.TryGetValue(name, out variable);
            if (variable == null)
            {
                // This is a local variable that has not been declared before.
                variable = new DeclaredVariable()
                {
                    Scope = this, Index = this.variables.Count, Name = name, Writable = writable, Deletable = deletable
                };
                this.variables.Add(name, variable);
            }

            // Set the initial value, if one was provided.
            if (valueAtTopOfScope != null)
            {
                // Function expressions override literals.
                if ((valueAtTopOfScope is LiteralExpression && variable.ValueAtTopOfScope is FunctionExpression) == false)
                {
                    variable.ValueAtTopOfScope = valueAtTopOfScope;
                }
            }

            return(variable);
        }
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="valueAtTopOfScope"> The value of the variable at the top of the scope.
        /// Can be <c>null</c> to indicate the variable does not need initializing. </param>
        /// <param name="writable"> <c>true</c> if the variable can be modified; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <param name="deletable"> <c>true</c> if the variable can be deleted; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal virtual DeclaredVariable DeclareVariable(string name, Expression valueAtTopOfScope = null, bool writable = true, bool deletable = false)
        {
            if (name == null)
                throw new ArgumentNullException("name");

            // If variables cannot be declared in the scope, try the parent scope instead.
            if (this.CanDeclareVariables == false)
            {
                if (this.ParentScope == null)
                    throw new InvalidOperationException("Invalid scope chain.");
                return this.ParentScope.DeclareVariable(name, valueAtTopOfScope, writable, deletable);
            }

            DeclaredVariable variable;
            this.variables.TryGetValue(name, out variable);
            if (variable == null)
            {
                // This is a local variable that has not been declared before.
                variable = new DeclaredVariable() { Scope = this, Index = this.variables.Count, Name = name, Writable = writable, Deletable = deletable };
                this.variables.Add(name, variable);
            }

            // Set the initial value, if one was provided.
            if (valueAtTopOfScope != null)
            {
                // Function expressions override literals.
                if ((valueAtTopOfScope is LiteralExpression && variable.ValueAtTopOfScope is FunctionExpression) == false)
                    variable.ValueAtTopOfScope = valueAtTopOfScope;
            }

            return variable;
        }