Skip to content

Commit

Permalink
feat: load module once
Browse files Browse the repository at this point in the history
  • Loading branch information
Myriad-Dreamin committed Sep 20, 2024
1 parent 4e05eba commit 10414ac
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 43 deletions.
11 changes: 6 additions & 5 deletions packages/cosmo/src/main/scala/cosmo/CodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@ class CodeGen(implicit val env: Env) {
s"$nsb${templateCode}$inlineModifier$staticModifier$virtualModifier $rt $name($paramCode)$constModifier$overrideModifier $bodyCode$nse"
// case ir.TypeAlias(ret_ty) =>
// s"using $name = ${returnTy(ret_ty)};"
case ir.NativeModule(info, env, fid) =>
case ir.NativeModule(info, env) =>
val name = info.defName(stem = true)
// fid.path (.cos -> .h)
// todo: unreliable path conversion
val fid = env.fid.get
val path = fid.path.slice(0, fid.path.length - 4) + ".h"
s"#include <${fid.pkg.namespace}/${fid.pkg.name}/src${path}>"
case ir.CModule(id, kind, path) =>
Expand Down Expand Up @@ -490,10 +491,10 @@ class CodeGen(implicit val env: Env) {
}
case SelfVal if genInImpl => "self()"
case SelfVal => "(*this)"
case Unreachable => return "unreachable();"
case Bool(v) => v.toString
case Str(s) => s"""::str("${escapeStr(s)}")"""
case s: Bytes => s"""cosmo_std::str::Bytes("${bytesRepr(s)}")"""
case Unreachable => return "unreachable();"
case Bool(v) => v.toString
case Str(s) => s"""::str("${escapeStr(s)}")"""
case s: Bytes => s"""cosmo_std::str::Bytes("${bytesRepr(s)}")"""
case Rune(s) if s < 0x80 && !s.toChar.isControl =>
s"Rune('${s.toChar}')"
case Rune(s) => s"Rune($s)"
Expand Down
60 changes: 32 additions & 28 deletions packages/cosmo/src/main/scala/cosmo/Cosmo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,41 @@ case class FileId(val pkg: Package, val path: String) {
val pns = List(pkg.namespace + "_" + pkg.name)
val fns = path.stripPrefix("/").stripSuffix(".cos").split("/").toList
pns ::: fns
override def toString(): String = s"$pkg:$path"
}
object FileId {
def any = FileId(Package.any, "")
}

trait PackageManager {
def loadModule(path: syntax.Node): Option[(FileId, Env)]
def loadModule(fid: FileId): Option[Env]
def loadModuleBySyntax(path: syntax.Node): Option[Env]
}

trait Transpiler {
def transpile(
src: String,
fid: Option[FileId] = None,
): Option[(String, Boolean)]
trait Transpiler extends PackageManager {
def transpile(src: String): Option[(String, Env)]
def transpileByFid(fid: FileId): Option[(String, Env)]
}

@JSExportTopLevel("Cosmo")
class Cosmo extends PackageManager, Transpiler {
class Cosmo extends Transpiler {
var packages: Map[String, Map[String, Package]] = Map()
val system: CosmoSystem = new JsPhysicalSystem()
val linker: Linker = new CmakeLinker(system)
val envBase = new Env(None, this).builtins()
var modules = Map[FileId, Option[Env]]()

@JSExport
def loadPackageByPath(path: String): Unit = {
def loadPackageByPath(path: String): Unit =
loadPackage(PackageMetaSource.ProjectPath(path))
}

@JSExport
def getExecutable(path: String): String = {
def getExecutable(path: String): String =
mayGetExecutable(path).getOrElse("") // js hate Option[T]
}

@JSExport
def convert(src: String): String = {
val fid = None
transpile(src, fid).map(_._1).getOrElse("#if 0\nCompilation failed\n#endif")
}
def convert(src: String): String =
transpile(src).map(_._1).getOrElse("#if 0\nCompilation failed\n#endif")

@JSExport
def preloadPackage(name: String): Unit = {
Expand All @@ -65,22 +62,24 @@ class Cosmo extends PackageManager, Transpiler {
}

@JSExport
def parseAsJson(s: String): String = {
def parseAsJson(s: String): String =
parse(s).map(syntax.toJson).getOrElse("")
}

def mayGetExecutable(path: String): Option[String] = {
val releaseDir = "target/cosmo/release"
linker.compile(path, this, releaseDir)
}

def transpile(src: String, fid: Option[FileId]): Option[(String, Boolean)] =
loadModuleBySrc(createEnv(fid), src).flatMap(cppBackend)
def transpile(src: String): Option[(String, Env)] =
loadModuleBySrc(createEnv(None), src).flatMap(cppBackend)

def cppBackend(e: Env): Option[(String, Boolean)] = {
def transpileByFid(fid: FileId): Option[(String, Env)] =
loadModule(fid).flatMap(cppBackend)

def cppBackend(e: Env): Option[(String, Env)] = {
implicit val env = e
val code = new CodeGen().gen()
Some((formatCode(code), env.noCore))
Some((formatCode(code), env))
}

def loadPackage(source: PackageMetaSource): Unit = {
Expand All @@ -90,18 +89,23 @@ class Cosmo extends PackageManager, Transpiler {
packages + (package_.namespace -> (nsPackages + (package_.name -> package_)))
}

def loadModuleByDotPath(s: String): Option[(FileId, Env)] = {
loadModule(libPath(s))
}
def loadModuleByDotPath(s: String): Option[Env] =
loadModuleBySyntax(libPath(s))

def loadModuleBySyntax(path: syntax.Node): Option[Env] =
loadModule(resolvePackage(path))

def loadModule(fid: FileId): Option[Env] = {
if (modules.contains(fid)) then return modules(fid)

def loadModule(path: syntax.Node): Option[(FileId, Env)] = {
val fid = resolvePackage(path)
val env = createEnv(Some(fid));
if (fid._1.toString().startsWith("@cosmo/std:")) {
env.noCore = true
}
// println(s"Loading module $fid")
loadModuleBySrc(env, fid.pkg.sources(fid.path).source).map((fid, _))
logln(s"Loading module $fid")
val res = loadModuleBySrc(env, fid.pkg.sources(fid.path).source)
modules += (fid -> res)
res
}

def parse(s: String): Option[syntax.Block] = {
Expand Down
6 changes: 3 additions & 3 deletions packages/cosmo/src/main/scala/cosmo/Eval.scala
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ class Env(val fid: Option[FileId], pacMgr: cosmo.PackageManager) {
case RefItem(r, isMut) => dispatch(lhs, r, field, casted)
case Term(_, _, Some(v)) => dispatch(lhs, v, field, casted)
case Term(id, _, None) => dispatch(lhs, id.ty, field, casted)
case NativeModule(info, env, fid) =>
case NativeModule(info, env) =>
return Some(env.scopes.get(field).map(env.byRef).getOrElse {
errors = s"Undefined item $field in ${info.name}" :: errors
Unresolved(ct(field))
Expand Down Expand Up @@ -707,8 +707,8 @@ class Env(val fid: Option[FileId], pacMgr: cosmo.PackageManager) {
case syntax.Ident(name) => name
case _ => "$module"
})
val moduleIns = pacMgr.loadModule(p) match {
case Some((fid, env)) => NativeModule(defInfo, env, fid)
val moduleIns = pacMgr.loadModuleBySyntax(p) match {
case Some(env) => NativeModule(defInfo, env)
case None => {
errors = s"Failed to load module $p" :: errors
Unresolved(defInfo)
Expand Down
3 changes: 1 addition & 2 deletions packages/cosmo/src/main/scala/cosmo/Item.scala
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ final case class CModule(id: DefInfo, kind: CModuleKind, path: String)
enum CModuleKind {
case Builtin, Error, Source
}
final case class NativeModule(id: DefInfo, env: Env, fid: FileId)
extends DeclLike {}
final case class NativeModule(id: DefInfo, env: Env) extends DeclLike {}
final case class HKTInstance(ty: Type, syntax: Item) extends Item {
override val level: Int = 1
override def toString(): String = s"(hkt($syntax)::type as $ty)"
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmo/src/main/scala/cosmo/linker/CmakeLinker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ target_link_libraries(cosmo_json INTERFACE cosmo_std)

val start = System.currentTimeMillis()
val src = system.readFile(path)
val generated = t.transpile(src).map { case (content, noCore) =>
var suf = if (noCore) "/lang" else ""
val generated = t.transpile(src).map { case (content, env) =>
var suf = if (env.noCore) "/lang" else ""
s"""#include <cosmo/std/src/prelude${suf}.h> // IWYU pragma: keep\n\n${content}"""
}

Expand Down
4 changes: 3 additions & 1 deletion packages/cosmo/src/main/scala/cosmo/linker/HeadOnly.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ def headOnlyPkg(
var subIdentifier =
(identifier + "_" + pathWithoutExt.replace("/", "_")).toUpperCase

val s = t.transpileByFid(src.fid)

var generated =
t.transpile(src.source, Some(src.fid)).map { case (content, noCore) =>
s.map { case (content, env) =>
s"""#ifndef ${subIdentifier}_H\n#define ${subIdentifier}_H\n\n""" + content + s"\n\n#endif // ${subIdentifier}_H\n"
}

Expand Down
4 changes: 2 additions & 2 deletions packages/cosmo/src/main/scala/cosmo/linker/MsvcLinker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class MsvcLinker(system: CosmoSystem) extends Linker {
relReleaseDir: String,
): Option[String] = {
val src = system.readFile(path)
val generated = t.transpile(src).map { case (content, noCore) =>
var suf = if (noCore) "/lang" else ""
val generated = t.transpile(src).map { case (content, env) =>
var suf = if (env.noCore) "/lang" else ""
s"""#include <cosmo/std/src/prelude${suf}.h> // IWYU pragma: keep\n\n${content}"""
}

Expand Down

0 comments on commit 10414ac

Please sign in to comment.