예제 #1
0
    public override AstNode ShallowClone()
    {
        var res = new AstDestructuring(Source, Start, End, IsArray);

        res.Names.AddRange(Names.AsReadOnlySpan());
        return(res);
    }
예제 #2
0
        protected override void Visit(AstNode node)
        {
            if (node is IMayBeBlockScope blockScope && blockScope.IsBlockScope)
            {
                var saveScope = _currentScope;
                blockScope.BlockScope = _currentScope = new AstScope(node);
                _currentScope.InitScopeVars(saveScope);
                if (!(node is AstScope))
                {
                    _currentScope.UsesWith = saveScope.UsesWith;
                    _currentScope.UsesEval = saveScope.UsesEval;
                    _currentScope.HasUseStrictDirective = saveScope.HasUseStrictDirective;
                }

                DescendOnce();
                _currentScope = saveScope;
                return;
            }

            if (node is AstDestructuring destructuring)
            {
                _inDestructuring = destructuring; // These don't nest
                DescendOnce();
                _inDestructuring = null;
                return;
            }

            if (node is AstScope astScope)
            {
                astScope.InitScopeVars(_currentScope);
                var saveScope  = _currentScope;
                var saveDefun  = _defun;
                var saveLabels = _labels;
                _labels = new Dictionary <string, AstLabel>();
                _defun  = _currentScope = astScope;
                DescendOnce();
                _defun        = saveDefun;
                _currentScope = saveScope;
                _labels       = saveLabels;
                return;
            }

            if (node is AstLabeledStatement labeledStatement)
            {
                var l = labeledStatement.Label;
                if (!_labels.TryAdd(l.Name, l))
                {
                    throw new Exception($"Label {l.Name} defined twice");
                }

                DescendOnce();
                _labels.Remove(l.Name);
                return;
            }

            if (node is AstWith)
            {
                for (var s = _currentScope; s != null; s = s.ParentScope)
                {
                    s.UsesWith = true;
                }

                return;
            }

            if (node is AstSymbol astSymbol)
            {
                astSymbol.Scope = _currentScope;
            }

            if (node is AstLabel astLabel)
            {
                astLabel.References = new StructList <AstLoopControl>();
            }
            else if (node is AstSymbolLambda astSymbolLambda)
            {
                _defun.DefFunction(astSymbolLambda, astSymbolLambda.Name == "arguments" ? null : _defun);
            }
            else if (node is AstSymbolDefun astSymbolDefun)
            {
                // This should be defined in the parent scope, as we encounter the
                // AstDefun node before getting to its AstSymbol.
                MarkExport((astSymbolDefun.Scope = _defun.ParentScope.Resolve()).DefFunction(astSymbolDefun, _defun),
                           1);
            }
            else if (node is AstSymbolClass)
            {
                MarkExport(_defun.DefVariable((AstSymbol)node, _defun), 1);
            }
            else if (node is AstSymbolImport)
            {
                _currentScope.DefVariable((AstSymbol)node, null);
            }
            else if (node is AstSymbolDefClass)
            {
                // This deals with the name of the class being available
                // inside the class.
                MarkExport((((AstSymbol)node).Scope = _defun.ParentScope).DefFunction((AstSymbol)node, _defun), 1);
            }
            else if (node is AstSymbolVar ||
                     node is AstSymbolLet ||
                     node is AstSymbolConst)
            {
                SymbolDef def;
                if (node is AstSymbolBlockDeclaration)
                {
                    def = _currentScope.DefVariable((AstSymbol)node, null);
                }
                else
                {
                    def = _defun.DefVariable((AstSymbol)node, null);
                }

                if (!def.Orig.All(sym =>
                {
                    if (sym == node)
                    {
                        return(true);
                    }
                    if (node is AstSymbolBlockDeclaration)
                    {
                        return(sym is AstSymbolLambda);
                    }

                    return(!(sym is AstSymbolLet || sym is AstSymbolConst));
                }))
                {
                    throw new Exception(((AstSymbol)node).Name + " redeclared");
                }

                MarkExport(def, 2);
                def.Destructuring = _inDestructuring;
                if (_defun != _currentScope)
                {
                    ((AstSymbol)node).MarkEnclosed(_options);
                    var def2 = _currentScope.FindVariable((AstSymbol)node);
                    if (((AstSymbol)node).Thedef != def2)
                    {
                        ((AstSymbol)node).Thedef = def2;
                        ((AstSymbol)node).Reference(_options);
                    }
                }
            }
            else if (node is AstSymbolCatch astSymbolCatch)
            {
                _currentScope.DefVariable(astSymbolCatch, null).Defun = _defun;
            }
            else if (node is AstLabelRef labelRef)
            {
                if (_labels.TryGetValue(labelRef.Name, out var sym))
                {
                    labelRef.Thedef = sym;
                }
                else
                {
                    throw new Exception(
                              $"Undefined label {labelRef.Name} [{labelRef.Start.Line},{labelRef.Start.Column}]");
                }
            }

            if (!(_currentScope is AstToplevel) && (node is AstExport || node is AstImport))
            {
                throw new Exception(node.PrintToString() + " statement may only appear at top level");
            }
        }
예제 #3
0
파일: LVal.cs 프로젝트: pombredanne/bbcore
        AstNode ToAssignable([CanBeNull] AstNode node, bool isBinding = false)
        {
            if (Options.EcmaVersion >= 6 && node != null)
            {
                switch (node)
                {
                case AstSymbol identifierNode:
                    if (_inAsync && identifierNode.Name == "await")
                    {
                        Raise(node.Start, "Can not use 'await' as identifier inside an async function");
                    }
                    break;

                case AstPropAccess _:
                    if (!isBinding)
                    {
                        break;
                    }
                    goto default;

                case AstDestructuring _:
                    break;

                case AstObject objectExpression:
                    var newProperties = new StructList <AstNode>();
                    newProperties.Reserve(objectExpression.Properties.Count);
                    for (var i = 0; i < newProperties.Count; i++)
                    {
                        newProperties[(uint)i] = ToAssignable(objectExpression.Properties[(uint)i], isBinding);
                    }
                    node = new AstDestructuring(this, node.Start, node.End, ref newProperties, false);
                    break;

                case AstArray arrayExpression:
                    ToAssignableList(ref arrayExpression.Elements, isBinding);
                    node = new AstDestructuring(this, node.Start, node.End, ref arrayExpression.Elements, true);
                    break;

                case AstExpansion spreadElement:
                    spreadElement.Expression = ToAssignable(spreadElement.Expression, isBinding);
                    if (spreadElement.Expression is AstDefaultAssign)
                    {
                        Raise(spreadElement.Expression.Start, "Rest elements cannot have a default value");
                    }

                    break;

                case AstAssign assignmentExpression:
                    if (assignmentExpression.Operator != Operator.Assignment)
                    {
                        Raise(assignmentExpression.Left.End,
                              "Only '=' operator can be used for specifying default value.");
                    }

                    var left  = ToAssignable(assignmentExpression.Left, isBinding);
                    var right = assignmentExpression.Right;
                    node = new AstDefaultAssign(this, node.Start, node.End, left, right);
                    goto AssignmentPatternNode;

                case AstDefaultAssign _:
AssignmentPatternNode:
                    break;

                default:
                    Raise(node.Start, "Assigning to rvalue");
                    break;
                }
            }

            return(node);
        }