aboutsummaryrefslogtreecommitdiff
path: root/sucl/history.icl
blob: 2482b5a97b1b7a0cbf8d15a3c2c8a39784bdd5d5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
implementation module history

// $Id$

import spine
import rule
import graph
import pfun
import basic
from general import Optional,Yes,No
import StdEnv

// A history relates node-ids in the subject graph to patterns
:: History sym var
   :== [HistoryAssociation sym var]

// An association between a node-id in the subject graph and a history pattern
:: HistoryAssociation sym var
   :== ( var                    // Attachment point in the subject graph where the history pattern is "housed"
       , HistoryPattern sym var // The pattern in the history
       )

// A pattern in the history, specifying the most general subject graph (footprint) for a reduction sequence
:: HistoryPattern sym var
   = Closed sym [HistoryPattern sym var]    // Indicates a closed node-id in the subject graph (created by a (partial) match)
   | OpenHist                               // Indicates an open node-id in the subject graph (created by instantiation)
   | Extensible (Link var)                  // Indicates a link to an untouched node-id in the subject graph, where this pattern can be extended

// A link in a graph, indicated by its source node-id and the argument number
// The root of a graph can be indicated by the No constructor
:: Link var
   :== Optional (var,Int)


/*********************************************
* Extending the history according to a spine *
*********************************************/

// A function that associates specific patterns with extensible nodes
// To be used for extending history patterns
:: LinkExtender sym var
   :== (Link var)               // The extensible link to look for
    -> HistoryPattern sym var   // The associated pattern

extendhistory
 :: (Graph sym var)         // Subject graph
    (Spine sym var pvar)    // Spine leading to the reduction operation
    (History sym var)       // Old history
 -> History sym var         // New history
 |  == sym
 &  == var
 &  == pvar

extendhistory sgraph spine history
 = [newpattern:touchmod history]
   where (newpattern,_,extender)
          = foldspine extendpair extenddefault extenddefault (extendforce sgraph) extenddefault extendopen (extendpartial sgraph) (const extenddefault) (extendredex sgraph) extenddefault spine No Extensible
         touchmod = map (mapsnd (patextend extender))

patextend
 :: (LinkExtender sym var)
    (HistoryPattern sym var)
 -> HistoryPattern sym var

patextend extender (Closed sym args) = Closed sym (map (patextend extender) args)
patextend extender OpenHist = OpenHist
patextend extender (Extensible link) = extender link

extendpair
 :: var                         // Subject node-id where spine is rooted
    (  var
       (Link var)
       (LinkExtender sym var)
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var
       , LinkExtender sym var
       )
    )
    (Link var)                  // Link in subject graph to this spine
    (LinkExtender sym var)      // Input link extender
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var    // Returned history pattern
    , LinkExtender sym var      // Returned link extender
    )

extendpair snode extendsub link extender
 = extendsub snode link extender

extenddefault
 :: var
    (Link var) 
    (LinkExtender sym var)
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var
    , LinkExtender sym var
    )
extenddefault _ link extender
 = (nonewpattern,Extensible link,extender)
   where nonewpattern = abort "history: extenddefault: no new pattern for default spine"

// Extend history for a Force spine
// FIXME: For now, only look at function node and to-be-strict argument
//        Forget what was already determined strict
extendforce
 :: (Graph sym var)
    Int
    (  (Link var)
       (LinkExtender sym var)
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var
       , LinkExtender sym var
       )
    )
    var
    (Link var)
    (LinkExtender sym var)
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var
    , LinkExtender sym var
    )
 |  == var

extendforce sgraph argno forcesub snode link extender0
 | not sdef
   = abort "history: extendforce: force from open node-id???"
 = (newpattern,histpat1,extender2)
   where (newpattern,histpat0,extender1) = forcesub (Yes (snode,argno)) extender0
         histpat1 = Closed ssym [argpat i \\ i <- [0..] & _ <- sargs]
         argpat i
          = if (i==argno) histpat0 (Extensible (Yes (snode,i)))
         (sdef,(ssym,sargs)) = varcontents sgraph snode
         extender2 = adjust link histpat1 extender1

