Esempio n. 1
0
        private BoundExpression BuildGet(ExpressionSyntax syntax, BoundTemporary withTarget)
        {
            switch (syntax.Type)
            {
                case SyntaxType.Identifier:
                    var identifier = ((IdentifierSyntax)syntax).Identifier;

                    if (identifier.Type == IdentifierType.Global)
                        _scope.IsGlobalScopeReferenced = true;

                    return BuildGet(identifier, withTarget);

                case SyntaxType.Property:
                    var property = (PropertySyntax)syntax;

                    return BuildGetMember(
                        BuildExpression(property.Expression),
                        BoundConstant.Create(property.Name)
                    );

                case SyntaxType.Indexer:
                    var indexer = (IndexerSyntax)syntax;

                    return BuildGetMember(
                        BuildGet(indexer.Expression, withTarget),
                        BuildExpression(indexer.Index)
                    );

                default:
                    return BuildExpression(syntax);
            }
        }
Esempio n. 2
0
            public Rewriter(IEnumerable<BoundExpression> resultExpressions, BoundTypeManager typeManager)
            {
                _typeManager = typeManager;
                _resultExpressions = new HashSet<BoundExpression>(resultExpressions);

                _resultTemporary = new BoundTemporary(
                    --_lastTemporaryIndex,
                    typeManager.CreateType(null, BoundTypeKind.Temporary)
                );
            }
Esempio n. 3
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);
            }
Esempio n. 4
0
            private void MarkRead(BoundTemporary temporary)
            {
                // Check if the local is still valid. If this temporary is
                // only written to from a local, it is eligible for replacement.
                // However, we can only do this when the local hasn't been
                // changed before we read the temporary. This is what is
                // checked below.

                var statistics = GetStatistic(temporary);
                if (statistics.WriteState == WriteType.Local && statistics.Value != null)
                {
                    var getVariable = statistics.Value.Expression as BoundGetVariable;
                    if (getVariable != null)
                    {
                        var local = getVariable.Variable as BoundLocal;
                        if (local != null)
                        {
                            int writeCount;
                            _variableWriteCount.TryGetValue(local, out writeCount);

                            if (writeCount != statistics.Value.WriteCount)
                                statistics.WriteState = WriteType.DoNotRemove;
                        }
                    }
                }


                statistics.Reads++;
            }
Esempio n. 5
0
            private Statistics GetStatistic(BoundTemporary temporary)
            {
                Statistics statistics;
                if (!_statistics.TryGetValue(temporary, out statistics))
                {
                    statistics = new Statistics();
                    _statistics.Add(temporary, statistics);
                }

                return statistics;
            }
Esempio n. 6
0
            public BoundTemporary CreateTemporary()
            {
                var result = new BoundTemporary(
                    _visitor._scope.GetNextTemporaryIndex(),
                    _visitor._scope.TypeManager.CreateType(null, BoundTypeKind.Temporary)
                );

                if (_temporaries == null)
                    _temporaries = new ReadOnlyArray<BoundTemporary>.Builder();

                _temporaries.Add(result);

                return result;
            }
Esempio n. 7
0
 public BoundExpression BuildExpression(BoundTemporary result, SourceLocation location)
 {
     return new BoundExpressionBlock(
         result,
         new BoundBlock(
             _temporaries == null ? ReadOnlyArray<BoundTemporary>.Empty : _temporaries.ToReadOnly(),
             _nodes == null ? ReadOnlyArray<BoundStatement>.Empty : _nodes.ToReadOnly(),
             location
         )
     );
 }
Esempio n. 8
0
        private BoundIf BuildSetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary value)
        {
            var withLocal = builder.CreateTemporary();

            builder.Add(new BoundSetVariable(
                withLocal,
                new BoundGetVariable(_withIdentifiers[withScope.Identifier]), SourceLocation.Missing
            ));

            var setter = new BoundSetMember(
                new BoundGetVariable(withLocal),
                BoundConstant.Create(fallback.Name),
                new BoundGetVariable(value),
                SourceLocation.Missing
            );

            BoundBlock @else;

            if (withScope.Parent == null)
            {
                @else = BuildBlock(BuildSet(
                    fallback,
                    new BoundGetVariable(value)
                ));
            }
            else
            {
                @else = BuildBlock(BuildSetWithScope(
                    builder,
                    withScope.Parent,
                    fallback,
                    value
                ));
            }

            return new BoundIf(
                new BoundHasMember(
                    new BoundGetVariable(withLocal),
                    fallback.Name
                ),
                BuildBlock(setter),
                @else,
                SourceLocation.Missing
            );
        }
Esempio n. 9
0
        private BoundIf BuildGetWithScope(BlockBuilder builder, WithScope withScope, IIdentifier fallback, BoundTemporary result, BoundTemporary withTarget)
        {
            var withLocal = builder.CreateTemporary();

            builder.Add(new BoundSetVariable(
                withLocal,
                new BoundGetVariable(_withIdentifiers[withScope.Identifier]),
                SourceLocation.Missing
            ));

            var getter = new BlockBuilder(this);

            if (withTarget != null)
            {
                getter.Add(new BoundSetVariable(
                    withTarget,
                    new BoundGetVariable(withLocal),
                    SourceLocation.Missing
                ));
            }

            getter.Add(new BoundSetVariable(
                result,
                BuildGetMember(
                    new BoundGetVariable(withLocal),
                    BoundConstant.Create(fallback.Name)
                ),
                SourceLocation.Missing
            ));

            BoundBlock @else;

            if (withScope.Parent == null)
            {
                @else = BuildBlock(new BoundSetVariable(
                    result,
                    BuildGet(
                        fallback,
                        null
                    ),
                    SourceLocation.Missing
                ));
            }
            else
            {
                @else = BuildBlock(BuildGetWithScope(
                    builder,
                    withScope.Parent,
                    fallback,
                    result,
                    withTarget
                ));
            }

            return new BoundIf(
                new BoundHasMember(
                    new BoundGetVariable(withLocal),
                    fallback.Name
                ),
                getter.BuildBlock(SourceLocation.Missing),
                @else,
                SourceLocation.Missing
            );
        }
Esempio n. 10
0
        private BoundExpression BuildGet(IIdentifier identifier, BoundTemporary withTarget)
        {
            switch (identifier.Type)
            {
                case IdentifierType.Null: return new BoundGetVariable(BoundMagicVariable.Null);
                case IdentifierType.Undefined: return new BoundGetVariable(BoundMagicVariable.Undefined);

                case IdentifierType.This:
                    _scope.IsThisReferenced = true;
                    return new BoundGetVariable(BoundMagicVariable.This);

                case IdentifierType.Arguments:
                    _scope.IsArgumentsReferenced = true;
                    return new BoundGetVariable(BoundMagicVariable.Arguments);

                case IdentifierType.Parameter:
                    return new BoundGetVariable(_scope.GetArgument(identifier));

                case IdentifierType.Scoped:
                    var builder = new BlockBuilder(this);
                    var result = builder.CreateTemporary();

                    builder.Add(
                        BuildGetWithScope(builder, identifier.WithScope, identifier.Fallback, result, withTarget)
                    );

                    return builder.BuildExpression(result, SourceLocation.Missing);

                case IdentifierType.Local:
                case IdentifierType.Global:
                    if (identifier.Closure != null)
                        return new BoundGetVariable(_scope.GetClosureField(identifier));

                    return new BoundGetVariable(_scope.GetLocal(identifier));

                default:
                    throw new InvalidOperationException("Cannot find variable of argument");
            }
        }