mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-04 10:16:13 +00:00 
			
		
		
		
	Merge branch 'master' into structs
# Conflicts: # compiler/src/prog8/compiler/Compiler.kt
This commit is contained in:
		@@ -65,6 +65,7 @@ private fun compileMain(args: Array<String>): Boolean {
 | 
			
		||||
    val dontSplitWordArrays by cli.option(ArgType.Boolean, fullName = "dontsplitarrays", description = "don't store any word array as split lsb/msb in memory, as if all of those have @nosplit")
 | 
			
		||||
    val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator)
 | 
			
		||||
    val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")} or a custom target properties file) (required)")
 | 
			
		||||
    val showTimings by cli.option(ArgType.Boolean, fullName = "timings", description = "show internal compiler timings (for performance analysis)")
 | 
			
		||||
    val varsGolden by cli.option(ArgType.Boolean, fullName = "varsgolden", description = "put uninitialized variables in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
 | 
			
		||||
    val varsHighBank by cli.option(ArgType.Int, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.")
 | 
			
		||||
    val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "run a .p8ir IR source file in the embedded VM")
 | 
			
		||||
@@ -181,6 +182,7 @@ private fun compileMain(args: Array<String>): Boolean {
 | 
			
		||||
                    warnSymbolShadowing == true,
 | 
			
		||||
                    quietAll == true,
 | 
			
		||||
                    quietAll == true || quietAssembler == true,
 | 
			
		||||
                    showTimings == true,
 | 
			
		||||
                    asmListfile == true,
 | 
			
		||||
                    dontIncludeSourcelines != true,
 | 
			
		||||
                    experimentalCodegen == true,
 | 
			
		||||
@@ -265,6 +267,7 @@ private fun compileMain(args: Array<String>): Boolean {
 | 
			
		||||
                    warnSymbolShadowing == true,
 | 
			
		||||
                    quietAll == true,
 | 
			
		||||
                    quietAll == true || quietAssembler == true,
 | 
			
		||||
                    showTimings == true,
 | 
			
		||||
                    asmListfile == true,
 | 
			
		||||
                    dontIncludeSourcelines != true,
 | 
			
		||||
                    experimentalCodegen == true,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,10 @@ import java.nio.file.Path
 | 
			
		||||
import kotlin.io.path.Path
 | 
			
		||||
import kotlin.io.path.isRegularFile
 | 
			
		||||
import kotlin.io.path.nameWithoutExtension
 | 
			
		||||
import kotlin.math.round
 | 
			
		||||
import kotlin.system.exitProcess
 | 
			
		||||
import kotlin.system.measureTimeMillis
 | 
			
		||||
import kotlin.time.Duration
 | 
			
		||||
import kotlin.time.measureTime
 | 
			
		||||
import kotlin.time.measureTimedValue
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompilationResult(val compilerAst: Program,   // deprecated, use codegenAst instead
 | 
			
		||||
@@ -40,6 +41,7 @@ class CompilerArguments(val filepath: Path,
 | 
			
		||||
                        val warnSymbolShadowing: Boolean,
 | 
			
		||||
                        val quietAll: Boolean,
 | 
			
		||||
                        val quietAssembler: Boolean,
 | 
			
		||||
                        val showTimings: Boolean,
 | 
			
		||||
                        val asmListfile: Boolean,
 | 
			
		||||
                        val includeSourcelines: Boolean,
 | 
			
		||||
                        val experimentalCodegen: Boolean,
 | 
			
		||||
@@ -83,9 +85,20 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        val totalTime = measureTimeMillis {
 | 
			
		||||
        val totalTime = measureTime {
 | 
			
		||||
            val libraryDirs =  if(compTarget.libraryPath!=null) listOf(compTarget.libraryPath.toString()) else emptyList()
 | 
			
		||||
            val (program, options, imported) = parseMainModule(args.filepath, args.errors, compTarget, args.sourceDirs, libraryDirs, args.quietAll)
 | 
			
		||||
            val (parseresult, parseDuration) = measureTimedValue {
 | 
			
		||||
                 parseMainModule(
 | 
			
		||||
                    args.filepath,
 | 
			
		||||
                    args.errors,
 | 
			
		||||
                    compTarget,
 | 
			
		||||
                    args.sourceDirs,
 | 
			
		||||
                    libraryDirs,
 | 
			
		||||
                    args.quietAll
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val (program, options, imported) = parseresult
 | 
			
		||||
            compilationOptions = options
 | 
			
		||||
 | 
			
		||||
            with(compilationOptions) {
 | 
			
		||||
@@ -120,10 +133,14 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            val processDuration = measureTime {
 | 
			
		||||
                processAst(program, args.errors, compilationOptions)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            println("*********** COMPILER AST RIGHT BEFORE OPTIMIZING *************")
 | 
			
		||||
//            printProgram(program)
 | 
			
		||||
 | 
			
		||||
            val optimizeDuration = measureTime {
 | 
			
		||||
                if (compilationOptions.optimize) {
 | 
			
		||||
                    optimizeAst(
 | 
			
		||||
                        program,
 | 
			
		||||
@@ -132,26 +149,33 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
			
		||||
                        BuiltinFunctionsFacade(BuiltinFunctions),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val postprocessDuration = measureTime {
 | 
			
		||||
                determineProgramLoadAddress(program, compilationOptions, args.errors)
 | 
			
		||||
                args.errors.report()
 | 
			
		||||
                postprocessAst(program, args.errors, compilationOptions)
 | 
			
		||||
                args.errors.report()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            println("*********** COMPILER AST BEFORE ASSEMBLYGEN *************")
 | 
			
		||||
//            printProgram(program)
 | 
			
		||||
 | 
			
		||||
            var createAssemblyDuration = Duration.ZERO
 | 
			
		||||
            var simplifiedAstDuration = Duration.ZERO
 | 
			
		||||
 | 
			
		||||
            if (args.writeAssembly) {
 | 
			
		||||
 | 
			
		||||
                // re-initialize memory areas with final compilationOptions
 | 
			
		||||
                compilationOptions.compTarget.initializeMemoryAreas(compilationOptions)
 | 
			
		||||
 | 
			
		||||
                if(args.printAst1) {
 | 
			
		||||
                if (args.printAst1) {
 | 
			
		||||
                    println("\n*********** COMPILER AST *************")
 | 
			
		||||
                    printProgram(program)
 | 
			
		||||
                    println("*********** COMPILER AST END *************\n")
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val (intermediateAst, simplifiedAstDuration2) = measureTimedValue {
 | 
			
		||||
                    val intermediateAst = SimplifiedAstMaker(program, args.errors).transform()
 | 
			
		||||
                    val stMaker = SymbolTableMaker(intermediateAst, compilationOptions)
 | 
			
		||||
                    val symbolTable = stMaker.make()
 | 
			
		||||
@@ -159,12 +183,12 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
			
		||||
                postprocessSimplifiedAst(intermediateAst, symbolTable, compilationOptions, args.errors)
 | 
			
		||||
                args.errors.report()
 | 
			
		||||
 | 
			
		||||
                if(compilationOptions.optimize) {
 | 
			
		||||
                    if (compilationOptions.optimize) {
 | 
			
		||||
                        optimizeSimplifiedAst(intermediateAst, compilationOptions, symbolTable, args.errors)
 | 
			
		||||
                        args.errors.report()
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                if(args.printAst2) {
 | 
			
		||||
                    if (args.printAst2) {
 | 
			
		||||
                        println("\n*********** SIMPLIFIED AST *************")
 | 
			
		||||
                        printAst(intermediateAst, true, ::println)
 | 
			
		||||
                        println("*********** SIMPLIFIED AST END *************\n")
 | 
			
		||||
@@ -172,29 +196,51 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
 | 
			
		||||
 | 
			
		||||
                    verifyFinalAstBeforeAsmGen(intermediateAst, compilationOptions, symbolTable, args.errors)
 | 
			
		||||
                    args.errors.report()
 | 
			
		||||
                    intermediateAst
 | 
			
		||||
                }
 | 
			
		||||
                simplifiedAstDuration =simplifiedAstDuration2
 | 
			
		||||
 | 
			
		||||
                if(!createAssemblyAndAssemble(intermediateAst, args.errors, compilationOptions, program.generatedLabelSequenceNumber)) {
 | 
			
		||||
                createAssemblyDuration = measureTime {
 | 
			
		||||
                    if (!createAssemblyAndAssemble(
 | 
			
		||||
                            intermediateAst,
 | 
			
		||||
                            args.errors,
 | 
			
		||||
                            compilationOptions,
 | 
			
		||||
                            program.generatedLabelSequenceNumber
 | 
			
		||||
                        )
 | 
			
		||||
                    ) {
 | 
			
		||||
                        System.err.println("Error in codegeneration or assembler")
 | 
			
		||||
                        return null
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                ast = intermediateAst
 | 
			
		||||
            } else {
 | 
			
		||||
                if(args.printAst1) {
 | 
			
		||||
                if (args.printAst1) {
 | 
			
		||||
                    println("\n*********** COMPILER AST *************")
 | 
			
		||||
                    printProgram(program)
 | 
			
		||||
                    println("*********** COMPILER AST END *************\n")
 | 
			
		||||
                }
 | 
			
		||||
                if(args.printAst2) {
 | 
			
		||||
                if (args.printAst2) {
 | 
			
		||||
                    System.err.println("There is no simplified Ast available if assembly generation is disabled.")
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            System.out.flush()
 | 
			
		||||
            System.err.flush()
 | 
			
		||||
 | 
			
		||||
            if(!args.quietAll && args.showTimings) {
 | 
			
		||||
                println("\n**** TIMING ****")
 | 
			
		||||
                println("source parsing   : ${parseDuration}")
 | 
			
		||||
                println("ast processing   : ${processDuration}")
 | 
			
		||||
                println("ast optimizing   : ${optimizeDuration}")
 | 
			
		||||
                println("ast postprocess  : ${postprocessDuration}")
 | 
			
		||||
                println("code prepare     : ${simplifiedAstDuration}")
 | 
			
		||||
                println("code generation  : ${createAssemblyDuration}")
 | 
			
		||||
                println("          total  : ${parseDuration + processDuration + optimizeDuration + postprocessDuration + simplifiedAstDuration + createAssemblyDuration}")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!args.quietAll) {
 | 
			
		||||
            val seconds = totalTime / 1000.0
 | 
			
		||||
            println("\nTotal compilation+assemble time: ${round(seconds * 100.0) / 100.0} sec.")
 | 
			
		||||
            println("\nTotal compilation+assemble time: ${totalTime}.")
 | 
			
		||||
        }
 | 
			
		||||
        return CompilationResult(resultingProgram!!, ast, compilationOptions, importedFiles)
 | 
			
		||||
    } catch (px: ParseError) {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
 | 
			
		||||
        warnSymbolShadowing = false,
 | 
			
		||||
        quietAll = true,
 | 
			
		||||
        quietAssembler = true,
 | 
			
		||||
        showTimings = false,
 | 
			
		||||
        asmListfile = false,
 | 
			
		||||
        includeSourcelines = false,
 | 
			
		||||
        experimentalCodegen = false,
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
 | 
			
		||||
            warnSymbolShadowing = false,
 | 
			
		||||
            quietAll = true,
 | 
			
		||||
            quietAssembler = true,
 | 
			
		||||
            showTimings = false,
 | 
			
		||||
            asmListfile = false,
 | 
			
		||||
            includeSourcelines = false,
 | 
			
		||||
            experimentalCodegen = false,
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ internal fun compileFile(
 | 
			
		||||
        warnSymbolShadowing = false,
 | 
			
		||||
        quietAll = true,
 | 
			
		||||
        quietAssembler = true,
 | 
			
		||||
        showTimings = false,
 | 
			
		||||
        asmListfile = false,
 | 
			
		||||
        includeSourcelines = false,
 | 
			
		||||
        experimentalCodegen = false,
 | 
			
		||||
 
 | 
			
		||||
@@ -18,14 +18,20 @@ Then you can choose a few ways to get a compiler:
 | 
			
		||||
 | 
			
		||||
**Or, install via a Package Manager:**
 | 
			
		||||
 | 
			
		||||
Currently, it's only available on `AUR <https://wiki.archlinux.org/title/Arch_User_Repository>`_ for Arch Linux and compatible systems.
 | 
			
		||||
The package is called `"prog8" <https://aur.archlinux.org/packages/prog8>`_.
 | 
			
		||||
Arch Linux:
 | 
			
		||||
    Currently, it's available on `AUR <https://wiki.archlinux.org/title/Arch_User_Repository>`_ for Arch Linux and compatible systems.
 | 
			
		||||
    The package is called `"prog8" <https://aur.archlinux.org/packages/prog8>`_.
 | 
			
		||||
 | 
			
		||||
This package, alongside the compiler itself, also globally installs syntax highlighting for ``vim`` and ``nano``.
 | 
			
		||||
In order to run compiler, you can type ``prog8c``. The usage of those commands is exactly the same as with the ``java -jar`` method.
 | 
			
		||||
    This package, alongside the compiler itself, also globally installs syntax highlighting for ``vim`` and ``nano``.
 | 
			
		||||
    In order to run compiler, you can type ``prog8c``. The usage of those commands is exactly the same as with the ``java -jar`` method.
 | 
			
		||||
 | 
			
		||||
In case you prefer to install AUR packages in a traditional manner, make sure to install `"tass64" package <https://aur.archlinux.org/packages/tass64>`_
 | 
			
		||||
before installing prog8, as `makepkg <https://wiki.archlinux.org/title/Makepkg>`_ itself doesn't fetch AUR dependencies.
 | 
			
		||||
    In case you prefer to install AUR packages in a traditional manner, make sure to install `"tass64" package <https://aur.archlinux.org/packages/tass64>`_
 | 
			
		||||
    before installing prog8, as `makepkg <https://wiki.archlinux.org/title/Makepkg>`_ itself doesn't fetch AUR dependencies.
 | 
			
		||||
 | 
			
		||||
Mac OS (and Linux, and WSL2 on Windows):
 | 
			
		||||
    Prog8 can be installed via `Homebrew <https://formulae.brew.sh/formula/prog8>`_ using the command ``brew install prog8``.
 | 
			
		||||
    It will make the ``prog8c`` command available and also installs the other required software tools for you.
 | 
			
		||||
    While Homebrew works on Linux, it's probably best to first check your distribution's native package manager.
 | 
			
		||||
 | 
			
		||||
**Or, download a bleeding edge development version from Github:**
 | 
			
		||||
 | 
			
		||||
@@ -236,6 +242,9 @@ One or more .p8 module files
 | 
			
		||||
    machine's configuration and properties from that configuration file instead of using one of the built-in targets.
 | 
			
		||||
    See :ref:`customizable_target` for details about this.
 | 
			
		||||
 | 
			
		||||
``-timings``
 | 
			
		||||
    Show a more detailed breakdown of the time taken in various compiler phases, for performance analysis of the compiler itself.
 | 
			
		||||
 | 
			
		||||
``-varsgolden``
 | 
			
		||||
    Like ``-varshigh``, but places the variables in the $0400-$07FF "golden ram" area instead.
 | 
			
		||||
    Because this is in normal system memory, there are no bank switching issues.
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,7 @@ Libraries
 | 
			
		||||
Optimizations
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
- Compilation speed: try to join multiple modifications in 1 result in the AST processors instead of returning it straight away every time
 | 
			
		||||
- Compare output of some Oscar64 samples to what prog8 does for the equivalent code (see https://github.com/drmortalwombat/OscarTutorials/tree/main and https://github.com/drmortalwombat/oscar64/tree/main/samples)
 | 
			
		||||
- Optimize the IfExpression code generation to be more like regular if-else code.  (both 6502 and IR) search for "TODO don't store condition as expression"
 | 
			
		||||
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user