public HappyScriptCode Analyze(Module module, SourceUnit sourceUnit) { Init(); //This List<Expression> becomes the global scope initializer var rootNamespaces = LoadAllAssemblies(module.LoadDirectives); ExpandoObject importScope = new ExpandoObject(); foreach (HappyNamespaceTracker tracker in rootNamespaces.Values) DynamicObjectHelpers.SetMember(importScope, tracker.Name, tracker); #if WRITE_AST AstWriter writer = new AstWriter(Console.Out); module.WriteString(writer); #endif var getRuntimeContextExpr = Expression.Dynamic(_languageContext.CreateGetMemberBinder(RuntimeContextIdentifier, false), typeof(object), _globalScopeExp); UnaryExpression runtimeContextExpression = Expression.Convert(getRuntimeContextExpr, typeof(HappyRuntimeContext)); var errorCollector = new ErrorCollector(_languageContext.ErrorSink); _analysisContext = new AnalysisContext(errorCollector, _languageContext, runtimeContextExpression, _globalScopeExp); RunAllVisitors(module, rootNamespaces); List<Expression> body = new List<Expression>(); //Initialize globals using (_scopeStack.TrackPush(module.SymbolTable)) { foreach (VariableDef def in module.GlobalDefStatements.SelectMany(defStmt => defStmt.VariableDefs)) { Expression initialValue = def.InitializerExpression != null ? ExpressionAnalyzer.Analyze(_analysisContext, def.InitializerExpression) : Expression.Constant(null, typeof(object)); HappySymbolBase symbol = module.SymbolTable.Items[def.Name.Text]; body.Add(symbol.GetSetExpression(initialValue)); } } body.AddRange(module.Functions.Select( func => _analysisContext.PropertyOrFieldSet(func.Name.Text, _globalScopeExp, FunctionAnalyzer.Analzye(_analysisContext, func)))); //At this point analysis has completed and all of our stacks should be empty DebugAssert.AreEqual(0, _scopeStack.Count, "scope stack not empty after analysis"); //Add an empty expression--prevents an exception by Expression.Lambda when body is empty. //This allows compilation of empty template sets. if(body.Count == 0) body.Add(Expression.Empty()); LambdaExpression globalScopeInitializer = Expression.Lambda(typeof(Action<IDynamicMetaObjectProvider>), Expression.Block(body), new[] { _globalScopeExp }); HappyScriptCode output = new HappyScriptCode(sourceUnit, globalScopeInitializer.Compile()); return output; }
void RunAllVisitors(Module module, Dictionary<string, HappyNamespaceTracker> rootNamespaces) { Visitors.AstVisitorBase[] visitors = { new Visitors.BuildSymbolTablesVisitor(_analysisContext, rootNamespaces), new Visitors.SemanticVisitor(_analysisContext.ErrorCollector), new Visitors.PreAnalyzeVisitor(_analysisContext.ErrorCollector) }; foreach (var v in visitors) module.Accept(v); }