aboutsummaryrefslogtreecommitdiff
path: root/module/c/flatten-begin.scm
blob: 7543a5ac56a969b86314816e073b3fc041aa5017 (plain)
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
(define-module (c flatten-begin)
  :use-module (srfi srfi-1)
  :use-module (ice-9 match)
  :use-module (ice-9 control)
  :export (flatten-begin remove-invalid-struct-like-declarations))

(define (flatten-begin-1 forms)
  (append-map
   (lambda (form)
     (match form
       (('begin x ...) x)
       (x (list x))))
   forms))

(define (flatten-begin form)
  (match form
    (`(begin ,x) (flatten-begin x))
    (`(let () ,('let '() x ...)) `(let () ,(flatten-begin x)))
    (('begin forms ...)
     `(begin ,@(map flatten-begin
                    (flatten-begin-1 forms))))
    (('let '() forms ...)
     `(let () ,@(map flatten-begin
                     (flatten-begin-1 forms))))
    ;; switch already has to traverse subforms in order to find its labels.
    ;; See (for example) Duff's device
    ;; (`(switch ,x (begin ,('let '() forms ...)))
    ;;  `(let () (switch ,(flatten-begin x)
    ;;                   ,@(map flatten-begin (flatten-begin-1 forms)))))
    ((x ...) (map flatten-begin x))
    (x x)))



;; [A]
;; ((type (struct
;;            (named s)
;;          (struct-declaration-list
;;           (struct-declarator-list
;;            (named x
;;                   (specifier-qualifier-list
;;                    (type int))))))))))


(define (tree-valid? tree abandon)
  (match tree
    (`(struct-like-declaration ((type ,('struct body ...))))
     `(struct-like-declaration ((type (struct ,@(tree-valid? body abandon))))))
    (`(struct-like-declaration ((type ,('union body ...))))
     `(struct-like-declaration ((type (union ,@(tree-valid? body abandon))))))
    (('struct-like-declaration body ...)
     (abandon #f))
    (('struct-declaration-list body ...)
     ;; Filters out case [A]
     (for-each (match-lambda
                 (`(specifier-qualifier-list (type ,((or 'struct 'union) body ...)))
                  'noop)
                 (('specifier-qualifier-list body ...)
                  (abandon #f))
                 (_ 'noop))
               body)
     `(struct-declaration-list ,@(tree-valid? body abandon)))
    ((a b ...)
     (cons (tree-valid? a abandon)
           (tree-valid? b abandon)))
    (x x)))

(define (remove-invalid-struct-like-declarations lst)
  (filter-map (lambda (tree)
                (call/ec (lambda (abandon) (tree-valid? tree abandon))))
              lst))