private static void SwitchOnLongargs(CrawlCompilerConfiguration crawlCompilerConfiguration, string longarg) { string[] parts = longarg.Split('='); try { switch (parts[0]) { case "help": crawlCompilerConfiguration.PrintHelp = true; break; case "print-ast": SetStage(crawlCompilerConfiguration, TargetStage.AbstractSyntaxTree); break; case "print-pt": SetStage(crawlCompilerConfiguration, TargetStage.ParseTree); break; case "typecheck": SetStage(crawlCompilerConfiguration, TargetStage.TypeCheck); break; case "optimize": if (parts.Length == 1) { crawlCompilerConfiguration.Optimizations.Add("*"); } else { foreach (string optimiaztion in parts[1].Split(',')) { crawlCompilerConfiguration.Optimizations.Add(optimiaztion); } } break; case "assembly": crawlCompilerConfiguration.Assemblies.Add(parts[1]); break; case "output": crawlCompilerConfiguration.OutputFile = parts[1]; break; case "force-single-thread": crawlCompilerConfiguration.ForceSingleThreaded = true; break; default: throw new UnknownOption(parts[0]); } } catch (IndexOutOfRangeException) { throw new RequiresArgumentException(parts[0]); } }
private static void SetStage(CrawlCompilerConfiguration crawlCompilerConfiguration, TargetStage stage) { if (crawlCompilerConfiguration.TargetStage >= 0) { throw new MutalExcluseiveOptionsException(crawlCompilerConfiguration.TargetStage.ToString(), stage.ToString()); } crawlCompilerConfiguration.TargetStage = stage; }
public static TextWriter GetPrimaryOutputStream(CrawlCompilerConfiguration configuration) { if (string.IsNullOrWhiteSpace(configuration.OutputFile)) { return(Console.Out); } return(new StreamWriter(File.OpenWrite(configuration.OutputFile))); }
internal static void WriteParseTrees(TextWriter output, CrawlCompilerConfiguration configuration) { foreach (string inputfile in configuration.Files) { output.WriteLine("Parsing file {0}", inputfile); CrawlParser.Translation_unitContext tu = ParseFile(File.OpenRead(inputfile)); //foreach (string line in Utils.MakeIndents(tu.ToStringTree(CrawlParser.ruleNames)).Split('\n')) //{ // output.WriteLine(line); //} output.WriteLine(Utils.MakeIndents(tu.ToStringTree(CrawlParser.ruleNames))); } }
private static void SwitchOnCharargs(CrawlCompilerConfiguration crawlCompilerConfiguration, char c) { switch (c) { case 'h': crawlCompilerConfiguration.PrintHelp = true; break; case 'p': SetStage(crawlCompilerConfiguration, TargetStage.ParseTree); break; case 'a': SetStage(crawlCompilerConfiguration, TargetStage.AbstractSyntaxTree); break; default: throw new UnknownOption(c.ToString()); } }
public static CrawlCompilerConfiguration Parse(string[] args) { CrawlCompilerConfiguration configuration = new CrawlCompilerConfiguration(); TargetStage defaultTargetStage = configuration.TargetStage; configuration.TargetStage = (TargetStage)(-1); for (int index = 0; index < args.Length; index++) { string arg = args[index]; if (arg.StartsWith("--")) { string longarg = arg.Substring(2); SwitchOnLongargs(configuration, longarg); } else if (arg.StartsWith("-")) { string multiargs = arg.Substring(1); foreach (char c in multiargs) { SwitchOnCharargs(configuration, c); } } else { configuration.Files.Add(arg); } } if (configuration.TargetStage < 0) { configuration.TargetStage = defaultTargetStage; } if (args.Length == 0) { configuration.PrintHelp = true; } return(configuration); }
/// <summary> /// /// </summary> /// <param name="configuration">Paths to source code, referenced assemblies and compiler directives</param> /// <returns>Any resulting errors, logs and executables.</returns> public static CompilationResult Compile(CrawlCompilerConfiguration configuration) { TextWriter output = Utils.GetPrimaryOutputStream(configuration); //TraceListners.AssemblyResolverListner = // new System.Diagnostics.TextWriterTraceListener(Utils.GetPrimaryOutputStream(configuration)); //From referenced files, build list of existing namespaces ConcurrentDictionary <string, Namespace> allNamespaces = NamespaceLoader.LoadAll(configuration.Assemblies); allNamespaces.MergeInto(Namespace.BuiltinNamespace.AsSingleIEnumerable()); //Set up logging and status SideeffectHelper sideeffectHelper = new SideeffectHelper(); CompilationStatus status = CompilationStatus.Success; try { //single line comments with /* */ are referering to a stage in general_archtechture.md bool parallel = !configuration.ForceSingleThreaded; //The ConcurrentBag is an unordered, thread safe, collection ConcurrentBag <AstData> parsedFiles = Run <AstData, string>(configuration.Files, parallel, sideeffectHelper, (destination, helper) => { //Syntax is slightly wonky, but cannot assign variable to method group. //_Could_ be hidden in ParsePipeline by making them properties instead.... //Get the starting transformaton /* Create parse tree */ Func <string, SideeffectHelper, ParseTreeData> parsePT = ParsePipeline.ReadFileToPt; //Jump out if we are intrested in earlier stage. if (configuration.TargetStage == TargetStage.ParseTree) { return(parsePT.EndWith(output.WriteLine, helper)); } /* Create AST */ var parseASt = parsePT .Then(ParsePipeline.CreateAst); //.Then adds another stage if (configuration.TargetStage == TargetStage.AbstractSyntaxTree) { return(parseASt.EndWith(output.WriteLine, helper)); } /* Collect types*/ var firstscopepass = parseASt.Then(SemanticAnalysisPipeline.CollectTypes); //.EndWith collects it return(firstscopepass.EndWith(destination.Add, helper)); } ); MaybeDie(sideeffectHelper); /* Merge type tables */ foreach (AstData file in parsedFiles) { TranslationUnitNode node = (TranslationUnitNode)file.Tree.RootNode; Namespace exportedTypes = new Namespace(node.Namespace.Module, node.Code.Scope.Classes()); allNamespaces.MergeInto(exportedTypes.AsSingleIEnumerable()); } //TODO: finish Semantic analysis ConcurrentBag <AstData> filesWithScope = Run <AstData, AstData>(parsedFiles, parallel, sideeffectHelper, (destination, helper) => { /* Find visible namespace*/ //NamespaceDecorator is a hack to pass all namespaces in to the function that finds the relevant ones Func <AstData, SideeffectHelper, AstData> first = new SemanticAnalysisPipeline.NamespaceDecorator(allNamespaces).AddExport; return(first /* Decorate TypeNode */ .Then(SemanticAnalysisPipeline.PutTypes) /* Collect remaining scope information */ .Then(SemanticAnalysisPipeline.SecondScopePass) /* Finish types */ .Then(SemanticAnalysisPipeline.FinishTypes) .EndWith(destination.Add, helper)); } ); //TODO: Merge namespaces again with extra (Methods/Variables) from scope. Right now, only classes are visible //in other files ConcurrentBag <AstData> decoratedAsts = Run <AstData, AstData>(filesWithScope, parallel, sideeffectHelper, (destination, helper) => { /* scope check */ Func <AstData, SideeffectHelper, AstData> first = SemanticAnalysisPipeline.DeclerationOrderCheck; var final = first .Then(SemanticAnalysisPipeline.TypeCheck) .EndWith(destination.Add, helper); //Typechecker would be added here or line above return(final); } ); ConcurrentBag <AstData> optimizedAsts = Run <AstData, AstData>(decoratedAsts, parallel, sideeffectHelper, (destination, helper) => { Func <AstData, SideeffectHelper, AstData> first = OptimizationPipeline.FoldConstants; var final = first .Then(OptimizationPipeline.RefWherePossible) .EndWith(destination.Add, helper); return(final); } ); //TODO: Interpeter or code generation //Until meaningfull end, print everything Execute(decoratedAsts, output.WriteLine, parallel); output.WriteLine("\n===Optimized To===>\n"); Execute(optimizedAsts, output.WriteLine, parallel); if (sideeffectHelper.CompilationMessages.Count(message => message.Severity >= MessageSeverity.Error) > 0) { status = CompilationStatus.Failure; } } catch (ExitCompilationException) { status = CompilationStatus.Failure; } catch (Exception e) when(false && !Debugger.IsAttached) { sideeffectHelper.CompilationMessages.Add(CompilationMessage.CreateNonCodeMessage(MessageCode.InternalCompilerError, e.ToString(), MessageSeverity.Fatal)); status = CompilationStatus.Failure; } return(new CompilationResult(status, sideeffectHelper.CompilationMessages)); }