From 1164ccf1a800ebf0ae3e22c668a1cd73af51d5b6 Mon Sep 17 00:00:00 2001 From: reidspencer Date: Wed, 26 Feb 2025 14:47:54 -0500 Subject: [PATCH 1/4] Initial Design * Create a PromptGeneration module * Implement the apply method to generate text from a node --- .../com/ossuminc/riddl/passes/Riddl.scala | 5 +- .../riddl/passes/symbols/SymbolsOutput.scala | 2 +- .../com/ossuminc/riddl/PromptGeneration.scala | 57 +++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala diff --git a/passes/shared/src/main/scala/com/ossuminc/riddl/passes/Riddl.scala b/passes/shared/src/main/scala/com/ossuminc/riddl/passes/Riddl.scala index 64f095bb4..4dcac2343 100644 --- a/passes/shared/src/main/scala/com/ossuminc/riddl/passes/Riddl.scala +++ b/passes/shared/src/main/scala/com/ossuminc/riddl/passes/Riddl.scala @@ -7,7 +7,7 @@ package com.ossuminc.riddl.passes import com.ossuminc.riddl -import com.ossuminc.riddl.language.AST.{Branch, Root, Token} +import com.ossuminc.riddl.language.AST.{Branch, PathIdentifier, Root, Token} import com.ossuminc.riddl.language.Messages.* import com.ossuminc.riddl.language.parsing.{RiddlParserInput, TopLevelParser} import com.ossuminc.riddl.passes.* @@ -101,8 +101,7 @@ object Riddl { /** Convert a previously parsed Root to Tokens and corresponding string text */ def mapTextAndToken[T]( root: Branch[?] - )(f: (IndexedSeqView[Char],Token) => T) - (using pc: PlatformContext): Either[Messages, List[T]] = + )(f: (IndexedSeqView[Char], Token) => T)(using pc: PlatformContext): Either[Messages, List[T]] = val text = toRiddlText(root) val rpi = RiddlParserInput(text, "") TopLevelParser.mapTextAndToken[T](rpi)(f) diff --git a/passes/shared/src/main/scala/com/ossuminc/riddl/passes/symbols/SymbolsOutput.scala b/passes/shared/src/main/scala/com/ossuminc/riddl/passes/symbols/SymbolsOutput.scala index f0bd425d4..a2c029d0c 100644 --- a/passes/shared/src/main/scala/com/ossuminc/riddl/passes/symbols/SymbolsOutput.scala +++ b/passes/shared/src/main/scala/com/ossuminc/riddl/passes/symbols/SymbolsOutput.scala @@ -45,7 +45,7 @@ case class SymbolsOutput( /** Get all parents of a definition * * @param definition - * The defintiion whose parents are to be sought. + * The definition whose parents are to be sought. * @return * the sequence of ParentDefOf parents or empty if none. */ diff --git a/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala new file mode 100644 index 000000000..84bf34068 --- /dev/null +++ b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala @@ -0,0 +1,57 @@ +/* + * Copyright 2019-2025 Ossum, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.ossuminc.riddl + +import com.ossuminc.riddl.language.AST.* +import com.ossuminc.riddl.language.Messages.Messages +import com.ossuminc.riddl.passes.PassesResult +import com.ossuminc.riddl.passes.symbols.{SymbolsOutput, SymbolsPass} + +case class PromptGeneration(passesResult: PassesResult) { + + extension (sb: StringBuilder) + def description(definition: Definition): StringBuilder = + sb + .append("briefly described as \"") + .append(definition.briefString) + .append("\", fully described as \"") + .append(definition.descriptionString) + sb + end extension + + def apply(definition: Definition, prompt: String): Either[Messages, String] = + val parents: Parents = passesResult.symbols.parentsOf(definition) + val stack: ParentStack = ParentStack(parents*) + val result = new StringBuilder + parents.reverse.foldLeft(result) { (sb: StringBuilder, definition: Definition) => + definition match + case d: Domain => + sb.append(s"In the knowledge Domain named ") + .append(d.id.format) + .append(", ") + .description(d) + .append(", ") + case c: Context => + sb.append(s"In the context of ") + .append(c.id.format) + .append(",") + .description(c) + .append(", ") + case e: Entity => + sb.append(s"For the entity named ") + .append(e.id.format) + .append(",") + .description(e) + .append(",") + // TODO: Write other cases + case _: Definition => () + end match + sb + } + result.append(": ").append(prompt) + Right(result.toString) +} From 10bf12191fafdd9052384f360c689c45bec2d29e Mon Sep 17 00:00:00 2001 From: reidspencer Date: Mon, 3 Mar 2025 20:48:46 -0500 Subject: [PATCH 2/4] Add PromptGeneration and simple test case * Turn --- .github/workflows/scala.yml | 2 +- .../com/ossuminc/riddl/PromptGeneration.scala | 8 ++--- .../ossuminc/riddl/PromptGenerationTest.scala | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 7440e303c..955af16c1 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -57,7 +57,7 @@ jobs: - name: Build And Test JVM Versions run: | - sbt -v clean cJVM tJVM + sbt -v clean cJVM tJVM checkMimaCompatibility - name: Build And Test Native Versions run: | diff --git a/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala index 84bf34068..40bc5caa6 100644 --- a/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala +++ b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala @@ -14,7 +14,7 @@ import com.ossuminc.riddl.passes.symbols.{SymbolsOutput, SymbolsPass} case class PromptGeneration(passesResult: PassesResult) { extension (sb: StringBuilder) - def description(definition: Definition): StringBuilder = + private def description(definition: Definition): StringBuilder = sb .append("briefly described as \"") .append(definition.briefString) @@ -34,19 +34,19 @@ case class PromptGeneration(passesResult: PassesResult) { .append(d.id.format) .append(", ") .description(d) - .append(", ") + .append(",\n") case c: Context => sb.append(s"In the context of ") .append(c.id.format) .append(",") .description(c) - .append(", ") + .append(",\n") case e: Entity => sb.append(s"For the entity named ") .append(e.id.format) .append(",") .description(e) - .append(",") + .append(",\n") // TODO: Write other cases case _: Definition => () end match diff --git a/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala b/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala new file mode 100644 index 000000000..877ce9c6f --- /dev/null +++ b/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala @@ -0,0 +1,30 @@ +/* + * Copyright 2019-2025 Ossum, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.ossuminc.riddl +import com.ossuminc.riddl.language.parsing.RiddlParserInput +import com.ossuminc.riddl.passes.validate.AbstractValidatingTest +import com.ossuminc.riddl.utils.pc +import org.scalatest.TestData + +class PromptGenerationTest extends AbstractValidatingTest: + "PromptGeneration" should { + "generate a prompt" in { (td: TestData) => + val rpi = RiddlParserInput("domain foo { ??? } ", td) + parseAndThenValidate(rpi){ (pr, root, _, _) => + val promptGen = PromptGeneration(pr) + val domain = root.domains.head + promptGen(domain, "Tell me more") match + case Left(messages) => + fail(messages.format) + case Right(prompt: String) => + info(prompt) + succeed + end match + } + } + } +end PromptGenerationTest From cf87b3eee34339311b7733b848e749186d0ed1a1 Mon Sep 17 00:00:00 2001 From: reidspencer Date: Mon, 3 Mar 2025 20:49:39 -0500 Subject: [PATCH 3/4] Add sbt aliases for Mima compatibility checks --- build.sbt | 59 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/build.sbt b/build.sbt index ef5df5b5c..87b17e8d8 100644 --- a/build.sbt +++ b/build.sbt @@ -14,13 +14,14 @@ Global / onChangedBuildSource := ReloadOnSourceChanges enablePlugins(OssumIncPlugin) -lazy val startYear: Int = 2019 +val mimaBase: String = "1.0.0" +val startYear: Int = 2019 def cpDep(cp: CrossProject): CrossClasspathDependency = cp % "compile->compile;test->test" def pDep(p: Project): ClasspathDependency = p % "compile->compile;test->test" def tkDep(cp: CrossProject): CrossClasspathDependency = cp % "compile->compile;test->test" -lazy val riddl: Project = Root("riddl", startYr = startYear, spdx ="Apache-2.0") +lazy val riddl: Project = Root("riddl", startYr = startYear, spdx = "Apache-2.0") .configure(With.noPublishing, With.git, With.dynver, With.noMiMa) .settings(concurrentRestrictions += Tags.limit(NativeTags.Link, 1)) .aggregate( @@ -59,7 +60,7 @@ lazy val utils_cp: CrossProject = CrossModule("utils", "riddl-utils")(JVM, JS, N ) .jvmConfigure(With.coverage(70)) .jvmConfigure(With.build_info) - .jvmConfigure(With.MiMa("0.57.0", Seq("com.ossuminc.riddl.utils.RiddlBuildInfo"))) + .jvmConfigure(With.MiMa(mimaBase, Seq("com.ossuminc.riddl.utils.RiddlBuildInfo"))) .jvmSettings( buildInfoPackage := "com.ossuminc.riddl.utils", buildInfoObject := "RiddlBuildInfo", @@ -109,12 +110,14 @@ lazy val utils_cp: CrossProject = CrossModule("utils", "riddl-utils")(JVM, JS, N Dep.scalactic_nojvm.value ) ) - .nativeConfigure(With.Native( - linkOptions = Seq( - "-I/usr/include", - "-I/usr/local/opt/curl/include", - "-I/opt/homebrew/opt/curl/include" - )) + .nativeConfigure( + With.Native( + linkOptions = Seq( + "-I/usr/include", + "-I/usr/local/opt/curl/include", + "-I/opt/homebrew/opt/curl/include" + ) + ) ) .nativeConfigure( With.BuildInfo.withKeys( @@ -147,7 +150,7 @@ lazy val language_cp: CrossProject = CrossModule("language", "riddl-language")(J Test / parallelExecution := false ) .jvmConfigure(With.coverage(65)) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jvmSettings( tastyMiMaConfig ~= { prevConfig => import java.util.Arrays.asList @@ -213,7 +216,7 @@ lazy val passes_cp = CrossModule("passes", "riddl-passes")(JVM, JS, Native) description := "AST Pass infrastructure and essential passes" ) .jvmConfigure(With.coverage(30)) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jvmSettings( coverageExcludedPackages := ";$anon", mimaBinaryIssueFilters ++= Seq( @@ -254,7 +257,7 @@ lazy val testkit_cp = CrossModule("testkit", "riddl-testkit")(JVM, JS, Native) Dep.scalactic_nojvm.value ) ) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jsConfigure(With.Javascript("RIDDL: language", withCommonJSModule = true)) .jsConfigure(With.noMiMa) .jsSettings( @@ -285,7 +288,7 @@ lazy val diagrams_cp: CrossProject = CrossModule("diagrams", "riddl-diagrams")(J description := "Implementation of various AST diagrams passes other libraries may use" ) .jvmConfigure(With.coverage(50)) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jvmSettings(coverageExcludedFiles := """;$anon""") .jsConfigure(With.Javascript("RIDDL: diagrams", withCommonJSModule = true)) .jsConfigure(With.noMiMa) @@ -300,14 +303,15 @@ lazy val riddlLib_cp: CrossProject = CrossModule("riddlLib", "riddl-lib")(JS, JV cpDep(utils_cp), cpDep(language_cp), cpDep(passes_cp), - cpDep(diagrams_cp) + cpDep(diagrams_cp), + cpDep(testkit_cp) ) .configure(With.typical, With.GithubPublishing) .settings( description := "Bundling of essential RIDDL libraries" ) .jvmConfigure(With.coverage(50)) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jvmConfigure( With.Packaging.universal( maintainerEmail = "reid@ossuminc.com", @@ -329,14 +333,20 @@ val riddlLibNative = riddlLib_cp.native val Commands = config("commands") lazy val commands_cp: CrossProject = CrossModule("commands", "riddl-commands")(JVM, Native) - .dependsOn(cpDep(utils_cp), cpDep(language_cp), cpDep(passes_cp), cpDep(diagrams_cp)) + .dependsOn( + cpDep(utils_cp), + cpDep(language_cp), + cpDep(passes_cp), + cpDep(diagrams_cp), + cpDep(riddlLib_cp) + ) .configure(With.typical, With.GithubPublishing) .settings( scalacOptions ++= Seq("-explain", "--explain-types", "--explain-cyclic", "--no-warnings"), description := "RIDDL Command Infrastructure and command definitions" ) .jvmConfigure(With.coverage(50)) - .jvmConfigure(With.MiMa("0.57.0")) + .jvmConfigure(With.MiMa(mimaBase)) .jvmSettings( libraryDependencies ++= Seq(Dep.scopt, Dep.sconfig, Dep.scalajs_stubs), coverageExcludedFiles := """;$anon""" @@ -415,7 +425,8 @@ lazy val docsite = DocSite( libraryDependencies ++= Dep.testing ) -lazy val plugin = OssumIncPlugin.autoImport.Plugin("sbt-riddl") +lazy val plugin = OssumIncPlugin.autoImport + .Plugin("sbt-riddl") .configure(With.scala2, With.build_info, With.noMiMa, With.GithubPublishing) .settings( description := "An sbt plugin to embellish a project with riddlc usage", @@ -465,3 +476,15 @@ addCommandAlias( "; riddlLibNative/nativeLink" + "; riddlLib/Universal/packageBin" ) +addCommandAlias( + "checkMimaCompatibility", + "; utils/mimaFindBinaryIssues ; language/mimaFindBinaryIssues ; passes/mimaFindBinaryIssues; " + + "testkit/mimaFindBinaryIssues ; diagrams/mimaFindBinaryIssues ; commands/mimaFindBinaryIssues ;" + + "riddlLib/mimaFindBinaryIssues" +) +addCommandAlias( + "checkTastyCompatibility", + "; utils/tastyMiMaReportIssues ; language/tastyMiMaReportIssues ; passes/tastyMiMaReportIssues; " + + "testkit/tastyMiMaReportIssues ; diagrams/tastyMiMaReportIssues ; " + + "commands/tastyMiMaReportIssues ; riddlLib/tastyMiMaReportIssues" +) From a3e08c5e41391c910080265ad6e318083dcf78de Mon Sep 17 00:00:00 2001 From: reidspencer Date: Wed, 5 Mar 2025 15:55:51 -0500 Subject: [PATCH 4/4] Finish PromptGeneration introduction * Remove "with" as a redability word, its a keyword * Simplify descriptions in rbbq.riddl * Add a test case to get a context from rbbq.riddl --- .../riddl/language/parsing/Readability.scala | 9 +--- .../language/parsing/StatementParser.scala | 40 ++++++++++++---- .../riddl/language/parsing/KeywordsTest.scala | 4 +- passes/input/rbbq.riddl | 13 ++--- .../validate/JVMAbstractValidatingTest.scala | 10 ++-- .../ossuminc/riddl/PromptGenerationTest.scala | 47 +++++++++++++++++++ .../com/ossuminc/riddl/PromptGeneration.scala | 6 ++- .../ossuminc/riddl/PromptGenerationTest.scala | 30 ------------ 8 files changed, 95 insertions(+), 64 deletions(-) create mode 100644 riddlLib/jvm/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala delete mode 100644 riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala diff --git a/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/Readability.scala b/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/Readability.scala index 2b456cb48..b1451fd14 100644 --- a/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/Readability.scala +++ b/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/Readability.scala @@ -42,8 +42,6 @@ trait Readability { def wants[u: P]: P[Unit] = readable("wants") - def `with`[u: P]: P[Unit] = readable("with") - def anyReadability[u: P]: P[Unit] = { P( Keywords.keywords( @@ -61,8 +59,7 @@ trait Readability { ReadabilityWords.so, ReadabilityWords.that, ReadabilityWords.to, - ReadabilityWords.wants, - ReadabilityWords.with_ + ReadabilityWords.wants ) ) ) @@ -84,7 +81,6 @@ object ReadabilityWords { final val that = "that" final val to = "to" final val wants = "wants" - final val with_ = "with" // NOTE: Keep this list in synch with the list in TokenParser def allReadability: Seq[String] = Seq( @@ -101,7 +97,6 @@ object ReadabilityWords { so, that, to, - wants, - with_ + wants ) } diff --git a/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/StatementParser.scala b/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/StatementParser.scala index b971c3227..d77037f98 100644 --- a/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/StatementParser.scala +++ b/language/shared/src/main/scala/com/ossuminc/riddl/language/parsing/StatementParser.scala @@ -11,13 +11,16 @@ import com.ossuminc.riddl.language.At import fastparse.* import fastparse.MultiLineWhitespace.* -/** StatementParser Define actions that various constructs can take for modelling behavior in a message-passing system +/** StatementParser Define actions that various constructs can take for modelling behavior in a + * message-passing system */ private[parsing] trait StatementParser { this: ReferenceParser & CommonParser => private def arbitraryStatement[u: P]: P[ArbitraryStatement] = { - P(Index ~ literalString ~/ Index)./ map { case (start, str, end) => ArbitraryStatement(at(start, end), str) } + P(Index ~ literalString ~/ Index)./ map { case (start, str, end) => + ArbitraryStatement(at(start, end), str) + } } private def errorStatement[u: P]: P[ErrorStatement] = { @@ -35,7 +38,9 @@ private[parsing] trait StatementParser { private def sendStatement[u: P]: P[SendStatement] = { P( Index ~ Keywords.send ~/ messageRef ~/ to ~ (outletRef | inletRef) ~/ Index - ).map { case (start, messageRef, portlet, end) => SendStatement(at(start, end), messageRef, portlet) } + ).map { case (start, messageRef, portlet, end) => + SendStatement(at(start, end), messageRef, portlet) + } } private def tellStatement[u: P]: P[TellStatement] = { @@ -97,8 +102,11 @@ private[parsing] trait StatementParser { private def morphStatement[u: P]: P[MorphStatement] = { P( - Index ~ Keywords.morph ~/ entityRef ~/ to ~ stateRef ~/ `with` ~ messageRef ~/ Index - )./.map { case (start, eRef, sRef, mRef, end) => MorphStatement(at(start, end), eRef, sRef, mRef) } + Index ~ Keywords.morph ~/ entityRef ~/ to ~ stateRef ~/ Keyword.with_ ~ messageRef ~/ + Index + )./.map { case (start, eRef, sRef, mRef, end) => + MorphStatement(at(start, end), eRef, sRef, mRef) + } } private def becomeStatement[u: P]: P[BecomeStatement] = { @@ -114,8 +122,9 @@ private[parsing] trait StatementParser { } private def replyStatement[u: P]: P[ReplyStatement] = { - P(Index ~ Keywords.reply ~/ `with`.?./ ~ messageRef ~~ Index).map { case (start, ref, end) => - ReplyStatement(at(start, end), ref) + P(Index ~ Keywords.reply ~/ Keyword.with_.?./ ~ messageRef ~~ Index).map { + case (start, ref, end) => + ReplyStatement(at(start, end), ref) } } @@ -136,7 +145,17 @@ private[parsing] trait StatementParser { private def writeStatement[u: P]: P[WriteStatement] = { P( - Index ~ StringIn("write", "put", "create", "update", "delete", "remove", "append", "insert", "modify").! ~ + Index ~ StringIn( + "write", + "put", + "create", + "update", + "delete", + "remove", + "append", + "insert", + "modify" + ).! ~ literalString ~ to ~ typeRef ~ Index ).map { case (start, keyword, what, to, end) => WriteStatement(at(start, end), keyword, what, to) @@ -163,8 +182,9 @@ private[parsing] trait StatementParser { def statement[u: P](set: StatementsSet): P[Statements] = { set match { - case StatementsSet.AdaptorStatements => anyDefStatements(set) | replyStatement - case StatementsSet.ContextStatements => anyDefStatements(set) | replyStatement | focusStatement + case StatementsSet.AdaptorStatements => anyDefStatements(set) | replyStatement + case StatementsSet.ContextStatements => + anyDefStatements(set) | replyStatement | focusStatement case StatementsSet.EntityStatements => anyDefStatements(set) | morphStatement | becomeStatement | replyStatement case StatementsSet.FunctionStatements => anyDefStatements(set) | returnStatement diff --git a/language/shared/src/test/scala/com/ossuminc/riddl/language/parsing/KeywordsTest.scala b/language/shared/src/test/scala/com/ossuminc/riddl/language/parsing/KeywordsTest.scala index aa91ab7f0..328468ec0 100644 --- a/language/shared/src/test/scala/com/ossuminc/riddl/language/parsing/KeywordsTest.scala +++ b/language/shared/src/test/scala/com/ossuminc/riddl/language/parsing/KeywordsTest.scala @@ -18,13 +18,13 @@ class KeywordsTest extends AbstractTestingBasis { "Punctuation" should { "produce all punctuation marks" in { - Punctuation.allPunctuation.size must be (17) + Punctuation.allPunctuation.size must be(17) } } "Readability" should { "produce all readability words" in { - ReadabilityWords.allReadability.size must be(15) + ReadabilityWords.allReadability.size must be(14) } } } diff --git a/passes/input/rbbq.riddl b/passes/input/rbbq.riddl index 7c83a5021..373d819d7 100644 --- a/passes/input/rbbq.riddl +++ b/passes/input/rbbq.riddl @@ -36,14 +36,11 @@ domain ReactiveBBQ is { handler Input is { ??? } } with { option is kind("device") + briefly "A device for viewing Orders" explained as { - |# brief - |This is an OrderViewer - |# details |The OrderViewer is the device in the kitchen, probably a touch screen, - |that the cooks use to view the sequence of orders to cook - |# see - |* http://foo.com/ + |that the cooks use to view the sequence of orders to cook and the items + |for that order. } } } with { @@ -161,10 +158,8 @@ domain ReactiveBBQ is { } } } with { + briefly "Reactive BBQ Domain Definition" explained as { - |# brief - | Reactive BBQ Domain Definition - |#details |This domain definition is designed to be instructive in the RIDDL language. |It uses the case study from the Lightbend Reactive Architecture course as |the basis for defining the domain. The course uses a set of interviews with diff --git a/passes/jvm-native/src/test/scala/com/ossuminc/riddl/passes/validate/JVMAbstractValidatingTest.scala b/passes/jvm-native/src/test/scala/com/ossuminc/riddl/passes/validate/JVMAbstractValidatingTest.scala index 47df9a119..adfe6f61d 100644 --- a/passes/jvm-native/src/test/scala/com/ossuminc/riddl/passes/validate/JVMAbstractValidatingTest.scala +++ b/passes/jvm-native/src/test/scala/com/ossuminc/riddl/passes/validate/JVMAbstractValidatingTest.scala @@ -34,12 +34,12 @@ class JVMAbstractValidatingTest extends AbstractValidatingTest { val future = RiddlParserInput.fromURL(url).map { rpi => TopLevelParser.parseInput(rpi) match case Left(errors) => - val msgs = errors.format + val msgs = errors.justErrors.format fail(s"In $label:\n$msgs") case Right(root) => runStandardPasses(root, shouldFailOnErrors) match { case Left(errors) => - fail(errors.justErrors.format) + fail(s"In $label:\n${errors.justErrors.format}") case Right(pr) => validation(root, pr) } @@ -79,7 +79,9 @@ class JVMAbstractValidatingTest extends AbstractValidatingTest { def validateFile( label: String, fileName: String - )(validation: (PassRoot, Messages) => Assertion = (_, msgs) => fail(msgs.format)): Assertion = { + )( + validation: (PassesResult, Messages) => Assertion = (_, msgs) => fail(msgs.format) + ): Assertion = { val url = URL.fromCwdPath(passesTestCase + fileName) val future = RiddlParserInput.fromURL(url).map { rpi => simpleParseAndValidate(rpi) match { @@ -87,7 +89,7 @@ class JVMAbstractValidatingTest extends AbstractValidatingTest { val msgs = errors.format fail(s"In $label:\n$msgs") case Right(result) => - validation(result.root, result.messages) + validation(result, result.messages) } } Await.result(future, 10.seconds) diff --git a/riddlLib/jvm/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala b/riddlLib/jvm/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala new file mode 100644 index 000000000..098339332 --- /dev/null +++ b/riddlLib/jvm/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala @@ -0,0 +1,47 @@ +/* + * Copyright 2019-2025 Ossum, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.ossuminc.riddl + +import com.ossuminc.riddl.language.Finder +import com.ossuminc.riddl.language.AST.* +import com.ossuminc.riddl.language.parsing.RiddlParserInput +import com.ossuminc.riddl.passes.validate.JVMAbstractValidatingTest +import org.scalatest.TestData + +class PromptGenerationTest extends JVMAbstractValidatingTest: + "PromptGeneration" should { + "generate a prompt" in { (td: TestData) => + val rpi = RiddlParserInput("domain foo { ??? } ", td) + parseAndThenValidate(rpi) { (pr, root, _, _) => + val promptGen = PromptGeneration(pr) + val domain = root.domains.head + promptGen(domain, "Tell me more") match + case Left(messages) => + fail(messages.format) + case Right(prompt: String) => + info(prompt) + succeed + end match + } + } + "generate a prompt for a test file" in { (td: TestData) => + parseAndValidateTestInput("Reactive BBQ", "rbbq.riddl") { case (root, result) => + val promptGen = PromptGeneration(result) + val finder = Finder(root.contents) + val entity = finder.recursiveFindByType[Entity].last + entity.handlers.head + promptGen(entity, "Tell me more") match + case Left(messages) => + fail(messages.format) + case Right(prompt: String) => + info(prompt) + succeed + end match + } + } + } +end PromptGenerationTest diff --git a/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala index 40bc5caa6..378b54c2a 100644 --- a/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala +++ b/riddlLib/shared/src/main/scala/com/ossuminc/riddl/PromptGeneration.scala @@ -20,14 +20,16 @@ case class PromptGeneration(passesResult: PassesResult) { .append(definition.briefString) .append("\", fully described as \"") .append(definition.descriptionString) + .append("\"") sb end extension def apply(definition: Definition, prompt: String): Either[Messages, String] = val parents: Parents = passesResult.symbols.parentsOf(definition) - val stack: ParentStack = ParentStack(parents*) + val stack: DefinitionStack = DefinitionStack(parents*) + stack.push(definition) val result = new StringBuilder - parents.reverse.foldLeft(result) { (sb: StringBuilder, definition: Definition) => + stack.foldLeft(result) { (sb: StringBuilder, definition: Definition) => definition match case d: Domain => sb.append(s"In the knowledge Domain named ") diff --git a/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala b/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala deleted file mode 100644 index 877ce9c6f..000000000 --- a/riddlLib/shared/src/test/scala/com/ossuminc/riddl/PromptGenerationTest.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2025 Ossum, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package com.ossuminc.riddl -import com.ossuminc.riddl.language.parsing.RiddlParserInput -import com.ossuminc.riddl.passes.validate.AbstractValidatingTest -import com.ossuminc.riddl.utils.pc -import org.scalatest.TestData - -class PromptGenerationTest extends AbstractValidatingTest: - "PromptGeneration" should { - "generate a prompt" in { (td: TestData) => - val rpi = RiddlParserInput("domain foo { ??? } ", td) - parseAndThenValidate(rpi){ (pr, root, _, _) => - val promptGen = PromptGeneration(pr) - val domain = root.domains.head - promptGen(domain, "Tell me more") match - case Left(messages) => - fail(messages.format) - case Right(prompt: String) => - info(prompt) - succeed - end match - } - } - } -end PromptGenerationTest