Skip to content

Commit

Permalink
[arrows,util] #52 support representing subtype selection arrows with …
Browse files Browse the repository at this point in the history
…`ToDot` utility:

- defined `ShowT` for `Coproduct`
- defined `ArrowToDot` for `Choose` arrow
- extended `chooseBookReview` example and added its diagram to new `examples.md` file
  • Loading branch information
fehu committed Mar 12, 2019
1 parent ce957e6 commit 88f2852
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 18 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Will be used for initial stage of the development.

It might include _Nous_ related code.

Cypher
-----------------------------------------------------

[Cypher syntax](cypher/doc/syntax.md)


Arrows
-----------------------------------------------------

[Examples](arrows/doc/examples.md)
17 changes: 17 additions & 0 deletions arrows/doc/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

### Example 1

```scala
ScalaExpr[Book].reviews.map(_.choose(
_.on[UserReview].split(_.user, _.text, _.vote),
_.on[AnonReview].text,
_.on[CustomReview].choose(
_.on[Reviews].reviews.map(_.choose(
_.on[AnonReview].text
)),
_.on[ImageReviewAttachment].split(_.review.split(_.user, _.text), _.url)
)
))
```

[Example1](examples/example-1.png)
184 changes: 184 additions & 0 deletions arrows/doc/examples/example-1.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// Generated with `ToDot(ScalaExprTest.chooseBookReview)`

