예제 #1
0
        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));
            }
        }