Hi Robert,
I hope you do not mind I CC this email to the list, because I think you made pretty good points and I think I also have some valid answers to them.
2009/10/19 Robert Goldman rpgoldman@sift.info:
Yes, that's right. You /do/ need to run through all of ASDF's code. I have been going through that code. I am trying to tell the list what I found there.
And I thank you for that. I probably never got as far as understanding TRAVERSE and the way it works and this is one of the reasons why I feel my design of the ASDF-ECL extensions might be very fragile.
ASDF invokes TRAVERSE to make a /plan/ for performing an operation. A plan is an ordered list of operation . component pairs. After traverse returns this plan, OPERATE loops over the ordered list, calling PERFORM on each pair.
Understood. However note one thing: these are ASDF internals. They are not "exposed" to the users and not fixed by the manual. ASDF might work equally well if one changes the way OPERATE uses the output of TRAVERSE, or if we fix an order for TRAVERSE, or if we dispense the plan-and-then-execute setup.
This means that the return values of PERFORM are /discarded/.
Not necesseraly.
It also means that it's not obvious to find which are the component operations that are done for some operation X. That is, if you do (OP1 . A) (OP2 . B) and (OP3 . C) in order to do (OP . X) all you know is that the first three will appear /somewhere/ before (OP . X) in the plan --- you have no stronger guarantee about where they are. In particular, there is no top-level function call to do OP X that will be on the stack when the three subsidiary operations are done.
Understood as well. However, this also does not prevent ASDF from exposing a history of what it has done so far and let later operations use that.
I attach a simple extension to ASDF's OPERATE that creates a log. The log is a list of objects, each one containing the operation that was performed, whether it failed, and the output of PERFORM. With that log it is easy to build a TEST function that parses only the log entries related to tests.
* (multiple-value-setq (op log) (asdf:operate 'asdf:load-op 'cl-unicode))
[...] ;;; Computing Hangul syllable names #<ASDF:LOAD-OP NIL {12229E41}> * (mapc #'asdf::print-log-entry log) ;;; Log entry: ;;; #<LOAD-OP NIL {12229E41}> on #<SYSTEM "cl-unicode" {11A88DF9}> ;;; No return values [...] * (describe (first log)) #<ASDF:LOG-ENTRY {12E80A69}> is an instance of class #<STANDARD-CLASS ASDF:LOG-ENTRY>. The following slots have :INSTANCE allocation: COMPONENT #<ASDF:SYSTEM "cl-unicode" {11A88DF9}> OPERATION #<ASDF:LOAD-OP NIL {12229E41}> FAILED-P NIL RETURN-VALUES NIL
Could we agree that this is a valid starting point? It is really compatible with previous uses of ASDF and it only asks one thing: PERFORM, applied on TEST-OP should return two values, success-p and a list of objects containing the tests, so that we can analyze the log.
Juanjo