Beispiel #1
0
        public ReadOnlyArray<JsonProperty> GetProperties()
        {
            var builder = new ReadOnlyArray<JsonProperty>.Builder();

            foreach (var assignment in _assignments)
            {
                if (assignment.Value.Mode == PropertyExpressionType.Data)
                {
                    builder.Add(new JsonDataProperty(
                        assignment.Key,
                        assignment.Value.Expression
                    ));
                }
                else
                {
                    builder.Add(new JsonAccessorProperty(
                        assignment.Key,
                        assignment.Value.GetExpression,
                        assignment.Value.SetExpression
                    ));
                }
            }

            return builder.ToReadOnly();
        }
Beispiel #2
0
        public static BoundProgram Perform(BoundProgram program, IList<BoundExpression> resultExpressions)
        {
            // If the last statement of the program is a return, we don't
            // have to rewrite the program.

            var body = program.Body;
            if (
                body.Body.Nodes.Count > 0 &&
                body.Body.Nodes[body.Body.Nodes.Count - 1] is BoundReturn
            )
                return program;

            // If we don't have any result expressions, we only have to
            // insert a return statement.

            if (resultExpressions == null || resultExpressions.Count == 0)
            {
                // Create a new nodes list with the added return statement.

                var nodes = new ReadOnlyArray<BoundStatement>.Builder();

                nodes.AddRange(body.Body.Nodes);
                nodes.Add(new BoundReturn(
                    null,
                    SourceLocation.Missing
                ));

                // Return the updated program.

                return program.Update(
                    body.Update(
                        body.Body.Update(
                            body.Body.Temporaries,
                            nodes.ToReadOnly(),
                            body.Body.Location
                            ),
                        body.Closure,
                        body.ScopedClosure,
                        body.Arguments,
                        body.Locals,
                        body.MappedArguments,
                        body.Flags,
                        body.TypeManager
                    )
                );
            }

            // Otherwise, we need to do a full rewrite.

            return program.Update(
                (BoundBody)new Rewriter(resultExpressions, body.TypeManager).Visit(program.Body)
            );
        }
Beispiel #3
0
            public override BoundNode VisitBody(BoundBody node)
            {
                node = (BoundBody)base.VisitBody(node);

                // Add the initialization of the result temporary and the
                // return statement.

                var nodes = new ReadOnlyArray<BoundStatement>.Builder(node.Body.Nodes.Count + 2);

                // We always add the default value. The reason for this is that
                // we're already passed the definite assignment phase, so it won't
                // be inserted for us automatically.

                nodes.Add(new BoundSetVariable(
                    _resultTemporary,
                    new BoundGetVariable(BoundMagicVariable.Undefined),
                    SourceLocation.Missing
                ));

                nodes.AddRange(node.Body.Nodes);

                nodes.Add(new BoundReturn(
                    new BoundGetVariable(_resultTemporary),
                    SourceLocation.Missing
                ));

                return node.Update(
                    node.Body.Update(
                        node.Body.Temporaries,
                        nodes.ToReadOnly(),
                        node.Body.Location
                    ),
                    node.Closure,
                    node.ScopedClosure,
                    node.Arguments,
                    node.Locals,
                    node.MappedArguments,
                    node.Flags,
                    node.TypeManager
                );
            }
Beispiel #4
0
            public override BoundNode Visit(BoundNode node)
            {
                var expression = node as BoundExpression;
                if (expression != null && _resultExpressions.Contains(expression))
                {
                    // Create a temporary to hold the result.

                    var temporary = new BoundTemporary(
                        --_lastTemporaryIndex,
                        _typeManager.CreateType(null, BoundTypeKind.Temporary)
                    );

                    var nodes = new ReadOnlyArray<BoundStatement>.Builder();

                    // Initialize the temporary with the expression.

                    nodes.Add(new BoundSetVariable(
                        temporary,
                        expression,
                        SourceLocation.Missing
                    ));

                    // Copy the temporary to the result.

                    nodes.Add(new BoundSetVariable(
                        _resultTemporary,
                        new BoundGetVariable(temporary),
                        SourceLocation.Missing
                    ));

                    // Return an expression block.

                    return new BoundExpressionBlock(
                        temporary,
                        new BoundBlock(
                            ReadOnlyArray<BoundTemporary>.CreateFrom(temporary),
                            nodes.ToReadOnly(),
                            SourceLocation.Missing
                        )
                    );
                }

                return base.Visit(node);
            }
