Skip to content

Commit

Permalink
inclusion support, closes #11
Browse files Browse the repository at this point in the history
  • Loading branch information
pshirshov committed Aug 28, 2024
1 parent 2640ba4 commit 306cdb7
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 52 deletions.
8 changes: 4 additions & 4 deletions src/main/scala/io/septimalmind/baboon/Baboon.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object Baboon {
System.exit(1)
case Right(value) =>
val opts = value._1

val inputPaths = opts.modelDir.map(s => Paths.get(s))
val rtOpt = opts.runtime match {
case Some("only") => RuntimeGenOpt.Only
case Some("without") => RuntimeGenOpt.Without
Expand All @@ -69,13 +69,13 @@ object Baboon {
!opts.omitMostRecentVersionSuffixFromPaths.getOrElse(false),
!opts.omitMostRecentVersionSuffixFromNamespaces.getOrElse(false),
)
Injector.NoCycles().produceRun(new BaboonModule(options)) {
Injector.NoCycles().produceRun(new BaboonModule(options, inputPaths)) {
(compiler: BaboonCompiler) =>
val inputModels = opts.model
.map(s => Paths.get(s))
.toSet ++ opts.modelDir.flatMap { dir =>
.toSet ++ inputPaths.flatMap { dir =>
IzFiles
.walk(Paths.get(dir).toFile)
.walk(dir.toFile)
.filter(_.toFile.getName.endsWith(".baboon"))
}
val outDir = Paths.get(opts.output)
Expand Down
7 changes: 6 additions & 1 deletion src/main/scala/io/septimalmind/baboon/BaboonModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import io.septimalmind.baboon.util.BLogger
import io.septimalmind.baboon.validator.BaboonValidator
import izumi.fundamentals.collections.nonempty.NEList

class BaboonModule(options: CompilerOptions) extends ModuleDef {
import java.nio.file.Path

class BaboonModule(options: CompilerOptions, inputs: Seq[Path])
extends ModuleDef {
make[BaboonCompiler].from[BaboonCompiler.BaboonCompilerImpl]
make[BaboonLoader].from[BaboonLoader.BaboonLoaderImpl]
make[CompilerOptions].fromValue(options)
Expand All @@ -35,6 +38,8 @@ class BaboonModule(options: CompilerOptions) extends ModuleDef {
make[ScopeSupport].from[ScopeSupport.ScopeSupportImpl]
make[CSCodecTestsTranslator].from[CSCodecTestsTranslator.Impl]

make[Seq[Path]].named("inputs").fromValue(inputs)

makeSubcontext[BaboonTranslator]
.localDependencies(
List(
Expand Down
71 changes: 63 additions & 8 deletions src/main/scala/io/septimalmind/baboon/parser/BaboonParser.scala
Original file line number Diff line number Diff line change
@@ -1,31 +1,86 @@
package io.septimalmind.baboon.parser

import distage.Id
import fastparse.Parsed
import io.septimalmind.baboon.parser.model.issues.BaboonIssue
import io.septimalmind.baboon.parser.model.{FSPath, RawDomain}
import izumi.fundamentals.collections.nonempty.NEList
import io.septimalmind.baboon.parser.model.{
FSPath,
RawDomain,
RawInclude,
RawTLDef
}
import izumi.fundamentals.collections.nonempty.{NEList, NEString}
import izumi.functional.IzEither.*
import izumi.fundamentals.platform.files.IzFiles

import java.nio.file.Path

trait BaboonParser {
def parse(
input: BaboonParser.Input
): Either[NEList[BaboonIssue.ParserIssue], RawDomain]
def parse(input: BaboonParser.Input): Either[NEList[BaboonIssue], RawDomain]
}

object BaboonParser {
case class Input(path: FSPath, content: String)

class BaboonParserImpl() extends BaboonParser {
class BaboonParserImpl(inputs: Seq[Path] @Id("inputs")) extends BaboonParser {
def parse(
input: BaboonParser.Input
): Either[NEList[BaboonIssue.ParserIssue], RawDomain] = {
): Either[NEList[BaboonIssue], RawDomain] = {
val context = ParserContext(input.path, input.content)

fastparse.parse(context.content, context.defModel.model(_)) match {
case Parsed.Success(value, _) =>
Right(value)
for {
included <- processIncludes(value.members.includes)
} yield {
value.copy(
members = value.members.copy(
includes = Seq.empty,
defs = included ++ value.members.defs
)
)
}

case failure: Parsed.Failure =>
Left(NEList(BaboonIssue.ParserFailed(failure)))
}
}

def processIncludes(
includes: Seq[RawInclude]
): Either[NEList[BaboonIssue], Seq[RawTLDef]] = {
if (includes.nonEmpty) {
includes.map { inc =>
val inclusion = inputs
.map(_.resolve(inc.value).toFile)
.find(f => f.exists() && f.isFile)
inclusion match {
case Some(incFile) =>
val content = IzFiles.readString(incFile)
val context = ParserContext(
FSPath.parse(NEString.unsafeFrom(incFile.getCanonicalPath)),
content
)
fastparse.parse(context.content, context.defModel.content(_)) match {
case Parsed.Success(value, _) =>
for {
sub <- processIncludes(value.includes)
} yield {
sub ++ value.defs
}
case failure: Parsed.Failure =>
Left(NEList(BaboonIssue.ParserFailed(failure)))

}

case None =>
Left(NEList(BaboonIssue.IncludeNotFound(inc.value)))
}
}.biFlatten
} else {
Right(Seq.empty)
}
}
}

}
36 changes: 23 additions & 13 deletions src/main/scala/io/septimalmind/baboon/parser/defns/DefModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ class DefModel(context: ParserContext,
) {
context.discard()

def model[$: P]: P[RawDomain] = {
import fastparse.ScalaWhitespace.whitespace
P(Start ~ header ~ version ~ content ~ End).map {
case (decl, version, members) =>
RawDomain(decl, version, members)
}
}

def header[$: P]: P[RawHeader] =
meta.withMeta(P(kw(kw.model, idt.symbolSeq))).map(RawHeader.tupled)

Expand All @@ -23,14 +31,10 @@ class DefModel(context: ParserContext,
.withMeta(P(kw(kw.version, Literals.Literals.SimpleStr)))
.map(RawVersion.tupled)

def choice[$: P]: P[RawTLDef.Enum] =
defEnum.enumEnclosed.map(RawTLDef.Enum(false, _))
def dto[$: P]: P[RawTLDef.DTO] =
defDto.dtoEnclosed.map(RawTLDef.DTO(false, _))
def adt[$: P]: P[RawTLDef.ADT] =
defAdt.adtEnclosed.map(RawTLDef.ADT(false, _))
def foreign[$: P]: P[RawTLDef.Foreign] =
defForeign.foreignEnclosed.map(RawTLDef.Foreign(false, _))
def include[$: P]: P[RawInclude] =
meta
.withMeta(P(kw(kw.include, Literals.Literals.SimpleStr)))
.map(RawInclude.tupled)

def member[$: P]: P[RawTLDef] = {
import fastparse.ScalaWhitespace.whitespace
Expand All @@ -40,11 +44,17 @@ class DefModel(context: ParserContext,
}
}

def model[$: P]: P[RawDomain] = {
def content[$: P]: P[RawContent] = {
import fastparse.ScalaWhitespace.whitespace
P(Start ~ header ~ version ~ member.rep() ~ End).map {
case (decl, version, members) =>
RawDomain(decl, version, members)
}
(include.rep() ~ member.rep()).map(RawContent.tupled)
}

def choice[$: P]: P[RawTLDef.Enum] =
defEnum.enumEnclosed.map(RawTLDef.Enum(false, _))
def dto[$: P]: P[RawTLDef.DTO] =
defDto.dtoEnclosed.map(RawTLDef.DTO(false, _))
def adt[$: P]: P[RawTLDef.ADT] =
defAdt.adtEnclosed.map(RawTLDef.ADT(false, _))
def foreign[$: P]: P[RawTLDef.Foreign] =
defForeign.foreignEnclosed.map(RawTLDef.Foreign(false, _))
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ trait Keywords {
def foreign[$: P]: P[Unit] = kw("foreign")
def root[$: P]: P[Unit] = kw("root")
def version[$: P]: P[Unit] = kw("version")
def include[$: P]: P[Unit] = kw("include")

def apply[T](kw: => P[Unit], defparser: => P[T])(implicit v: P[?]): P[T] = {
import fastparse.ScalaWhitespace.whitespace
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.septimalmind.baboon.parser.model



case class RawDomain(header: RawHeader,
version: RawVersion,
members: Seq[RawTLDef])
members: RawContent)
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package io.septimalmind.baboon.parser.model

case class RawVersion(meta: RawNodeMeta, value: String)

case class RawInclude(meta: RawNodeMeta, value: String)

case class RawContent(includes: Seq[RawInclude], defs: Seq[RawTLDef])
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object BaboonIssue {
sealed trait ParserIssue extends BaboonIssue

case class ParserFailed(error: Parsed.Failure) extends ParserIssue
case class IncludeNotFound(path: String) extends ParserIssue

//
sealed trait TyperIssue extends BaboonIssue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ object IssuePrinter {
s"Parser error occurred on => line:$line position:$character".stripMargin
}

implicit val includeNotFoundPrinter: IssuePrinter[IncludeNotFound] =
(issue: IncludeNotFound) => {
s"Failed to find inclusion `${issue.path}``".stripMargin
}

implicit val scalaExpectedPrinter: IssuePrinter[ScalarExpected] =
new BugPrinter[ScalarExpected] {
override def errorMessage(bug: ScalarExpected): String = {
Expand Down Expand Up @@ -652,7 +657,8 @@ object IssuePrinter {
}

implicit val parserIssuePrinter: IssuePrinter[ParserIssue] = {
case i: ParserFailed => apply[ParserFailed].stringify(i)
case i: ParserFailed => apply[ParserFailed].stringify(i)
case i: IncludeNotFound => apply[IncludeNotFound].stringify(i)
}

implicit val typerIssue: IssuePrinter[TyperIssue] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import io.septimalmind.baboon.translator.csharp.CSBaboonTranslator.{
iBaboonGenerated,
iBaboonGeneratedLatest
}
import io.septimalmind.baboon.translator.csharp.CSBaboonTranslator.{
iBaboonGenerated,
iBaboonGeneratedLatest
}
import io.septimalmind.baboon.translator.csharp.CSValue.{CSPackageId, CSType}
import io.septimalmind.baboon.typer.model.*
import io.septimalmind.baboon.typer.model.TypeId.ComparatorType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object BaboonTyper {
for {
id <- parsePkg(model.header)
version <- parseVersion(model.version)
defs <- runTyper(id, model.members, model.header.meta)
defs <- runTyper(id, model.members.defs, model.header.meta)
indexedDefs <- defs
.map(d => (d.id, d))
.toUniqueMap(e => NEList(BaboonIssue.DuplicatedTypedefs(model, e)))
Expand Down
16 changes: 16 additions & 0 deletions src/test/resources/baboon/pkg0/pkg03-inclusion.model
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
root data Maps {
f1: map[i08, str]
}

enum T1_E1 {
A
C
}

root data T1_E1_RET {
f: T1_E1
}

data T1_D2 {
f: str
}
17 changes: 1 addition & 16 deletions src/test/resources/baboon/pkg0/pkg03.baboon
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,7 @@ model testpkg.pkg0

version "3.0.0"

root data Maps {
f1: map[i08, str]
}

enum T1_E1 {
A
C
}

root data T1_E1_RET {
f: T1_E1
}

data T1_D2 {
f: str
}
include "pkg0/pkg03-inclusion.model"

root data T1_D1 {
f0: T1_D2
Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/io/septimalmind/baboon/tests/BaboonTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ abstract class BaboonTest extends Spec1[Identity] {
disregardImplicitUsings = true,
omitMostRecentVersionSuffixFromPaths = true,
omitMostRecentVersionSuffixFromNamespaces = true,
)
),
Seq.empty,
).morph[PluginBase]
)
)
Expand Down

0 comments on commit 306cdb7

Please sign in to comment.