summaryrefslogtreecommitdiffstats
path: root/stdlib/struct.tl
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-10-03 22:10:32 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-10-03 22:10:32 -0700
commit9c1e2974fad18576c0051d046f03d799d2879fdc (patch)
treef67f60de1965f70ec4c717486ef4b88871e61ad1 /stdlib/struct.tl
parent502543ea94913ec4d4792dbd07151fba22220637 (diff)
downloadtxr-9c1e2974fad18576c0051d046f03d799d2879fdc.tar.gz
txr-9c1e2974fad18576c0051d046f03d799d2879fdc.tar.bz2
txr-9c1e2974fad18576c0051d046f03d799d2879fdc.zip
New: %fun% mechanism for current function name.
* eval.c (pct_fun_s): New symbol variable, holding the usr:%fun% symbol. (fun_macro_env): New static function. (do_expand): For defun and defmacro, use fun_macro_env to establish an environment binding the %fun% symbol macro, and expand everything in that environment. (eval_init): Intern the %fun% symbol, initializing pct_fun_s, and also register a global symbol macro in that name so that we can freely use %fun% everywhere without worrying that the code will blow up. E.g. a logging macro can use it to get the function name, but still be useful in a top-level form outside of a named function. * stdlib/struct.tl (sys:meth-lambda): New macro. (defstruct, defmeth): Use sys:meth-lambda as a replacement for lambda to set up the %fun% symbol macro. In the :init case which doesn't use a lambda, an open-coded symacrolet does the job. * tests/019/pct-fun.tl: New file. * tests/019/pct-fun.expected: Likewise. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'stdlib/struct.tl')
-rw-r--r--stdlib/struct.tl38
1 files changed, 23 insertions, 15 deletions
diff --git a/stdlib/struct.tl b/stdlib/struct.tl
index f0806723..3a89ee3a 100644
--- a/stdlib/struct.tl
+++ b/stdlib/struct.tl
@@ -36,6 +36,10 @@
(not init-form-present)))
slot-init-forms))
+(defmacro sys:meth-lambda (struct slot params . body)
+ ^(symacrolet ((%fun% '(,struct ,slot)))
+ (lambda ,params ,*body)))
+
(defmacro defstruct (:form form name-spec super-spec . slot-specs)
(tree-bind (name args) (tree-case name-spec
((atom . args) (list atom args))
@@ -57,22 +61,22 @@
(append-each ((exslot [expander slot form]))
[expand-slot form exslot])
:))
- ((word name args . body)
+ ((word slname args . body)
(caseq word
(:method
(when (not args)
- (compile-error form "method ~s needs at least one parameter" name))
- ^((:function ,name
- (lambda ,args
- (block ,name ,*body)))))
- (:function ^((,word ,name
- (lambda ,args
- (block ,name
+ (compile-error form "method ~s needs at least one parameter" slname))
+ ^((:function ,slname
+ (sys:meth-lambda ,slname ,name ,args
+ (block ,slname ,*body)))))
+ (:function ^((,word ,slname
+ (sys:meth-lambda ,slname ,name ,args
+ (block ,slname
,*body)))))
((:static :instance)
(when body
(sys:bad-slot-syntax form slot))
- ^((,word ,name ,args)))
+ ^((,word ,slname ,args)))
(t :)))
((word (arg) . body)
(caseq word
@@ -172,11 +176,13 @@
instance-fini-form instance-postfini-form)
^(lambda (,arg-sym)
,*(if (cdr instance-fini-form)
- ^((finalize ,arg-sym (lambda (,(car instance-fini-form))
+ ^((finalize ,arg-sym (sys:meth-lambda ,name :fini
+ (,(car instance-fini-form))
,*(cdr instance-fini-form))
t)))
,*(if (cdr instance-postfini-form)
- ^((finalize ,arg-sym (lambda (,(car instance-postfini-form))
+ ^((finalize ,arg-sym (sys:meth-lambda ,name :postfini
+ (,(car instance-postfini-form))
,*(cdr instance-postfini-form)))))
,*(if inst-si-forms
^((let ((,type-sym (struct-type ,arg-sym)))
@@ -184,8 +190,9 @@
(slotset ,arg-sym ',@2 ,@3)))
inst-si-forms))))
,*(if (cdr instance-init-form)
- ^((let ((,(car instance-init-form) ,arg-sym))
- ,*(cdr instance-init-form))))))
+ ^((symacrolet ((%fun% '(,name :init)))
+ (let ((,(car instance-init-form) ,arg-sym))
+ ,*(cdr instance-init-form)))))))
,(when args
(when (> (countql : args) 1)
(compile-error form
@@ -207,7 +214,7 @@
(slotset ,arg-sym ',@1 ,@2)))
opt-args o-gens p-gens))))))
,(if instance-postinit-form
- ^(lambda (,arg-sym)
+ ^(sys:meth-lambda ,name :postinit (,arg-sym)
,*(if (cdr instance-postinit-form)
^((let ((,(car instance-postinit-form) ,arg-sym))
,*(cdr instance-postinit-form)))))))))))))
@@ -364,7 +371,8 @@
(compile-defr-warning form ^(struct-type . ,type-sym)
"definition of struct ~s not seen here" type-sym)))
(register-tentative-def ^(slot . ,name))
- ^(sys:define-method ',type-sym ',name (lambda ,arglist
+ ^(sys:define-method ',type-sym ',name (sys:meth-lambda ,type-sym ,name
+ ,arglist
(block ,name ,*body))))
(defmacro with-slots ((. slot-specs) obj-expr . body)