freenode/lisp - IRC Chatlog
Search
4:31:47
drmeister
Hey folks - I'm trying to fix broken bootstrapping code and some of it mystifies me.
4:32:08
drmeister
(macroexpand '(setf (class-id class) name)) -> (LET* ((G11279 CLASS)) (MULTIPLE-VALUE-BIND (G11280) NAME (FUNCALL #'(SETF CLASS-ID) G11280 G11279)))
4:37:10
drmeister
Bike: so (macroexpand '(setf (class-id class) name)) should give me the correct expansion for the SETF?
4:37:44
drmeister
Because right after I print the macroexpansion I print #'(setf class-id) and it is #:UNBOUND
4:47:13
drmeister
This is all happening within a (with-early-accessors (+the-standard-class+) ...) macro that sets up a macrolet that defines an accessor for class-id.
4:47:59
drmeister
(get-setf-expansion '(class-id class)) -> ((G11279) (CLASS) (G11280) (FUNCALL #'(SETF CLASS-ID) G11280 G11279) (CLASS-ID G11279))
4:49:37
drmeister
I've added some stuff to with-compilation-unit to track problems with function definitions.
4:50:07
drmeister
This has somehow broken Clasp's bootstrapping - it's a delicate thing to level up from a C++ interpreter to a simple compiler to a full Common Lisp with CLOS.
4:51:20
drmeister
I'm doing macroexpansion on the (setf (class-id class) name) that is causing the problem.
4:51:36
drmeister
The weird thing is that the working version? It shouldn't work according to what I see.
4:51:51
drmeister
(get-setf-expansion '(class-id class)) -> ((G11279) (CLASS) (G11280) (FUNCALL #'(SETF CLASS-ID) G11280 G11279) (CLASS-ID G11279))
4:53:27
drmeister
It's happening inside of a macrolet - can I just evaluate the form? I can check that after evaluation if the value changed.
4:55:05
BusFactor1
I can't believe it's taken me this long to try and find a replacement for python's SimpleHTTPServer in CL still with no success...
4:55:52
BusFactor1
Wookie seems broken, hunchentoot doesn't handle index.html's without writing handlers, s-http-server just doesn't work, woo doesn't come with a file/directory handler...
4:56:15
Bike
so macroexpand is expanding like that because it doesn't know what the hell class-id is
4:58:55
Bike
(macrolet ((class-id (object) (backquote-append ...)) (hack (form &environment e) `',(macroexpand-1 form e))) (hack (setf (class-id class) name)))
5:02:33
Bike
macrolet expands in the global environment by default, but you can pass it an environment object
5:04:08
drmeister
So: (macrolet ((class-id (object) (backquote-append (LIST 'INSTANCE-REF) (LIST OBJECT) (LIST 3) 'NIL)) (hack (form &environment e) `',(macroexpand-1 form e))) (hack (setf (class-id class) name)))
5:06:20
drmeister
And if I put this in the code inside the macrolet that sets up all of these accessors:
5:06:21
drmeister
(debug-boot " (macroexpand-1 '(class-id class)) -> ~a~%" (macrolet ((hack (form &environment e) `',(macroexpand-1 form e))) (hack (setf (class-id class) name))))
5:08:43
drmeister
(macroexpand-1 '(class-id class) ENV) -> (LET* ((G11093 CLASS)) (MULTIPLE-VALUE-BIND (G11094) NAME (INSTANCE-SET G11093 3 G11094)))
5:12:20
drmeister
(macroexpand-1 '(class-id class) ENV) -> (LET* ((G5142 CLASS)) (MULTIPLE-VALUE-BIND (G5143) NAME (FUNCALL #'(SETF INSTANCE-REF) G5143 G5142 3)))
5:13:41
drmeister
Well, this makes a bit more sense. Because in trying to fix the bootstrapping process I decided to try and cut out reloading setf.lsp again.
5:14:13
drmeister
So if the behavior of SETF isn't completely defined - then this sort of thing might happen.
5:17:48
drmeister
So: (debug-boot " (get-setf-expansion '(class-id class) ENV) -> ~a~%" (macrolet ((hack (form &environment e) `',(get-setf-expansion form e))) (hack '(class-id class))))
5:17:57
Bike
"Within the body of macrolet, global setf expander definitions of the names defined by the macrolet do not apply; rather, setf expands the macro form and recursively process the resulting form. "
5:20:01
Bike
if you like, you can do (defmacro cmacroexpand-1 (form &environment e) `',(macroexpand-1 form e)) and skip the macrolet
5:22:21
Bike
get-setf-expansion takes an environment argument the same way macroexpand does, and by default uses the global environment, same way as macroexpand
5:22:58
drmeister
I want to find out where and why the broken bootstrapping code is different from the working code
5:23:54
drmeister
In particular, the broken code fails on: (with-early-accessors (+the-standard-class+) (setf (class-id class) name))
5:27:17
drmeister
I'm going to back up - and go back to the original bootstrapping sequence for bclasp.
5:40:08
drmeister
aclasp defines a few structs with: (defstruct (compiler-message (:type vector)) (prefix "Note") (format +note-format+) message source-pos-info top-level-form form)
5:41:26
drmeister
I use :type vector because before clos is running I can't use defclass and defstruct with CLOS uses defclass.
5:42:40
Bike
this doesn't seem like it should involve anything like class-id, then, seeing as there's no class involved.
5:42:56
drmeister
bclasp is screwing up when it loads the defstruct definition again overtop of the existing one.
5:43:33
drmeister
No - sorry to hit you with whiplash - but I think the class-id issue was because I was avoiding loading this earlier code - that just caused another problem.
5:44:30
drmeister
aclasp loads that defstruct into the interpreter and then compile-file's it and loads it again - that seems to work fine.
5:45:24
drmeister
bclasp loads aclasp (which defines that defstruct) and then compiles and loads the definition AGAIN.
5:50:16
Bike
okay, so it tries to do (subtypep vector (or list vector)), presumably to make sure the defstruct is valid
5:50:19
drmeister
This is a problem that has come up several times that I've tried to improve the bclasp compiler - the bootstrapping always fails on the first defstruct
5:52:30
drmeister
I'm about to put some code in to print debugging messages when I bind a dynamic variable to T
5:53:47
Bike
well, here's a dumb idea: i think that defstruct doesn't take a subtype of vector, it only takes literally vector, list, or (vector some-element-type)
5:57:05
Bike
so more like (or (eq type 'list) (eq type 'vector) (and (consp type) (eq (car type) 'vector)))
5:58:27
drmeister
(#+clasp(or (eq type 'list) (eq type 'vector) (and (consp type) (eq (car type) 'vector))) #+ecl(subtypep type '(OR LIST VECTOR))
6:09:52
drmeister
I wonder though if I shouldn't be looking at the root cause - why 'CONS isn't recognized properly
10:01:05
larsen
arduo: if you're looking for an italian Lisp channel, I'd like to resurrect #lisp-it (currently no traffic, but it is not completely desert)
13:36:51
specbot
Potential Numbers as Tokens: http://www.lispworks.com/reference/HyperSpec/Body/02_caa.htm
13:46:24
lieven
last time I looked at this stuff I was working out how to recover from (setf *read-base* 26)
13:51:55
beach
As I recall, Maclisp already had the dot. And (again as I recall) the default base on Maclisp was 8.
14:44:04
knobo
varjag: cl-jpeg has a todo item to "Add progressive JPEG support in decoder". But how about encoding it?
15:04:48
phoe_
(defmacro age (person &optional (default ''thirty-something)) `(get ,person 'age ,default))
15:05:30
phoe_
it would be more like, single-quoted, and the expansion would be `(get ,person 'age ',default)
15:08:39
phoe_
this is the page of GET - and this DEFMACRO smells of some ancient ways of defining accessors
15:11:25
jurov
phoe_: i found this http://www.lispworks.com/documentation/HyperSpec/Issues/iss055_w.htm
15:12:11
jurov
which says about :number lol "Benefits: Programmer expectations that any useful behavior can be portably relied upon in this pathological case should be soundly trounced."
15:13:13
ogamita
phoe_: double quotes in default values for macro arguments is not strange, because macro arguments are source code!
15:13:47
ogamita
phoe_: on the other hand, the fact that it seems unnatural to you is a hint it should be written as a function, not as a macro. ;-)
15:13:48
phoe_
One quote is for evaluating the source code, second quote is for evaluating the function argument.
15:14:49
ogamita
(defmacro age (person &optional (default ''thirty-something)) `(get ,person 'age ,default)) (macroexpand-1 ' (age p (setf last-default-used 42))) #| --> (get p 'age (setf last-default-used 42)) ; t |#
15:16:29
flip214
ogamita: with the macro as it is, DEFAULT will get evaluated always. just like with the function.
15:17:01
ogamita
Reify the person! (defun make-person () (cons 'person nil)) (defun age (p &optional (default 'thirty-something)) (get (cdr p) 'age default)) (defun (setf age) (new-age p &optional default) (declare (ignore default)) (setf (get (cdr p) 'age) new-age))
15:19:16
ogamita
flip214: with (setf getf) can change a nil into a list. (defun (setf …) …) cannot do that, you need a define-setf-expander.
15:20:05
ogamita
phoe_: : on the other hand, with get, we have already an object, since get works on symbols, so there's no point in using the macro, (defun (setf age) (new-age p &optional d) (declare (ignore d)) (setf (get p 'age) new-age)) works nicely.
15:21:46
ogamita
Since macros are allowed, they tend to use them for setf, since a single form would define the while accessor.
15:23:11
flip214
I'm not sure about the effects on code size (because of inlining vs. being to optimize things away)...
15:24:24
flip214
phoe_: I'm trying to form an opinion whether using such macros in examples like this is a good idea