mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-17 07:30: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
|
## `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
|
## Statements
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ import java.nio.charset.StandardCharsets
|
|||||||
import java.nio.file.{Files, Paths}
|
import java.nio.file.{Files, Paths}
|
||||||
|
|
||||||
import fastparse.core.Parsed.{Failure, Success}
|
import fastparse.core.Parsed.{Failure, Success}
|
||||||
import millfork.{CompilationFlag, CompilationOptions}
|
import millfork.{CompilationFlag, CompilationOptions, Tarjan}
|
||||||
import millfork.error.ConsoleLogger
|
|
||||||
import millfork.node.{ImportStatement, Position, Program}
|
import millfork.node.{ImportStatement, Position, Program}
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
@ -16,12 +15,32 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
|||||||
val options: CompilationOptions) {
|
val options: CompilationOptions) {
|
||||||
|
|
||||||
protected val parsedModules: mutable.Map[String, Program] = mutable.Map[String, Program]()
|
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]()
|
protected val moduleQueue: mutable.Queue[() => Unit] = mutable.Queue[() => Unit]()
|
||||||
val extension: String = ".mfk"
|
val extension: String = ".mfk"
|
||||||
|
|
||||||
|
def standardModules: IndexedSeq[String]
|
||||||
|
|
||||||
def enqueueStandardModules(): Unit
|
def enqueueStandardModules(): Unit
|
||||||
|
|
||||||
def run(): Program = {
|
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 =>
|
initialFilenames.foreach { i =>
|
||||||
parseModule(extractName(i), includePath, Right(i))
|
parseModule(extractName(i), includePath, Right(i))
|
||||||
}
|
}
|
||||||
@ -37,7 +56,9 @@ abstract class AbstractSourceLoadingQueue[T](val initialFilenames: List[String],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.log.assertNoErrors("Parse failed")
|
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 = {
|
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)
|
parsedModules.put(moduleName, prog)
|
||||||
prog.declarations.foreach {
|
prog.declarations.foreach {
|
||||||
case s@ImportStatement(m) =>
|
case s@ImportStatement(m) =>
|
||||||
|
moduleDependecies += moduleName -> m
|
||||||
if (!parsedModules.contains(m)) {
|
if (!parsedModules.contains(m)) {
|
||||||
moduleQueue.enqueue(() => parseModule(m, parentDir :: includePath, Left(s.position)))
|
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 = {
|
def extractName(i: String): String = {
|
||||||
val noExt = i.stripSuffix(extension)
|
val noExt = i.stripSuffix(extension)
|
||||||
val lastSlash = noExt.lastIndexOf('/') max noExt.lastIndexOf('\\')
|
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] =
|
override def createParser(filename: String, src: String, parentDir: String, featureConstants: Map[String, Long], pragmas: Set[String]): MfParser[AssemblyLine] =
|
||||||
MosParser(filename, src, parentDir, options, featureConstants)
|
MosParser(filename, src, parentDir, options, featureConstants)
|
||||||
|
|
||||||
|
override def standardModules: IndexedSeq[String] = IndexedSeq("zp_reg", "bcd_6502")
|
||||||
|
|
||||||
def enqueueStandardModules(): Unit = {
|
def enqueueStandardModules(): Unit = {
|
||||||
if (options.zpRegisterSize > 0) {
|
if (options.zpRegisterSize > 0) {
|
||||||
moduleQueue.enqueue(() => parseModule("zp_reg", includePath, Left(None)))
|
moduleQueue.enqueue(() => parseModule("zp_reg", includePath, Left(None)))
|
||||||
|
@ -19,6 +19,8 @@ class ZSourceLoadingQueue(initialFilenames: List[String],
|
|||||||
Z80Parser(filename, src, parentDir, options, featureConstants, useIntelSyntax)
|
Z80Parser(filename, src, parentDir, options, featureConstants, useIntelSyntax)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def standardModules: IndexedSeq[String] = IndexedSeq.empty
|
||||||
|
|
||||||
def enqueueStandardModules(): Unit = {
|
def enqueueStandardModules(): Unit = {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user