Beispiel #5
0
            public override BoundNode VisitBlock(BoundBlock node)
            {
                // First check whether we have work.

                bool haveWork = false;

                foreach (var temporary in node.Temporaries)
                {
                    if (_statistics[temporary].ShouldReplace)
                    {
                        haveWork = true;
                        break;
                    }
                }

                // If we don't have work, just cascade.
                if (!haveWork)
                    return base.VisitBlock(node);

                // Create a new list of temporaries with the variables to be
                // squelched removed.
                var newTemporaries = new ReadOnlyArray<BoundTemporary>.Builder();
                foreach (var temporary in node.Temporaries)
                {
                    if (_statistics[temporary].ShouldReplace)
                        temporary.Type.MarkUnused();
                    else
                        newTemporaries.Add(temporary);
                }
                var temporaries = newTemporaries.ToReadOnly();

                // Rebuild the nodes with the new rules applied.
                var nodes = new ReadOnlyArray<BoundStatement>.Builder();

                foreach (var statement in node.Nodes)
                {
                    var setVariable = statement as BoundSetVariable;
                    if (setVariable != null)
                    {
                        setVariable = (BoundSetVariable)Visit(setVariable);

                        // If the set variable reduced to an assignment to itself,
                        // remove the set variable. This happens when the variable
                        // of the set variable is replaced.

                        var getVariable = setVariable.Value as BoundGetVariable;
                        if (getVariable != null && setVariable.Variable == getVariable.Variable)
                            continue;

                        // If we're going to squelch this local, remove the
                        // set variable for it.

                        var temporary = setVariable.Variable as BoundTemporary;
                        if (temporary != null && _statistics[temporary].ShouldRemove)
                            continue;
                    }

                    nodes.Add((BoundStatement)Visit(statement));
                }

                // Return the new block.

                return new BoundBlock(temporaries, nodes.ToReadOnly(), node.Location);
            }
            public BoundBlock BuildBlock(SourceLocation location)
            {
                if (_nodes == null)
                {
                    Debug.Assert(_temporaries == null);

                    return new BoundBlock(
                        ReadOnlyArray<BoundTemporary>.Empty,
                        ReadOnlyArray<BoundStatement>.Empty,
                        location
                    );
                }

                var nodes = new ReadOnlyArray<BoundStatement>.Builder();

                foreach (var node in _nodes.ToReadOnly())
                {
                    // Flatten blocks. Nested blocks have no use, so we flatten
                    // them into this block. First we try to see whether the node
                    // is a block. If not, we try to see whether the node is an
                    // expression statement that has an expression block
                    // as its expression. In that case, we're taking the value of
                    // an expression block without doing anything with it.

                    var block = node as BoundBlock;
                    if (block != null)
                    {
                        if (_temporaries == null)
                            _temporaries = new ReadOnlyArray<BoundTemporary>.Builder();

                        _temporaries.AddRange(block.Temporaries);
                        if (block.Location != SourceLocation.Missing)
                            nodes.Add(new BoundEmpty(block.Location));
                        nodes.AddRange(block.Nodes);
                        continue;
                    }

                    // Otherwise, we keep the node unchanged.
                    nodes.Add(node);
                }

                return new BoundBlock(
                    _temporaries == null ? ReadOnlyArray<BoundTemporary>.Empty : _temporaries.ToReadOnly(),
                    nodes.ToReadOnly(),
                    location
                );
            }
        private BoundStatement BuildThrow(string @class, string message)
        {
            var arguments = new ReadOnlyArray<BoundCallArgument>.Builder();

            if (message != null)
            {
                arguments.Add(new BoundCallArgument(
                    BoundConstant.Create(message),
                    false
                ));
            }

            _scope.IsGlobalScopeReferenced = true;

            // Build the throw.
            return new BoundThrow(
                // Instantiate the new error class.
                new BoundNew(
                    // Get the error class.
                    new BoundGetMember(
                        new BoundGetVariable(BoundMagicVariable.Global),
                        BoundConstant.Create(@class)
                    ),
                    // Pass the arguments (the message).
                    arguments.ToReadOnly(),
                    ReadOnlyArray<BoundExpression>.Empty
                ),
                SourceLocation.Missing
            );
        }