Example #1
0
        // This is the main entry point for turning an AST into compiled code.
        internal void Compile(CompiledScriptBlockData scriptBlock, bool optimize)
        {
            var body = scriptBlock.Ast;
            Diagnostics.Assert(body is ScriptBlockAst || body is FunctionDefinitionAst || body is FunctionMemberAst || body is CompilerGeneratedMemberFunctionAst,
                               "Caller to verify ast is correct type.");
            var ast = (Ast)body;
            Optimize = optimize;
            _compilingScriptCmdlet = scriptBlock.UsesCmdletBinding;

            var fileName = ast.Extent.File;
            if (fileName != null)
            {
                _debugSymbolDocument = Expression.SymbolDocument(fileName);
            }

            var details = VariableAnalysis.Analyze(body, !optimize, _compilingScriptCmdlet);
            LocalVariablesTupleType = details.Item1;
            var nameToIndexMap = details.Item2;

            if (!nameToIndexMap.TryGetValue(SpecialVariables.@switch, out _switchTupleIndex))
            {
                _switchTupleIndex = VariableAnalysis.ForceDynamic;
            }
            if (!nameToIndexMap.TryGetValue(SpecialVariables.@foreach, out _foreachTupleIndex))
            {
                _foreachTupleIndex = VariableAnalysis.ForceDynamic;
            }

            LocalVariablesParameter = Expression.Variable(LocalVariablesTupleType, "locals");

            var functionMemberAst = ast as FunctionMemberAst;
            if (functionMemberAst != null)
            {
                CompilingMemberFunction = true;
                MemberFunctionReturnType = functionMemberAst.GetReturnType();
                _memberFunctionType = (TypeDefinitionAst)functionMemberAst.Parent;
                SpecialMemberFunctionType = SpecialMemberFunctionType.None;
                if (functionMemberAst.Name.Equals(_memberFunctionType.Name, StringComparison.OrdinalIgnoreCase))
                {
                    // TODO: default argument support
                    var parameters = ((IParameterMetadataProvider)functionMemberAst.Body).Parameters;
                    if (parameters == null || parameters.Count == 0)
                    {
                        SpecialMemberFunctionType = functionMemberAst.IsStatic
                            ? SpecialMemberFunctionType.StaticConstructor
                            : SpecialMemberFunctionType.DefaultConstructor;
                    }
                }
            }
            else
            {
                var generatedMemberFunctionAst = ast as CompilerGeneratedMemberFunctionAst;
                if (generatedMemberFunctionAst != null)
                {
                    CompilingMemberFunction = true;
                    SpecialMemberFunctionType = generatedMemberFunctionAst.Type;
                    MemberFunctionReturnType = typeof(void);
                    _memberFunctionType = generatedMemberFunctionAst.DefiningType;
                }
            }

            body.Body.Accept(this);

            if (_sequencePoints.Count == 0)
            {
                // Uncommon, but possible if a script is empty, or if it only defines functions.
                // In this case, add the entire body as a sequence point.  Debugging won't stop
                // on this sequence point, but it makes it safe to access the CurrentPosition
                // property in FunctionContext (which can happen if there are exceptions
                // defining the functions.)
                _sequencePoints.Add(ast.Extent);
            }

            var compileInterpretChoice = (_stmtCount > 300) ? CompileInterpretChoice.NeverCompile : CompileInterpretChoice.CompileOnDemand;

            if (optimize)
            {
                scriptBlock.DynamicParamBlock = CompileTree(_dynamicParamBlockLambda, compileInterpretChoice);
                scriptBlock.BeginBlock = CompileTree(_beginBlockLambda, compileInterpretChoice);
                scriptBlock.ProcessBlock = CompileTree(_processBlockLambda, compileInterpretChoice);
                scriptBlock.EndBlock = CompileTree(_endBlockLambda, compileInterpretChoice);
                scriptBlock.LocalsMutableTupleType = LocalVariablesTupleType;
                scriptBlock.LocalsMutableTupleCreator = MutableTuple.TupleCreator(LocalVariablesTupleType);
                scriptBlock.NameToIndexMap = nameToIndexMap;
            }
            else
            {
                scriptBlock.UnoptimizedDynamicParamBlock = CompileTree(_dynamicParamBlockLambda, compileInterpretChoice);
                scriptBlock.UnoptimizedBeginBlock = CompileTree(_beginBlockLambda, compileInterpretChoice);
                scriptBlock.UnoptimizedProcessBlock = CompileTree(_processBlockLambda, compileInterpretChoice);
                scriptBlock.UnoptimizedEndBlock = CompileTree(_endBlockLambda, compileInterpretChoice);
                scriptBlock.UnoptimizedLocalsMutableTupleType = LocalVariablesTupleType;
                scriptBlock.UnoptimizedLocalsMutableTupleCreator = MutableTuple.TupleCreator(LocalVariablesTupleType);
            }

            // The sequence points are identical optimized or not.  Regardless, we want to ensure
            // that the list is unique no matter when the property is accessed, so make sure it is set just once.
            if (scriptBlock.SequencePoints == null)
            {
                scriptBlock.SequencePoints = _sequencePoints.ToArray();
            }
        }
Example #2
0
        public bool CompileFunction()
        {
            var compiledData = new CompiledScriptBlockData(_currentAst, isFilter: false);

            return(compiledData.Compile(true));
        }