// 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(); } }
public bool CompileFunction() { var compiledData = new CompiledScriptBlockData(_currentAst, isFilter: false); return(compiledData.Compile(true)); }