www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit fb1786b4ac5f94f1fa9f0607ec2fb004be0419dd
parent b7c2babf85ad636ff5b73c50a4e4bc953788ab11
Author: Georges Dupéron <georges.duperon@gmail.com>
Date:   Mon, 16 Jan 2017 03:11:16 +0100

More work on the invariants

Diffstat:
M.gitignore | 2++
MGraph-notes-copy2.vue | 150++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Aalpha-equivalence-normal-form.rkt | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abench001.rkt | 33+++++++++++++++++++++++++++++++++
Mflexible-with-utils.hl.rkt | 6++++--
Mflexible-with.hl.rkt | 2+-
Rgraph-info.rkt -> graph-info.hl.rkt | 0
Minvariants-phantom.hl.rkt | 132++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Athoughts.rkt | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtraversal.hl.rkt | 2+-
10 files changed, 466 insertions(+), 66 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -4,3 +4,4 @@ .DS_Store compiled/ /doc/ +/.~*.vue +\ No newline at end of file diff --git a/Graph-notes-copy2.vue b/Graph-notes-copy2.vue @@ -1,14 +1,14 @@ -<!-- Tufts VUE 3.3.0 concept-map (Graph-notes-copy2.vue) 2017-01-05 --> +<!-- Tufts VUE 3.3.0 concept-map (Graph-notes-copy2.vue) 2017-01-16 --> <!-- Tufts VUE: http://vue.tufts.edu/ --> <!-- Do Not Remove: VUE mapping @version(1.1) jar:file:/nix/store/z92y35qgs6g3cvvh0i4f14mg5n47zvvi-vue-3.3.0/share/vue/vue.jar!/tufts/vue/resources/lw_mapping_1_1.xml --> -<!-- Do Not Remove: Saved date Thu Jan 05 00:59:01 CET 2017 by georges on platform Linux 4.4.38 in JVM 1.8.0_122-04 --> +<!-- Do Not Remove: Saved date Mon Jan 16 01:54:56 CET 2017 by georges on platform Linux 4.4.38 in JVM 1.8.0_122-04 --> <!-- Do Not Remove: Saving version @(#)VUE: built October 8 2015 at 1724 by tomadm on Linux 2.6.32-504.23.4.el6.x86_64 i386 JVM 1.7.0_21-b11(bits=32) --> <?xml version="1.0" encoding="US-ASCII"?> <LW-MAP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="none" ID="0" label="Graph-notes-copy2.vue" created="1479309847604" x="0.0" y="0.0" width="1.4E-45" height="1.4E-45" strokeWidth="0.0" autoSized="false"> - <resource referenceCreated="1483574341626" size="204773" + <resource referenceCreated="1484528096110" size="208901" spec="/home/georges/phc/racket-packages/phc-graph/Graph-notes-copy2.vue" type="1" xsi:type="URLResource"> <title>Graph-notes-copy2.vue</title> @@ -314,9 +314,9 @@ <ID2 xsi:type="node">36</ID2> </child> <child ID="42" - label="Cache all calls to equal? while grouping nodes" + label="Cache all calls to equal? and equal-hash-code and equal-secondary-hash-code while grouping nodes" layerID="1" created="1479310644302" x="1518.7698" y="1259.8262" - width="315.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> + width="681.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#F2AE45</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> @@ -988,7 +988,7 @@ <child ID="195" label=" " layerID="1" created="1479312165108" x="-862.1742" y="400.12408" width="97.0" height="23.0" strokeWidth="1.0" autoSized="false" xsi:type="node"> - <fillColor>#C1F780</fillColor> + <fillColor>#FFFFFF</fillColor> <strokeColor>#D0D0D0</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -1352,9 +1352,9 @@ <ID1 xsi:type="node">11</ID1> <ID2 xsi:type="node">241</ID2> </child> - <child ID="244" label="&#x3b1;-equivalence" layerID="1" + <child ID="244" label="&#x3b1;-equivalence normal form" layerID="1" created="1479314913291" x="1434.1376" y="1005.7449" - width="104.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> + width="184.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#A6A6A6</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> @@ -1362,21 +1362,21 @@ <URIString>http://vue.tufts.edu/rdf/resource/6e0b664b43a6be970d2ffe25608d7f84</URIString> <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> </child> - <child ID="245" layerID="1" created="1479314913294" x="1409.2081" - y="956.80304" width="62.766357" height="49.441895" + <child ID="245" layerID="1" created="1479314913294" x="1415.6469" + y="956.803" width="89.88867" height="49.441833" strokeWidth="1.0" autoSized="false" controlCount="0" arrowState="2" xsi:type="link"> <strokeColor>#000000</strokeColor> <textColor>#404040</textColor> <font>SansSerif-plain-11</font> <URIString>http://vue.tufts.edu/rdf/resource/6e0b664b43a6be970d2ffe252aafd35e</URIString> - <point1 x="1409.7081" y="957.30304"/> - <point2 x="1471.4745" y="1005.74493"/> + <point1 x="1416.1469" y="957.30304"/> + <point2 x="1505.0355" y="1005.7449"/> <ID1 xsi:type="node">11</ID1> <ID2 xsi:type="node">244</ID2> </child> <child ID="246" label="Too hard to implement for now" layerID="1" - created="1479314956001" x="1417.3375" y="1043.5447" + created="1479314956001" x="1452.3375" y="1052.5447" width="210.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#A6A6A6</fillColor> <strokeColor>#776D6D</strokeColor> @@ -1385,22 +1385,22 @@ <URIString>http://vue.tufts.edu/rdf/resource/6e0b664c43a6be970d2ffe253b42a8fa</URIString> <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> </child> - <child ID="247" layerID="1" created="1479314956003" x="1496.6509" - y="1028.2449" width="15.17334" height="15.799805" + <child ID="247" layerID="1" created="1479314956003" x="1533.3042" + y="1028.2449" width="16.866577" height="24.799805" strokeWidth="1.0" autoSized="false" controlCount="0" arrowState="2" xsi:type="link"> <strokeColor>#000000</strokeColor> <textColor>#404040</textColor> <font>SansSerif-plain-11</font> <URIString>http://vue.tufts.edu/rdf/resource/6e0b664c43a6be970d2ffe25426d76fa</URIString> - <point1 x="1497.1509" y="1028.7449"/> - <point2 x="1511.3242" y="1043.5447"/> + <point1 x="1533.8043" y="1028.7449"/> + <point2 x="1549.6709" y="1052.5447"/> <ID1 xsi:type="node">244</ID1> <ID2 xsi:type="node">246</ID2> </child> <child ID="252" label="http://docs.racket-lang.org/graph/index.html#%28def._%28%28lib._graph%2Fmain..rkt%29._coloring%2Fgreedy%29%29" - layerID="1" created="1479315385244" x="872.13745" y="-11.855225" + layerID="1" created="1479315385244" x="436.13745" y="60.144775" width="784.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#F2AE45</fillColor> <strokeColor>#776D6D</strokeColor> @@ -1409,16 +1409,15 @@ <URIString>http://vue.tufts.edu/rdf/resource/6e12548843a6be970d2ffe259bb5e939</URIString> <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> </child> - <child ID="253" layerID="1" created="1479315385245" x="1270.5393" - y="10.644775" width="34.10388" height="56.158203" - strokeWidth="1.0" autoSized="false" controlCount="0" - arrowState="2" xsi:type="link"> + <child ID="253" layerID="1" created="1479315385245" x="1218.9329" + y="76.13478" width="60.11206" height="1.75383" strokeWidth="1.0" + autoSized="false" controlCount="0" arrowState="2" xsi:type="link"> <strokeColor>#000000</strokeColor> <textColor>#404040</textColor> <font>SansSerif-plain-11</font> <URIString>http://vue.tufts.edu/rdf/resource/6e12548843a6be970d2ffe25f25ed174</URIString> - <point1 x="1304.1432" y="66.30298"/> - <point2 x="1271.0393" y="11.144775"/> + <point1 x="1278.5449" y="77.38861"/> + <point2 x="1219.4329" y="76.63478"/> <ID1 xsi:type="node">23</ID1> <ID2 xsi:type="node">252</ID2> </child> @@ -1475,7 +1474,7 @@ <child ID="262" label=" " layerID="1" created="1479315626294" x="-689.56244" y="438.0868" width="97.0" height="23.0" strokeWidth="1.0" autoSized="false" xsi:type="node"> - <fillColor>#FFFFFF</fillColor> + <fillColor>#C1F780</fillColor> <strokeColor>#D0D0D0</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -1699,7 +1698,7 @@ label="Each node has an extra field of the following type:&#xa;" layerID="1" created="1479317112254" x="-826.86255" y="972.24475" width="339.0" height="107.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> - <fillColor>#F2AE45</fillColor> + <fillColor>#C1F780</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -1760,7 +1759,7 @@ label="Use a private struct to prevent forging of the invariants aggregated in a case&#x2192;&#xa;(since it is never executed, any non-terminating &#x3bb; could otherwise be supplied).&#xa;" layerID="1" created="1479317202233" x="-960.86255" y="1145.7448" width="531.0" height="77.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> - <fillColor>#F2AE45</fillColor> + <fillColor>#C1F780</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -1814,7 +1813,7 @@ label="graph invariants should only define the dummy type used to identify them" layerID="1" created="1479317586757" x="-968.86255" y="1282.7448" width="611.0" height="172.25" strokeWidth="1.0" autoSized="true" xsi:type="node"> - <fillColor>#F2AE45</fillColor> + <fillColor>#C1F780</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -1902,7 +1901,7 @@ label="The returned type may contain symbols, to indicate node names and field names,&#xa;and will contain a reference to a private struct type, so that&#xa;two invariants with the same name defined in separate won't conflict" layerID="1" created="1479317996531" x="-1558.8625" y="1375.2448" width="543.0" height="53.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> - <fillColor>#F2AE45</fillColor> + <fillColor>#C1F780</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -2175,7 +2174,7 @@ <ID2 xsi:type="node">353</ID2> </child> <child ID="355" label="Too hard to implement for now" layerID="1" - created="1479341061597" x="1677.9707" y="128.74475" + created="1479341061597" x="1622.9707" y="-37.25525" width="210.0" height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#A6A6A6</fillColor> <strokeColor>#776D6D</strokeColor> @@ -2184,15 +2183,16 @@ <URIString>http://vue.tufts.edu/rdf/resource/6f9963d1c0a80026616d9239f16e4b43</URIString> <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> </child> - <child ID="356" layerID="1" created="1479341061598" x="1613.4707" - y="140.18779" width="65.0" height="1.27005" strokeWidth="1.0" - autoSized="false" controlCount="0" arrowState="2" xsi:type="link"> + <child ID="356" layerID="1" created="1479341061598" x="1558.0037" + y="-14.755249" width="157.93408" height="145.0" + strokeWidth="1.0" autoSized="false" controlCount="0" + arrowState="2" xsi:type="link"> <strokeColor>#404040</strokeColor> <textColor>#404040</textColor> <font>SansSerif-plain-11</font> <URIString>http://vue.tufts.edu/rdf/resource/6f9963d1c0a80026616d923937836369</URIString> - <point1 x="1613.9707" y="140.95784"/> - <point2 x="1677.9707" y="140.68779"/> + <point1 x="1558.5037" y="129.74475"/> + <point2 x="1715.4377" y="-14.255249"/> <ID1 xsi:type="node">353</ID1> <ID2 xsi:type="node">355</ID2> </child> @@ -2345,7 +2345,7 @@ label="What about invariants?&#xa;* Just copy them over syntactically?&#xa;* Require that they are re-specified&#xa;(at least by explicitly copying them by their name)" layerID="1" created="1479346589797" x="788.9707" y="332.74475" width="329.0" height="68.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> - <fillColor>#DD7B11</fillColor> + <fillColor>#F2AE45</fillColor> <strokeColor>#776D6D</strokeColor> <textColor>#000000</textColor> <font>SansSerif-plain-12</font> @@ -2628,7 +2628,7 @@ <ctrlPoint0 x="1464.6375" y="1218.2448" xsi:type="point"/> </child> <child ID="410" layerID="1" created="1479388143803" x="1399.9028" - y="1172.803" width="119.48682" height="96.929565" + y="1172.803" width="119.57471" height="96.49426" strokeWidth="1.0" autoSized="false" controlCount="1" arrowState="2" xsi:type="link"> <strokeColor>#000000</strokeColor> @@ -2636,7 +2636,7 @@ <font>SansSerif-plain-11</font> <URIString>http://vue.tufts.edu/rdf/resource/72688d2cc0a8002633539faacb736715</URIString> <point1 x="1400.4028" y="1173.303"/> - <point2 x="1518.8896" y="1269.2325"/> + <point2 x="1518.9775" y="1268.7972"/> <ID1 xsi:type="node">25</ID1> <ID2 xsi:type="node">42</ID2> <ctrlPoint0 x="1444.6375" y="1268.2448" xsi:type="point"/> @@ -3470,7 +3470,7 @@ <ID2 xsi:type="node">512</ID2> </child> <child ID="514" - label="Problem: how do we make the field accessors &quot;hyb&#xa;id&quot;, i.e. working both on fixed records and flex records?&#xa;We don't want nested field accesses to build up a tower of U types,&#xa;which makes acceesses very costly for the typechecker" + label="Problem: how do we make the field accessors &quot;hybrid&quot;,&#xa;i.e. working both on fixed records and flex records?&#xa;We don't want nested field accesses to build up a tower of U types,&#xa;which makes acceesses very costly for the typechecker" layerID="1" created="1482936685798" x="3909.6375" y="310.24475" width="454.0" height="68.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> <fillColor>#FC938D</fillColor> @@ -3708,12 +3708,82 @@ <ID1 xsi:type="node">103</ID1> <ID2 xsi:type="node">535</ID2> </child> + <child ID="538" label="i.e. a lens" layerID="1" + created="1484518582413" x="3000.6375" y="699.74475" width="76.0" + height="23.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> + <fillColor>#E6F7FD</fillColor> + <strokeColor>#776D6D</strokeColor> + <textColor>#000000</textColor> + <font>SansSerif-plain-12</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f60c0a801286acbb58b97c6fd0a</URIString> + <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> + </child> + <child ID="539" layerID="1" created="1484518582423" x="3055.4656" + y="673.2446" width="40.17627" height="27.000122" + strokeWidth="1.0" autoSized="false" controlCount="0" + arrowState="2" xsi:type="link"> + <strokeColor>#404040</strokeColor> + <textColor>#404040</textColor> + <font>SansSerif-plain-11</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f61c0a801286acbb58b996c697e</URIString> + <point1 x="3095.1418" y="673.7446"/> + <point2 x="3055.9656" y="699.74475"/> + <ID1 xsi:type="node">393</ID1> + <ID2 xsi:type="node">538</ID2> + </child> + <child ID="540" + label="Could be implemented using the function-updating-binarry-tree trick&#xa;Start from a tree with all positions filled with an empty vector (can be implemented as a single &quot;base&quot; function)&#xa;and then &quot;cons&quot; the non-empty vectors, effectively hiding the empty ones" + layerID="1" created="1484520835681" x="983.63745" y="-145.25525" + width="730.0" height="53.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> + <fillColor>#F2AE45</fillColor> + <strokeColor>#776D6D</strokeColor> + <textColor>#000000</textColor> + <font>SansSerif-plain-12</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f61c0a801286acbb58b2b628a00</URIString> + <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> + </child> + <child ID="541" layerID="1" created="1484520835688" x="1368.2502" + y="-92.75525" width="169.49231" height="223.00012" + strokeWidth="1.0" autoSized="false" controlCount="0" + arrowState="2" xsi:type="link"> + <strokeColor>#404040</strokeColor> + <textColor>#404040</textColor> + <font>SansSerif-plain-11</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f62c0a801286acbb58b19d6b212</URIString> + <point1 x="1537.2426" y="129.74487"/> + <point2 x="1368.7502" y="-92.25525"/> + <ID1 xsi:type="node">353</ID1> + <ID2 xsi:type="node">540</ID2> + </child> + <child ID="542" + label="O(1) memory overhead for each type which is live within an SCC&#xa;O(m) time overhead for access, m being the number of SCCs to traverse before reaching the desired node from its ancestor&#xa;The O(m) factor can probably be turned into a O(log m) with a bit of extra space usage" + layerID="1" created="1484521031023" x="926.63745" y="-235.25525" + width="825.0" height="53.0" strokeWidth="1.0" autoSized="true" xsi:type="node"> + <fillColor>#F2AE45</fillColor> + <strokeColor>#776D6D</strokeColor> + <textColor>#000000</textColor> + <font>SansSerif-plain-12</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f62c0a801286acbb58beacd7655</URIString> + <shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/> + </child> + <child ID="543" layerID="1" created="1484521031026" x="1341.4347" + y="-182.75488" width="4.9055176" height="38.0" strokeWidth="1.0" + autoSized="false" controlCount="0" arrowState="2" xsi:type="link"> + <strokeColor>#404040</strokeColor> + <textColor>#404040</textColor> + <font>SansSerif-plain-11</font> + <URIString>http://vue.tufts.edu/rdf/resource/a46d8f62c0a801286acbb58b90bacc82</URIString> + <point1 x="1345.8402" y="-145.25488"/> + <point2 x="1341.9347" y="-182.25488"/> + <ID1 xsi:type="node">540</ID1> + <ID2 xsi:type="node">542</ID2> + </child> <layer ID="1" label="Layer 1" created="1479309847607" x="0.0" y="0.0" width="1.4E-45" height="1.4E-45" strokeWidth="0.0" autoSized="false"> <URIString>http://vue.tufts.edu/rdf/resource/6dbf6b15c0a80026548592b8d2f3fee2</URIString> </layer> <userZoom>1.0</userZoom> - <userOrigin x="-1829.3625" y="-403.75525"/> + <userOrigin x="-1656.3625" y="-636.75525"/> <presentationBackground>#FFFFFF</presentationBackground> <PathwayList currentPathway="0" revealerIndex="-1"> <pathway ID="0" label="Chemin sans nom" created="1479309847603" diff --git a/alpha-equivalence-normal-form.rkt b/alpha-equivalence-normal-form.rkt @@ -0,0 +1,79 @@ +#lang racket +(let () + ;; Given an order-independent let + (let ([x 'b] + [y 'a]) + (cons x y)) + + ;; e.g. represented roughly as: + (list 'let + (set (cons 'x ''b) (cons 'y ''a)) ;; bindings + (list 'cons 'x 'y)) ;; body + + ;; Can we devise an α-equivalence normal form? + + ;; Let's sort the right-hand side of the let bindings, and number them in that + ;; order. x gets renamed to var1, and y gets renamed to var0, given the order + ;; ('a, 'b) + (let ([var0 'a] + [var1 'b]) + (cons var1 var0)) + + ;; The idea roughly amounts to transforming sets into lists by sorting their + ;; contents, knowing that the sort operation must not depend on unrenamed + ;; variables. Given a letrec, what can we do? + + (let ([x 'b] + [y 'a]) + (letrec ([f (λ (v) (f (cons v x)))] + [g (λ (v) (g (cons v y)))]) + '…)) + + ;; In the example above, x and y can be renamed first, giving var1 and var0 + ;; respectively. Then it becomes possible to sort f and g, as they differ + ;; by their references to var1 and var0 respectively, and these have already + ;; been assigned a new number. + + (letrec ([f (λ (v) (f v))] + [g (λ (v) (f v))]) + '…) + + ;; Here, we have no difference in the values, but there is a difference in the + ;; way these values refer to the bingings: f refers to itself, while g refers to + ;; f. Topologically sorting that graph would give a cannon order. + + (letrec ([f (λ (v) (g v))] + [g (λ (v) (f v))]) + '…) + + ;; Here, there is no difference in the values, and swapping them gives a new + ;; graph isomorphic to the original. Another more complex case follows: + + (letrec ([f (λ (v) (g v))] + [g (λ (v) (h v))] + [h (λ (v) (f v))]) + '…) + + ;; In these cases, the order we assign to each variable does not matter, as they + ;; are strictly symmetric (in the sense that the bound values are at run-time + ;; observarionally identical). + + ;; What general solution can we find? + ;; * What if we topo-sort bindings which cannot be distinguished by their values + ;; * then, within each SCC, if there are some values which are isomorphic to + ;; each other, they can be grouped together for the purpose of numbering. + ;; this operation can be repeated. + ;; * By alternating these two steps, do we systematically get a + ;; topologically-sorted DAG, where some nodes are a group of nodes which were + ;; isomorphic one level down? + ;; + ;; Relevant: + ;; @inproceedings{babai1983canonical, + ;; title={Canonical labeling of graphs}, + ;; author={Babai, L{\'a}szl{\'o} and Luks, Eugene M}, + ;; booktitle={Proceedings of the fifteenth annual ACM symposium on Theory of computing}, + ;; pages={171--183}, + ;; year={1983}, + ;; organization={ACM} + ;; } + (void)) +\ No newline at end of file diff --git a/bench001.rkt b/bench001.rkt @@ -0,0 +1,32 @@ +#lang type-expander/lang +(require (for-syntax racket + phc-toolkit)) + +(struct Or ()) +(define-type-expander (Invariants stx) + (syntax-case stx () + [(_ invᵢ …) + #'(→ (U Or (→ invᵢ Void) …) Void) + #;#'(→ (→ (∩ invᵢ …) Void) Void)])) + + + +(define-syntax (foo stx) + (syntax-case stx () + [(_ T nb) + #`(define-type T + (Invariants + #,@(map (λ (x) #`(List 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j 'k #,x 'm 'n)) + (range (syntax-e #'nb)))))])) +(foo T0 600) +(foo T1 550) + +(define f0 : T0 (λ (x) (void))) + +(define-syntax (repeat stx) + (syntax-case stx () + [(_ n body) + #`(begin #,@(map (const #'body) + (range (syntax-e #'n))))])) +(repeat 100 + (ann f0 T1)) +\ No newline at end of file diff --git a/flexible-with-utils.hl.rkt b/flexible-with-utils.hl.rkt @@ -2,12 +2,14 @@ @(require scribble-math) -@title[#:style manual-doc-style]{Utility math functions for binary tree +@title[#:tag-prefix "utils" + #:style manual-doc-style]{Utility math functions for binary tree manipulation} @(chunks-toc-prefix '("(lib phc-graph/scribblings/phc-graph-implementation.scrbl)" - "phc-graph/flexible-with")) + "phc-graph/flexible-with" + "utils")) @defmodule[(lib "phc-graph/flexible-with-utils.hl.rkt")] diff --git a/flexible-with.hl.rkt b/flexible-with.hl.rkt @@ -1,6 +1,6 @@ #lang aful/unhygienic hyper-literate type-expander/lang -@title[#;#:style #;(with-html5 manual-doc-style) +@title[#:style manual-doc-style ;#:style (with-html5 manual-doc-style) #:tag "flexible-with" #:tag-prefix "phc-graph/flexible-with"]{Flexible functional modification and extension of records} diff --git a/graph-info.rkt b/graph-info.hl.rkt diff --git a/invariants-phantom.hl.rkt b/invariants-phantom.hl.rkt @@ -141,8 +141,8 @@ In addition to testifying that a graph node was checked against multiple, separate contracts, there might be some contracts which check stronger properties than others. A way to encode this relationship in the type system is to have subtyping relationships between the contract witnesses, so that -@; TODO: get rid of the mathit -@${\mathit{P}₁(x) ⇒ \mathit{P}₂(x) ⇒ \mathit{Inv}₁ @texsubtype \mathit{Inv}₂}: +@; TODO: get rid of the textit +@${\textit{P}₁(x) ⇒ \textit{P}₂(x) ⇒ \textit{Inv}₁ @texsubtype \textit{Inv}₂}: @chunk[<invariant-contract-subtyping> (struct InvWeak ()) @@ -336,7 +336,8 @@ having an empty union. (define-type-expander (Invariants stx) (syntax-case stx () [(_ invᵢ …) - #'(→ (U Or (→ invᵢ Void) …) Void)]))] + #'(→ (U Or (→ invᵢ Void) …) Void) + #;#'(→ (→ (∩ invᵢ …) Void) Void)]))] @subsection{Structural (in)equality and (non-)membership invariants} @@ -346,20 +347,87 @@ We define some tokens which will be used to identify the operator which relates two nodes in the graph. @chunk[<comparison-operators> - (struct (A B) inv≡ ([a : A] [b : B])) - (struct (A B) inv≢ ([a : A] [b : B])) + (struct (A) inv≡ ([a : A])) + (struct (A) inv≢ ([a : A])) ;(struct inv∈ ()) ;; Can be expressed in terms of ≡ ;(struct inv∉ ()) ;; Can be expressed in terms of ≢ ] -@chunk[<≡> - (define-type-expander (≡ stx) - (syntax-case stx () - [(_ (patha ...) (pathb ...)) - ;; TODO: probably not just List here, have to think. - #'(inv≡ (List 'patha ...) (List 'pathb ...))]))] - -@; TODO: don't forget to include both directions a = b and b = a (or sort the fields?) +@CHUNK[<≡> + (define-for-syntax (relation inv) + (syntax-parser + [(_ (pre-a … {~literal _} post-a …) + (pre-b … {~literal _} post-b …)) + #:with (r-pre-a …) (reverse (syntax->list #'(pre-a …))) + #:with (r-pre-b …) (reverse (syntax->list #'(pre-b …))) + ;; Use U to make it order-independent + #`(#,inv (U (Pairof (Cycle r-pre-a …) + (Cycle post-a …)) + (Pairof (Cycle r-pre-b …) + (Cycle post-b …))))])) + + (define-type-expander ≡ (relation #'inv≡)) + (define-type-expander ≢ (relation #'inv≢))] + +@chunk[<cycles> + (struct ε () #:transparent) + (struct (T) Target () #:transparent) + (struct (T) NonTarget Target ([x : T]) #:transparent) + + (define-type-expander Cycle + (syntax-parser + [(_ field:id … {~literal ↙} loop1:id … (target:id) loop2:id …) + #'(List* (NonTarget ε) + (NonTarget 'field) … + (Rec R (List* (NonTarget 'loop1) … ;(NonTarget 'loop1) … + (Target 'target) ;(NonTarget 'target) + (NonTarget 'loop2) … ;(NonTarget 'loop2) … + R)))] + [(_ field … target) + ;; TODO: something special at the end? + #'(List (NonTarget ε) (NonTarget 'field) … (Target 'target))] + [(_) + #'(List (Target ε))]))] + +@;{@[ + + ;.a.b = .x.y + ;(l1=a ∧ l2=b ∧ r1=x ∧ r2=y) ⇒ eq + ;¬(l1=a ∧ l2=b ∧ r1=x ∧ r2=y) ∨ eq + ;¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=y ∨ eq + + ;.a.c = .x.y + ;(l1=a ∧ l2=c ∧ r1=x ∧ r2=y) ⇒ eq + + ;.a.c = .x.z + ;(l1=a ∧ l2=b ∧ r1=x ∧ r2=z) ⇒ eq + ;¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=z ∨ eq + + + ;.a.b = .x.y ∧ .a.c = .x.z + ;(¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=y ∨ eq) ∧ (¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=z ∨ eq) + ;¬¬(¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=y ∨ eq) ∧ (¬l1=a ∨ ¬l2=b ∨ ¬r1=x ∨ ¬r2=z ∨ eq) + ;¬(l1=a ∧ l2=b ∧ r1=x ∧ r2=y ∧ eq) ∨ (l1=a ∧ l2=b ∧ r1=x ∧ r2=z ∧ ¬eq) + ]} + +@; Problem with ∩: it factors out too much, (∩ '(a . b) '(a . c) '(x . b)) +@; becomes (Pairof (∩ 'a 'x) (∩ 'b 'c)), which is equivalent to have all four +@; elements of {a,x} × {b,c}, but we only want three out of these four. + +Two sorts of paths inside (in)equality constraints: + +@itemlist[ + @item{those anchored on a node, stating that + @$${ + ∀\ \textit{node} : \textit{NodeType},\quad + \textit{node}.\textit{path}₁ ≡ \textit{node}.\textit{path}₂}} + @item{those not anchored on a node, stating that + @$${ + \begin{array}{c} + ∀\ \textit{node}₁ : \textit{NodeType}₁,\quad + ∀\ \textit{node}₂ : \textit{NodeType}₂,\\ + \textit{node}₁.\textit{path}₁ ≡ \textit{node}₂.\textit{path}₂ + \end{array}}}] @subsection{Putting it all together} @@ -369,27 +437,47 @@ relates two nodes in the graph. [(_ stronger weaker) (syntax/top-loc stx (check-ann (ann witness-value stronger) - weaker))]))] + weaker))])) + + (define-syntax (check-a-same-b stx) + (syntax-case stx () + [(_ a b) + (syntax/top-loc stx + (begin + (check-ann (ann witness-value a) b) + (check-ann (ann witness-value b) a)))]))] @chunk[<*> - (require (for-syntax phc-toolkit)) + (require (for-syntax phc-toolkit/untyped + syntax/parse)) <witness-value> <grouping-invariants> + <cycles> <comparison-operators> <≡> (module+ test (require phc-toolkit) <check-a-stronger-b> - + (ann witness-value (Invariants)) ;; No invariants - (ann witness-value (Invariants (≡ (a) (a b c)))) + (ann witness-value (Invariants (≡ (_ a) (_ a b c)))) - (check-a-stronger-or-same-b (Invariants (≡ (a) (a b c))) + (check-a-stronger-or-same-b (Invariants (≡ (_ a) (_ a b c))) (Invariants)) - (check-a-stronger-or-same-b (Invariants (≡ (a) (a b c)) (≡ (a) (a b d))) - (Invariants (≡ (a) (a b c)))) - (check-a-stronger-or-same-b (Invariants (≡ (a) (a b d)) (≡ (a) (a b c))) - (Invariants (≡ (a) (a b c)))))] + (check-a-same-b (Invariants (≡ (_ a) (_ a b c))) + (Invariants (≡ (_ a b c) (_ a)))) + + (check-a-stronger-or-same-b (Invariants (≡ (_) (_ b c)) + (≡ (_) (_ b d))) + (Invariants (≡ (_) (_ b c)))) + (check-a-stronger-or-same-b (Invariants (≡ (_) (_ b d)) + (≡ (_) (_ b c))) + (Invariants (≡ (_) (_ b c)))) + + (check-a-stronger-or-same-b (Invariants (≡ (_) + (_ b d a b d ↙ a b (d)))) + (Invariants (≡ (_) + (_ b d ↙ a b (d))))))] diff --git a/thoughts.rkt b/thoughts.rkt @@ -0,0 +1,124 @@ +#lang type-expander/lang + +#| +Adding fields to the prefix path makes it weaker +Adding fields to the postfix path makes it stronger + +(Expand prefix postfix) +=> (and prefixᵢ postfix) … +Also could be expanded as: +=> (and prefix postfixᵢ) … + +Rewording ((u pre_x pre_x2) pre_a _ post_b (u post_c post_c2) +=> property holds iff + pre1 = a + and (pre2 = x or pre2 = x2) + and post1 = b + and (post2 = c or post2 = c2) +|# + +(define-type (F A) (I (I A))) +(define-type (I A) (→ A Void)) + +(define-type eqA1 (F (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1) (G 'u2))) + (List (G 'b) (G 'c))))) + +(define-type eqB1 (F (∩ (Pairof (List* (G 'a1) (∩ (G 'u1) (G 'u2))) + (List (G 'b) (G 'c))) + (Pairof (List* (G 'a2) (∩ (G 'u1) (G 'u2))) + (List (G 'b) (G 'c)))))) + +(define-type eqC1 (F (∩ (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1))) + (List (G 'b) (G 'c))) + (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u2))) + (List (G 'b) (G 'c)))))) + +(define-type weakerD1 (F (∩ (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1))) + (List (G 'b) (G 'c)))))) + +(define-type strongerE1 (F (∩ (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1) (G 'u2))) + (∩ (List (G 'b) (G 'c)) + (List (G 'b2) (G 'c))))))) + +(define-type strongerF1 (F (∩ (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1) (G 'u2))) + (Pairof (G 'b) (∩ (List (G 'c)) + (List (G 'c2)))))))) + +(define-type altF1 (F (∩ (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1) (G 'u2))) + (Pairof (G 'b) (List (G 'c)))) + (Pairof (List* (∩ (G 'a1) (G 'a2)) (∩ (G 'u1) (G 'u2))) + (Pairof (G 'b) (List (G 'c2))))))) + +(ann (ann (λ (x) (void)) eqA1) eqB1) +(ann (ann (λ (x) (void)) eqA1) eqC1) +(ann (ann (λ (x) (void)) eqB1) eqA1) +(ann (ann (λ (x) (void)) eqB1) eqC1) +(ann (ann (λ (x) (void)) eqC1) eqA1) +(ann (ann (λ (x) (void)) eqC1) eqB1) +(ann (ann (λ (x) (void)) eqA1) weakerD1) +(ann (ann (λ (x) (void)) eqB1) weakerD1) +(ann (ann (λ (x) (void)) eqC1) weakerD1) +;(ann (ann (λ (x) (void)) eqA1) strongerD1) ;; rejected, as it should +(ann (ann (λ (x) (void)) strongerE1) eqA1) +;(ann (ann (λ (x) (void)) eqA1) strongerE1) ;; rejected, as it should +(ann (ann (λ (x) (void)) strongerF1) eqA1) +;(ann (ann (λ (x) (void)) eqA1) strongerF1) ;; rejected, as it should +(ann (ann (λ (x) (void)) altF1) eqA1) +;(ann (ann (λ (x) (void)) eqA1) altF1) ;; rejected, as it should +(ann (ann (λ (x) (void)) altF1) strongerF1) +(ann (ann (λ (x) (void)) strongerF1) altF1) + + + + +(let () + (define-type eqA2 (F (case→ (→ (List 'b 'c) 'a1) + (→ (List 'b 'c) 'a2)))) + + (define-type eqB2 (F (case→ (→ (List 'b 'c) + (U 'a1 'a2))))) + + (ann (ann (λ (x) (void)) eqA2) eqB2) + #;(ann (ann (λ (x) (void)) eqB2) eqA2)) + +;(let () +(define-type (G A) (F A)) +(define-type-expander (+ stx) (syntax-case stx () [(_ . rest) #'(∩ . rest)])) +(define-type-expander (* stx) (syntax-case stx () [(_ . rest) #'(U . rest)])) + +(define-type eqA2 (F (+ (* (G 'b) (G 'c) (G 'a1)) + (* (G 'b) (G 'c) (G 'a2))))) + +(define-type eqB2 (F (+ (* (G 'b) (G 'c) (+ (G 'a1) (G 'a2)))))) + +(define-type Weaker2 (F (+ (* (G 'b) (G 'c) (G 'a1))))) + +(ann (ann (λ (x) (void)) eqA2) eqB2) +(ann (ann (λ (x) (void)) eqB2) eqA2) +(ann (ann (λ (x) (void)) eqA2) Weaker2) +(ann (ann (λ (x) (void)) eqB2) Weaker2) +;(ann (ann (λ (x) (void)) Weaker2) eqA2) +;(ann (ann (λ (x) (void)) Weaker2) eqB2) +;) + + + +(let () + (define-type weaker3 + (F (∩ (G (Rec R (List* 'a Any R))) + (G (Rec R (List* Any 'b R)))))) + (define-type stronger3 + (F (∩ (G (List* 'a Any (Rec R (List* 'a Any R)))) + (G (List* Any 'b (Rec R (List* Any 'b R))))))) + + (ann (ann (λ (x) (void)) stronger3) weaker3) + ) + +#| +Put the U ∩ inside the positional list? +What about loops of different sizes => won't work +What about merging all the invariants blindly => won't work, but we can +special-case merging these regexp-like invariants, as long as the merging +doesn't need any info about the regexp itself +(e.g. all are "merge the second elements") +|# +\ No newline at end of file diff --git a/traversal.hl.rkt b/traversal.hl.rkt @@ -25,7 +25,7 @@ @title[#:style manual-doc-style #:tag "traversal" #:tag-prefix "phc-graph/traversal"]{Parametric replacement of parts of - data structures, identified by their type} + data structures} @(chunks-toc-prefix '("(lib phc-graph/scribblings/phc-graph-implementation.scrbl)"