예제 #1
0
        /// <summary>
        /// Creates variables which are defined in a parent scope and used by a child scope.
        /// </summary>
        private void CreateChildReferencedVariables(AstGenerator ag, MSAst.Expression parentContext, List<MSAst.Expression> init) {
            MSAst.Expression localTuple = null;
            foreach (KeyValuePair<SymbolId, PythonReference> kv in _childReferences) {
                // a child scope refers to this closure value but we don't refer
                // to it directly.
                int index = ag.TupleIndex(kv.Value.PythonVariable);
                Type tupleType = ag.GetParentTupleType();

                if (localTuple == null) {
                    // pull the tuple from the context once
                    localTuple = ag.HiddenVariable(tupleType, "$parentClosureTuple");
                    init.Add(
                        MSAst.Expression.Assign(
                            localTuple,
                            MSAst.Expression.Convert(
                                MSAst.Expression.Call(
                                    typeof(PythonOps).GetMethod("GetClosureTupleFromContext"),
                                    parentContext
                                ),
                                tupleType
                            )
                        )
                    );
                }

                ag.ReferenceVariable(kv.Value.PythonVariable, index, localTuple, false);
            }
        }
예제 #2
0
        /// <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);
                    }
                }
            }
        }