1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-25 19:29:49 +00:00

Compilation order should be decided by the import statements

This commit is contained in:
Karol Stasiak 2019-06-14 23:20:03 +02:00
parent ba16021426
commit f46466365b
4 changed files with 42 additions and 5 deletions

View File

@ -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

View File

@ -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
}
}

View File

@ -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)))

View File

@ -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
}