internal ScriptCode/*!*/ TransformToAst(CompilationMode mode, CompilerContext/*!*/ context) { // Create the ast generator // Use the PrintExpression value for the body (global level code) PythonCompilerOptions pco = context.Options as PythonCompilerOptions; Debug.Assert(pco != null); string name; if (!context.SourceUnit.HasPath || (pco.Module & ModuleOptions.ExecOrEvalCode) != 0) { name = "<module>"; } else { name = context.SourceUnit.Path; } AstGenerator ag = new AstGenerator(mode, context, _body.Span, name, false, _printExpressions); MSAst.Expression body = Ast.Block( Ast.Call( AstGenerator.GetHelperMethod("ModuleStarted"), ag.LocalContext, AstUtils.Constant(ag.BinderState, typeof(object)), AstUtils.Constant(_languageFeatures) ), ag.UpdateLineNumber(0), ag.UpdateLineUpdated(false), ag.WrapScopeStatements(Transform(ag)), // new ComboActionRewriter().VisitNode(Transform(ag)) AstUtils.Empty() ); if (_isModule) { string moduleName = pco.ModuleName; if (moduleName == null) { #if !SILVERLIGHT if (context.SourceUnit.HasPath && context.SourceUnit.Path.IndexOfAny(Path.GetInvalidFileNameChars()) == -1) { moduleName = Path.GetFileNameWithoutExtension(context.SourceUnit.Path); #else if (context.SourceUnit.HasPath) { moduleName = context.SourceUnit.Path; #endif } else { moduleName = "<module>"; } } Debug.Assert(moduleName != null); body = Ast.Block( ag.Globals.Assign(ag.Globals.GetVariable(ag, _fileVariable), Ast.Constant(name)), ag.Globals.Assign(ag.Globals.GetVariable(ag, _nameVariable), Ast.Constant(moduleName)), body // already typed to void ); if ((pco.Module & ModuleOptions.Initialize) != 0) { MSAst.Expression tmp = ag.HiddenVariable(typeof(object), "$originalModule"); // TODO: Should be try/fault body = AstUtils.Try( Ast.Assign(tmp, Ast.Call(AstGenerator.GetHelperMethod("PublishModule"), ag.LocalContext, Ast.Constant(moduleName))), body ).Catch( typeof(Exception), Ast.Call(AstGenerator.GetHelperMethod("RemoveModule"), ag.LocalContext, Ast.Constant(moduleName), tmp), Ast.Rethrow(body.Type) ); } } body = ag.AddProfiling(body); body = ag.AddReturnTarget(body); if (body.Type == typeof(void)) { body = Ast.Block(body, Ast.Constant(null)); } return ag.MakeScriptCode(body, context, this); }
private MSAst.Expression EnsureLocalTuple(AstGenerator ag, List<System.Linq.Expressions.Expression> init, MSAst.Expression localTuple, Type tupleType) { if (localTuple == null) { // pull the tuple from the context once localTuple = ag.HiddenVariable(tupleType, "$closureTuple"); init.Add( MSAst.Expression.Assign( localTuple, MSAst.Expression.Convert( GetClosureTuple(), tupleType ) ) ); } return localTuple; }
/// <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); } } } }
/// <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); } }
public MSAst.Expression/*!*/ CreateVariable(AstGenerator/*!*/ ag, PythonVariable/*!*/ variable) { 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) { return _variables[variable] = ag.ClosedOverVariable(typeof(object), name); } else { return _variables[variable] = ag.Variable(typeof(object), name); } case VariableKind.Temporary: return _variables[variable] = ag.HiddenVariable(typeof(object), name); default: throw Assert.Unreachable; } }