Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implementation of RandomAccess class #1007

Merged
merged 3 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion coalton.asd
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@
(:file "complex")
(:file "elementary")
(:file "dyadic")
(:file "dual")))
(:file "dual")))
(:file "randomaccess")
(:file "cell")
(:file "iterator")
(:file "optional")
Expand Down
68 changes: 68 additions & 0 deletions library/randomaccess.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,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")
19 changes: 17 additions & 2 deletions library/vector.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
(#:types #:coalton-library/types)
(#:list #:coalton-library/list)
(#:cell #:coalton-library/cell)
(#:iter #:coalton-library/iterator))
(#:iter #:coalton-library/iterator)
(#:ram #:coalton-library/randomaccess))
(:export
#:Vector
#:new
Expand Down Expand Up @@ -66,7 +67,7 @@
(lisp (Vector :a) (n)
(cl:make-array n :fill-pointer 0 :adjustable cl:t :element-type cl:t)))

(declare with-initial-element (types:RuntimeRepr :a => UFix -> :a -> Vector :a))
(declare with-initial-element (UFix -> :a -> Vector :a))
(define (with-initial-element n x)
"Create a new vector with `n` elements equal to `x`."
(let v = (with-capacity n))
Expand Down Expand Up @@ -286,6 +287,20 @@
:initial-value init
:from-end cl:t))))

(define-instance (ram:RandomAccess (Vector :t) :t)
(define (ram:make n x)
(with-initial-element n x))
(define (ram:length a)
(length a))
(define (ram:readable? _)
True)
(define (ram:writable? _)
True)
(define (ram:unsafe-aref a n)
(index-unsafe n a))
(define (ram:unsafe-set! a n x)
(set! n x a)))

(define-instance (Into (List :a) (Vector :a))
(define (into lst)
(let ((out (with-capacity (list:length lst)))
Expand Down
1 change: 1 addition & 0 deletions src/doc/generate-documentation.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
coalton-library/list
coalton-library/result
coalton-library/cell
coalton-library/randomaccess
coalton-library/vector
coalton-library/slice
coalton-library/hashtable
Expand Down
Loading