reducing ast dependencies

This commit is contained in:
Irmen de Jong 2021-02-07 19:38:20 +01:00
parent 1070dedd7c
commit 9e05e97d7f
7 changed files with 56 additions and 34 deletions

View File

@ -127,12 +127,13 @@ private class BuiltinFunctionsFacade(functions: Map<String, FSignature>): IBuilt
}
private fun parseImports(filepath: Path, errors: ErrorReporter): Triple<Program, CompilationOptions, List<Path>> {
println("Compiler target: ${CompilationTarget.instance.name}. Parsing...")
val compilationTargetName = CompilationTarget.instance.name
println("Compiler target: $compilationTargetName. Parsing...")
val importer = ModuleImporter()
val bf = BuiltinFunctionsFacade(BuiltinFunctions)
val programAst = Program(moduleName(filepath.fileName), mutableListOf(), bf)
bf.program = programAst
importer.importModule(programAst, filepath)
importer.importModule(programAst, filepath, CompilationTarget.instance, compilationTargetName)
errors.handle()
val importedFiles = programAst.modules.filter { !it.source.startsWith("@embedded@") }.map { it.source }
@ -142,11 +143,11 @@ private fun parseImports(filepath: Path, errors: ErrorReporter): Triple<Program,
throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.")
// depending on the machine and compiler options we may have to include some libraries
CompilationTarget.instance.machine.importLibs(compilerOptions, importer, programAst)
CompilationTarget.instance.machine.importLibs(compilerOptions, importer, programAst, CompilationTarget.instance, compilationTargetName)
// always import prog8_lib and math
importer.importLibraryModule(programAst, "math")
importer.importLibraryModule(programAst, "prog8_lib")
importer.importLibraryModule(programAst, "math", CompilationTarget.instance, compilationTargetName)
importer.importLibraryModule(programAst, "prog8_lib", CompilationTarget.instance, compilationTargetName)
errors.handle()
return Triple(programAst, compilerOptions, importedFiles)
}

View File

@ -1,6 +1,5 @@
package prog8.compiler.astprocessing
import prog8.ast.Module
import prog8.ast.Program
import prog8.ast.base.ErrorReporter
import prog8.ast.base.FatalAstException
@ -37,12 +36,6 @@ internal fun Program.verifyFunctionArgTypes() {
fixer.visit(this)
}
internal fun Module.checkImportedValid() {
val imr = ImportedModuleDirectiveRemover()
imr.visit(this, this.parent)
imr.applyModifications()
}
internal fun Program.checkIdentifiers(errors: ErrorReporter) {
val checker2 = AstIdentifiersChecker(this, errors)

View File

@ -12,6 +12,8 @@ internal class ImportedModuleDirectiveRemover: AstWalker() {
* Most global directives don't apply for imported modules, so remove them
*/
// TODO don't use an AstWalker for this, do it directly on the imported module
private val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address")
private val noModifications = emptyList<IAstModification>()

View File

@ -1,5 +1,6 @@
package prog8.compiler.target
import prog8.ast.IStringEncoding
import prog8.ast.Program
import prog8.compiler.CompilationOptions
import prog8.compiler.Zeropage
@ -32,7 +33,11 @@ internal interface IMachineDefinition {
fun initializeZeropage(compilerOptions: CompilationOptions)
fun getFloat(num: Number): IMachineFloat
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program)
// TODO don't do the importing here, just return a list of modules to import...:
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program,
encoder: IStringEncoding, compilationTargetName: String)
fun launchEmulator(programName: String)
fun isRegularRAMaddress(address: Int): Boolean
}

View File

