-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstrategy-stratego.rkt
97 lines (72 loc) · 1.99 KB
/
strategy-stratego.rkt
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
#lang racket/base
#|
A Stratego-inspired strategic-term-rewriting API.
|#
(require "strategy.rkt" "util.rkt")
;; Identity strategy. Named `id` in Stratego.
(define* (id-rw ast) ast)
;; Failure strategy. Named `fail` in Stratego.
(define* (fail-rw ast) #f)
;; Sequential composition.
;; Uses Kiama naming rather than |;| of Stratego.
(define-syntax-rule* (<* s ...)
(lambda (ast)
(and (begin
(set! ast (s ast))
ast) ...
ast)))
;; Deterministic choice.
(define-syntax-rule* (<+ s ...)
(lambda (ast)
(or (s ast) ...)))
;; Tries a rewrite, restoring original term on failure.
(define* (try s)
(lambda (ast)
(or (s ast) ast)))
;; Test strategy.
;; Tries a rewrite, but restores original term on success.
(define* (where s)
(lambda (ast)
(and (s ast) ast)))
;; Negated test strategy.
(define* (where-not s)
(lambda (ast)
(if (s ast) #f ast)))
(define* (when-rw c s)
(lambda (ast)
(if (c ast)
(s ast)
ast)))
;; Recursive closure, like "rec x(s)" in Stratego.
(define-syntax-rule* (rec x s)
(lambda (ast)
(letrec ([x s])
(x ast))))
(define* (repeat s)
(rec x (try (<* s x))))
;; Turns a function `f` with a signature of the form (f s ast) into a
;; strategy combinator.
(define* (((make-strategy f) s) ast)
(f s ast))
;; Strategies for sub-term rewrites.
(define* all (make-strategy term-rewrite-all))
(define* some (make-strategy term-rewrite-some))
(define* one (make-strategy term-rewrite-one))
(define* (topdown s [all all])
(rec x (<* s (all x))))
(define* (bottomup s [all all])
(rec x (<* (all x) s)))
(define* (downup s [all all])
(rec x (<* s (all x) s)))
(define* (onebu s [one one])
(rec x (<+ (one x) s)))
(define* (downup2 s1 s2 [all all])
(rec x (<* s1 (all x) s2)))
(define* (alltd s [all all])
(rec x (<+ s (all x))))
(define* (oncetd s [one one])
(rec x (<+ s (one x))))
(define* (sometd s [some some])
(rec x (<+ s (some x))))
(define* (somebu s [some some])
(rec x (<+ (some x) s)))