-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexport.scm
130 lines (102 loc) · 3.59 KB
/
export.scm
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
;;----------------------------------------------------------------
;; Facililities for "exporting" functions to Minion
;;----------------------------------------------------------------
(require "core")
(define *var-functions* nil)
;; Mark a function as safe to be replaced with a variable reference
;; $(call FN,$1) -> $(FN)
;; $(call FN,$1,$2) -> $(FN)
;; Must be non-recursive, and must not have optional arguments.
;;
(define (VF! fn-name)
&public
(set *var-functions*
(append *var-functions* fn-name)))
(define single-chars
(.. "a b c d e f g h i j k l m n o p q r s t u v w x y z "
"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
";"))
;; Rename variable references and "foreach" bindings
;;
(define (rename-vars fn-body froms tos)
(define `(var-ref name)
(if (filter single-chars name)
(.. "$" name)
(.. "$(" name ")")))
(define `from (word 1 froms))
(define `to (word 1 tos))
(define `renamed
(subst (.. "foreach " from ",") (.. "foreach " to ",")
(var-ref from) (var-ref to)
fn-body))
(if froms
(rename-vars renamed (rest froms) (rest tos))
fn-body))
(expect (rename-vars "$(foreach a,bcd,$(foreach bcd,a $a,$(bcd)))"
"a bcd" "A BCD")
"$(foreach A,bcd,$(foreach BCD,a $A,$(BCD)))")
;; Collapse function calls into variable references.
;;
(define (omit-calls body)
(foldl (lambda (text fname)
(subst (.. "$(call " fname ")")
(.. "$(" fname ")")
(.. "$(call " fname ",$1)")
(.. "$(" fname ")")
(.. "$(call " fname ",$1,$2)")
(.. "$(" fname ")")
(.. "$(call " fname ",$1,$2,$3)")
(.. "$(" fname ")")
(.. "$(call " fname ",$1,$2,$3,$4)")
(.. "$(" fname ")")
text))
body
*var-functions*))
(define *exports* nil)
;; Mark FN-NAME as a function to be exported to Minion, and perform
;; relevant translations.
;;
(define (export fn-name is-vf ?vars-to-in ?vars-from-in)
&public
;; Avoid ";" because Minion uses `$;` for ","
(define `vars-to (or vars-to-in "w x"))
(define `vars-from (or vars-from-in "; ;; ;;; ;;;; ;;;;;"))
(if is-vf
(VF! fn-name))
(set-native-fn fn-name
(omit-calls
(rename-vars (native-value fn-name) vars-from vars-to)))
(set *exports* (conj *exports* fn-name)))
(define (export-text text)
&public
(set *exports* (conj *exports* (.. "=" text))))
;; Output a SCAM function as Make code, renaming automatic vars.
;;
(define (get-export fn-name)
&public
(define `minionized
(subst "$ " "$(\\s)" ;; SCAM runtime -> Minionese
"$ \t" "$(\\t)" ;; SCAM runtime -> Minionese
"$ " "" ;; not needed to avoid keywords in "=" defns
"$(if ,,,)" "$;" ;; SCAM runtime -> Minionese
"$(if ,,:,)" ":$;" ;; SCAM runtime -> Minionese
"$(&)" "$&" ;; smaller, isn't it?
"$`" "$$" ;; SCAM runtime -> Minionese
(native-value fn-name)))
(define `escaped
(subst "\n" "$(\\n)" "#" "\\#" minionized))
(if (filter "s%" (native-flavor fn-name))
(.. fn-name " := " (subst "$" "$$" (native-var fn-name)))
(.. fn-name " = " escaped)))
(define (get-exports)
&public
(foreach (e *exports* "\n")
(if (filter "=%" e)
(.. "\n" (first (patsubst "=%" "%" e)) "\n")
(get-export (first e)))))
(define (show-export fn-name)
&public
(print (get-export fn-name)))
(define (show-exports)
&public
(print (get-exports)))