// Extend history patterns according to an Open spine
extendopen
 :: rgraph                      // Pattern to drive instantiation (not used)
    var                         // Node-id in subject graph that was open
    (Link var)                  // Where subject graph pointed to this open node-id
    (LinkExtender sym var)      // Input link extender
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var    // Pattern for this spine
    , LinkExtender sym var      // Resulting link extender
    )
 |  == var

extendopen _ snode link extender0
 = (newpattern,histpat,extender1)
   where histpat = OpenHist
         newpattern = (snode,histpat)
         extender1 = adjust link histpat extender0

extendpartial
 :: (Graph sym var)             // Subject graph
    (Rule sym pvar)             // Applied rewrite rule
    (Pfun pvar var)             // Partial match from rewrite rule's pattern to subject graph
    pvar                        // Node-id in rule where partial match went to subspine
    (  (Link var)               // Link passed to subspine handler
       (LinkExtender sym var)   // Link extender input to subspine handler
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var // Pattern returned for subspine
       , LinkExtender sym var   // Link extender returned for subspine
       )
    )
    var                         // Node-id in subject with function application
    (Link var)                  // Link to root of partial match in subject graph
    (LinkExtender sym var)      // Remaining link extender
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var    // History patterns with derived pattern prefixed
    , LinkExtender sym var      // Extended link extender
    )
 |  == sym
 &  == var
 &  == pvar

extendpartial sgraph rule matching subnode extendsub snode link restextender
 = extendfunction sgraph rule matching ((==)subnode) (const extendsub) snode link restextender

extendredex
 :: (Graph sym var)             // Subject graph
    (Rule sym pvar)             // Applied rewrite rule
    (Pfun pvar var)             // Partial match from rewrite rule's pattern to subject graph
    var                         // Root of redex in subject graph
    (Link var)                  // Link to root of redex in subject graph
    (LinkExtender sym var)      // Remaining link extender
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var    // History patterns with derived pattern prefixed
    , LinkExtender sym var      // Extended link extender
    )
 |  == sym
 &  == var
 &  == pvar

extendredex sgraph rule matching snode link extender
 = extendfunction sgraph rule matching (const False) nosub snode link extender
   where nosub = abort "history: extendredex: full match with subspine??"

extendfunction
 :: (Graph sym var)             // Subject graph
    (Rule sym pvar)             // Applied rewrite rule
    (Pfun pvar var)             // Partial match from rewrite rule's pattern to subject graph
    (pvar -> Bool)              // Checks whether the subspine applies here
    (  (HistoryAssociation sym var)
       (Link var)               // Link passed to subspine handler
       (LinkExtender sym var)   // Link extender input to subspine handler
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var // Pattern returned for subspine
       , LinkExtender sym var   // Link extender returned for subspine
       )
    )
    var                         // Root of partial match in subject graph
    (Link var)                  // Link to root of partial match in subject graph
    (LinkExtender sym var)      // Remaining link extender
 -> ( HistoryAssociation sym var
    , HistoryPattern sym var    // History patterns with derived pattern prefixed
    , LinkExtender sym var      // Extended link extender
    )
 |  == sym
 &  == var
 &  == pvar

extendfunction sgraph rule matching issub extendsub snode link extender0
 | not sdef
   = abort "history: extendfunction: partial or full match at open node-id???"
 = (newpattern,thispat,extender2)
   where extender2 = adjust link thispat extender1
         thispat = Closed ssym argpatts
         (newpattern,argpatts,extender1) = extendnodes sgraph rgraph matching snode issub extendsub thisnewpattern extender0 rargs
         (sdef,(ssym,_)) = varcontents sgraph snode
         rgraph = rulegraph rule
         rargs = arguments rule
         thisnewpattern = (snode,thispat)

