summaryrefslogtreecommitdiff
path: root/src/lib/Codec/Pesto/Graph.lhs
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2022-09-07 15:07:04 +0200
committerLars-Dominik Braun <lars@6xq.net>2022-09-07 15:07:04 +0200
commitb282af35ad4b0bb8d90e517f4b9ff03c22234090 (patch)
treed4b9834fe836e77d1253794c19ca0735e291716a /src/lib/Codec/Pesto/Graph.lhs
parent8571736188131acac9540814aeb4d4da99ab2454 (diff)
downloadpesto-b282af35ad4b0bb8d90e517f4b9ff03c22234090.tar.gz
pesto-b282af35ad4b0bb8d90e517f4b9ff03c22234090.tar.bz2
pesto-b282af35ad4b0bb8d90e517f4b9ff03c22234090.zip
Copy-edit specification
Diffstat (limited to 'src/lib/Codec/Pesto/Graph.lhs')
-rw-r--r--src/lib/Codec/Pesto/Graph.lhs96
1 files changed, 59 insertions, 37 deletions
diff --git a/src/lib/Codec/Pesto/Graph.lhs b/src/lib/Codec/Pesto/Graph.lhs
index a9d42a7..43142b6 100644
--- a/src/lib/Codec/Pesto/Graph.lhs
+++ b/src/lib/Codec/Pesto/Graph.lhs
@@ -45,7 +45,7 @@ both directives.
> (between, next) = break isEnd stream
> extract (_:xs) = extract xs
-Start and end directive are removed from the extracted instructions. The
+Start and end directives are removed from the extracted instructions. The
directive “buonappetito” is optional at the end of a stream.
> testExtract = [
@@ -63,62 +63,80 @@ Instructions surrounding the start and end directive are removed.
The stream may contain multiple recipes. The start directive also ends the
previous recipe and starts a new one.
-> , extract [startDirective, Action "pour", endDirective, Action "foobar", startDirective, Annotation "something"] ~?= [[Action "pour"], [Annotation "something"]]
-> , extract [startDirective, Action "heat", startDirective, Annotation "something"] ~?= [[Action "heat"], [Annotation "something"]]
-> , extract [startDirective, Annotation "foobar", startDirective, endDirective] ~?= [[Annotation "foobar"], []]
+> , extract [
+> startDirective
+> , Action "pour"
+> , endDirective
+> , Action "foobar"
+> , startDirective
+> , Annotation "something"]
+> ~?= [[Action "pour"], [Annotation "something"]]
+> , extract [
+> startDirective
+> , Action "heat"
+> , startDirective
+> , Annotation "something"]
+> ~?= [[Action "heat"], [Annotation "something"]]
+> , extract [
+> startDirective
+> , Annotation "foobar"
+> , startDirective
+> , endDirective]
+> ~?= [[Annotation "foobar"], []]
> ]
Each recipe’s stream of instructions drives a stack-based machine that transforms
it into a directed graph. Think of the stack as your kitchen’s workspace that
is used to prepare the food’s components. You can add new ingredients, perform
-actions on them, put them aside and add them again.
+actions on them, put them aside, and add them again.
-This function processes a list of nodes, that is instructions uniquely identified
-by an integer and returns the edges of the directed graph as a list of tuples.
+This function processes a list of nodes, that is, instructions uniquely identified
+by an integer, and returns the edges of the directed graph as a list of tuples.
+> toGraph :: Nodes Instruction -> Edges
> toGraph nodes = third $ foldl f (Nothing, [[]], []) nodes
> where
-Ingredients are simply added to the current workspace. They should for example
+Ingredients are simply added to the current workspace. They should, for example,
appear on the shopping list.
> f ctx (i, Ingredient _) = addToStack ctx i
-The same happens for for tools. However they are not part of the final product,
-but used in the process of making it. For instance they do not appear on the
-shopping list. `Time is a tool <#time-is-a-tool>`_.
+The same happens for tools. However, they are not part of the final product
+but are used in the process of making it. Thus, they do not appear on the
+shopping list. `Time is considered a tool <#time-is-a-tool>`_.
> f ctx (i, Tool _) = addToStack ctx i
Actions take all ingredients and tools currently on the workspace, perform some
-action with them and put the product back onto the workspace.
+action with them, and put the product back onto the workspace.
> f (_, stack:sx, edges) (i, Action _) = (Just i, [i]:stack:sx, edgesTo i stack ++ edges)
> f (_, [], _) (_, Action _) = undefined -- never reached
Results add a label to the current workspace’s contents and move them out of
-the way. It should be a meaningful name, not just A and B obviously.
-Consecutive Results add different labels to the same workspace. That’s useful
+the way. It should be a meaningful name, not just A and B.
+Consecutive results add different labels to the same workspace. That’s useful
when an action yields multiple results at once that are processed in different
ways.
> f ctx (i, Result _) = consumeStack ctx i
-Alternatives too add a label to the current workspace’s content, but they pick
-one of things on the workspace and throw everything else away. This allows
-adding optional or equivalent ingredients to a recipe (i.e. margarine or butter).
+Alternatives, too, add a label to the current workspace’s content, but they pick
+one of the things on the workspace and throw everything else away. This allows
+adding optional or equivalent ingredients to a recipe (i.e., margarine or butter).
> f ctx (i, Alternative _) = consumeStack ctx i
References are similar to ingredients. They are used to add items from a
-workspace labeled with Result or Alternative. More on that `in the next section
+workspace labeled with ``Result`` or ``Alternative``. More on that `in the next section
<#references>`_.
> f ctx (i, Reference _) = addToStack ctx i
Annotations add a description to any of the previous instructions. They can be
used to provide more information about ingredients (so “hot water” becomes
-``+water (hot)``, tools (``&oven (200 °C)``) or actions (``[cook]
+``+water (hot)``, tools (``&oven (200 °C)``), or actions (``[cook]
(until brown)``).
> f ctx@(Nothing, _, _) (_, Annotation _) = ctx
@@ -141,14 +159,14 @@ These are helper functions:
> in (Just i, []:top:sx, edgesTo i top ++ edges)
> edgesTo i = map (\x -> (x, i))
-Here are a few example of how this stack-machine works. Each edge is a tuple of
+Here are a few examples of how this stack-machine works. Each edge is a tuple of
two integer numbers. These are the nodes it connects, starting with zero.
-Ingredient, Tool and Reference itself do not create any edges:
+``Ingredient``, ``Tool``, and ``Reference`` itself do not create any edges:
> testGraph = [
> cmpGraph "+ketchup &spoon *foobar" []
-But Action, Alternative and Result do in combination with them:
+But ``Action``, ``Alternative`` and ``Result`` do in combination with them:
> , cmpGraph "+foobar [barbaz]" [(0, 1)]
> , cmpGraph "+foobar |barbaz" [(0, 1)]
@@ -158,11 +176,12 @@ But Action, Alternative and Result do in combination with them:
> , cmpGraph "+foobar [barbaz] +foobar >barbaz" [(0, 1), (1, 3), (2, 3)]
> , cmpGraph "&foobar [barbaz] [C] >D" [(0, 1), (1, 2), (2, 3)]
-If the stack is empty, i.e. it was cleared by a Result or Alternative
+If the stack is empty, i.e. it was cleared by a ``Result`` or ``Alternative``
instruction, consecutive results or alternatives operate on the *previous*,
non-empty stack.
> , cmpGraph "+foobar >barbaz >C" [(0, 1), (0, 2)]
+> , cmpGraph "+foobar >barbaz >C >D" [(0, 1), (0, 2), (0, 3)]
> , cmpGraph "+foobar |barbaz |C" [(0, 1), (0, 2)]
> , cmpGraph "+foobar >barbaz |C" [(0, 1), (0, 2)]
@@ -173,7 +192,7 @@ Unless that stack too is empty. Then they do nothing:
> , cmpGraph "(foobar) (foobar)" []
> , cmpGraph "[foobar]" []
-The Annotation instruction always creates an edge to the most-recently processed
+The ``Annotation`` instruction always creates an edge to the most-recently processed
node that was not an annotation. Thus two consecutive annotations create edges
to the same node.
@@ -195,30 +214,33 @@ Unknown directives or instructions are never connected to other nodes.
References
++++++++++
-Results and alternatives can be referenced with the Reference instruction.
-Resolving these references does not happen while buiding the graph, but
-afterwards. This allows referencing an a result or alternative before its
-definition with regard to the their processing order.
+Results and alternatives can be referenced with the ``Reference`` instruction.
+Resolving these references does not happen while building the graph but
+afterward. This allows referencing a result or alternative before its
+definition with regard to their processing order.
-Resolving references is fairly simple: For every reference its object name a
-case-insensitive looked is performed in a table containing all results and
-alternatives. If it succeeds an edge from every result and alternative returned
+Resolving references is fairly simple: For every reference’s object name, a
+case-insensitive lookup is performed in a table containing all results and
+alternatives. If it succeeds, an edge from every result and alternative returned
to the reference in question is created.
+> resolveReferences :: Nodes Instruction -> Edges
> resolveReferences nodes = foldl f [] nodes
> where
-> f edges (i, ref@(Reference _)) = map (\x -> (x, i)) (findTarget nodes ref) ++ edges
+> f edges (i, ref@(Reference _)) = map (\x -> (x, i)) (findTargets nodes ref) ++ edges
> f edges _ = edges
-> findTarget nodes (Reference (Quantity _ _ a)) = map fst $ filter (isTarget a) nodes
+> findTargets :: Nodes Instruction -> Instruction -> [NodeId]
+> findTargets nodes (Reference (Quantity _ _ a)) = map fst $ filter (isTarget a) nodes
> where
> lc = map toLower
> isTarget dest (_, Result (Quantity _ _ x)) = lc x == lc dest
-> isTarget dest (_, Alternative (Quantity _ _ x)) = lc x == lc dest
+> isTarget dest (_, Alternative (Quantity _ _ x)) = lc x == lc dest
> isTarget _ _ = False
-> findTarget _ _ = []
+> findTargets _ _ = []
-References works before or after the result instruction.
+References are position-independent and can be used before or after the
+result instruction they are referencing.
> testRef = [
> cmpGraphRef ">foobar *foobar" [(0, 1)]
@@ -263,7 +285,7 @@ Appendix
Find graph’s root node(s), that is a node without outgoing edges:
> walkRoot nodes edges = let out = nub $ map fst edges
-> in filter (\(x, _) -> notElem x out) nodes
+> in filter (\(x, _) -> notElem x out) nodes
Get all nodes with edges pointing towards nodeid