internal MSAst.Expression Transform(AstGenerator inner, bool needsWrapperMethod, bool needsLocalsDictionary, List<MSAst.Expression> init) { string name = SymbolTable.IdToString(Name); if (_variable.AccessedInNestedScope || needsLocalsDictionary) { ClosureExpression closureVar; if (needsWrapperMethod) { closureVar = inner.LiftedVariable(Variable, name, _variable.AccessedInNestedScope); } else { closureVar = inner.LiftedParameter(Variable, name); } inner.SetLocalLiftedVariable(_variable, closureVar); init.Add(closureVar.Create()); return closureVar; } else { MSAst.Expression parameter; if (needsWrapperMethod) { parameter = inner.Variable(typeof(object), name); } else { parameter = inner.Parameter(typeof(object), name); } inner.Globals.SetParameter(_variable, parameter); return parameter; } }
public MSAst.Expression/*!*/ CreateVariable(AstGenerator/*!*/ ag, PythonVariable/*!*/ variable, bool emitDictionary) { Assert.NotNull(ag, variable); Debug.Assert(variable.Kind != VariableKind.Parameter); string name = SymbolTable.IdToString(variable.Name); switch (variable.Kind) { case VariableKind.Global: case VariableKind.GlobalLocal: return _variables[variable] = GetGlobal(name, ag, false); case VariableKind.Local: case VariableKind.HiddenLocal: if (ag.IsGlobal) { return _variables[variable] = GetGlobal(name, ag, true); } else if (variable.AccessedInNestedScope || (emitDictionary && variable.Kind != VariableKind.HiddenLocal)) { return ag.SetLocalLiftedVariable(variable, ag.LiftedVariable(variable, name, variable.AccessedInNestedScope)); } else { return _variables[variable] = ag.Variable(typeof(object), name); } default: throw Assert.Unreachable; } }
/// <summary> /// Creates variables which are defined in a parent scope and accessed in this scope. /// </summary> private void CreateReferencedVariables(AstGenerator ag, List<MSAst.Expression> init, bool emitDictionary, bool needsLocals) { MSAst.Expression localTuple = null; foreach (KeyValuePair<SymbolId, PythonReference> kv in _references) { PythonVariable var = kv.Value.PythonVariable; if (var == null || var.Scope == this) { continue; } if ((var.Kind == VariableKind.Local || var.Kind == VariableKind.Parameter) && !var.Scope.IsGlobal) { // closed over local, we need to pull in the closure variable Type tupleType = ag.GetParentTupleType(); int index = ag.TupleIndex(var); localTuple = EnsureLocalTuple(ag, init, localTuple, tupleType); // get the closure cell from the tuple MSAst.Expression tuplePath = localTuple; foreach (var v in MutableTuple.GetAccessPath(tupleType, index)) { tuplePath = MSAst.Expression.Property(tuplePath, v); } MSAst.ParameterExpression pe = ag.HiddenVariable(typeof(ClosureCell), SymbolTable.IdToString(var.Name)); init.Add(MSAst.Expression.Assign(pe, tuplePath)); ag.SetLocalLiftedVariable(var, new ClosureExpression(var, pe, null)); if (emitDictionary) { ag.ReferenceVariable(var, index, localTuple, needsLocals); } } } }