removed PROG8_LIBDIR env variables and replaced with -libdirs command line option

This commit is contained in:
Irmen de Jong 2021-04-28 20:04:23 +02:00
parent 81a91d62cb
commit 17068130bb
6 changed files with 37 additions and 43 deletions

View File

@ -23,8 +23,6 @@
; higher color dephts in highres are not supported due to lack of VRAM ; higher color dephts in highres are not supported due to lack of VRAM
; TODO use trb / tsb instructions more for and/or bit manipulations?
; TODO can we make a FB vector table and emulation routines for the Cx16s' GRAPH_init() call? to replace the builtin 320x200 fb driver? ; TODO can we make a FB vector table and emulation routines for the Cx16s' GRAPH_init() call? to replace the builtin 320x200 fb driver?
gfx2 { gfx2 {

View File

@ -1,15 +1,13 @@
package prog8 package prog8
import kotlinx.cli.ArgParser import kotlinx.cli.*
import kotlinx.cli.ArgType
import kotlinx.cli.default
import kotlinx.cli.multiple
import prog8.ast.base.AstException import prog8.ast.base.AstException
import prog8.compiler.CompilationResult import prog8.compiler.CompilationResult
import prog8.compiler.compileProgram import prog8.compiler.compileProgram
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.parser.ParsingFailedError import prog8.parser.ParsingFailedError
import java.io.File
import java.nio.file.FileSystems import java.nio.file.FileSystems
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.StandardWatchEventKinds import java.nio.file.StandardWatchEventKinds
@ -43,6 +41,7 @@ private fun compileMain(args: Array<String>) {
val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation") val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation")
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler, currently '${C64Target.name}' and '${Cx16Target.name}' available").default(C64Target.name) val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler, currently '${C64Target.name}' and '${Cx16Target.name}' available").default(C64Target.name)
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
val libDirs by cli.option(ArgType.String, fullName="libdirs", description = "list of extra paths to search in for imported modules").multiple().delimiter(File.pathSeparator)
try { try {
cli.parse(args) cli.parse(args)
@ -57,6 +56,10 @@ private fun compileMain(args: Array<String>) {
exitProcess(1) exitProcess(1)
} }
val libdirs = libDirs.toMutableList()
if(libdirs.firstOrNull()!=".")
libdirs.add(0, ".")
if(watchMode==true) { if(watchMode==true) {
val watchservice = FileSystems.getDefault().newWatchService() val watchservice = FileSystems.getDefault().newWatchService()
val allImportedFiles = mutableSetOf<Path>() val allImportedFiles = mutableSetOf<Path>()
@ -66,7 +69,7 @@ private fun compileMain(args: Array<String>) {
val results = mutableListOf<CompilationResult>() val results = mutableListOf<CompilationResult>()
for(filepathRaw in moduleFiles) { for(filepathRaw in moduleFiles) {
val filepath = pathFrom(filepathRaw).normalize() val filepath = pathFrom(filepathRaw).normalize()
val compilationResult = compileProgram(filepath, dontOptimize!=true, dontWriteAssembly!=true, slowCodegenWarnings==true, compilationTarget, outputPath) val compilationResult = compileProgram(filepath, dontOptimize!=true, dontWriteAssembly!=true, slowCodegenWarnings==true, compilationTarget, libdirs, outputPath)
results.add(compilationResult) results.add(compilationResult)
} }
@ -103,7 +106,7 @@ private fun compileMain(args: Array<String>) {
val filepath = pathFrom(filepathRaw).normalize() val filepath = pathFrom(filepathRaw).normalize()
val compilationResult: CompilationResult val compilationResult: CompilationResult
try { try {
compilationResult = compileProgram(filepath, dontOptimize!=true, dontWriteAssembly!=true, slowCodegenWarnings==true, compilationTarget, outputPath) compilationResult = compileProgram(filepath, dontOptimize!=true, dontWriteAssembly!=true, slowCodegenWarnings==true, compilationTarget, libdirs, outputPath)
if(!compilationResult.success) if(!compilationResult.success)
exitProcess(1) exitProcess(1)
} catch (x: ParsingFailedError) { } catch (x: ParsingFailedError) {

View File

@ -70,6 +70,7 @@ fun compileProgram(filepath: Path,
writeAssembly: Boolean, writeAssembly: Boolean,
slowCodegenWarnings: Boolean, slowCodegenWarnings: Boolean,
compilationTarget: String, compilationTarget: String,
libdirs: List<String>,
outputDir: Path): CompilationResult { outputDir: Path): CompilationResult {
var programName = "" var programName = ""
lateinit var programAst: Program lateinit var programAst: Program
@ -89,7 +90,7 @@ fun compileProgram(filepath: Path,
try { try {
val totalTime = measureTimeMillis { val totalTime = measureTimeMillis {
// import main module and everything it needs // import main module and everything it needs
val (ast, compilationOptions, imported) = parseImports(filepath, errors, compTarget) val (ast, compilationOptions, imported) = parseImports(filepath, errors, compTarget, libdirs)
compilationOptions.slowCodegenWarnings = slowCodegenWarnings compilationOptions.slowCodegenWarnings = slowCodegenWarnings
compilationOptions.optimize = optimize compilationOptions.optimize = optimize
programAst = ast programAst = ast
@ -165,14 +166,15 @@ private class BuiltinFunctionsFacade(functions: Map<String, FSignature>): IBuilt
builtinFunctionReturnType(name, args, program) builtinFunctionReturnType(name, args, program)
} }
private fun parseImports(filepath: Path, errors: IErrorReporter, compTarget: ICompilationTarget): Triple<Program, CompilationOptions, List<Path>> { private fun parseImports(filepath: Path, errors: IErrorReporter, compTarget: ICompilationTarget, libdirs: List<String>): Triple<Program, CompilationOptions, List<Path>> {
val compilationTargetName = compTarget.name val compilationTargetName = compTarget.name
println("Compiler target: $compilationTargetName. Parsing...") println("Compiler target: $compilationTargetName. Parsing...")
val importer = ModuleImporter()
val bf = BuiltinFunctionsFacade(BuiltinFunctions) val bf = BuiltinFunctionsFacade(BuiltinFunctions)
val programAst = Program(moduleName(filepath.fileName), mutableListOf(), bf, compTarget) val programAst = Program(moduleName(filepath.fileName), mutableListOf(), bf, compTarget)
bf.program = programAst bf.program = programAst
importer.importModule(programAst, filepath, compTarget, compilationTargetName)
val importer = ModuleImporter(programAst, compTarget, compilationTargetName, libdirs)
importer.importModule(filepath)
errors.report() errors.report()
val importedFiles = programAst.modules.filter { !it.source.startsWith("@embedded@") }.map { it.source } val importedFiles = programAst.modules.filter { !it.source.startsWith("@embedded@") }.map { it.source }
@ -182,11 +184,11 @@ private fun parseImports(filepath: Path, errors: IErrorReporter, compTarget: ICo
// depending on the machine and compiler options we may have to include some libraries // depending on the machine and compiler options we may have to include some libraries
for(lib in compTarget.machine.importLibs(compilerOptions, compilationTargetName)) for(lib in compTarget.machine.importLibs(compilerOptions, compilationTargetName))
importer.importLibraryModule(programAst, lib, compTarget, compilationTargetName) importer.importLibraryModule(lib)
// always import prog8_lib and math // always import prog8_lib and math
importer.importLibraryModule(programAst, "math", compTarget, compilationTargetName) importer.importLibraryModule("math")
importer.importLibraryModule(programAst, "prog8_lib", compTarget, compilationTargetName) importer.importLibraryModule("prog8_lib")
errors.report() errors.report()
return Triple(programAst, compilerOptions, importedFiles) return Triple(programAst, compilerOptions, importedFiles)
} }

View File

@ -25,9 +25,9 @@ fun moduleName(fileName: Path) = fileName.toString().substringBeforeLast('.')
internal fun pathFrom(stringPath: String, vararg rest: String): Path = FileSystems.getDefault().getPath(stringPath, *rest) internal fun pathFrom(stringPath: String, vararg rest: String): Path = FileSystems.getDefault().getPath(stringPath, *rest)
class ModuleImporter { class ModuleImporter(val program: Program, val encoder: IStringEncoding, val compilationTargetName: String, val libdirs: List<String>) {
fun importModule(program: Program, filePath: Path, encoder: IStringEncoding, compilationTargetName: String): Module { fun importModule(filePath: Path): Module {
print("importing '${moduleName(filePath.fileName)}'") print("importing '${moduleName(filePath.fileName)}'")
if(filePath.parent!=null) { if(filePath.parent!=null) {
var importloc = filePath.toString() var importloc = filePath.toString()
@ -42,15 +42,14 @@ class ModuleImporter {
throw ParsingFailedError("No such file: $filePath") throw ParsingFailedError("No such file: $filePath")
val content = filePath.toFile().readText().replace("\r\n", "\n") val content = filePath.toFile().readText().replace("\r\n", "\n")
return importModule(program, CharStreams.fromString(content), filePath, false, encoder, compilationTargetName) return importModule(CharStreams.fromString(content), filePath, false)
} }
fun importLibraryModule(program: Program, name: String, fun importLibraryModule(name: String): Module? {
encoder: IStringEncoding, compilationTargetName: String): Module? {
val import = Directive("%import", listOf( val import = Directive("%import", listOf(
DirectiveArg("", name, 42, position = Position("<<<implicit-import>>>", 0, 0, 0)) DirectiveArg("", name, 42, position = Position("<<<implicit-import>>>", 0, 0, 0))
), Position("<<<implicit-import>>>", 0, 0, 0)) ), Position("<<<implicit-import>>>", 0, 0, 0))
return executeImportDirective(program, import, Paths.get(""), encoder, compilationTargetName) return executeImportDirective(import, Paths.get(""))
} }
private class MyErrorListener: ConsoleErrorListener() { private class MyErrorListener: ConsoleErrorListener() {
@ -67,8 +66,7 @@ class ModuleImporter {
} }
} }
private fun importModule(program: Program, stream: CharStream, modulePath: Path, isLibrary: Boolean, private fun importModule(stream: CharStream, modulePath: Path, isLibrary: Boolean): Module {
encoder: IStringEncoding, compilationTargetName: String): Module {
val moduleName = moduleName(modulePath.fileName) val moduleName = moduleName(modulePath.fileName)
val lexer = CustomLexer(modulePath, stream) val lexer = CustomLexer(modulePath, stream)
lexer.removeErrorListeners() lexer.removeErrorListeners()
@ -97,14 +95,13 @@ class ModuleImporter {
lines.asSequence() lines.asSequence()
.mapIndexed { i, it -> i to it } .mapIndexed { i, it -> i to it }
.filter { (it.second as? Directive)?.directive == "%import" } .filter { (it.second as? Directive)?.directive == "%import" }
.forEach { executeImportDirective(program, it.second as Directive, modulePath, encoder, compilationTargetName) } .forEach { executeImportDirective(it.second as Directive, modulePath) }
moduleAst.statements = lines moduleAst.statements = lines
return moduleAst return moduleAst
} }
private fun executeImportDirective(program: Program, import: Directive, source: Path, private fun executeImportDirective(import: Directive, source: Path): Module? {
encoder: IStringEncoding, compilationTargetName: String): Module? {
if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null) if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null)
throw SyntaxError("invalid import directive", import.position) throw SyntaxError("invalid import directive", import.position)
val moduleName = import.args[0].name!! val moduleName = import.args[0].name!!
@ -123,12 +120,11 @@ class ModuleImporter {
resource.use { resource.use {
println("importing '$moduleName' (library)") println("importing '$moduleName' (library)")
val content = it.reader().readText().replace("\r\n", "\n") val content = it.reader().readText().replace("\r\n", "\n")
importModule(program, CharStreams.fromString(content), Paths.get("@embedded@/$resourcePath"), importModule(CharStreams.fromString(content), Paths.get("@embedded@/$resourcePath"), true)
true, encoder, compilationTargetName)
} }
} else { } else {
val modulePath = tryGetModuleFromFile(moduleName, source, import.position) val modulePath = tryGetModuleFromFile(moduleName, source, import.position)
importModule(program, modulePath, encoder, compilationTargetName) importModule(modulePath)
} }
removeDirectivesFromImportedModule(importedModule) removeDirectivesFromImportedModule(importedModule)
@ -160,15 +156,10 @@ class ModuleImporter {
private fun tryGetModuleFromFile(name: String, source: Path, position: Position?): Path { private fun tryGetModuleFromFile(name: String, source: Path, position: Position?): Path {
val fileName = "$name.p8" val fileName = "$name.p8"
val locations = if(source.toString().isEmpty()) mutableListOf<Path>() else mutableListOf(source.parent ?: Path.of(".")) val libpaths = libdirs.map {Path.of(it)}
val locations =
val propPath = System.getProperty("prog8.libdir") (if(source.toString().isEmpty()) libpaths else libpaths.drop(1) + (source.parent ?: Path.of("."))) +
if(propPath!=null) Paths.get(Paths.get("").toAbsolutePath().toString(), "prog8lib")
locations.add(pathFrom(propPath))
val envPath = System.getenv("PROG8_LIBDIR")
if(envPath!=null)
locations.add(pathFrom(envPath))
locations.add(Paths.get(Paths.get("").toAbsolutePath().toString(), "prog8lib"))
locations.forEach { locations.forEach {
val file = pathFrom(it.toString(), fileName) val file = pathFrom(it.toString(), fileName)

View File

@ -117,11 +117,11 @@ They are embedded into the packaged release version of the compiler so you don't
where they are, but their names are still reserved. where they are, but their names are still reserved.
User defined library files User defined library files and -location
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can create library files yourself too that can be shared among programs. You can create library files yourself too that can be shared among programs.
You can tell the compiler where it should look for these files, by setting the java command line property ``prog8.libdir`` You can tell the compiler where it should look for these files, by using
or by setting the ``PROG8_LIBDIR`` environment variable to the correct directory. the libdirs command line option.
.. _debugging: .. _debugging:

View File

@ -29,7 +29,7 @@ class RequestParser : Take {
val form = RqFormBase(request) val form = RqFormBase(request)
val names = form.names() val names = form.names()
val a = form.param("a").single() val a = form.param("a").single()
val compilationResult = compileProgram(Path.of(a), true, true, true, "c64", Path.of(".")) val compilationResult = compileProgram(Path.of(a), true, true, true, "c64", emptyList<String>(), Path.of("."))
return RsJson(Jsonding()) return RsJson(Jsonding())
} }
} }