mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
cleanup SourceCode class
This commit is contained in:
parent
975594703d
commit
6070afa6b6
@ -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)
|
||||||
|
@ -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) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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])
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user