aboutsummaryrefslogtreecommitdiffstats
path: root/lib/scheme/base/50-records.csc
diff options
context:
space:
mode:
authorRose Hogenson <rhogenson@posteo.net>2022-08-05 21:04:49 -0700
committerRose Hogenson <rhogenson@posteo.net>2022-08-05 21:04:49 -0700
commit83a18a658ac925b589d36e37ae150ec986d5eba8 (patch)
treeecea56f73087903aae129bf5b88f8bf2acac6a49 /lib/scheme/base/50-records.csc
parentc458c02f3cbf24770a18e4e0e3ee2854b7bc0377 (diff)
downloadchromatopelma-83a18a658ac925b589d36e37ae150ec986d5eba8.tar.zst
Add more of the standard library.
Diffstat (limited to 'lib/scheme/base/50-records.csc')
-rw-r--r--lib/scheme/base/50-records.csc83
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/scheme/base/50-records.csc b/lib/scheme/base/50-records.csc
new file mode 100644
index 0000000..d7fa8d1
--- /dev/null
+++ b/lib/scheme/base/50-records.csc
@@ -0,0 +1,83 @@
+(export
+ define-record-type)
+(import (only (csc builtins)
+ call-builtin))
+(begin
+
+
+ ; There are a few builtin types such as vector, which uses type code 0. We'll
+ ; start at 10 to give some room for more in the future.
+ (define *next-type-id* 10)
+
+
+ (define-syntax macro-length
+ (syntax-rules ()
+ ((macro-length ()) 0)
+ ((macro-length (x xs ...))
+ (+ 1 (macro-length (xs ...))))))
+
+
+ (define-syntax set-arguments
+ (syntax-rules ()
+ ((set-arguments _ _)
+ #f)
+ ((set-arguments r n field1 field2 ...)
+ (begin
+ (call-builtin poke field1 r n)
+ (set-arguments r (+ 1 n) field2 ...)))))
+
+
+ (define-syntax define-selectors
+ (syntax-rules ()
+ ((define-selectors (selectors ...))
+ (values selectors ...))
+ ((define-selectors (selectors ...) (field getter) selector ...)
+ (define-selectors (selectors ... (lambda (r)
+ (call-builtin peek r field)))
+ selector ...))
+ ((define-selectors (selectors ...) (field getter setter) selector ...)
+ (define-selectors (selectors ... (lambda (r)
+ (call-builtin peek r field))
+ (lambda (r val)
+ (call-builtin poke val r field)))
+ selector ...))))
+
+
+ (define-syntax enumerate-fields
+ (syntax-rules ()
+ ((enumerate-fields _ selectors)
+ (define-selectors selectors))
+ ((enumerate-fields n selectors field1 field2 ...)
+ (begin
+ (define field1 n)
+ (enumerate-fields (+ 1 n) selectors field2 ...)))))
+
+
+ (define-syntax selector-names
+ (syntax-rules ()
+ ((selector-names selectors (field ...) (name ...))
+ (define-values (name ...)
+ (enumerate-fields 1 selectors field ...)))
+ ((selector-names selectors fields (names ...) (_ getter) selector ...)
+ (selector-names selectors fields (names ... getter) selector ...))
+ ((selector-names selectors fields (names ...) (_ getter setter) selector ...)
+ (selector-names selectors fields (names ... getter setter) selector ...))))
+
+
+ (define-syntax define-record-type
+ (syntax-rules ()
+ ((define-record-type _
+ (constructor field ...)
+ pred
+ selectors ...)
+ (define type-id
+ (let ((id *next-type-id*))
+ (set! *next-type-id* (call-builtin + 1 *next-type-id*))))
+ (define (pred r)
+ (call-builtin eq? type-id (call-builtin peek r 0)))
+ (define (constructor field ...)
+ (define r (call-builtin alloc (macro-length (field ...))))
+ (call-builtin poke type-id r 0)
+ (set-arguments r 1 field ...)
+ r)
+ (selector-names (selectors ...) (field ...) () selectors ...)))))