@ -1,5 +1,6 @@
package prog8.compiler.target.c64
import prog8.ast.IStringEncoding
import prog8.ast.Program
import prog8.compiler.*
import prog8.compiler.target.CpuType
@ -30,9 +31,15 @@ internal object C64MachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = Mflpt5.fromNumber(num)
override fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program) {
override fun importLibs(
compilerOptions: CompilationOptions,
importer: ModuleImporter,
program: Program,
encoder: IStringEncoding,
compilationTargetName: String)
{
if (compilerOptions.launcher == LauncherType.BASIC || compilerOptions.output == OutputType.PRG)
importer.importLibraryModule(program, "syslib")
importer.importLibraryModule(program, "syslib", encoder, compilationTargetName)
}
override fun launchEmulator(programName: String) {

View File

@ -1,5 +1,6 @@
package prog8.compiler.target.cx16
import prog8.ast.IStringEncoding
import prog8.ast.Program
import prog8.compiler.*
import prog8.compiler.target.CpuType
@ -28,9 +29,15 @@ internal object CX16MachineDefinition: IMachineDefinition {
override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num)
override fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program) {
override fun importLibs(
compilerOptions: CompilationOptions,
importer: ModuleImporter,
program: Program,
encoder: IStringEncoding,
compilationTargetName: String)
{
if (compilerOptions.launcher == LauncherType.BASIC || compilerOptions.output == OutputType.PRG)
importer.importLibraryModule(program, "syslib")
importer.importLibraryModule(program, "syslib", encoder, compilationTargetName)
}
override fun launchEmulator(programName: String) {

View File

@ -1,6 +1,7 @@
package prog8.parser
import org.antlr.v4.runtime.*
import prog8.ast.IStringEncoding
import prog8.ast.Module
import prog8.ast.Program
import prog8.ast.antlr.toAst
@ -8,8 +9,7 @@ import prog8.ast.base.Position
import prog8.ast.base.SyntaxError
import prog8.ast.statements.Directive
import prog8.ast.statements.DirectiveArg
import prog8.compiler.astprocessing.checkImportedValid
import prog8.compiler.target.CompilationTarget
import prog8.compiler.astprocessing.ImportedModuleDirectiveRemover
import prog8.pathFrom
import java.io.InputStream
import java.nio.file.Files
@ -28,7 +28,7 @@ internal fun moduleName(fileName: Path) = fileName.toString().substringBeforeLas
internal class ModuleImporter {
internal fun importModule(program: Program, filePath: Path): Module {
internal fun importModule(program: Program, filePath: Path, encoder: IStringEncoding, compilationTargetName: String): Module {
print("importing '${moduleName(filePath.fileName)}'")
if(filePath.parent!=null) {
var importloc = filePath.toString()
@ -43,14 +43,15 @@ internal class ModuleImporter {
throw ParsingFailedError("No such file: $filePath")
val input = CharStreams.fromPath(filePath)
return importModule(program, input, filePath, false)
return importModule(program, input, filePath, false, encoder, compilationTargetName)
}
internal fun importLibraryModule(program: Program, name: String): Module? {
internal fun importLibraryModule(program: Program, name: String,
encoder: IStringEncoding, compilationTargetName: String): Module? {
val import = Directive("%import", listOf(
DirectiveArg("", name, 42, position = Position("<<<implicit-import>>>", 0, 0, 0))
), Position("<<<implicit-import>>>", 0, 0, 0))
return executeImportDirective(program, import, Paths.get(""))
return executeImportDirective(program, import, Paths.get(""), encoder, compilationTargetName)
}
private class MyErrorListener: ConsoleErrorListener() {
@ -65,7 +66,8 @@ internal class ModuleImporter {
}
}
private fun importModule(program: Program, stream: CharStream, modulePath: Path, isLibrary: Boolean): Module {
private fun importModule(program: Program, stream: CharStream, modulePath: Path, isLibrary: Boolean,
encoder: IStringEncoding, compilationTargetName: String): Module {
val moduleName = moduleName(modulePath.fileName)
val lexer = CustomLexer(modulePath, stream)
lexer.removeErrorListeners()
@ -84,7 +86,7 @@ internal class ModuleImporter {
// tokens.commentTokens().forEach { println(it) }
// convert to Ast
val moduleAst = parseTree.toAst(moduleName, isLibrary, modulePath, CompilationTarget.instance)
val moduleAst = parseTree.toAst(moduleName, isLibrary, modulePath, encoder)
moduleAst.program = program
moduleAst.linkParents(program.namespace)
program.modules.add(moduleAst)
@ -94,13 +96,14 @@ internal class ModuleImporter {
lines.asSequence()
.mapIndexed { i, it -> i to it }
.filter { (it.second as? Directive)?.directive == "%import" }
.forEach { executeImportDirective(program, it.second as Directive, modulePath) }
.forEach { executeImportDirective(program, it.second as Directive, modulePath, encoder, compilationTargetName) }
moduleAst.statements = lines
return moduleAst
}
private fun executeImportDirective(program: Program, import: Directive, source: Path): Module? {
private fun executeImportDirective(program: Program, import: Directive, source: Path,
encoder: IStringEncoding, compilationTargetName: String): Module? {
if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null)
throw SyntaxError("invalid import directive", import.position)
val moduleName = import.args[0].name!!
@ -111,27 +114,31 @@ internal class ModuleImporter {
if(existing!=null)
return null
val rsc = tryGetModuleFromResource("$moduleName.p8")
val rsc = tryGetModuleFromResource("$moduleName.p8", compilationTargetName)
val importedModule =
if(rsc!=null) {
// load the module from the embedded resource
val (resource, resourcePath) = rsc
resource.use {
println("importing '$moduleName' (library)")
importModule(program, CharStreams.fromStream(it), Paths.get("@embedded@/$resourcePath"), true)
importModule(program, CharStreams.fromStream(it), Paths.get("@embedded@/$resourcePath"),
true, encoder, compilationTargetName)
}
} else {
val modulePath = tryGetModuleFromFile(moduleName, source, import.position)
importModule(program, modulePath)
importModule(program, modulePath, encoder, compilationTargetName)
}
importedModule.checkImportedValid()
// TODO don't do this via an AstWalker:
val imr = ImportedModuleDirectiveRemover()
imr.visit(importedModule, importedModule.parent)
imr.applyModifications()
return importedModule
}
private fun tryGetModuleFromResource(name: String): Pair<InputStream, String>? {
val target = CompilationTarget.instance.name
val targetSpecificPath = "/prog8lib/$target/$name"
private fun tryGetModuleFromResource(name: String, compilationTargetName: String): Pair<InputStream, String>? {
val targetSpecificPath = "/prog8lib/$compilationTargetName/$name"
val targetSpecificResource = object{}.javaClass.getResourceAsStream(targetSpecificPath)
if(targetSpecificResource!=null)
return Pair(targetSpecificResource, targetSpecificPath)