primitives.scm 24 KB

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