-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathrandomaccess.lisp
68 lines (59 loc) · 2.47 KB
/
randomaccess.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(coalton-library/utils:defstdlib-package #:coalton-library/randomaccess
(:use
#:coalton
#:coalton-library/classes)
(:export
#:RandomAccess
#:make
#:length
#:readable?
#:writable?
#:unsafe-aref
#:unsafe-set!
#:aref
#:set!))
(in-package #:coalton-library/randomaccess)
(named-readtables:in-readtable coalton:coalton)
#+coalton-release
(cl:declaim #.coalton-impl/settings:*coalton-optimize-library*)
;;; Class Implementation
(coalton-toplevel
;; The decision to use a functional dependency was an ergonomic one,
;; not a technical one. If we did not establish this dependency, we
;; would win flexibility (a single storage type can store multiple
;; data types), but we would lose a lot of practical ergonomics
;; (e.g., we would need Proxy types, calls to length would need to be
;; disambiguated, etc.).
;;
;; While we lose some flexibility, we still retain some. For
;; instance, we can have multiple storage types for double floats
;; (think: Lisp arrays, C arrays, GPU arrays, etc.).
(define-class (RandomAccess :f :t (:f -> :t))
"Establishes that `:f` is a random-access store of elements of type `:t`. The **storage type** `:f` implies the **stored type** `:t`. The storage is expected to be sequential and O(1) in random access reads and writes.
It is permitted for any of `make`, `unsafe-aref`, or `unsafe-set!` to error."
(make (UFix -> :t -> :f))
(length (:f -> UFix))
(readable? (:f -> Boolean))
(writable? (:f -> Boolean))
(unsafe-aref (:f -> UFix -> :t))
(unsafe-set! (:f -> UFix -> :t -> Unit))))
;;; Derived Functions
(coalton-toplevel
(declare aref (RandomAccess :f :t => :f -> UFix -> (Optional :t)))
(define (aref storage index)
"Read the element at `index` of the random-access storage `storage`. Return `None` if the read is out-of-bounds or not permitted."
(if (and (readable? storage)
(<= 0 index)
(< index (length storage)))
(Some (unsafe-aref storage index))
None))
(declare set! (RandomAccess :f :t => :f -> UFix -> :t -> (Optional Unit)))
(define (set! storage index value)
"Write the element `value` at `index` of the random-access storage `storage`. Return `None` if the write is out-of-bounds or not permitted."
(if (and (writable? storage)
(<= 0 index)
(< index (length storage)))
(Some (unsafe-set! storage index value))
None)))
#+sb-package-locks
(sb-ext:lock-package "COALTON-LIBRARY/RANDOMACCESS")