mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-16 16:31:04 +00:00
Compilation order should be decided by the import statements
This commit is contained in:
parent
ba16021426
commit
f46466365b
@ -143,7 +143,18 @@ A function can be declared at the top level. For more details, see [Functions](.
|
||||
|
||||
## `import` statements
|
||||
|
||||
TODO
|
||||
import <module>
|
||||
|
||||
Adds a module to the program.
|
||||
|
||||
The module is looked up first in the current working directory, and then in the include directories.
|
||||
|
||||
Usually, the imported module will undergo the first phase of compilation first.
|
||||
This means that the constants in the imported module will be resolved first, allowing you to use them in the importing module.
|
||||
|
||||
The only exception to this rule is when the importing graph has a cycle, in which case the order of modules within the cycle is unspecified.
|
||||
|
||||
All starting modules are considered to be imported by all source files explicitly mentioned on the command line.
|
||||
|
||||
## Statements
|
||||
|
||||
|
@ -4,8 +4,7 @@ import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.{Files, Paths}
|
||||
|
||||
import fastparse.core.Parsed.{Failure, Success}
|
||||
import millfork.{CompilationFlag, CompilationOptions}
|
||||
import millfork.error.ConsoleLogger
|
||||
import millfork.{CompilationFlag, CompilationOptions, Tarjan}
|
||||
import millfork.node.{ImportStatement, Position, Program}
|
||||
|
||||
import scala.collection.mutable
|
||||
@ -16,12 +15,32 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
||||
val options: CompilationOptions) {
|
||||
|
||||
protected val parsedModules: mutable.Map[String, Program] = mutable.Map[String, Program]()
|
||||
protected val moduleDependecies: mutable.Set[(String, String)] = mutable.Set[(String, String)]()
|
||||
protected val moduleQueue: mutable.Queue[() => Unit] = mutable.Queue[() => Unit]()
|
||||
val extension: String = ".mfk"
|
||||
|
||||
def standardModules: IndexedSeq[String]
|
||||
|
||||
def enqueueStandardModules(): Unit
|
||||
|
||||
def run(): Program = {
|
||||
for {
|
||||
initialFilename <- initialFilenames
|
||||
startingModule <- options.platform.startingModules
|
||||
} {
|
||||
val initialModule = extractName(initialFilename)
|
||||
moduleDependecies += initialModule -> startingModule
|
||||
for (standardModule <- standardModules) {
|
||||
moduleDependecies += initialModule -> standardModule
|
||||
moduleDependecies += startingModule -> standardModule
|
||||
}
|
||||
}
|
||||
for {
|
||||
earlier <- standardModules.indices
|
||||
later <- (earlier + 1) until standardModules.length
|
||||
} {
|
||||
moduleDependecies += standardModules(later) -> standardModules(earlier)
|
||||
}
|
||||
initialFilenames.foreach { i =>
|
||||
parseModule(extractName(i), includePath, Right(i))
|
||||
}
|
||||
@ -37,7 +56,9 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
||||
}
|
||||
}
|
||||
options.log.assertNoErrors("Parse failed")
|
||||
parsedModules.values.reduce(_ + _).applyImportantAliases
|
||||
val compilationOrder = Tarjan.sort(parsedModules.keys, moduleDependecies)
|
||||
options.log.debug("Compilation order: " + compilationOrder.mkString(", "))
|
||||
compilationOrder.filter(parsedModules.contains).map(parsedModules).reduce(_ + _).applyImportantAliases
|
||||
}
|
||||
|
||||
def lookupModuleFile(includePath: List[String], moduleName: String, position: Option[Position]): String = {
|
||||
@ -75,6 +96,7 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
||||
parsedModules.put(moduleName, prog)
|
||||
prog.declarations.foreach {
|
||||
case s@ImportStatement(m) =>
|
||||
moduleDependecies += moduleName -> m
|
||||
if (!parsedModules.contains(m)) {
|
||||
moduleQueue.enqueue(() => parseModule(m, parentDir :: includePath, Left(s.position)))
|
||||
}
|
||||
@ -94,6 +116,6 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
||||
def extractName(i: String): String = {
|
||||
val noExt = i.stripSuffix(extension)
|
||||
val lastSlash = noExt.lastIndexOf('/') max noExt.lastIndexOf('\\')
|
||||
if (lastSlash >= 0) i.substring(lastSlash + 1) else i
|
||||
if (lastSlash >= 0) noExt.substring(lastSlash + 1) else noExt
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ class MosSourceLoadingQueue(initialFilenames: List[String],
|
||||
override def createParser(filename: String, src: String, parentDir: String, featureConstants: Map[String, Long], pragmas: Set[String]): MfParser[AssemblyLine] =
|
||||
MosParser(filename, src, parentDir, options, featureConstants)
|
||||
|
||||
override def standardModules: IndexedSeq[String] = IndexedSeq("zp_reg", "bcd_6502")
|
||||
|
||||
def enqueueStandardModules(): Unit = {
|
||||
if (options.zpRegisterSize > 0) {
|
||||
moduleQueue.enqueue(() => parseModule("zp_reg", includePath, Left(None)))
|
||||
|
@ -19,6 +19,8 @@ class ZSourceLoadingQueue(initialFilenames: List[String],
|
||||
Z80Parser(filename, src, parentDir, options, featureConstants, useIntelSyntax)
|
||||
}
|
||||
|
||||
override def standardModules: IndexedSeq[String] = IndexedSeq.empty
|
||||
|
||||
def enqueueStandardModules(): Unit = {
|
||||
// TODO
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user