aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-04-23 21:22:48 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-04-25 02:24:42 +0200
commit296e90186d7107424156770e7b06c93b90cb7860 (patch)
tree293a5122a200f3d5ad121a1453463c1cef5fa9fc
parentdocs: add use cases to landing page (diff)
downloadrefinery-docs.tar.gz
refinery-docs.tar.zst
refinery-docs.zip
docs: language referencedocs
-rw-r--r--subprojects/docs/src/learn/language/classes.md14
-rw-r--r--subprojects/docs/src/learn/language/classes/ContainmentInstance.svg227
-rw-r--r--subprojects/docs/src/learn/language/classes/InvalidInstance.svg20
-rw-r--r--subprojects/docs/src/learn/language/classes/MultiplicityConstraintsInstance.svg229
-rw-r--r--subprojects/docs/src/learn/language/classes/NewObjectsSimple.svg29
-rw-r--r--subprojects/docs/src/learn/language/classes/NewObjectsWithInheritance.svg38
-rw-r--r--subprojects/docs/src/learn/language/classes/ReferencesOppositeInstance.svg69
-rw-r--r--subprojects/docs/src/learn/language/classes/ReferencesOppositeSelf.svg24
-rw-r--r--subprojects/docs/src/learn/language/classes/ReferencesSimple.svg43
-rw-r--r--subprojects/docs/src/learn/language/classes/index.md212
-rw-r--r--subprojects/docs/src/learn/language/logic/AssertionsError.svg20
-rw-r--r--subprojects/docs/src/learn/language/logic/AssertionsExample.svg99
-rw-r--r--subprojects/docs/src/learn/language/logic/DefaultAssertions.svg129
-rw-r--r--subprojects/docs/src/learn/language/logic/MultiObjects.svg81
-rw-r--r--subprojects/docs/src/learn/language/logic/ObjectScopes.svg58
-rw-r--r--subprojects/docs/src/learn/language/logic/StrongerObjectScopes.svg58
-rw-r--r--subprojects/docs/src/learn/language/logic/index.md256
-rw-r--r--subprojects/docs/src/learn/language/predicates/DerivedFeature.svg76
-rw-r--r--subprojects/docs/src/learn/language/predicates/index.md284
19 files changed, 1952 insertions, 14 deletions
diff --git a/subprojects/docs/src/learn/language/classes.md b/subprojects/docs/src/learn/language/classes.md
deleted file mode 100644
index 7278dc35..00000000
--- a/subprojects/docs/src/learn/language/classes.md
+++ /dev/null
@@ -1,14 +0,0 @@
1---
2SPDX-FileCopyrightText: 2024 The Refinery Authors
3SPDX-License-Identifier: EPL-2.0
4description: Metamodeling in Refinery
5sidebar_position: 0
6---
7
8# Classes and references
9
10:::warning
11
12Under construction
13
14:::
diff --git a/subprojects/docs/src/learn/language/classes/ContainmentInstance.svg b/subprojects/docs/src/learn/language/classes/ContainmentInstance.svg
new file mode 100644
index 00000000..197f4b48
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/ContainmentInstance.svg
@@ -0,0 +1,227 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="395pt" height="226pt" viewBox="-6 -6 407.4700012207031 238.39999389648438" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-sdYDAL2PsHukjJUpNyUhU"><style>.refinery-sdYDAL2PsHukjJUpNyUhU .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .node .node-outline{stroke:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .node .node-header{fill:rgb(53, 161, 173);}.refinery-sdYDAL2PsHukjJUpNyUhU .node .node-bg{fill:#fff;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-h .node-header{fill:#e06c75;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-i .node-header{fill:#98c379;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-j .node-header{fill:#c678dd;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-n .node-header{fill:#abcc94;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge .edge-line{stroke:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge .edge-arrow{fill:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN text{fill:#696c77;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR text{fill:#ca1243;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-sdYDAL2PsHukjJUpNyUhU .icon-TRUE{fill:#19202b;}.refinery-sdYDAL2PsHukjJUpNyUhU .icon-UNKNOWN{fill:#696c77;}.refinery-sdYDAL2PsHukjJUpNyUhU .icon-ERROR{fill:#ca1243;}.refinery-sdYDAL2PsHukjJUpNyUhU text.label-UNKNOWN{fill:#696c77;}.refinery-sdYDAL2PsHukjJUpNyUhU text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-sdYDAL2PsHukjJUpNyUhU text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-sdYDAL2PsHukjJUpNyUhU-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-sdYDAL2PsHukjJUpNyUhU-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="scale(1 1) rotate(0) translate(4 222.4)">
4<!-- n3 -->
5<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
6
7<rect stroke="none" x="155.95" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="151" y="-137" width="72" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-0)" class="node-header"/>
9<text text-anchor="start" x="181.53" y="-117.8" font-size="12.00">v1</text>
10<use x="161.952" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
11<g><text text-anchor="start" x="177.95" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
12</g>
13<polyline points="155.95,-110.2 219.98,-110.2" class="node-outline"/>
14<rect fill="none" x="155.95" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-0"><rect stroke="none" x="155.95" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n4 -->
17<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
18
19<rect stroke="none" x="113.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="109" y="-222" width="74" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-1)" class="node-header"/>
21<text text-anchor="start" x="141.09" y="-202.6" font-size="12.00">r1</text>
22<use x="119.78" y="-188.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
23<g><text text-anchor="start" x="135.78" y="-179.2" font-size="12.00" class="label label-TRUE">Region</text>
24</g>
25<polyline points="113.78,-195 180.15,-195" class="node-outline"/>
26<rect fill="none" x="113.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-outline"/>
27<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-1"><rect stroke="none" x="113.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-bg"/></clipPath></g>
28<!-- n3&#45;&gt;n4 -->
29<g class="edge edge-TRUE">
30
31<path fill="none" d="M182.6,-133.43C179.13,-141.63 174.65,-151.02 170,-159.88" class="edge-line"/>
32<polygon points="166.95,-158.15 165.24,-168.61 173.1,-161.5 166.95,-158.15" class="edge-line edge-arrow"/>
33<text text-anchor="middle" x="158.39" y="-155.04" font-size="10.50">region</text>
34</g>
35<!-- n8 -->
36<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
37
38<rect stroke="none" x="53.86" y="-48.8" width="84.22000000000001" height="48.8" rx="12" ry="12" class="node-bg"/>
39<rect stroke="none" x="49" y="-52" width="92" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-2)" class="node-header"/>
40<text text-anchor="start" x="90.42" y="-33" font-size="12.00">t1</text>
41<use x="59.8559" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
42<g><text text-anchor="start" x="75.86" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
43</g>
44<polyline points="53.86,-25.4 138.08,-25.4" class="node-outline"/>
45<rect fill="none" x="53.86" y="-48.8" width="84.22000000000001" height="48.8" rx="12" ry="12" class="node-outline"/>
46<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-2"><rect stroke="none" x="53.86" y="-48.8" width="84.22000000000001" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
47<!-- n3&#45;&gt;n8 -->
48<g class="edge edge-TRUE">
49
50<path fill="none" stroke-width="2" d="M155.95,-84.92C145.63,-76.18 134.29,-66.11 124.25,-56.77" class="edge-line"/>
51<polygon stroke-width="2" points="126.48,-54.66 118.02,-50.88 122.27,-59.11 126.48,-54.66" class="edge-line edge-arrow"/>
52<text text-anchor="start" x="35.36" y="-71.18" font-weight="bold" font-size="10.50">outgoingTransition</text>
53</g>
54<!-- n3&#45;&gt;n8 -->
55
56<!-- n9 -->
57<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
58
59<rect stroke="none" x="155.86" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/>
60<rect stroke="none" x="151" y="-52" width="92" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-3)" class="node-header"/>
61<text text-anchor="start" x="192.42" y="-33" font-size="12.00">t2</text>
62<use x="161.856" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
63<g><text text-anchor="start" x="177.86" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
64</g>
65<polyline points="155.86,-25.4 240.08,-25.4" class="node-outline"/>
66<rect fill="none" x="155.86" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-outline"/>
67<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-3"><rect stroke="none" x="155.86" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
68<!-- n3&#45;&gt;n9 -->
69<g class="edge edge-TRUE">
70
71<path fill="none" stroke-width="2" d="M172.38,-85.14C171.61,-77.31 172.15,-68.38 173.81,-59.86" class="edge-line"/>
72<polygon stroke-width="2" points="176.73,-60.8 175.99,-51.56 170.81,-59.24 176.73,-60.8" class="edge-line edge-arrow"/>
73<text text-anchor="start" x="72.62" y="-58.26" font-weight="bold" font-size="10.50">outgoingTransition</text>
74</g><g class="edge edge-TRUE">
75
76<path fill="none" d="M184.63,-85.14C185,-77.31 185.9,-68.38 187.14,-59.86" class="edge-line"/>
77<polygon points="190.57,-60.56 188.77,-50.12 183.67,-59.4 190.57,-60.56" class="edge-line edge-arrow"/>
78<text text-anchor="middle" x="233.31" y="-70.26" font-size="10.50">incomingTransition</text>
79</g>
80<!-- n3&#45;&gt;n9 -->
81
82<!-- n10 -->
83<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
84
85<rect stroke="none" x="257.86" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/>
86<rect stroke="none" x="253" y="-52" width="92" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-4)" class="node-header"/>
87<text text-anchor="start" x="294.42" y="-33" font-size="12.00">t3</text>
88<use x="263.856" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
89<g><text text-anchor="start" x="279.86" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
90</g>
91<polyline points="257.86,-25.4 342.08,-25.4" class="node-outline"/>
92<rect fill="none" x="257.86" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-outline"/>
93<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-4"><rect stroke="none" x="257.86" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
94<!-- n3&#45;&gt;n10 -->
95
96<!-- n4&#45;&gt;n3 -->
97<g class="edge edge-TRUE">
98
99<path fill="none" stroke-width="2" d="M152.26,-169.94C155.72,-161.75 160.2,-152.37 164.84,-143.5" class="edge-line"/>
100<polygon stroke-width="2" points="167.39,-145.24 168.88,-136.09 162.01,-142.31 167.39,-145.24" class="edge-line edge-arrow"/>
101<text text-anchor="start" x="119.24" y="-143.04" font-weight="bold" font-size="10.50">vertices</text>
102</g>
103<!-- n5 -->
104<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
105
106<rect stroke="none" x="73.95" y="-133.6" width="64.02999999999999" height="48.8" rx="12" ry="12" class="node-bg"/>
107<rect stroke="none" x="69" y="-137" width="72" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-5)" class="node-header"/>
108<text text-anchor="start" x="99.53" y="-117.8" font-size="12.00">v2</text>
109<use x="79.9516" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
110<g><text text-anchor="start" x="95.95" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
111</g>
112<polyline points="73.95,-110.2 137.98,-110.2" class="node-outline"/>
113<rect fill="none" x="73.95" y="-133.6" width="64.02999999999999" height="48.8" rx="12" ry="12" class="node-outline"/>
114<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-5"><rect stroke="none" x="73.95" y="-133.6" width="64.02999999999999" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
115<!-- n4&#45;&gt;n5 -->
116<g class="edge edge-TRUE">
117
118<path fill="none" stroke-width="2" d="M129.42,-169.94C124.87,-161.93 120.16,-152.77 116.09,-144.08" class="edge-line"/>
119<polygon stroke-width="2" points="118.93,-142.93 112.57,-136.19 113.34,-145.43 118.93,-142.93" class="edge-line edge-arrow"/>
120<text text-anchor="start" x="78.34" y="-156.05" font-weight="bold" font-size="10.50">vertices</text>
121</g>
122<!-- n5&#45;&gt;n4 -->
123<g class="edge edge-TRUE">
124
125<path fill="none" d="M123.6,-133.43C128.21,-141.54 132.96,-150.81 137.06,-159.59" class="edge-line"/>
126<polygon points="133.79,-160.84 141.05,-168.55 140.18,-157.99 133.79,-160.84" class="edge-line edge-arrow"/>
127<text text-anchor="middle" x="117.57" y="-142.24" font-size="10.50">region</text>
128</g>
129<!-- n5&#45;&gt;n8 -->
130<g class="edge edge-TRUE">
131
132<path fill="none" d="M97.06,-85.14C95.54,-77.31 94.28,-68.38 93.46,-59.86" class="edge-line"/>
133<polygon points="96.97,-59.85 92.75,-50.14 89.99,-60.37 96.97,-59.85" class="edge-line edge-arrow"/>
134<text text-anchor="middle" x="47.13" y="-57.66" font-size="10.50">incomingTransition</text>
135</g>
136<!-- n5&#45;&gt;n9 -->
137
138<!-- n5&#45;&gt;n10 -->
139
140<!-- n6 -->
141<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
142
143<rect stroke="none" x="267.95" y="-133.6" width="64.03000000000003" height="48.8" rx="12" ry="12" class="node-bg"/>
144<rect stroke="none" x="263" y="-137" width="72" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-6)" class="node-header"/>
145<text text-anchor="start" x="293.53" y="-117.8" font-size="12.00">v3</text>
146<use x="273.952" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
147<g><text text-anchor="start" x="289.95" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
148</g>
149<polyline points="267.95,-110.2 331.98,-110.2" class="node-outline"/>
150<rect fill="none" x="267.95" y="-133.6" width="64.03000000000003" height="48.8" rx="12" ry="12" class="node-outline"/>
151<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-6"><rect stroke="none" x="267.95" y="-133.6" width="64.03000000000003" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="edge edge-TRUE">
152
153<path fill="none" d="M293.84,-85.14C293.27,-77.31 293.09,-68.38 293.3,-59.86" class="edge-line"/>
154<polygon points="296.78,-60.29 293.76,-50.14 289.79,-59.96 296.78,-60.29" class="edge-line edge-arrow"/>
155<text text-anchor="middle" x="340.34" y="-70.26" font-size="10.50">incomingTransition</text>
156</g>
157<!-- n7 -->
158<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
159
160<rect stroke="none" x="266.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-bg"/>
161<rect stroke="none" x="262" y="-222" width="74" height="27" clip-path="url(#refinery-sdYDAL2PsHukjJUpNyUhU-clip-7)" class="node-header"/>
162<text text-anchor="start" x="294.09" y="-202.6" font-size="12.00">r2</text>
163<use x="272.78" y="-188.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-sdYDAL2PsHukjJUpNyUhU-icon-TRUE"/>
164<g><text text-anchor="start" x="288.78" y="-179.2" font-size="12.00" class="label label-TRUE">Region</text>
165</g>
166<polyline points="266.78,-195 333.15,-195" class="node-outline"/>
167<rect fill="none" x="266.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-outline"/>
168<clipPath id="refinery-sdYDAL2PsHukjJUpNyUhU-clip-7"><rect stroke="none" x="266.78" y="-218.4" width="66.37" height="48.80000000000001" rx="12" ry="12" class="node-bg"/></clipPath></g>
169<!-- n6&#45;&gt;n7 -->
170<g class="edge edge-TRUE">
171
172<path fill="none" d="M306.1,-133.43C306.67,-141.27 306.84,-150.2 306.63,-158.72" class="edge-line"/>
173<polygon points="303.14,-158.27 306.16,-168.42 310.14,-158.6 303.14,-158.27" class="edge-line edge-arrow"/>
174<text text-anchor="middle" x="291.03" y="-142.02" font-size="10.50">region</text>
175</g>
176<!-- n6&#45;&gt;n8 -->
177
178<!-- n6&#45;&gt;n9 -->
179
180<!-- n6&#45;&gt;n10 -->
181<g class="edge edge-TRUE">
182
183<path fill="none" d="M213.57,-48.63C214.33,-56.56 213.75,-65.61 212.03,-74.21" class="edge-line"/>
184<polygon points="208.7,-73.11 209.51,-83.67 215.47,-74.91 208.7,-73.11" class="edge-line edge-arrow"/>
185<text text-anchor="middle" x="198.62" y="-70.03" font-size="10.50">target</text>
186</g>
187<!-- n6&#45;&gt;n10 -->
188
189<!-- n7&#45;&gt;n6 -->
190<g class="edge edge-TRUE">
191
192<path fill="none" stroke-width="2" d="M293.84,-169.94C293.28,-162.19 293.09,-153.38 293.29,-144.95" class="edge-line"/>
193<polygon stroke-width="2" points="296.34,-145.33 293.69,-136.45 290.22,-145.05 296.34,-145.33" class="edge-line edge-arrow"/>
194<text text-anchor="start" x="251.69" y="-155.87" font-weight="bold" font-size="10.50">vertices</text>
195</g><g class="edge edge-TRUE">
196
197<path fill="none" stroke-width="2" d="M281.6,-85.14C279.9,-77.39 279.35,-68.58 279.95,-60.15" class="edge-line"/>
198<polygon stroke-width="2" points="282.96,-60.72 281.14,-51.63 276.9,-59.87 282.96,-60.72" class="edge-line edge-arrow"/>
199<text text-anchor="start" x="179.61" y="-58.47" font-weight="bold" font-size="10.50">outgoingTransition</text>
200</g><g class="edge edge-TRUE">
201
202<path fill="none" d="M318.37,-48.63C320.07,-56.47 320.6,-65.4 319.95,-73.92" class="edge-line"/>
203<polygon points="316.51,-73.24 318.55,-83.64 323.44,-74.24 316.51,-73.24" class="edge-line edge-arrow"/>
204<text text-anchor="middle" x="305.62" y="-57.22" font-size="10.50">target</text>
205</g>
206<g class="edge edge-TRUE">
207
208<path fill="none" d="M127.91,-48.63C138.46,-57.54 150.06,-67.86 160.27,-77.38" class="edge-line"/>
209<polygon points="157.7,-79.76 167.36,-84.09 162.51,-74.68 157.7,-79.76" class="edge-line edge-arrow"/>
210<text text-anchor="middle" x="165.07" y="-69.83" font-size="10.50">source</text>
211</g><g class="edge edge-TRUE">
212
213<path fill="none" d="M104.91,-48.63C106.42,-56.47 107.67,-65.4 108.49,-73.92" class="edge-line"/>
214<polygon points="104.98,-73.91 109.19,-83.63 111.96,-73.4 104.98,-73.91" class="edge-line edge-arrow"/>
215<text text-anchor="middle" x="122.29" y="-69.82" font-size="10.50">target</text>
216</g><g class="edge edge-TRUE">
217
218<path fill="none" d="M201.3,-48.63C200.91,-56.47 200.01,-65.4 198.77,-73.92" class="edge-line"/>
219<polygon points="195.34,-73.2 197.13,-83.64 202.24,-74.36 195.34,-73.2" class="edge-line edge-arrow"/>
220<text text-anchor="middle" x="183.25" y="-57.22" font-size="10.50">source</text>
221</g><g class="edge edge-TRUE">
222
223<path fill="none" d="M306.1,-48.63C306.67,-56.47 306.84,-65.4 306.63,-73.92" class="edge-line"/>
224<polygon points="303.14,-73.47 306.16,-83.62 310.14,-73.8 303.14,-73.47" class="edge-line edge-arrow"/>
225<text text-anchor="middle" x="323.2" y="-57.22" font-size="10.50">source</text>
226</g></g>
227</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/InvalidInstance.svg b/subprojects/docs/src/learn/language/classes/InvalidInstance.svg
new file mode 100644
index 00000000..fb9dd37d
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/InvalidInstance.svg
@@ -0,0 +1,20 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="74pt" height="72pt" viewBox="-6 -6 86 84.4000015258789" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-S3CluI8WDJspDI9OUqv4H"><style>.refinery-S3CluI8WDJspDI9OUqv4H .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .node .node-outline{stroke:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .node .node-header{fill:rgb(53, 161, 173);}.refinery-S3CluI8WDJspDI9OUqv4H .node .node-bg{fill:#fff;}.refinery-S3CluI8WDJspDI9OUqv4H .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-S3CluI8WDJspDI9OUqv4H .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-S3CluI8WDJspDI9OUqv4H .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-h .node-header{fill:#e06c75;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-i .node-header{fill:#98c379;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-j .node-header{fill:#c678dd;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-n .node-header{fill:#abcc94;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-S3CluI8WDJspDI9OUqv4H .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .edge .edge-line{stroke:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .edge .edge-arrow{fill:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN text{fill:#696c77;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR text{fill:#ca1243;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-S3CluI8WDJspDI9OUqv4H .icon-TRUE{fill:#19202b;}.refinery-S3CluI8WDJspDI9OUqv4H .icon-UNKNOWN{fill:#696c77;}.refinery-S3CluI8WDJspDI9OUqv4H .icon-ERROR{fill:#ca1243;}.refinery-S3CluI8WDJspDI9OUqv4H text.label-UNKNOWN{fill:#696c77;}.refinery-S3CluI8WDJspDI9OUqv4H text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-S3CluI8WDJspDI9OUqv4H text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-S3CluI8WDJspDI9OUqv4H-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-S3CluI8WDJspDI9OUqv4H-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-S3CluI8WDJspDI9OUqv4H-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 68.4000015258789)">
4<!-- n0 -->
5
6<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE">
7
8<rect stroke="none" x="0" y="-64.4" width="66" height="64.4" rx="12" ry="12" class="node-bg"/>
9<rect stroke="none" x="-4" y="-68" width="74" height="27" clip-path="url(#refinery-S3CluI8WDJspDI9OUqv4H-clip-0)" class="node-header"/>
10<text text-anchor="start" x="14.75" y="-48.6" font-size="12.00">invalid</text>
11<use x="6" y="-35" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-S3CluI8WDJspDI9OUqv4H-icon-ERROR"/>
12<g><text text-anchor="start" x="21.81" y="-25.2" font-size="12.00" class="label label-ERROR">Region</text>
13</g>
14<use x="6" y="-19" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-S3CluI8WDJspDI9OUqv4H-icon-ERROR"/>
15<g><text text-anchor="start" x="22" y="-9.2" font-size="12.00" class="label label-ERROR">State</text>
16</g>
17<polyline points="0,-41 66,-41" class="node-outline"/>
18<rect fill="none" x="0" y="-64.4" width="66" height="64.4" rx="12" ry="12" class="node-outline"/>
19<clipPath id="refinery-S3CluI8WDJspDI9OUqv4H-clip-0"><rect stroke="none" x="0" y="-64.4" width="66" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g></g>
20</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/MultiplicityConstraintsInstance.svg b/subprojects/docs/src/learn/language/classes/MultiplicityConstraintsInstance.svg
new file mode 100644
index 00000000..b28c295a
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/MultiplicityConstraintsInstance.svg
@@ -0,0 +1,229 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="802pt" height="157pt" viewBox="-6 -6 814.3800048828125 169.1999969482422" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-MZ1i4PkeOsY_2x7-6CJ29"><style>.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-outline{stroke:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-header{fill:rgb(53, 161, 173);}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-bg{fill:#fff;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-h .node-header{fill:#e06c75;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-i .node-header{fill:#98c379;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-j .node-header{fill:#c678dd;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-n .node-header{fill:#abcc94;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge .edge-line{stroke:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge .edge-arrow{fill:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN text{fill:#696c77;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR text{fill:#ca1243;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-TRUE{fill:#19202b;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-UNKNOWN{fill:#696c77;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-ERROR{fill:#ca1243;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 text.label-UNKNOWN{fill:#696c77;}.refinery-MZ1i4PkeOsY_2x7-6CJ29 text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-MZ1i4PkeOsY_2x7-6CJ29 text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 153.1999969482422)">
4<!-- n0 -->
5
6<!-- n0&#45;&gt;n0 -->
7
8<!-- n0&#45;&gt;n1 -->
9
10<!-- n0&#45;&gt;n1 -->
11
12<!-- n3 -->
13<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
14
15<rect stroke="none" x="84.25" y="-141.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-bg"/>
16<rect stroke="none" x="80" y="-145" width="72" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-0)" class="node-header"/>
17<text text-anchor="start" x="109.83" y="-125.6" font-size="12.00">v1</text>
18<use x="90.2516" y="-111.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
19<g><text text-anchor="start" x="106.25" y="-102.2" font-size="12.00" class="label label-TRUE">Vertex</text>
20</g>
21<polyline points="84.25,-118 148.28,-118" class="node-outline"/>
22<rect fill="none" x="84.25" y="-141.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-outline"/>
23<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-0"><rect stroke="none" x="84.25" y="-141.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-bg"/></clipPath></g>
24<!-- n1&#45;&gt;n3 -->
25<g class="edge edge-TRUE">
26
27<path fill="none" d="M127.79,-92.67C135,-81.99 144.45,-69.17 153.6,-57.6" class="edge-line"/>
28<polygon points="156.32,-59.81 159.88,-49.83 150.87,-55.41 156.32,-59.81" class="edge-line edge-arrow"/>
29<text text-anchor="middle" x="190.06" y="-60.95" font-size="10.50">outgoingTransition</text>
30</g>
31<!-- n5 -->
32<g class="edge edge-TRUE">
33
34<path fill="none" d="M172.8,-48.65C165.6,-59.32 156.15,-72.13 147,-83.71" class="edge-line"/>
35<polygon points="144.27,-81.51 140.72,-91.49 149.72,-85.91 144.27,-81.51" class="edge-line edge-arrow"/>
36<text text-anchor="middle" x="140.38" y="-74.06" font-size="10.50">source</text>
37</g>
38<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
39
40<rect stroke="none" x="40.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/>
41<rect stroke="none" x="36" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-1)" class="node-header"/>
42<text text-anchor="start" x="76.72" y="-33" font-size="12.00">t1</text>
43<use x="46.1559" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
44<g><text text-anchor="start" x="62.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
45</g>
46<polyline points="40.16,-25.4 124.38,-25.4" class="node-outline"/>
47<rect fill="none" x="40.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-outline"/>
48<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-1"><rect stroke="none" x="40.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="edge edge-TRUE">
49
50<path fill="none" d="M96.97,-48.65C101.54,-58.79 106.27,-70.87 110.06,-81.98" class="edge-line"/>
51<polygon points="106.64,-82.78 113.04,-91.23 113.3,-80.64 106.64,-82.78" class="edge-line edge-arrow"/>
52<text text-anchor="middle" x="89.38" y="-60.85" font-size="10.50">source</text>
53</g><g class="edge edge-TRUE">
54
55<path fill="none" d="M101.52,-92.67C96.95,-82.52 92.23,-70.44 88.44,-59.33" class="edge-line"/>
56<polygon points="91.87,-58.54 85.47,-50.09 85.2,-60.68 91.87,-58.54" class="edge-line edge-arrow"/>
57<text text-anchor="middle" x="46.32" y="-74.16" font-size="10.50">outgoingTransition</text>
58</g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
59
60<rect stroke="none" x="142.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/>
61<rect stroke="none" x="138" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-2)" class="node-header"/>
62<text text-anchor="start" x="178.72" y="-33" font-size="12.00">t2</text>
63<use x="148.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
64<g><text text-anchor="start" x="164.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
65</g>
66<polyline points="142.16,-25.4 226.38,-25.4" class="node-outline"/>
67<rect fill="none" x="142.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-outline"/>
68<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-2"><rect stroke="none" x="142.16" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g><!-- n5 -->
69<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
70
71<rect stroke="none" x="200.77" y="-149.2" width="236.99999999999997" height="64.39999999999999" rx="12" ry="12" class="node-bg"/>
72<rect stroke="none" x="196" y="-153" width="244" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-3)" class="node-header"/>
73<text text-anchor="start" x="312.83" y="-133.4" font-size="12.00">v2</text>
74<use x="206.766" y="-119.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
75<g><text text-anchor="start" x="222.77" y="-110" font-size="12.00" class="label label-TRUE">Vertex</text>
76</g>
77<use x="206.766" y="-103.8" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-ERROR"/>
78<g><text text-anchor="start" x="222.4" y="-94" font-size="12.00" class="label label-ERROR">outgoingTransition::invalidMultiplicity</text>
79</g>
80<polyline points="200.77,-125.8 437.77,-125.8" class="node-outline"/>
81<rect fill="none" x="200.77" y="-149.2" width="236.99999999999997" height="64.39999999999999" rx="12" ry="12" class="node-outline"/>
82<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-3"><rect stroke="none" x="200.77" y="-149.2" width="236.99999999999997" height="64.39999999999999" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
83
84<rect stroke="none" x="277.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/>
85<rect stroke="none" x="273" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-4)" class="node-header"/>
86<text text-anchor="start" x="313.72" y="-33" font-size="12.00">t3</text>
87<use x="283.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
88<g><text text-anchor="start" x="299.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
89</g>
90<polyline points="277.16,-25.4 361.38,-25.4" class="node-outline"/>
91<rect fill="none" x="277.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-outline"/>
92<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-4"><rect stroke="none" x="277.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
93<!-- n4&#45;&gt;n5 -->
94
95<!-- n5&#45;&gt;n4 -->
96<g class="edge edge-TRUE">
97
98<path fill="none" d="M325.25,-48.62C325.82,-56.19 326.07,-64.85 326.01,-73.38" class="edge-line"/>
99<polygon points="322.51,-73.22 325.75,-83.31 329.51,-73.4 322.51,-73.22" class="edge-line edge-arrow"/>
100<text text-anchor="middle" x="309.51" y="-57.13" font-size="10.50">source</text>
101</g>
102<!-- n6&#45;&gt;n5 -->
103<g class="edge edge-TRUE">
104
105<path fill="none" d="M312.82,-84.82C312.47,-76.84 312.42,-68.21 312.68,-60.07" class="edge-line"/>
106<polygon points="316.18,-60.3 313.21,-50.13 309.19,-59.94 316.18,-60.3" class="edge-line edge-arrow"/>
107<text text-anchor="middle" x="358.85" y="-70.18" font-size="10.50">outgoingTransition</text>
108</g>
109<!-- n7 -->
110<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
111
112<rect stroke="none" x="404.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/>
113<rect stroke="none" x="400" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-5)" class="node-header"/>
114<text text-anchor="start" x="440.72" y="-33" font-size="12.00">t4</text>
115<use x="410.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
116<g><text text-anchor="start" x="426.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
117</g>
118<polyline points="404.16,-25.4 488.38,-25.4" class="node-outline"/>
119<rect fill="none" x="404.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-outline"/>
120<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-5"><rect stroke="none" x="404.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
121<!-- n8 -->
122<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
123
124<rect stroke="none" x="493.77" y="-149.2" width="237" height="64.39999999999999" rx="12" ry="12" class="node-bg"/>
125<rect stroke="none" x="489" y="-153" width="245" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-6)" class="node-header"/>
126<text text-anchor="start" x="605.83" y="-133.4" font-size="12.00">v3</text>
127<use x="499.766" y="-119.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
128<g><text text-anchor="start" x="515.77" y="-110" font-size="12.00" class="label label-TRUE">Vertex</text>
129</g>
130<polyline points="493.77,-125.8 730.77,-125.8" class="node-outline"/><use x="499.766" y="-103.8" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-ERROR"/>
131
132<rect fill="none" x="493.77" y="-149.2" width="237" height="64.39999999999999" rx="12" ry="12" class="node-outline"/><g><text text-anchor="start" x="515.4" y="-94" font-size="12.00" class="label label-ERROR">outgoingTransition::invalidMultiplicity</text>
133</g>
134
135<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-6"><rect stroke="none" x="493.77" y="-149.2" width="237" height="64.39999999999999" rx="12" ry="12" class="node-bg"/></clipPath></g>
136<!-- n7&#45;&gt;n8 -->
137<g class="edge edge-TRUE">
138
139<path fill="none" d="M488.13,-45.15C507.42,-55.16 530.62,-67.65 551.73,-79.34" class="edge-line"/>
140<polygon points="549.83,-82.28 560.27,-84.08 553.23,-76.16 549.83,-82.28" class="edge-line edge-arrow"/>
141<text text-anchor="middle" x="508.37" y="-55.19" font-size="10.50">source</text>
142</g>
143<!-- n8&#45;&gt;n7 -->
144<g class="edge edge-TRUE">
145
146<path fill="none" d="M548.69,-84.82C530.15,-74.94 510.25,-64.06 492.94,-54.34" class="edge-line"/>
147<polygon points="494.83,-51.38 484.4,-49.51 491.38,-57.48 494.83,-51.38" class="edge-line edge-arrow"/>
148<text text-anchor="middle" x="469.61" y="-70.25" font-size="10.50">outgoingTransition</text>
149</g>
150<!-- n9 -->
151<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
152
153<rect stroke="none" x="506.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/>
154<rect stroke="none" x="502" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-7)" class="node-header"/>
155<text text-anchor="start" x="542.72" y="-33" font-size="12.00">t5</text>
156<use x="512.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
157<g><text text-anchor="start" x="528.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
158</g>
159<polyline points="506.16,-25.4 590.38,-25.4" class="node-outline"/>
160<rect fill="none" x="506.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-outline"/>
161<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-7"><rect stroke="none" x="506.16" y="-48.8" width="84.21999999999997" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
162<!-- n8&#45;&gt;n9 -->
163<g class="edge edge-TRUE">
164
165<path fill="none" d="M583.79,-84.82C577.32,-76.19 570.67,-66.81 564.85,-58.09" class="edge-line"/>
166<polygon points="567.9,-56.37 559.52,-49.89 562.03,-60.18 567.9,-56.37" class="edge-line edge-arrow"/>
167<text text-anchor="middle" x="617.13" y="-69.99" font-size="10.50">outgoingTransition</text>
168</g>
169<!-- n10 -->
170<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
171
172<rect stroke="none" x="608.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-bg"/>
173<rect stroke="none" x="604" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-8)" class="node-header"/>
174<text text-anchor="start" x="644.72" y="-33" font-size="12.00">t6</text>
175<use x="614.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
176<g><text text-anchor="start" x="630.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
177</g>
178<polyline points="608.16,-25.4 692.38,-25.4" class="node-outline"/>
179<rect fill="none" x="608.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-outline"/>
180<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-8"><rect stroke="none" x="608.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
181<!-- n8&#45;&gt;n10 -->
182<g class="edge edge-TRUE">
183
184<path fill="none" d="M618.89,-84.82C622.03,-76.47 625.8,-67.41 629.66,-58.94" class="edge-line"/>
185<polygon points="632.78,-60.52 633.9,-49.99 626.45,-57.53 632.78,-60.52" class="edge-line edge-arrow"/>
186<text text-anchor="middle" x="579.94" y="-57.16" font-size="10.50">outgoingTransition</text>
187</g>
188<!-- n11 -->
189<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
190
191<rect stroke="none" x="710.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-bg"/>
192<rect stroke="none" x="706" y="-52" width="92" height="27" clip-path="url(#refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-9)" class="node-header"/>
193<text text-anchor="start" x="746.72" y="-33" font-size="12.00">t7</text>
194<use x="716.156" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-MZ1i4PkeOsY_2x7-6CJ29-icon-TRUE"/>
195<g><text text-anchor="start" x="732.16" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
196</g>
197<polyline points="710.16,-25.4 794.38,-25.4" class="node-outline"/>
198<rect fill="none" x="710.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-outline"/>
199<clipPath id="refinery-MZ1i4PkeOsY_2x7-6CJ29-clip-9"><rect stroke="none" x="710.16" y="-48.8" width="84.22000000000003" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
200<!-- n8&#45;&gt;n11 -->
201<g class="edge edge-TRUE">
202
203<path fill="none" d="M654,-84.82C668.76,-74.99 685.52,-64.17 700.97,-54.48" class="edge-line"/>
204<polygon points="702.47,-57.67 709.12,-49.42 698.78,-51.73 702.47,-57.67" class="edge-line edge-arrow"/>
205<text text-anchor="middle" x="728.4" y="-57.01" font-size="10.50">outgoingTransition</text>
206</g>
207<!-- n9&#45;&gt;n8 -->
208<g class="edge edge-TRUE">
209
210<path fill="none" d="M570.65,-48.62C577.04,-56.79 583.96,-66.23 590.31,-75.41" class="edge-line"/>
211<polygon points="587.33,-77.25 595.84,-83.57 593.13,-73.33 587.33,-77.25" class="edge-line edge-arrow"/>
212<text text-anchor="middle" x="567.43" y="-69.5" font-size="10.50">source</text>
213</g>
214<!-- n10&#45;&gt;n8 -->
215<g class="edge edge-TRUE">
216
217<path fill="none" d="M646.51,-48.62C643.79,-56.54 640.22,-65.64 636.38,-74.54" class="edge-line"/>
218<polygon points="633.29,-72.88 632.41,-83.44 639.68,-75.73 633.29,-72.88" class="edge-line edge-arrow"/>
219<text text-anchor="middle" x="656.03" y="-57.56" font-size="10.50">source</text>
220</g>
221<!-- n11&#45;&gt;n8 -->
222<g class="edge edge-TRUE">
223
224<path fill="none" d="M722.36,-48.62C708.84,-57.83 692.35,-68.64 676.28,-78.88" class="edge-line"/>
225<polygon points="674.75,-75.7 668.17,-84.01 678.5,-81.62 674.75,-75.7" class="edge-line edge-arrow"/>
226<text text-anchor="middle" x="711.22" y="-70.14" font-size="10.50">source</text>
227</g>
228</g>
229</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/NewObjectsSimple.svg b/subprojects/docs/src/learn/language/classes/NewObjectsSimple.svg
new file mode 100644
index 00000000..95ba8def
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/NewObjectsSimple.svg
@@ -0,0 +1,29 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="172pt" height="57pt" viewBox="-6 -6 184.24000549316406 68.79999923706055" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-8UTvxM6Gq4184FIveUdov"><style>.refinery-8UTvxM6Gq4184FIveUdov .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .node .node-outline{stroke:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .node .node-header{fill:rgb(53, 161, 173);}.refinery-8UTvxM6Gq4184FIveUdov .node .node-bg{fill:#fff;}.refinery-8UTvxM6Gq4184FIveUdov .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-8UTvxM6Gq4184FIveUdov .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-8UTvxM6Gq4184FIveUdov .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-h .node-header{fill:#e06c75;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-i .node-header{fill:#98c379;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-j .node-header{fill:#c678dd;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-n .node-header{fill:#abcc94;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-8UTvxM6Gq4184FIveUdov .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .edge .edge-line{stroke:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .edge .edge-arrow{fill:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN text{fill:#696c77;}.refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR text{fill:#ca1243;}.refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-8UTvxM6Gq4184FIveUdov .icon-TRUE{fill:#19202b;}.refinery-8UTvxM6Gq4184FIveUdov .icon-UNKNOWN{fill:#696c77;}.refinery-8UTvxM6Gq4184FIveUdov .icon-ERROR{fill:#ca1243;}.refinery-8UTvxM6Gq4184FIveUdov text.label-UNKNOWN{fill:#696c77;}.refinery-8UTvxM6Gq4184FIveUdov text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-8UTvxM6Gq4184FIveUdov text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-8UTvxM6Gq4184FIveUdov-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-8UTvxM6Gq4184FIveUdov-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-8UTvxM6Gq4184FIveUdov-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 52.79999923706055)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-k"><rect stroke="none" x="5.5" y="-42.5" width="79" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="0" y="-48.8" width="78.19" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-4" y="-52" width="86" height="27" clip-path="url(#refinery-8UTvxM6Gq4184FIveUdov-clip-0)" class="node-header"/>
9<text text-anchor="start" x="5" y="-33" font-size="12.00">Region::new</text>
10<use x="6" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-8UTvxM6Gq4184FIveUdov-icon-TRUE"/>
11<g><text text-anchor="start" x="22" y="-9.6" font-size="12.00" class="label label-TRUE">Region</text>
12</g>
13<polyline points="0,-25.4 78.19,-25.4" class="node-outline"/>
14<rect fill="none" x="0" y="-48.8" width="78.19" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-8UTvxM6Gq4184FIveUdov-clip-0"><rect stroke="none" x="0" y="-48.8" width="78.19" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n2 -->
17
18<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-h"><rect stroke="none" x="100.5" y="-42.5" width="69" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
19
20<rect stroke="none" x="95.95" y="-48.8" width="68.29" height="48.8" rx="12" ry="12" class="node-bg"/>
21<rect stroke="none" x="91" y="-52" width="76" height="27" clip-path="url(#refinery-8UTvxM6Gq4184FIveUdov-clip-1)" class="node-header"/>
22<text text-anchor="start" x="100.95" y="-33" font-size="12.00">State::new</text>
23
24
25
26
27<use x="101.954" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-8UTvxM6Gq4184FIveUdov-icon-TRUE"/><g><text text-anchor="start" x="117.95" y="-9.6" font-size="12.00" class="label label-TRUE">State</text>
28</g><polyline points="95.95,-25.4 164.24,-25.4" class="node-outline"/><rect fill="none" x="95.95" y="-48.8" width="68.29" height="48.8" rx="12" ry="12" class="node-outline"/><clipPath id="refinery-8UTvxM6Gq4184FIveUdov-clip-1"><rect stroke="none" x="95.95" y="-48.8" width="68.29" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g></g>
29</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/NewObjectsWithInheritance.svg b/subprojects/docs/src/learn/language/classes/NewObjectsWithInheritance.svg
new file mode 100644
index 00000000..cdf365f0
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/NewObjectsWithInheritance.svg
@@ -0,0 +1,38 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="230pt" height="104pt" viewBox="-6 -6 242.10000610351562 116.4000015258789" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-snWM44tZVFiopoyqQzHDw"><style>.refinery-snWM44tZVFiopoyqQzHDw .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .node .node-outline{stroke:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .node .node-header{fill:rgb(53, 161, 173);}.refinery-snWM44tZVFiopoyqQzHDw .node .node-bg{fill:#fff;}.refinery-snWM44tZVFiopoyqQzHDw .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-snWM44tZVFiopoyqQzHDw .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-snWM44tZVFiopoyqQzHDw .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-h .node-header{fill:#e06c75;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-i .node-header{fill:#98c379;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-j .node-header{fill:#c678dd;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-n .node-header{fill:#abcc94;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-snWM44tZVFiopoyqQzHDw .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .edge .edge-line{stroke:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .edge .edge-arrow{fill:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN text{fill:#696c77;}.refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR text{fill:#ca1243;}.refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-snWM44tZVFiopoyqQzHDw .icon-TRUE{fill:#19202b;}.refinery-snWM44tZVFiopoyqQzHDw .icon-UNKNOWN{fill:#696c77;}.refinery-snWM44tZVFiopoyqQzHDw .icon-ERROR{fill:#ca1243;}.refinery-snWM44tZVFiopoyqQzHDw text.label-UNKNOWN{fill:#696c77;}.refinery-snWM44tZVFiopoyqQzHDw text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-snWM44tZVFiopoyqQzHDw text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-snWM44tZVFiopoyqQzHDw-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-snWM44tZVFiopoyqQzHDw-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 100.4000015258789)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-k"><rect stroke="none" x="5.5" y="-66.5" width="79" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="0" y="-72.6" width="78.19" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-4" y="-76" width="86" height="27" clip-path="url(#refinery-snWM44tZVFiopoyqQzHDw-clip-0)" class="node-header"/>
9<text text-anchor="start" x="5" y="-56.8" font-size="12.00">Region::new</text>
10<use x="6" y="-43" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE"/>
11<g><text text-anchor="start" x="22" y="-33.4" font-size="12.00" class="label label-TRUE">Region</text>
12</g>
13<polyline points="0,-49.2 78.19,-49.2" class="node-outline"/>
14<rect fill="none" x="0" y="-72.6" width="78.19" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-snWM44tZVFiopoyqQzHDw-clip-0"><rect stroke="none" x="0" y="-72.6" width="78.19" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n1 -->
17<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-h"><rect stroke="none" x="101.5" y="-90.5" width="127" height="97" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
18
19<rect stroke="none" x="96.1" y="-96.4" width="126" height="96.4" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="92" y="-100" width="134" height="27" clip-path="url(#refinery-snWM44tZVFiopoyqQzHDw-clip-1)" class="node-header"/>
21<text text-anchor="start" x="129.95" y="-80.6" font-size="12.00">State::new</text>
22<use x="102.096" y="-67" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE"/>
23<g><text text-anchor="start" x="118.01" y="-58.2" font-style="italic" font-size="12.00" class="label label-TRUE">CompositeElement</text>
24</g>
25<use x="102.096" y="-51" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE"/>
26<g><text text-anchor="start" x="118.1" y="-42.2" font-style="italic" font-size="12.00" class="label label-TRUE">Vertex</text>
27</g>
28<use x="102.096" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE"/>
29<g><text text-anchor="start" x="118.1" y="-26.2" font-style="italic" font-size="12.00" class="label label-TRUE">RegularState</text>
30</g>
31<use x="102.096" y="-19" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-snWM44tZVFiopoyqQzHDw-icon-TRUE"/>
32<g><text text-anchor="start" x="118.1" y="-9.2" font-size="12.00" class="label label-TRUE">State</text>
33</g>
34<polyline points="96.1,-73 222.1,-73" class="node-outline"/>
35<rect fill="none" x="96.1" y="-96.4" width="126" height="96.4" rx="12" ry="12" class="node-outline"/>
36<clipPath id="refinery-snWM44tZVFiopoyqQzHDw-clip-1"><rect stroke="none" x="96.1" y="-96.4" width="126" height="96.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
37</g>
38</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/ReferencesOppositeInstance.svg b/subprojects/docs/src/learn/language/classes/ReferencesOppositeInstance.svg
new file mode 100644
index 00000000..56a4d956
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/ReferencesOppositeInstance.svg
@@ -0,0 +1,69 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="236pt" height="142pt" viewBox="-6 -6 247.8800048828125 153.60000610351562" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-aUMOWvqBGMJmEq5FBgfQD"><style>.refinery-aUMOWvqBGMJmEq5FBgfQD .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-outline{stroke:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-header{fill:rgb(53, 161, 173);}.refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-bg{fill:#fff;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-h .node-header{fill:#e06c75;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-i .node-header{fill:#98c379;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-j .node-header{fill:#c678dd;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-n .node-header{fill:#abcc94;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge .edge-line{stroke:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge .edge-arrow{fill:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN text{fill:#696c77;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR text{fill:#ca1243;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-aUMOWvqBGMJmEq5FBgfQD .icon-TRUE{fill:#19202b;}.refinery-aUMOWvqBGMJmEq5FBgfQD .icon-UNKNOWN{fill:#696c77;}.refinery-aUMOWvqBGMJmEq5FBgfQD .icon-ERROR{fill:#ca1243;}.refinery-aUMOWvqBGMJmEq5FBgfQD text.label-UNKNOWN{fill:#696c77;}.refinery-aUMOWvqBGMJmEq5FBgfQD text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-aUMOWvqBGMJmEq5FBgfQD text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-aUMOWvqBGMJmEq5FBgfQD-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-aUMOWvqBGMJmEq5FBgfQD-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-aUMOWvqBGMJmEq5FBgfQD-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 137.60000610351562)">
4<!-- n0 -->
5
6<!-- n1 -->
7
8<!-- n1&#45;&gt;n0 -->
9<!-- n1&#45;&gt;n0 -->
10
11<!-- n1&#45;&gt;n0 -->
12
13<!-- n1&#45;&gt;n0 -->
14
15
16<!-- n3 -->
17<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
18
19<rect stroke="none" x="46.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="42" y="-137" width="72" height="27" clip-path="url(#refinery-aUMOWvqBGMJmEq5FBgfQD-clip-0)" class="node-header"/>
21<text text-anchor="start" x="72.39" y="-117.8" font-size="12.00">v1</text>
22<use x="52.8135" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-aUMOWvqBGMJmEq5FBgfQD-icon-TRUE"/>
23<g><text text-anchor="start" x="68.81" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
24</g>
25<polyline points="46.81,-110.2 110.84,-110.2" class="node-outline"/>
26<rect fill="none" x="46.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-outline"/>
27<clipPath id="refinery-aUMOWvqBGMJmEq5FBgfQD-clip-0"><rect stroke="none" x="46.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
28<g class="edge edge-TRUE">
29
30<path fill="none" d="M114.46,-48.63C110.99,-56.83 106.51,-66.22 101.86,-75.08" class="edge-line"/>
31<polygon points="98.81,-73.35 97.1,-83.81 104.96,-76.7 98.81,-73.35" class="edge-line edge-arrow"/>
32<text text-anchor="middle" x="89.45" y="-70.24" font-size="10.50">source</text>
33</g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
34
35<rect stroke="none" x="128.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/>
36<rect stroke="none" x="124" y="-137" width="72" height="27" clip-path="url(#refinery-aUMOWvqBGMJmEq5FBgfQD-clip-1)" class="node-header"/>
37<text text-anchor="start" x="154.39" y="-117.8" font-size="12.00">v2</text>
38<use x="134.814" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-aUMOWvqBGMJmEq5FBgfQD-icon-TRUE"/>
39<g><text text-anchor="start" x="150.81" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
40</g>
41<polyline points="128.81,-110.2 192.84,-110.2" class="node-outline"/>
42<rect fill="none" x="128.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-outline"/>
43<clipPath id="refinery-aUMOWvqBGMJmEq5FBgfQD-clip-1"><rect stroke="none" x="128.81" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
44
45<rect stroke="none" x="77.72" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/>
46<rect stroke="none" x="73" y="-52" width="92" height="27" clip-path="url(#refinery-aUMOWvqBGMJmEq5FBgfQD-clip-2)" class="node-header"/>
47<text text-anchor="start" x="114.28" y="-33" font-size="12.00">t1</text>
48<use x="83.7178" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-aUMOWvqBGMJmEq5FBgfQD-icon-TRUE"/>
49<g><text text-anchor="start" x="99.72" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
50</g>
51<polyline points="77.72,-25.4 161.94,-25.4" class="node-outline"/>
52<rect fill="none" x="77.72" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-outline"/>
53<clipPath id="refinery-aUMOWvqBGMJmEq5FBgfQD-clip-2"><rect stroke="none" x="77.72" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="edge edge-TRUE">
54
55<path fill="none" d="M84.13,-85.14C87.58,-76.95 92.06,-67.57 96.71,-58.7" class="edge-line"/>
56<polygon points="99.76,-60.41 101.47,-49.96 93.61,-57.06 99.76,-60.41" class="edge-line edge-arrow"/>
57<text text-anchor="middle" x="46.32" y="-57.24" font-size="10.50">outgoingTransition</text>
58</g><g class="edge edge-TRUE">
59
60<path fill="none" d="M137.47,-48.63C142.07,-56.74 146.83,-66.01 150.92,-74.79" class="edge-line"/>
61<polygon points="147.65,-76.04 154.91,-83.75 154.04,-73.19 147.65,-76.04" class="edge-line edge-arrow"/>
62<text text-anchor="middle" x="132.53" y="-57.44" font-size="10.50">target</text>
63</g><g class="edge edge-TRUE">
64
65<path fill="none" d="M143.28,-85.14C138.68,-77.04 133.92,-67.77 129.82,-58.99" class="edge-line"/>
66<polygon points="133.08,-57.72 125.81,-50.01 126.69,-60.57 133.08,-57.72" class="edge-line edge-arrow"/>
67<text text-anchor="middle" x="180.75" y="-70.04" font-size="10.50">incomingTransition</text>
68</g></g>
69</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/ReferencesOppositeSelf.svg b/subprojects/docs/src/learn/language/classes/ReferencesOppositeSelf.svg
new file mode 100644
index 00000000..81ab4a0c
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/ReferencesOppositeSelf.svg
@@ -0,0 +1,24 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="117pt" height="57pt" viewBox="-6 -6 128.5 68.79999923706055" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-4mmABsPwhJURILrHpcKRU"><style>.refinery-4mmABsPwhJURILrHpcKRU .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .node .node-outline{stroke:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .node .node-header{fill:rgb(53, 161, 173);}.refinery-4mmABsPwhJURILrHpcKRU .node .node-bg{fill:#fff;}.refinery-4mmABsPwhJURILrHpcKRU .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-4mmABsPwhJURILrHpcKRU .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-4mmABsPwhJURILrHpcKRU .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-h .node-header{fill:#e06c75;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-i .node-header{fill:#98c379;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-j .node-header{fill:#c678dd;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-n .node-header{fill:#abcc94;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-4mmABsPwhJURILrHpcKRU .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .edge .edge-line{stroke:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .edge .edge-arrow{fill:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN text{fill:#696c77;}.refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR text{fill:#ca1243;}.refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-4mmABsPwhJURILrHpcKRU .icon-TRUE{fill:#19202b;}.refinery-4mmABsPwhJURILrHpcKRU .icon-UNKNOWN{fill:#696c77;}.refinery-4mmABsPwhJURILrHpcKRU .icon-ERROR{fill:#ca1243;}.refinery-4mmABsPwhJURILrHpcKRU text.label-UNKNOWN{fill:#696c77;}.refinery-4mmABsPwhJURILrHpcKRU text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-4mmABsPwhJURILrHpcKRU text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-4mmABsPwhJURILrHpcKRU-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-4mmABsPwhJURILrHpcKRU-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-4mmABsPwhJURILrHpcKRU-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 52.79999923706055)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-p"><rect stroke="none" x="5.5" y="-42.5" width="80" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="0" y="-48.8" width="79.01" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-4" y="-52" width="87" height="27" clip-path="url(#refinery-4mmABsPwhJURILrHpcKRU-clip-0)" class="node-header"/>
9<text text-anchor="start" x="5" y="-33" font-size="12.00">Person::new</text>
10<use x="6" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-4mmABsPwhJURILrHpcKRU-icon-TRUE"/>
11<g><text text-anchor="start" x="22" y="-9.6" font-size="12.00" class="label label-TRUE">Person</text>
12</g>
13<polyline points="0,-25.4 79.01,-25.4" class="node-outline"/>
14<rect fill="none" x="0" y="-48.8" width="79.01" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-4mmABsPwhJURILrHpcKRU-clip-0"><rect stroke="none" x="0" y="-48.8" width="79.01" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n0&#45;&gt;n0 -->
17<g class="edge edge-UNKNOWN">
18
19<path fill="none" stroke-dasharray="5,2" d="M78.75,-33.47C89.14,-32.95 97.01,-29.93 97.01,-24.4 97.01,-21.12 94.24,-18.72 89.81,-17.2" class="edge-line"/>
20<polygon points="90.68,-13.8 80.24,-15.58 89.52,-20.7 90.68,-13.8" class="edge-line edge-arrow"/>
21<text text-anchor="middle" x="93.87" y="-36.59" font-size="10.50">friend</text>
22</g>
23</g>
24</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/ReferencesSimple.svg b/subprojects/docs/src/learn/language/classes/ReferencesSimple.svg
new file mode 100644
index 00000000..fac74815
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/ReferencesSimple.svg
@@ -0,0 +1,43 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="104pt" height="142pt" viewBox="-6 -6 116.04000091552734 153.60000610351562" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-KS4S5srdaYqLoF1P1dM89"><style>.refinery-KS4S5srdaYqLoF1P1dM89 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .node .node-outline{stroke:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .node .node-header{fill:rgb(53, 161, 173);}.refinery-KS4S5srdaYqLoF1P1dM89 .node .node-bg{fill:#fff;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-h .node-header{fill:#e06c75;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-i .node-header{fill:#98c379;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-j .node-header{fill:#c678dd;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-n .node-header{fill:#abcc94;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge .edge-line{stroke:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge .edge-arrow{fill:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN text{fill:#696c77;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR text{fill:#ca1243;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-KS4S5srdaYqLoF1P1dM89 .icon-TRUE{fill:#19202b;}.refinery-KS4S5srdaYqLoF1P1dM89 .icon-UNKNOWN{fill:#696c77;}.refinery-KS4S5srdaYqLoF1P1dM89 .icon-ERROR{fill:#ca1243;}.refinery-KS4S5srdaYqLoF1P1dM89 text.label-UNKNOWN{fill:#696c77;}.refinery-KS4S5srdaYqLoF1P1dM89 text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-KS4S5srdaYqLoF1P1dM89 text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-KS4S5srdaYqLoF1P1dM89-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-KS4S5srdaYqLoF1P1dM89-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-KS4S5srdaYqLoF1P1dM89-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 137.60000610351562)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-h"><rect stroke="none" x="15.5" y="-42.5" width="76" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="10.1" y="-48.8" width="75.84" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="6" y="-52" width="83" height="27" clip-path="url(#refinery-KS4S5srdaYqLoF1P1dM89-clip-0)" class="node-header"/>
9<text text-anchor="start" x="15.1" y="-33" font-size="12.00">Vertex::new</text>
10<use x="16.0957" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-KS4S5srdaYqLoF1P1dM89-icon-TRUE"/>
11<g><text text-anchor="start" x="32.1" y="-9.6" font-size="12.00" class="label label-TRUE">Vertex</text>
12</g>
13<polyline points="10.1,-25.4 85.94,-25.4" class="node-outline"/>
14<rect fill="none" x="10.1" y="-48.8" width="75.84" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-KS4S5srdaYqLoF1P1dM89-clip-0"><rect stroke="none" x="10.1" y="-48.8" width="75.84" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n1 -->
17<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-i"><rect stroke="none" x="5.5" y="-127.5" width="97" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
18
19<rect stroke="none" x="0" y="-133.6" width="96.04" height="48.8" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="-4" y="-137" width="104" height="27" clip-path="url(#refinery-KS4S5srdaYqLoF1P1dM89-clip-1)" class="node-header"/>
21<text text-anchor="start" x="5" y="-117.8" font-size="12.00">Transition::new</text>
22<use x="6" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-KS4S5srdaYqLoF1P1dM89-icon-TRUE"/>
23<g><text text-anchor="start" x="22" y="-94.4" font-size="12.00" class="label label-TRUE">Transition</text>
24</g>
25<polyline points="0,-110.2 96.04,-110.2" class="node-outline"/>
26<rect fill="none" x="0" y="-133.6" width="96.04" height="48.8" rx="12" ry="12" class="node-outline"/>
27<clipPath id="refinery-KS4S5srdaYqLoF1P1dM89-clip-1"><rect stroke="none" x="0" y="-133.6" width="96.04" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
28<!-- n1&#45;&gt;n0 -->
29<g class="edge edge-UNKNOWN">
30
31<path fill="none" stroke-dasharray="5,2" d="M41.9,-85.14C41.32,-77.31 41.14,-68.38 41.35,-59.86" class="edge-line"/>
32<polygon points="44.84,-60.29 41.81,-50.14 37.85,-59.96 44.84,-60.29" class="edge-line edge-arrow"/>
33<text text-anchor="middle" x="24.78" y="-70.26" font-size="10.50">source</text>
34</g>
35<!-- n1&#45;&gt;n0 -->
36<g class="edge edge-UNKNOWN">
37
38<path fill="none" stroke-dasharray="5,2" d="M54.14,-85.14C54.71,-77.31 54.9,-68.38 54.68,-59.86" class="edge-line"/>
39<polygon points="58.19,-59.96 54.23,-50.14 51.2,-60.29 58.19,-59.96" class="edge-line edge-arrow"/>
40<text text-anchor="middle" x="40.18" y="-57.66" font-size="10.50">target</text>
41</g>
42</g>
43</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/classes/index.md b/subprojects/docs/src/learn/language/classes/index.md
new file mode 100644
index 00000000..73108039
--- /dev/null
+++ b/subprojects/docs/src/learn/language/classes/index.md
@@ -0,0 +1,212 @@
1---
2SPDX-FileCopyrightText: 2024 The Refinery Authors
3SPDX-License-Identifier: EPL-2.0
4description: Metamodeling in Refinery
5sidebar_position: 0
6---
7
8# Classes and references
9
10Refinery supports _metamodeling_ to describe the desired structure of generated models.
11
12The metamodeling facilities are inspired by object-oriented software and the [Eclipse Modeling Foundation](https://eclipse.dev/modeling/emf/) (EMF) Core, a lightweight framework for data models.
13The textual syntax in Refinery for defining metamodels is largely compatible with [Xcore](https://wiki.eclipse.org/Xcore), a textual syntax for EMF metamodels.
14
15## Classes
16
17Classes are declared with the `class` keyword.
18
19Like in many programming languages, class members are specified between curly braces `{}`.
20If a class has no members, the declaration may be terminated with a `.` instead.
21
22```refinery
23% Class with no members.
24class Region {}
25
26% Alternative syntax without curly braces.
27class State.
28```
29
30By default, a _new object_ is added to the partial model to represent the instances of a class.
31For example, the new objects `Region::new` and `State::new` represent potential instances of the classes `Region` and `State`, respectively:
32
33import NewObjectsSimple from './NewObjectsSimple.svg';
34
35<NewObjectsSimple />
36
37As you can see, no new objects represent potential nodes that are instanceof of both `Region` and `State`.
38In fact, such instances are not permitted at all.
39Each node must the instance of a _single most-specific class:_
40
41import InvalidInstance from './InvalidInstance.svg';
42
43<InvalidInstance />
44
45### Inheritance
46
47Like in object-oriented programming languages, classes may declare _superclasses_ with the `extends` keyword.
48The inheritance hierarchy may not contain any cycles (a class cannot be a superclass of itself), but _multiple inheritance_ is allowed.
49
50Classes that can't be instantiated directly (i.e., a subclass must be instantiated instead) can be marked with the `abstract` keyword.
51Such classes do not have a _new object,_ since there are no direct instances to represent.
52
53```refinery
54abstract class CompositeElement.
55class Region.
56abstract class Vertex.
57abstract class RegularState extends Vertex.
58class State extends RegularState, CompositeElement.
59```
60
61Notice that the new object `State::new` is an instance of `CompositeElement`, `Vertex`, `RegularState`, and `State` as well.
62
63import NewObjectsWithInheritance from './NewObjectsWithInheritance.svg';
64
65<NewObjectsWithInheritance />
66
67## References
68
69The graph structure of model generated by Refinery is determined by the _references_ of the metamodel, which will appear as labeled edges between nodes (class instances).
70
71References are declared as class members by providing the _target type,_ and optional _multiplicity,_ and the name of the reference:
72
73```refinery
74class Vertex.
75class Transition {
76 Vertex[1] source
77 Vertex[1] target
78}
79```
80
81import ReferencesSimple from './ReferencesSimple.svg';
82
83<ReferencesSimple />
84
85You may add the `refers` keyword for compatibility with [Xcore](https://wiki.eclipse.org/Xcore). The following specification is equivalent:
86
87```refinery
88class Vertex.
89class Transition {
90 refers Vertex[1] source
91 refers Vertex[1] target
92}
93```
94
95### Opposite constraints
96
97The `opposite` keywords specifies that two references are in an _opposite_ relationship, i.e., if one reference is present in a direction, the other must be present between the same nodes in the opposite direction.
98
99```
100class Vertex {
101 Transition[] outgoingTransition opposite source
102 Transition[] incomingTransition opposite target
103}
104class Transition {
105 Vertex[1] source opposite outgoingTransition
106 Vertex[1] target opposite incomingTransition
107}
108```
109
110import ReferencesOppositeInstance from './ReferencesOppositeInstance.svg';
111
112<ReferencesOppositeInstance />
113
114Opposites must be declared in pairs: it is a specification error to declare the `opposite` for one direction but not the other.
115
116Unlike in EMF, references that are the `opposite` of themselves are also supported.
117These must always be present in both directions between two nodes.
118Thus, they correspond to undirected graph edges.
119
120```refinery
121class Person {
122 Person[] friend opposite friend
123}
124```
125
126import ReferencesOppositeSelf from './ReferencesOppositeSelf.svg';
127
128<ReferencesOppositeSelf />
129
130### Multiplicity
131
132_Multiplicity constrains_ can be provided after the reference type in square braces.
133They specify how many _outgoing_ references should exist for any given instance of the class.
134
135:::info
136
137To control the number of _incoming_ references, add an `opposite` reference with multiplicity constraint.
138
139:::
140
141A multiplicity constraint is of the form `[n..m]`, where the non-negative integer `n` is the _lower_ bound of outgoing references,
142and `m` is a positive integer or `*` corresponding to the _upper_ bound of outgoing references.
143The value of `*` represent a reference with _unbounded_ upper multiplicity.
144
145If `n` = `m`, the shorter form `[n]` may be used.
146The bound `[0..*]` may be abbreviated as `[]`.
147If the multiplicity constraint is omitted, the bound `[0..1]` is assumed.
148
149---
150
151In the following model, the node `v1` satisfies all multiplicity constraints of `outgoingTransition`.
152The node `v2` violates the lower bound constraint, while `v3` violates the upper bound constraint.
153All `Transition` instances satisfy the multiplicity constrains associated with `source`.
154
155```refinery
156class Vertex {
157 Transition[2..3] outgoingTransition opposite source
158}
159class Transition {
160 Vertex[1] source opposite outgoingTransition
161}
162```
163
164import MultiplicityConstraintsInstance from './MultiplicityConstraintsInstance.svg';
165
166<MultiplicityConstraintsInstance />
167
168### Containment hierarchy
169
170To structure models and ensure their connectedness, Refinery supports _containment_ constraints.
171
172References may be marked as _containment_ references with the `contains` keyword.
173
174Classes that are the _target type_ of at least one _containment_ reference are considered `contained`.
175An instance of a `contained` class must have exactly 1 incoming containment reference.
176Instances of classes that are not `contained` must _not_ have any incoming containment references.
177
178Containment references have to form a _forest_, i.e., they must not contain any cycles.
179The _roots_ of the forest are instances of classes that are not `contained`, while `contained` classes for the internal nodes and leaves of the trees.
180
181Opposites of _containment_ references have to be marked with the `container` keyword.
182They must not specify any multiplicity constraint, since the multiplicity is already implied by the containment hierarchy.
183
184---
185
186In the following model, the instances of `Region` are the roots of the containment hierarchy.
187The classes `Vertex` are `Transition` are both considered `contained`.
188
189```refinery
190class Region {
191 contains Vertex[] vertices opposite region
192}
193
194class Vertex {
195 container Region region opposite vertices
196 contains Transition[] outgoingTransition opposite source
197 Transition[] incomingTransition opposite target
198}
199
200class Transition {
201 container Vertex source opposite outgoingTransition
202 Vertex[1] target opposite incomingTransition
203}
204```
205
206Containment edges are show with **thick** lines:
207
208import ContainmentInstance from './ContainmentInstance.svg';
209
210<ContainmentInstance />
211
212Containment edges form trees, while non-containment references, such as `target`, may point across the containment hierarchy.
diff --git a/subprojects/docs/src/learn/language/logic/AssertionsError.svg b/subprojects/docs/src/learn/language/logic/AssertionsError.svg
new file mode 100644
index 00000000..8ddc65f3
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/AssertionsError.svg
@@ -0,0 +1,20 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="72pt" height="72pt" viewBox="-6 -6 84 84.4000015258789" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-t1ihtn3yDar9Rl2Fph8SJ"><style>.refinery-t1ihtn3yDar9Rl2Fph8SJ .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-outline{stroke:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-header{fill:rgb(53, 161, 173);}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-bg{fill:#fff;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-h .node-header{fill:#e06c75;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-i .node-header{fill:#98c379;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-j .node-header{fill:#c678dd;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-n .node-header{fill:#abcc94;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge .edge-line{stroke:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge .edge-arrow{fill:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN text{fill:#696c77;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR text{fill:#ca1243;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-TRUE{fill:#19202b;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-UNKNOWN{fill:#696c77;}.refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-ERROR{fill:#ca1243;}.refinery-t1ihtn3yDar9Rl2Fph8SJ text.label-UNKNOWN{fill:#696c77;}.refinery-t1ihtn3yDar9Rl2Fph8SJ text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-t1ihtn3yDar9Rl2Fph8SJ text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-t1ihtn3yDar9Rl2Fph8SJ-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-t1ihtn3yDar9Rl2Fph8SJ-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-t1ihtn3yDar9Rl2Fph8SJ-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 68.4000015258789)">
4<!-- n3 -->
5<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE">
6
7<rect stroke="none" x="0" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-4" y="-68" width="72" height="27" clip-path="url(#refinery-t1ihtn3yDar9Rl2Fph8SJ-clip-0)" class="node-header"/>
9<text text-anchor="start" x="25.56" y="-48.6" font-size="12.00">v1</text>
10
11
12<use x="6" y="-35" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-t1ihtn3yDar9Rl2Fph8SJ-icon-ERROR"/>
13<g><text text-anchor="start" x="21.99" y="-25.2" font-size="12.00" class="label label-ERROR">Vertex</text>
14</g>
15<use x="6" y="-19" width="12" height="12" id="" class="icon icon-ERROR" href="#refinery-t1ihtn3yDar9Rl2Fph8SJ-icon-ERROR"/>
16<g><text text-anchor="start" x="22" y="-9.2" font-size="12.00" class="label label-ERROR">State</text>
17</g>
18<polyline points="0,-41 64,-41" class="node-outline"/><rect fill="none" x="0" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-outline"/><clipPath id="refinery-t1ihtn3yDar9Rl2Fph8SJ-clip-0"><rect stroke="none" x="0" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
19</g>
20</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/AssertionsExample.svg b/subprojects/docs/src/learn/language/logic/AssertionsExample.svg
new file mode 100644
index 00000000..26b3d1ff
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/AssertionsExample.svg
@@ -0,0 +1,99 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="250pt" height="157pt" viewBox="-6 -6 262.17999267578125 169.1999969482422" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-yow0X_ZN3HQDi30KE0Sac"><style>.refinery-yow0X_ZN3HQDi30KE0Sac .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .node .node-outline{stroke:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .node .node-header{fill:rgb(53, 161, 173);}.refinery-yow0X_ZN3HQDi30KE0Sac .node .node-bg{fill:#fff;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-h .node-header{fill:#e06c75;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-i .node-header{fill:#98c379;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-j .node-header{fill:#c678dd;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-n .node-header{fill:#abcc94;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge .edge-line{stroke:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge .edge-arrow{fill:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN text{fill:#696c77;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR text{fill:#ca1243;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-yow0X_ZN3HQDi30KE0Sac .icon-TRUE{fill:#19202b;}.refinery-yow0X_ZN3HQDi30KE0Sac .icon-UNKNOWN{fill:#696c77;}.refinery-yow0X_ZN3HQDi30KE0Sac .icon-ERROR{fill:#ca1243;}.refinery-yow0X_ZN3HQDi30KE0Sac text.label-UNKNOWN{fill:#696c77;}.refinery-yow0X_ZN3HQDi30KE0Sac text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-yow0X_ZN3HQDi30KE0Sac text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-yow0X_ZN3HQDi30KE0Sac-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-yow0X_ZN3HQDi30KE0Sac-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 153.1999969482422)">
4<!-- n3 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-k"><rect stroke="none" x="6.5" y="-143.5" width="79" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="1.07" y="-149.2" width="78.19000000000001" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-3" y="-153" width="86" height="27" clip-path="url(#refinery-yow0X_ZN3HQDi30KE0Sac-clip-0)" class="node-header"/>
9<text text-anchor="start" x="6.07" y="-133.4" font-size="12.00">Region::new</text>
10<use x="7.07291" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
11<g><text text-anchor="start" x="23.07" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
12</g>
13<polyline points="1.07,-125.8 79.26,-125.8" class="node-outline"/>
14<rect fill="none" x="1.07" y="-149.2" width="78.19000000000001" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-yow0X_ZN3HQDi30KE0Sac-clip-0"><rect stroke="none" x="1.07" y="-149.2" width="78.19000000000001" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n4 -->
17<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-j"><rect stroke="none" x="14.5" y="-58.5" width="69" height="65" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
18
19<rect stroke="none" x="9.03" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="5" y="-68" width="76" height="27" clip-path="url(#refinery-yow0X_ZN3HQDi30KE0Sac-clip-1)" class="node-header"/>
21<text text-anchor="start" x="14.03" y="-48.6" font-size="12.00">State::new</text>
22<use x="15.027" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
23<g><text text-anchor="start" x="31.01" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
24</g>
25<use x="15.027" y="-19" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
26<g><text text-anchor="start" x="31.03" y="-9.2" font-size="12.00" class="label label-TRUE">State</text>
27</g>
28<polyline points="9.03,-41 77.31,-41" class="node-outline"/>
29<rect fill="none" x="9.03" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-outline"/>
30<clipPath id="refinery-yow0X_ZN3HQDi30KE0Sac-clip-1"><rect stroke="none" x="9.03" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
31<!-- n3&#45;&gt;n4 -->
32<g class="edge edge-UNKNOWN">
33
34<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M40.94,-100.47C41.19,-92.98 41.47,-84.45 41.75,-76.02" class="edge-line"/>
35<polygon stroke-width="2" points="44.81,-76.18 42.04,-67.34 38.69,-75.98 44.81,-76.18" class="edge-line edge-arrow"/>
36<text text-anchor="start" x="0" y="-86.89" font-weight="bold" font-size="10.50">vertices</text>
37</g>
38<!-- n8 -->
39<!-- n4 -->
40<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
41
42<rect stroke="none" x="96.17" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-bg"/>
43<rect stroke="none" x="92" y="-68" width="71" height="27" clip-path="url(#refinery-yow0X_ZN3HQDi30KE0Sac-clip-2)" class="node-header"/>
44<text text-anchor="start" x="121.73" y="-48.6" font-size="12.00">v1</text>
45<use x="102.169" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
46<g><text text-anchor="start" x="118.15" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
47</g>
48<use x="102.169" y="-19" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-UNKNOWN"/>
49<g><text text-anchor="start" x="118.17" y="-9.2" font-size="12.00" class="label label-UNKNOWN">State</text>
50</g>
51<polyline points="96.17,-41 160.17,-41" class="node-outline"/>
52<rect fill="none" x="96.17" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-outline"/>
53<clipPath id="refinery-yow0X_ZN3HQDi30KE0Sac-clip-2"><rect stroke="none" x="96.17" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g><!-- n0&#45;&gt;n3 -->
54<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
55
56<rect stroke="none" x="96.98" y="-149.2" width="66.38000000000001" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
57<rect stroke="none" x="92" y="-153" width="74" height="27" clip-path="url(#refinery-yow0X_ZN3HQDi30KE0Sac-clip-3)" class="node-header"/>
58<text text-anchor="start" x="124.29" y="-133.4" font-size="12.00">r1</text>
59<use x="102.982" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
60<g><text text-anchor="start" x="118.98" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
61</g>
62<polyline points="96.98,-125.8 163.36,-125.8" class="node-outline"/>
63<rect fill="none" x="96.98" y="-149.2" width="66.38000000000001" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
64<clipPath id="refinery-yow0X_ZN3HQDi30KE0Sac-clip-3"><rect stroke="none" x="96.98" y="-149.2" width="66.38000000000001" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
65
66<rect stroke="none" x="178.15" y="-56.6" width="64.03" height="48.800000000000004" rx="12" ry="12" class="node-bg"/>
67<rect stroke="none" x="174" y="-60" width="72" height="27" clip-path="url(#refinery-yow0X_ZN3HQDi30KE0Sac-clip-4)" class="node-header"/>
68<text text-anchor="start" x="203.73" y="-40.8" font-size="12.00">v2</text>
69<use x="184.154" y="-27" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-yow0X_ZN3HQDi30KE0Sac-icon-TRUE"/>
70<g><text text-anchor="start" x="200.15" y="-17.4" font-size="12.00" class="label label-TRUE">Vertex</text>
71</g>
72
73
74<polyline points="178.15,-33.2 242.18,-33.2" class="node-outline"/><rect fill="none" x="178.15" y="-56.6" width="64.03" height="48.800000000000004" rx="12" ry="12" class="node-outline"/><clipPath id="refinery-yow0X_ZN3HQDi30KE0Sac-clip-4"><rect stroke="none" x="178.15" y="-56.6" width="64.03" height="48.800000000000004" rx="12" ry="12" class="node-bg"/></clipPath></g>
75<g class="edge edge-UNKNOWN">
76
77<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M107.76,-100.47C99.59,-91.95 90.1,-82.07 80.95,-72.55" class="edge-line"/>
78<polygon stroke-width="2" points="83.41,-70.68 75.14,-66.49 78.99,-74.93 83.41,-70.68" class="edge-line edge-arrow"/>
79<text text-anchor="start" x="48.91" y="-86.57" font-weight="bold" font-size="10.50">vertices</text>
80</g>
81<!-- n2&#45;&gt;n0 -->
82
83<!-- n3&#45;&gt;n0 -->
84
85<!-- n3&#45;&gt;n4 -->
86
87<g class="edge edge-TRUE">
88
89<path fill="none" stroke-width="2" d="M129.65,-100.47C129.49,-92.98 129.3,-84.45 129.11,-76.02" class="edge-line"/>
90<polygon stroke-width="2" points="132.18,-76.02 128.92,-67.34 126.05,-76.15 132.18,-76.02" class="edge-line edge-arrow"/>
91<text text-anchor="start" x="129.26" y="-86.89" font-weight="bold" font-size="10.50">vertices</text>
92</g>
93<g class="edge edge-TRUE">
94
95<path fill="none" stroke-width="2" d="M150.77,-100.47C160.29,-89.69 171.74,-76.72 182.04,-65.06" class="edge-line"/>
96<polygon stroke-width="2" points="184.14,-67.31 187.63,-58.72 179.55,-63.25 184.14,-67.31" class="edge-line edge-arrow"/>
97<text text-anchor="start" x="128.85" y="-69.81" font-weight="bold" font-size="10.50">vertices</text>
98</g></g>
99</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/DefaultAssertions.svg b/subprojects/docs/src/learn/language/logic/DefaultAssertions.svg
new file mode 100644
index 00000000..2ab002bf
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/DefaultAssertions.svg
@@ -0,0 +1,129 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="327pt" height="157pt" viewBox="-6 -6 339.3299865722656 169.1999969482422" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-p_2c2ycZZXd-I3Xg-BBah"><style>.refinery-p_2c2ycZZXd-I3Xg-BBah .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-outline{stroke:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-header{fill:rgb(53, 161, 173);}.refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-bg{fill:#fff;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-h .node-header{fill:#e06c75;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-i .node-header{fill:#98c379;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-j .node-header{fill:#c678dd;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-n .node-header{fill:#abcc94;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge .edge-line{stroke:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge .edge-arrow{fill:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN text{fill:#696c77;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR text{fill:#ca1243;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-p_2c2ycZZXd-I3Xg-BBah .icon-TRUE{fill:#19202b;}.refinery-p_2c2ycZZXd-I3Xg-BBah .icon-UNKNOWN{fill:#696c77;}.refinery-p_2c2ycZZXd-I3Xg-BBah .icon-ERROR{fill:#ca1243;}.refinery-p_2c2ycZZXd-I3Xg-BBah text.label-UNKNOWN{fill:#696c77;}.refinery-p_2c2ycZZXd-I3Xg-BBah text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-p_2c2ycZZXd-I3Xg-BBah text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-p_2c2ycZZXd-I3Xg-BBah-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-p_2c2ycZZXd-I3Xg-BBah-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="scale(1 1) rotate(0) translate(4 153.2)">
4<!-- n0 -->
5
6<!-- n2 -->
7<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-j"><rect stroke="none" x="5.5" y="-58.5" width="69" height="65" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
8
9<rect stroke="none" x="0" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-bg"/>
10<rect stroke="none" x="-4" y="-68" width="76" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-0)" class="node-header"/>
11<text text-anchor="start" x="5" y="-48.6" font-size="12.00">State::new</text>
12<use x="6" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
13<g><text text-anchor="start" x="21.99" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
14</g>
15<use x="6" y="-19" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
16<g><text text-anchor="start" x="22" y="-9.2" font-size="12.00" class="label label-TRUE">State</text>
17</g>
18<polyline points="0,-41 68.28,-41" class="node-outline"/>
19<rect fill="none" x="0" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-outline"/>
20<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-0"><rect stroke="none" x="0" y="-64.4" width="68.28" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
21<!-- n0&#45;&gt;n2 -->
22
23<!-- n3 -->
24<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
25
26<rect stroke="none" x="84.96" y="-149.2" width="66.37000000000002" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
27<rect stroke="none" x="80" y="-153" width="74" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-1)" class="node-header"/>
28<text text-anchor="start" x="112.26" y="-133.4" font-size="12.00">r1</text>
29<use x="90.9551" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
30<g><text text-anchor="start" x="106.96" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
31</g>
32<polyline points="84.96,-125.8 151.33,-125.8" class="node-outline"/>
33<rect fill="none" x="84.96" y="-149.2" width="66.37000000000002" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
34<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-1"><rect stroke="none" x="84.96" y="-149.2" width="66.37000000000002" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g>
35<!-- n3&#45;&gt;n2 -->
36<g class="edge edge-UNKNOWN">
37
38<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M96.51,-100.47C88.69,-92.04 79.64,-82.27 70.89,-72.83" class="edge-line"/>
39<polygon stroke-width="2" points="73.24,-70.86 65.04,-66.53 68.75,-75.03 73.24,-70.86" class="edge-line edge-arrow"/>
40<text text-anchor="start" x="38.02" y="-86.32" font-weight="bold" font-size="10.50">vertices</text>
41</g>
42<!-- n4 -->
43<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
44
45<rect stroke="none" x="86.14" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-bg"/>
46<rect stroke="none" x="82" y="-68" width="71" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-2)" class="node-header"/>
47<text text-anchor="start" x="111.71" y="-48.6" font-size="12.00">v1</text>
48<use x="92.1416" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
49<g><text text-anchor="start" x="108.13" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
50</g>
51<use x="92.1416" y="-19" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-UNKNOWN"/>
52<g><text text-anchor="start" x="108.14" y="-9.2" font-size="12.00" class="label label-UNKNOWN">State</text>
53</g>
54<polyline points="86.14,-41 150.14,-41" class="node-outline"/>
55<rect fill="none" x="86.14" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-outline"/>
56<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-2"><rect stroke="none" x="86.14" y="-64.4" width="63.999999999999986" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
57<!-- n3&#45;&gt;n4 -->
58<g class="edge edge-TRUE">
59
60<path fill="none" stroke-width="2" d="M118.14,-100.47C118.14,-92.98 118.14,-84.45 118.14,-76.02" class="edge-line"/>
61<polygon stroke-width="2" points="121.2,-76.09 118.14,-67.34 115.08,-76.09 121.2,-76.09" class="edge-line edge-arrow"/>
62<text text-anchor="start" x="118.14" y="-86.89" font-weight="bold" font-size="10.50">vertices</text>
63</g>
64<!-- n5 -->
65<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
66
67<rect stroke="none" x="168.96" y="-149.2" width="66.37" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
68<rect stroke="none" x="164" y="-153" width="74" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-3)" class="node-header"/>
69<text text-anchor="start" x="196.26" y="-133.4" font-size="12.00">r2</text>
70<use x="174.955" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
71<g><text text-anchor="start" x="190.96" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
72</g>
73<polyline points="168.96,-125.8 235.33,-125.8" class="node-outline"/>
74<rect fill="none" x="168.96" y="-149.2" width="66.37" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
75<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-3"><rect stroke="none" x="168.96" y="-149.2" width="66.37" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g>
76<!-- n6 -->
77<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
78
79<rect stroke="none" x="170.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/>
80<rect stroke="none" x="166" y="-68" width="72" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-4)" class="node-header"/>
81<text text-anchor="start" x="195.71" y="-48.6" font-size="12.00">v2</text>
82<use x="176.142" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
83<g><text text-anchor="start" x="192.13" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
84</g>
85<use x="176.142" y="-19" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-UNKNOWN"/>
86<g><text text-anchor="start" x="192.14" y="-9.2" font-size="12.00" class="label label-UNKNOWN">State</text>
87</g>
88<polyline points="170.14,-41 234.14,-41" class="node-outline"/>
89<rect fill="none" x="170.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-outline"/>
90<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-4"><rect stroke="none" x="170.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
91<!-- n5&#45;&gt;n6 -->
92<g class="edge edge-TRUE">
93
94<path fill="none" stroke-width="2" d="M202.14,-100.47C202.14,-92.98 202.14,-84.45 202.14,-76.02" class="edge-line"/>
95<polygon stroke-width="2" points="205.2,-76.09 202.14,-67.34 199.08,-76.09 205.2,-76.09" class="edge-line edge-arrow"/>
96<text text-anchor="start" x="160.61" y="-86.89" font-weight="bold" font-size="10.50">vertices</text>
97</g><g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
98
99<rect stroke="none" x="254.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/>
100<rect stroke="none" x="250" y="-68" width="72" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-5)" class="node-header"/>
101<text text-anchor="start" x="279.71" y="-48.6" font-size="12.00">v3</text>
102<use x="260.142" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
103<g><text text-anchor="start" x="276.13" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
104</g>
105<use x="260.142" y="-19" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-UNKNOWN"/>
106<g><text text-anchor="start" x="276.14" y="-9.2" font-size="12.00" class="label label-UNKNOWN">State</text>
107</g>
108<polyline points="254.14,-41 318.14,-41" class="node-outline"/>
109<rect fill="none" x="254.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-outline"/>
110<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-5"><rect stroke="none" x="254.14" y="-64.4" width="64" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g>
111<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-k">
112
113<rect stroke="none" x="252.96" y="-149.2" width="66.36999999999998" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
114<rect stroke="none" x="248" y="-153" width="74" height="27" clip-path="url(#refinery-p_2c2ycZZXd-I3Xg-BBah-clip-6)" class="node-header"/>
115<text text-anchor="start" x="280.26" y="-133.4" font-size="12.00">r3</text>
116<use x="258.955" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-p_2c2ycZZXd-I3Xg-BBah-icon-TRUE"/>
117<g><text text-anchor="start" x="274.96" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
118</g>
119<polyline points="252.96,-125.8 319.33,-125.8" class="node-outline"/>
120<rect fill="none" x="252.96" y="-149.2" width="66.36999999999998" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
121<clipPath id="refinery-p_2c2ycZZXd-I3Xg-BBah-clip-6"><rect stroke="none" x="252.96" y="-149.2" width="66.36999999999998" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g><!-- n7&#45;&gt;n8 -->
122<g class="edge edge-TRUE">
123
124<path fill="none" stroke-width="2" d="M286.14,-100.47C286.14,-92.98 286.14,-84.45 286.14,-76.02" class="edge-line"/>
125<polygon stroke-width="2" points="289.2,-76.09 286.14,-67.34 283.08,-76.09 289.2,-76.09" class="edge-line edge-arrow"/>
126<text text-anchor="start" x="244.61" y="-86.89" font-weight="bold" font-size="10.50">vertices</text>
127</g>
128</g>
129</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/MultiObjects.svg b/subprojects/docs/src/learn/language/logic/MultiObjects.svg
new file mode 100644
index 00000000..a5232575
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/MultiObjects.svg
@@ -0,0 +1,81 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="508pt" height="57pt" viewBox="-6 -6 519.5700073242188 68.79999923706055" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-meygjgDtG1kB8-FV4IATS"><style>.refinery-meygjgDtG1kB8-FV4IATS .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .node .node-outline{stroke:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .node .node-header{fill:rgb(53, 161, 173);}.refinery-meygjgDtG1kB8-FV4IATS .node .node-bg{fill:#fff;}.refinery-meygjgDtG1kB8-FV4IATS .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-meygjgDtG1kB8-FV4IATS .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-meygjgDtG1kB8-FV4IATS .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-h .node-header{fill:#e06c75;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-i .node-header{fill:#98c379;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-j .node-header{fill:#c678dd;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-n .node-header{fill:#abcc94;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-meygjgDtG1kB8-FV4IATS .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .edge .edge-line{stroke:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .edge .edge-arrow{fill:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN text{fill:#696c77;}.refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR text{fill:#ca1243;}.refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-meygjgDtG1kB8-FV4IATS .icon-TRUE{fill:#19202b;}.refinery-meygjgDtG1kB8-FV4IATS .icon-UNKNOWN{fill:#696c77;}.refinery-meygjgDtG1kB8-FV4IATS .icon-ERROR{fill:#ca1243;}.refinery-meygjgDtG1kB8-FV4IATS text.label-UNKNOWN{fill:#696c77;}.refinery-meygjgDtG1kB8-FV4IATS text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-meygjgDtG1kB8-FV4IATS text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-meygjgDtG1kB8-FV4IATS-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-meygjgDtG1kB8-FV4IATS-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-meygjgDtG1kB8-FV4IATS-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 52.79999923706055)">
4<!-- n0 -->
5<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE">
6
7<rect stroke="none" x="0" y="-48.8" width="59.74" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="-4" y="-52" width="67" height="27" clip-path="url(#refinery-meygjgDtG1kB8-FV4IATS-clip-0)" class="node-header"/>
9<text text-anchor="start" x="6.58" y="-33" font-size="12.00">node [1]</text>
10
11
12<polyline points="0,-25.4 59.74,-25.4" class="node-outline"/><use x="6" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-meygjgDtG1kB8-FV4IATS-icon-TRUE"/>
13<rect fill="none" x="0" y="-48.8" width="59.74" height="48.8" rx="12" ry="12" class="node-outline"/><g><text text-anchor="start" x="22" y="-9.6" font-size="12.00" class="label label-TRUE">exists</text>
14</g>
15<clipPath id="refinery-meygjgDtG1kB8-FV4IATS-clip-0"><rect stroke="none" x="0" y="-48.8" width="59.74" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n0&#45;&gt;n0 -->
17<g class="edge edge-TRUE">
18
19<path fill="none" d="M59.32,-33.55C69.51,-33.64 77.74,-30.6 77.74,-24.4 77.74,-20.82 74.99,-18.29 70.7,-16.81" class="edge-line"/>
20<polygon points="71.2,-13.35 60.82,-15.46 70.25,-20.28 71.2,-13.35" class="edge-line edge-arrow"/>
21<text text-anchor="middle" x="75.93" y="-36.7" font-size="10.50">equals</text>
22</g>
23<!-- n1 -->
24<g class="node node-IMPLICIT node-exists-UNKNOWN node-equalsSelf-TRUE">
25
26<rect stroke="none" x="95.38" y="-48.8" width="100.98000000000002" height="48.8" rx="12" ry="12" class="node-bg"/>
27<rect stroke="none" x="91" y="-52" width="108" height="27" clip-path="url(#refinery-meygjgDtG1kB8-FV4IATS-clip-1)" class="node-header"/>
28<text text-anchor="start" x="100.38" y="-33" font-size="12.00">removable [0..1]</text>
29
30
31<use x="101.384" y="-19.2" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-meygjgDtG1kB8-FV4IATS-icon-UNKNOWN"/>
32<g><text text-anchor="start" x="117.38" y="-9.6" font-size="12.00" class="label label-UNKNOWN">exists</text>
33</g>
34<polyline points="95.38,-25.4 196.36,-25.4" class="node-outline"/><rect fill="none" x="95.38" y="-48.8" width="100.98000000000002" height="48.8" rx="12" ry="12" class="node-outline"/><clipPath id="refinery-meygjgDtG1kB8-FV4IATS-clip-1"><rect stroke="none" x="95.38" y="-48.8" width="100.98000000000002" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
35<!-- n1&#45;&gt;n1 -->
36<g class="edge edge-TRUE">
37
38<path fill="none" d="M196.34,-33.23C206.82,-32.3 214.36,-29.36 214.36,-24.4 214.36,-21.46 211.7,-19.22 207.35,-17.7" class="edge-line"/>
39<polygon points="208.31,-14.32 197.83,-15.86 206.98,-21.2 208.31,-14.32" class="edge-line edge-arrow"/>
40<text text-anchor="middle" x="213.45" y="-36.29" font-size="10.50">equals</text>
41</g>
42<!-- n2 -->
43<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-UNKNOWN"><rect stroke="none" x="237.5" y="-42.5" width="70" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
44
45<rect stroke="none" x="232.01" y="-48.8" width="69.72000000000003" height="48.8" rx="12" ry="12" class="node-bg"/>
46<rect stroke="none" x="228" y="-52" width="77" height="27" clip-path="url(#refinery-meygjgDtG1kB8-FV4IATS-clip-2)" class="node-header"/>
47<text text-anchor="start" x="237.01" y="-33" font-size="12.00">multi [1..*]</text>
48<use x="238.011" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-meygjgDtG1kB8-FV4IATS-icon-TRUE"/>
49<g><text text-anchor="start" x="254.01" y="-9.6" font-size="12.00" class="label label-TRUE">exists</text>
50</g>
51<polyline points="232.01,-25.4 301.73,-25.4" class="node-outline"/>
52<rect fill="none" x="232.01" y="-48.8" width="69.72000000000003" height="48.8" rx="12" ry="12" class="node-outline"/>
53<clipPath id="refinery-meygjgDtG1kB8-FV4IATS-clip-2"><rect stroke="none" x="232.01" y="-48.8" width="69.72000000000003" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
54<!-- n2&#45;&gt;n2 -->
55<g class="edge edge-UNKNOWN">
56
57<path fill="none" d="M301.69,-33.52C311.86,-33.21 319.73,-30.17 319.73,-24.4 319.73,-21.07 317.1,-18.64 312.91,-17.13" class="edge-line" stroke-dasharray="5,2"/>
58<polygon points="313.62,-13.7 303.19,-15.52 312.48,-20.61 313.62,-13.7" class="edge-line edge-arrow"/>
59<text text-anchor="middle" x="318.3" y="-36.66" font-size="10.50">equals</text>
60</g>
61<!-- n3 -->
62<g class="node node-IMPLICIT node-exists-UNKNOWN node-equalsSelf-UNKNOWN"><rect stroke="none" x="342.5" y="-42.5" width="130" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
63
64<rect stroke="none" x="337.25" y="-48.8" width="129.24" height="48.8" rx="12" ry="12" class="node-bg"/>
65<rect stroke="none" x="333" y="-52" width="137" height="27" clip-path="url(#refinery-meygjgDtG1kB8-FV4IATS-clip-3)" class="node-header"/>
66<text text-anchor="start" x="342.25" y="-33" font-size="12.00">removableMulti [0..*]</text>
67<use x="343.251" y="-19.2" width="12" height="12" id="" class="icon icon-UNKNOWN" href="#refinery-meygjgDtG1kB8-FV4IATS-icon-UNKNOWN"/>
68<g><text text-anchor="start" x="359.25" y="-9.6" font-size="12.00" class="label label-UNKNOWN">exists</text>
69</g>
70<polyline points="337.25,-25.4 466.49,-25.4" class="node-outline"/>
71<rect fill="none" x="337.25" y="-48.8" width="129.24" height="48.8" rx="12" ry="12" class="node-outline"/>
72<clipPath id="refinery-meygjgDtG1kB8-FV4IATS-clip-3"><rect stroke="none" x="337.25" y="-48.8" width="129.24" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
73<!-- n3&#45;&gt;n3 -->
74<g class="edge edge-UNKNOWN">
75
76<path fill="none" stroke-dasharray="5,2" d="M466.3,-32.9C477.06,-31.71 484.49,-28.88 484.49,-24.4 484.49,-21.74 481.87,-19.66 477.49,-18.16" class="edge-line"/>
77<polygon points="478.28,-14.75 467.78,-16.2 476.89,-21.61 478.28,-14.75" class="edge-line edge-arrow"/>
78<text text-anchor="middle" x="483.44" y="-35.94" font-size="10.50">equals</text>
79</g>
80</g>
81</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/ObjectScopes.svg b/subprojects/docs/src/learn/language/logic/ObjectScopes.svg
new file mode 100644
index 00000000..440dfb19
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/ObjectScopes.svg
@@ -0,0 +1,58 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="260pt" height="157pt" viewBox="-6 -6 271.9100036621094 169.1999969482422" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery--ID4ju8v8LPQmawWdGqBG"><style>.refinery--ID4ju8v8LPQmawWdGqBG .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .node .node-outline{stroke:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .node .node-header{fill:rgb(53, 161, 173);}.refinery--ID4ju8v8LPQmawWdGqBG .node .node-bg{fill:#fff;}.refinery--ID4ju8v8LPQmawWdGqBG .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery--ID4ju8v8LPQmawWdGqBG .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery--ID4ju8v8LPQmawWdGqBG .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-g .node-header{fill:#e5c07b;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-h .node-header{fill:#e06c75;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-i .node-header{fill:#98c379;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-j .node-header{fill:#c678dd;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-k .node-header{fill:#80a7f4;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-m .node-header{fill:#e78b8f;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-n .node-header{fill:#abcc94;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-p .node-header{fill:#92c0e9;}.refinery--ID4ju8v8LPQmawWdGqBG .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .edge .edge-line{stroke:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .edge .edge-arrow{fill:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN text{fill:#696c77;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN .edge-arrow{fill:none;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR text{fill:#ca1243;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR .edge-line{stroke:#ca1243;}.refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery--ID4ju8v8LPQmawWdGqBG .icon-TRUE{fill:#19202b;}.refinery--ID4ju8v8LPQmawWdGqBG .icon-UNKNOWN{fill:#696c77;}.refinery--ID4ju8v8LPQmawWdGqBG .icon-ERROR{fill:#ca1243;}.refinery--ID4ju8v8LPQmawWdGqBG text.label-UNKNOWN{fill:#696c77;}.refinery--ID4ju8v8LPQmawWdGqBG text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery--ID4ju8v8LPQmawWdGqBG text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery--ID4ju8v8LPQmawWdGqBG-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery--ID4ju8v8LPQmawWdGqBG-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery--ID4ju8v8LPQmawWdGqBG-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="scale(1 1) rotate(0) translate(4 153.2)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-k"><rect stroke="none" x="74.5" y="-143.5" width="117" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="69.26" y="-149.2" width="116.17999999999999" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="65" y="-153" width="124" height="27" clip-path="url(#refinery--ID4ju8v8LPQmawWdGqBG-clip-0)" class="node-header"/>
9<text text-anchor="start" x="74.26" y="-133.4" font-size="12.00">Region::new [0..70]</text>
10<use x="75.2588" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery--ID4ju8v8LPQmawWdGqBG-icon-TRUE"/>
11<g><text text-anchor="start" x="91.26" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
12</g>
13<polyline points="69.26,-125.8 185.44,-125.8" class="node-outline"/>
14<rect fill="none" x="69.26" y="-149.2" width="116.17999999999999" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery--ID4ju8v8LPQmawWdGqBG-clip-0"><rect stroke="none" x="69.26" y="-149.2" width="116.17999999999999" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n2 -->
17<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-j"><rect stroke="none" x="143.5" y="-58.5" width="114" height="65" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
18
19<rect stroke="none" x="138.78" y="-64.4" width="113.13" height="64.4" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="134" y="-68" width="121" height="27" clip-path="url(#refinery--ID4ju8v8LPQmawWdGqBG-clip-1)" class="node-header"/>
21<text text-anchor="start" x="143.78" y="-48.6" font-size="12.00">State::new [0..120]</text>
22<use x="144.782" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery--ID4ju8v8LPQmawWdGqBG-icon-TRUE"/>
23<g><text text-anchor="start" x="160.77" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
24</g>
25<use x="144.782" y="-19" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery--ID4ju8v8LPQmawWdGqBG-icon-TRUE"/>
26<g><text text-anchor="start" x="160.78" y="-9.2" font-size="12.00" class="label label-TRUE">State</text>
27</g>
28<polyline points="138.78,-41 251.91,-41" class="node-outline"/>
29<rect fill="none" x="138.78" y="-64.4" width="113.13" height="64.4" rx="12" ry="12" class="node-outline"/>
30<clipPath id="refinery--ID4ju8v8LPQmawWdGqBG-clip-1"><rect stroke="none" x="138.78" y="-64.4" width="113.13" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-h"><rect stroke="none" x="5.5" y="-50.5" width="121" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
31
32<rect stroke="none" x="0" y="-56.6" width="120.7" height="48.800000000000004" rx="12" ry="12" class="node-bg"/>
33<rect stroke="none" x="-4" y="-60" width="128" height="27" clip-path="url(#refinery--ID4ju8v8LPQmawWdGqBG-clip-2)" class="node-header"/>
34<text text-anchor="start" x="5" y="-40.8" font-size="12.00">Vertex::new [0..120]</text>
35<use x="6" y="-27" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery--ID4ju8v8LPQmawWdGqBG-icon-TRUE"/>
36<g><text text-anchor="start" x="22" y="-17.4" font-size="12.00" class="label label-TRUE">Vertex</text>
37</g>
38<polyline points="0,-33.2 120.7,-33.2" class="node-outline"/>
39<rect fill="none" x="0" y="-56.6" width="120.7" height="48.800000000000004" rx="12" ry="12" class="node-outline"/>
40<clipPath id="refinery--ID4ju8v8LPQmawWdGqBG-clip-2"><rect stroke="none" x="0" y="-56.6" width="120.7" height="48.800000000000004" rx="12" ry="12" class="node-bg"/></clipPath></g>
41<!-- n0&#45;&gt;n2 -->
42<g class="edge edge-UNKNOWN">
43
44<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M110.09,-100.47C102.28,-89.9 92.91,-77.23 84.42,-65.75" class="edge-line"/>
45<polygon stroke-width="2" points="87.01,-64.1 79.34,-58.89 82.08,-67.74 87.01,-64.1" class="edge-line edge-arrow"/>
46<text text-anchor="start" x="52.27" y="-82.58" font-weight="bold" font-size="10.50">vertices</text>
47</g>
48<!-- n3 -->
49
50<!-- n3&#45;&gt;n2 -->
51<g class="edge edge-UNKNOWN">
52
53<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M144.86,-100.47C150.99,-92.3 158.07,-82.87 164.95,-73.7" class="edge-line"/>
54<polygon stroke-width="2" points="167.38,-75.57 170.18,-66.73 162.48,-71.89 167.38,-75.57" class="edge-line edge-arrow"/>
55<text text-anchor="start" x="116.95" y="-86.47" font-weight="bold" font-size="10.50">vertices</text>
56</g>
57</g>
58</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/StrongerObjectScopes.svg b/subprojects/docs/src/learn/language/logic/StrongerObjectScopes.svg
new file mode 100644
index 00000000..6f988065
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/StrongerObjectScopes.svg
@@ -0,0 +1,58 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="246pt" height="157pt" viewBox="-6 -6 258.2899932861328 169.1999969482422" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-J5TgkNWMX1Aj-K6cbPdd9"><style>.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-outline{stroke:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-header{fill:rgb(53, 161, 173);}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-bg{fill:#fff;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-h .node-header{fill:#e06c75;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-i .node-header{fill:#98c379;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-j .node-header{fill:#c678dd;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-n .node-header{fill:#abcc94;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge .edge-line{stroke:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge .edge-arrow{fill:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN text{fill:#696c77;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR text{fill:#ca1243;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-TRUE{fill:#19202b;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-UNKNOWN{fill:#696c77;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-ERROR{fill:#ca1243;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 text.label-UNKNOWN{fill:#696c77;}.refinery-J5TgkNWMX1Aj-K6cbPdd9 text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-J5TgkNWMX1Aj-K6cbPdd9 text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="scale(1 1) rotate(0) translate(4 153.2)">
4<!-- n0 -->
5<g class="node node-NEW node-exists-UNKNOWN node-equalsSelf-UNKNOWN node-typeHash-k"><rect stroke="none" x="74.5" y="-143.5" width="117" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
6
7<rect stroke="none" x="69.69" y="-149.2" width="116.18" height="48.79999999999998" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="65" y="-153" width="124" height="27" clip-path="url(#refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-0)" class="node-header"/>
9<text text-anchor="start" x="74.69" y="-133.4" font-size="12.00">Region::new [0..70]</text>
10<use x="75.6895" y="-119.6" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-TRUE"/>
11<g><text text-anchor="start" x="91.69" y="-110" font-size="12.00" class="label label-TRUE">Region</text>
12</g>
13<polyline points="69.69,-125.8 185.87,-125.8" class="node-outline"/>
14<rect fill="none" x="69.69" y="-149.2" width="116.18" height="48.79999999999998" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-0"><rect stroke="none" x="69.69" y="-149.2" width="116.18" height="48.79999999999998" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n2 -->
17<g class="node node-NEW node-exists-TRUE node-equalsSelf-UNKNOWN node-typeHash-j"><rect stroke="none" x="150.5" y="-58.5" width="94" height="65" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
18
19<rect stroke="none" x="145.27" y="-64.4" width="93.01999999999998" height="64.4" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="141" y="-68" width="101" height="27" clip-path="url(#refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-1)" class="node-header"/>
21<text text-anchor="start" x="150.27" y="-48.6" font-size="12.00">State::new [20]</text>
22<use x="151.268" y="-35" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-TRUE"/>
23<g><text text-anchor="start" x="167.25" y="-25.2" font-size="12.00" class="label label-TRUE">Vertex</text>
24</g>
25<use x="151.268" y="-19" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-TRUE"/>
26<g><text text-anchor="start" x="167.27" y="-9.2" font-size="12.00" class="label label-TRUE">State</text>
27</g>
28<polyline points="145.27,-41 238.29,-41" class="node-outline"/>
29<rect fill="none" x="145.27" y="-64.4" width="93.01999999999998" height="64.4" rx="12" ry="12" class="node-outline"/>
30<clipPath id="refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-1"><rect stroke="none" x="145.27" y="-64.4" width="93.01999999999998" height="64.4" rx="12" ry="12" class="node-bg"/></clipPath></g><g class="node node-NEW node-exists-TRUE node-equalsSelf-UNKNOWN node-typeHash-h"><rect stroke="none" x="5.5" y="-50.5" width="128" height="49" rx="12.5" ry="12.5" class="node-shadow node-bg"/>
31
32<rect stroke="none" x="0" y="-56.6" width="127.56" height="48.800000000000004" rx="12" ry="12" class="node-bg"/>
33<rect stroke="none" x="-4" y="-60" width="135" height="27" clip-path="url(#refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-2)" class="node-header"/>
34<text text-anchor="start" x="5" y="-40.8" font-size="12.00">Vertex::new [30..100]</text>
35<use x="6" y="-27" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-J5TgkNWMX1Aj-K6cbPdd9-icon-TRUE"/>
36<g><text text-anchor="start" x="22" y="-17.4" font-size="12.00" class="label label-TRUE">Vertex</text>
37</g>
38<polyline points="0,-33.2 127.56,-33.2" class="node-outline"/>
39<rect fill="none" x="0" y="-56.6" width="127.56" height="48.800000000000004" rx="12" ry="12" class="node-outline"/>
40<clipPath id="refinery-J5TgkNWMX1Aj-K6cbPdd9-clip-2"><rect stroke="none" x="0" y="-56.6" width="127.56" height="48.800000000000004" rx="12" ry="12" class="node-bg"/></clipPath></g>
41<!-- n0&#45;&gt;n2 -->
42<g class="edge edge-UNKNOWN">
43
44<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M111.3,-100.47C103.83,-89.9 94.88,-77.23 86.77,-65.75" class="edge-line"/>
45<polygon stroke-width="2" points="89.5,-64.3 81.95,-58.93 84.5,-67.84 89.5,-64.3" class="edge-line edge-arrow"/>
46<text text-anchor="start" x="54.2" y="-82.58" font-weight="bold" font-size="10.50">vertices</text>
47</g>
48<!-- n3 -->
49
50<!-- n3&#45;&gt;n2 -->
51<g class="edge edge-UNKNOWN">
52
53<path fill="none" stroke-width="2" stroke-dasharray="5,2" d="M144.26,-100.47C150.03,-92.3 156.69,-82.87 163.17,-73.7" class="edge-line"/>
54<polygon stroke-width="2" points="165.51,-75.7 168.06,-66.78 160.51,-72.16 165.51,-75.7" class="edge-line edge-arrow"/>
55<text text-anchor="start" x="115.55" y="-86.47" font-weight="bold" font-size="10.50">vertices</text>
56</g>
57</g>
58</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/logic/index.md b/subprojects/docs/src/learn/language/logic/index.md
new file mode 100644
index 00000000..e366e9b8
--- /dev/null
+++ b/subprojects/docs/src/learn/language/logic/index.md
@@ -0,0 +1,256 @@
1---
2SPDX-FileCopyrightText: 2024 The Refinery Authors
3SPDX-License-Identifier: EPL-2.0
4description: Four-valued logic abstraction
5sidebar_position: 1
6---
7
8# Partial modeling
9
10Refinery allow precisely expressing _unknown,_ _uncertain_ or even _contradictory_ information using [four-valued logic](https://en.wikipedia.org/wiki/Four-valued_logic#Belnap).
11During model generation, unknown aspects of the partial model get _refined_ into concrete (true or false) facts until the generated model is completed, or a contradiction is reached.
12
13The _Belnap--Dunn four-valued logic_ supports the following truth values:
14
15* `true` values correspond to facts known about the model, e.g., that a node is the instance of a given class or there is a reference between two nodes.
16* `false` values correspond to facts that are known not to hold, e.g., that a node is _not_ an instance of a given class or there is _no_ reference between two nodes.
17* `unknown` values express uncertain properties and design decisions yet to be made. During model refinement, `unknown` values are gradually replaced with `true` and `false` values until a consistent and concrete model is derived.
18* `error` values represent contradictions and validation failures in the model. One a model contains an error value, it can't be refined into a consistent model anymore.
19
20## Assertions
21
22_Assertions_ express facts about a partial model. An assertion is formed by a _symbol_ and an _argument list_ of _nodes_ in parentheses.
23Possible symbols include [classes](../classes/#classes), [references](../classes/#references), and [predicates](../predicates).
24Nodes appearing in the argument list are automatically added to the model.
25
26A _negative_ assertion with a `false` truth value is indicated by prefixing it with `!`.
27
28---
29
30Consider the following metamodel:
31
32```refinery
33class Region {
34 contains Vertex[] vertices
35}
36class Vertex.
37class State extends Vertex.
38```
39
40Along with the following set of assertions:
41
42```refinery
43Region(r1).
44Vertex(v1).
45Vertex(v2).
46!State(v2).
47vertices(r1, v1).
48vertices(r1, v2).
49!vertices(Region::new, v1).
50!vertices(Region::new, v2).
51```
52
53import AssertionsExample from './AssertionsExample.svg';
54
55<AssertionsExample />
56
57It is `true` that `r1` is an instance of the class `Region`, while `v1` and `v2` are instances of the class `Vertex`.
58We also assert that `v2` is _not_ an instance of the class `State`, but it is unknown whether `v1` is an instance of the class `State`.
59Types that are `unknown` are shown in a lighter color and with an outlined icon.
60
61It is `true` that there is a `vertices` reference between `r1` and `v1`, as well as `r1` and `v2`, but there is no such reference from `Region::new` to the same vertices.
62As no information is provided, it is `unknown` whether `State::new` is a vertex of any `Region` instance.
63References that are `unknown` are shown in a lighter color and with a dashed line.
64
65### Propagation
66
67Refinery can automatically infer some facts about the partial model based on the provided assertions by information _propagation._
68The set of assertions in the [example above](#assertions) is equivalent to the following:
69
70```refinery
71vertices(r1, v1).
72vertices(r1, v2).
73!State(v2).
74```
75
76By the type constraints of the `vertices` reference, Refinery can infer that `r1` is a `Region` instance and `v1` and `v2` are `Vertex` instances.
77Since `State` is a subclass of `Vertex`, it is still unknown whether `v1` is a `State` instance,
78but `v2` is explicitly forbidden from being such by the negative assertion `!State(v2)`.
79We may omit `!vertices(Region::new, v1)` and `!vertices(Region::new, v2)`, since `v1` and `v2` may be a target of only one [containment](../classes/#containment-hierarchy) reference.
80
81Contradictory assertions lead to `error` values in the partial model:
82
83```refinery
84State(v1).
85!Vertex(v1).
86```
87
88import AssertionsError from './AssertionsError.svg';
89
90<AssertionsError />
91
92### Default assertions
93
94Assertions marked with the `default` keyword have _lower priority_ that other assertions.
95They may contain wildcard arguments `*` to specify information about _all_ nodes in the graph.
96However, they can be overridden by more specific assertions that are not marked with the `default` keyword.
97
98---
99
100To make sure that the reference `vertices` is `false` everywhere except where explicitly asserted, we may add a `default` assertion:
101
102```refinery
103default !vertices(*, *).
104vertices(r1, v1).
105vertices(r2, v2).
106vertices(r3, v3).
107?vertices(r1, State::new).
108```
109
110import DefaultAssertions from './DefaultAssertions.svg';
111
112<DefaultAssertions />
113
114We can prefix an assertion with `?` to explicitly assert that some fact about the partial model is `unknown`.
115This is useful for overriding negative `default` assertions.
116
117## Multi-objects
118
119The special symbols `exists` and `equals` control the _number of graph nodes_ represented by an object in a partial model.
120
121By default, `exists` is `true` for all objects.
122An object `o` with `?exists(o)` (i.e., `exists(o)` explicitly set to `unknown`) may be _removed_ from the partial model.
123Therefore, it represents _at least 0_ graph nodes.
124
125By default, `equals` is `true` for its _diagonal_, i.e., we have `equals(o, o)` for all object `o`.
126For off-diagonal pairs, i.e., `(p, q)` with `p` not equal to `q`, we always have `!equals(p, q)`: distinct objects can never be _merged._
127If we set a _diagonal_ entry to `unknown` by writing `?equals(o, o)`, the object `o` becomes a **multi-object:** it can be freely _split_ into multiple graph nodes.
128Therefore, multi-objects represent _possibly more than 1_ graph nodes.
129
130| `exists(o)` | `equals(o, o)` | Number of nodes | Description |
131|:-:|:-:|-:|:-|
132| `true` | `true` | `1` | graph node |
133| `unknown` | `true` | `0..1` | removable graph node |
134| `true` | `unknown` | `1..*` | multi-object |
135| `unknown` | `unknown` | `0..*` | removable multi-object |
136
137In the Refinery web UI, `?exists(o)` is represented with a _dashed_ border, while `?equals(o, o)`
138
139```refinery
140node(node).
141
142node(removable).
143?exists(removable).
144
145node(multi).
146?equals(multi, multi).
147
148node(removableMulti).
149?exists(removableMulti).
150?equals(removableMulti, removableMulti).
151```
152
153import MultiObjects from './MultiObjects.svg';
154
155<MultiObjects />
156
157import TuneIcon from '@material-icons/svg/svg/tune/baseline.svg';
158import LabelIcon from '@material-icons/svg/svg/label/baseline.svg';
159import LabelOutlineIcon from '@material-icons/svg/svg/label/outline.svg';
160
161:::info
162
163You may use the <TuneIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Filter panel icon" />&nbsp;_filter panel_ icon in Refinery to toggle the visibility of special symbols like `exists` and `equals`.
164You may either show <LabelOutlineIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Unknown value icon" />&nbsp;_both true and unknown_ values or <LabelIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="True value icon" />&nbsp;_just true_ values.
165The _object scopes_ toggle will also show the number of graph nodes represented by an object in square brackets after its name, like in the figure above.
166:::
167
168By default, a **new object** `C::new` is added for each non-`abstract` [class](../classes#classes) `C` with `?exists(C::new)` and `?equals(C::new, C::new)`.
169This multi-object represents all potential instances of the class.
170To assert that no new instances of `C` should be added to the generated model, you may write `!exists(C::new)`.
171
172You may use the `multi` keyword to quickly defined a (removable) multi-object:
173
174```refinery
175multi removableMulti.
176% This is equivalent to:
177% ?exists(removableMulti).
178% ?equals(removableMulti, removableMulti).
179```
180
181## Type scopes
182
183_Type scopes_ offer finer-grained control over the number of graph nodes in the generated model (as represented by the multi-objects) that `exists` or `equals` assertions.
184
185A _type scope constraint_ is formed by a unary symbol (a [class](../classes/#classes) or a [predicate](../predicates) with a single parameter) and _scope range._
186Ranges have a form similar to [multiplicity constraints](../classes#multiplicity): a range `n..m` indicates a lower bound of `n` and an upper bound of `m`.
187While an upper bound of `*` indicates a possibly unbounded number of objects, generated models will always be finite.
188Like for multiplicity constraints, the case `n..n` can be abbreviated as `n`.
189
190The number of nodes in the generated model can be controlled using the `node` special symbol.
191For example, we may write the following to generate a model with at least 100 at and most 120 nodes:
192
193```refinery
194scope node = 100..200.
195```
196
197A `scope` declaration may prescribe type scope constraint for any number of symbols, separated by `,`.
198Multiple `scope` declarations are also permitted.
199Multiple ranges provided for the same symbol will be intersected, i.e., they influence the generated model simultaneously.
200
201In other words,
202```
203scope Region = 10, State = 80..120.
204scope State = 100..150.
205% Equivalent to:
206scope Region = 10, State = 100..120.
207```
208
209The _object scopes_ option in the <TuneIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Filter panel icon" />&nbsp;_filter panel_ may help in exploring the effects of object scopes.
210
211---
212
213Consider the example
214
215```refinery
216class Region {
217 contains Vertex[] vertices
218}
219class Vertex.
220class State extends Vertex.
221scope node = 100..120, Vertex = 50..*.
222```
223
224import ObjectScopes from './ObjectScopes.svg';
225
226<ObjectScopes />
227
228Notice that Refinery could determine that there can be no more than 70 `Region` instances in the generated model, since at least 50 of the `100..120` nodes in the model must be `Vertex` instances.
229However, since `State` is a subclass of `Vertex` (i.e., `State::new` is also an instance of `Vertex`), the range `50..*` is shared between both `Vertex::new` and `State::new`, resulting in both representing `0..120` nodes.
230Nevertheless, every generated model will obey the scope constraint exactly, i.e., will have between 100 and 120 node, at least 50 of which are `Vertex` instances.
231
232By providing more information, Refinery can determine more precise ranges for multi-objects.
233For example, we may strengthen the scope constraints as follows:
234
235```refinery
236scope node = 100..120, Vertex = 50..*, State = 20.
237```
238
239import StrongerObjectScopes from './StrongerObjectScopes.svg';
240
241<StrongerObjectScopes />
242
243### Incremental scopes
244
245We may specify an _incremental_ object scope with the `+=` operator to determine the number of new instances to be added to the model.
246This is only allowed for symbol that are classes with no subclasses, as it directly influences the number of nodes represented by the corresponding `::new` object.
247
248For example, to ensure that between 5 and 7 `State` instances are added to the model, we may write:
249
250```refinery
251State(s1).
252State(s2).
253scope State += 5..7.
254```
255
256Since `s1` and `s2` are also instances of the `State` class, the generated concrete model will have between 7 and 9 `State` instances altogether.
diff --git a/subprojects/docs/src/learn/language/predicates/DerivedFeature.svg b/subprojects/docs/src/learn/language/predicates/DerivedFeature.svg
new file mode 100644
index 00000000..be9465b8
--- /dev/null
+++ b/subprojects/docs/src/learn/language/predicates/DerivedFeature.svg
@@ -0,0 +1,76 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<svg width="216pt" height="226pt" viewBox="-6 -6 227.8699951171875 238.39999389648438" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="refinery-9k5t5y1ScYnYvNXEZbWT4"><style>.refinery-9k5t5y1ScYnYvNXEZbWT4 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-outline{stroke:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-header{fill:rgb(53, 161, 173);}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-bg{fill:#fff;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-INDIVIDUAL .node-outline{stroke-width:2;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-shadow.node-bg{fill:#19202b;opacity:0.24;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-g .node-header{fill:#e5c07b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-h .node-header{fill:#e06c75;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-i .node-header{fill:#98c379;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-j .node-header{fill:#c678dd;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-k .node-header{fill:#80a7f4;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-l .node-header{fill:#e3d1b2;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-m .node-header{fill:#e78b8f;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-n .node-header{fill:#abcc94;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-o .node-header{fill:#dbb2e8;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-p .node-header{fill:#92c0e9;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge .edge-line{stroke:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge .edge-arrow{fill:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN text{fill:#696c77;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN .edge-line{stroke:#696c77;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN .edge-arrow{fill:none;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR text{fill:#ca1243;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR .edge-line{stroke:#ca1243;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR .edge-arrow{fill:#ca1243;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-TRUE{fill:#19202b;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-UNKNOWN{fill:#696c77;}.refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-ERROR{fill:#ca1243;}.refinery-9k5t5y1ScYnYvNXEZbWT4 text.label-UNKNOWN{fill:#696c77;}.refinery-9k5t5y1ScYnYvNXEZbWT4 text.label-ERROR{fill:#ca1243;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-outline{stroke:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-header{fill:rgb(60, 127, 135);}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node .node-bg{fill:#282c34;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-INDIVIDUAL .node-outline{stroke-width:2;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-shadow.node-bg{fill:#ebebff;opacity:0.32;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-exists-UNKNOWN .node-outline{stroke-dasharray:5 2;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-g .node-header{fill:#ae8003;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-h .node-header{fill:#a23b47;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-i .node-header{fill:#428141;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-j .node-header{fill:#854797;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-k .node-header{fill:#3982bb;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-l .node-header{fill:#827662;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-m .node-header{fill:#904f53;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-n .node-header{fill:#647e63;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-o .node-header{fill:#805f89;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .node-typeHash-p .node-header{fill:#4f7799;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge text{font-family:"Open Sans Variable","Open Sans","Roboto","Helvetica","Arial",sans-serif;fill:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge .edge-line{stroke:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge .edge-arrow{fill:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN text{fill:#abb2bf;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN .edge-line{stroke:#abb2bf;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-UNKNOWN .edge-arrow{fill:none;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR text{fill:#e06c75;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR .edge-line{stroke:#e06c75;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .edge-ERROR .edge-arrow{fill:#e06c75;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-TRUE{fill:#ebebff;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 .icon-ERROR{fill:#e06c75;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 text.label-UNKNOWN{fill:#abb2bf;}[data-theme="dark"] .refinery-9k5t5y1ScYnYvNXEZbWT4 text.label-ERROR{fill:#e06c75;}</style><defs><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-9k5t5y1ScYnYvNXEZbWT4-icon-TRUE" class="icon-TRUE"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-9k5t5y1ScYnYvNXEZbWT4-icon-UNKNOWN" class="icon-UNKNOWN"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="refinery-9k5t5y1ScYnYvNXEZbWT4-icon-ERROR" class="icon-ERROR"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10s10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41L8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59z"/></svg></defs>
3<g class="graph" transform="translate(4, 222.39999389648438)">
4<!-- n2 -->
5<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-i">
6
7<rect stroke="none" x="64.75" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/>
8<rect stroke="none" x="60" y="-52" width="92" height="27" clip-path="url(#refinery-9k5t5y1ScYnYvNXEZbWT4-clip-0)" class="node-header"/>
9<text text-anchor="start" x="76.52" y="-33" font-size="12.00">transition1</text>
10<use x="70.7485" y="-19.2" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-9k5t5y1ScYnYvNXEZbWT4-icon-TRUE"/>
11<g><text text-anchor="start" x="86.75" y="-9.6" font-size="12.00" class="label label-TRUE">Transition</text>
12</g>
13<polyline points="64.75,-25.4 148.97,-25.4" class="node-outline"/>
14<rect fill="none" x="64.75" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-outline"/>
15<clipPath id="refinery-9k5t5y1ScYnYvNXEZbWT4-clip-0"><rect stroke="none" x="64.75" y="-48.8" width="84.22" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
16<!-- n3 -->
17<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
18
19<rect stroke="none" x="74.84" y="-218.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-bg"/>
20<rect stroke="none" x="70" y="-222" width="72" height="27" clip-path="url(#refinery-9k5t5y1ScYnYvNXEZbWT4-clip-1)" class="node-header"/>
21<text text-anchor="start" x="85.98" y="-202.6" font-size="12.00">vertex1</text>
22<use x="80.8442" y="-188.8" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-9k5t5y1ScYnYvNXEZbWT4-icon-TRUE"/>
23<g><text text-anchor="start" x="96.84" y="-179.2" font-size="12.00" class="label label-TRUE">Vertex</text>
24</g>
25<polyline points="74.84,-195 138.87,-195" class="node-outline"/>
26<rect fill="none" x="74.84" y="-218.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-outline"/>
27<clipPath id="refinery-9k5t5y1ScYnYvNXEZbWT4-clip-1"><rect stroke="none" x="74.84" y="-218.4" width="64.03" height="48.80000000000001" rx="12" ry="12" class="node-bg"/></clipPath></g>
28<!-- n2&#45;&gt;n3 -->
29<g class="edge edge-TRUE">
30
31<path fill="none" d="M111.71,-48.78C113.97,-77.25 114.21,-125.59 112.45,-158.38" class="edge-line"/>
32<polygon points="108.96,-157.98 111.8,-168.19 115.95,-158.44 108.96,-157.98" class="edge-line edge-arrow"/>
33<text text-anchor="middle" x="97.12" y="-99.47" font-size="10.50">source</text>
34</g>
35<!-- n4 -->
36<g class="node node-IMPLICIT node-exists-TRUE node-equalsSelf-TRUE node-typeHash-h">
37
38<rect stroke="none" x="143.84" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/>
39<rect stroke="none" x="139" y="-137" width="72" height="27" clip-path="url(#refinery-9k5t5y1ScYnYvNXEZbWT4-clip-2)" class="node-header"/>
40<text text-anchor="start" x="154.98" y="-117.8" font-size="12.00">vertex2</text>
41<use x="149.844" y="-104" width="12" height="12" id="" class="icon icon-TRUE" href="#refinery-9k5t5y1ScYnYvNXEZbWT4-icon-TRUE"/>
42<g><text text-anchor="start" x="165.84" y="-94.4" font-size="12.00" class="label label-TRUE">Vertex</text>
43</g>
44<polyline points="143.84,-110.2 207.87,-110.2" class="node-outline"/>
45<rect fill="none" x="143.84" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-outline"/>
46<clipPath id="refinery-9k5t5y1ScYnYvNXEZbWT4-clip-2"><rect stroke="none" x="143.84" y="-133.6" width="64.03" height="48.8" rx="12" ry="12" class="node-bg"/></clipPath></g>
47<!-- n2&#45;&gt;n4 -->
48<g class="edge edge-TRUE">
49
50<path fill="none" d="M132.35,-48.63C140.1,-57.19 148.46,-67.04 155.81,-76.23" class="edge-line"/>
51<polygon points="152.92,-78.21 161.83,-83.94 158.44,-73.91 152.92,-78.21" class="edge-line edge-arrow"/>
52<text text-anchor="middle" x="133.35" y="-57.15" font-size="10.50">target</text>
53</g>
54<!-- n3&#45;&gt;n2 -->
55<g class="edge edge-TRUE">
56
57<path fill="none" stroke-width="2" d="M102.01,-169.7C99.75,-141.26 99.5,-92.92 101.27,-60.1" class="edge-line"/>
58<polygon stroke-width="2" points="104.3,-60.73 101.81,-51.8 98.18,-60.33 104.3,-60.73" class="edge-line edge-arrow"/>
59<text text-anchor="start" x="0" y="-113.73" font-weight="bold" font-size="10.50">outgoingTransition</text>
60</g>
61<!-- n4&#45;&gt;n2 -->
62<!-- n4&#45;&gt;n2 -->
63<g class="edge edge-TRUE">
64
65<path fill="none" d="M150.52,-85.14C142.77,-76.59 134.41,-66.75 127.05,-57.54" class="edge-line"/>
66<polygon points="129.93,-55.54 121.01,-49.82 124.41,-59.86 129.93,-55.54" class="edge-line edge-arrow"/>
67<text text-anchor="middle" x="87.8" y="-70.33" font-size="10.50">incomingTransition</text>
68</g><g class="edge edge-TRUE">
69
70<path fill="none" d="M126.08,-169.94C133.27,-161.31 141.57,-151.34 149.31,-142.06" class="edge-line"/>
71<polygon points="151.82,-144.51 155.53,-134.59 146.44,-140.03 151.82,-144.51" class="edge-line edge-arrow"/>
72<text text-anchor="middle" x="116.57" y="-154.94" font-size="10.50">neighbors</text>
73</g>
74
75</g>
76</svg> \ No newline at end of file
diff --git a/subprojects/docs/src/learn/language/predicates/index.md b/subprojects/docs/src/learn/language/predicates/index.md
new file mode 100644
index 00000000..261054c1
--- /dev/null
+++ b/subprojects/docs/src/learn/language/predicates/index.md
@@ -0,0 +1,284 @@
1---
2SPDX-FileCopyrightText: 2024 The Refinery Authors
3SPDX-License-Identifier: EPL-2.0
4description: Model queries and model validation
5sidebar_position: 2
6---
7
8# Graph predicates
9
10Graph predicates are logic expressions that can be used to query for interesting model fragments, as well as for validating the consistency of models. They are evaluated on partial models according to [four-valued logic](../logic) semantics.
11
12Predicates in Refinery are written in [Disjunctive Normal Form](https://en.wikipedia.org/wiki/Disjunctive_normal_form) (DNF) as an _OR_ of _ANDs_, i.e., a _disjunction_ of _clauses_ formed as a _conjunction_ of positive or negated logic _literals._
13This matches the syntax and semantics of logical query languages, such as [Datalog](https://en.wikipedia.org/wiki/Datalog), and logical programming languages, such as [Prolog](https://en.wikipedia.org/wiki/Prolog).
14
15import Link from '@docusaurus/Link';
16
17<details>
18<summary>Example metamodel</summary>
19
20In the examples on this page, we will use the following metamodel as illustration:
21
22```refinery
23abstract class CompositeElement {
24 contains Region[] regions
25}
26
27class Region {
28 contains Vertex[] vertices opposite region
29}
30
31abstract class Vertex {
32 container Region region opposite vertices
33 contains Transition[] outgoingTransition opposite source
34 Transition[] incomingTransition opposite target
35}
36
37class Transition {
38 container Vertex source opposite outgoingTransition
39 Vertex[1] target opposite incomingTransition
40}
41
42abstract class Pseudostate extends Vertex.
43
44abstract class RegularState extends Vertex.
45
46class Entry extends Pseudostate.
47
48class Exit extends Pseudostate.
49
50class Choice extends Pseudostate.
51
52class FinalState extends RegularState.
53
54class State extends RegularState, CompositeElement.
55
56class Statechart extends CompositeElement.
57```
58
59<p>
60 <Link
61 href="https://refinery.services/#/1/KLUv_WAEAiUIAOIKIR5gadMGg1ajk9jLoipJ58vc0vAE5opt1YaDpyOCAAdaCjMohSdgl4rj1yTo8UCgpTDHCIAE-o3Jr28mGO9AEoDcR-tLGh4liE2Z3IOX50z-FksLaNWLpLXd1QiUII2vNjCMBWOVEgTzjhG0eHVMIyIyFOjoxcrBv83FkgftlmJ0K_0eVDQgEBSCrXYvD1Q2wlwGXecz2HjRADQOLMh6iIYIWBPuFBBCI2igVgiHAFH4uclAydd4TFayN-oOpjzxgd0FlTzkN6QZ8CQDXBN4EPjB5VJZCANQlJA3wDd_PVyUA5eA0gaeAcgENsm4YnCogWihMAMkA8-CoB-gm9HJC0AB"
62 className="button button--lg button--primary button--play"
63 >Try in Refinery</Link>
64</p>
65
66</details>
67
68[Assertions](../logic/#assertions) about graph predicates can prescribe where the predicate should (for positive assertions) or should not (for negative assertions) hold.
69When generating consistent models
70
71## Atoms
72
73An _atom_ is formed by a _symbol_ and _argument list_ of variables.
74Possible symbols include [classes](../classes/#classes), [references](../classes/#references), and [predicates](../predicates).
75We may write a basic graph query as a conjunction (AND) of atoms.
76
77The `pred` keyword defines a graph predicate. After the _predicate name_, a _parameter list_ of variables is provided. The atoms of the graph predicate are written after the `<->` operator, and a full stop `.` terminates the predicate definition.
78
79The following predicate `entryInRegion` will match pairs of `Region` instances `r` and `Entry` instances `e` such that `e` is a vertex in `r`.
80
81```refinery
82pred entryInRegion(r, e) <->
83 Region(r),
84 vertices(r, e),
85 Entry(e).
86```
87
88We may write unary symbols that act as _parameter types_ directly in the parameter list. The following definition is equivalent to the previous one:
89
90```refinery
91pred entryInRegion(Region r, Entry e) <->
92 vertices(r, e).
93```
94
95import TableIcon from '@material-icons/svg/svg/table_chart/baseline.svg';
96
97:::info
98
99You may display the result of graph predicate matching in the <TableIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Table view icon" />&nbsp;_table view_ of the Refinery web UI.
100
101:::
102
103## Quantification
104
105Variables not appearing in the parameter list are _existentially quantified._
106
107The following predicate matches `Region` instances with two entries:
108
109```refinery
110pred multipleEntriesInRegion(Region r) <->
111 entryInRegion(r, e1),
112 entryInRegion(r, e2),
113 e1 != e2.
114```
115
116Existentially quantified variables that appear only once in the predicate should be prefixed with `_`. This shows that the variable is intentionally used only once (as opposite to the second reference to the variable being omitted by mistake).
117
118```refinery
119pred regionWithEntry(Region r) <->
120 entryInRegion(r, _e).
121```
122
123Alternatively, you may use a single `_` whenever a variable occurring only once is desired. Different occurrences of `_` are considered distinct variables.
124
125```refinery
126pred regionWithEntry(Region r) <->
127 entryInRegion(r, _).
128```
129
130## Negation
131
132Negative literals are written by prefixing the corresponding atom with `!`.
133
134Inside negative literals, quantification is _universal:_ the literal matches if there is no assignment of the variables solely appearing in it that satisfies the corresponding atom.
135
136The following predicate matches `Region` instances that have no `Entry`:
137
138```refinery
139pred regionWithoutEntry(Region r) <->
140 !entryInRegion(r, _).
141```
142
143In a graph predicate, all parameter variables must be _positively bound,_ i.e., appear in at least one positive literal (atom).
144Negative literals may further constrain the predicate match one it has been established by the positive literals.
145
146## Object equality
147
148The operators `a == b` and `a != b` correspond to the literals `equals(a, b)` and `!equals(a, b)`, respectively.
149See the section about [multi-objects](../logic/#multi-objects) for more information about the `equals` symbol.
150
151## Transitive closure
152
153The `+` operator forms the [transitive closure](https://en.wikipedia.org/wiki/Transitive_closure) of symbols with exactly 2 parameters.
154The transitive closure `r+(a, b)` holds if either `r(a, b)` is `true`, or there is a sequence of objects `c1`, `c2`, &hellip;, `cn` such that `r(a, c1)`, `r(c1, c2)`, `r(c2, c3)`, &hellip;, `r(cn, b)`.
155In other words, there is a path labelled with `r` in the graph from `a` to `b`.
156
157Transitive closure may express queries about graph reachability:
158
159```refinery
160pred neighbors(Vertex v1, Vertex v2) <->
161 Transition(t),
162 source(t, v1),
163 target(t, v2).
164
165pred cycle(Vertex v) <->
166 neighbors+(v, v).
167```
168
169## Disjunction
170
171Disjunction (OR) of _clauses_ formed by a conjunction (AND) of literals is denoted by `;`.
172
173```refinery
174pred regionWithInvalidNumberOfEntries(Region r) <->
175 !entryInRegion(r, _)
176;
177 entryInRegion(r, e1),
178 entryInRegion(r, e2),
179 e1 != e2.
180```
181
182Every clause of a disjunction must bind every parameter variable of the graph predicate _positively._
183_Type annotations_ on parameter are applied in all clauses.
184Therefore, the previous graph pattern is equivalent to the following:
185
186```refinery
187pred regionWithInvalidNumberOfEntries(r) <->
188 Region(r),
189 !entryInRegion(r, _)
190;
191 Region(r),
192 entryInRegion(r, e1),
193 entryInRegion(r, e2),
194 e1 != e2.
195```
196
197## Derived features
198
199Graph predicates may act as _derived types_ and _references_ in metamodel.
200
201A graph predicate with exactly 1 parameters can be use as if it was a class: you may use it as a [_parameter type_](#atoms) in other graph patterns, as a _target type_ of a (non-containment) [reference](../classes/#references), or in a [_scope constraint_](../logic#type-scopes).
202
203_Derived references_ are graph predicates with exactly 2 parameters, which correspond the source and target node of the reference.
204
205import TuneIcon from '@material-icons/svg/svg/tune/baseline.svg';
206import LabelIcon from '@material-icons/svg/svg/label/baseline.svg';
207import LabelOutlineIcon from '@material-icons/svg/svg/label/outline.svg';
208
209:::info
210
211You may use the <TuneIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Filter panel icon" />&nbsp;_filter panel_ icon in Refinery to toggle the visibility of graph predicates with 1 or 2 parameters.
212You may either show <LabelOutlineIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="Unknown value icon" />&nbsp;_both true and unknown_ values or <LabelIcon style={{ fill: 'currentColor', verticalAlign: 'text-top' }} title="True value icon" />&nbsp;_just true_ values.
213
214:::
215
216---
217
218For example, we may replace the reference `neighbors` in the class `Vertex`:
219
220```refinery
221class Vertex {
222 Vertex[] neighbors
223}
224```
225
226with the graph predicate `neighbors` as follows:
227
228
229```refinery
230class Vertex {
231 contains Transition[] outgoingTransition opposite source
232 Transition[] incomingTransition opposite target
233}
234
235class Transition {
236 container Vertex source opposite outgoingTransition
237 Vertex[1] target opposite incomingTransition
238}
239
240pred neighbors(Vertex v1, Vertex v2) <->
241 Transition(t),
242 source(t, v1),
243 target(t, v2).
244```
245
246Since `neighbors` is now computed based on the `Transition` instances and their `source` and `target` references present in the model, the assertion
247
248```refinery
249neighbors(vertex1, vertex2).
250```
251
252will only be satisfied if a corresponding node `transition1` is present in the generated model that also satisfies
253
254```refinery
255Transition(transition1).
256source(transition1, vertex1).
257target(transition1, vertex2).
258```
259
260import DerivedFeature from './DerivedFeature.svg';
261
262<DerivedFeature />
263
264## Error predicates
265
266A common use-case for graph predicates is _model validation_, where a predicate highlights _errors_ in the model.
267Such predicates are called _error predicates._
268In a consistent generated model, an error predicates should have no matches.
269
270You can declare error predicates with the `error` keyword:
271
272```refinery
273error regionWithoutEntry(Region r) <->
274 !entryInRegion(r, _).
275```
276
277This is equivalent to asserting that the error predicate is `false` everywhere:
278
279```refinery
280pred regionWithoutEntry(Region r) <->
281 !entryInRegion(r, _).
282
283!regionWithoutEntry(*).
284```