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

Native standard library #1180

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
14 changes: 7 additions & 7 deletions coalton.asd
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@
:serial t
:components ((:file "set-float-traps")
(:file "utils")
(:file "types")
(:coalton-file "types")
(:file "primitive-types")
(:file "classes")
(:file "hash")
(:file "builtin")
(:file "functions")
(:file "boolean")
(:file "bits")
(:coalton-file "functions")
(:coalton-file "boolean")
(:coalton-file "bits")
(:module "math"
:serial t
:components ((:file "arith")
Expand All @@ -65,15 +65,15 @@
(:file "dyadic")
(:file "dual")))
(:file "randomaccess")
(:file "cell")
(:coalton-file "cell")
(:file "tuple")
(:file "iterator")
(:file "optional")
(:file "result")
(:file "lisparray")
(:file "list")
(:file "vector")
(:file "char")
(:coalton-file "vector")
(:coalton-file "char")
(:file "string")
(:file "slice")
(:file "hashtable")
Expand Down
25 changes: 25 additions & 0 deletions library/bits.coal
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(package coalton-library/bits
(shadow
and
or
xor
not)
(import-from
coalton-library/classes
Num)
(export
Bits
and
or
xor
not
shift))

(define-class (Num :int => Bits :int)
"Operations on the bits of twos-complement integers"
(and (:int -> :int -> :int))
(or (:int -> :int -> :int))
(xor (:int -> :int -> :int))
(not (:int -> :int))
(shift (Integer -> :int -> :int)))

33 changes: 33 additions & 0 deletions library/boolean.coal
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(package coalton-library/boolean
(import
coalton-library/classes
coalton-library/hash))

;;
;; Boolean instances
;;

(define-instance (Hash Boolean)
(define (hash item)
(lisp Hash (item)
(cl:sxhash item))))

(define-instance (Eq Boolean)
(define (== x y)
(lisp Boolean (x y)
(cl:eq x y))))

(define-instance (Ord Boolean)
(define (<=> x y)
(match x
((True)
(match y
((True) EQ)
((False) GT)))
((False)
(match y
((True) LT)
((False) EQ))))))

(define-instance (Default Boolean)
(define (default) False))
60 changes: 60 additions & 0 deletions library/builtin.coal
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
(package coalton-library/builtin
(import
coalton-library/classes)
(export
unreachable
undefined
error ; re-export from classes
not
xor
boolean-not
boolean-or
boolean-and
boolean-xor))

(lisp-toplevel ()
(cl:eval-when (:compile-toplevel)
(cl:defmacro unreachable (cl:&optional (datum "Unreachable") cl:&rest arguments)
"Signal an error with CL format string DATUM and optional format arguments ARGUMENTS."
`(lisp :a ()
(cl:error ,datum ,@arguments)))))

(define (undefined _)
"A function which can be used in place of any value, throwing an error at runtime."
(error "Undefined"))

(define not
"Synonym for `boolean-not`."
boolean-not)

(define xor
"Synonym for `boolean-xor`."
boolean-xor)

(declare boolean-not (Boolean -> Boolean))
(define (boolean-not x)
"The logical negation of `x`. Is `x` false?"
(match x
((True) False)
((False) True)))

(declare boolean-or (Boolean -> Boolean -> Boolean))
(define (boolean-or x y)
"Is either `x` or `y` true? Note that this is a *function* which means both `x` and `y` will be evaluated. Use the `or` macro for short-circuiting behavior."
(match x
((True) True)
((False) y)))

(declare boolean-and (Boolean -> Boolean -> Boolean))
(define (boolean-and x y)
"Are both `x` and `y` true? Note that this is a *function* which means both `x` and `y` will be evaluated. Use the `and` macro for short-circuiting behavior."
(match x
((True) y)
((False) False)))

(declare boolean-xor (Boolean -> Boolean -> Boolean))
(define (boolean-xor x y)
"Are `x` or `y` true, but not both?"
(match x
((True) (boolean-not y))
((False) y)))
141 changes: 141 additions & 0 deletions library/cell.coal
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
(package coalton-library/cell
(import
coalton-library/builtin
coalton-library/classes)
(export
Cell
new
read
swap!
write!
update!
update-swap!
push!
pop!
increment!
decrement!))

(lisp-toplevel ()
(cl:eval-when (:compile-toplevel :load-toplevel)

(cl:declaim (cl:inline make-cell-internal))

(cl:defstruct cell-internal
(inner (cl:error "") :type cl:t))

(cl:defmethod cl:print-object ((self cell-internal) stream)
(cl:format stream "#.(CELL ~A)" (cell-internal-inner self))
self)

#+sbcl
(cl:declaim (sb-ext:freeze-type cell-internal))))

(repr :native cell-internal)
(define-type (Cell :a)
"Internally mutable cell")

(declare new (:a -> Cell :a))
(define (new data)
"Create a new mutable cell"
(lisp (Cell :a) (data)
(make-cell-internal :inner data)))

(declare read (Cell :a -> :a))
(define (read cel)
"Read the value of a mutable cell"
(lisp :a (cel)
(cell-internal-inner cel)))

(declare swap! (Cell :a -> :a -> :a))
(define (swap! cel data)
"Replace the value of a mutable cell with a new value, then return the old value"
(lisp :a (data cel)
(cl:let* ((old (cell-internal-inner cel)))
(cl:setf (cell-internal-inner cel) data)
old)))

(declare write! (Cell :a -> :a -> :a))
(define (write! cel data)
"Set the value of a mutable cell, returning the new value"
(lisp :a (data cel)
(cl:setf (cell-internal-inner cel) data)))

(declare update! ((:a -> :a) -> Cell :a -> :a))
(define (update! f cel)
"Apply F to the contents of CEL, storing and returning the result"
(write! cel (f (read cel))))

(declare update-swap! ((:a -> :a) -> Cell :a -> :a))
(define (update-swap! f cel)
"Apply F to the contents of CEL, swapping the result for the old value"
(swap! cel (f (read cel))))

;;; operators on cells of lists
(declare push! (Cell (List :elt) -> :elt -> List :elt))
(define (push! cel new-elt)
"Push NEW-ELT onto the start of the list in CEL."
(update! (Cons new-elt) cel))

(declare pop! (Cell (List :elt) -> Optional :elt))
(define (pop! cel)
"Remove and return the first element of the list in CEL."
(match (read cel)
((Cons fst rst)
(write! cel rst)
(Some fst))
((Nil) None)))

;;; operators on cells of numbers
(declare increment! (Num :counter => Cell :counter -> :counter))
(define (increment! cel)
"Add one to the contents of CEL, storing and returning the new value"
(update! (+ 1) cel))

(declare decrement! (Num :counter => (Cell :counter) -> :counter))
(define (decrement! cel)
"Subtract one from the contents of CEL, storing and returning the new value"
(update! (+ -1) cel))

;; i am very skeptical of these instances
(define-instance (Eq :a => Eq (Cell :a))
(define (== c1 c2)
(== (read c1) (read c2))))

(define-instance (Ord :a => Ord (Cell :a))
(define (<=> c1 c2)
(match (<=> (read c1) (read c2))
((LT) LT)
((GT) GT)
((EQ) EQ))))

(define-instance (Num :a => Num (Cell :a))
(define (+ c1 c2)
(new (+ (read c1) (read c2))))
(define (- c1 c2)
(new (- (read c1) (read c2))))
(define (* c1 c2)
(new (* (read c1) (read c2))))
(define (fromInt i)
(new (fromInt i))))

(define-instance (Semigroup :a => Semigroup (Cell :a))
(define (<> a b)
(new (<> (read a) (read b)))))

(define-instance (Functor Cell)
(define (map f c)
(new (f (read c)))))

(define-instance (Applicative Cell)
(define pure new)
(define (liftA2 f c1 c2)
(new (f (read c1) (read c2)))))

(define-instance (Into :a (Cell :a))
(define into new))

(define-instance (Into (Cell :a) :a)
(define into read))

(define-instance (Default :a => Default (Cell :a))
(define (default) (new (default))))
Loading
Loading