1
+ (* ****** ****** *)
2
+
3
+ #include
4
+ "share/atspre_staload.hats"
5
+
6
+ (* ****** ****** *)
7
+ //
8
+ sortdef t0p = t@ype
9
+ sortdef vt0p = viewt@ype
10
+ //
11
+ (* ****** ****** *)
12
+ //
13
+ absview
14
+ dlnode_v (
15
+ l: addr, lp: addr, ln: addr // lp: previous; ln: next
16
+ ) // end of [dlnode_v]
17
+ //
18
+ prfun
19
+ dlnode_ptr_is_gtz
20
+ {l,lp,ln:addr}
21
+ (pf: ! dlnode_v (l, lp, ln)): [l > null] void
22
+ // end of [dlnode_ptr_is_gtz]
23
+ //
24
+ (* ****** ****** *)
25
+ //
26
+ dataview
27
+ dlfseg_v (
28
+ int(*len*)
29
+ , addr(*leftmost*)
30
+ , addr(*prev of leftmost*)
31
+ , addr(*rightmost*)
32
+ , addr(*next of rightmost*)
33
+ ) =
34
+ | {n:nat}
35
+ {lf,lfp:addr}
36
+ {lr,lrn:addr}
37
+ {lfn:addr}
38
+ dlfseg_v_cons (n+ 1 , lf, lfp, lr, lrn) of (
39
+ dlnode_v (lf, lfp, lfn), dlfseg_v (n, lfn, lf, lr, lrn)
40
+ ) // end of [dlfseg_v_cons]
41
+ | {lf:addr}
42
+ {lr:addr}
43
+ // why is this cyclic??? lf, lr, lr, lf?
44
+ // because it's a segment! a segment is a portion of a list
45
+ dlfseg_v_nil (0 , lf, lr, lr, lf) of ()
46
+ // end of [dlfseg_v]
47
+
48
+ // NOTE: unproven, because to show this, we'd have to always assume and check
49
+ // that at-proofs don't alias (and they don't!)
50
+ prfun
51
+ dlfseg_lemma3 {n:nat} {lf,lfp,lr,lrn:addr} (
52
+ pf_dl: ! dlfseg_v (n, lf, lfp, lr, lrn)
53
+ ):<> [n == 0 && lf == lrn || n > 0 && lf != lrn] void
54
+ (*
55
+ primplement dlfseg_lemma3 {n} {lf,lfp,lr,lrn} (pf_dl) =
56
+ case pf_dl of
57
+ | dlfseg_v_nil () => let val () = pf_dl := dlfseg_v_nil () in end
58
+ | dlfseg_v_cons (pf_at, pf1_dl) => let val () = pf_dl := dlfseg_v_cons (pf_at, pf1_dl) in end
59
+ *)
60
+ (* ****** ****** *)
61
+
62
+ dataview
63
+ dlrseg_v (
64
+ int(*size*)
65
+ , addr(*leftmost*)
66
+ , addr(*prev of leftmost*)
67
+ , addr(*rightmost*)
68
+ , addr(*next of rightmost*)
69
+ ) =
70
+ | {n:nat}
71
+ {lf,lfp:addr}
72
+ {lr,lrn:addr}
73
+ {lrp:addr}
74
+ dlrseg_v_cons (n+ 1 , lf, lfp, lr, lrn) of (
75
+ dlrseg_v (n, lf, lfp, lrp, lr), dlnode_v (lr, lrp, lrn)
76
+ ) // end of [dlrseg_v_cons]
77
+ | {lf:addr}
78
+ {lr:addr}
79
+ dlrseg_v_nil (0 , lf, lr, lr, lf) of ()
80
+ // end of [dlrseg_v]
81
+
82
+ (* ****** ****** *)
83
+
84
+ // API?
85
+ // - insert new node after head, or before head
86
+ // - fmap (forward or backwards)
87
+ // - iterator (begin/end ptrs)
88
+ // - deep copy
89
+ // - circular list to array and vice versa
90
+ // - is_empty, pop front, pop back, takeout the head node for mutation
91
+ // - length
92
+ // - find first that satisfies a predicate
93
+ // - concat two circular lists
94
+ // http://www.dcs.bbk.ac.uk/~trevor/FoC/NOTES/notes1%20lists%20p9_13.pdf
95
+
96
+ // next: what about singly-linked lists? these could also get a similar treatment!
97
+ // library of pointer-linked data structures for ATS! also giving users complete
98
+ // control over memory layout (this should be QUITE useful for gaming/simulation)
99
+
100
+ // what about e.g. portals-cells?
101
+ // - cells are nodes of a graph
102
+ // - portals are arcs connecting two cells
103
+ // how to represent that?
104
+ // - there can be MANY references to a cell...
105
+
106
+ (* ****** ****** *)
107
+
108
+ // forward-navigating circular list: either NULL, or a head element
109
+ // followed by up to N elements, ending at the head
110
+ dataview dlfcircular_v (int, addr) =
111
+ | {n:nat}
112
+ {lf:agz;lfn,lr:addr}
113
+ dlfcircular_v_some (n+ 1 , lf) of (
114
+ dlnode_v (lf, lr, lfn)
115
+ , dlfseg_v (n, lfn, lf, lr, lf)
116
+ ) (* end of [dlcircular_v_some] *)
117
+ | dlfcircular_v_none (0 , null)
118
+
119
+ (* ****** ****** *)
120
+ // functions that every client must implement
121
+
122
+ // NOTE: this should actually be moved somewhere else, we should not
123
+ // dictate to clients the memory layout of the node
124
+ vtypedef dlnode0_vt = @{x= int, p= ptr null, n= ptr null}?
125
+ vtypedef dlnode_vt (lp:addr, ln:addr) = @{x= int, p= ptr lp, n= ptr ln}
126
+
127
+ fun dlnode_alloc ():<> [l:addr] (dlnode0_vt @ l, mfree_gc_v (l) | ptr l)
128
+ fun dlnode_init {l,lp,ln:addr} (
129
+ mfree_gc_v (l), dlnode0_vt @ l
130
+ | ptr l, int, ptr lp, ptr ln
131
+ ): (dlnode_v (l, lp, ln) | void)
132
+ fun dlnode_free {l:addr} (pfgc: mfree_gc_v (l), pfat: dlnode0_vt @ l | p: ptr l):<> void
133
+ //
134
+ fun
135
+ dlnode_ptr_next {l,lp,ln:addr} (! dlnode_v (l, lp, ln) | ptr l): ptr ln
136
+ fun
137
+ dlnode_ptr_prev {l,lp,ln:addr} (! dlnode_v (l, lp, ln) | ptr l): ptr lp
138
+ fun
139
+ dlnode_ptr_value {l,lp,ln:addr} (! dlnode_v (l, lp, ln) | ptr l): int
140
+ //
141
+ fun
142
+ dlnode_ptr_free {l,lp,ln:addr} (dlnode_v (l, lp, ln) | ptr l): void
143
+ //
144
+ fun
145
+ fprint_dlnode_ptr {l,lp,ln:addr} (! dlnode_v (l, lp, ln) | FILEref, ptr l): void
146
+ //
147
+ (* ****** ****** *)
148
+ // functions provided by the library
149
+
150
+ //
151
+ fun {}
152
+ fprint_dlfcircular$sep (out: FILEref): void
153
+ //
154
+ fun {}
155
+ fprint_dlfcircular {n:int} {l:addr} (! dlfcircular_v (n, l) | out: FILEref, ptr l): void
156
+ //
157
+ fun {}
158
+ fprint_dlfcircular_sep {n:int} {l:addr}
159
+ (
160
+ ! dlfcircular_v (n, l)
161
+ | out: FILEref
162
+ , ptr l
163
+ , sep: NSH(string)
164
+ ) : void // end of [fprint_dlfcircular_sep]
165
+ //
166
+ fun
167
+ dlfcircular_ptr_length {n:int} {l:addr} (! dlfcircular_v (n, l) | ptr l): int n
168
+ //
169
+ fun
170
+ dlfcircular_ptr_free {n:int} {l:addr} (dlfcircular_v (n, l) | ptr l): void
171
+ //
0 commit comments