예제 #1
0
        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);
        }
예제 #2
0
 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;
 }
예제 #3
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);
                    }
                }
            }
        }
예제 #4
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);
            }
        }
예제 #5
0
        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;
            }
        }