summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/place.tl11
-rw-r--r--share/txr/stdlib/struct.tl57
2 files changed, 68 insertions, 0 deletions
diff --git a/share/txr/stdlib/place.tl b/share/txr/stdlib/place.tl
index 270baace..256f8592 100644
--- a/share/txr/stdlib/place.tl
+++ b/share/txr/stdlib/place.tl
@@ -592,6 +592,17 @@
^(macrolet ((,deleter () ^(makunbound ,',sym-expr)))
,*body)))
+(defplace (slot struct sym) body
+ (getter setter
+ (with-gensyms (struct-sym)
+ ^(rlet ((,struct-sym ,struct))
+ (macrolet ((,getter () ^(slot ,',struct-sym ,',sym))
+ (,setter (val) ^(slotset ,',struct-sym ,',sym ,val)))
+ ,body))))
+ (ssetter
+ ^(macrolet ((,ssetter (val) ^(slotset ,',struct ,',sym ,val)))
+ ,body)))
+
(defmacro define-modify-macro (name lambda-list function)
(let ((cleaned-lambda-list (mapcar [iffi consp car]
(remql : lambda-list))))
diff --git a/share/txr/stdlib/struct.tl b/share/txr/stdlib/struct.tl
new file mode 100644
index 00000000..9030a90a
--- /dev/null
+++ b/share/txr/stdlib/struct.tl
@@ -0,0 +1,57 @@
+(defmacro defstruct (name-spec super . slot-specs)
+ (tree-bind (name args) (tree-case name-spec
+ ((atom . args) (list atom args))
+ (atom (list atom nil)))
+ (unless (bindable name)
+ (throwf 'eval-error "~s: ~s isn't a bindable symbol" 'defstruct name))
+ (unless (proper-listp slot-specs)
+ (throwf 'eval-error "~s: bad slot syntax" 'defstruct))
+ (let ((slot-init-forms (collect-each ((slot slot-specs))
+ (tree-case slot
+ ((sym init-form) slot)
+ (sym (list sym nil))))))
+ (whenlet ((bad [find-if [notf bindable] slot-init-forms car]))
+ (throwf 'eval-error "~s: slot name ~s isn't a bindable symbol"
+ 'defstruct (car bad)))
+ (let ((arg-sym (gensym)))
+ ^(make-struct-type ',name ',super ',[mapcar car slot-init-forms]
+ (lambda (,arg-sym)
+ ,*(mapcar (aret ^(slotset ,arg-sym ',@1 ,@2)) slot-init-forms))
+ ,(if args
+ (let ((gens (mapcar (ret (gensym)) args)))
+ ^(lambda (,arg-sym ,*gens)
+ ,*(mapcar (ret ^(slotset ,arg-sym ',@1 ,@2))
+ args gens)))))))))
+
+(defmacro sys:struct-lit (name . plist)
+ ^(make-struct ',name ',plist))
+
+(defmacro qref (:whole form obj . refs)
+ (when (null refs)
+ (throwf 'eval-error "~s: bad syntax" 'qref))
+ (tree-case refs
+ (() ())
+ (((dw sym . args))
+ (if (eq dw 'dwim) ^[(slot ,obj ',sym) ,*args] :))
+ (((dw sym . args) . more)
+ (if (eq dw 'dwim) ^(qref [(slot ,obj ',sym) ,*args] ,*more) :))
+ (((sym . args))
+ (let ((osym (gensym)))
+ ^(let ((,osym ,obj))
+ (call (slot ,osym ',sym) ,osym ,*args))))
+ (((sym . args) . more)
+ (let ((osym (gensym)))
+ ^(qref (let ((,osym ,obj))
+ (call (slot ,osym ',sym) ,osym ,*args)) ,*more)))
+ ((sym) ^(slot ,obj ',sym))
+ ((sym . more) ^(qref (slot ,obj ',sym) ,*more))
+ (obj (throwf 'eval-error "~s: bad syntax: ~s" 'qref refs))))
+
+(defmacro new (spec . pairs)
+ (let ((qpairs (mappend (aret ^(',@1 ,@2)) (tuples 2 pairs))))
+ (tree-case spec
+ ((atom . args) ^(make-struct ',atom (list ,*qpairs) ,*args))
+ (atom ^(make-struct ',atom (list ,*qpairs))))))
+
+(defmacro meth (obj slot)
+ ^(method ,obj ',slot))