public Linker(ASTCompiler compiler, Domain globalDomain, List <ExternContainer> externals) { this.m_compiler = compiler; this.m_globalDomain = globalDomain; this.m_externals = externals; this.m_bindings = new BindTable(); }
public static List <ByteInstruction> CompileCondition(ASTCompiler compiler, IExpr condition, CompileContext context) { ASTNode node = condition as ASTNode; var instructions = compiler.CompileNode(node, context); // Check instructions for condition optimization return(instructions); }
private ProgramOutput GetCompileOutput(ASTCompiler compiler, Linker linker, Domain globalDomain) { ProgramOutput program = new ProgramOutput(); Dictionary <string, long> offsets = new Dictionary <string, long>(); List <ByteInstruction> allInstructions = new List <ByteInstruction>(); long offset = 0; var context = compiler.GetCompileContext(); var funcs = compiler.GetCompiledBytecode(); if (funcs is not null) { for (int i = 0; i < funcs.Length; i++) { offsets.Add(funcs[i].Name, offset); for (int j = 0; j < funcs[i].Instructions.Count; j++) { ByteInstruction instruction = funcs[i].Instructions[j]; allInstructions.Add(instruction); offset += instruction.GetSize(); } long remainder = offset % 4; if (remainder > 0) { for (int j = 0; j < remainder; j++) { allInstructions.Add(new ByteInstruction(Bytecode.NOP)); } offset += remainder; } } } // Set instructions, offsets, bytes, strings etc... program.SetProgramType(this.m_currentProject.ProjectType); program.SetInstructions(allInstructions.ToArray()); program.SetOffsets(offsets, offset); program.SetBytes(context?.ConstBytes); program.SetStrings(context?.Strings); program.SetDeclaredTypes(linker.ExportTypes); program.SetBindTable(linker.Bindings); // Set program return(program); }
public CompileResult CompileProject(SourceProject project) { // Set active project this.m_currentProject = project; // Meta data generation this.m_thisLog = new(); this.m_externalBindables = new(); this.m_timer = Stopwatch.StartNew(); // Parse all files AST[] asts = new AST[this.m_currentProject.Sources.Length]; for (int i = 0; i < this.m_currentProject.Sources.Length; i++) { var parseResult = ParseFile(this.m_currentProject.Sources[i], out AST ast); if (!parseResult) { Log.WriteLine($"Failed to parse {this.m_currentProject.Sources[i].Name} :\n\t{"Some currently un-generated error!"}"); Log.WriteLine(); return(parseResult); } asts[i] = ast; } // Create the global domain and import external references Domain globalDomain = Domain.GetGlobalDomain(); var result = ImportReferences(globalDomain, this.m_currentProject); if (!result) { return(this.FatalError(result)); } // Detect types result = StaticTypeDetector.Detect(asts, globalDomain); if (!result) { return(this.FatalError(result)); } // Define types result = StaticTypeDefiner.DefineAllTypes(asts, globalDomain); if (!result) { return(this.FatalError(result)); } // Solve potential inheritance problems etc. result = InheritanceSolver.Solve(asts, globalDomain); if (!result) { return(this.FatalError(result)); } // TODO: Run static checks // Verify variables VarsVerifier vVerifier = new VarsVerifier(); for (int i = 0; i < asts.Length; i++) { result = vVerifier.Vars(asts[i]); if (!result) { return(this.FatalError(result)); } } // Verify control paths ControlpathVerifier pathVerifier = new ControlpathVerifier(); for (int i = 0; i < asts.Length; i++) { result = pathVerifier.Verify(asts[i]); if (!result) { return(this.FatalError(result)); } } // Run static typecheck Typechecker typechecker = new Typechecker(); for (int i = 0; i < asts.Length; i++) { result = typechecker.Typecheck(asts[i], globalDomain); if (!result) { return(this.FatalError(result)); } } // Compile Application ASTCompiler astCompiler = new ASTCompiler(asts); result = astCompiler.Compile(); if (!result) { return(this.FatalError(result)); } // Apply linking Linker linker = new Linker(astCompiler, globalDomain, this.m_externalBindables); result = linker.Link(); if (!result) { return(this.FatalError(result)); } // Stop timer this.m_timer.Stop(); // Get compile output ProgramOutput compilerOutput = this.GetCompileOutput(astCompiler, linker, globalDomain); // If successful compile, save, otherwise log error if (compilerOutput is not null) { compilerOutput.Save(project.Output); compilerOutput.SaveAsText(project.Output.Replace(".bin", ".txt").Replace(".hlib", ".txt")); Log.WriteLine($"Compiled \"{project.Name}\" successfully in {this.m_timer.ElapsedMilliseconds / 1000.0}s."); Log.WriteLine(); this.m_thisLog.SaveAndClose(project.Output.Replace(".bin", ".log").Replace(".hlib", ".log")); return(new CompileResult(true)); } else { Log.WriteLine($"Compile Error \"{project.Name}\" : {result}"); Log.WriteLine(); this.m_thisLog.SaveAndClose(project.Output.Replace(".bin", ".log").Replace(".hlib", ".log")); return(new CompileResult(false)); } }