public Expression Store(Variable v, Expression value) { Field field; if (VariableFields.TryGetValue(v, out field)) { return(new StoreField(Source.Unknown, Expression, field, value)); } if (Parent == null) { throw new InvalidOperationException("ClosureConversionTransform: No matching closure field for local " + v); } return(Parent.Store(v, value)); }
Closure CreateClosure(Closure parent, HashSet <Variable> locals) { if (parent != null && locals.Count == 0) { return(parent); } var type = new ClassType( Source.Unknown, Function.DeclaringType, Function.Name + " lambda closure", Modifiers.Private | Modifiers.Generated, Function.DeclaringType.GetUniqueIdentifier(Function.Name + "_$closure")); type.SetBase(Essentials.Object); var constrBody = new Scope( Source.Unknown, new CallConstructor(Source.Unknown, Essentials.Object.TryGetConstructor())); type.Constructors.Add( new Constructor( Source.Unknown, type, "", Modifiers.Public | Modifiers.Generated, ParameterList.Empty, constrBody)); Function.DeclaringType.NestedTypes.Add(type); _generatedTypes.Add(type); var decl = new VariableDeclaration( Source.Unknown, Function, Function.DeclaringType.GetUniqueIdentifier("generated_closure"), type, optionalValue: ILFactory.NewObject(type)); var statements = new List <Statement>(); statements.Add(decl); var result = new Closure(type, statements, new LoadLocal(Source.Unknown, decl.Variable), parent); // The root closure gets 'this' and the params if (parent == null) { if (_closureVars.This) { var field = new Field( Source.Unknown, type, type.GetUniqueIdentifier("self"), "", Modifiers.Public | Modifiers.Generated, 0, Function.DeclaringType); type.Fields.Add(field); statements.Add(result.StoreThis(new This(Function.DeclaringType))); } foreach (var p in _closureVars.Params) { var field = new Field( p.Source, type, type.GetUniqueIdentifier(p.Name), "", Modifiers.Public | Modifiers.Generated, 0, p.Type); type.Fields.Add(field); result.ParameterFields[p] = field; statements.Add(result.Store(p, new LoadArgument(Source.Unknown, Function, ParamIndex(p)))); } } // Non-root closures get a parent field for the parent closure else { type.Fields.Add( new Field( Source.Unknown, type, type.GetUniqueIdentifier("parent"), "", Modifiers.Public | Modifiers.Generated, 0, parent.Type)); statements.Add(result.StoreParent(parent.Expression)); } foreach (var v in locals) { var field = new Field( v.Source, type, type.GetUniqueIdentifier(v.Name), "", Modifiers.Public | Modifiers.Generated, 0, v.ValueType); type.Fields.Add(field); result.VariableFields[v] = field; } return(result); }