digraph {
Book_423227530 [label="Book",]
List_695052054 [label="List[Review]",]

edge [label="reviews",];
Book_423227530 -> List_695052054;

subgraph cluster_1229032927{
Review_1903643206 [label="Review",]

UserReview_689467429 [label="UserReview",style=dashed]AnonReview_38705457 [label="AnonReview",style=dashed]CustomReview_575025072 [label="CustomReview",style=dashed]
edge [style=dashed,dir=back,arrowtail=odot];

edge [label=<<i>on</i>>,];
Review_1903643206 -> UserReview_689467429;

edge [label=<<i>on</i>>,];
Review_1903643206 -> AnonReview_38705457;

edge [label=<<i>on</i>>,];
Review_1903643206 -> CustomReview_575025072;

edge [style=solid,dir=forward]; // reset
choose_1856150562 [label="(String, String, Int) :+: String :+: (List :+: ((String, String), String) :+: CNil) :+: CNil"];

split_tuple_2141803520 [label="(String, String, Int)"];

String_1837281868 [label="String",]

edge [label="user",];
UserReview_689467429 -> String_1837281868;


String_1672831165 [label="String",]

edge [label="text",];
UserReview_689467429 -> String_1672831165;


Int_73631283 [label="Int",]

edge [label="vote",];
UserReview_689467429 -> Int_73631283;


edge[style=bold];

edge [label="_1",];
String_1837281868 -> split_tuple_2141803520;

edge [label="_2",];
String_1672831165 -> split_tuple_2141803520;

edge [label="_3",];
Int_73631283 -> split_tuple_2141803520;

edge[style=solid]; // reset

String_1384336613 [label="String",]

edge [label="text",];
AnonReview_38705457 -> String_1384336613;


Reviews_1674881998 [label="Reviews",style=dashed]ImageReviewAttachment_785445613 [label="ImageReviewAttachment",style=dashed]
edge [style=dashed,dir=back,arrowtail=odot];

edge [label=<<i>on</i>>,];
CustomReview_575025072 -> Reviews_1674881998;

edge [label=<<i>on</i>>,];
CustomReview_575025072 -> ImageReviewAttachment_785445613;

edge [style=solid,dir=forward]; // reset
choose_1602215124 [label="List :+: ((String, String), String) :+: CNil"];

List_1136366801 [label="List[Review]",]

edge [label="reviews",];
Reviews_1674881998 -> List_1136366801;

subgraph cluster_1706715864{
Review_1840830355 [label="Review",]

AnonReview_633466538 [label="AnonReview",style=dashed]
edge [style=dashed,dir=back,arrowtail=odot];

edge [label=<<i>on</i>>,];
Review_1840830355 -> AnonReview_633466538;

edge [style=solid,dir=forward]; // reset
choose_1171156189 [label="String :+: CNil"];

String_209084694 [label="String",]

edge [label="text",];
AnonReview_633466538 -> String_209084694;



edge [label="",style=dashed];
String_209084694 -> choose_1171156189;


}
edge [label=<<b>map</b>>,arrowtail=inv,dir=both];
List_1136366801 -> Review_1840830355;
edge [dir=forward]; // reset

split_tuple_1926684109 [label="((String, String), String)"];

UserReview_2028626560 [label="UserReview",]

edge [label="review",];
ImageReviewAttachment_785445613 -> UserReview_2028626560;


split_tuple_2005246918 [label="(String, String)"];

String_806469817 [label="String",]

edge [label="user",];
UserReview_2028626560 -> String_806469817;


String_1742664243 [label="String",]

edge [label="text",];
UserReview_2028626560 -> String_1742664243;


edge[style=bold];

edge [label="_1",];
String_806469817 -> split_tuple_2005246918;

edge [label="_2",];
String_1742664243 -> split_tuple_2005246918;

edge[style=solid]; // reset

String_366708769 [label="String",]

edge [label="url",];
ImageReviewAttachment_785445613 -> String_366708769;


edge[style=bold];

edge [label="_1",];
split_tuple_2005246918 -> split_tuple_1926684109;

edge [label="_2",];
String_366708769 -> split_tuple_1926684109;

edge[style=solid]; // reset


edge [label="",style=dashed];
choose_1171156189 -> choose_1602215124;

edge [label="",style=dashed];
split_tuple_1926684109 -> choose_1602215124;



edge [label="",style=dashed];
split_tuple_2141803520 -> choose_1856150562;

edge [label="",style=dashed];
String_1384336613 -> choose_1856150562;

edge [label="",style=dashed];
choose_1602215124 -> choose_1856150562;


}
edge [label=<<b>map</b>>,arrowtail=inv,dir=both];
List_695052054 -> Review_1903643206;
edge [dir=forward]; // reset

}
Binary file added arrows/doc/examples/example-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 62 additions & 10 deletions arrows/src/main/scala/com/abraxas/slothql/arrow/util/show.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,22 @@ object ShowT extends ShowTLowPriorityImplicits {
showEach: ops.hlist.LiftAll.Aux[ShowT, L, ShowL],
toList: ops.hlist.ToTraversable.Aux[ShowL, List, ShowT[_]],
low: LowPriority
): ShowT[L] = {
val showL = showEach.instances.toList
ShowT.define[L](
show = showL.foldRight("HNil")((show, acc) => s"${showInfix(show, _())} :: $acc"),
showSimple = showL.foldRight("HNil")((show, acc) => s"${showInfix(show, _.simple)} :: $acc"),
showSimplest = "HList",
infix = true
)
}
): ShowT[L] = showCons("HList", "HNil", "::", showEach.instances.toList)

implicit def defaultCoproductShowT[C <: Coproduct, ShowL <: HList](
implicit
showEach: ops.coproduct.LiftAll.Aux[ShowT, C, ShowL],
toList: ops.hlist.ToTraversable.Aux[ShowL, List, ShowT[_]],
low: LowPriority
): ShowT[C] = showCons("Coproduct", "CNil", ":+:", showEach.instances.toList)


private def showCons[A](name: String, empty: String, op: String, showL: List[ShowT[_]]) = ShowT.define[A](
show = showL.foldRight(empty)((show, acc) => s"${showInfix(show, _())} $op $acc"),
showSimple = showL.foldRight(empty)((show, acc) => s"${showInfix(show, _.simple)} $op $acc"),
showSimplest = name,
infix = true
)
private def showInfix(show: ShowT[_], f: ShowT[_] => String) = if (show.isInfix) s"(${f(show)})" else f(show)
}

