public
Description: Arc Lisp to C compiler
Homepage:
Clone URL: git://github.com/sacado/arc2c.git
arc2c / rm-global.arc
100644 82 lines (79 sloc) 2.832 kb
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
; rm-global.arc
; by AmkG
; partial dead code elimination - unused global removal
;
; removes assignments to globals, if the global
; is not read. Also removes bits of the program
; that won't return any values and have side effects,
; such as docstrings.
 
(def rm-global (ast)
  (with (writeset (gv-set ast)
         readset (gv-read ast)
         ; private functions
         remove-consts nil
         remove-assigns nil)
    ; removes assigments to variables in the
    ; toremove set
    (= remove-assigns
       (fn (toremove ast)
         ; if it's an assignment, and it's one of
         ; the assigments to remove, then remove the
         ; enclosing assignment: remember that we need
         ; to handle the case:
         ; (set used-global (set unused-global value))
         ; =>
         ; (set used-global value)
         (if
           (and (aset ast) (some ast!var toremove))
             (car ast!subx)
           (aquote ast)
             ast
             (do
               (= ast!subx (map [remove-assigns toremove _] ast!subx))
               ast))))
    ; removes constants and other no-side-effect code
    ; from within sequences
    (= remove-consts
       (fn (ast)
         (if
           (aseq ast)
             (do
               (= ast!subx
                  ((afn ((ast . rest))
                     (if
                       rest
                       ; check if ast can't have side-effects
                       ; Note: this test is the most important
                       ; part of the dead-code elimination
                       ; If we can detect that something won't have
                       ; an effect if it isn't the return value,
                       ; then we can eliminate it
                         (if ((orf alit aref aquote alam) ast)
                             (self rest)
                             (cons (remove-consts ast) (self rest)))
                       ; tails are always useful
                       ast
                         (cons (remove-consts ast) nil)))
                   ast!subx))
               ast)
           (aquote ast)
             ast
             (do
               (= ast!subx (map remove-consts ast!subx))
               ast))))
    (aif
      ; remove any global variables written that
      ; aren't read
      (diff writeset readset)
        (rm-global:remove-consts:remove-assigns it ast)
      ; if there's anything read that isn't written,
      ; raise exception
      (diff readset writeset)
        ; allow some undefined globals: these are inserted later in
        ; the transformation
        (if (all [in _!uid 'ccc '<arc2c>!apply] it)
          ast
          (err:tostring:pr "Global variables read, but aren't assigned to: "
                           (map [_ 'uid] it)))
      ; else continue
        ast)))