extendnodes
 :: (Graph sym var)             // Subject graph
    (Graph sym pvar)            // Applied rewrite rule
    (Pfun pvar var)             // Partial match from rewrite rule's pattern to subject graph
    var                         // Parent node-id in subject graph to this node-id list for creating links
    (pvar -> Bool)              // Tells if this is where the subspine was attached
    (  (HistoryAssociation sym var)
       (Link var)               // Link passed to subspine handler
       (LinkExtender sym var)   // Link extender input to subspine handler
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var // Pattern returned for subspine
       , LinkExtender sym var   // Link extender returned for subspine
       )
    )
    (HistoryAssociation sym var)
    (LinkExtender sym var)      // Remaining link extender
    [pvar]                      // Node-ids in rule to handle
 -> ( HistoryAssociation sym var
    , [HistoryPattern sym var]  // History patterns with derived pattern prefixed
    , LinkExtender sym var      // Extended link extender
    )
 |  == sym
 &  == var
 &  == pvar

extendnodes sgraph rgraph matching sparent issub extendsub newpattern restextender rnodes
 = foldr (extendnode sgraph rgraph matching issub extendsub) (newpattern,[],restextender) (zip2 links rnodes)
   where links = [Yes (sparent,i)\\i<-[0..]]

extendnode
 :: (Graph sym var)                 // Subject graph
    (Graph sym pvar)                // Applied rewrite rule
    (Pfun pvar var)                 // Partial match from rewrite rule's pattern to subject graph
    (pvar -> Bool)                  // Tells if this is where the subspine was attached
    (  (HistoryAssociation sym var)
       (Link var)                   // Link passed to subspine handler
       (LinkExtender sym var)       // Link extender input to subspine handler
    -> ( HistoryAssociation sym var
       , HistoryPattern sym var     // Pattern returned for subspine
       , LinkExtender sym var       // Link extender returned for subspine
       )
    )
    ( Link var                      // Referring link to current node-id
    , pvar                          // Current node-id in rule
    )
    ( HistoryAssociation sym var
    , [HistoryPattern sym var]      // History patterns to prefix derived patterns to
    , (LinkExtender sym var)        // Remaining link extender
    )
 -> ( HistoryAssociation sym var
    , [HistoryPattern sym var]      // History patterns with derived pattern prefixed
    , (LinkExtender sym var)        // Extended link extender
    )
 |  == sym
 &  == var
 &  == pvar

extendnode sgraph rgraph matching issub extendsub (link,rnode) (newpattern0,rest,extender0)
 | issub rnode
   = (subnewpattern,[subpattern:rest],subextender)
 | rdef
   = foldpfun mapped unmapped matching rnode
 = unmapped
   where (subnewpattern,subpattern,subextender)
          = extendsub newpattern0 link extender0
         mapped snode
          = (newpattern1,[thispat:rest],extender2)
            where extender2 = adjust link thispat extender1
                  thispat = Closed rsym argpatts
                  (newpattern1,argpatts,extender1) = extendnodes sgraph rgraph matching snode issub extendsub newpattern0 extender0 rargs
         unmapped
          = (newpattern0,[Extensible link:rest],extender0)
         (rdef,(rsym,rargs)) = varcontents rgraph rnode


/************************************************
* Verifying a subject graph against the history *
************************************************/

matchhistory
 :: (History sym var)           // Complete history against which to check
    [var]                       // Node-ids for which to include history patterns
    (Graph sym var)             // Current subject graph
    var                         // Current application point of strategy
 -> [HistoryPattern sym var]    // Matching history patterns
 |  == sym
 &  == var

matchhistory hist spinenodes sgraph snode
 = foldr (checkassoc spinenodes sgraph snode) [] hist

checkassoc spinenodes sgraph snode (var,pat) rest
 | isMember var spinenodes && checkpat sgraph pat snode
   = [pat:rest]
 = rest

checkpat :: (Graph sym var) (HistoryPattern sym var) var -> Bool | == sym & == var
checkpat sgraph (Closed psym pargs) snode
 # (sdef,(ssym,sargs)) = varcontents sgraph snode
 = sdef && psym==ssym && eqlen pargs sargs && and [checkpat sgraph parg sarg \\ parg<-pargs & sarg<-sargs]
checkpat sgraph OpenHist snode
 = not (fst (varcontents sgraph snode))
checkpat _ (Extensible _) _
 = True


/****************
* Miscellaneous *
****************/

instance == (Optional a) | == a
 where (==) No No = True
       (==) (Yes x1) (Yes x2) = x1==x2
       (==) _ _ = False