Skip to content

Commit

Permalink
OSS-277-Claude-Inspired-Changes (#716)
Browse files Browse the repository at this point in the history
Changes Inspired By Claude

* Fix some documentation in the AST and Pass modules
* Functions no longer have readability words after requires/returns
* Fix toEndOfLine to accept 0 characters too.
* Improve validation to recognize empty functions properly.
* Add ShopifyCart test case
* Teach Finder to find values recursively from the container
* Revise overload checking to be smarter so that only the
  overloads that refer to different kinds of definitions or
  fields that have different type definitions are noted.
* Don't bother warning about missing author references.
* Don't warn about modesl without streaming data.
* Make checking for event and result message generation in
  on clauses better and recursively search the statements
* Make function validation use a specialized check for
  emptiness because its contents are not definitions
* Get all tests working with these changes 

---------

Co-authored-by: reidspencer <[email protected]>
  • Loading branch information
reid-spencer and reidspencer authored Mar 1, 2025
1 parent ad91035 commit 5796a16
Show file tree
Hide file tree
Showing 46 changed files with 825 additions and 874 deletions.
6 changes: 3 additions & 3 deletions commands/input/everything.riddl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ domain Everything is {

context APlant is {
source Source is { outlet Commands is DoAThing } with { described by "Data Source" }
sink Sink is { inlet Commands is DoAThing } with { explained as "Data Sink" }
sink Sink is { inlet Events is DoAThing } with { explained as "Data Sink" }
connector AChannel is {
from outlet APlant.Source.Commands to inlet APlant.Sink.Commands
from outlet APlant.Source.Commands to inlet APlant.Sink.Events
} with { explained as "A Channel" }
} with { explained as "A Plant" }

Expand All @@ -24,7 +24,7 @@ domain Everything is {

sink Sink is { inlet input is type DoAThing }

connector foo is {
connector con is {
from outlet Everything.APlant.Source.Commands to inlet full.Sink.input
}

Expand Down
22 changes: 11 additions & 11 deletions commands/input/rbbq.riddl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
domain ReactiveBBQ is {

type CustomerId is Id(ReactiveBBQ.Customer.Customer) with { explained as {
type CustomerId is Id(ReactiveBBQ.Customers.Customer) with { explained as {
"Unique identifier for a customer"
}}

type OrderId is Id(ReactiveBBQ.Order.Order) with {
type OrderId is Id(ReactiveBBQ.Orders.Order) with {
described as {
|# brief
|Unique identifier for a customer's order
Expand All @@ -15,7 +15,7 @@ domain ReactiveBBQ is {

type Empty = Nothing

context Customer is {
context Customers is {
entity Customer is {
state main of ReactiveBBQ.Empty
handler input is { ??? }
Expand Down Expand Up @@ -86,12 +86,12 @@ domain ReactiveBBQ is {
handler Inputs is { ??? }
}

adaptor PaymentAdapter from context ReactiveBBQ.Payment is {
adaptor PaymentAdapter from context ReactiveBBQ.Payments is {
???
}
}

context Order is {
context Orders is {
entity Order is {
record fields is {
orderId is ReactiveBBQ.OrderId,
Expand All @@ -104,7 +104,7 @@ domain ReactiveBBQ is {
}
}

context Payment is {
context Payments is {
entity Payment is {
record fields is {
orderId is ReactiveBBQ.OrderId,
Expand All @@ -118,23 +118,23 @@ domain ReactiveBBQ is {
}
}

context Menu is {
context Menus is {
entity MenuItem is {
record fields is { something: String }
state MenuState of Menu.MenuItem.fields
state MenuState of Menus.MenuItem.fields
handler foo is {}
}
type MenuItemRef is reference to entity Menu.MenuItem
type MenuItemRef is reference to entity Menus.MenuItem
entity MenuEntity is {
record fields is { items: many Menu.MenuItemRef }
record fields is { items: many Menus.MenuItemRef }
state typical of MenuEntity.fields
handler foo is { ??? }
} with {
option is aggregate
}
}

context Reservation is {
context Reservations is {
type ReservationValue is {
partyName is String,
phoneNumber is String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DataFlowDiagramTest extends JVMAbstractValidatingTest {
case Left(messages) => fail(messages.justErrors.format)
case Right(passesResult: PassesResult) =>
val dfd = DataFlowDiagram(passesResult)
val domains =
val domains =
passesResult.root match
case root1: Root => AST.getTopLevelDomains(root1)
case nebula: Nebula => nebula.contents.filter[Domain]
Expand All @@ -40,11 +40,11 @@ class DataFlowDiagramTest extends JVMAbstractValidatingTest {
val actual = dfd.generate(contexts.head)
val expected =
"""flowchart LR
|Commands[\"Outlet Source.Commands"\]
|Commands[/"Inlet Sink.Commands"/]
|OutCommands[\"Outlet Source.OutCommands"\]
|InCommands[/"Inlet Sink.InCommands"/]
|APlant[{"Context Everything.APlant"}]
|command ACommand["OnMessageClause adaptCommands.command ACommand"]
|Commands -- Type 'DoAThing' --> Commands
|OutCommands -- Type 'DoAThing' --> InCommands
|""".stripMargin
actual must be(expected)
}
Expand Down
26 changes: 13 additions & 13 deletions language/input/dokn.riddl
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ domain dokn is {
"^[a-zA-Z0-9_+&*-] + (?:\\.[a-zA-Z0-9_+&*-] + )*@(?:[a-zA-Z0-9-]+\\.) + [a-zA-Z]{2,7}"
)
type LoadingMethod = any of { dock, tailgate, forklift, none }
type CompanyId = Id(dokn.Company.Company)
type CompanyId = Id(dokn.Companies.Company)
type DriverId = MobileNumber
type NoteId = Id(dokn.Note.Note)
type MediaId is Id(dokn.Media.Media)
type LocationId is Id(dokn.Location.Location)
type NoteList is reference to entity dokn.Note.Note
type NoteId = Id(dokn.Notes.Note)
type MediaId is Id(dokn.Media.Medium)
type LocationId is Id(dokn.Locations.Location)
type NoteList is reference to entity dokn.Notes.Note

context Company is {
context Companies is {
flow events is {
inlet CompanyEvents_in is event dokn.Company.Company.CompanyEvent
outlet CompanyEvents_out is event dokn.Company.Company.CompanyEvent
inlet CompanyEvents_in is event dokn.Companies.Company.CompanyEvent
outlet CompanyEvents_out is event dokn.Companies.Company.CompanyEvent
}
connector CompanyEvents is {
from outlet CompanyEvents_out to inlet CompanyEvents_in
Expand Down Expand Up @@ -61,7 +61,7 @@ domain dokn is {
}
}

context Driver is {
context Drivers is {
flow DriverMessages is {
inlet Driver_in is type DriverCommands
outlet Driver_out is type DriverEvents
Expand Down Expand Up @@ -103,7 +103,7 @@ domain dokn is {
}
}

context Note is {
context Notes is {
entity Note is {
record fields is {
noteId: NoteId,
Expand All @@ -122,20 +122,20 @@ domain dokn is {
}

context Media is {
entity Media is {
entity Medium is {
record fields is {
mediaId: MediaId,
path: String,
companyId: CompanyId
}
state MediaBase of Media.fields
state MediaBase of Medium.fields
handler MediaBaseHandler is { ??? }
} with {
option consistent
}
}

context Location is {
context Locations is {
entity Location is {

type AddDeliveryLocation is command {
Expand Down
8 changes: 4 additions & 4 deletions language/input/everything_APlant.riddl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
context APlant is {
source Source is { outlet Commands is type DoAThing } with { described as "Data Source" }
sink Sink is { inlet Commands is type DoAThing } with { described as "Data Sink" }
source Source is { outlet OutCommands is type DoAThing } with { described as "Data Source" }
sink Sink is { inlet InCommands is type DoAThing } with { described as "Data Sink" }

connector AChannel is {
from outlet Source.Commands
to inlet Sink.Commands
from outlet Source.OutCommands
to inlet Sink.InCommands
} with { described as "A Channel" }
} with { described as "A bunch of data flow connections" }
4 changes: 2 additions & 2 deletions language/input/everything_app.riddl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
context Whatever is {
record Identity is { name: String, id: UUID, age: Integer }
record Identity is { name: String, uuid: UUID, age: Integer }
group AcquireIdentity is {
form Identity takes record Whatever.Identity
form GetIdentity takes record Whatever.Identity
}
handler DoIt is { ??? }
}
2 changes: 1 addition & 1 deletion language/input/everything_full.riddl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ context full is {
adaptor fromAPlant to context APlant is {
handler adaptCommands is {
on command ACommand {
send command DoAThing to outlet APlant.Source.Commands
send command DoAThing to outlet APlant.Source.OutCommands
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions language/input/rbbq.riddl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
domain ReactiveBBQ is {

type CustomerId is Id(ReactiveBBQ.Customer.Customer) with {
type CustomerId is Id(ReactiveBBQ.Customers.Customer) with {
described as {
"Unique identifier for a customer"
}
}

type OrderId is Id(ReactiveBBQ.Order.Order) with {
type OrderId is Id(ReactiveBBQ.Orders.Order) with {
described as {
|# brief
|Unique identifier for a customer's order
Expand All @@ -17,7 +17,7 @@ domain ReactiveBBQ is {

type Empty = Nothing

context Customer is {
context Customers is {
entity Customer is {
state main of ReactiveBBQ.Empty
handler Input is { ??? }
Expand Down Expand Up @@ -90,12 +90,12 @@ domain ReactiveBBQ is {
handler Inputs is { ??? }
}

adaptor PaymentAdapter from context ReactiveBBQ.Payment is {
adaptor PaymentAdapter from context ReactiveBBQ.Payments is {
???
}
}

context Order is {
context Orders is {
entity Order is {
record Fields is {
orderId is OrderId,
Expand All @@ -108,7 +108,7 @@ domain ReactiveBBQ is {
}
}

context Payment is {
context Payments is {
entity Payment is {
record Fields is {
orderId is OrderId,
Expand All @@ -122,7 +122,7 @@ domain ReactiveBBQ is {
}
}

context Menu is {
context Menus is {
entity MenuItem is {
record Fields is { something: String }
state MenuState of MenuItem.Fields
Expand All @@ -138,7 +138,7 @@ domain ReactiveBBQ is {
}
}

context Reservation is {
context Reservations is {
type ReservationValue is {
partyName is String,
phoneNumber is String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ object AST:
d.isInstanceOf[WithIdentifier] && d.asInstanceOf[WithIdentifier].id.value == name
)

/** Find the first element of the [[Contents]] that */
/** Find the first element of the [[Contents]] that have identifiers */
def identifiedValues: Seq[WithIdentifier] =
container
.filter(d => d.isInstanceOf[WithIdentifier])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,31 @@ case class Finder[CV <: RiddlValue](root: Container[CV]) {
result.asInstanceOf[Seq[T]]
end findByType

def recursiveFindByType[T <: AST.RiddlValue: ClassTag]: Seq[T] =
import scala.reflect.classTag
val lookingFor = classTag[T].runtimeClass
def consider(list: Seq[T], child: RiddlValue): Seq[T] =
val nested = {
child match
case c: Container[?] =>
c.contents.foldLeft(list) { case (next, child) => consider(next, child) }
case IfThenElseStatement(_, _, thens, elses) =>
val r1 = thens.foldLeft(list) { case (next, child) => consider(next, child) }
elses.foldLeft(r1) { case (next, child) => consider(next, child) }
case ForEachStatement(_, _, do_) =>
do_.foldLeft(list) { case (next, child) => consider(next, child) }
case SagaStep(_, _, dos, undos, _) =>
val r2 = dos.foldLeft(list) { case (next, child) => consider(next, child) }
undos.foldLeft(r2) { case (next, child) => consider(next, child) }
case _ => list
end match
}
if lookingFor.isAssignableFrom(child.getClass) then nested :+ child.asInstanceOf[T]
else nested
end consider
root.contents.foldLeft(Seq.empty) { case (list, child) => consider(list, child) }
end recursiveFindByType

/** The return value for the [[Finder.findWithParents()]] function */
type DefWithParents[T <: RiddlValue] = Seq[(T, Parents)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,25 @@ private[parsing] trait FunctionParser {
}

def funcInput[u: P]: P[Aggregation] = {
P(Keywords.requires ~ Punctuation.colon.? ~ aggregation)./
P(Keywords.requires ~ aggregation)./
}

def funcOutput[u: P]: P[Aggregation] = {
P(Keywords.returns ~ Punctuation.colon.? ~ aggregation)./
P(Keywords.returns ~ aggregation)./
}

private def functionDefinitions[u: P]: P[Seq[FunctionContents]] = {
P(
undefined(Seq.empty[FunctionContents]) | (
vitalDefinitionContents | function | functionInclude | statement(StatementsSet.FunctionStatements)
vitalDefinitionContents | function | functionInclude | statement(
StatementsSet.FunctionStatements
)
).asInstanceOf[P[FunctionContents]]./.rep(0)
)
}

private type BodyType = (Option[Aggregation], Option[Aggregation], Seq[FunctionContents])

private def functionBody[u: P]: P[BodyType] =
P(funcInput.? ~ funcOutput.? ~ functionDefinitions)

Expand All @@ -54,7 +56,7 @@ private[parsing] trait FunctionParser {
Index ~ Keywords.function ~/ identifier ~ is ~ open ~/ functionBody ~ close ~ withMetaData ~/ Index
)./.map { case (start, id, (ins, outs, contents), descriptives, end) =>
checkForDuplicateIncludes(contents)
Function(at(start,end), id, ins, outs, contents.toContents, descriptives.toContents)
Function(at(start, end), id, ins, outs, contents.toContents, descriptives.toContents)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ private[parsing] trait NoWhiteSpaceParsers {

def toEndOfLine[u: P]: P[String] = {
P(
CharsWhile(ch => ch != '\n' && ch != '\r').!
CharsWhile(ch => ch != '\n' && ch != '\r', 0).!
)
}

Expand Down
Loading

0 comments on commit 5796a16

Please sign in to comment.