From 439373f18af9b90a2bbb6e2cc87999d36a448938 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 10:30:25 +0100 Subject: [PATCH 01/14] scopes: debug reprs, parent references --- .../baboon/typer/BaboonTyper.scala | 90 ++++++++++++++----- .../baboon/typer/model/Scope.scala | 34 ++++--- 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 5c61f86..e0b0d5b 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -20,6 +20,24 @@ trait BaboonTyper { object BaboonTyper { case class FullRawDefn(defn: RawDefn, gcRoot: Boolean) + object FullRawDefn { + implicit class DebugExt(defn: FullRawDefn) { + def debugRepr: String = { + val n = defn.defn.name.name + val name = defn.defn match { + case _: RawDto => s"dto" + case _: RawContract => s"contract" + case _: RawEnum => s"contract" + case _: RawAdt => s"adt" + case _: RawForeign => s"foreign" + case _: RawNamespace => s"namespace" + } + + val root = if (defn.gcRoot) { "!" } else { "" } + s"$root$name $n" + } + } + } case class ScopedDefn(thisScope: NestedScope[FullRawDefn], path: NEList[Scope[FullRawDefn]]) @@ -351,7 +369,15 @@ object BaboonTyper { .map(s => (s.name, s)) .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) } yield { - RootScope(pkg, asMap) + val out = RootScope(pkg, asMap) + asMap.foreach { + case (_, s) => + assert(s.parent == null) + s.parent = out + } + + //println(out.debugRepr(_.debugRepr)) + out } } @@ -360,6 +386,22 @@ object BaboonTyper { member: RawDefn, isRoot: Boolean ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { + def finish(defn: RawDefn, + asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { + val out = SubScope( + ScopeName(defn.name.name), + FullRawDefn(defn, isRoot), + asNEMap, + null, + ) + asNEMap.foreach { + case (_, s) => + assert(s.parent == null) + s.parent = out + } + out + } + member match { case namespace: RawNamespace => for { @@ -375,26 +417,9 @@ object BaboonTyper { .from(asMap) .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) } yield { - SubScope( - ScopeName(namespace.name.name), - FullRawDefn(namespace, isRoot), - asNEMap - ) + finish(namespace, asNEMap) } - case dto: RawDto => - Right(LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot))) - case contract: RawContract => - Right( - LeafScope( - ScopeName(contract.name.name), - FullRawDefn(contract, isRoot) - ) - ) - case e: RawEnum => - Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot))) - case f: RawForeign => - Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot))) case adt: RawAdt => for { sub <- adt.members @@ -410,12 +435,29 @@ object BaboonTyper { .from(asMap) .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) } yield { - SubScope( - ScopeName(adt.name.name), - FullRawDefn(adt, isRoot), - asNEMap - ) + finish(adt, asNEMap) } + + case dto: RawDto => + Right( + LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot), null) + ) + + case contract: RawContract => + Right( + LeafScope( + ScopeName(contract.name.name), + FullRawDefn(contract, isRoot), + null, + ) + ) + + case e: RawEnum => + Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot), null)) + + case f: RawForeign => + Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot), null)) + } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index 0809f7f..e5f4cbe 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -13,25 +13,31 @@ object Scope { sealed trait NestedScope[Def] extends Scope[Def] { def name: ScopeName def defn: Def + var parent: Scope[Def] } case class SubScope[Def](name: ScopeName, defn: Def, - nested: NEMap[ScopeName, NestedScope[Def]]) - extends NestedScope[Def] - - case class LeafScope[Def](name: ScopeName, defn: Def) extends NestedScope[Def] - - implicit class DebugExt[Def](path: List[Scope[Def]]) { - private def asPathElement(s: Scope[?]): String = { - s match { - case RootScope(pkg, _) => pkg.toString - case scope: NestedScope[_] => scope.name.name + nested: NEMap[ScopeName, NestedScope[Def]], + var parent: Scope[Def], + ) extends NestedScope[Def] + + case class LeafScope[Def](name: ScopeName, + defn: Def, + var parent: Scope[Def], + ) extends NestedScope[Def] + + implicit class DebugExt[Def](scope: Scope[Def]) { + def debugRepr(defnRepr: Def => String): String = { + import izumi.fundamentals.platform.strings.IzString.* + scope match { + case s: RootScope[Def] => + s"${s.pkg.toString}${s.nested.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" + case s: SubScope[Def] => + s"${s.name.name} <- ${defnRepr(s.defn)} ${s.nested.toMap.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" + case s: LeafScope[Def] => + s"${s.name.name} := ${defnRepr(s.defn)}" } } - - def asStrDebug: String = { - path.map(v => asPathElement(v)).mkString("/") - } } } From b95258201f41e261b31297e1f50f0dd6557e9fc8 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 11:15:44 +0100 Subject: [PATCH 02/14] wip --- .../parser/model/issues/BaboonIssue.scala | 2 +- .../baboon/typer/BaboonTranslator.scala | 25 ++-- .../baboon/typer/BaboonTyper.scala | 5 +- .../baboon/typer/ScopeSupport.scala | 123 ++++++++---------- 4 files changed, 67 insertions(+), 88 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala index bd5d3cd..cc7154f 100644 --- a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala +++ b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala @@ -64,7 +64,7 @@ object BaboonIssue { case class UnexpectedNonBuiltin(name: TypeName, pkg: Pkg, - path: NEList[Scope[FullRawDefn]], + path: Scope[FullRawDefn], meta: RawNodeMeta) extends TyperIssue diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 1a7aaa4..138927d 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -25,7 +25,7 @@ class BaboonTranslator(pkg: Pkg, rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - path, + path.last, pkg, rawDefn.defn.meta ) @@ -117,7 +117,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], Seq[Field]] = { for { - id <- scopeSupport.resolveScopedRef(parent, path, pkg, refMeta) + id <- scopeSupport.resolveScopedRef(parent, path.last, pkg, refMeta) parentDef = defined(id) out <- parentDef match { case DomainMember.User(_, defn: Typedef.Dto, _) => @@ -158,7 +158,12 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta, ): Either[NEList[BaboonIssue.TyperIssue], List[ContractContent]] = { for { - id <- scopeSupport.resolveScopedRef(c.contract.tpe, path, pkg, refMeta) + id <- scopeSupport.resolveScopedRef( + c.contract.tpe, + path.last, + pkg, + refMeta + ) content <- readContractContent(id, meta) } yield { content @@ -277,12 +282,7 @@ class BaboonTranslator(pkg: Pkg, .map( member => scopeSupport - .resolveUserTypeId( - member.defn.name, - path :+ thisScope, - pkg, - member.meta - ) + .resolveUserTypeId(member.defn.name, thisScope, pkg, member.meta) ) .biSequence nel <- NEList @@ -291,7 +291,8 @@ class BaboonTranslator(pkg: Pkg, contracts <- adt.contracts .map( ref => - scopeSupport.resolveScopedRef(ref.contract.tpe, path, pkg, ref.meta) + scopeSupport + .resolveScopedRef(ref.contract.tpe, path.last, pkg, ref.meta) ) .biSequence .map(_.toList) @@ -316,7 +317,7 @@ class BaboonTranslator(pkg: Pkg, tpe match { case RawTypeRef.Simple(name, prefix) => for { - id <- scopeSupport.resolveTypeId(prefix, name, path, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, path.last, pkg, meta) asScalar <- id match { case scalar: TypeId.Scalar => Right(scalar) @@ -331,7 +332,7 @@ class BaboonTranslator(pkg: Pkg, _ <- Either.ifThenFail(prefix.nonEmpty)( NEList(ScopedRefToNamespacedGeneric(prefix, meta)) ) - id <- scopeSupport.resolveTypeId(prefix, name, path, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, path.last, pkg, meta) asCollection <- id match { case coll: TypeId.BuiltinCollection => Right(coll) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index e0b0d5b..0bef346 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -313,7 +313,7 @@ object BaboonTyper { rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - defn.path, + defn.thisScope, pkg, rawDefn.defn.meta ) @@ -322,7 +322,7 @@ object BaboonTyper { .map( v => scopeSupport - .resolveScopedRef(v, defn.path, pkg, rawDefn.defn.meta) + .resolveScopedRef(v, defn.path.last, pkg, rawDefn.defn.meta) ) .biSequence } yield { @@ -376,7 +376,6 @@ object BaboonTyper { s.parent = out } - //println(out.debugRepr(_.debugRepr)) out } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 0bbf485..86aaea1 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -1,7 +1,7 @@ package io.septimalmind.baboon.typer -import io.septimalmind.baboon.parser.model.issues.BaboonIssue import io.septimalmind.baboon.parser.model.* +import io.septimalmind.baboon.parser.model.issues.BaboonIssue import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.{ @@ -18,7 +18,7 @@ import scala.annotation.tailrec trait ScopeSupport { def resolveScopedRef( name: ScopedRef, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -26,14 +26,14 @@ trait ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] def resolveUserTypeId( name: RawTypeName, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -51,12 +51,12 @@ object ScopeSupport { class ScopeSupportImpl extends ScopeSupport { def resolveScopedRef( name: ScopedRef, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { - val found = findDefn(ScopeName(name.path.head.name), path.reverse.toList) - + val found = findScope(NEList(ScopeName(name.path.head.name)), scope) + .map(convertToDefn) found match { case Some(found) => for { @@ -64,7 +64,7 @@ object ScopeSupport { fullPath = (found.path :+ found.scope) ++ scope.suffix resolved <- resolveUserTypeId( name.path.last, - NEList.unsafeFrom(fullPath.init), + fullPath.last, pkg, meta ) @@ -73,7 +73,6 @@ object ScopeSupport { } case None => - System.exit(1) Left(NEList(BaboonIssue.NameNotFound(pkg, name, meta))) } } @@ -111,12 +110,12 @@ object ScopeSupport { def resolveUserTypeId( name: RawTypeName, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { for { - id <- resolveTypeId(List.empty, name, path, pkg, meta) + id <- resolveTypeId(List.empty, name, scope, pkg, meta) userId <- id match { case id: TypeId.Builtin => Left(NEList(BaboonIssue.UnexpectedBuiltin(id, pkg, meta))) @@ -143,18 +142,20 @@ object ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] = { for { typename <- convertTypename(name, meta) - needle = prefix.map(_.name).map(ScopeName) ++ List(ScopeName(name.name)) - found = findPrefixedDefn(needle, path.reverse.toList) + needle = prefix.map(_.name).map(ScopeName) ++: NEList( + ScopeName(name.name) + ) + found = findScope(needle, scope).map(convertToDefn) result <- found match { case Some(value) => for { - owner <- pathToOwner(value.path, pkg) + owner <- pathToOwner(asPath(value.scope).toList, pkg) } yield { val out = TypeId.User(pkg, owner, typename) out @@ -162,7 +163,7 @@ object ScopeSupport { case None => asBuiltin(typename).toRight( NEList( - BaboonIssue.UnexpectedNonBuiltin(typename, pkg, path, meta) + BaboonIssue.UnexpectedNonBuiltin(typename, pkg, scope, meta) ) ) } @@ -171,38 +172,6 @@ object ScopeSupport { } } - private def findPrefixedDefn( - needles: List[ScopeName], - reversePath: List[Scope[FullRawDefn]] - ): Option[FoundDefn] = { - - def subfind(needle: ScopeName, - reversePath: List[Scope[FullRawDefn]]): Option[FoundDefn] = { - findDefn(needle, reversePath).orElse { - reversePath match { - case _ :: tail => - subfind(needle, tail) - case Nil => - None - } - - } - } - - val out = needles match { - case Nil => - None - case head :: Nil => - subfind(head, reversePath) - case head :: tail => - subfind(head, reversePath).flatMap { found => - val newpath = (found.path ++ List(found.scope)).reverse - findPrefixedDefn(tail, newpath) - } - } - out - } - private def pathToOwner(defnPath: List[Scope[FullRawDefn]], pkg: Pkg, ): Either[NEList[BaboonIssue.TyperIssue], Owner] = { @@ -274,40 +243,50 @@ object ScopeSupport { } } - private def findDefn( - needle: ScopeName, - reversePath: List[Scope[FullRawDefn]] - ): Option[FoundDefn] = { - def found(p: List[Scope[FullRawDefn]], n: NestedScope[FullRawDefn]) = { - if (p.last == n) { - FoundDefn(p.init, n) - } else { - FoundDefn(p, n) + private def asPath(scope: Scope[FullRawDefn]): List[Scope[FullRawDefn]] = { + + def go(scope: Scope[FullRawDefn]): NEList[Scope[FullRawDefn]] = { + scope match { + case r: RootScope[FullRawDefn] => NEList(r) + case scope: NestedScope[FullRawDefn] => + go(scope.parent) ++ NEList(scope) } } + go(scope).toList.init + + } + private def convertToDefn(scope: NestedScope[FullRawDefn]): FoundDefn = { + FoundDefn(asPath(scope), scope) + } + + private def findScope(needles: NEList[ScopeName], + scope: Scope[FullRawDefn], + ): Option[NestedScope[FullRawDefn]] = { - reversePath.headOption match { - case Some(s: RootScope[FullRawDefn]) => - s.nested - .get(needle) - .map(n => found(reversePath, n)) + val head = needles.head - case Some(s: LeafScope[FullRawDefn]) => + val headScope = scope match { + case s: RootScope[FullRawDefn] => + s.nested.get(head) + + case s: LeafScope[FullRawDefn] => Some(s) - .filter(_.name == needle) - .map(n => found(reversePath.reverse, n)) - .orElse(findDefn(needle, reversePath.tail)) + .filter(_.name == head) + .orElse(findScope(needles, s.parent)) - case Some(s: SubScope[FullRawDefn]) => + case s: SubScope[FullRawDefn] => s.nested.toMap - .get(needle) - .orElse(Some(s).filter(_.name == needle)) - .map(n => found(reversePath.reverse, n)) - .orElse(findDefn(needle, reversePath.tail)) + .get(head) + .orElse(Some(s).filter(_.name == head)) + .orElse(findScope(needles, s.parent)) + } + NEList.from(needles.tail) match { + case Some(value) => + headScope.flatMap(nested => findScope(value, nested)) case None => - None + headScope } } From c0964e1545778cd277b23b4155705641e1cf1edd Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 11:24:06 +0100 Subject: [PATCH 03/14] wip --- .../io/septimalmind/baboon/BaboonModule.scala | 2 +- .../baboon/typer/BaboonTranslator.scala | 19 +++++++------------ .../baboon/typer/BaboonTyper.scala | 16 +++++++--------- .../baboon/typer/ScopeSupport.scala | 17 ++++------------- 4 files changed, 19 insertions(+), 35 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala index 176647c..a0ed6a6 100644 --- a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala +++ b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala @@ -47,7 +47,7 @@ class BaboonModule(options: CompilerOptions, .localDependencies( List( DIKey[Pkg], - DIKey[NEList[Scope[FullRawDefn]]], + DIKey[Scope[FullRawDefn]], DIKey[Map[TypeId, DomainMember]] ) ) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 138927d..999c8ab 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -14,7 +14,7 @@ import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.NEList class BaboonTranslator(pkg: Pkg, - path: NEList[Scope[FullRawDefn]], + scope: Scope[FullRawDefn], defined: Map[TypeId, DomainMember], scopeSupport: ScopeSupport) { def translate( @@ -25,7 +25,7 @@ class BaboonTranslator(pkg: Pkg, rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - path.last, + scope, pkg, rawDefn.defn.meta ) @@ -117,7 +117,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], Seq[Field]] = { for { - id <- scopeSupport.resolveScopedRef(parent, path.last, pkg, refMeta) + id <- scopeSupport.resolveScopedRef(parent, scope, pkg, refMeta) parentDef = defined(id) out <- parentDef match { case DomainMember.User(_, defn: Typedef.Dto, _) => @@ -158,12 +158,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta, ): Either[NEList[BaboonIssue.TyperIssue], List[ContractContent]] = { for { - id <- scopeSupport.resolveScopedRef( - c.contract.tpe, - path.last, - pkg, - refMeta - ) + id <- scopeSupport.resolveScopedRef(c.contract.tpe, scope, pkg, refMeta) content <- readContractContent(id, meta) } yield { content @@ -292,7 +287,7 @@ class BaboonTranslator(pkg: Pkg, .map( ref => scopeSupport - .resolveScopedRef(ref.contract.tpe, path.last, pkg, ref.meta) + .resolveScopedRef(ref.contract.tpe, scope, pkg, ref.meta) ) .biSequence .map(_.toList) @@ -317,7 +312,7 @@ class BaboonTranslator(pkg: Pkg, tpe match { case RawTypeRef.Simple(name, prefix) => for { - id <- scopeSupport.resolveTypeId(prefix, name, path.last, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, scope, pkg, meta) asScalar <- id match { case scalar: TypeId.Scalar => Right(scalar) @@ -332,7 +327,7 @@ class BaboonTranslator(pkg: Pkg, _ <- Either.ifThenFail(prefix.nonEmpty)( NEList(ScopedRefToNamespacedGeneric(prefix, meta)) ) - id <- scopeSupport.resolveTypeId(prefix, name, path.last, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, scope, pkg, meta) asCollection <- id match { case coll: TypeId.BuiltinCollection => Right(coll) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 0bef346..070b4a7 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -39,8 +39,7 @@ object BaboonTyper { } } - case class ScopedDefn(thisScope: NestedScope[FullRawDefn], - path: NEList[Scope[FullRawDefn]]) + case class ScopedDefn(thisScope: NestedScope[FullRawDefn]) class BaboonTyperImpl(enquiries: BaboonEnquiries, translator: Subcontext[BaboonTranslator], @@ -261,7 +260,7 @@ object BaboonTyper { for { next <- translator .provide(pkg) - .provide(defn.path) + .provide(defn.thisScope: Scope[FullRawDefn]) .provide(acc) .produce() .use(_.translate(defn)) @@ -322,7 +321,7 @@ object BaboonTyper { .map( v => scopeSupport - .resolveScopedRef(v, defn.path.last, pkg, rawDefn.defn.meta) + .resolveScopedRef(v, defn.thisScope, pkg, rawDefn.defn.meta) ) .biSequence } yield { @@ -339,22 +338,21 @@ object BaboonTyper { root: RootScope[FullRawDefn] ): List[ScopedDefn] = { root.nested.values - .flatMap(defn => flattenScopes(NEList(root), defn)) + .flatMap(defn => flattenScopes(defn)) .toList } private def flattenScopes( - path: NEList[Scope[FullRawDefn]], current: NestedScope[FullRawDefn] ): List[ScopedDefn] = { current match { case s: SubScope[FullRawDefn] => - List(ScopedDefn(s, path)) ++ s.nested.toMap.values - .flatMap(n => flattenScopes(path :+ current, n)) + List(ScopedDefn(s)) ++ s.nested.toMap.values + .flatMap(n => flattenScopes(n)) .toList case l: LeafScope[FullRawDefn] => - List(ScopedDefn(l, path)) + List(ScopedDefn(l)) } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 86aaea1..bbb81ea 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -40,11 +40,6 @@ trait ScopeSupport { } object ScopeSupport { - case class FoundDefn(path: List[Scope[FullRawDefn]], - scope: NestedScope[FullRawDefn]) { - def defn: FullRawDefn = scope.defn - } - case class LookupResult(suffix: List[Scope[FullRawDefn]], scope: LeafScope[FullRawDefn]) @@ -56,12 +51,11 @@ object ScopeSupport { meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { val found = findScope(NEList(ScopeName(name.path.head.name)), scope) - .map(convertToDefn) found match { case Some(found) => for { - scope <- lookupName(name.path.tail, found.scope, List.empty, meta) - fullPath = (found.path :+ found.scope) ++ scope.suffix + scope <- lookupName(name.path.tail, found, List.empty, meta) + fullPath = List(found) ++ scope.suffix resolved <- resolveUserTypeId( name.path.last, fullPath.last, @@ -151,11 +145,11 @@ object ScopeSupport { needle = prefix.map(_.name).map(ScopeName) ++: NEList( ScopeName(name.name) ) - found = findScope(needle, scope).map(convertToDefn) + found = findScope(needle, scope) result <- found match { case Some(value) => for { - owner <- pathToOwner(asPath(value.scope).toList, pkg) + owner <- pathToOwner(asPath(value), pkg) } yield { val out = TypeId.User(pkg, owner, typename) out @@ -256,9 +250,6 @@ object ScopeSupport { go(scope).toList.init } - private def convertToDefn(scope: NestedScope[FullRawDefn]): FoundDefn = { - FoundDefn(asPath(scope), scope) - } private def findScope(needles: NEList[ScopeName], scope: Scope[FullRawDefn], From 895b601fc9b344b45aa01a5f38be09609fe4d7d4 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 11:26:18 +0100 Subject: [PATCH 04/14] wip --- .../baboon/typer/BaboonTyper.scala | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 070b4a7..0ad1fea 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -337,25 +337,22 @@ object BaboonTyper { private def flattenScopes( root: RootScope[FullRawDefn] ): List[ScopedDefn] = { + def flattenScopes(current: NestedScope[FullRawDefn]): List[ScopedDefn] = { + current match { + case s: SubScope[FullRawDefn] => + List(ScopedDefn(s)) ++ s.nested.toMap.values + .flatMap(n => flattenScopes(n)) + .toList + case l: LeafScope[FullRawDefn] => + List(ScopedDefn(l)) + } + } + root.nested.values .flatMap(defn => flattenScopes(defn)) .toList } - private def flattenScopes( - current: NestedScope[FullRawDefn] - ): List[ScopedDefn] = { - - current match { - case s: SubScope[FullRawDefn] => - List(ScopedDefn(s)) ++ s.nested.toMap.values - .flatMap(n => flattenScopes(n)) - .toList - case l: LeafScope[FullRawDefn] => - List(ScopedDefn(l)) - } - } - private def buildScopes( pkg: Pkg, members: Seq[RawTLDef], From 89cc9bab321589eb3fbcb9bc686f554735859971 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 15:54:30 +0100 Subject: [PATCH 05/14] wip --- .../baboon/typer/BaboonTyper.scala | 18 ++++------ .../baboon/typer/ScopeSupport.scala | 6 ++-- .../baboon/typer/model/Scope.scala | 36 +++++++++++++------ 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 0ad1fea..89f9dc1 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -367,8 +367,7 @@ object BaboonTyper { val out = RootScope(pkg, asMap) asMap.foreach { case (_, s) => - assert(s.parent == null) - s.parent = out + s.unsafeGetWriter.setParent(out) } out @@ -386,12 +385,10 @@ object BaboonTyper { ScopeName(defn.name.name), FullRawDefn(defn, isRoot), asNEMap, - null, ) asNEMap.foreach { case (_, s) => - assert(s.parent == null) - s.parent = out + s.unsafeGetWriter.setParent(out) } out } @@ -433,24 +430,21 @@ object BaboonTyper { } case dto: RawDto => - Right( - LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot), null) - ) + Right(LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot))) case contract: RawContract => Right( LeafScope( ScopeName(contract.name.name), - FullRawDefn(contract, isRoot), - null, + FullRawDefn(contract, isRoot) ) ) case e: RawEnum => - Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot), null)) + Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot))) case f: RawForeign => - Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot), null)) + Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot))) } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index bbb81ea..8dfccc7 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -243,7 +243,7 @@ object ScopeSupport { scope match { case r: RootScope[FullRawDefn] => NEList(r) case scope: NestedScope[FullRawDefn] => - go(scope.parent) ++ NEList(scope) + go(scope.getParent) ++ NEList(scope) } } @@ -264,13 +264,13 @@ object ScopeSupport { case s: LeafScope[FullRawDefn] => Some(s) .filter(_.name == head) - .orElse(findScope(needles, s.parent)) + .orElse(findScope(needles, s.getParent)) case s: SubScope[FullRawDefn] => s.nested.toMap .get(head) .orElse(Some(s).filter(_.name == head)) - .orElse(findScope(needles, s.parent)) + .orElse(findScope(needles, s.getParent)) } NEList.from(needles.tail) match { diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index e5f4cbe..add03c4 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -10,22 +10,38 @@ object Scope { case class RootScope[Def](pkg: Pkg, nested: Map[ScopeName, NestedScope[Def]]) extends Scope[Def] - sealed trait NestedScope[Def] extends Scope[Def] { + sealed trait ParentWriter[Def] { + def setParent(parent: Scope[Def]): Unit + } + + sealed trait WithParent[Def] { + this: NestedScope[Def] => + + private var parent: Scope[Def] = null + + def getParent: Scope[Def] = parent + + def unsafeGetWriter: ParentWriter[Def] = { + new ParentWriter[Def] { + def setParent(parent: Scope[Def]): Unit = { + assert(WithParent.this.parent == null) + WithParent.this.parent = parent + } + } + } + } + + sealed trait NestedScope[Def] extends Scope[Def] with WithParent[Def] { def name: ScopeName def defn: Def - var parent: Scope[Def] } case class SubScope[Def](name: ScopeName, defn: Def, - nested: NEMap[ScopeName, NestedScope[Def]], - var parent: Scope[Def], - ) extends NestedScope[Def] - - case class LeafScope[Def](name: ScopeName, - defn: Def, - var parent: Scope[Def], - ) extends NestedScope[Def] + nested: NEMap[ScopeName, NestedScope[Def]]) + extends NestedScope[Def] + + case class LeafScope[Def](name: ScopeName, defn: Def) extends NestedScope[Def] implicit class DebugExt[Def](scope: Scope[Def]) { def debugRepr(defnRepr: Def => String): String = { From 0c0f726c1cea4a44e422e1fb0a6180604d22e496 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 16:25:59 +0100 Subject: [PATCH 06/14] wip --- .../baboon/typer/BaboonTyper.scala | 102 +---------------- .../baboon/typer/ScopeBuilder.scala | 108 ++++++++++++++++++ 2 files changed, 111 insertions(+), 99 deletions(-) create mode 100644 src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 89f9dc1..e628ac9 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -7,7 +7,7 @@ import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.* import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* -import izumi.fundamentals.collections.nonempty.{NEList, NEMap} +import izumi.fundamentals.collections.nonempty.NEList import izumi.fundamentals.graphs.struct.IncidenceMatrix import izumi.fundamentals.graphs.tools.{Toposort, ToposortLoopBreaker} import izumi.fundamentals.graphs.{DG, GraphMeta} @@ -250,8 +250,8 @@ object BaboonTyper { initial <- Right( TypeId.Builtins.all.map(id => DomainMember.Builtin(id)) ) - - scopes <- buildScopes(pkg, members, meta) + builder = new ScopeBuilder() + scopes <- builder.buildScopes(pkg, members, meta) flattened = flattenScopes(scopes) ordered <- order(pkg, flattened, meta) @@ -353,102 +353,6 @@ object BaboonTyper { .toList } - private def buildScopes( - pkg: Pkg, - members: Seq[RawTLDef], - meta: RawNodeMeta - ): Either[NEList[BaboonIssue.TyperIssue], RootScope[FullRawDefn]] = { - for { - sub <- members.map(m => buildScope(m.value, m.root)).biSequence - asMap <- sub - .map(s => (s.name, s)) - .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) - } yield { - val out = RootScope(pkg, asMap) - asMap.foreach { - case (_, s) => - s.unsafeGetWriter.setParent(out) - } - - out - } - - } - - private def buildScope( - member: RawDefn, - isRoot: Boolean - ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { - def finish(defn: RawDefn, - asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { - val out = SubScope( - ScopeName(defn.name.name), - FullRawDefn(defn, isRoot), - asNEMap, - ) - asNEMap.foreach { - case (_, s) => - s.unsafeGetWriter.setParent(out) - } - out - } - - member match { - case namespace: RawNamespace => - for { - sub <- namespace.defns - .map(m => buildScope(m.value, isRoot = m.root)) - .biSequence - asMap <- sub - .map(s => (s.name, s)) - .toUniqueMap( - nus => NEList(BaboonIssue.NonUniqueScope(nus, member.meta)) - ) - asNEMap <- NEMap - .from(asMap) - .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) - } yield { - finish(namespace, asNEMap) - } - - case adt: RawAdt => - for { - sub <- adt.members - .collect { case d: RawAdtMember => d } - .map(m => buildScope(m.defn, isRoot = false)) - .biSequence - asMap <- sub - .map(s => (s.name, s)) - .toUniqueMap( - nus => NEList(BaboonIssue.NonUniqueScope(nus, member.meta)) - ) - asNEMap <- NEMap - .from(asMap) - .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) - } yield { - finish(adt, asNEMap) - } - - case dto: RawDto => - Right(LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot))) - - case contract: RawContract => - Right( - LeafScope( - ScopeName(contract.name.name), - FullRawDefn(contract, isRoot) - ) - ) - - case e: RawEnum => - Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot))) - - case f: RawForeign => - Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot))) - - } - } - } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala new file mode 100644 index 0000000..3a20db7 --- /dev/null +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -0,0 +1,108 @@ +package io.septimalmind.baboon.typer + +import io.septimalmind.baboon.parser.model.* +import io.septimalmind.baboon.parser.model.issues.BaboonIssue +import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn +import io.septimalmind.baboon.typer.model.* +import io.septimalmind.baboon.typer.model.Scope.* +import izumi.functional.IzEither.* +import izumi.fundamentals.collections.IzCollections.* +import izumi.fundamentals.collections.nonempty.{NEList, NEMap} + +class ScopeBuilder() { + def buildScopes( + pkg: Pkg, + members: Seq[RawTLDef], + meta: RawNodeMeta + ): Either[NEList[BaboonIssue.TyperIssue], RootScope[FullRawDefn]] = { + for { + sub <- members.map(m => buildScope(m.value, m.root)).biSequence + asMap <- sub + .map(s => (s.name, s)) + .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) + } yield { + val out = RootScope(pkg, asMap) + asMap.foreach { + case (_, s) => + s.unsafeGetWriter.setParent(out) + } + + out + } + + } + + private def buildScope( + member: RawDefn, + isRoot: Boolean + ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { + def finish(defn: RawDefn, + asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { + val out = SubScope( + ScopeName(defn.name.name), + FullRawDefn(defn, isRoot), + asNEMap, + ) + asNEMap.foreach { + case (_, s) => + s.unsafeGetWriter.setParent(out) + } + out + } + + member match { + case namespace: RawNamespace => + for { + sub <- namespace.defns + .map(m => buildScope(m.value, isRoot = m.root)) + .biSequence + asMap <- sub + .map(s => (s.name, s)) + .toUniqueMap( + nus => NEList(BaboonIssue.NonUniqueScope(nus, member.meta)) + ) + asNEMap <- NEMap + .from(asMap) + .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) + } yield { + finish(namespace, asNEMap) + } + + case adt: RawAdt => + for { + sub <- adt.members + .collect { case d: RawAdtMember => d } + .map(m => buildScope(m.defn, isRoot = false)) + .biSequence + asMap <- sub + .map(s => (s.name, s)) + .toUniqueMap( + nus => NEList(BaboonIssue.NonUniqueScope(nus, member.meta)) + ) + asNEMap <- NEMap + .from(asMap) + .toRight(NEList(BaboonIssue.ScopeCannotBeEmpty(member))) + } yield { + finish(adt, asNEMap) + } + + case dto: RawDto => + Right(LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot))) + + case contract: RawContract => + Right( + LeafScope( + ScopeName(contract.name.name), + FullRawDefn(contract, isRoot) + ) + ) + + case e: RawEnum => + Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot))) + + case f: RawForeign => + Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot))) + + } + } +} From 0ef148ecdbf69860fc16305593160168808d57ef Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 16:31:31 +0100 Subject: [PATCH 07/14] wip --- .../io/septimalmind/baboon/BaboonModule.scala | 4 +- .../baboon/typer/BaboonTranslator.scala | 42 +++++++++++++------ .../baboon/typer/BaboonTyper.scala | 6 +-- .../baboon/typer/ScopeBuilder.scala | 40 ++++++++++++++---- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala index a0ed6a6..e151bfa 100644 --- a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala +++ b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala @@ -7,7 +7,7 @@ import io.septimalmind.baboon.translator.BaboonAbstractTranslator import io.septimalmind.baboon.translator.csharp.CSValue.CSPackageId import io.septimalmind.baboon.translator.csharp.* import io.septimalmind.baboon.typer.* -import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn +import io.septimalmind.baboon.typer.BaboonTyper.{FullRawDefn, ScopedDefn} import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.util.BLogger import io.septimalmind.baboon.validator.BaboonValidator @@ -47,7 +47,7 @@ class BaboonModule(options: CompilerOptions, .localDependencies( List( DIKey[Pkg], - DIKey[Scope[FullRawDefn]], + DIKey[ScopedDefn], DIKey[Map[TypeId, DomainMember]] ) ) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 999c8ab..cbd3961 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -14,24 +14,23 @@ import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.NEList class BaboonTranslator(pkg: Pkg, - scope: Scope[FullRawDefn], + defn: ScopedDefn, defined: Map[TypeId, DomainMember], scopeSupport: ScopeSupport) { - def translate( - defn: ScopedDefn - ): Either[NEList[BaboonIssue.TyperIssue], List[DomainMember]] = { + def translate() + : Either[NEList[BaboonIssue.TyperIssue], List[DomainMember]] = { for { rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - scope, + defn.thisScope, pkg, rawDefn.defn.meta ) members <- convertMember(id, rawDefn, defn.thisScope) } yield { - members.toList + members } } @@ -117,7 +116,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], Seq[Field]] = { for { - id <- scopeSupport.resolveScopedRef(parent, scope, pkg, refMeta) + id <- scopeSupport.resolveScopedRef(parent, defn.thisScope, pkg, refMeta) parentDef = defined(id) out <- parentDef match { case DomainMember.User(_, defn: Typedef.Dto, _) => @@ -158,7 +157,12 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta, ): Either[NEList[BaboonIssue.TyperIssue], List[ContractContent]] = { for { - id <- scopeSupport.resolveScopedRef(c.contract.tpe, scope, pkg, refMeta) + id <- scopeSupport.resolveScopedRef( + c.contract.tpe, + defn.thisScope, + pkg, + refMeta + ) content <- readContractContent(id, meta) } yield { content @@ -256,11 +260,11 @@ class BaboonTranslator(pkg: Pkg, _ <- finalFields .map(m => (m.name.name.toLowerCase, m)) .toUniqueMap(e => NEList(BaboonIssue.NonUniqueFields(id, e, dto.meta))) - contractRefs = contracts.flatMap(_.refs).distinct.toList + contractRefs = contracts.flatMap(_.refs).distinct } yield { DomainMember.User( isRoot, - produce(id, finalFields.toList, contractRefs), + produce(id, finalFields, contractRefs), dto.meta ) } @@ -287,7 +291,7 @@ class BaboonTranslator(pkg: Pkg, .map( ref => scopeSupport - .resolveScopedRef(ref.contract.tpe, scope, pkg, ref.meta) + .resolveScopedRef(ref.contract.tpe, defn.thisScope, pkg, ref.meta) ) .biSequence .map(_.toList) @@ -312,7 +316,13 @@ class BaboonTranslator(pkg: Pkg, tpe match { case RawTypeRef.Simple(name, prefix) => for { - id <- scopeSupport.resolveTypeId(prefix, name, scope, pkg, meta) + id <- scopeSupport.resolveTypeId( + prefix, + name, + defn.thisScope, + pkg, + meta + ) asScalar <- id match { case scalar: TypeId.Scalar => Right(scalar) @@ -327,7 +337,13 @@ class BaboonTranslator(pkg: Pkg, _ <- Either.ifThenFail(prefix.nonEmpty)( NEList(ScopedRefToNamespacedGeneric(prefix, meta)) ) - id <- scopeSupport.resolveTypeId(prefix, name, scope, pkg, meta) + id <- scopeSupport.resolveTypeId( + prefix, + name, + defn.thisScope, + pkg, + meta + ) asCollection <- id match { case coll: TypeId.BuiltinCollection => Right(coll) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index e628ac9..3860573 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -252,7 +252,7 @@ object BaboonTyper { ) builder = new ScopeBuilder() scopes <- builder.buildScopes(pkg, members, meta) - flattened = flattenScopes(scopes) + flattened = flattenScopes(scopes.root) ordered <- order(pkg, flattened, meta) out <- ordered.biFoldLeft(Map.empty[TypeId, DomainMember]) { @@ -260,10 +260,10 @@ object BaboonTyper { for { next <- translator .provide(pkg) - .provide(defn.thisScope: Scope[FullRawDefn]) + .provide(defn) .provide(acc) .produce() - .use(_.translate(defn)) + .use(_.translate()) mapped = next.map(m => (m.id, m)) dupes = acc.keySet.intersect(mapped.map(_._1).toSet) _ <- Either.ifThenFail(dupes.nonEmpty)( diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala index 3a20db7..cb62462 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -4,37 +4,59 @@ import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.parser.model.issues.BaboonIssue import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn import io.septimalmind.baboon.typer.model.* -import io.septimalmind.baboon.typer.model.Scope.* +import io.septimalmind.baboon.typer.model.Scope.{NestedScope, *} import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.{NEList, NEMap} +import java.util + +case class ScopeTree( + root: RootScope[FullRawDefn], + parents: scala.collection.Map[NestedScope[FullRawDefn], Scope[FullRawDefn]] +) + class ScopeBuilder() { def buildScopes( pkg: Pkg, members: Seq[RawTLDef], meta: RawNodeMeta - ): Either[NEList[BaboonIssue.TyperIssue], RootScope[FullRawDefn]] = { + ): Either[NEList[BaboonIssue.TyperIssue], ScopeTree] = { + + val parents = + new util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]]() + for { - sub <- members.map(m => buildScope(m.value, m.root)).biSequence + sub <- members.map(m => buildScope(m.value, m.root, parents)).biSequence asMap <- sub .map(s => (s.name, s)) .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) } yield { val out = RootScope(pkg, asMap) + asMap.foreach { case (_, s) => s.unsafeGetWriter.setParent(out) + assert(!parents.containsKey(s)) + parents.put(s, out) } - out + import scala.jdk.CollectionConverters.* + val tree = parents.asScala + asMap.foreach { + case (_, s) => + assert(tree(s) == out) + } + + ScopeTree(out, tree) } } private def buildScope( member: RawDefn, - isRoot: Boolean + isRoot: Boolean, + parents: util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]] ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { def finish(defn: RawDefn, asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { @@ -46,6 +68,9 @@ class ScopeBuilder() { asNEMap.foreach { case (_, s) => s.unsafeGetWriter.setParent(out) + assert(!parents.containsKey(s)) + val prev = parents.put(s, out) + assert(prev == null) } out } @@ -54,7 +79,7 @@ class ScopeBuilder() { case namespace: RawNamespace => for { sub <- namespace.defns - .map(m => buildScope(m.value, isRoot = m.root)) + .map(m => buildScope(m.value, isRoot = m.root, parents)) .biSequence asMap <- sub .map(s => (s.name, s)) @@ -72,7 +97,7 @@ class ScopeBuilder() { for { sub <- adt.members .collect { case d: RawAdtMember => d } - .map(m => buildScope(m.defn, isRoot = false)) + .map(m => buildScope(m.defn, isRoot = false, parents)) .biSequence asMap <- sub .map(s => (s.name, s)) @@ -105,4 +130,5 @@ class ScopeBuilder() { } } + } From 2c550677b51b71bfdf1f72e6f779a738b971b684 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 16:58:00 +0100 Subject: [PATCH 08/14] wip --- .../baboon/typer/BaboonTranslator.scala | 36 ++++++++----------- .../baboon/typer/BaboonTyper.scala | 25 +++++++------ .../baboon/typer/ScopeSupport.scala | 35 +++++++++--------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index cbd3961..360ee35 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -6,7 +6,11 @@ import io.septimalmind.baboon.parser.model.issues.BaboonIssue.{ MissingContractFields, ScopedRefToNamespacedGeneric } -import io.septimalmind.baboon.typer.BaboonTyper.{FullRawDefn, ScopedDefn} +import io.septimalmind.baboon.typer.BaboonTyper.{ + FullRawDefn, + ScopeInContext, + ScopedDefn +} import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.NestedScope import izumi.functional.IzEither.* @@ -24,11 +28,11 @@ class BaboonTranslator(pkg: Pkg, rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - defn.thisScope, + defn.sic, pkg, rawDefn.defn.meta ) - members <- convertMember(id, rawDefn, defn.thisScope) + members <- convertMember(id, rawDefn, defn.sic) } yield { members } @@ -36,7 +40,7 @@ class BaboonTranslator(pkg: Pkg, private def convertMember(id: TypeId.User, defn: FullRawDefn, - thisScope: NestedScope[FullRawDefn], + thisScope: ScopeInContext, ): Either[NEList[BaboonIssue.TyperIssue], List[DomainMember.User]] = { val root = defn.gcRoot defn.defn match { @@ -116,7 +120,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], Seq[Field]] = { for { - id <- scopeSupport.resolveScopedRef(parent, defn.thisScope, pkg, refMeta) + id <- scopeSupport.resolveScopedRef(parent, defn.sic, pkg, refMeta) parentDef = defined(id) out <- parentDef match { case DomainMember.User(_, defn: Typedef.Dto, _) => @@ -159,7 +163,7 @@ class BaboonTranslator(pkg: Pkg, for { id <- scopeSupport.resolveScopedRef( c.contract.tpe, - defn.thisScope, + defn.sic, pkg, refMeta ) @@ -273,7 +277,7 @@ class BaboonTranslator(pkg: Pkg, private def convertAdt(id: TypeId.User, isRoot: Boolean, adt: RawAdt, - thisScope: NestedScope[FullRawDefn], + thisScope: ScopeInContext, ): Either[NEList[BaboonIssue.TyperIssue], NEList[DomainMember.User]] = { for { converted <- adt.members @@ -291,7 +295,7 @@ class BaboonTranslator(pkg: Pkg, .map( ref => scopeSupport - .resolveScopedRef(ref.contract.tpe, defn.thisScope, pkg, ref.meta) + .resolveScopedRef(ref.contract.tpe, defn.sic, pkg, ref.meta) ) .biSequence .map(_.toList) @@ -316,13 +320,7 @@ class BaboonTranslator(pkg: Pkg, tpe match { case RawTypeRef.Simple(name, prefix) => for { - id <- scopeSupport.resolveTypeId( - prefix, - name, - defn.thisScope, - pkg, - meta - ) + id <- scopeSupport.resolveTypeId(prefix, name, defn.sic, pkg, meta) asScalar <- id match { case scalar: TypeId.Scalar => Right(scalar) @@ -337,13 +335,7 @@ class BaboonTranslator(pkg: Pkg, _ <- Either.ifThenFail(prefix.nonEmpty)( NEList(ScopedRefToNamespacedGeneric(prefix, meta)) ) - id <- scopeSupport.resolveTypeId( - prefix, - name, - defn.thisScope, - pkg, - meta - ) + id <- scopeSupport.resolveTypeId(prefix, name, defn.sic, pkg, meta) asCollection <- id match { case coll: TypeId.BuiltinCollection => Right(coll) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 3860573..2f2023f 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -39,7 +39,14 @@ object BaboonTyper { } } - case class ScopedDefn(thisScope: NestedScope[FullRawDefn]) + case class ScopedDefn(thisScope: NestedScope[FullRawDefn], tree: ScopeTree) { + def sic: ScopeInContext = ScopeInContext(thisScope, tree) + } + + case class ScopeInContext(scope: Scope[FullRawDefn], tree: ScopeTree) { + def parentOf(s: NestedScope[FullRawDefn]) = + ScopeInContext(tree.parents(s), tree) + } class BaboonTyperImpl(enquiries: BaboonEnquiries, translator: Subcontext[BaboonTranslator], @@ -252,7 +259,7 @@ object BaboonTyper { ) builder = new ScopeBuilder() scopes <- builder.buildScopes(pkg, members, meta) - flattened = flattenScopes(scopes.root) + flattened = flattenScopes(scopes) ordered <- order(pkg, flattened, meta) out <- ordered.biFoldLeft(Map.empty[TypeId, DomainMember]) { @@ -312,7 +319,7 @@ object BaboonTyper { rawDefn <- Right(defn.thisScope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - defn.thisScope, + defn.sic, pkg, rawDefn.defn.meta ) @@ -321,7 +328,7 @@ object BaboonTyper { .map( v => scopeSupport - .resolveScopedRef(v, defn.thisScope, pkg, rawDefn.defn.meta) + .resolveScopedRef(v, defn.sic, pkg, rawDefn.defn.meta) ) .biSequence } yield { @@ -334,21 +341,19 @@ object BaboonTyper { } } - private def flattenScopes( - root: RootScope[FullRawDefn] - ): List[ScopedDefn] = { + private def flattenScopes(root: ScopeTree): List[ScopedDefn] = { def flattenScopes(current: NestedScope[FullRawDefn]): List[ScopedDefn] = { current match { case s: SubScope[FullRawDefn] => - List(ScopedDefn(s)) ++ s.nested.toMap.values + List(ScopedDefn(s, root)) ++ s.nested.toMap.values .flatMap(n => flattenScopes(n)) .toList case l: LeafScope[FullRawDefn] => - List(ScopedDefn(l)) + List(ScopedDefn(l, root)) } } - root.nested.values + root.root.nested.values .flatMap(defn => flattenScopes(defn)) .toList } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 8dfccc7..7f0a71d 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -2,7 +2,7 @@ package io.septimalmind.baboon.typer import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.parser.model.issues.BaboonIssue -import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn +import io.septimalmind.baboon.typer.BaboonTyper.{FullRawDefn, ScopeInContext} import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.{ LeafScope, @@ -18,7 +18,7 @@ import scala.annotation.tailrec trait ScopeSupport { def resolveScopedRef( name: ScopedRef, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -26,14 +26,14 @@ trait ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] def resolveUserTypeId( name: RawTypeName, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -46,7 +46,7 @@ object ScopeSupport { class ScopeSupportImpl extends ScopeSupport { def resolveScopedRef( name: ScopedRef, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { @@ -54,11 +54,11 @@ object ScopeSupport { found match { case Some(found) => for { - scope <- lookupName(name.path.tail, found, List.empty, meta) - fullPath = List(found) ++ scope.suffix + scopeOfFound <- lookupName(name.path.tail, found, List.empty, meta) + fullPath = List(found) ++ scopeOfFound.suffix resolved <- resolveUserTypeId( name.path.last, - fullPath.last, + ScopeInContext(fullPath.last, scope.tree), pkg, meta ) @@ -104,7 +104,7 @@ object ScopeSupport { def resolveUserTypeId( name: RawTypeName, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { @@ -136,7 +136,7 @@ object ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - scope: Scope[FullRawDefn], + scope: ScopeInContext, pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] = { @@ -157,7 +157,8 @@ object ScopeSupport { case None => asBuiltin(typename).toRight( NEList( - BaboonIssue.UnexpectedNonBuiltin(typename, pkg, scope, meta) + BaboonIssue + .UnexpectedNonBuiltin(typename, pkg, scope.scope, meta) ) ) } @@ -252,30 +253,32 @@ object ScopeSupport { } private def findScope(needles: NEList[ScopeName], - scope: Scope[FullRawDefn], + scope: ScopeInContext, ): Option[NestedScope[FullRawDefn]] = { val head = needles.head - val headScope = scope match { + val headScope = scope.scope match { case s: RootScope[FullRawDefn] => s.nested.get(head) case s: LeafScope[FullRawDefn] => Some(s) .filter(_.name == head) - .orElse(findScope(needles, s.getParent)) + .orElse(findScope(needles, scope.parentOf(s))) case s: SubScope[FullRawDefn] => s.nested.toMap .get(head) .orElse(Some(s).filter(_.name == head)) - .orElse(findScope(needles, s.getParent)) + .orElse(findScope(needles, scope.parentOf(s))) } NEList.from(needles.tail) match { case Some(value) => - headScope.flatMap(nested => findScope(value, nested)) + headScope.flatMap( + nested => findScope(value, ScopeInContext(nested, scope.tree)) + ) case None => headScope } From 6f47802ed1a282b171e78cd911ac0fd917d74fb5 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 17:01:15 +0100 Subject: [PATCH 09/14] wip --- .../io/septimalmind/baboon/BaboonModule.scala | 36 ++----------------- .../baboon/typer/BaboonTranslator.scala | 1 - .../baboon/typer/ScopeBuilder.scala | 2 -- .../baboon/typer/ScopeSupport.scala | 17 +++++---- .../baboon/typer/model/Scope.scala | 23 +----------- 5 files changed, 14 insertions(+), 65 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala index e151bfa..8c3ebf3 100644 --- a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala +++ b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala @@ -4,14 +4,13 @@ import distage.{DIKey, ModuleDef} import io.septimalmind.baboon.BaboonCompiler.CompilerOptions import io.septimalmind.baboon.parser.BaboonParser import io.septimalmind.baboon.translator.BaboonAbstractTranslator -import io.septimalmind.baboon.translator.csharp.CSValue.CSPackageId import io.septimalmind.baboon.translator.csharp.* +import io.septimalmind.baboon.translator.csharp.CSValue.CSPackageId import io.septimalmind.baboon.typer.* -import io.septimalmind.baboon.typer.BaboonTyper.{FullRawDefn, ScopedDefn} +import io.septimalmind.baboon.typer.BaboonTyper.ScopedDefn import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.util.BLogger import io.septimalmind.baboon.validator.BaboonValidator -import izumi.fundamentals.collections.nonempty.NEList import java.nio.file.Path @@ -45,11 +44,7 @@ class BaboonModule(options: CompilerOptions, makeSubcontext[BaboonTranslator] .localDependencies( - List( - DIKey[Pkg], - DIKey[ScopedDefn], - DIKey[Map[TypeId, DomainMember]] - ) + List(DIKey[Pkg], DIKey[ScopedDefn], DIKey[Map[TypeId, DomainMember]]) ) .withSubmodule(new ModuleDef { make[BaboonTranslator] @@ -57,17 +52,6 @@ class BaboonModule(options: CompilerOptions, .extractWith { (translator: BaboonTranslator) => translator } -// make[LocalContext[Identity, BaboonTranslator]] -// .fromLocalContext(new ModuleDef { -// make[BaboonTranslator] -// }.running { (translator: BaboonTranslator) => -// translator -// }) -// .external( -// DIKey[Pkg], -// DIKey[NEList[Scope[FullRawDefn]]], -// DIKey[Map[TypeId, DomainMember]] -// ) makeSubcontext[IndividualConversionHandler] .localDependencies( @@ -87,20 +71,6 @@ class BaboonModule(options: CompilerOptions, handler } -// make[LocalContext[Identity, IndividualConversionHandler]] -// .fromLocalContext(new ModuleDef { -// make[IndividualConversionHandler] -// }.running { (handler: IndividualConversionHandler) => -// handler -// }) -// .external( -// DIKey[CSPackageId], -// DIKey[Version], -// DIKey.get[Domain].named("current"), -// DIKey.get[Domain].named("source"), -// DIKey.get[BaboonRuleset] -// ) - many[CSCodecTranslator] .add[CSNSJsonCodecGenerator] .add[CSUEBACodecGenerator] diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 360ee35..5a47405 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -12,7 +12,6 @@ import io.septimalmind.baboon.typer.BaboonTyper.{ ScopedDefn } import io.septimalmind.baboon.typer.model.* -import io.septimalmind.baboon.typer.model.Scope.NestedScope import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.NEList diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala index cb62462..e959fc4 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -36,7 +36,6 @@ class ScopeBuilder() { asMap.foreach { case (_, s) => - s.unsafeGetWriter.setParent(out) assert(!parents.containsKey(s)) parents.put(s, out) } @@ -67,7 +66,6 @@ class ScopeBuilder() { ) asNEMap.foreach { case (_, s) => - s.unsafeGetWriter.setParent(out) assert(!parents.containsKey(s)) val prev = parents.put(s, out) assert(prev == null) diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 7f0a71d..103590f 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -149,7 +149,10 @@ object ScopeSupport { result <- found match { case Some(value) => for { - owner <- pathToOwner(asPath(value), pkg) + owner <- pathToOwner( + asPath(ScopeInContext(value, scope.tree)), + pkg + ) } yield { val out = TypeId.User(pkg, owner, typename) out @@ -238,17 +241,17 @@ object ScopeSupport { } } - private def asPath(scope: Scope[FullRawDefn]): List[Scope[FullRawDefn]] = { + private def asPath(scope: ScopeInContext): List[Scope[FullRawDefn]] = { - def go(scope: Scope[FullRawDefn]): NEList[Scope[FullRawDefn]] = { - scope match { + def go(s: Scope[FullRawDefn]): NEList[Scope[FullRawDefn]] = { + s match { case r: RootScope[FullRawDefn] => NEList(r) - case scope: NestedScope[FullRawDefn] => - go(scope.getParent) ++ NEList(scope) + case n: NestedScope[FullRawDefn] => + go(scope.parentOf(n).scope) ++ NEList(n) } } - go(scope).toList.init + go(scope.scope).toList.init } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index add03c4..0aa9dfb 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -10,28 +10,7 @@ object Scope { case class RootScope[Def](pkg: Pkg, nested: Map[ScopeName, NestedScope[Def]]) extends Scope[Def] - sealed trait ParentWriter[Def] { - def setParent(parent: Scope[Def]): Unit - } - - sealed trait WithParent[Def] { - this: NestedScope[Def] => - - private var parent: Scope[Def] = null - - def getParent: Scope[Def] = parent - - def unsafeGetWriter: ParentWriter[Def] = { - new ParentWriter[Def] { - def setParent(parent: Scope[Def]): Unit = { - assert(WithParent.this.parent == null) - WithParent.this.parent = parent - } - } - } - } - - sealed trait NestedScope[Def] extends Scope[Def] with WithParent[Def] { + sealed trait NestedScope[Def] extends Scope[Def] { def name: ScopeName def defn: Def } From 5dee9995c3c81bd6a0189e6673d57bda91230ba9 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 17:14:10 +0100 Subject: [PATCH 10/14] wip --- .../io/septimalmind/baboon/BaboonModule.scala | 3 +- .../parser/model/issues/BaboonIssue.scala | 6 +- .../baboon/typer/BaboonTranslator.scala | 28 +++------- .../baboon/typer/BaboonTyper.scala | 56 +++++-------------- .../baboon/typer/ScopeBuilder.scala | 6 -- .../baboon/typer/ScopeSupport.scala | 9 ++- .../baboon/typer/model/FullRawDefn.scala | 24 ++++++++ .../baboon/typer/model/ScopeInContext.scala | 17 ++++++ .../baboon/typer/model/ScopeTree.scala | 9 +++ 9 files changed, 80 insertions(+), 78 deletions(-) create mode 100644 src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala create mode 100644 src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala create mode 100644 src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala diff --git a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala index 8c3ebf3..d3e0be5 100644 --- a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala +++ b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala @@ -7,7 +7,6 @@ import io.septimalmind.baboon.translator.BaboonAbstractTranslator import io.septimalmind.baboon.translator.csharp.* import io.septimalmind.baboon.translator.csharp.CSValue.CSPackageId import io.septimalmind.baboon.typer.* -import io.septimalmind.baboon.typer.BaboonTyper.ScopedDefn import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.util.BLogger import io.septimalmind.baboon.validator.BaboonValidator @@ -44,7 +43,7 @@ class BaboonModule(options: CompilerOptions, makeSubcontext[BaboonTranslator] .localDependencies( - List(DIKey[Pkg], DIKey[ScopedDefn], DIKey[Map[TypeId, DomainMember]]) + List(DIKey[Pkg], DIKey[CNestedScope], DIKey[Map[TypeId, DomainMember]]) ) .withSubmodule(new ModuleDef { make[BaboonTranslator] diff --git a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala index cc7154f..62e0be9 100644 --- a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala +++ b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala @@ -4,8 +4,6 @@ import fastparse.Parsed import io.septimalmind.baboon.parser.BaboonParser import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.translator.OutputFile -import io.septimalmind.baboon.typer.BaboonTyper -import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn import io.septimalmind.baboon.typer.model.* import izumi.fundamentals.collections.nonempty.NEList import izumi.fundamentals.graphs.ToposortError @@ -128,8 +126,8 @@ object BaboonIssue { case class BadTypeName(name: String, meta: RawNodeMeta) extends TyperIssue case class BadInheritance( - bad: Map[TypeId.User, List[(Set[TypeId.User], BaboonTyper.ScopedDefn)]], - meta: RawNodeMeta + bad: Map[TypeId.User, List[(Set[TypeId.User], CNestedScope)]], + meta: RawNodeMeta ) extends TyperIssue with BaboonBug diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 5a47405..59c36e0 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -6,32 +6,27 @@ import io.septimalmind.baboon.parser.model.issues.BaboonIssue.{ MissingContractFields, ScopedRefToNamespacedGeneric } -import io.septimalmind.baboon.typer.BaboonTyper.{ - FullRawDefn, - ScopeInContext, - ScopedDefn -} import io.septimalmind.baboon.typer.model.* import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.NEList class BaboonTranslator(pkg: Pkg, - defn: ScopedDefn, + defn: CNestedScope, defined: Map[TypeId, DomainMember], scopeSupport: ScopeSupport) { def translate() : Either[NEList[BaboonIssue.TyperIssue], List[DomainMember]] = { for { - rawDefn <- Right(defn.thisScope.defn) + rawDefn <- Right(defn.scope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - defn.sic, + defn, pkg, rawDefn.defn.meta ) - members <- convertMember(id, rawDefn, defn.sic) + members <- convertMember(id, rawDefn, defn) } yield { members } @@ -119,7 +114,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], Seq[Field]] = { for { - id <- scopeSupport.resolveScopedRef(parent, defn.sic, pkg, refMeta) + id <- scopeSupport.resolveScopedRef(parent, defn, pkg, refMeta) parentDef = defined(id) out <- parentDef match { case DomainMember.User(_, defn: Typedef.Dto, _) => @@ -160,12 +155,7 @@ class BaboonTranslator(pkg: Pkg, refMeta: RawNodeMeta, ): Either[NEList[BaboonIssue.TyperIssue], List[ContractContent]] = { for { - id <- scopeSupport.resolveScopedRef( - c.contract.tpe, - defn.sic, - pkg, - refMeta - ) + id <- scopeSupport.resolveScopedRef(c.contract.tpe, defn, pkg, refMeta) content <- readContractContent(id, meta) } yield { content @@ -294,7 +284,7 @@ class BaboonTranslator(pkg: Pkg, .map( ref => scopeSupport - .resolveScopedRef(ref.contract.tpe, defn.sic, pkg, ref.meta) + .resolveScopedRef(ref.contract.tpe, defn, pkg, ref.meta) ) .biSequence .map(_.toList) @@ -319,7 +309,7 @@ class BaboonTranslator(pkg: Pkg, tpe match { case RawTypeRef.Simple(name, prefix) => for { - id <- scopeSupport.resolveTypeId(prefix, name, defn.sic, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, defn, pkg, meta) asScalar <- id match { case scalar: TypeId.Scalar => Right(scalar) @@ -334,7 +324,7 @@ class BaboonTranslator(pkg: Pkg, _ <- Either.ifThenFail(prefix.nonEmpty)( NEList(ScopedRefToNamespacedGeneric(prefix, meta)) ) - id <- scopeSupport.resolveTypeId(prefix, name, defn.sic, pkg, meta) + id <- scopeSupport.resolveTypeId(prefix, name, defn, pkg, meta) asCollection <- id match { case coll: TypeId.BuiltinCollection => Right(coll) diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index 2f2023f..c47638e 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -19,34 +19,6 @@ trait BaboonTyper { } object BaboonTyper { - case class FullRawDefn(defn: RawDefn, gcRoot: Boolean) - object FullRawDefn { - implicit class DebugExt(defn: FullRawDefn) { - def debugRepr: String = { - val n = defn.defn.name.name - val name = defn.defn match { - case _: RawDto => s"dto" - case _: RawContract => s"contract" - case _: RawEnum => s"contract" - case _: RawAdt => s"adt" - case _: RawForeign => s"foreign" - case _: RawNamespace => s"namespace" - } - - val root = if (defn.gcRoot) { "!" } else { "" } - s"$root$name $n" - } - } - } - - case class ScopedDefn(thisScope: NestedScope[FullRawDefn], tree: ScopeTree) { - def sic: ScopeInContext = ScopeInContext(thisScope, tree) - } - - case class ScopeInContext(scope: Scope[FullRawDefn], tree: ScopeTree) { - def parentOf(s: NestedScope[FullRawDefn]) = - ScopeInContext(tree.parents(s), tree) - } class BaboonTyperImpl(enquiries: BaboonEnquiries, translator: Subcontext[BaboonTranslator], @@ -289,10 +261,10 @@ object BaboonTyper { } private def order( - pkg: Pkg, - flattened: List[ScopedDefn], - meta: RawNodeMeta - ): Either[NEList[BaboonIssue.TyperIssue], List[ScopedDefn]] = { + pkg: Pkg, + flattened: List[CNestedScope], + meta: RawNodeMeta + ): Either[NEList[BaboonIssue.TyperIssue], List[CNestedScope]] = { for { depmap <- flattened.map(d => deps(pkg, d)).biSequence asMap <- depmap.toUniqueMap( @@ -312,23 +284,23 @@ object BaboonTyper { private def deps( pkg: Pkg, - defn: ScopedDefn + defn: CNestedScope ): Either[NEList[BaboonIssue.TyperIssue], - (TypeId.User, (Set[TypeId.User], ScopedDefn))] = { + (TypeId.User, (Set[TypeId.User], CNestedScope))] = { for { - rawDefn <- Right(defn.thisScope.defn) + rawDefn <- Right(defn.scope.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, - defn.sic, + defn, pkg, rawDefn.defn.meta ) mappedDeps <- enquiries - .hardDepsOfRawDefn(defn.thisScope.defn.defn) + .hardDepsOfRawDefn(defn.scope.defn.defn) .map( v => scopeSupport - .resolveScopedRef(v, defn.sic, pkg, rawDefn.defn.meta) + .resolveScopedRef(v, defn, pkg, rawDefn.defn.meta) ) .biSequence } yield { @@ -341,15 +313,15 @@ object BaboonTyper { } } - private def flattenScopes(root: ScopeTree): List[ScopedDefn] = { - def flattenScopes(current: NestedScope[FullRawDefn]): List[ScopedDefn] = { + private def flattenScopes(root: ScopeTree): List[CNestedScope] = { + def flattenScopes(current: NestedScope[FullRawDefn]): List[CNestedScope] = { current match { case s: SubScope[FullRawDefn] => - List(ScopedDefn(s, root)) ++ s.nested.toMap.values + List(CNestedScope(s, root)) ++ s.nested.toMap.values .flatMap(n => flattenScopes(n)) .toList case l: LeafScope[FullRawDefn] => - List(ScopedDefn(l, root)) + List(CNestedScope(l, root)) } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala index e959fc4..c097dfd 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -2,7 +2,6 @@ package io.septimalmind.baboon.typer import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.parser.model.issues.BaboonIssue -import io.septimalmind.baboon.typer.BaboonTyper.FullRawDefn import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.{NestedScope, *} import izumi.functional.IzEither.* @@ -11,11 +10,6 @@ import izumi.fundamentals.collections.nonempty.{NEList, NEMap} import java.util -case class ScopeTree( - root: RootScope[FullRawDefn], - parents: scala.collection.Map[NestedScope[FullRawDefn], Scope[FullRawDefn]] -) - class ScopeBuilder() { def buildScopes( pkg: Pkg, diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 103590f..89bf4f3 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -2,7 +2,6 @@ package io.septimalmind.baboon.typer import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.parser.model.issues.BaboonIssue -import io.septimalmind.baboon.typer.BaboonTyper.{FullRawDefn, ScopeInContext} import io.septimalmind.baboon.typer.model.* import io.septimalmind.baboon.typer.model.Scope.{ LeafScope, @@ -58,7 +57,7 @@ object ScopeSupport { fullPath = List(found) ++ scopeOfFound.suffix resolved <- resolveUserTypeId( name.path.last, - ScopeInContext(fullPath.last, scope.tree), + CAnyScope(fullPath.last, scope.tree), pkg, meta ) @@ -142,7 +141,7 @@ object ScopeSupport { ): Either[NEList[BaboonIssue.TyperIssue], TypeId] = { for { typename <- convertTypename(name, meta) - needle = prefix.map(_.name).map(ScopeName) ++: NEList( + needle = prefix.map(_.name).map(ScopeName.apply) ++: NEList( ScopeName(name.name) ) found = findScope(needle, scope) @@ -150,7 +149,7 @@ object ScopeSupport { case Some(value) => for { owner <- pathToOwner( - asPath(ScopeInContext(value, scope.tree)), + asPath(CAnyScope(value, scope.tree)), pkg ) } yield { @@ -280,7 +279,7 @@ object ScopeSupport { NEList.from(needles.tail) match { case Some(value) => headScope.flatMap( - nested => findScope(value, ScopeInContext(nested, scope.tree)) + nested => findScope(value, CAnyScope(nested, scope.tree)) ) case None => headScope diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala new file mode 100644 index 0000000..2117dee --- /dev/null +++ b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala @@ -0,0 +1,24 @@ +package io.septimalmind.baboon.typer.model + +import io.septimalmind.baboon.parser.model.* + +case class FullRawDefn(defn: RawDefn, gcRoot: Boolean) + +object FullRawDefn { + implicit class DebugExt(defn: FullRawDefn) { + def debugRepr: String = { + val n = defn.defn.name.name + val name = defn.defn match { + case _: RawDto => s"dto" + case _: RawContract => s"contract" + case _: RawEnum => s"contract" + case _: RawAdt => s"adt" + case _: RawForeign => s"foreign" + case _: RawNamespace => s"namespace" + } + + val root = if (defn.gcRoot) { "!" } else { "" } + s"$root$name $n" + } + } +} diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala new file mode 100644 index 0000000..dd0559e --- /dev/null +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala @@ -0,0 +1,17 @@ +package io.septimalmind.baboon.typer.model + +import io.septimalmind.baboon.typer.model.Scope.NestedScope + +trait ScopeInContext { + def tree: ScopeTree + def scope: Scope[FullRawDefn] + + def parentOf(s: NestedScope[FullRawDefn]): ScopeInContext = + CAnyScope(tree.parents(s), tree) +} + +case class CNestedScope(scope: NestedScope[FullRawDefn], tree: ScopeTree) + extends ScopeInContext + +case class CAnyScope(scope: Scope[FullRawDefn], tree: ScopeTree) + extends ScopeInContext diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala new file mode 100644 index 0000000..9523703 --- /dev/null +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala @@ -0,0 +1,9 @@ +package io.septimalmind.baboon.typer.model + +import io.septimalmind.baboon.typer.model.Scope.{NestedScope, RootScope} + +case class ScopeTree( + root: RootScope[FullRawDefn], + // the underlying map is an identity hashmap! + parents: scala.collection.Map[NestedScope[FullRawDefn], Scope[FullRawDefn]] +) From 8b09aeafcbae2f5a8694a08f9f919d253c086bca Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 17:39:29 +0100 Subject: [PATCH 11/14] wip --- .../baboon/typer/ScopeBuilder.scala | 93 ++++++++++++------- .../baboon/typer/model/Scope.scala | 68 +++++++++++++- .../baboon/typer/model/ScopeInContext.scala | 2 +- .../baboon/typer/model/ScopeTree.scala | 10 +- 4 files changed, 126 insertions(+), 47 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala index c097dfd..a4ae5a0 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -8,62 +8,74 @@ import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.{NEList, NEMap} -import java.util +import java.util.concurrent.atomic.AtomicInteger class ScopeBuilder() { + trait UIDGen { + val uidGen = new AtomicInteger(0) + + def next(): ScopeUID = { + ScopeUID(uidGen.getAndIncrement()) + } + } + def buildScopes( pkg: Pkg, members: Seq[RawTLDef], meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], ScopeTree] = { - val parents = - new util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]]() + val gen = new UIDGen {} +// val parents = +// new util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]]() for { - sub <- members.map(m => buildScope(m.value, m.root, parents)).biSequence + sub <- members.map(m => buildScope(m.value, m.root, gen)).biSequence asMap <- sub .map(s => (s.name, s)) .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) } yield { - val out = RootScope(pkg, asMap) - - asMap.foreach { - case (_, s) => - assert(!parents.containsKey(s)) - parents.put(s, out) - } - - import scala.jdk.CollectionConverters.* - val tree = parents.asScala - asMap.foreach { - case (_, s) => - assert(tree(s) == out) - } - - ScopeTree(out, tree) + val out = RootScope(gen.next(), pkg, asMap) + +// asMap.foreach { +// case (_, s) => +// assert(!parents.containsKey(s)) +// parents.put(s, out) +// } +// +// import scala.jdk.CollectionConverters.* +// val tree = parents.asScala +// asMap.foreach { +// case (_, s) => +// assert(tree(s) == out) +// } + + + + ScopeTree(out, out.identifyParents, out.index) } } - private def buildScope( - member: RawDefn, - isRoot: Boolean, - parents: util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]] + private def buildScope(member: RawDefn, + isRoot: Boolean, + //parents: util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]], + gen: UIDGen, ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { def finish(defn: RawDefn, asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { val out = SubScope( + gen.next(), ScopeName(defn.name.name), FullRawDefn(defn, isRoot), asNEMap, ) - asNEMap.foreach { - case (_, s) => - assert(!parents.containsKey(s)) - val prev = parents.put(s, out) - assert(prev == null) - } +// asNEMap.foreach { +// case (_, s) => +// assert(!parents.containsKey(s)) +// val prev = parents.put(s, out) +// assert(prev == null) +// } out } @@ -71,7 +83,7 @@ class ScopeBuilder() { case namespace: RawNamespace => for { sub <- namespace.defns - .map(m => buildScope(m.value, isRoot = m.root, parents)) + .map(m => buildScope(m.value, isRoot = m.root, gen)) .biSequence asMap <- sub .map(s => (s.name, s)) @@ -89,7 +101,7 @@ class ScopeBuilder() { for { sub <- adt.members .collect { case d: RawAdtMember => d } - .map(m => buildScope(m.defn, isRoot = false, parents)) + .map(m => buildScope(m.defn, isRoot = false, gen)) .biSequence asMap <- sub .map(s => (s.name, s)) @@ -104,21 +116,32 @@ class ScopeBuilder() { } case dto: RawDto => - Right(LeafScope(ScopeName(dto.name.name), FullRawDefn(dto, isRoot))) + Right( + LeafScope( + gen.next(), + ScopeName(dto.name.name), + FullRawDefn(dto, isRoot) + ) + ) case contract: RawContract => Right( LeafScope( + gen.next(), ScopeName(contract.name.name), FullRawDefn(contract, isRoot) ) ) case e: RawEnum => - Right(LeafScope(ScopeName(e.name.name), FullRawDefn(e, isRoot))) + Right( + LeafScope(gen.next(), ScopeName(e.name.name), FullRawDefn(e, isRoot)) + ) case f: RawForeign => - Right(LeafScope(ScopeName(f.name.name), FullRawDefn(f, isRoot))) + Right( + LeafScope(gen.next(), ScopeName(f.name.name), FullRawDefn(f, isRoot)) + ) } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index 0aa9dfb..7f4fa1c 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -1,26 +1,45 @@ package io.septimalmind.baboon.typer.model +import io.septimalmind.baboon.typer.model.Scope.ScopeUID import izumi.fundamentals.collections.nonempty.NEMap -sealed trait Scope[Def] +sealed trait Scope[Def] { + def id: ScopeUID +} object Scope { + case class ScopeUID(id: Int) extends AnyVal + case class ScopeName(name: String) extends AnyVal - case class RootScope[Def](pkg: Pkg, nested: Map[ScopeName, NestedScope[Def]]) - extends Scope[Def] + case class RootScope[Def](id: ScopeUID, + pkg: Pkg, + nested: Map[ScopeName, NestedScope[Def]]) + extends Scope[Def] { + + def identifyParents: Map[ScopeUID, ScopeUID] = { + Scope.identifyParents(this) + } + + def index: Map[ScopeUID, Scope[Def]] = { + Scope.index(this) + } + + } sealed trait NestedScope[Def] extends Scope[Def] { def name: ScopeName def defn: Def } - case class SubScope[Def](name: ScopeName, + case class SubScope[Def](id: ScopeUID, + name: ScopeName, defn: Def, nested: NEMap[ScopeName, NestedScope[Def]]) extends NestedScope[Def] - case class LeafScope[Def](name: ScopeName, defn: Def) extends NestedScope[Def] + case class LeafScope[Def](id: ScopeUID, name: ScopeName, defn: Def) + extends NestedScope[Def] implicit class DebugExt[Def](scope: Scope[Def]) { def debugRepr(defnRepr: Def => String): String = { @@ -35,4 +54,43 @@ object Scope { } } } + + private def identifyParents(root: RootScope[?]): Map[ScopeUID, ScopeUID] = { + def identifySubParents( + scope: NestedScope[?], + currentParent: ScopeUID + ): List[(ScopeUID, ScopeUID)] = { + scope match { + case s: SubScope[_] => + List((s.id, currentParent)) ++ s.nested.toIterable + .flatMap(n => identifySubParents(n._2, s.id)) + case s: LeafScope[_] => + List((s.id, currentParent)) + } + } + val list = root.nested.toList + .flatMap(n => identifySubParents(n._2, root.id)) + + assert(list.map(_._1).toSet.size == list.size) + list.toMap + } + + private def index[Def](root: RootScope[Def]): Map[ScopeUID, Scope[Def]] = { + def identifySubParents( + scope: NestedScope[Def] + ): List[(ScopeUID, Scope[Def])] = { + scope match { + case s: SubScope[_] => + List((s.id, s: Scope[Def])) ++ s.nested.toIterable + .flatMap(n => identifySubParents(n._2)) + case s: LeafScope[_] => + List((s.id, s)) + } + } + val list = List((root.id, root)) ++ root.nested.toList + .flatMap(n => identifySubParents(n._2)) + + assert(list.map(_._1).toSet.size == list.size) + list.toMap + } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala index dd0559e..71e4baa 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala @@ -7,7 +7,7 @@ trait ScopeInContext { def scope: Scope[FullRawDefn] def parentOf(s: NestedScope[FullRawDefn]): ScopeInContext = - CAnyScope(tree.parents(s), tree) + CAnyScope(tree.index(tree.parents(s.id)), tree) } case class CNestedScope(scope: NestedScope[FullRawDefn], tree: ScopeTree) diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala index 9523703..a18d733 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala @@ -1,9 +1,7 @@ package io.septimalmind.baboon.typer.model -import io.septimalmind.baboon.typer.model.Scope.{NestedScope, RootScope} +import io.septimalmind.baboon.typer.model.Scope.{RootScope, ScopeUID} -case class ScopeTree( - root: RootScope[FullRawDefn], - // the underlying map is an identity hashmap! - parents: scala.collection.Map[NestedScope[FullRawDefn], Scope[FullRawDefn]] -) +case class ScopeTree(root: RootScope[FullRawDefn], + parents: Map[ScopeUID, ScopeUID], + index: Map[ScopeUID, Scope[FullRawDefn]]) From 86fc220a368180104dd6c45cccdb32bbf8c05542 Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 17:59:40 +0100 Subject: [PATCH 12/14] wip: immutability --- .../parser/model/issues/BaboonIssue.scala | 13 +++--- .../baboon/typer/BaboonTranslator.scala | 2 +- .../baboon/typer/BaboonTyper.scala | 24 +++++----- .../baboon/typer/ScopeBuilder.scala | 32 +++---------- .../baboon/typer/ScopeSupport.scala | 45 +++++++++---------- .../baboon/typer/model/FullRawDefn.scala | 9 ++++ .../baboon/typer/model/Scope.scala | 41 +++++++++++++---- .../baboon/typer/model/ScopeInContext.scala | 16 ++++--- .../baboon/typer/model/ScopeTree.scala | 14 +++--- 9 files changed, 104 insertions(+), 92 deletions(-) diff --git a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala index 62e0be9..ca31923 100644 --- a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala +++ b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala @@ -62,7 +62,7 @@ object BaboonIssue { case class UnexpectedNonBuiltin(name: TypeName, pkg: Pkg, - path: Scope[FullRawDefn], + path: Scope[ExtendedRawDefn], meta: RawNodeMeta) extends TyperIssue @@ -111,7 +111,8 @@ object BaboonIssue { meta: RawNodeMeta ) extends TyperIssue - case class UnexpectedScoping(e: List[Scope[FullRawDefn]], meta: RawNodeMeta) + case class UnexpectedScoping(e: List[Scope[ExtendedRawDefn]], + meta: RawNodeMeta) extends TyperIssue with BaboonBug @@ -126,8 +127,8 @@ object BaboonIssue { case class BadTypeName(name: String, meta: RawNodeMeta) extends TyperIssue case class BadInheritance( - bad: Map[TypeId.User, List[(Set[TypeId.User], CNestedScope)]], - meta: RawNodeMeta + bad: Map[TypeId.User, List[(Set[TypeId.User], CNestedScope)]], + meta: RawNodeMeta ) extends TyperIssue with BaboonBug @@ -138,11 +139,11 @@ object BaboonIssue { case class NameNotFound(pkg: Pkg, name: ScopedRef, meta: RawNodeMeta) extends TyperIssue - case class UnexpectedScopeLookup(b: Scope[FullRawDefn], meta: RawNodeMeta) + case class UnexpectedScopeLookup(b: Scope[ExtendedRawDefn], meta: RawNodeMeta) extends TyperIssue case class NamSeqeNotFound(names: Seq[RawTypeName], - scope: Scope.SubScope[FullRawDefn], + scope: Scope.SubScope[ExtendedRawDefn], meta: RawNodeMeta) extends TyperIssue diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index 59c36e0..db9f49c 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -33,7 +33,7 @@ class BaboonTranslator(pkg: Pkg, } private def convertMember(id: TypeId.User, - defn: FullRawDefn, + defn: ExtendedRawDefn, thisScope: ScopeInContext, ): Either[NEList[BaboonIssue.TyperIssue], List[DomainMember.User]] = { val root = defn.gcRoot diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index c47638e..a30b06e 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -261,9 +261,9 @@ object BaboonTyper { } private def order( - pkg: Pkg, - flattened: List[CNestedScope], - meta: RawNodeMeta + pkg: Pkg, + flattened: List[CNestedScope], + meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], List[CNestedScope]] = { for { depmap <- flattened.map(d => deps(pkg, d)).biSequence @@ -313,19 +313,23 @@ object BaboonTyper { } } - private def flattenScopes(root: ScopeTree): List[CNestedScope] = { - def flattenScopes(current: NestedScope[FullRawDefn]): List[CNestedScope] = { + private def flattenScopes( + root: RootScope[ExtendedRawDefn] + ): List[CNestedScope] = { + def flattenScopes( + current: NestedScope[ExtendedRawDefn] + ): List[CNestedScope] = { current match { - case s: SubScope[FullRawDefn] => - List(CNestedScope(s, root)) ++ s.nested.toMap.values + case s: SubScope[ExtendedRawDefn] => + List(CNestedScope(s)) ++ s.nested.toMap.values .flatMap(n => flattenScopes(n)) .toList - case l: LeafScope[FullRawDefn] => - List(CNestedScope(l, root)) + case l: LeafScope[ExtendedRawDefn] => + List(CNestedScope(l)) } } - root.root.nested.values + root.nested.values .flatMap(defn => flattenScopes(defn)) .toList } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala index a4ae5a0..aec58d9 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeBuilder.scala @@ -23,11 +23,9 @@ class ScopeBuilder() { pkg: Pkg, members: Seq[RawTLDef], meta: RawNodeMeta - ): Either[NEList[BaboonIssue.TyperIssue], ScopeTree] = { + ): Either[NEList[BaboonIssue.TyperIssue], RootScope[ExtendedRawDefn]] = { val gen = new UIDGen {} -// val parents = -// new util.IdentityHashMap[NestedScope[FullRawDefn], Scope[FullRawDefn]]() for { sub <- members.map(m => buildScope(m.value, m.root, gen)).biSequence @@ -36,23 +34,10 @@ class ScopeBuilder() { .toUniqueMap(nus => NEList(BaboonIssue.NonUniqueScope(nus, meta))) } yield { val out = RootScope(gen.next(), pkg, asMap) + val parents = out.identifyParents + val index = out.index -// asMap.foreach { -// case (_, s) => -// assert(!parents.containsKey(s)) -// parents.put(s, out) -// } -// -// import scala.jdk.CollectionConverters.* -// val tree = parents.asScala -// asMap.foreach { -// case (_, s) => -// assert(tree(s) == out) -// } - - - - ScopeTree(out, out.identifyParents, out.index) + out.map(defn => ExtendedRawDefn(defn, ScopeContext(parents, index))) } } @@ -64,19 +49,12 @@ class ScopeBuilder() { ): Either[NEList[BaboonIssue.TyperIssue], NestedScope[FullRawDefn]] = { def finish(defn: RawDefn, asNEMap: NEMap[ScopeName, NestedScope[FullRawDefn]]) = { - val out = SubScope( + SubScope( gen.next(), ScopeName(defn.name.name), FullRawDefn(defn, isRoot), asNEMap, ) -// asNEMap.foreach { -// case (_, s) => -// assert(!parents.containsKey(s)) -// val prev = parents.put(s, out) -// assert(prev == null) -// } - out } member match { diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 89bf4f3..049c32f 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -39,8 +39,8 @@ trait ScopeSupport { } object ScopeSupport { - case class LookupResult(suffix: List[Scope[FullRawDefn]], - scope: LeafScope[FullRawDefn]) + case class LookupResult(suffix: List[Scope[ExtendedRawDefn]], + scope: LeafScope[ExtendedRawDefn]) class ScopeSupportImpl extends ScopeSupport { def resolveScopedRef( @@ -57,7 +57,7 @@ object ScopeSupport { fullPath = List(found) ++ scopeOfFound.suffix resolved <- resolveUserTypeId( name.path.last, - CAnyScope(fullPath.last, scope.tree), + CAnyScope(fullPath.last), pkg, meta ) @@ -73,14 +73,14 @@ object ScopeSupport { @tailrec private def lookupName( names: Seq[RawTypeName], - in: Scope[FullRawDefn], - suffix: List[Scope[FullRawDefn]], + in: Scope[ExtendedRawDefn], + suffix: List[Scope[ExtendedRawDefn]], meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], LookupResult] = { names.headOption match { case Some(value) => in match { - case s: SubScope[FullRawDefn] => + case s: SubScope[ExtendedRawDefn] => s.nested.toMap.get(ScopeName(value.name)) match { case Some(value) => lookupName(names.tail, value, suffix :+ value, meta) @@ -92,7 +92,7 @@ object ScopeSupport { } case None => in match { - case s: LeafScope[FullRawDefn] => + case s: LeafScope[ExtendedRawDefn] => Right(LookupResult(suffix, s)) case b => Left(NEList(BaboonIssue.UnexpectedScopeLookup(b, meta))) @@ -148,10 +148,7 @@ object ScopeSupport { result <- found match { case Some(value) => for { - owner <- pathToOwner( - asPath(CAnyScope(value, scope.tree)), - pkg - ) + owner <- pathToOwner(asPath(CAnyScope(value)), pkg) } yield { val out = TypeId.User(pkg, owner, typename) out @@ -169,7 +166,7 @@ object ScopeSupport { } } - private def pathToOwner(defnPath: List[Scope[FullRawDefn]], + private def pathToOwner(defnPath: List[Scope[ExtendedRawDefn]], pkg: Pkg, ): Either[NEList[BaboonIssue.TyperIssue], Owner] = { @@ -181,7 +178,7 @@ object ScopeSupport { Right(Owner.Ns(ns)) } out <- defnPath.lastOption match { - case Some(value: SubScope[FullRawDefn]) => + case Some(value: SubScope[ExtendedRawDefn]) => value.defn.defn match { case a: RawAdt => for { @@ -207,7 +204,7 @@ object ScopeSupport { } private def namespaceOf( - path: List[Scope[FullRawDefn]], + path: List[Scope[ExtendedRawDefn]], ): Either[NEList[BaboonIssue.TyperIssue], List[TypeName]] = { path match { case head :: tail => @@ -240,12 +237,12 @@ object ScopeSupport { } } - private def asPath(scope: ScopeInContext): List[Scope[FullRawDefn]] = { + private def asPath(scope: ScopeInContext): List[Scope[ExtendedRawDefn]] = { - def go(s: Scope[FullRawDefn]): NEList[Scope[FullRawDefn]] = { + def go(s: Scope[ExtendedRawDefn]): NEList[Scope[ExtendedRawDefn]] = { s match { - case r: RootScope[FullRawDefn] => NEList(r) - case n: NestedScope[FullRawDefn] => + case r: RootScope[ExtendedRawDefn] => NEList(r) + case n: NestedScope[ExtendedRawDefn] => go(scope.parentOf(n).scope) ++ NEList(n) } @@ -256,20 +253,20 @@ object ScopeSupport { private def findScope(needles: NEList[ScopeName], scope: ScopeInContext, - ): Option[NestedScope[FullRawDefn]] = { + ): Option[NestedScope[ExtendedRawDefn]] = { val head = needles.head val headScope = scope.scope match { - case s: RootScope[FullRawDefn] => + case s: RootScope[ExtendedRawDefn] => s.nested.get(head) - case s: LeafScope[FullRawDefn] => + case s: LeafScope[ExtendedRawDefn] => Some(s) .filter(_.name == head) .orElse(findScope(needles, scope.parentOf(s))) - case s: SubScope[FullRawDefn] => + case s: SubScope[ExtendedRawDefn] => s.nested.toMap .get(head) .orElse(Some(s).filter(_.name == head)) @@ -278,9 +275,7 @@ object ScopeSupport { NEList.from(needles.tail) match { case Some(value) => - headScope.flatMap( - nested => findScope(value, CAnyScope(nested, scope.tree)) - ) + headScope.flatMap(nested => findScope(value, CAnyScope(nested))) case None => headScope } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala index 2117dee..e042421 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala @@ -1,6 +1,7 @@ package io.septimalmind.baboon.typer.model import io.septimalmind.baboon.parser.model.* +import io.septimalmind.baboon.typer.model.Scope.ScopeUID case class FullRawDefn(defn: RawDefn, gcRoot: Boolean) @@ -22,3 +23,11 @@ object FullRawDefn { } } } + +case class ScopeContext(parents: Map[ScopeUID, ScopeUID], + index: Map[ScopeUID, Scope[FullRawDefn]]) + +case class ExtendedRawDefn(origin: FullRawDefn, context: ScopeContext) { + def defn: RawDefn = origin.defn + def gcRoot: Boolean = origin.gcRoot +} diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index 7f4fa1c..7aec08c 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -5,6 +5,8 @@ import izumi.fundamentals.collections.nonempty.NEMap sealed trait Scope[Def] { def id: ScopeUID + + def map[Def2](defnMap: Def => Def2): Scope[Def2] } object Scope { @@ -17,12 +19,12 @@ object Scope { nested: Map[ScopeName, NestedScope[Def]]) extends Scope[Def] { - def identifyParents: Map[ScopeUID, ScopeUID] = { - Scope.identifyParents(this) - } - - def index: Map[ScopeUID, Scope[Def]] = { - Scope.index(this) + def map[Def2](defnMap: Def => Def2): RootScope[Def2] = { + copy( + nested = nested.view + .mapValues(_.map(defnMap).asInstanceOf[NestedScope[Def2]]) + .toMap + ) } } @@ -36,12 +38,33 @@ object Scope { name: ScopeName, defn: Def, nested: NEMap[ScopeName, NestedScope[Def]]) - extends NestedScope[Def] + extends NestedScope[Def] { + def map[Def2](defnMap: Def => Def2): SubScope[Def2] = { + copy(defn = defnMap(defn), nested = nested.map { + case (n, v) => (n, v.map(defnMap).asInstanceOf[NestedScope[Def2]]) + }) + } + + } case class LeafScope[Def](id: ScopeUID, name: ScopeName, defn: Def) - extends NestedScope[Def] + extends NestedScope[Def] { + def map[Def2](defnMap: Def => Def2): LeafScope[Def2] = { + copy(defn = defnMap(defn)) + } + } + + implicit class RootScopeExt[Def](scope: RootScope[Def]) { + def identifyParents: Map[ScopeUID, ScopeUID] = { + Scope.identifyParents(scope) + } + + def index: Map[ScopeUID, Scope[Def]] = { + Scope.index(scope) + } + } - implicit class DebugExt[Def](scope: Scope[Def]) { + implicit class ScopeExt[Def](scope: Scope[Def]) { def debugRepr(defnRepr: Def => String): String = { import izumi.fundamentals.platform.strings.IzString.* scope match { diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala index 71e4baa..8b612c9 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala @@ -3,15 +3,17 @@ package io.septimalmind.baboon.typer.model import io.septimalmind.baboon.typer.model.Scope.NestedScope trait ScopeInContext { - def tree: ScopeTree - def scope: Scope[FullRawDefn] + def scope: Scope[ExtendedRawDefn] - def parentOf(s: NestedScope[FullRawDefn]): ScopeInContext = - CAnyScope(tree.index(tree.parents(s.id)), tree) + def parentOf(s: NestedScope[ExtendedRawDefn]): ScopeInContext = + CAnyScope( + s.defn.context + .index(s.defn.context.parents(s.id)) + .map(d => ExtendedRawDefn(d, s.defn.context)) + ) } -case class CNestedScope(scope: NestedScope[FullRawDefn], tree: ScopeTree) +case class CNestedScope(scope: NestedScope[ExtendedRawDefn]) extends ScopeInContext -case class CAnyScope(scope: Scope[FullRawDefn], tree: ScopeTree) - extends ScopeInContext +case class CAnyScope(scope: Scope[ExtendedRawDefn]) extends ScopeInContext diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala index a18d733..030cc68 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala @@ -1,7 +1,7 @@ -package io.septimalmind.baboon.typer.model - -import io.septimalmind.baboon.typer.model.Scope.{RootScope, ScopeUID} - -case class ScopeTree(root: RootScope[FullRawDefn], - parents: Map[ScopeUID, ScopeUID], - index: Map[ScopeUID, Scope[FullRawDefn]]) +//package io.septimalmind.baboon.typer.model +// +//import io.septimalmind.baboon.typer.model.Scope.{RootScope, ScopeUID} +// +//case class ScopeTree(root: RootScope[FullRawDefn], +// parents: Map[ScopeUID, ScopeUID], +// index: Map[ScopeUID, Scope[FullRawDefn]]) From e4f05242a3011cf19b3eef7bd9639d5bae243bff Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 18:06:37 +0100 Subject: [PATCH 13/14] wip: immutability --- .../septimalmind/baboon/typer/ScopeSupport.scala | 16 ++++++++-------- .../baboon/typer/model/FullRawDefn.scala | 7 ++++++- .../baboon/typer/model/ScopeTree.scala | 7 ------- 3 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 049c32f..9716b45 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -49,7 +49,7 @@ object ScopeSupport { pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { - val found = findScope(NEList(ScopeName(name.path.head.name)), scope) + val found = findScope(NEList(ScopeName(name.path.head.name)), scope.scope) found match { case Some(found) => for { @@ -144,7 +144,7 @@ object ScopeSupport { needle = prefix.map(_.name).map(ScopeName.apply) ++: NEList( ScopeName(name.name) ) - found = findScope(needle, scope) + found = findScope(needle, scope.scope) result <- found match { case Some(value) => for { @@ -243,7 +243,7 @@ object ScopeSupport { s match { case r: RootScope[ExtendedRawDefn] => NEList(r) case n: NestedScope[ExtendedRawDefn] => - go(scope.parentOf(n).scope) ++ NEList(n) + go(n.defn.parentOf(n)) ++ NEList(n) } } @@ -252,30 +252,30 @@ object ScopeSupport { } private def findScope(needles: NEList[ScopeName], - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], ): Option[NestedScope[ExtendedRawDefn]] = { val head = needles.head - val headScope = scope.scope match { + val headScope = scope match { case s: RootScope[ExtendedRawDefn] => s.nested.get(head) case s: LeafScope[ExtendedRawDefn] => Some(s) .filter(_.name == head) - .orElse(findScope(needles, scope.parentOf(s))) + .orElse(findScope(needles, s.defn.parentOf(s))) case s: SubScope[ExtendedRawDefn] => s.nested.toMap .get(head) .orElse(Some(s).filter(_.name == head)) - .orElse(findScope(needles, scope.parentOf(s))) + .orElse(findScope(needles, s.defn.parentOf(s))) } NEList.from(needles.tail) match { case Some(value) => - headScope.flatMap(nested => findScope(value, CAnyScope(nested))) + headScope.flatMap(nested => findScope(value, nested)) case None => headScope } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala index e042421..9860b65 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/FullRawDefn.scala @@ -1,7 +1,7 @@ package io.septimalmind.baboon.typer.model import io.septimalmind.baboon.parser.model.* -import io.septimalmind.baboon.typer.model.Scope.ScopeUID +import io.septimalmind.baboon.typer.model.Scope.{NestedScope, ScopeUID} case class FullRawDefn(defn: RawDefn, gcRoot: Boolean) @@ -30,4 +30,9 @@ case class ScopeContext(parents: Map[ScopeUID, ScopeUID], case class ExtendedRawDefn(origin: FullRawDefn, context: ScopeContext) { def defn: RawDefn = origin.defn def gcRoot: Boolean = origin.gcRoot + + def parentOf(s: NestedScope[ExtendedRawDefn]): Scope[ExtendedRawDefn] = + s.defn.context + .index(s.defn.context.parents(s.id)) + .map(d => ExtendedRawDefn(d, s.defn.context)) } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala deleted file mode 100644 index 030cc68..0000000 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeTree.scala +++ /dev/null @@ -1,7 +0,0 @@ -//package io.septimalmind.baboon.typer.model -// -//import io.septimalmind.baboon.typer.model.Scope.{RootScope, ScopeUID} -// -//case class ScopeTree(root: RootScope[FullRawDefn], -// parents: Map[ScopeUID, ScopeUID], -// index: Map[ScopeUID, Scope[FullRawDefn]]) From bd48a4d48eb6ccd553af206e55dca04baab51d4b Mon Sep 17 00:00:00 2001 From: Pavel Shirshov Date: Wed, 18 Sep 2024 18:14:16 +0100 Subject: [PATCH 14/14] wip: immutability --- .../io/septimalmind/baboon/BaboonModule.scala | 7 +- .../parser/model/RawAdtMemberContract.scala | 2 - .../parser/model/issues/BaboonIssue.scala | 2 +- .../baboon/typer/BaboonTranslator.scala | 14 ++- .../baboon/typer/BaboonTyper.scala | 27 +++--- .../baboon/typer/ScopeSupport.scala | 28 +++--- .../baboon/typer/model/Scope.scala | 91 ++++++++++--------- .../baboon/typer/model/ScopeInContext.scala | 19 ---- 8 files changed, 89 insertions(+), 101 deletions(-) delete mode 100644 src/main/scala/io/septimalmind/baboon/parser/model/RawAdtMemberContract.scala delete mode 100644 src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala diff --git a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala index d3e0be5..b943de5 100644 --- a/src/main/scala/io/septimalmind/baboon/BaboonModule.scala +++ b/src/main/scala/io/septimalmind/baboon/BaboonModule.scala @@ -8,6 +8,7 @@ import io.septimalmind.baboon.translator.csharp.* import io.septimalmind.baboon.translator.csharp.CSValue.CSPackageId import io.septimalmind.baboon.typer.* import io.septimalmind.baboon.typer.model.* +import io.septimalmind.baboon.typer.model.Scope.NestedScope import io.septimalmind.baboon.util.BLogger import io.septimalmind.baboon.validator.BaboonValidator @@ -43,7 +44,11 @@ class BaboonModule(options: CompilerOptions, makeSubcontext[BaboonTranslator] .localDependencies( - List(DIKey[Pkg], DIKey[CNestedScope], DIKey[Map[TypeId, DomainMember]]) + List( + DIKey[Pkg], + DIKey[NestedScope[ExtendedRawDefn]], + DIKey[Map[TypeId, DomainMember]] + ) ) .withSubmodule(new ModuleDef { make[BaboonTranslator] diff --git a/src/main/scala/io/septimalmind/baboon/parser/model/RawAdtMemberContract.scala b/src/main/scala/io/septimalmind/baboon/parser/model/RawAdtMemberContract.scala deleted file mode 100644 index 32cf37a..0000000 --- a/src/main/scala/io/septimalmind/baboon/parser/model/RawAdtMemberContract.scala +++ /dev/null @@ -1,2 +0,0 @@ -package io.septimalmind.baboon.parser.model - diff --git a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala index ca31923..56fc633 100644 --- a/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala +++ b/src/main/scala/io/septimalmind/baboon/parser/model/issues/BaboonIssue.scala @@ -127,7 +127,7 @@ object BaboonIssue { case class BadTypeName(name: String, meta: RawNodeMeta) extends TyperIssue case class BadInheritance( - bad: Map[TypeId.User, List[(Set[TypeId.User], CNestedScope)]], + bad: Map[TypeId.User, List[(Set[TypeId.User], Scope[ExtendedRawDefn])]], meta: RawNodeMeta ) extends TyperIssue with BaboonBug diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala index db9f49c..d92f1d1 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTranslator.scala @@ -2,24 +2,22 @@ package io.septimalmind.baboon.typer import io.septimalmind.baboon.parser.model.* import io.septimalmind.baboon.parser.model.issues.BaboonIssue -import io.septimalmind.baboon.parser.model.issues.BaboonIssue.{ - MissingContractFields, - ScopedRefToNamespacedGeneric -} +import io.septimalmind.baboon.parser.model.issues.BaboonIssue.{MissingContractFields, ScopedRefToNamespacedGeneric} import io.septimalmind.baboon.typer.model.* +import io.septimalmind.baboon.typer.model.Scope.NestedScope import izumi.functional.IzEither.* import izumi.fundamentals.collections.IzCollections.* import izumi.fundamentals.collections.nonempty.NEList class BaboonTranslator(pkg: Pkg, - defn: CNestedScope, + defn: NestedScope[ExtendedRawDefn], defined: Map[TypeId, DomainMember], scopeSupport: ScopeSupport) { def translate() : Either[NEList[BaboonIssue.TyperIssue], List[DomainMember]] = { for { - rawDefn <- Right(defn.scope.defn) + rawDefn <- Right(defn.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, defn, @@ -34,7 +32,7 @@ class BaboonTranslator(pkg: Pkg, private def convertMember(id: TypeId.User, defn: ExtendedRawDefn, - thisScope: ScopeInContext, + thisScope: NestedScope[ExtendedRawDefn], ): Either[NEList[BaboonIssue.TyperIssue], List[DomainMember.User]] = { val root = defn.gcRoot defn.defn match { @@ -266,7 +264,7 @@ class BaboonTranslator(pkg: Pkg, private def convertAdt(id: TypeId.User, isRoot: Boolean, adt: RawAdt, - thisScope: ScopeInContext, + thisScope: NestedScope[ExtendedRawDefn], ): Either[NEList[BaboonIssue.TyperIssue], NEList[DomainMember.User]] = { for { converted <- adt.members diff --git a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala index a30b06e..1c61aa9 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/BaboonTyper.scala @@ -262,9 +262,11 @@ object BaboonTyper { private def order( pkg: Pkg, - flattened: List[CNestedScope], + flattened: List[NestedScope[ExtendedRawDefn]], meta: RawNodeMeta - ): Either[NEList[BaboonIssue.TyperIssue], List[CNestedScope]] = { + ): Either[NEList[BaboonIssue.TyperIssue], List[ + NestedScope[ExtendedRawDefn] + ]] = { for { depmap <- flattened.map(d => deps(pkg, d)).biSequence asMap <- depmap.toUniqueMap( @@ -282,13 +284,12 @@ object BaboonTyper { } } - private def deps( - pkg: Pkg, - defn: CNestedScope - ): Either[NEList[BaboonIssue.TyperIssue], - (TypeId.User, (Set[TypeId.User], CNestedScope))] = { + private def deps(pkg: Pkg, + defn: NestedScope[ExtendedRawDefn]): Either[NEList[ + BaboonIssue.TyperIssue + ], (TypeId.User, (Set[TypeId.User], NestedScope[ExtendedRawDefn]))] = { for { - rawDefn <- Right(defn.scope.defn) + rawDefn <- Right(defn.defn) id <- scopeSupport.resolveUserTypeId( rawDefn.defn.name, defn, @@ -296,7 +297,7 @@ object BaboonTyper { rawDefn.defn.meta ) mappedDeps <- enquiries - .hardDepsOfRawDefn(defn.scope.defn.defn) + .hardDepsOfRawDefn(defn.defn.defn) .map( v => scopeSupport @@ -315,17 +316,17 @@ object BaboonTyper { private def flattenScopes( root: RootScope[ExtendedRawDefn] - ): List[CNestedScope] = { + ): List[NestedScope[ExtendedRawDefn]] = { def flattenScopes( current: NestedScope[ExtendedRawDefn] - ): List[CNestedScope] = { + ): List[NestedScope[ExtendedRawDefn]] = { current match { case s: SubScope[ExtendedRawDefn] => - List(CNestedScope(s)) ++ s.nested.toMap.values + List(s) ++ s.nested.toMap.values .flatMap(n => flattenScopes(n)) .toList case l: LeafScope[ExtendedRawDefn] => - List(CNestedScope(l)) + List(l) } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala index 9716b45..784bacc 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/ScopeSupport.scala @@ -17,7 +17,7 @@ import scala.annotation.tailrec trait ScopeSupport { def resolveScopedRef( name: ScopedRef, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -25,14 +25,14 @@ trait ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] def resolveUserTypeId( name: RawTypeName, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] @@ -45,11 +45,11 @@ object ScopeSupport { class ScopeSupportImpl extends ScopeSupport { def resolveScopedRef( name: ScopedRef, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { - val found = findScope(NEList(ScopeName(name.path.head.name)), scope.scope) + val found = findScope(NEList(ScopeName(name.path.head.name)), scope) found match { case Some(found) => for { @@ -57,7 +57,7 @@ object ScopeSupport { fullPath = List(found) ++ scopeOfFound.suffix resolved <- resolveUserTypeId( name.path.last, - CAnyScope(fullPath.last), + fullPath.last, pkg, meta ) @@ -103,7 +103,7 @@ object ScopeSupport { def resolveUserTypeId( name: RawTypeName, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId.User] = { @@ -135,7 +135,7 @@ object ScopeSupport { def resolveTypeId( prefix: List[RawTypeName], name: RawTypeName, - scope: ScopeInContext, + scope: Scope[ExtendedRawDefn], pkg: Pkg, meta: RawNodeMeta ): Either[NEList[BaboonIssue.TyperIssue], TypeId] = { @@ -144,11 +144,11 @@ object ScopeSupport { needle = prefix.map(_.name).map(ScopeName.apply) ++: NEList( ScopeName(name.name) ) - found = findScope(needle, scope.scope) + found = findScope(needle, scope) result <- found match { case Some(value) => for { - owner <- pathToOwner(asPath(CAnyScope(value)), pkg) + owner <- pathToOwner(asPath(value), pkg) } yield { val out = TypeId.User(pkg, owner, typename) out @@ -157,7 +157,7 @@ object ScopeSupport { asBuiltin(typename).toRight( NEList( BaboonIssue - .UnexpectedNonBuiltin(typename, pkg, scope.scope, meta) + .UnexpectedNonBuiltin(typename, pkg, scope, meta) ) ) } @@ -237,7 +237,9 @@ object ScopeSupport { } } - private def asPath(scope: ScopeInContext): List[Scope[ExtendedRawDefn]] = { + private def asPath( + scope: Scope[ExtendedRawDefn] + ): List[Scope[ExtendedRawDefn]] = { def go(s: Scope[ExtendedRawDefn]): NEList[Scope[ExtendedRawDefn]] = { s match { @@ -247,7 +249,7 @@ object ScopeSupport { } } - go(scope.scope).toList.init + go(scope).toList.init } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala index 7aec08c..ae809dd 100644 --- a/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala +++ b/src/main/scala/io/septimalmind/baboon/typer/model/Scope.scala @@ -10,7 +10,9 @@ sealed trait Scope[Def] { } object Scope { - case class ScopeUID(id: Int) extends AnyVal + case class ScopeUID(id: Int) extends AnyVal { + override def toString: String = s"[$id]" + } case class ScopeName(name: String) extends AnyVal @@ -56,11 +58,50 @@ object Scope { implicit class RootScopeExt[Def](scope: RootScope[Def]) { def identifyParents: Map[ScopeUID, ScopeUID] = { - Scope.identifyParents(scope) + identifyParents(scope) } def index: Map[ScopeUID, Scope[Def]] = { - Scope.index(scope) + index(scope) + } + + private def identifyParents(root: RootScope[?]): Map[ScopeUID, ScopeUID] = { + def identifySubParents( + scope: NestedScope[?], + currentParent: ScopeUID + ): List[(ScopeUID, ScopeUID)] = { + scope match { + case s: SubScope[_] => + List((s.id, currentParent)) ++ s.nested.toIterable + .flatMap(n => identifySubParents(n._2, s.id)) + case s: LeafScope[_] => + List((s.id, currentParent)) + } + } + val list = root.nested.toList + .flatMap(n => identifySubParents(n._2, root.id)) + + assert(list.map(_._1).toSet.size == list.size) + list.toMap + } + + private def index[Def](root: RootScope[Def]): Map[ScopeUID, Scope[Def]] = { + def identifySubParents( + scope: NestedScope[Def] + ): List[(ScopeUID, Scope[Def])] = { + scope match { + case s: SubScope[_] => + List((s.id, s: Scope[Def])) ++ s.nested.toIterable + .flatMap(n => identifySubParents(n._2)) + case s: LeafScope[_] => + List((s.id, s)) + } + } + val list = List((root.id, root)) ++ root.nested.toList + .flatMap(n => identifySubParents(n._2)) + + assert(list.map(_._1).toSet.size == list.size) + list.toMap } } @@ -69,51 +110,13 @@ object Scope { import izumi.fundamentals.platform.strings.IzString.* scope match { case s: RootScope[Def] => - s"${s.pkg.toString}${s.nested.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" + s"${s.id}: ${s.pkg.toString}${s.nested.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" case s: SubScope[Def] => - s"${s.name.name} <- ${defnRepr(s.defn)} ${s.nested.toMap.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" + s"${s.id}: ${s.name.name} <- ${defnRepr(s.defn)} ${s.nested.toMap.view.values.map(_.debugRepr(defnRepr)).niceList().shift(2)}" case s: LeafScope[Def] => - s"${s.name.name} := ${defnRepr(s.defn)}" - } - } - } - - private def identifyParents(root: RootScope[?]): Map[ScopeUID, ScopeUID] = { - def identifySubParents( - scope: NestedScope[?], - currentParent: ScopeUID - ): List[(ScopeUID, ScopeUID)] = { - scope match { - case s: SubScope[_] => - List((s.id, currentParent)) ++ s.nested.toIterable - .flatMap(n => identifySubParents(n._2, s.id)) - case s: LeafScope[_] => - List((s.id, currentParent)) + s"${s.id}: ${s.name.name} := ${defnRepr(s.defn)}" } } - val list = root.nested.toList - .flatMap(n => identifySubParents(n._2, root.id)) - - assert(list.map(_._1).toSet.size == list.size) - list.toMap } - private def index[Def](root: RootScope[Def]): Map[ScopeUID, Scope[Def]] = { - def identifySubParents( - scope: NestedScope[Def] - ): List[(ScopeUID, Scope[Def])] = { - scope match { - case s: SubScope[_] => - List((s.id, s: Scope[Def])) ++ s.nested.toIterable - .flatMap(n => identifySubParents(n._2)) - case s: LeafScope[_] => - List((s.id, s)) - } - } - val list = List((root.id, root)) ++ root.nested.toList - .flatMap(n => identifySubParents(n._2)) - - assert(list.map(_._1).toSet.size == list.size) - list.toMap - } } diff --git a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala b/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala deleted file mode 100644 index 8b612c9..0000000 --- a/src/main/scala/io/septimalmind/baboon/typer/model/ScopeInContext.scala +++ /dev/null @@ -1,19 +0,0 @@ -package io.septimalmind.baboon.typer.model - -import io.septimalmind.baboon.typer.model.Scope.NestedScope - -trait ScopeInContext { - def scope: Scope[ExtendedRawDefn] - - def parentOf(s: NestedScope[ExtendedRawDefn]): ScopeInContext = - CAnyScope( - s.defn.context - .index(s.defn.context.parents(s.id)) - .map(d => ExtendedRawDefn(d, s.defn.context)) - ) -} - -case class CNestedScope(scope: NestedScope[ExtendedRawDefn]) - extends ScopeInContext - -case class CAnyScope(scope: Scope[ExtendedRawDefn]) extends ScopeInContext