cleanup SourceCode class

This commit is contained in:
Irmen de Jong 2021-10-13 18:55:56 +02:00
parent 975594703d
commit 6070afa6b6
14 changed files with 170 additions and 160 deletions

View File

@ -18,6 +18,7 @@ import prog8.compiler.target.ICompilationTarget
import prog8.compiler.target.asmGeneratorFor import prog8.compiler.target.asmGeneratorFor
import prog8.optimizer.* import prog8.optimizer.*
import prog8.parser.ParsingFailedError import prog8.parser.ParsingFailedError
import prog8.parser.SourceCode
import prog8.parser.SourceCode.Companion.libraryFilePrefix import prog8.parser.SourceCode.Companion.libraryFilePrefix
import java.io.File import java.io.File
import java.nio.file.Path import java.nio.file.Path
@ -185,9 +186,8 @@ fun parseImports(filepath: Path,
importedModuleResult.onFailure { throw it } importedModuleResult.onFailure { throw it }
errors.report() errors.report()
val importedFiles = programAst.modules val importedFiles = programAst.modules.map { it.source }
.mapNotNull { it.source } .filter { it !is SourceCode.Generated && !it.isFromResources } // TODO: parseImports/importedFiles - maybe rather `source.isFromFilesystem`?
.filter { !it.isFromResources } // TODO: parseImports/importedFiles - maybe rather `source.isFromFilesystem`?
.map { Path(it.pathString()) } .map { Path(it.pathString()) }
val compilerOptions = determineCompilationOptions(programAst, compTarget) val compilerOptions = determineCompilationOptions(programAst, compTarget)
if (compilerOptions.launcher == LauncherType.BASIC && compilerOptions.output != OutputType.PRG) if (compilerOptions.launcher == LauncherType.BASIC && compilerOptions.output != OutputType.PRG)

View File

@ -42,7 +42,7 @@ class ModuleImporter(private val program: Program,
val logMsg = "importing '${filePath.nameWithoutExtension}' (from file $srcPath)" val logMsg = "importing '${filePath.nameWithoutExtension}' (from file $srcPath)"
println(logMsg) println(logMsg)
return Ok(importModule(SourceCode.fromPath(srcPath))) return Ok(importModule(SourceCode.File(srcPath)))
} }
fun importLibraryModule(name: String): Module? { fun importLibraryModule(name: String): Module? {
@ -110,11 +110,11 @@ class ModuleImporter(private val program: Program,
private fun tryGetModuleFromResource(name: String, compilationTargetName: String): SourceCode? { private fun tryGetModuleFromResource(name: String, compilationTargetName: String): SourceCode? {
// try target speficic first // try target speficic first
try { try {
return SourceCode.fromResources("/prog8lib/$compilationTargetName/$name") return SourceCode.Resource("/prog8lib/$compilationTargetName/$name")
} catch (e: FileSystemException) { } catch (e: FileSystemException) {
} }
try { try {
return SourceCode.fromResources("/prog8lib/$name") return SourceCode.Resource("/prog8lib/$name")
} catch (e: FileSystemException) { } catch (e: FileSystemException) {
} }
return null return null
@ -134,7 +134,7 @@ class ModuleImporter(private val program: Program,
locations.forEach { locations.forEach {
try { try {
return SourceCode.fromPath(it.resolve(fileName)) return SourceCode.File(it.resolve(fileName))
} catch (e: NoSuchFileException) { } catch (e: NoSuchFileException) {
} }
} }

View File

@ -13,6 +13,7 @@ import prog8.compiler.ZeropageType
import prog8.compiler.functions.BuiltinFunctions import prog8.compiler.functions.BuiltinFunctions
import prog8.compiler.functions.builtinFunctionReturnType import prog8.compiler.functions.builtinFunctionReturnType
import prog8.compiler.target.ICompilationTarget import prog8.compiler.target.ICompilationTarget
import prog8.parser.SourceCode
import java.io.CharConversionException import java.io.CharConversionException
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -726,20 +727,16 @@ internal class AstChecker(private val program: Program,
if (File(filename).isFile) if (File(filename).isFile)
return return
var definingModule = directive.parent // TODO: why not just use directive.definingModule() here? val definingModule = directive.definingModule
while (definingModule !is Module) if (definingModule.isLibrary || definingModule.source is SourceCode.Generated)
definingModule = definingModule.parent
if (definingModule.isLibrary)
return return
val s = definingModule.source?.pathString() val s = definingModule.source.pathString()
if (s != null) { val sourceFileCandidate = Path(s).resolveSibling(filename).toFile()
val sourceFileCandidate = Path(s).resolveSibling(filename).toFile() if (sourceFileCandidate.isFile)
if (sourceFileCandidate.isFile) return
return else
} errors.err("included file not found: $filename", directive.position)
errors.err("included file not found: $filename", directive.position)
} }
override fun visit(array: ArrayLiteralValue) { override fun visit(array: ArrayLiteralValue) {

View File

@ -1325,7 +1325,7 @@ $repeatLabel lda $counterVar
"%asminclude" -> { "%asminclude" -> {
// TODO: handle %asminclude with SourceCode // TODO: handle %asminclude with SourceCode
val includedName = stmt.args[0].str!! val includedName = stmt.args[0].str!!
val sourcePath = Path(stmt.definingModule.source!!.pathString()) // FIXME: %asminclude inside non-library, non-filesystem module val sourcePath = Path(stmt.definingModule.source.pathString()) // FIXME: %asminclude inside non-library, non-filesystem module
loadAsmIncludeFile(includedName, sourcePath).fold( loadAsmIncludeFile(includedName, sourcePath).fold(
success = { assemblyLines.add(it.trimEnd().trimStart('\n')) }, success = { assemblyLines.add(it.trimEnd().trimStart('\n')) },
failure = { errors.err(it.toString(), stmt.position) } failure = { errors.err(it.toString(), stmt.position) }
@ -1335,7 +1335,7 @@ $repeatLabel lda $counterVar
val includedName = stmt.args[0].str!! val includedName = stmt.args[0].str!!
val offset = if(stmt.args.size>1) ", ${stmt.args[1].int}" else "" val offset = if(stmt.args.size>1) ", ${stmt.args[1].int}" else ""
val length = if(stmt.args.size>2) ", ${stmt.args[2].int}" else "" val length = if(stmt.args.size>2) ", ${stmt.args[2].int}" else ""
val sourcePath = Path(stmt.definingModule.source!!.pathString()) // FIXME: %asmbinary inside non-library, non-filesystem module val sourcePath = Path(stmt.definingModule.source.pathString()) // FIXME: %asmbinary inside non-library, non-filesystem module
val includedPath = sourcePath.resolveSibling(includedName) val includedPath = sourcePath.resolveSibling(includedName)
val pathForAssembler = outputDir // #54: 64tass needs the path *relative to the .asm file* val pathForAssembler = outputDir // #54: 64tass needs the path *relative to the .asm file*
.absolute() // avoid IllegalArgumentExc due to non-absolute path .relativize(absolute path) .absolute() // avoid IllegalArgumentExc due to non-absolute path .relativize(absolute path)

View File

@ -15,6 +15,7 @@ import prog8.compiler.*
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.cpu6502.codegen.AsmGen import prog8.compiler.target.cpu6502.codegen.AsmGen
import prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions
import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyMemsizer
import java.nio.file.Path import java.nio.file.Path
@ -67,7 +68,7 @@ locallabel:
val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, Position.DUMMY) val varInBlock = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", null, false, false, false, Position.DUMMY)
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY) val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
val module = Module("test", mutableListOf(block), Position.DUMMY, null) val module = Module("test", mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)

View File

@ -14,6 +14,7 @@ import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.PrefixExpression import prog8.ast.expressions.PrefixExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions
import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyMemsizer
import kotlin.test.assertFalse import kotlin.test.assertFalse
@ -91,7 +92,7 @@ class TestMemory {
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
module.linkParents(program.namespace) module.linkParents(program.namespace)
return target return target
} }
@ -110,7 +111,7 @@ class TestMemory {
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)
@ -124,7 +125,7 @@ class TestMemory {
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)
@ -138,7 +139,7 @@ class TestMemory {
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)
@ -152,7 +153,7 @@ class TestMemory {
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)
@ -167,7 +168,7 @@ class TestMemory {
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)
@ -182,7 +183,7 @@ class TestMemory {
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY)
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null) val module = Module("test", mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
val program = Program("test", DummyFunctions, DummyMemsizer) val program = Program("test", DummyFunctions, DummyMemsizer)
.addModule(module) .addModule(module)
module.linkParents(program.namespace) module.linkParents(program.namespace)

View File

@ -246,7 +246,8 @@ class Program(val name: String,
init { init {
// insert a container module for all interned strings later // insert a container module for all interned strings later
val internedStringsModule = Module(internedStringsModuleName, mutableListOf(), Position.DUMMY, null) val internedStringsModule = Module(internedStringsModuleName, mutableListOf(),
Position.DUMMY, SourceCode.Generated(internedStringsModuleName))
val block = Block(internedStringsModuleName, null, mutableListOf(), true, Position.DUMMY) val block = Block(internedStringsModuleName, null, mutableListOf(), true, Position.DUMMY)
internedStringsModule.statements.add(block) internedStringsModule.statements.add(block)
@ -350,7 +351,7 @@ class Program(val name: String,
open class Module(override val name: String, open class Module(override val name: String,
override var statements: MutableList<Statement>, override var statements: MutableList<Statement>,
final override val position: Position, final override val position: Position,
val source: SourceCode?) : Node, INameScope { val source: SourceCode) : Node, INameScope {
override lateinit var parent: Node override lateinit var parent: Node
lateinit var program: Program lateinit var program: Program
@ -380,7 +381,7 @@ open class Module(override val name: String,
fun accept(visitor: IAstVisitor) = visitor.visit(this) fun accept(visitor: IAstVisitor) = visitor.visit(this)
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
val isLibrary get() = (source == null) || source.isFromResources val isLibrary get() = source.isFromResources
} }

View File

@ -3,6 +3,7 @@ package prog8.parser
import org.antlr.v4.runtime.CharStream import org.antlr.v4.runtime.CharStream
import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CharStreams
import java.io.File import java.io.File
import java.io.IOException
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.absolutePathString import kotlin.io.path.absolutePathString
import kotlin.io.path.exists import kotlin.io.path.exists
@ -13,7 +14,7 @@ import kotlin.io.path.isReadable
* Encapsulates - and ties together - actual source code (=text) * Encapsulates - and ties together - actual source code (=text)
* and its [origin]. * and its [origin].
*/ */
abstract class SourceCode { sealed class SourceCode {
/** /**
* To be used *only* by the parser (as input to a TokenStream). * To be used *only* by the parser (as input to a TokenStream).
@ -23,16 +24,16 @@ abstract class SourceCode {
/** /**
* Whether this [SourceCode] instance was created by * Whether this [SourceCode] instance was created by
* factory method [fromResources] * factory method [Resource]
*/ */
abstract val isFromResources: Boolean abstract val isFromResources: Boolean
/** /**
* Where this [SourceCode] instance came from. * Where this [SourceCode] instance came from.
* This can be one of the following: * This can be one of the following:
* * a normal string representation of a [java.nio.file.Path], if it originates from a file (see [fromPath]) * * a normal string representation of a [java.nio.file.Path], if it originates from a file (see [File])
* * `<String@44c56085>` if was created via [of] * * `<String@44c56085>` if was created via [String]
* * `library:/x/y/z.ext` if it is a library file that was loaded from resources (see [fromResources]) * * `library:/x/y/z.ext` if it is a library file that was loaded from resources (see [Resource])
*/ */
abstract val origin: String abstract val origin: String
@ -42,9 +43,7 @@ abstract class SourceCode {
* This is really just [origin] with any stuff removed that would render it an invalid path name. * This is really just [origin] with any stuff removed that would render it an invalid path name.
* (Note: a *valid* path name does NOT mean that the denoted file or folder *exists*) * (Note: a *valid* path name does NOT mean that the denoted file or folder *exists*)
*/ */
fun pathString() = fun pathString() = origin.substringAfter("<").substringBeforeLast(">") // or from plain string?
origin
.substringAfter("<").substringBeforeLast(">") // or from plain string?
/** /**
* The source code as plain string. * The source code as plain string.
@ -58,42 +57,39 @@ abstract class SourceCode {
*/ */
final override fun toString() = "${this.javaClass.name}[${this.origin}]" final override fun toString() = "${this.javaClass.name}[${this.origin}]"
// "static" factory methods
companion object { companion object {
/** /**
* filename prefix to designate library files that will be retreived from internal resources rather than disk * filename prefix to designate library files that will be retreived from internal resources rather than disk
*/ */
const val libraryFilePrefix = "library:" const val libraryFilePrefix = "library:"
}
/** /**
* Turn a plain String into a [SourceCode] object. * Turn a plain String into a [SourceCode] object.
* [origin] will be something like `<String@44c56085>`. * [origin] will be something like `<String@44c56085>`.
*/ */
fun of(text: String): SourceCode { class Text(val text: String): SourceCode() {
return object : SourceCode() { override val isFromResources = false
override val isFromResources = false override val origin = "<String@${System.identityHashCode(text).toString(16)}>"
override val origin = "<String@${System.identityHashCode(text).toString(16)}>" override fun getCharStream(): CharStream = CharStreams.fromString(text)
override fun getCharStream(): CharStream { }
return CharStreams.fromString(text)
}
}
}
/** /**
* Get [SourceCode] from the file represented by the specified Path. * Get [SourceCode] from the file represented by the specified Path.
* This does not actually *access* the file, but it does check * This does not actually *access* the file, but it does check
* whether it * whether it
* * exists * * exists
* * is a regular file (ie: not a directory) * * is a regular file (ie: not a directory)
* * and is actually readable * * and is actually readable
* *
* [origin] will be the given path in absolute and normalized form. * [origin] will be the given path in absolute and normalized form.
* @throws NoSuchFileException if the file does not exist * @throws NoSuchFileException if the file does not exist
* @throws AccessDeniedException if the given path points to a directory or the file is non-readable for some other reason * @throws AccessDeniedException if the given path points to a directory or the file is non-readable for some other reason
*/ */
fun fromPath(path: Path): SourceCode { class File(path: Path): SourceCode() {
val normalized = path.normalize() private val normalized = path.normalize()
init {
val file = normalized.toFile() val file = normalized.toFile()
if (!path.exists()) if (!path.exists())
throw NoSuchFileException(file) throw NoSuchFileException(file)
@ -101,40 +97,48 @@ abstract class SourceCode {
throw AccessDeniedException(file, reason = "Not a file but a directory") throw AccessDeniedException(file, reason = "Not a file but a directory")
if (!path.isReadable()) if (!path.isReadable())
throw AccessDeniedException(file, reason = "Is not readable") throw AccessDeniedException(file, reason = "Is not readable")
return object : SourceCode() {
override val isFromResources = false
override val origin = normalized.absolutePathString()
override fun getCharStream(): CharStream {
return CharStreams.fromPath(normalized)
}
}
} }
/** override val isFromResources = false
* [origin]: `<library:/x/y/z.p8>` for a given `pathString` of "x/y/z.p8" override val origin = normalized.absolutePathString()
*/ override fun getCharStream(): CharStream = CharStreams.fromPath(normalized)
fun fromResources(pathString: String): SourceCode { }
val path = Path.of(pathString).normalize()
val sep = "/" /**
val normalized = sep + path.toMutableList().joinToString(sep) * [origin]: `<library:/x/y/z.p8>` for a given `pathString` of "x/y/z.p8"
val rscURL = object{}.javaClass.getResource(normalized) */
class Resource(pathString: String): SourceCode() {
private val normalized = "/" + Path.of(pathString).normalize().toMutableList().joinToString("/")
init {
val rscURL = object {}.javaClass.getResource(normalized)
if (rscURL == null) { if (rscURL == null) {
val rscRoot = object{}.javaClass.getResource("/") val rscRoot = object {}.javaClass.getResource("/")
throw NoSuchFileException( throw NoSuchFileException(
File(normalized), File(normalized),
reason = "looked in resources rooted at $rscRoot") reason = "looked in resources rooted at $rscRoot"
} )
return object : SourceCode() {
override val isFromResources = true
override val origin = "$libraryFilePrefix$normalized"
override fun getCharStream(): CharStream {
val inpStr = object {}.javaClass.getResourceAsStream(normalized)
return CharStreams.fromStream(inpStr)
}
} }
} }
// TODO: possibly more, like fromURL(..) override val isFromResources = true
override val origin = "$libraryFilePrefix$normalized"
override fun getCharStream(): CharStream {
val inpStr = object {}.javaClass.getResourceAsStream(normalized)
return CharStreams.fromStream(inpStr)
}
}
/**
* SourceCode for internally generated nodes (usually Modules)
*/
class Generated(name: String) : SourceCode() {
override fun getCharStream(): CharStream = throw IOException("generated code doesn't have a stream to read")
override val isFromResources: Boolean = false
override val origin: String = name
}
// TODO: possibly more, like fromURL(..)
/* // For `jar:..` URLs /* // For `jar:..` URLs
// see https://stackoverflow.com/questions/22605666/java-access-files-in-jar-causes-java-nio-file-filesystemnotfoundexception // see https://stackoverflow.com/questions/22605666/java-access-files-in-jar-causes-java-nio-file-filesystemnotfoundexception
var url = URL("jar:file:/E:/x16/prog8(meisl)/compiler/build/libs/prog8compiler-7.0-BETA3-all.jar!/prog8lib/c64/textio.p8") var url = URL("jar:file:/E:/x16/prog8(meisl)/compiler/build/libs/prog8compiler-7.0-BETA3-all.jar!/prog8lib/c64/textio.p8")
@ -143,5 +147,4 @@ abstract class SourceCode {
val fs = FileSystems.newFileSystem(URI.create(parts[0]), mutableMapOf(Pair("", "")) ) val fs = FileSystems.newFileSystem(URI.create(parts[0]), mutableMapOf(Pair("", "")) )
val path = fs.getPath(parts[1]) val path = fs.getPath(parts[1])
*/ */
}
} }

View File

@ -31,7 +31,7 @@ class TestAstToSourceCode {
private fun roundTrip(module: Module): Pair<String, Module> { private fun roundTrip(module: Module): Pair<String, Module> {
val generatedText = generateP8(module) val generatedText = generateP8(module)
try { try {
val parsedAgain = parseModule(SourceCode.of(generatedText)) val parsedAgain = parseModule(SourceCode.Text(generatedText))
return Pair(generatedText, parsedAgain) return Pair(generatedText, parsedAgain)
} catch (e: ParseError) { } catch (e: ParseError) {
assert(false) { "should produce valid Prog8 but threw $e" } assert(false) { "should produce valid Prog8 but threw $e" }
@ -41,7 +41,7 @@ class TestAstToSourceCode {
@Test @Test
fun testMentionsInternedStringsModule() { fun testMentionsInternedStringsModule() {
val orig = SourceCode.of("\n") val orig = SourceCode.Text("\n")
val (txt, _) = roundTrip(parseModule(orig)) val (txt, _) = roundTrip(parseModule(orig))
// assertContains has *actual* first! // assertContains has *actual* first!
assertContains(txt, Regex(";.*$internedStringsModuleName")) assertContains(txt, Regex(";.*$internedStringsModuleName"))
@ -49,7 +49,7 @@ class TestAstToSourceCode {
@Test @Test
fun testImportDirectiveWithLib() { fun testImportDirectiveWithLib() {
val orig = SourceCode.of("%import textio\n") val orig = SourceCode.Text("%import textio\n")
val (txt, _) = roundTrip(parseModule(orig)) val (txt, _) = roundTrip(parseModule(orig))
// assertContains has *actual* first! // assertContains has *actual* first!
assertContains(txt, Regex("%import +textio")) assertContains(txt, Regex("%import +textio"))
@ -57,7 +57,7 @@ class TestAstToSourceCode {
@Test @Test
fun testImportDirectiveWithUserModule() { fun testImportDirectiveWithUserModule() {
val orig = SourceCode.of("%import my_own_stuff\n") val orig = SourceCode.Text("%import my_own_stuff\n")
val (txt, _) = roundTrip(parseModule(orig)) val (txt, _) = roundTrip(parseModule(orig))
// assertContains has *actual* first! // assertContains has *actual* first!
assertContains(txt, Regex("%import +my_own_stuff")) assertContains(txt, Regex("%import +my_own_stuff"))
@ -66,7 +66,7 @@ class TestAstToSourceCode {
@Test @Test
fun testStringLiteral_noAlt() { fun testStringLiteral_noAlt() {
val orig = SourceCode.of(""" val orig = SourceCode.Text("""
main { main {
str s = "fooBar\n" str s = "fooBar\n"
} }
@ -78,7 +78,7 @@ class TestAstToSourceCode {
@Test @Test
fun testStringLiteral_withAlt() { fun testStringLiteral_withAlt() {
val orig = SourceCode.of(""" val orig = SourceCode.Text("""
main { main {
str sAlt = @"fooBar\n" str sAlt = @"fooBar\n"
} }
@ -90,7 +90,7 @@ class TestAstToSourceCode {
@Test @Test
fun testCharLiteral_noAlt() { fun testCharLiteral_noAlt() {
val orig = SourceCode.of(""" val orig = SourceCode.Text("""
main { main {
ubyte c = 'x' ubyte c = 'x'
} }
@ -102,7 +102,7 @@ class TestAstToSourceCode {
@Test @Test
fun testCharLiteral_withAlt() { fun testCharLiteral_withAlt() {
val orig = SourceCode.of(""" val orig = SourceCode.Text("""
main { main {
ubyte cAlt = @'x' ubyte cAlt = @'x'
} }

View File

@ -39,7 +39,7 @@ class TestProg8Parser {
@Test @Test
fun `is not required - #40, fixed by #45`() { fun `is not required - #40, fixed by #45`() {
val nl = "\n" // say, Unix-style (different flavours tested elsewhere) val nl = "\n" // say, Unix-style (different flavours tested elsewhere)
val src = SourceCode.of("foo {" + nl + "}") // source ends with '}' (= NO newline, issue #40) val src = SourceCode.Text("foo {" + nl + "}") // source ends with '}' (= NO newline, issue #40)
// #40: Prog8ANTLRParser would report (throw) "missing <EOL> at '<EOF>'" // #40: Prog8ANTLRParser would report (throw) "missing <EOL> at '<EOF>'"
val module = parseModule(src) val module = parseModule(src)
@ -50,7 +50,7 @@ class TestProg8Parser {
fun `is still accepted - #40, fixed by #45`() { fun `is still accepted - #40, fixed by #45`() {
val nl = "\n" // say, Unix-style (different flavours tested elsewhere) val nl = "\n" // say, Unix-style (different flavours tested elsewhere)
val srcText = "foo {" + nl + "}" + nl // source does end with a newline (issue #40) val srcText = "foo {" + nl + "}" + nl // source does end with a newline (issue #40)
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertEquals(1, module.statements.size) assertEquals(1, module.statements.size)
} }
} }
@ -65,22 +65,22 @@ class TestProg8Parser {
// GOOD: 2nd block `bar` does start on a new line; however, a nl at the very end ain't needed // GOOD: 2nd block `bar` does start on a new line; however, a nl at the very end ain't needed
val srcGood = "foo {" + nl + "}" + nl + "bar {" + nl + "}" val srcGood = "foo {" + nl + "}" + nl + "bar {" + nl + "}"
assertFailsWith<ParseError> { parseModule(SourceCode.of(srcBad)) } assertFailsWith<ParseError> { parseModule(SourceCode.Text(srcBad)) }
val module = parseModule(SourceCode.of(srcGood)) val module = parseModule(SourceCode.Text(srcGood))
assertEquals(2, module.statements.size) assertEquals(2, module.statements.size)
} }
@Test @Test
fun `is required between two Blocks or Directives - #47`() { fun `is required between two Blocks or Directives - #47`() {
// block and block // block and block
assertFailsWith<ParseError>{ parseModule(SourceCode.of(""" assertFailsWith<ParseError>{ parseModule(SourceCode.Text("""
blockA { blockA {
} blockB { } blockB {
} }
""")) } """)) }
// block and directive // block and directive
assertFailsWith<ParseError>{ parseModule(SourceCode.of(""" assertFailsWith<ParseError>{ parseModule(SourceCode.Text("""
blockB { blockB {
} %import textio } %import textio
""")) } """)) }
@ -89,12 +89,12 @@ class TestProg8Parser {
// Leaving them in anyways. // Leaving them in anyways.
// dir and block // dir and block
assertFailsWith<ParseError>{ parseModule(SourceCode.of(""" assertFailsWith<ParseError>{ parseModule(SourceCode.Text("""
%import textio blockB { %import textio blockB {
} }
""")) } """)) }
assertFailsWith<ParseError>{ parseModule(SourceCode.of(""" assertFailsWith<ParseError>{ parseModule(SourceCode.Text("""
%import textio %import syslib %import textio %import syslib
""")) } """)) }
} }
@ -123,7 +123,7 @@ class TestProg8Parser {
"}" + "}" +
nlUnix // end with newline (see testModuleSourceNeedNotEndWithNewline) nlUnix // end with newline (see testModuleSourceNeedNotEndWithNewline)
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertEquals(2, module.statements.size) assertEquals(2, module.statements.size)
} }
} }
@ -142,7 +142,7 @@ class TestProg8Parser {
blockA { blockA {
} }
""" """
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertEquals(1, module.statements.size) assertEquals(1, module.statements.size)
} }
@ -159,7 +159,7 @@ class TestProg8Parser {
blockB { blockB {
} }
""" """
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertEquals(2, module.statements.size) assertEquals(2, module.statements.size)
} }
@ -174,7 +174,7 @@ class TestProg8Parser {
; comment ; comment
""" """
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertEquals(1, module.statements.size) assertEquals(1, module.statements.size)
} }
} }
@ -187,7 +187,7 @@ class TestProg8Parser {
val importedNoExt = assumeNotExists(fixturesDir, "i_do_not_exist") val importedNoExt = assumeNotExists(fixturesDir, "i_do_not_exist")
assumeNotExists(fixturesDir, "i_do_not_exist.p8") assumeNotExists(fixturesDir, "i_do_not_exist.p8")
val text = "%import ${importedNoExt.name}" val text = "%import ${importedNoExt.name}"
val module = parseModule(SourceCode.of(text)) val module = parseModule(SourceCode.Text(text))
assertEquals(1, module.statements.size) assertEquals(1, module.statements.size)
} }
@ -198,14 +198,14 @@ class TestProg8Parser {
inner class EmptySourcecode { inner class EmptySourcecode {
@Test @Test
fun `from an empty string should result in empty Module`() { fun `from an empty string should result in empty Module`() {
val module = parseModule(SourceCode.of("")) val module = parseModule(SourceCode.Text(""))
assertEquals(0, module.statements.size) assertEquals(0, module.statements.size)
} }
@Test @Test
fun `from an empty file should result in empty Module`() { fun `from an empty file should result in empty Module`() {
val path = assumeReadableFile(fixturesDir, "empty.p8") val path = assumeReadableFile(fixturesDir, "empty.p8")
val module = parseModule(SourceCode.fromPath(path)) val module = parseModule(SourceCode.File(path))
assertEquals(0, module.statements.size) assertEquals(0, module.statements.size)
} }
} }
@ -218,7 +218,7 @@ class TestProg8Parser {
main { main {
} }
""".trimIndent() """.trimIndent()
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
// Note: assertContains has *actual* as first param // Note: assertContains has *actual* as first param
assertContains(module.name, Regex("^anonymous_[0-9a-f]+$")) assertContains(module.name, Regex("^anonymous_[0-9a-f]+$"))
@ -227,7 +227,7 @@ class TestProg8Parser {
@Test @Test
fun `parsed from a file`() { fun `parsed from a file`() {
val path = assumeReadableFile(fixturesDir, "simple_main.p8") val path = assumeReadableFile(fixturesDir, "simple_main.p8")
val module = parseModule(SourceCode.fromPath(path)) val module = parseModule(SourceCode.File(path))
assertEquals(path.nameWithoutExtension, module.name) assertEquals(path.nameWithoutExtension, module.name)
} }
} }
@ -287,9 +287,9 @@ class TestProg8Parser {
fun `in ParseError from bad string source code`() { fun `in ParseError from bad string source code`() {
val srcText = "bad * { }\n" val srcText = "bad * { }\n"
assertFailsWith<ParseError> { parseModule(SourceCode.of(srcText)) } assertFailsWith<ParseError> { parseModule(SourceCode.Text(srcText)) }
try { try {
parseModule(SourceCode.of(srcText)) parseModule(SourceCode.Text(srcText))
} catch (e: ParseError) { } catch (e: ParseError) {
assertPosition(e.position, Regex("^<String@[0-9a-f]+>$"), 1, 4, 4) assertPosition(e.position, Regex("^<String@[0-9a-f]+>$"), 1, 4, 4)
} }
@ -299,9 +299,9 @@ class TestProg8Parser {
fun `in ParseError from bad file source code`() { fun `in ParseError from bad file source code`() {
val path = assumeReadableFile(fixturesDir, "file_with_syntax_error.p8") val path = assumeReadableFile(fixturesDir, "file_with_syntax_error.p8")
assertFailsWith<ParseError> { parseModule(SourceCode.fromPath(path)) } assertFailsWith<ParseError> { parseModule(SourceCode.File(path)) }
try { try {
parseModule(SourceCode.fromPath(path)) parseModule(SourceCode.File(path))
} catch (e: ParseError) { } catch (e: ParseError) {
assertPosition(e.position, path.absolutePathString(), 2, 6) // TODO: endCol wrong assertPosition(e.position, path.absolutePathString(), 2, 6) // TODO: endCol wrong
} }
@ -313,7 +313,7 @@ class TestProg8Parser {
main { main {
} }
""".trimIndent() """.trimIndent()
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
assertPositionOf(module, Regex("^<String@[0-9a-f]+>$"), 1, 0) // TODO: endCol wrong assertPositionOf(module, Regex("^<String@[0-9a-f]+>$"), 1, 0) // TODO: endCol wrong
} }
@ -321,7 +321,7 @@ class TestProg8Parser {
fun `of Module parsed from a file`() { fun `of Module parsed from a file`() {
val path = assumeReadableFile(fixturesDir, "simple_main.p8") val path = assumeReadableFile(fixturesDir, "simple_main.p8")
val module = parseModule(SourceCode.fromPath(path)) val module = parseModule(SourceCode.File(path))
assertPositionOf(module, path.absolutePathString(), 1, 0) // TODO: endCol wrong assertPositionOf(module, path.absolutePathString(), 1, 0) // TODO: endCol wrong
} }
@ -329,7 +329,7 @@ class TestProg8Parser {
fun `of non-root Nodes parsed from file`() { fun `of non-root Nodes parsed from file`() {
val path = assumeReadableFile(fixturesDir, "simple_main.p8") val path = assumeReadableFile(fixturesDir, "simple_main.p8")
val module = parseModule(SourceCode.fromPath(path)) val module = parseModule(SourceCode.File(path))
val mpf = module.position.file val mpf = module.position.file
assertPositionOf(module, path.absolutePathString(), 1, 0) // TODO: endCol wrong assertPositionOf(module, path.absolutePathString(), 1, 0) // TODO: endCol wrong
@ -360,7 +360,7 @@ class TestProg8Parser {
} }
} }
""".trimIndent() """.trimIndent()
val module = parseModule(SourceCode.of(srcText)) val module = parseModule(SourceCode.Text(srcText))
val mpf = module.position.file val mpf = module.position.file
val targetDirective = module.statements.filterIsInstance<Directive>()[0] val targetDirective = module.statements.filterIsInstance<Directive>()[0]
@ -388,7 +388,7 @@ class TestProg8Parser {
@Test @Test
fun `in argument position, no altEnc`() { fun `in argument position, no altEnc`() {
val src = SourceCode.of(""" val src = SourceCode.Text("""
main { main {
sub start() { sub start() {
chrout('\n') chrout('\n')
@ -409,7 +409,7 @@ class TestProg8Parser {
@Test @Test
fun `on rhs of block-level var decl, no AltEnc`() { fun `on rhs of block-level var decl, no AltEnc`() {
val src = SourceCode.of(""" val src = SourceCode.Text("""
main { main {
ubyte c = 'x' ubyte c = 'x'
} }
@ -426,7 +426,7 @@ class TestProg8Parser {
@Test @Test
fun `on rhs of block-level const decl, with AltEnc`() { fun `on rhs of block-level const decl, with AltEnc`() {
val src = SourceCode.of(""" val src = SourceCode.Text("""
main { main {
const ubyte c = @'x' const ubyte c = @'x'
} }
@ -443,7 +443,7 @@ class TestProg8Parser {
@Test @Test
fun `on rhs of subroutine-level var decl, no AltEnc`() { fun `on rhs of subroutine-level var decl, no AltEnc`() {
val src = SourceCode.of(""" val src = SourceCode.Text("""
main { main {
sub start() { sub start() {
ubyte c = 'x' ubyte c = 'x'
@ -463,7 +463,7 @@ class TestProg8Parser {
@Test @Test
fun `on rhs of subroutine-level const decl, with AltEnc`() { fun `on rhs of subroutine-level const decl, with AltEnc`() {
val src = SourceCode.of(""" val src = SourceCode.Text("""
main { main {
sub start() { sub start() {
const ubyte c = @'x' const ubyte c = @'x'
@ -487,7 +487,7 @@ class TestProg8Parser {
@Test @Test
fun `in for-loops`() { fun `in for-loops`() {
val module = parseModule(SourceCode.of(""" val module = parseModule(SourceCode.Text("""
main { main {
sub start() { sub start() {
ubyte ub ubyte ub

View File

@ -22,7 +22,7 @@ class TestSourceCode {
val text = """ val text = """
main { } main { }
""".trimIndent() """.trimIndent()
val src = SourceCode.of(text) val src = SourceCode.Text(text)
val actualText = src.getCharStream().toString() val actualText = src.getCharStream().toString()
assertContains(src.origin, Regex("^<String@[0-9a-f]+>$")) assertContains(src.origin, Regex("^<String@[0-9a-f]+>$"))
@ -33,26 +33,26 @@ class TestSourceCode {
fun testFromPathWithNonExistingPath() { fun testFromPathWithNonExistingPath() {
val filename = "i_do_not_exist.p8" val filename = "i_do_not_exist.p8"
val path = assumeNotExists(fixturesDir, filename) val path = assumeNotExists(fixturesDir, filename)
assertFailsWith<NoSuchFileException> { SourceCode.fromPath(path) } assertFailsWith<NoSuchFileException> { SourceCode.File(path) }
} }
@Test @Test
fun testFromPathWithMissingExtension_p8() { fun testFromPathWithMissingExtension_p8() {
val pathWithoutExt = assumeNotExists(fixturesDir,"simple_main") val pathWithoutExt = assumeNotExists(fixturesDir,"simple_main")
assumeReadableFile(fixturesDir,"simple_main.p8") assumeReadableFile(fixturesDir,"simple_main.p8")
assertFailsWith<NoSuchFileException> { SourceCode.fromPath(pathWithoutExt) } assertFailsWith<NoSuchFileException> { SourceCode.File(pathWithoutExt) }
} }
@Test @Test
fun testFromPathWithDirectory() { fun testFromPathWithDirectory() {
assertFailsWith<AccessDeniedException> { SourceCode.fromPath(fixturesDir) } assertFailsWith<AccessDeniedException> { SourceCode.File(fixturesDir) }
} }
@Test @Test
fun testFromPathWithExistingPath() { fun testFromPathWithExistingPath() {
val filename = "simple_main.p8" val filename = "simple_main.p8"
val path = assumeReadableFile(fixturesDir, filename) val path = assumeReadableFile(fixturesDir, filename)
val src = SourceCode.fromPath(path) val src = SourceCode.File(path)
val expectedOrigin = path.normalize().absolutePathString() val expectedOrigin = path.normalize().absolutePathString()
assertEquals(expectedOrigin, src.origin) assertEquals(expectedOrigin, src.origin)
@ -64,7 +64,7 @@ class TestSourceCode {
val filename = "simple_main.p8" val filename = "simple_main.p8"
val path = Path(".", "test", "..", "test", "fixtures", filename) val path = Path(".", "test", "..", "test", "fixtures", filename)
val srcFile = assumeReadableFile(path).toFile() val srcFile = assumeReadableFile(path).toFile()
val src = SourceCode.fromPath(path) val src = SourceCode.File(path)
val expectedOrigin = path.normalize().absolutePathString() val expectedOrigin = path.normalize().absolutePathString()
assertEquals(expectedOrigin, src.origin) assertEquals(expectedOrigin, src.origin)
@ -75,7 +75,7 @@ class TestSourceCode {
fun testFromResourcesWithExistingP8File_withoutLeadingSlash() { fun testFromResourcesWithExistingP8File_withoutLeadingSlash() {
val pathString = "prog8lib/math.p8" val pathString = "prog8lib/math.p8"
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile() val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
val src = SourceCode.fromResources(pathString) val src = SourceCode.Resource(pathString)
assertEquals("$libraryFilePrefix/$pathString", src.origin) assertEquals("$libraryFilePrefix/$pathString", src.origin)
assertEquals(srcFile.readText(), src.asString()) assertEquals(srcFile.readText(), src.asString())
@ -85,7 +85,7 @@ class TestSourceCode {
fun testFromResourcesWithExistingP8File_withLeadingSlash() { fun testFromResourcesWithExistingP8File_withLeadingSlash() {
val pathString = "/prog8lib/math.p8" val pathString = "/prog8lib/math.p8"
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile() val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
val src = SourceCode.fromResources(pathString) val src = SourceCode.Resource(pathString)
assertEquals("$libraryFilePrefix$pathString", src.origin) assertEquals("$libraryFilePrefix$pathString", src.origin)
assertEquals(srcFile.readText(), src.asString()) assertEquals(srcFile.readText(), src.asString())
@ -95,7 +95,7 @@ class TestSourceCode {
fun testFromResourcesWithExistingAsmFile_withoutLeadingSlash() { fun testFromResourcesWithExistingAsmFile_withoutLeadingSlash() {
val pathString = "prog8lib/math.asm" val pathString = "prog8lib/math.asm"
val srcFile = assumeReadableFile(resourcesDir, pathString).toFile() val srcFile = assumeReadableFile(resourcesDir, pathString).toFile()
val src = SourceCode.fromResources(pathString) val src = SourceCode.Resource(pathString)
assertEquals("$libraryFilePrefix/$pathString", src.origin) assertEquals("$libraryFilePrefix/$pathString", src.origin)
assertEquals(srcFile.readText(), src.asString()) assertEquals(srcFile.readText(), src.asString())
@ -106,7 +106,7 @@ class TestSourceCode {
fun testFromResourcesWithExistingAsmFile_withLeadingSlash() { fun testFromResourcesWithExistingAsmFile_withLeadingSlash() {
val pathString = "/prog8lib/math.asm" val pathString = "/prog8lib/math.asm"
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile() val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
val src = SourceCode.fromResources(pathString) val src = SourceCode.Resource(pathString)
assertEquals("$libraryFilePrefix$pathString", src.origin) assertEquals("$libraryFilePrefix$pathString", src.origin)
assertEquals(srcFile.readText(), src.asString()) assertEquals(srcFile.readText(), src.asString())
@ -116,7 +116,7 @@ class TestSourceCode {
fun testFromResourcesWithNonNormalizedPath() { fun testFromResourcesWithNonNormalizedPath() {
val pathString = "/prog8lib/../prog8lib/math.p8" val pathString = "/prog8lib/../prog8lib/math.p8"
val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile() val srcFile = assumeReadableFile(resourcesDir, pathString.substring(1)).toFile()
val src = SourceCode.fromResources(pathString) val src = SourceCode.Resource(pathString)
assertEquals("$libraryFilePrefix/prog8lib/math.p8", src.origin) assertEquals("$libraryFilePrefix/prog8lib/math.p8", src.origin)
assertEquals(srcFile.readText(), src.asString()) assertEquals(srcFile.readText(), src.asString())
@ -129,14 +129,14 @@ class TestSourceCode {
val pathString = "/prog8lib/i_do_not_exist" val pathString = "/prog8lib/i_do_not_exist"
assumeNotExists(resourcesDir, pathString.substring(1)) assumeNotExists(resourcesDir, pathString.substring(1))
assertFailsWith<NoSuchFileException> { SourceCode.fromResources(pathString) } assertFailsWith<NoSuchFileException> { SourceCode.Resource(pathString) }
} }
@Test @Test
fun testFromResourcesWithNonExistingFile_withoutLeadingSlash() { fun testFromResourcesWithNonExistingFile_withoutLeadingSlash() {
val pathString = "prog8lib/i_do_not_exist" val pathString = "prog8lib/i_do_not_exist"
assumeNotExists(resourcesDir, pathString) assumeNotExists(resourcesDir, pathString)
assertFailsWith<NoSuchFileException> { SourceCode.fromResources(pathString) } assertFailsWith<NoSuchFileException> { SourceCode.Resource(pathString) }
} }
@Test @Test
@ -144,7 +144,7 @@ class TestSourceCode {
fun testFromResourcesWithDirectory() { fun testFromResourcesWithDirectory() {
val pathString = "/prog8lib" val pathString = "/prog8lib"
assumeDirectory(resourcesDir, pathString.substring(1)) assumeDirectory(resourcesDir, pathString.substring(1))
assertFailsWith<AccessDeniedException> { SourceCode.fromResources(pathString) } assertFailsWith<AccessDeniedException> { SourceCode.Resource(pathString) }
} }
} }

View File

@ -11,6 +11,7 @@ import prog8.ast.Module
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.internedStringsModuleName import prog8.ast.internedStringsModuleName
import prog8.parser.SourceCode
import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyFunctions
import prog8tests.helpers.DummyMemsizer import prog8tests.helpers.DummyMemsizer
import kotlin.test.assertContains import kotlin.test.assertContains
@ -39,7 +40,7 @@ class ProgramTests {
@Test @Test
fun withEmptyModule() { fun withEmptyModule() {
val program = Program("foo", DummyFunctions, DummyMemsizer) val program = Program("foo", DummyFunctions, DummyMemsizer)
val m1 = Module("bar", mutableListOf(), Position.DUMMY, null) val m1 = Module("bar", mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
val retVal = program.addModule(m1) val retVal = program.addModule(m1)
@ -73,15 +74,15 @@ class ProgramTests {
@Test @Test
fun withForeignModule() { fun withForeignModule() {
val program = Program("foo", DummyFunctions, DummyMemsizer) val program = Program("foo", DummyFunctions, DummyMemsizer)
val m = Module("bar", mutableListOf(), Position.DUMMY, null) val m = Module("bar", mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
assertFailsWith<IllegalArgumentException> { program.moveModuleToFront(m) } assertFailsWith<IllegalArgumentException> { program.moveModuleToFront(m) }
} }
@Test @Test
fun withFirstOfPreviouslyAddedModules() { fun withFirstOfPreviouslyAddedModules() {
val program = Program("foo", DummyFunctions, DummyMemsizer) val program = Program("foo", DummyFunctions, DummyMemsizer)
val m1 = Module("bar", mutableListOf(), Position.DUMMY, null) val m1 = Module("bar", mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
val m2 = Module("qmbl", mutableListOf(), Position.DUMMY, null) val m2 = Module("qmbl", mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl"))
program.addModule(m1) program.addModule(m1)
program.addModule(m2) program.addModule(m2)
@ -92,8 +93,8 @@ class ProgramTests {
@Test @Test
fun withSecondOfPreviouslyAddedModules() { fun withSecondOfPreviouslyAddedModules() {
val program = Program("foo", DummyFunctions, DummyMemsizer) val program = Program("foo", DummyFunctions, DummyMemsizer)
val m1 = Module("bar", mutableListOf(), Position.DUMMY, null) val m1 = Module("bar", mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
val m2 = Module("qmbl", mutableListOf(), Position.DUMMY, null) val m2 = Module("qmbl", mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl"))
program.addModule(m1) program.addModule(m1)
program.addModule(m2) program.addModule(m2)

View File

@ -4,7 +4,6 @@ TODO
For next compiler release For next compiler release
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
- can we derive module.name from module.source (taking just the filename base)? - can we derive module.name from module.source (taking just the filename base)?
- can Position.file be a Path- making the source variable for nodes unnecessary?
Blocked by Commander-x16 v39 release Blocked by Commander-x16 v39 release

View File

@ -1,7 +1,14 @@
%option enable_floats %import textio
main { main {
sub start() { str myBar = "main.bar"
float[] cs = 1 to 42 ; values are computed at compile time
cs[0] = 23 ; keep optimizer from removing it foo_bar:
} %asminclude "compiler/test/fixtures/foo_bar.asm22" ; FIXME: should be accessible from inside start() but give assembler error
sub start() {
txt.print(myBar)
txt.print(&foo_bar)
return
}
} }