public BoundProgram Update(BoundBody body) { if (body == Body) return this; return new BoundProgram(body); }
public override void VisitBody(BoundBody node) { using (var marker = _typeManager.CreateDefiniteAssignmentMarker(_parentBranch)) { _branch = marker.CreateDefaultBranch(); var block = new Block(_branch, null, false, false, null); PushBlock(block); base.VisitBody(node); PopBlock(block); ResultExpressions = _branch.Expressions; // If the last statement of the body is a return, the return // provides the result expression and we don't have to track // the result expressions. if ( node.Body.Nodes.Count == 0 || node.Body.Nodes[node.Body.Nodes.Count - 1] is BoundReturn ) ResultExpressions = null; _branch.IsKilled = true; _branch = null; } }
public BoundProgram(BoundBody body) { if (body == null) throw new ArgumentNullException("body"); Body = body; }
private static BoundExpression[] Perform(BoundBody node, BoundTypeManager.DefiniteAssignmentMarker.Branch parentBranch) { var marker = new Marker(node.TypeManager, parentBranch); marker.Visit(node); return marker.ResultExpressions; }
public override void VisitBody(BoundBody node) { _scope = new Scope(node, _scope); using (_scope) { base.VisitBody(node); } _scope = _scope.Parent; }
public static ReadOnlyArray<BoundFunction> Gather(BoundBody body) { if (body == null) throw new ArgumentNullException("body"); var functions = new ReadOnlyArray<BoundFunction>.Builder(); new Gatherer(functions).Visit(body); return functions.ToReadOnlyArray(); }
public BoundFunction Update(string name, ReadOnlyArray<string> parameters, BoundBody body, SourceLocation location) { if ( name == Name && parameters == Parameters && body == Body && location == Location ) return this; return new BoundFunction(name, parameters, body, location); }
public BoundFunction(string name, ReadOnlyArray<string> parameters, BoundBody body, SourceLocation location) { if (parameters == null) throw new ArgumentNullException("parameters"); if (body == null) throw new ArgumentNullException("body"); if (location == null) throw new ArgumentNullException("location"); Name = name; Parameters = parameters; Body = body; Location = location; }
private static BoundBody Perform(BoundBody node) { if (node == null) throw new ArgumentNullException("node"); var statistics = new Dictionary<BoundTemporary, Statistics>(); new Gatherer(statistics).Visit(node); Validate(statistics); node = (BoundBody)new Rewriter(statistics).Visit(node); return node; }
public Scope(CodeGenerator generator, ILBuilder il, bool isFunction, BoundBody body, BoundClosureField argumentsClosureField, ITypeBuilder typeBuilder, Scope parent) { IL = il; ArgumentsClosureField = argumentsClosureField; Generator = generator; _isFunction = isFunction; _body = body; if (argumentsClosureField != null) ArgumentsEmitter = new ClosureFieldEmitter(generator, argumentsClosureField); TypeBuilder = typeBuilder; Parent = parent; _isStatic = TypeBuilder is IScriptBuilder; if (body.MappedArguments != null) _arguments = body.MappedArguments.ToDictionary(p => p.Argument, p => p.Mapped); BreakTargets = new Stack<NamedLabel>(); ContinueTargets = new Stack<NamedLabel>(); }
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 ); }
public virtual void VisitBody(BoundBody node) { DefaultVisit(node); }
public Scope(BoundBody body, Scope parent) { Parent = parent; _marker = body.TypeManager.CreateTypeMarker(); foreach (var argument in body.Arguments) { if (argument.Closure != null) MarkWrite(body.Closure.Fields[argument.Name], BoundValueType.Unknown); } if (body.MappedArguments != null) _arguments = body.MappedArguments.ToDictionary(p => p.Argument, p => p.Mapped); if (body.MappedArguments != null) { foreach (var mapping in body.MappedArguments) { MarkWrite(mapping.Mapped, BoundValueType.Unknown); } } if (body.Closure != null) { var argumentsClosureField = body.Closure.Fields.SingleOrDefault(p => p.Name == BoundClosure.ArgumentsFieldName); if (argumentsClosureField != null) MarkWrite(argumentsClosureField, BoundValueType.Object); } _magicTypes = body.TypeManager.MagicTypes.ToDictionary(p => p.MagicType, p => p.Type); foreach (var item in _magicTypes) { switch (item.Key) { case BoundMagicVariableType.Arguments: case BoundMagicVariableType.Global: _marker.SpeculateType(item.Value, SpeculatedType.Object, true); _marker.MarkWrite(item.Value, BoundValueType.Object); break; case BoundMagicVariableType.This: _marker.MarkWrite(item.Value, BoundValueType.Unknown); break; default: throw new InvalidOperationException(); } } }
private static void Perform(BoundBody body) { new Marker().Visit(body); }
private void EmitInitializeArguments(BoundBody body) { if (body.MappedArguments == null) return; foreach (var mapping in body.MappedArguments) { if (mapping.Mapped.Kind == BoundVariableKind.ClosureField) { // Closure fields are initialized on the closure, so if we // don't have the index in the arguments, we can just skip // the complete set. var after = IL.DefineLabel(); // Get the length of the arguments. _scope.EmitLoad(SpecialLocal.ArgumentsRaw); IL.Emit(OpCodes.Ldlen); // Emit the index we want. IL.EmitConstant(mapping.Argument.Index); // If arguments.Length <= index jump over the set. IL.Emit(OpCodes.Ble, after); EmitSetVariable( mapping.Mapped, new BoundEmitExpression( BoundValueType.Unknown, () => { // Push the arguments array onto the stack. _scope.EmitLoad(SpecialLocal.ArgumentsRaw); // Get the correct member from the arguments object. IL.EmitConstant(mapping.Argument.Index); // Load the element out of the array. IL.Emit(OpCodes.Ldelem, typeof(object)); } ) ); IL.MarkLabel(after); } else { // Otherwise, we move the branch into the getter because // if we don't have the index, we need to initialize the local // with undefined. EmitSetVariable( mapping.Mapped, new BoundEmitExpression( BoundValueType.Unknown, () => { var missingIndex = IL.DefineLabel(); var after = IL.DefineLabel(); // Get the length of the arguments. _scope.EmitLoad(SpecialLocal.ArgumentsRaw); IL.Emit(OpCodes.Ldlen); // Emit the index we want. IL.EmitConstant(mapping.Argument.Index); // If arguments.Length <= index jump over getting the // element from the array. IL.Emit(OpCodes.Ble, missingIndex); // Push the arguments array onto the stack. _scope.EmitLoad(SpecialLocal.ArgumentsRaw); // Get the correct member from the arguments object. IL.EmitConstant(mapping.Argument.Index); // Load the element out of the array. IL.Emit(OpCodes.Ldelem, typeof(object)); // Jump to the end of the if. IL.Emit(OpCodes.Br, after); // We're missing the index. IL.MarkLabel(missingIndex); // Load undefined. _scope.EmitLoad(SpecialLocal.Undefined); // Mark the end of the if. IL.MarkLabel(after); } ) ); } } }
private void EmitClosureSetup(BoundBody body) { Debug.Assert(body.Closure != null); var closure = body.Closure; // Check whether the constructor expects a parent. if (body.Closure.Parent != null) IL.Emit(OpCodes.Ldarg_0); // Instantiate the closure. IL.Emit(OpCodes.Newobj, closure.Builder.Constructor); // Store the reference to the closure in the scope. var closureLocal = IL.DeclareLocal(closure.Builder.Type); _scope.SetClosureLocal(closureLocal); IL.Emit(OpCodes.Stloc, closureLocal); }