Пример #1
0
            public override void VisitGetVariable(BoundGetVariable node)
            {
                base.VisitGetVariable(node);

                var temporary = node.Variable as BoundTemporary;
                if (temporary != null)
                    MarkRead(temporary);
            }
Пример #2
0
            public void EmitLocals(BoundTypeManager typeManager)
            {
                _magicTypes = _body.TypeManager.MagicTypes.ToDictionary(p => p.MagicType, p => p.Type);

                // Create the arguments local if it's required and there isn't
                // a closure field for it.

                if ((_body.Flags & BoundBodyFlags.ArgumentsReferenced) != 0 && ArgumentsEmitter == null)
                {
                    var type = _magicTypes[BoundMagicVariableType.Arguments];

                    var argumentsEmitter = CreateEmitter(type);
                    argumentsEmitter.DeclareLocal();

                    ArgumentsEmitter = argumentsEmitter;

                    _locals.Add(type, argumentsEmitter);
                }

                if ((_body.Flags & BoundBodyFlags.GlobalReferenced) != 0)
                {
                    _globalLocal = IL.DeclareLocal(typeof(JsGlobal));

                    EmitLoad(SpecialLocal.Runtime);
                    IL.EmitCall(_runtimeGetGlobal);
                    IL.Emit(OpCodes.Stloc, _globalLocal);
                }

                if ((_body.Flags & BoundBodyFlags.GlobalScopeReferenced) != 0)
                {
                    var type = _magicTypes[BoundMagicVariableType.Global];

                    GlobalScopeEmitter = CreateEmitter(type);
                    GlobalScopeEmitter.DeclareLocal();
                    GlobalScopeEmitter.EmitSetValue(new BoundEmitExpression(
                        BoundValueType.Object,
                        () =>
                        {
                            EmitLoad(SpecialLocal.Runtime);
                            IL.EmitCall(_runtimeGetGlobalScope);
                        }
                    ));

                    _locals.Add(type, GlobalScopeEmitter);
                }

                if ((_body.Flags & BoundBodyFlags.ThisReferenced) != 0)
                {
                    // We can't set assign to _thisLocal because then EmitLoad
                    // would return the local.

                    var type = _magicTypes[BoundMagicVariableType.This];

                    var thisLocal = CreateEmitter(type);
                    thisLocal.DeclareLocal();
                    thisLocal.EmitSetValue(new BoundEmitExpression(
                        BoundValueType.Unknown,
                        () => EmitLoad(SpecialLocal.This)
                    ));

                    _thisLocal = thisLocal;

                    _locals.Add(type, _thisLocal);
                }

                var getUnknown = new BoundGetVariable(BoundMagicVariable.Undefined);

                foreach (var type in typeManager.Types)
                {
                    if (type.Type == BoundValueType.Unset)
                        continue;

                    if (type.Kind == BoundTypeKind.Local || type.Kind == BoundTypeKind.Temporary)
                    {
                        var emitter = CreateEmitter(type);

                        emitter.DeclareLocal();

                        if (type.Kind == BoundTypeKind.Local)
                            emitter.Local.SetLocalSymInfo(type.Name);

                        if (!type.DefinitelyAssigned)
                            emitter.EmitSetValue(getUnknown);

                        _locals.Add(type, emitter);
                    }
                    else if (type.Kind == BoundTypeKind.ClosureField)
                    {
                        _locals.Add(type, new ClosureFieldEmitter(
                            Generator,
                            Closure.Fields[type.Name]
                        ));
                    }
                }
            }
Пример #3
0
 public virtual void VisitGetVariable(BoundGetVariable node)
 {
     DefaultVisit(node);
 }
Пример #4
0
 public override void VisitGetVariable(BoundGetVariable node)
 {
     MarkRead(node.Variable);
 }
Пример #5
0
            public override BoundNode VisitGetVariable(BoundGetVariable node)
            {
                // Return the associated expression of the temporary if we're
                // going to squelch the temporary.

                var temporary = node.Variable as BoundTemporary;
                if (temporary != null)
                {
                    var statistic = _statistics[temporary];
                    if (statistic.ShouldReplace)
                        return statistic.Value.Expression.Accept(this);
                }

                return base.VisitGetVariable(node);
            }
