public override void VisitGetVariable(BoundGetVariable node) { base.VisitGetVariable(node); var temporary = node.Variable as BoundTemporary; if (temporary != null) MarkRead(temporary); }
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] )); } } }
public virtual void VisitGetVariable(BoundGetVariable node) { DefaultVisit(node); }
public override void VisitGetVariable(BoundGetVariable node) { MarkRead(node.Variable); }
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); }
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(); } }
private BoundValueType EmitGetVariable(BoundGetVariable node) { return EmitGetVariable(node.Variable); }
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(); }
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(); } }