3 ;; Copyright (C) 2001 Free Software Foundation, Inc.
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program; see the file COPYING. If not, write to
17 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 ;; Boston, MA 02111-1307, USA.
22 (define-module (language elisp compile-tree-il)
23 #:use-module (language tree-il)
24 #:use-module (system base pmatch)
25 #:export (compile-tree-il))
28 ; Find the source properties of some parsed expression if there are any
33 (let ((props (source-properties x)))
34 (and (not (null? props))
38 ; Value to use for Elisp's nil and t.
40 (define (nil-value loc) (make-const loc #f))
41 (define (t-value loc) (make-const loc #t))
44 ; Modules that contain the value and function slot bindings.
46 (define runtime '(language elisp runtime))
47 (define value-slot '(language elisp runtime value-slot))
48 (define function-slot '(language elisp runtime function-slot))
51 ; Error reporting routine for syntax/compilation problems.
53 (define (report-error loc . args)
57 ; Generate code to ensure a fluid is there for further use of a given symbol.
59 (define (ensure-fluid! loc sym module)
64 ; Generate code to reference a fluid saved variable.
66 (define (reference-variable loc sym module)
68 (list (ensure-fluid! loc sym module)
69 (make-application loc (make-primitive-ref loc 'fluid-ref)
70 (list (make-module-ref loc module sym #f))))))
73 ; Reference a variable and error if the value is void.
75 (define (reference-with-check loc sym module)
77 (make-let loc '(value) `(,var) `(,(reference-variable loc sym module))
79 (make-application loc (make-primitive-ref loc 'eq?)
80 (list (make-module-ref loc runtime 'void #t)
81 (make-lexical-ref loc 'value var)))
82 (make-application loc (make-primitive-ref loc 'error)
83 (list (make-const loc "variable is void:")
84 (make-const loc sym)))
85 (make-lexical-ref loc 'value var)))))
88 ; Generate code to set a fluid saved variable.
90 (define (set-variable! loc sym module value)
92 (list (ensure-fluid! loc sym module)
93 (make-application loc (make-primitive-ref loc 'fluid-set!)
94 (list (make-module-ref loc module sym #f)
98 ; Compile a symbol expression. This is a variable reference or maybe some
99 ; special value like nil.
101 (define (compile-symbol loc sym)
104 ((nil) (nil-value loc))
109 (reference-with-check loc sym value-slot))))
112 ; Compile a pair-expression (that is, any structure-like construct).
114 (define (compile-pair loc expr)
118 (make-sequence loc (map compile-expr forms)))
120 ((if ,condition ,ifclause)
121 (make-conditional loc (compile-expr condition)
122 (compile-expr ifclause)
124 ((if ,condition ,ifclause ,elseclause)
125 (make-conditional loc (compile-expr condition)
126 (compile-expr ifclause)
127 (compile-expr elseclause)))
128 ((if ,condition ,ifclause . ,elses)
129 (make-conditional loc (compile-expr condition)
130 (compile-expr ifclause)
131 (make-sequence loc (map compile-expr elses))))
133 ; For (cond ...) forms, a special case is a (condition) clause without
134 ; body. In this case, the value of condition itself should be returned,
135 ; and thus is saved in a local variable for testing and returning, if it
137 ((cond . ,clauses) (guard (and-map (lambda (el)
138 (and (list? el) (not (null? el))))
140 (let iterate ((tail clauses))
143 (let ((cur (car tail)))
144 (if (null? (cdr cur))
145 (let ((var (gensym)))
147 '(condition) `(,var) `(,(compile-expr (car cur)))
148 (make-conditional loc
149 (make-lexical-ref loc 'condition var)
150 (make-lexical-ref loc 'condition var)
151 (iterate (cdr tail)))))
152 (make-conditional loc
153 (compile-expr (car cur))
154 (make-sequence loc (map compile-expr (cdr cur)))
155 (iterate (cdr tail))))))))
157 ((and) (t-value loc))
158 ((and . ,expressions)
159 (let iterate ((tail expressions))
160 (if (null? (cdr tail))
161 (compile-expr (car tail))
162 (make-conditional loc
163 (compile-expr (car tail))
168 (let iterate ((tail expressions))
171 (let ((var (gensym)))
173 '(condition) `(,var) `(,(compile-expr (car tail)))
174 (make-conditional loc
175 (make-lexical-ref loc 'condition var)
176 (make-lexical-ref loc 'condition var)
177 (iterate (cdr tail))))))))
179 ; Build a set form for possibly multiple values. The code is not formulated
180 ; tail recursive because it is clearer this way and large lists of symbol
181 ; expression pairs are very unlikely.
184 (let iterate ((tail args))
186 (list (make-void loc))
187 (let ((sym (car tail))
188 (tailtail (cdr tail)))
189 (if (not (symbol? sym))
190 (report-error loc "expected symbol in setq")
192 (report-error loc "missing value for symbol in setq" sym)
193 (let* ((val (compile-expr (car tailtail)))
194 (op (set-variable! loc sym value-slot val)))
195 (cons op (iterate (cdr tailtail)))))))))))
198 (make-const loc val))
201 (report-error loc "unrecognized elisp" expr))))
204 ; Compile a single expression to TreeIL.
206 (define (compile-expr expr)
207 (let ((loc (location expr)))
210 (compile-symbol loc expr))
212 (compile-pair loc expr))
213 (else (make-const loc expr)))))
216 ; Entry point for compilation to TreeIL.
218 (define (compile-tree-il expr env opts)