Expand Down Expand Up @@ -107,8 +113,12 @@ object ArrowToDot {
s"""$id [label="${show()}",${props.mkString(",")}]""" -> id
}
def defaultEdge(source: SourceNodeId, target: TargetNodeId, label: String, props: String*): String =
dotEdge(source, target, s"""label="$label",${props.mkString(",")}""")
def defaultHtmlLabelEdge(source: SourceNodeId, target: TargetNodeId, labelHtml: String, props: String*): String =
dotEdge(source, target, s"""label=<$labelHtml>,${props.mkString(",")}""")
def dotEdge(source: SourceNodeId, target: TargetNodeId, props: String*): String =
s"""
|edge [label="$label",${props.mkString(",")}];
|edge [${props.mkString(",")}];
|$source -> $target;
""".stripMargin

Expand Down Expand Up @@ -140,6 +150,48 @@ object ArrowToDot {
dot -> id
}

object ArrowToDotPoly2 extends Poly2 {
implicit def impl[A <: Arrow](implicit toDot: ArrowToDot[A]): Case.Aux[A, SourceNodeId, (String, TargetNodeId)] =
at{ (a, source) => toDot(a, source) }
}

implicit def chooseArrowToDot[
A <: Arrow, Arrs <: HList, ArrsLen <: Nat, SourceNodeIds <: HList, ArrsDot <: HList,
SourceTypes <: HList, ShowSourceTypes <: HList
](
implicit
choose: A <:< Arrow.Choose[_, Arrs],
arrsLength: ops.hlist.Length.Aux[Arrs, ArrsLen],
sourceNodesIdsType: ops.hlist.Fill.Aux[ArrsLen, String, SourceNodeIds],
liftSourceNodeIds: ops.traversable.FromTraversable[SourceNodeIds],
toDot: ops.hlist.ZipWith.Aux[Arrs, SourceNodeIds, ArrowToDotPoly2.type, ArrsDot],
dotToList: ops.hlist.ToTraversable.Aux[ArrsDot, List, (String, TargetNodeId)],
arrSourceTypes: Arrow.Sources.Aux[Arrs, SourceTypes],
showSourceTypes: ops.hlist.LiftAll.Aux[ShowT, SourceTypes, ShowSourceTypes],
showSourceTypesToList: ops.hlist.ToTraversable.Aux[ShowSourceTypes, List, ShowT[_]],
showTargetType: ShowT[A#Target]
): ArrowToDot[A] = define {
(a, source0) =>
val showSources = showSourceTypes.instances.toList
val (sources, sourceIds) = showSources.map(defaultNewTypeNode("style=dashed")(_)).unzip
val chooseArrows = sourceIds.map{ id => defaultHtmlLabelEdge(source0, id, "<i>on</i>") }.mkString
val (dots, targets) = toDot(a.arrows, liftSourceNodeIds(sourceIds).get).toList.unzip
val coprodNodeId = "choose_" + randInt()
val coprodNode = s"""$coprodNodeId [label="${showTargetType.simple}"]"""
val coprodArrows = targets.map{ id => defaultEdge(id, coprodNodeId, "", "style=dashed") }.mkString
val dot =
s"""
|${sources.mkString}
|edge [style=dashed,dir=back,arrowtail=odot];
|$chooseArrows
|edge [style=solid,dir=forward]; // reset
|$coprodNode;
|${dots.mkString}
|${coprodArrows.mkString}
""".stripMargin
dot -> coprodNodeId
}

implicit def compositeArrowToDot[A <: Arrow, Arrs0 <: HList, Arrs <: HList](
implicit
notSplit: A <:!< Arrow.Split[_],
Expand Down
Loading

0 comments on commit 88f2852

Please sign in to comment.