primitives.scm 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. ;;; open-coding primitive procedures
  2. ;; Copyright (C) 2009-2015, 2017-2021 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library 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 GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Code:
  17. (define-module (language tree-il primitives)
  18. #:use-module (system base pmatch)
  19. #:use-module (ice-9 match)
  20. #:use-module (ice-9 threads)
  21. #:use-module (rnrs bytevectors)
  22. #:use-module (system base syntax)
  23. #:use-module (language tree-il)
  24. #:use-module (srfi srfi-4)
  25. #:use-module (srfi srfi-16)
  26. #:export (resolve-primitives add-interesting-primitive!
  27. expand-primcall expand-primitives
  28. effect-free-primitive? effect+exception-free-primitive?
  29. constructor-primitive?
  30. singly-valued-primitive? equality-primitive?
  31. bailout-primitive?
  32. negate-primitive))
  33. ;; When adding to this, be sure to update *multiply-valued-primitives*
  34. ;; if appropriate.
  35. (define *interesting-primitive-names*
  36. '(apply
  37. call-with-values
  38. call-with-current-continuation
  39. call/cc
  40. dynamic-wind
  41. values
  42. eq? eqv? equal?
  43. memq memv
  44. = < > <= >= zero? positive? negative?
  45. + * - / 1- 1+ quotient remainder modulo exact->inexact
  46. ash logand logior logxor lognot logtest logbit?
  47. sqrt abs floor ceiling sin cos tan asin acos atan
  48. not
  49. pair? null? list? symbol? vector? string? struct? number? char? nil?
  50. eof-object?
  51. bytevector? keyword? bitvector?
  52. symbol->string string->symbol
  53. procedure? thunk?
  54. complex? real? rational? inf? nan? integer? exact? inexact? even? odd?
  55. exact-integer?
  56. char<? char<=? char>=? char>?
  57. integer->char char->integer number->string string->number
  58. acons cons cons*
  59. list vector
  60. car cdr
  61. set-car! set-cdr!
  62. caar cadr cdar cddr
  63. caaar caadr cadar caddr cdaar cdadr cddar cdddr
  64. caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
  65. cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
  66. length
  67. make-vector vector-length vector-ref vector-set!
  68. variable? variable-ref variable-set!
  69. variable-bound?
  70. current-module define!
  71. current-thread fluid-ref fluid-set! with-fluid* with-dynamic-state
  72. call-with-prompt
  73. abort-to-prompt* abort-to-prompt
  74. make-prompt-tag
  75. throw error scm-error
  76. string-length string-ref string-set!
  77. make-struct/simple struct-vtable struct-ref struct-set!
  78. bytevector-length
  79. bytevector-u8-ref bytevector-u8-set!
  80. bytevector-s8-ref bytevector-s8-set!
  81. u8vector-ref u8vector-set! s8vector-ref s8vector-set!
  82. bytevector-u16-ref bytevector-u16-set!
  83. bytevector-u16-native-ref bytevector-u16-native-set!
  84. bytevector-s16-ref bytevector-s16-set!
  85. bytevector-s16-native-ref bytevector-s16-native-set!
  86. u16vector-ref u16vector-set! s16vector-ref s16vector-set!
  87. bytevector-u32-ref bytevector-u32-set!
  88. bytevector-u32-native-ref bytevector-u32-native-set!
  89. bytevector-s32-ref bytevector-s32-set!
  90. bytevector-s32-native-ref bytevector-s32-native-set!
  91. u32vector-ref u32vector-set! s32vector-ref s32vector-set!
  92. bytevector-u64-ref bytevector-u64-set!
  93. bytevector-u64-native-ref bytevector-u64-native-set!
  94. bytevector-s64-ref bytevector-s64-set!
  95. bytevector-s64-native-ref bytevector-s64-native-set!
  96. u64vector-ref u64vector-set! s64vector-ref s64vector-set!
  97. bytevector-ieee-single-ref bytevector-ieee-single-set!
  98. bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
  99. bytevector-ieee-double-ref bytevector-ieee-double-set!
  100. bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!
  101. f32vector-ref f32vector-set! f64vector-ref f64vector-set!))
  102. (define (add-interesting-primitive! name)
  103. (hashq-set! *interesting-primitive-vars*
  104. (or (module-variable (current-module) name)
  105. (error "unbound interesting primitive" name))
  106. name))
  107. (define *interesting-primitive-vars* (make-hash-table))
  108. (for-each add-interesting-primitive! *interesting-primitive-names*)
  109. (define *primitive-constructors*
  110. ;; Primitives that return a fresh object.
  111. '(acons cons cons* list vector make-vector
  112. make-struct/simple
  113. make-prompt-tag))
  114. (define *primitive-accessors*
  115. ;; Primitives that are pure, but whose result depends on the mutable
  116. ;; memory pointed to by their operands.
  117. ;;
  118. ;; Note: if you add an accessor here, be sure to add a corresponding
  119. ;; case in (language tree-il effects)!
  120. '(vector-ref
  121. car cdr
  122. memq memv
  123. struct-ref
  124. string-ref
  125. bytevector-u8-ref bytevector-s8-ref
  126. bytevector-u16-ref bytevector-u16-native-ref
  127. bytevector-s16-ref bytevector-s16-native-ref
  128. bytevector-u32-ref bytevector-u32-native-ref
  129. bytevector-s32-ref bytevector-s32-native-ref
  130. bytevector-u64-ref bytevector-u64-native-ref
  131. bytevector-s64-ref bytevector-s64-native-ref
  132. bytevector-ieee-single-ref bytevector-ieee-single-native-ref
  133. bytevector-ieee-double-ref bytevector-ieee-double-native-ref))
  134. (define *effect-free-primitives*
  135. `(values
  136. eq? eqv? equal?
  137. = < > <= >= zero? positive? negative?
  138. ash logand logior logxor lognot logtest logbit?
  139. + * - / 1- 1+ sqrt abs quotient remainder modulo exact->inexact
  140. floor ceiling sin cos tan asin acos atan
  141. not
  142. pair? null? nil? list?
  143. symbol? variable? vector? struct? string? number? char?
  144. bytevector? keyword? bitvector? atomic-box?
  145. complex? real? rational? inf? nan? integer? exact? inexact? even? odd?
  146. exact-integer?
  147. char<? char<=? char>=? char>?
  148. integer->char char->integer number->string string->number
  149. symbol->string string->symbol
  150. struct-vtable
  151. length string-length vector-length bytevector-length
  152. ;; These all should get expanded out by expand-primitives.
  153. caar cadr cdar cddr
  154. caaar caadr cadar caddr cdaar cdadr cddar cdddr
  155. caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
  156. cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
  157. ,@*primitive-constructors*
  158. ,@*primitive-accessors*))
  159. ;; Like *effect-free-primitives* above, but further restricted in that they
  160. ;; cannot raise exceptions.
  161. (define *effect+exception-free-primitives*
  162. '(values
  163. eq? eqv? equal?
  164. not
  165. pair? null? nil? list?
  166. symbol? variable? vector? struct? string? number? char? eof-object?
  167. exact-integer?
  168. bytevector? keyword? bitvector?
  169. procedure? thunk? atomic-box?
  170. acons cons cons* list vector))
  171. ;; Primitives that don't always return one value.
  172. (define *multiply-valued-primitives*
  173. '(apply
  174. call-with-values
  175. call-with-current-continuation
  176. call/cc
  177. dynamic-wind
  178. values
  179. call-with-prompt
  180. @abort abort-to-prompt))
  181. ;; Procedures that cause a nonlocal, non-resumable abort.
  182. (define *bailout-primitives*
  183. '(throw error scm-error))
  184. ;; Negatable predicates.
  185. (define *negatable-primitives*
  186. '((even? . odd?)
  187. (exact? . inexact?)
  188. ;; (< <= > >=) are not negatable because of NaNs.
  189. (char<? . char>=?)
  190. (char>? . char<=?)))
  191. (define *equality-primitives*
  192. '(eq? eqv? equal?))
  193. (define *effect-free-primitive-table* (make-hash-table))
  194. (define *effect+exceptions-free-primitive-table* (make-hash-table))
  195. (define *equality-primitive-table* (make-hash-table))
  196. (define *multiply-valued-primitive-table* (make-hash-table))
  197. (define *bailout-primitive-table* (make-hash-table))
  198. (define *negatable-primitive-table* (make-hash-table))
  199. (for-each (lambda (x)
  200. (hashq-set! *effect-free-primitive-table* x #t))
  201. *effect-free-primitives*)
  202. (for-each (lambda (x)
  203. (hashq-set! *effect+exceptions-free-primitive-table* x #t))
  204. *effect+exception-free-primitives*)
  205. (for-each (lambda (x)
  206. (hashq-set! *equality-primitive-table* x #t))
  207. *equality-primitives*)
  208. (for-each (lambda (x)
  209. (hashq-set! *multiply-valued-primitive-table* x #t))
  210. *multiply-valued-primitives*)
  211. (for-each (lambda (x)
  212. (hashq-set! *bailout-primitive-table* x #t))
  213. *bailout-primitives*)
  214. (for-each (lambda (x)
  215. (hashq-set! *negatable-primitive-table* (car x) (cdr x))
  216. (hashq-set! *negatable-primitive-table* (cdr x) (car x)))
  217. *negatable-primitives*)
  218. (define (constructor-primitive? prim)
  219. (memq prim *primitive-constructors*))
  220. (define (effect-free-primitive? prim)
  221. (hashq-ref *effect-free-primitive-table* prim))
  222. (define (effect+exception-free-primitive? prim)
  223. (hashq-ref *effect+exceptions-free-primitive-table* prim))
  224. (define (equality-primitive? prim)
  225. (hashq-ref *equality-primitive-table* prim))
  226. (define (singly-valued-primitive? prim)
  227. (not (hashq-ref *multiply-valued-primitive-table* prim)))
  228. (define (bailout-primitive? prim)
  229. (hashq-ref *bailout-primitive-table* prim))
  230. (define (negate-primitive prim)
  231. (hashq-ref *negatable-primitive-table* prim))
  232. (define (resolve-primitives x mod)
  233. (define local-definitions
  234. (make-hash-table))
  235. ;; Assume that any definitions with primitive names in the root module
  236. ;; have the same semantics as the primitives.
  237. (unless (eq? mod the-root-module)
  238. (let collect-local-definitions ((x x))
  239. (record-case x
  240. ((<toplevel-define> name)
  241. (hashq-set! local-definitions name #t))
  242. ((<seq> head tail)
  243. (collect-local-definitions head)
  244. (collect-local-definitions tail))
  245. (else #f))))
  246. (post-order
  247. (lambda (x)
  248. (or
  249. (record-case x
  250. ((<toplevel-ref> src name)
  251. (and=> (and (not (hashq-ref local-definitions name))
  252. (hashq-ref *interesting-primitive-vars*
  253. (module-variable mod name)))
  254. (lambda (name) (make-primitive-ref src name))))
  255. ((<module-ref> src mod name public?)
  256. ;; for the moment, we're disabling primitive resolution for
  257. ;; public refs because resolve-interface can raise errors.
  258. (and=> (and=> (resolve-module mod)
  259. (if public?
  260. module-public-interface
  261. identity))
  262. (lambda (m)
  263. (and=> (hashq-ref *interesting-primitive-vars*
  264. (module-variable m name))
  265. (lambda (name)
  266. (make-primitive-ref src name))))))
  267. ((<call> src proc args)
  268. (and (primitive-ref? proc)
  269. (make-primcall src (primitive-ref-name proc) args)))
  270. (else #f))
  271. x))
  272. x))
  273. (define *primitive-expand-table* (make-hash-table))
  274. (define (expand-primcall x)
  275. (record-case x
  276. ((<primcall> src name args)
  277. (let ((expand (hashq-ref *primitive-expand-table* name)))
  278. (or (and expand (apply expand src args))
  279. x)))
  280. (else x)))
  281. (define (expand-primitives x)
  282. (pre-order expand-primcall x))
  283. (define-syntax-rule (define-primitive-expander! sym proc)
  284. (hashq-set! *primitive-expand-table* sym proc))
  285. (define-syntax primitive-expander
  286. (lambda (stx)
  287. (define (expand-args args)
  288. (syntax-case args ()
  289. (() #''())
  290. ((a . b) #`(cons #,(expand-expr #'a) #,(expand-args #'b)))
  291. (a (expand-expr #'a))))
  292. (define (expand-expr body)
  293. (syntax-case body (quote)
  294. (id (identifier? #'id) #'id)
  295. ((quote x) #'(make-const src 'x))
  296. ((op . args) #`(make-primcall src 'op #,(expand-args #'args)))
  297. (x (self-evaluating? (syntax->datum #'x)) #'(make-const src x))))
  298. (define (match-clauses args+body)
  299. (syntax-case args+body (if)
  300. (() '())
  301. ((args body . args+body)
  302. (cons #`(args #,(expand-expr #'body))
  303. (match-clauses #'args+body)))))
  304. (syntax-case stx ()
  305. ((_ args+body ...)
  306. #`(lambda (src . args)
  307. (match args
  308. #,@(match-clauses #'(args+body ...))
  309. (_ #f)))))))
  310. (define-syntax-rule (define-primitive-expander sym . clauses)
  311. (define-primitive-expander! 'sym (primitive-expander . clauses)))
  312. ;; Oddly, scm-error is just an explicitly 5-argument `throw'. Weird.
  313. (define-primitive-expander scm-error (key who message args data)
  314. (throw key who message args data))
  315. (define (escape-format-directives str)
  316. (string-join (string-split str #\~) "~~"))
  317. (define-primitive-expander! 'error
  318. (match-lambda*
  319. ((src)
  320. (make-primcall src 'throw
  321. (list (make-const src 'misc-error)
  322. (make-const src #f)
  323. (make-const src "?")
  324. (make-const src #f)
  325. (make-const src #f))))
  326. ((src ($ <const> src2 (? string? message)) . args)
  327. (let ((msg (string-join (cons (escape-format-directives message)
  328. (make-list (length args) "~S")))))
  329. (make-primcall src 'throw
  330. (list (make-const src 'misc-error)
  331. (make-const src #f)
  332. (make-const src2 msg)
  333. (make-primcall src 'list args)
  334. (make-const src #f)))))
  335. ((src message . args)
  336. (let ((msg (string-join (cons "~A" (make-list (length args) "~S")))))
  337. (make-primcall src 'throw
  338. (list (make-const src 'misc-error)
  339. (make-const src #f)
  340. (make-const src msg)
  341. (make-primcall src 'list (cons message args))
  342. (make-const src #f)))))))
  343. (define-primitive-expander define! (sym val)
  344. (%variable-set! (module-ensure-local-variable! (current-module) sym) val))
  345. (define-primitive-expander module-define! (mod sym val)
  346. (%variable-set! (module-ensure-local-variable! mod sym) val))
  347. (define-primitive-expander! 'eof-object?
  348. (match-lambda*
  349. ((src obj)
  350. (make-primcall src 'eq? (list obj (make-const #f the-eof-object))))
  351. (_ #f)))
  352. (define-primitive-expander zero? (x)
  353. (= x 0))
  354. (define-primitive-expander positive? (x)
  355. (> x 0))
  356. (define-primitive-expander negative? (x)
  357. (< x 0))
  358. ;; FIXME: All the code that uses `const?' is redundant with `peval'.
  359. (define-primitive-expander 1+ (x)
  360. (+ x 1))
  361. (define-primitive-expander 1- (x)
  362. (- x 1))
  363. (define-primitive-expander +
  364. () 0
  365. (x) (values x)
  366. (x y) (+ x y)
  367. (x y z ... last) (+ (+ x y . z) last))
  368. (define-primitive-expander *
  369. () 1
  370. (x) (values x)
  371. (x y z ... last) (* (* x y . z) last))
  372. (define-primitive-expander -
  373. (x) (- 0 x)
  374. (x y) (- x y)
  375. (x y z ... last) (- (- x y . z) last))
  376. (define-primitive-expander /
  377. (x) (/ 1 x)
  378. (x y z ... last) (/ (/ x y . z) last))
  379. (define-primitive-expander atan
  380. (x) (atan x)
  381. (x y) (atan2 x y))
  382. (define-primitive-expander logior
  383. () 0
  384. (x) (logior x 0)
  385. (x y) (logior x y)
  386. (x y z ... last) (logior (logior x y . z) last))
  387. (define-primitive-expander logand
  388. () -1
  389. (x) (logand x -1)
  390. (x y) (logand x y)
  391. (x y z ... last) (logand (logand x y . z) last))
  392. (define-primitive-expander! 'make-vector
  393. (match-lambda*
  394. ((src len)
  395. (make-primcall src 'make-vector (list len (make-const src *unspecified*))))
  396. ((src len init)
  397. (make-primcall src 'make-vector (list len init)))
  398. ((src . args)
  399. (make-call src (make-primitive-ref src 'make-vector) args))))
  400. (define-primitive-expander caar (x) (car (car x)))
  401. (define-primitive-expander cadr (x) (car (cdr x)))
  402. (define-primitive-expander cdar (x) (cdr (car x)))
  403. (define-primitive-expander cddr (x) (cdr (cdr x)))
  404. (define-primitive-expander caaar (x) (car (car (car x))))
  405. (define-primitive-expander caadr (x) (car (car (cdr x))))
  406. (define-primitive-expander cadar (x) (car (cdr (car x))))
  407. (define-primitive-expander caddr (x) (car (cdr (cdr x))))
  408. (define-primitive-expander cdaar (x) (cdr (car (car x))))
  409. (define-primitive-expander cdadr (x) (cdr (car (cdr x))))
  410. (define-primitive-expander cddar (x) (cdr (cdr (car x))))
  411. (define-primitive-expander cdddr (x) (cdr (cdr (cdr x))))
  412. (define-primitive-expander caaaar (x) (car (car (car (car x)))))
  413. (define-primitive-expander caaadr (x) (car (car (car (cdr x)))))
  414. (define-primitive-expander caadar (x) (car (car (cdr (car x)))))
  415. (define-primitive-expander caaddr (x) (car (car (cdr (cdr x)))))
  416. (define-primitive-expander cadaar (x) (car (cdr (car (car x)))))
  417. (define-primitive-expander cadadr (x) (car (cdr (car (cdr x)))))
  418. (define-primitive-expander caddar (x) (car (cdr (cdr (car x)))))
  419. (define-primitive-expander cadddr (x) (car (cdr (cdr (cdr x)))))
  420. (define-primitive-expander cdaaar (x) (cdr (car (car (car x)))))
  421. (define-primitive-expander cdaadr (x) (cdr (car (car (cdr x)))))
  422. (define-primitive-expander cdadar (x) (cdr (car (cdr (car x)))))
  423. (define-primitive-expander cdaddr (x) (cdr (car (cdr (cdr x)))))
  424. (define-primitive-expander cddaar (x) (cdr (cdr (car (car x)))))
  425. (define-primitive-expander cddadr (x) (cdr (cdr (car (cdr x)))))
  426. (define-primitive-expander cdddar (x) (cdr (cdr (cdr (car x)))))
  427. (define-primitive-expander cddddr (x) (cdr (cdr (cdr (cdr x)))))
  428. (define-primitive-expander cons*
  429. (x) (values x)
  430. (x y) (cons x y)
  431. (x y . rest) (cons x (cons* y . rest)))
  432. (define-primitive-expander acons (x y z)
  433. (cons (cons x y) z))
  434. (define-primitive-expander call/cc (proc)
  435. (call-with-current-continuation proc))
  436. (define-primitive-expander u8vector-ref (vec i)
  437. (bytevector-u8-ref vec i))
  438. (define-primitive-expander u8vector-set! (vec i x)
  439. (bytevector-u8-set! vec i x))
  440. (define-primitive-expander s8vector-ref (vec i)
  441. (bytevector-s8-ref vec i))
  442. (define-primitive-expander s8vector-set! (vec i x)
  443. (bytevector-s8-set! vec i x))
  444. (define-primitive-expander u16vector-ref (vec i)
  445. (bytevector-u16-native-ref vec (* i 2)))
  446. (define-primitive-expander u16vector-set! (vec i x)
  447. (bytevector-u16-native-set! vec (* i 2) x))
  448. (define-primitive-expander s16vector-ref (vec i)
  449. (bytevector-s16-native-ref vec (* i 2)))
  450. (define-primitive-expander s16vector-set! (vec i x)
  451. (bytevector-s16-native-set! vec (* i 2) x))
  452. (define-primitive-expander u32vector-ref (vec i)
  453. (bytevector-u32-native-ref vec (* i 4)))
  454. (define-primitive-expander u32vector-set! (vec i x)
  455. (bytevector-u32-native-set! vec (* i 4) x))
  456. (define-primitive-expander s32vector-ref (vec i)
  457. (bytevector-s32-native-ref vec (* i 4)))
  458. (define-primitive-expander s32vector-set! (vec i x)
  459. (bytevector-s32-native-set! vec (* i 4) x))
  460. (define-primitive-expander u64vector-ref (vec i)
  461. (bytevector-u64-native-ref vec (* i 8)))
  462. (define-primitive-expander u64vector-set! (vec i x)
  463. (bytevector-u64-native-set! vec (* i 8) x))
  464. (define-primitive-expander s64vector-ref (vec i)
  465. (bytevector-s64-native-ref vec (* i 8)))
  466. (define-primitive-expander s64vector-set! (vec i x)
  467. (bytevector-s64-native-set! vec (* i 8) x))
  468. (define-primitive-expander f32vector-ref (vec i)
  469. (bytevector-ieee-single-native-ref vec (* i 4)))
  470. (define-primitive-expander f32vector-set! (vec i x)
  471. (bytevector-ieee-single-native-set! vec (* i 4) x))
  472. (define-primitive-expander f32vector-ref (vec i)
  473. (bytevector-ieee-single-native-ref vec (* i 4)))
  474. (define-primitive-expander f32vector-set! (vec i x)
  475. (bytevector-ieee-single-native-set! vec (* i 4) x))
  476. (define-primitive-expander f64vector-ref (vec i)
  477. (bytevector-ieee-double-native-ref vec (* i 8)))
  478. (define-primitive-expander f64vector-set! (vec i x)
  479. (bytevector-ieee-double-native-set! vec (* i 8) x))
  480. (define-primitive-expander f64vector-ref (vec i)
  481. (bytevector-ieee-double-native-ref vec (* i 8)))
  482. (define-primitive-expander f64vector-set! (vec i x)
  483. (bytevector-ieee-double-native-set! vec (* i 8) x))
  484. (define (expand-eq prim)
  485. (case-lambda
  486. ((src) (make-const src #t))
  487. ((src a) (make-const src #t))
  488. ((src a b) #f)
  489. ((src a b . rest)
  490. (with-lexicals src (b)
  491. (make-conditional src (make-primcall src prim (list a b))
  492. (make-primcall src prim (cons b rest))
  493. (make-const src #f))))
  494. (else #f)))
  495. (define-primitive-expander! 'eq? (expand-eq 'eq?))
  496. (define-primitive-expander! 'eqv? (expand-eq 'eqv?))
  497. (define-primitive-expander! 'equal? (expand-eq 'equal?))
  498. (define (expand-chained-comparisons prim)
  499. (case-lambda
  500. ((src) (make-const src #t))
  501. ((src a)
  502. ;; (< x) -> (begin (< x 0) #t). Residualizes side-effects from x
  503. ;; and, for numeric comparisons, checks that x is a number.
  504. (make-seq src
  505. (make-primcall src prim (list a (make-const src 0)))
  506. (make-const src #t)))
  507. ((src a b) #f)
  508. ((src a b . rest)
  509. (with-lexicals src (b)
  510. (make-conditional src (make-primcall src prim (list a b))
  511. (make-primcall src prim (cons b rest))
  512. (make-const src #f))))
  513. (else #f)))
  514. (for-each (lambda (prim)
  515. (define-primitive-expander! prim
  516. (expand-chained-comparisons prim)))
  517. '(< <= = >= > eq?))
  518. (define (character-comparison-expander char< <)
  519. (lambda (src . args)
  520. (expand-primcall
  521. (make-primcall src <
  522. (map (lambda (arg)
  523. (make-primcall src 'char->integer (list arg)))
  524. args)))))
  525. (for-each (match-lambda
  526. ((char< . <)
  527. (define-primitive-expander! char<
  528. (character-comparison-expander char< <))))
  529. '((char<? . <)
  530. (char>? . >)
  531. (char<=? . <=)
  532. (char>=? . >=)
  533. (char=? . =)))
  534. (define-primitive-expander! 'call-with-prompt
  535. (case-lambda
  536. ((src tag thunk handler)
  537. (match handler
  538. (($ <lambda> _ _ ($ <lambda-case> _ _ #f _ #f () _ _ #f))
  539. (make-prompt src #f tag thunk handler))
  540. (_
  541. ;; Eta-convert prompts without inline handlers.
  542. (let ((h (gensym "h "))
  543. (args (gensym "args ")))
  544. (define-syntax-rule (primcall name . args)
  545. (make-primcall src 'name (list . args)))
  546. (define-syntax-rule (const val)
  547. (make-const src val))
  548. (with-lexicals src (handler)
  549. (make-conditional
  550. src
  551. (primcall procedure? handler)
  552. (make-prompt
  553. src #f tag thunk
  554. (make-lambda
  555. src '()
  556. (make-lambda-case
  557. src '() #f 'args #f '() (list args)
  558. (primcall apply handler (make-lexical-ref #f 'args args))
  559. #f)))
  560. (primcall throw
  561. (const 'wrong-type-arg)
  562. (const "call-with-prompt")
  563. (const "Wrong type (expecting procedure): ~S")
  564. (primcall list handler)
  565. (primcall list handler))))))))
  566. (else #f)))
  567. (define-primitive-expander! 'abort-to-prompt*
  568. (case-lambda
  569. ((src tag tail-args)
  570. (make-abort src tag '() tail-args))
  571. (else #f)))
  572. (define-primitive-expander! 'abort-to-prompt
  573. (case-lambda
  574. ((src tag . args)
  575. (make-abort src tag args (make-const #f '())))
  576. (else #f)))