compile-tree-il.scm 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. ;;; Guile Emacs Lisp
  2. ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation; either version 3, or (at your option)
  6. ;; any later version.
  7. ;;
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program; see the file COPYING. If not, write to
  15. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. ;; Boston, MA 02111-1307, USA.
  17. ;;; Code:
  18. (define-module (language elisp compile-tree-il)
  19. #:use-module (language elisp bindings)
  20. #:use-module (language elisp runtime)
  21. #:use-module (language tree-il)
  22. #:use-module (system base pmatch)
  23. #:use-module (system base compile)
  24. #:use-module (srfi srfi-1)
  25. #:use-module (srfi srfi-8)
  26. #:use-module (srfi srfi-11)
  27. #:use-module (srfi srfi-26)
  28. #:export (compile-tree-il
  29. compile-progn
  30. compile-if
  31. compile-defconst
  32. compile-defvar
  33. compile-setq
  34. compile-let
  35. compile-lexical-let
  36. compile-flet
  37. compile-let*
  38. compile-lexical-let*
  39. compile-flet*
  40. compile-without-void-checks
  41. compile-with-always-lexical
  42. compile-guile-ref
  43. compile-guile-primitive
  44. compile-while
  45. compile-function
  46. compile-defmacro
  47. compile-defun
  48. #{compile-`}#
  49. compile-quote))
  50. ;;; Certain common parameters (like the bindings data structure or
  51. ;;; compiler options) are not always passed around but accessed using
  52. ;;; fluids to simulate dynamic binding (hey, this is about elisp).
  53. ;;; The bindings data structure to keep track of symbol binding related
  54. ;;; data.
  55. (define bindings-data (make-fluid))
  56. ;;; Store for which symbols (or all/none) void checks are disabled.
  57. (define disable-void-check (make-fluid))
  58. ;;; Store which symbols (or all/none) should always be bound lexically,
  59. ;;; even with ordinary let and as lambda arguments.
  60. (define always-lexical (make-fluid))
  61. ;;; Find the source properties of some parsed expression if there are
  62. ;;; any associated with it.
  63. (define (location x)
  64. (and (pair? x)
  65. (let ((props (source-properties x)))
  66. (and (not (null? props))
  67. props))))
  68. ;;; Values to use for Elisp's nil and t.
  69. (define (nil-value loc)
  70. (make-const loc (@ (language elisp runtime) nil-value)))
  71. (define (t-value loc)
  72. (make-const loc (@ (language elisp runtime) t-value)))
  73. ;;; Modules that contain the value and function slot bindings.
  74. (define runtime '(language elisp runtime))
  75. (define value-slot (@ (language elisp runtime) value-slot-module))
  76. (define function-slot (@ (language elisp runtime) function-slot-module))
  77. ;;; The backquoting works the same as quasiquotes in Scheme, but the
  78. ;;; forms are named differently; to make easy adaptions, we define these
  79. ;;; predicates checking for a symbol being the car of an
  80. ;;; unquote/unquote-splicing/backquote form.
  81. (define (unquote? sym)
  82. (and (symbol? sym) (eq? sym '#{,}#)))
  83. (define (unquote-splicing? sym)
  84. (and (symbol? sym) (eq? sym '#{,@}#)))
  85. ;;; Build a call to a primitive procedure nicely.
  86. (define (call-primitive loc sym . args)
  87. (make-application loc (make-primitive-ref loc sym) args))
  88. ;;; Error reporting routine for syntax/compilation problems or build
  89. ;;; code for a runtime-error output.
  90. (define (report-error loc . args)
  91. (apply error args))
  92. (define (runtime-error loc msg . args)
  93. (make-application loc
  94. (make-primitive-ref loc 'error)
  95. (cons (make-const loc msg) args)))
  96. ;;; Generate code to ensure a global symbol is there for further use of
  97. ;;; a given symbol. In general during the compilation, those needed are
  98. ;;; only tracked with the bindings data structure. Afterwards, however,
  99. ;;; for all those needed symbols the globals are really generated with
  100. ;;; this routine.
  101. (define (generate-ensure-global loc sym module)
  102. (make-application loc
  103. (make-module-ref loc runtime 'ensure-fluid! #t)
  104. (list (make-const loc module)
  105. (make-const loc sym))))
  106. (define (ensuring-globals loc bindings body)
  107. (make-sequence
  108. loc
  109. `(,@(map-globals-needed (fluid-ref bindings)
  110. (lambda (mod sym)
  111. (generate-ensure-global loc sym mod)))
  112. ,body)))
  113. ;;; Build a construct that establishes dynamic bindings for certain
  114. ;;; variables. We may want to choose between binding with fluids and
  115. ;;; with-fluids* and using just ordinary module symbols and
  116. ;;; setting/reverting their values with a dynamic-wind.
  117. (define (let-dynamic loc syms module vals body)
  118. (call-primitive
  119. loc
  120. 'with-fluids*
  121. (make-application loc
  122. (make-primitive-ref loc 'list)
  123. (map (lambda (sym)
  124. (make-module-ref loc module sym #t))
  125. syms))
  126. (make-application loc (make-primitive-ref loc 'list) vals)
  127. (make-lambda loc
  128. '()
  129. (make-lambda-case #f '() #f #f #f '() '() body #f))))
  130. ;;; Handle access to a variable (reference/setting) correctly depending
  131. ;;; on whether it is currently lexically or dynamically bound. lexical
  132. ;;; access is done only for references to the value-slot module!
  133. (define (access-variable loc
  134. sym
  135. module
  136. handle-global
  137. handle-lexical
  138. handle-dynamic)
  139. (let ((lexical (get-lexical-binding (fluid-ref bindings-data) sym)))
  140. (cond
  141. (lexical (handle-lexical lexical))
  142. ((equal? module function-slot) (handle-global))
  143. (else (handle-dynamic)))))
  144. ;;; Generate code to reference a variable. For references in the
  145. ;;; value-slot module, we may want to generate a lexical reference
  146. ;;; instead if the variable has a lexical binding.
  147. (define (reference-variable loc sym module)
  148. (access-variable
  149. loc
  150. sym
  151. module
  152. (lambda () (make-module-ref loc module sym #t))
  153. (lambda (lexical) (make-lexical-ref loc lexical lexical))
  154. (lambda ()
  155. (mark-global-needed! (fluid-ref bindings-data) sym module)
  156. (call-primitive loc
  157. 'fluid-ref
  158. (make-module-ref loc module sym #t)))))
  159. ;;; Generate code to set a variable. Just as with reference-variable, in
  160. ;;; case of a reference to value-slot, we want to generate a lexical set
  161. ;;; when the variable has a lexical binding.
  162. (define (set-variable! loc sym module value)
  163. (access-variable
  164. loc
  165. sym
  166. module
  167. (lambda ()
  168. (make-application
  169. loc
  170. (make-module-ref loc runtime 'set-variable! #t)
  171. (list (make-const loc module) (make-const loc sym) value)))
  172. (lambda (lexical) (make-lexical-set loc lexical lexical value))
  173. (lambda ()
  174. (mark-global-needed! (fluid-ref bindings-data) sym module)
  175. (call-primitive loc
  176. 'fluid-set!
  177. (make-module-ref loc module sym #t)
  178. value))))
  179. ;;; Process the bindings part of a let or let* expression; that is,
  180. ;;; check for correctness and bring it to the form ((sym1 . val1) (sym2
  181. ;;; . val2) ...).
  182. (define (process-let-bindings loc bindings)
  183. (map
  184. (lambda (b)
  185. (if (symbol? b)
  186. (cons b 'nil)
  187. (if (or (not (list? b))
  188. (not (= (length b) 2)))
  189. (report-error
  190. loc
  191. "expected symbol or list of 2 elements in let")
  192. (if (not (symbol? (car b)))
  193. (report-error loc "expected symbol in let")
  194. (cons (car b) (cadr b))))))
  195. bindings))
  196. ;;; Split the let bindings into a list to be done lexically and one
  197. ;;; dynamically. A symbol will be bound lexically if and only if: We're
  198. ;;; processing a lexical-let (i.e. module is 'lexical), OR we're
  199. ;;; processing a value-slot binding AND the symbol is already lexically
  200. ;;; bound or is always lexical, OR we're processing a function-slot
  201. ;;; binding.
  202. (define (bind-lexically? sym module)
  203. (or (eq? module 'lexical)
  204. (eq? module function-slot)
  205. (and (equal? module value-slot)
  206. (let ((always (fluid-ref always-lexical)))
  207. (or (eq? always 'all)
  208. (memq sym always)
  209. (get-lexical-binding (fluid-ref bindings-data) sym))))))
  210. (define (split-let-bindings bindings module)
  211. (let iterate ((tail bindings)
  212. (lexical '())
  213. (dynamic '()))
  214. (if (null? tail)
  215. (values (reverse lexical) (reverse dynamic))
  216. (if (bind-lexically? (caar tail) module)
  217. (iterate (cdr tail) (cons (car tail) lexical) dynamic)
  218. (iterate (cdr tail) lexical (cons (car tail) dynamic))))))
  219. ;;; Compile let and let* expressions. The code here is used both for
  220. ;;; let/let* and flet/flet*, just with a different bindings module.
  221. ;;;
  222. ;;; A special module value 'lexical means that we're doing a lexical-let
  223. ;;; instead and the bindings should not be saved to globals at all but
  224. ;;; be done with the lexical framework instead.
  225. ;;; Let is done with a single call to let-dynamic binding them locally
  226. ;;; to new values all "at once". If there is at least one variable to
  227. ;;; bind lexically among the bindings, we first do a let for all of them
  228. ;;; to evaluate all values before any bindings take place, and then call
  229. ;;; let-dynamic for the variables to bind dynamically.
  230. (define (generate-let loc module bindings body)
  231. (let ((bind (process-let-bindings loc bindings)))
  232. (call-with-values
  233. (lambda () (split-let-bindings bind module))
  234. (lambda (lexical dynamic)
  235. (for-each (lambda (sym)
  236. (mark-global-needed! (fluid-ref bindings-data)
  237. sym
  238. module))
  239. (map car dynamic))
  240. (let ((make-values (lambda (for)
  241. (map (lambda (el) (compile-expr (cdr el)))
  242. for)))
  243. (make-body (lambda ()
  244. (make-sequence loc (map compile-expr body)))))
  245. (if (null? lexical)
  246. (let-dynamic loc (map car dynamic) module
  247. (make-values dynamic) (make-body))
  248. (let* ((lexical-syms (map (lambda (el) (gensym)) lexical))
  249. (dynamic-syms (map (lambda (el) (gensym)) dynamic))
  250. (all-syms (append lexical-syms dynamic-syms))
  251. (vals (append (make-values lexical)
  252. (make-values dynamic))))
  253. (make-let loc
  254. all-syms
  255. all-syms
  256. vals
  257. (with-lexical-bindings
  258. (fluid-ref bindings-data)
  259. (map car lexical) lexical-syms
  260. (lambda ()
  261. (if (null? dynamic)
  262. (make-body)
  263. (let-dynamic loc
  264. (map car dynamic)
  265. module
  266. (map
  267. (lambda (sym)
  268. (make-lexical-ref loc
  269. sym
  270. sym))
  271. dynamic-syms)
  272. (make-body)))))))))))))
  273. ;;; Let* is compiled to a cascaded set of "small lets" for each binding
  274. ;;; in turn so that each one already sees the preceding bindings.
  275. (define (generate-let* loc module bindings body)
  276. (let ((bind (process-let-bindings loc bindings)))
  277. (begin
  278. (for-each (lambda (sym)
  279. (if (not (bind-lexically? sym module))
  280. (mark-global-needed! (fluid-ref bindings-data)
  281. sym
  282. module)))
  283. (map car bind))
  284. (let iterate ((tail bind))
  285. (if (null? tail)
  286. (make-sequence loc (map compile-expr body))
  287. (let ((sym (caar tail))
  288. (value (compile-expr (cdar tail))))
  289. (if (bind-lexically? sym module)
  290. (let ((target (gensym)))
  291. (make-let loc
  292. `(,target)
  293. `(,target)
  294. `(,value)
  295. (with-lexical-bindings
  296. (fluid-ref bindings-data)
  297. `(,sym)
  298. `(,target)
  299. (lambda () (iterate (cdr tail))))))
  300. (let-dynamic loc
  301. `(,(caar tail))
  302. module
  303. `(,value)
  304. (iterate (cdr tail))))))))))
  305. ;;; Split the argument list of a lambda expression into required,
  306. ;;; optional and rest arguments and also check it is actually valid.
  307. ;;; Additionally, we create a list of all "local variables" (that is,
  308. ;;; required, optional and rest arguments together) and also this one
  309. ;;; split into those to be bound lexically and dynamically. Returned is
  310. ;;; as multiple values: required optional rest lexical dynamic
  311. (define (bind-arg-lexical? arg)
  312. (let ((always (fluid-ref always-lexical)))
  313. (or (eq? always 'all)
  314. (memq arg always))))
  315. (define (split-lambda-arguments loc args)
  316. (let iterate ((tail args)
  317. (mode 'required)
  318. (required '())
  319. (optional '())
  320. (lexical '())
  321. (dynamic '()))
  322. (cond
  323. ((null? tail)
  324. (let ((final-required (reverse required))
  325. (final-optional (reverse optional))
  326. (final-lexical (reverse lexical))
  327. (final-dynamic (reverse dynamic)))
  328. (values final-required
  329. final-optional
  330. #f
  331. final-lexical
  332. final-dynamic)))
  333. ((and (eq? mode 'required)
  334. (eq? (car tail) '&optional))
  335. (iterate (cdr tail) 'optional required optional lexical dynamic))
  336. ((eq? (car tail) '&rest)
  337. (if (or (null? (cdr tail))
  338. (not (null? (cddr tail))))
  339. (report-error loc "expected exactly one symbol after &rest")
  340. (let* ((rest (cadr tail))
  341. (rest-lexical (bind-arg-lexical? rest))
  342. (final-required (reverse required))
  343. (final-optional (reverse optional))
  344. (final-lexical (reverse (if rest-lexical
  345. (cons rest lexical)
  346. lexical)))
  347. (final-dynamic (reverse (if rest-lexical
  348. dynamic
  349. (cons rest dynamic)))))
  350. (values final-required
  351. final-optional
  352. rest
  353. final-lexical
  354. final-dynamic))))
  355. (else
  356. (if (not (symbol? (car tail)))
  357. (report-error loc
  358. "expected symbol in argument list, got"
  359. (car tail))
  360. (let* ((arg (car tail))
  361. (bind-lexical (bind-arg-lexical? arg))
  362. (new-lexical (if bind-lexical
  363. (cons arg lexical)
  364. lexical))
  365. (new-dynamic (if bind-lexical
  366. dynamic
  367. (cons arg dynamic))))
  368. (case mode
  369. ((required) (iterate (cdr tail) mode
  370. (cons arg required) optional
  371. new-lexical new-dynamic))
  372. ((optional) (iterate (cdr tail) mode
  373. required (cons arg optional)
  374. new-lexical new-dynamic))
  375. (else
  376. (error "invalid mode in split-lambda-arguments"
  377. mode)))))))))
  378. ;;; Compile a lambda expression. One thing we have to be aware of is
  379. ;;; that lambda arguments are usually dynamically bound, even when a
  380. ;;; lexical binding is intact for a symbol. For symbols that are marked
  381. ;;; as 'always lexical,' however, we lexically bind here as well, and
  382. ;;; thus we get them out of the let-dynamic call and register a lexical
  383. ;;; binding for them (the lexical target variable is already there,
  384. ;;; namely the real lambda argument from TreeIL).
  385. (define (compile-lambda loc args body)
  386. (if (not (list? args))
  387. (report-error loc "expected list for argument-list" args))
  388. (if (null? body)
  389. (report-error loc "function body must not be empty"))
  390. (receive (required optional rest lexical dynamic)
  391. (split-lambda-arguments loc args)
  392. (define (process-args args)
  393. (define (find-pairs pairs filter)
  394. (lset-intersection (lambda (name+sym x)
  395. (eq? (car name+sym) x))
  396. pairs
  397. filter))
  398. (let* ((syms (map (lambda (x) (gensym)) args))
  399. (pairs (map cons args syms))
  400. (lexical-pairs (find-pairs pairs lexical))
  401. (dynamic-pairs (find-pairs pairs dynamic)))
  402. (values syms pairs lexical-pairs dynamic-pairs)))
  403. (let*-values (((required-syms
  404. required-pairs
  405. required-lex-pairs
  406. required-dyn-pairs)
  407. (process-args required))
  408. ((optional-syms
  409. optional-pairs
  410. optional-lex-pairs
  411. optional-dyn-pairs)
  412. (process-args optional))
  413. ((rest-syms rest-pairs rest-lex-pairs rest-dyn-pairs)
  414. (process-args (if rest (list rest) '())))
  415. ((the-rest-sym) (if rest (car rest-syms) #f))
  416. ((all-syms) (append required-syms
  417. optional-syms
  418. rest-syms))
  419. ((all-lex-pairs) (append required-lex-pairs
  420. optional-lex-pairs
  421. rest-lex-pairs))
  422. ((all-dyn-pairs) (append required-dyn-pairs
  423. optional-dyn-pairs
  424. rest-dyn-pairs)))
  425. (for-each (lambda (sym)
  426. (mark-global-needed! (fluid-ref bindings-data)
  427. sym
  428. value-slot))
  429. dynamic)
  430. (with-dynamic-bindings
  431. (fluid-ref bindings-data)
  432. dynamic
  433. (lambda ()
  434. (with-lexical-bindings
  435. (fluid-ref bindings-data)
  436. (map car all-lex-pairs)
  437. (map cdr all-lex-pairs)
  438. (lambda ()
  439. (make-lambda
  440. loc
  441. '()
  442. (make-lambda-case
  443. #f
  444. required
  445. optional
  446. rest
  447. #f
  448. (map (lambda (x) (nil-value loc)) optional)
  449. all-syms
  450. (let ((compiled-body
  451. (make-sequence loc (map compile-expr body))))
  452. (make-sequence
  453. loc
  454. (list
  455. (if rest
  456. (make-conditional
  457. loc
  458. (call-primitive loc
  459. 'null?
  460. (make-lexical-ref loc
  461. rest
  462. the-rest-sym))
  463. (make-lexical-set loc
  464. rest
  465. the-rest-sym
  466. (nil-value loc))
  467. (make-void loc))
  468. (make-void loc))
  469. (if (null? dynamic)
  470. compiled-body
  471. (let-dynamic loc
  472. dynamic
  473. value-slot
  474. (map (lambda (name-sym)
  475. (make-lexical-ref
  476. loc
  477. (car name-sym)
  478. (cdr name-sym)))
  479. all-dyn-pairs)
  480. compiled-body)))))
  481. #f)))))))))
  482. ;;; Handle the common part of defconst and defvar, that is, checking for
  483. ;;; a correct doc string and arguments as well as maybe in the future
  484. ;;; handling the docstring somehow.
  485. (define (handle-var-def loc sym doc)
  486. (cond
  487. ((not (symbol? sym)) (report-error loc "expected symbol, got" sym))
  488. ((> (length doc) 1) (report-error loc "too many arguments to defvar"))
  489. ((and (not (null? doc)) (not (string? (car doc))))
  490. (report-error loc "expected string as third argument of defvar, got"
  491. (car doc)))
  492. ;; TODO: Handle doc string if present.
  493. (else #t)))
  494. ;;; Handle macro and special operator bindings.
  495. (define (find-operator sym type)
  496. (and
  497. (symbol? sym)
  498. (module-defined? (resolve-interface function-slot) sym)
  499. (let* ((op (module-ref (resolve-module function-slot) sym))
  500. (op (if (fluid? op) (fluid-ref op) op)))
  501. (if (and (pair? op) (eq? (car op) type))
  502. (cdr op)
  503. #f))))
  504. ;;; See if a (backquoted) expression contains any unquotes.
  505. (define (contains-unquotes? expr)
  506. (if (pair? expr)
  507. (if (or (unquote? (car expr)) (unquote-splicing? (car expr)))
  508. #t
  509. (or (contains-unquotes? (car expr))
  510. (contains-unquotes? (cdr expr))))
  511. #f))
  512. ;;; Process a backquoted expression by building up the needed
  513. ;;; cons/append calls. For splicing, it is assumed that the expression
  514. ;;; spliced in evaluates to a list. The emacs manual does not really
  515. ;;; state either it has to or what to do if it does not, but Scheme
  516. ;;; explicitly forbids it and this seems reasonable also for elisp.
  517. (define (unquote-cell? expr)
  518. (and (list? expr) (= (length expr) 2) (unquote? (car expr))))
  519. (define (unquote-splicing-cell? expr)
  520. (and (list? expr) (= (length expr) 2) (unquote-splicing? (car expr))))
  521. (define (process-backquote loc expr)
  522. (if (contains-unquotes? expr)
  523. (if (pair? expr)
  524. (if (or (unquote-cell? expr) (unquote-splicing-cell? expr))
  525. (compile-expr (cadr expr))
  526. (let* ((head (car expr))
  527. (processed-tail (process-backquote loc (cdr expr)))
  528. (head-is-list-2 (and (list? head)
  529. (= (length head) 2)))
  530. (head-unquote (and head-is-list-2
  531. (unquote? (car head))))
  532. (head-unquote-splicing (and head-is-list-2
  533. (unquote-splicing?
  534. (car head)))))
  535. (if head-unquote-splicing
  536. (call-primitive loc
  537. 'append
  538. (compile-expr (cadr head))
  539. processed-tail)
  540. (call-primitive loc 'cons
  541. (if head-unquote
  542. (compile-expr (cadr head))
  543. (process-backquote loc head))
  544. processed-tail))))
  545. (report-error loc
  546. "non-pair expression contains unquotes"
  547. expr))
  548. (make-const loc expr)))
  549. ;;; Temporarily update a list of symbols that are handled specially
  550. ;;; (disabled void check or always lexical) for compiling body. We need
  551. ;;; to handle special cases for already all / set to all and the like.
  552. (define (with-added-symbols loc fluid syms body)
  553. (if (null? body)
  554. (report-error loc "symbol-list construct has empty body"))
  555. (if (not (or (eq? syms 'all)
  556. (and (list? syms) (and-map symbol? syms))))
  557. (report-error loc "invalid symbol list" syms))
  558. (let ((old (fluid-ref fluid))
  559. (make-body (lambda ()
  560. (make-sequence loc (map compile-expr body)))))
  561. (if (eq? old 'all)
  562. (make-body)
  563. (let ((new (if (eq? syms 'all)
  564. 'all
  565. (append syms old))))
  566. (with-fluids ((fluid new))
  567. (make-body))))))
  568. ;;; Special operators
  569. (defspecial progn (loc args)
  570. (make-sequence loc (map compile-expr args)))
  571. (defspecial if (loc args)
  572. (pmatch args
  573. ((,cond ,then . ,else)
  574. (make-conditional loc
  575. (compile-expr cond)
  576. (compile-expr then)
  577. (if (null? else)
  578. (nil-value loc)
  579. (make-sequence loc
  580. (map compile-expr else)))))))
  581. (defspecial defconst (loc args)
  582. (pmatch args
  583. ((,sym ,value . ,doc)
  584. (if (handle-var-def loc sym doc)
  585. (make-sequence loc
  586. (list (set-variable! loc
  587. sym
  588. value-slot
  589. (compile-expr value))
  590. (make-const loc sym)))))))
  591. (defspecial defvar (loc args)
  592. (pmatch args
  593. ((,sym) (make-const loc sym))
  594. ((,sym ,value . ,doc)
  595. (if (handle-var-def loc sym doc)
  596. (make-sequence
  597. loc
  598. (list
  599. (make-conditional
  600. loc
  601. (make-conditional
  602. loc
  603. (call-primitive
  604. loc
  605. 'module-bound?
  606. (call-primitive loc
  607. 'resolve-interface
  608. (make-const loc value-slot))
  609. (make-const loc sym))
  610. (call-primitive loc
  611. 'fluid-bound?
  612. (make-module-ref loc value-slot sym #t))
  613. (make-const loc #f))
  614. (make-void loc)
  615. (set-variable! loc sym value-slot (compile-expr value)))
  616. (make-const loc sym)))))))
  617. (defspecial setq (loc args)
  618. (define (car* x) (if (null? x) '() (car x)))
  619. (define (cdr* x) (if (null? x) '() (cdr x)))
  620. (define (cadr* x) (car* (cdr* x)))
  621. (define (cddr* x) (cdr* (cdr* x)))
  622. (make-sequence
  623. loc
  624. (let loop ((args args) (last (nil-value loc)))
  625. (if (null? args)
  626. (list last)
  627. (let ((sym (car args))
  628. (val (compile-expr (cadr* args))))
  629. (if (not (symbol? sym))
  630. (report-error loc "expected symbol in setq")
  631. (cons
  632. (set-variable! loc sym value-slot val)
  633. (loop (cddr* args)
  634. (reference-variable loc sym value-slot)))))))))
  635. (defspecial let (loc args)
  636. (pmatch args
  637. ((,bindings . ,body)
  638. (generate-let loc value-slot bindings body))))
  639. (defspecial lexical-let (loc args)
  640. (pmatch args
  641. ((,bindings . ,body)
  642. (generate-let loc 'lexical bindings body))))
  643. (defspecial flet (loc args)
  644. (pmatch args
  645. ((,bindings . ,body)
  646. (generate-let loc function-slot bindings body))))
  647. (defspecial let* (loc args)
  648. (pmatch args
  649. ((,bindings . ,body)
  650. (generate-let* loc value-slot bindings body))))
  651. (defspecial lexical-let* (loc args)
  652. (pmatch args
  653. ((,bindings . ,body)
  654. (generate-let* loc 'lexical bindings body))))
  655. (defspecial flet* (loc args)
  656. (pmatch args
  657. ((,bindings . ,body)
  658. (generate-let* loc function-slot bindings body))))
  659. ;;; Temporarily set symbols as always lexical only for the lexical scope
  660. ;;; of a construct.
  661. (defspecial with-always-lexical (loc args)
  662. (pmatch args
  663. ((,syms . ,body)
  664. (with-added-symbols loc always-lexical syms body))))
  665. ;;; guile-ref allows building TreeIL's module references from within
  666. ;;; elisp as a way to access data within the Guile universe. The module
  667. ;;; and symbol referenced are static values, just like (@ module symbol)
  668. ;;; does!
  669. (defspecial guile-ref (loc args)
  670. (pmatch args
  671. ((,module ,sym) (guard (and (list? module) (symbol? sym)))
  672. (make-module-ref loc module sym #t))))
  673. ;;; guile-primitive allows to create primitive references, which are
  674. ;;; still a little faster.
  675. (defspecial guile-primitive (loc args)
  676. (pmatch args
  677. ((,sym)
  678. (make-primitive-ref loc sym))))
  679. ;;; A while construct is transformed into a tail-recursive loop like
  680. ;;; this:
  681. ;;;
  682. ;;; (letrec ((iterate (lambda ()
  683. ;;; (if condition
  684. ;;; (begin body
  685. ;;; (iterate))
  686. ;;; #nil))))
  687. ;;; (iterate))
  688. ;;;
  689. ;;; As letrec is not directly accessible from elisp, while is
  690. ;;; implemented here instead of with a macro.
  691. (defspecial while (loc args)
  692. (pmatch args
  693. ((,condition . ,body)
  694. (let* ((itersym (gensym))
  695. (compiled-body (map compile-expr body))
  696. (iter-call (make-application loc
  697. (make-lexical-ref loc
  698. 'iterate
  699. itersym)
  700. (list)))
  701. (full-body (make-sequence loc
  702. `(,@compiled-body ,iter-call)))
  703. (lambda-body (make-conditional loc
  704. (compile-expr condition)
  705. full-body
  706. (nil-value loc)))
  707. (iter-thunk (make-lambda loc
  708. '()
  709. (make-lambda-case #f
  710. '()
  711. #f
  712. #f
  713. #f
  714. '()
  715. '()
  716. lambda-body
  717. #f))))
  718. (make-letrec loc
  719. #f
  720. '(iterate)
  721. (list itersym)
  722. (list iter-thunk)
  723. iter-call)))))
  724. (defspecial function (loc args)
  725. (pmatch args
  726. (((lambda ,args . ,body))
  727. (compile-lambda loc args body))
  728. ((,sym) (guard (symbol? sym))
  729. (reference-variable loc sym function-slot))))
  730. (defspecial defmacro (loc args)
  731. (pmatch args
  732. ((,name ,args . ,body)
  733. (if (not (symbol? name))
  734. (report-error loc "expected symbol as macro name" name)
  735. (let* ((tree-il
  736. (make-sequence
  737. loc
  738. (list
  739. (set-variable!
  740. loc
  741. name
  742. function-slot
  743. (make-application
  744. loc
  745. (make-module-ref loc '(guile) 'cons #t)
  746. (list (make-const loc 'macro)
  747. (compile-lambda loc args body))))
  748. (make-const loc name)))))
  749. (compile (ensuring-globals loc bindings-data tree-il)
  750. #:from 'tree-il
  751. #:to 'value)
  752. tree-il)))))
  753. (defspecial defun (loc args)
  754. (pmatch args
  755. ((,name ,args . ,body)
  756. (if (not (symbol? name))
  757. (report-error loc "expected symbol as function name" name)
  758. (make-sequence loc
  759. (list (set-variable! loc
  760. name
  761. function-slot
  762. (compile-lambda loc
  763. args
  764. body))
  765. (make-const loc name)))))))
  766. (defspecial #{`}# (loc args)
  767. (pmatch args
  768. ((,val)
  769. (process-backquote loc val))))
  770. (defspecial quote (loc args)
  771. (pmatch args
  772. ((,val)
  773. (make-const loc val))))
  774. ;;; Compile a compound expression to Tree-IL.
  775. (define (compile-pair loc expr)
  776. (let ((operator (car expr))
  777. (arguments (cdr expr)))
  778. (cond
  779. ((find-operator operator 'special-operator)
  780. => (lambda (special-operator-function)
  781. (special-operator-function loc arguments)))
  782. ((find-operator operator 'macro)
  783. => (lambda (macro-function)
  784. (compile-expr (apply macro-function arguments))))
  785. (else
  786. (make-application loc
  787. (if (symbol? operator)
  788. (reference-variable loc
  789. operator
  790. function-slot)
  791. (compile-expr operator))
  792. (map compile-expr arguments))))))
  793. ;;; Compile a symbol expression. This is a variable reference or maybe
  794. ;;; some special value like nil.
  795. (define (compile-symbol loc sym)
  796. (case sym
  797. ((nil) (nil-value loc))
  798. ((t) (t-value loc))
  799. (else (reference-variable loc sym value-slot))))
  800. ;;; Compile a single expression to TreeIL.
  801. (define (compile-expr expr)
  802. (let ((loc (location expr)))
  803. (cond
  804. ((symbol? expr)
  805. (compile-symbol loc expr))
  806. ((pair? expr)
  807. (compile-pair loc expr))
  808. (else (make-const loc expr)))))
  809. ;;; Process the compiler options.
  810. ;;; FIXME: Why is '(()) passed as options by the REPL?
  811. (define (valid-symbol-list-arg? value)
  812. (or (eq? value 'all)
  813. (and (list? value) (and-map symbol? value))))
  814. (define (process-options! opt)
  815. (if (and (not (null? opt))
  816. (not (equal? opt '(()))))
  817. (if (null? (cdr opt))
  818. (report-error #f "Invalid compiler options" opt)
  819. (let ((key (car opt))
  820. (value (cadr opt)))
  821. (case key
  822. ((#:warnings) ; ignore
  823. #f)
  824. ((#:always-lexical)
  825. (if (valid-symbol-list-arg? value)
  826. (fluid-set! always-lexical value)
  827. (report-error #f
  828. "Invalid value for #:always-lexical"
  829. value)))
  830. (else (report-error #f
  831. "Invalid compiler option"
  832. key)))))))
  833. ;;; Entry point for compilation to TreeIL. This creates the bindings
  834. ;;; data structure, and after compiling the main expression we need to
  835. ;;; make sure all globals for symbols used during the compilation are
  836. ;;; created using the generate-ensure-global function.
  837. (define (compile-tree-il expr env opts)
  838. (values
  839. (with-fluids ((bindings-data (make-bindings))
  840. (disable-void-check '())
  841. (always-lexical '()))
  842. (process-options! opts)
  843. (let ((compiled (compile-expr expr)))
  844. (ensuring-globals (location expr) bindings-data compiled)))
  845. env
  846. env))