mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
* no more scattering magic "@embedded@" all over the place: add SourceCode.isFromResources, *change Module.source from type Path to type SourceCode*
This commit is contained in:
parent
b0073ac933
commit
19bb56df47
@ -22,6 +22,7 @@ import prog8.parser.moduleName
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
|
||||
@ -183,7 +184,10 @@ private fun parseImports(filepath: Path,
|
||||
importer.importModule(filepath)
|
||||
errors.report()
|
||||
|
||||
val importedFiles = programAst.modules.filter { !it.source.startsWith("@embedded@") }.map { it.source }
|
||||
val importedFiles = programAst.modules
|
||||
.mapNotNull { it.source }
|
||||
.filter { !it.isFromResources } // TODO: parseImports/importedFiles - maybe rather `source.isFromFilesystem`?
|
||||
.map { Path(it.pathString()) }
|
||||
val compilerOptions = determineCompilationOptions(programAst, compTarget)
|
||||
if (compilerOptions.launcher == LauncherType.BASIC && compilerOptions.output != OutputType.PRG)
|
||||
throw ParsingFailedError("${programAst.modules.first().position} BASIC launcher requires output type PRG.")
|
||||
@ -357,14 +361,14 @@ fun printAst(programAst: Program) {
|
||||
println()
|
||||
}
|
||||
|
||||
fun loadAsmIncludeFile(filename: String, source: Path): String {
|
||||
return if (filename.startsWith("library:")) {
|
||||
fun loadAsmIncludeFile(filename: String, sourcePath: Path): String {
|
||||
return if (filename.startsWith("library:")) { // FIXME: is the prefix "library:" or is it "@embedded@"?
|
||||
val resource = tryGetEmbeddedResource(filename.substring(8))
|
||||
?: throw IllegalArgumentException("library file '$filename' not found")
|
||||
resource.bufferedReader().use { it.readText() }
|
||||
} else {
|
||||
// first try in the isSameAs folder as where the containing file was imported from
|
||||
val sib = source.resolveSibling(filename)
|
||||
val sib = sourcePath.resolveSibling(filename)
|
||||
if (sib.toFile().isFile)
|
||||
sib.toFile().readText()
|
||||
else
|
||||
@ -372,6 +376,9 @@ fun loadAsmIncludeFile(filename: String, source: Path): String {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle via SourceCode
|
||||
*/
|
||||
internal fun tryGetEmbeddedResource(name: String): InputStream? {
|
||||
return object{}.javaClass.getResourceAsStream("/prog8lib/$name")
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import prog8.compiler.target.Cx16Target
|
||||
import prog8.compiler.target.ICompilationTarget
|
||||
import java.io.CharConversionException
|
||||
import java.io.File
|
||||
import kotlin.io.path.*
|
||||
import java.util.*
|
||||
|
||||
internal class AstChecker(private val program: Program,
|
||||
@ -728,11 +729,23 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
private fun checkFileExists(directive: Directive, filename: String) {
|
||||
var definingModule = directive.parent
|
||||
if (File(filename).isFile)
|
||||
return
|
||||
|
||||
var definingModule = directive.parent // TODO: why not just use directive.definingModule() here?
|
||||
while (definingModule !is Module)
|
||||
definingModule = definingModule.parent
|
||||
if (!(filename.startsWith("library:") || definingModule.source.resolveSibling(filename).toFile().isFile || File(filename).isFile))
|
||||
errors.err("included file not found: $filename", directive.position)
|
||||
if (definingModule.isLibrary())
|
||||
return
|
||||
|
||||
val s = definingModule.source?.pathString()
|
||||
if (s != null) {
|
||||
val sourceFileCandidate = Path(s).resolveSibling(filename).toFile()
|
||||
if (sourceFileCandidate.isFile)
|
||||
return
|
||||
}
|
||||
|
||||
errors.err("included file not found: $filename", directive.position)
|
||||
}
|
||||
|
||||
override fun visit(array: ArrayLiteralValue) {
|
||||
|
@ -1311,13 +1311,17 @@ $repeatLabel lda $counterVar
|
||||
private fun translate(stmt: Directive) {
|
||||
when(stmt.directive) {
|
||||
"%asminclude" -> {
|
||||
val sourcecode = loadAsmIncludeFile(stmt.args[0].str!!, stmt.definingModule().source)
|
||||
// TODO: handle %asminclude with SourceCode
|
||||
val sourcePath = Path.of(stmt.definingModule().source!!.pathString()) // FIXME: %asminclude inside non-library, non-filesystem module
|
||||
val sourcecode = loadAsmIncludeFile(stmt.args[0].str!!, sourcePath)
|
||||
assemblyLines.add(sourcecode.trimEnd().trimStart('\n'))
|
||||
}
|
||||
"%asmbinary" -> {
|
||||
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 includedSourcePath = stmt.definingModule().source.resolveSibling(stmt.args[0].str)
|
||||
// TODO: handle %asmbinary with SourceCode
|
||||
val sourcePath = Path.of(stmt.definingModule().source!!.pathString()) // FIXME: %asmbinary inside non-library, non-filesystem module
|
||||
val includedSourcePath = sourcePath.resolveSibling(stmt.args[0].str)
|
||||
val relPath = Paths.get("").relativize(includedSourcePath)
|
||||
out(" .binary \"$relPath\" $offset $length")
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ locallabel:
|
||||
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 module = Module("test", mutableListOf(block), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(block), Position.DUMMY, null)
|
||||
module.linkParents(ParentSentinel)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.program = program
|
||||
|
@ -98,7 +98,7 @@ class TestMemory {
|
||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
module.linkParents(ParentSentinel)
|
||||
return target
|
||||
}
|
||||
@ -117,7 +117,7 @@ class TestMemory {
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertTrue(C64Target.isInRegularRAM(target, program))
|
||||
@ -130,7 +130,7 @@ class TestMemory {
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertTrue(C64Target.isInRegularRAM(target, program))
|
||||
@ -143,7 +143,7 @@ class TestMemory {
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertFalse(C64Target.isInRegularRAM(target, program))
|
||||
@ -156,7 +156,7 @@ class TestMemory {
|
||||
val target = AssignTarget(null, arrayindexed, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertTrue(C64Target.isInRegularRAM(target, program))
|
||||
@ -170,7 +170,7 @@ class TestMemory {
|
||||
val target = AssignTarget(null, arrayindexed, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertTrue(C64Target.isInRegularRAM(target, program))
|
||||
@ -184,7 +184,7 @@ class TestMemory {
|
||||
val target = AssignTarget(null, arrayindexed, null, 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 module = Module("test", mutableListOf(subroutine), Position.DUMMY, Path.of(""))
|
||||
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, null)
|
||||
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
|
||||
module.linkParents(ParentSentinel)
|
||||
assertFalse(C64Target.isInRegularRAM(target, program))
|
||||
|
@ -5,6 +5,7 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.parser.SourceCode
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.name
|
||||
@ -265,7 +266,7 @@ class Program(val name: String,
|
||||
init {
|
||||
// insert a container module for all interned strings later
|
||||
if(modules.firstOrNull()?.name != internedStringsModuleName) {
|
||||
val internedStringsModule = Module(internedStringsModuleName, mutableListOf(), Position.DUMMY, Path.of(""))
|
||||
val internedStringsModule = Module(internedStringsModuleName, mutableListOf(), Position.DUMMY, null)
|
||||
modules.add(0, internedStringsModule)
|
||||
val block = Block(internedStringsModuleName, null, mutableListOf(), true, Position.DUMMY)
|
||||
internedStringsModule.statements.add(block)
|
||||
@ -342,7 +343,7 @@ class Program(val name: String,
|
||||
open class Module(override val name: String,
|
||||
override var statements: MutableList<Statement>,
|
||||
override val position: Position,
|
||||
val source: Path) : Node, INameScope {
|
||||
val source: SourceCode?) : Node, INameScope {
|
||||
|
||||
override lateinit var parent: Node
|
||||
lateinit var program: Program
|
||||
@ -370,15 +371,7 @@ open class Module(override val name: String,
|
||||
fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
|
||||
companion object {
|
||||
fun pathForResource(resourcePath: String): Path {
|
||||
return Paths.get("@embedded@/$resourcePath")
|
||||
}
|
||||
|
||||
fun isLibrary(source: Path) = source.name=="" || source.startsWith("@embedded@/")
|
||||
}
|
||||
|
||||
fun isLibrary() = isLibrary(source)
|
||||
fun isLibrary() = (source == null) || source.isFromResources
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.parser.Prog8ANTLRParser
|
||||
import prog8.parser.SourceCode
|
||||
import java.io.CharConversionException
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
@ -18,10 +19,10 @@ import java.nio.file.Path
|
||||
|
||||
private data class NumericLiteral(val number: Number, val datatype: DataType)
|
||||
|
||||
internal fun Prog8ANTLRParser.ModuleContext.toAst(name: String, source: Path, encoding: IStringEncoding) : Module {
|
||||
internal fun Prog8ANTLRParser.ModuleContext.toAst(name: String, source: SourceCode, encoding: IStringEncoding) : Module {
|
||||
val nameWithoutSuffix = if(name.endsWith(".p8")) name.substringBeforeLast('.') else name
|
||||
val directives = this.directive().map { it.toAst() }
|
||||
val blocks = this.block().map { it.toAst(Module.isLibrary(source), encoding) }
|
||||
val blocks = this.block().map { it.toAst(isInLibrary = source.isFromResources, encoding) }
|
||||
return Module(nameWithoutSuffix, (directives + blocks).toMutableList(), toPosition(), source)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import prog8.ast.antlr.toAst
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Directive
|
||||
import kotlin.io.path.Path
|
||||
|
||||
|
||||
open class ParsingFailedError(override var message: String) : Exception(message)
|
||||
@ -43,19 +42,18 @@ object Prog8Parser {
|
||||
return module
|
||||
}
|
||||
|
||||
private class ParsedModule(src: SourceCode) : Module(
|
||||
private class ParsedModule(source: SourceCode) : Module(
|
||||
// FIXME: hacking together a name for the module:
|
||||
name = src.pathString()
|
||||
name = source.pathString()
|
||||
.substringBeforeLast(".") // must also work with an origin = "<String@123beef>"
|
||||
.substringAfterLast("/")
|
||||
.substringAfterLast("\\")
|
||||
.replace("String@", "anonymous_"),
|
||||
// FIXME: hacking together a path
|
||||
source = Path(src.pathString()),
|
||||
statements = mutableListOf(),
|
||||
position = Position(src.origin, 1, 0, 0)
|
||||
position = Position(source.origin, 1, 0, 0),
|
||||
source
|
||||
) {
|
||||
val provenance = Pair(src, Triple(1, 0, 0))
|
||||
val provenance = Pair(source, Triple(1, 0, 0))
|
||||
|
||||
/**
|
||||
* Adds a [Directive] to [statements] and
|
||||
|
@ -18,6 +18,12 @@ abstract class SourceCode {
|
||||
*/
|
||||
internal abstract fun getCharStream(): CharStream
|
||||
|
||||
/**
|
||||
* Whether this [SourceCode] instance was created by
|
||||
* factory method [fromResources]
|
||||
*/
|
||||
abstract val isFromResources: Boolean
|
||||
|
||||
/**
|
||||
* Where this [SourceCode] instance came from.
|
||||
* This can be one of the following:
|
||||
@ -58,6 +64,7 @@ abstract class SourceCode {
|
||||
*/
|
||||
fun of(text: String): SourceCode {
|
||||
return object : SourceCode() {
|
||||
override val isFromResources = false
|
||||
override val origin = "<String@${System.identityHashCode(text).toString(16)}>"
|
||||
override fun getCharStream(): CharStream {
|
||||
return CharStreams.fromString(text)
|
||||
@ -86,6 +93,7 @@ abstract class SourceCode {
|
||||
throw AccessDeniedException(path.toFile(), reason = "Is not readable")
|
||||
val normalized = path.normalize()
|
||||
return object : SourceCode() {
|
||||
override val isFromResources = false
|
||||
override val origin = normalized.absolutePathString()
|
||||
override fun getCharStream(): CharStream {
|
||||
return CharStreams.fromPath(normalized)
|
||||
@ -108,6 +116,7 @@ abstract class SourceCode {
|
||||
reason = "looked in resources rooted at $rscRoot")
|
||||
}
|
||||
return object : SourceCode() {
|
||||
override val isFromResources = true
|
||||
override val origin = "@embedded@$normalized"
|
||||
override fun getCharStream(): CharStream {
|
||||
val inpStr = object{}.javaClass.getResourceAsStream(normalized)
|
||||
|
Loading…
Reference in New Issue
Block a user