Exemple #1
0
        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;
        }