Пример #6
0
        private BoundValueType EmitGetVariable(IBoundReadable variable)
        {
            switch (variable.Kind)
            {
                case BoundVariableKind.Global:
                    return _scope.GlobalScopeEmitter.EmitGetMember(new BoundGetMember(
                        new BoundGetVariable(BoundMagicVariable.Global),
                        BoundConstant.Create(((BoundGlobal)variable).Name)
                    ));

                case BoundVariableKind.Local:
                case BoundVariableKind.Temporary:
                case BoundVariableKind.ClosureField:
                    _scope.GetEmitter(variable).EmitGetValue();
                    return variable.ValueType;

                case BoundVariableKind.Magic:
                    switch (((BoundMagicVariable)variable).VariableType)
                    {
                        case BoundMagicVariableType.Global: return _scope.EmitLoad(SpecialLocal.GlobalScope);
                        case BoundMagicVariableType.This: return _scope.EmitLoad(SpecialLocal.This);
                        case BoundMagicVariableType.Null: return _scope.EmitLoad(SpecialLocal.Null);
                        case BoundMagicVariableType.Undefined: return _scope.EmitLoad(SpecialLocal.Undefined);
                        case BoundMagicVariableType.Arguments: return _scope.EmitLoad(SpecialLocal.Arguments);
                        default: throw new InvalidOperationException();
                    }

                case BoundVariableKind.Argument:
                    var argument = (BoundArgument)variable;

                    // Check whether the argument is mapped to a local or closure
                    // field.

                    var scope = argument.Closure == null ? _scope : _scope.FindScope(argument.Closure);
                    var mappedArgument = scope.GetMappedArgument(argument);
                    if (mappedArgument != null)
                        return EmitGetVariable(mappedArgument);

                    BoundGetVariable getVariable;
                    if (scope.ArgumentsClosureField != null)
                        getVariable = new BoundGetVariable(scope.ArgumentsClosureField);
                    else
                        getVariable = new BoundGetVariable(BoundMagicVariable.Arguments);

                    EmitGetMember(new BoundGetMember(
                        getVariable,
                        BoundConstant.Create((double)argument.Index)
                    ));

                    return BoundValueType.Unknown;

                default:
                    throw new InvalidOperationException();
            }
        }
Пример #7
0
 private BoundValueType EmitGetVariable(BoundGetVariable node)
 {
     return EmitGetVariable(node.Variable);
 }
Пример #8
0
        private void EmitSwitch(BoundSwitch node)
        {
            // Create the label that jumps to the end of the switch.
            var after = IL.DefineLabel(GetLabel(node));
            _scope.BreakTargets.Push(after);

            // Create the bound node to get the temporary.
            var temporaryNode = new BoundGetVariable(node.Temporary);

            var bodies = new List<Tuple<Label, BoundBlock>>();

            // Emit the jump table.

            Label? defaultTarget = null;

            foreach (var @case in node.Cases)
            {
                if (@case.Expression == null)
                {
                    IL.MarkSequencePoint(@case.Location);

                    defaultTarget = IL.DefineLabel();

                    bodies.Add(Tuple.Create(defaultTarget.Value, @case.Body));
                }
                else
                {
                    var target = IL.DefineLabel();

                    IL.MarkSequencePoint(@case.Location);

                    EmitTest(
                        new BoundBinary(
                            BoundExpressionType.Equal,
                            temporaryNode,
                            @case.Expression
                        ),
                        target
                    );

                    bodies.Add(Tuple.Create(target, @case.Body));
                }
            }

            // Emit the jump to either the default block or after the switch.

            IL.Emit(OpCodes.Br, defaultTarget.GetValueOrDefault(after.Label));

            // Emit the bodies.

            foreach (var body in bodies)
            {
                IL.MarkLabel(body.Item1);

                EmitStatement(body.Item2);
            }

            // Emit the label after the switch.

            IL.MarkLabel(after);

            // Pop the break target to make the previous one available.
            _scope.BreakTargets.Pop();
        }
Пример #9
0
        private void EmitSetVariable(IBoundWritable variable, BoundExpression value)
        {
            switch (variable.Kind)
            {
                case BoundVariableKind.Global:
                    _scope.GlobalScopeEmitter.EmitSetMember(new BoundSetMember(
                        new BoundGetVariable(BoundMagicVariable.Global),
                        BoundConstant.Create(((BoundGlobal)variable).Name),
                        value,
                        SourceLocation.Missing
                    ));
                    break;

                case BoundVariableKind.Local:
                case BoundVariableKind.Temporary:
                case BoundVariableKind.ClosureField:
                    _scope.GetEmitter(variable).EmitSetValue(value);
                    break;

                case BoundVariableKind.Argument:
                    var argument = (BoundArgument)variable;

                    // Check whether the argument is mapped to a local or closure
                    // field.

                    var scope = argument.Closure == null ? _scope : _scope.FindScope(argument.Closure);
                    var mappedArgument = scope.GetMappedArgument(argument);
                    if (mappedArgument != null)
                    {
                        EmitSetVariable(mappedArgument, value);
                        return;
                    }

                    BoundGetVariable getVariable;
                    if (scope.ArgumentsClosureField != null)
                        getVariable = new BoundGetVariable(scope.ArgumentsClosureField);
                    else
                        getVariable = new BoundGetVariable(BoundMagicVariable.Arguments);

                    EmitSetMember(new BoundSetMember(
                        getVariable,
                        BoundConstant.Create((double)argument.Index),
                        value,
                        SourceLocation.Missing
                    ));
                    return;

                default:
                    throw new InvalidOperationException();
            }
        }