From: Douglas K. <do...@go...> - 2013-09-16 15:26:48
|
This function attempts to read an expression that resembles a similar one in DUMP-I-VECTOR: (defun test (xc-host-p cl-user::my-word-bits) (declare (special cl-user::my-word-bits)) (let ((*features* (if xc-host-p (cons :sb-xc-host *features*) *features*))) (read-from-string "(typecase foo ((simple-array (unsigned-byte 32) (*)) (dump-unsigned-vector 32 (* 4 len))) #-sb-xc-host #!+#.(cl:if (cl:= 64 cl-user::my-word-bits) '(and) '(or)) ((simple-array (unsigned-byte 63) (*)) (dump-unsigned-vector 63 (* 8 len))) #!+#.(cl:if (cl:= 64 cl-user::my-word-bits) '(and) '(or)) ((simple-array (unsigned-byte 64) (*)) (dump-unsigned-vector 64 (* 8 len))) ((simple-array (signed-byte 8) (*)) ; <-- Watch this (dump-signed-vector 8 len)) ((simple-array (signed-byte 16) (*)) (dump-signed-vector 16 (* 2 len))))"))) Notice what if 'xc-host' is true and bits = 32 the (SIGNED-BYTE 8) clause disappears. * (test t 32) => (TYPECASE FOO ((SIMPLE-ARRAY (UNSIGNED-BYTE 32) (*)) (DUMP-UNSIGNED-VECTOR 32 (* 4 LEN))) ((SIMPLE-ARRAY (SIGNED-BYTE 16) (*)) (DUMP-SIGNED-VECTOR 16 (* 2 LEN)))) 624 Obviously not what was intended. The '#-xc-host' needs to read and discard a form, but neither of the next 2 macros produces a value. The form seen and discarded by #-sb-xc-host is the (signed-byte 8) clause. A few things would make this kind of construct more concise and legible: 1. Avoid #![-+] when the feature expression following is just (AND) or (OR) stuffed in by a read-time eval of an arbitrary Lisp form. It makes no difference whether that "feature" is evaluated with respect to host or target features. Better still, add a :64-bit feature which replaces the somewhat obscure expression (cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) with just #!+64-bit 2. Avoid nesting of the macros - it's not very clear. If the #! reader were to understand :sb-xc-host as a special-case, treating it as if it were a target feature, then the conditionalized form #-sb-xc-host #!+#.(cl:if ....) ((simple-array (unsigned-byte 63) (*)) ...) could be written as #!+(and (not sb-xc-host) :64-bit) ((simple-array (unsigned-byte 63) (*)) ...) Similarly in x86-64/vm.lisp #!+sb-simd-pack (#+sb-xc-host nil #-sb-xc-host (simd-pack double-float) (sc-number-or-lose 'double-sse-immediate)) could be written as #!+(and (not sb-xc-host) sb-simd-pack) ((simd-pack double-float) (sb-number-or-lose ...) |
From: Faré <fa...@gm...> - 2013-09-16 16:39:58
|
On Mon, Sep 16, 2013 at 11:02 AM, Douglas Katzman <do...@go...> wrote: > 2. Avoid nesting of the macros - it's not very clear. If the #! reader were > to understand :sb-xc-host as a special-case, treating it as if it were a > target feature, then the conditionalized form > #-sb-xc-host > #!+#.(cl:if ....) > ((simple-array (unsigned-byte 63) (*)) ...) > could be written as > #!+(and (not sb-xc-host) :64-bit) > ((simple-array (unsigned-byte 63) (*)) ...) > Alternatively, an escape from #!+ to distinguish target from host features, e.g. 'foo or (quote :foo) to signify not-the-default, might do wonders. —♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Give up all hope for a better yesterday, even a better just now. Never give up hope for a better tomorrow. — Patri Friedman |
From: Douglas K. <do...@go...> - 2013-09-16 18:16:53
|
QUOTE doesn't make sense to me. How about: #!+(and (not (host-feature :sb-sb-host)) ...) On Mon, Sep 16, 2013 at 12:39 PM, Faré <fa...@gm...> wrote: > On Mon, Sep 16, 2013 at 11:02 AM, Douglas Katzman <do...@go...> > wrote: > > 2. Avoid nesting of the macros - it's not very clear. If the #! reader > were > > to understand :sb-xc-host as a special-case, treating it as if it were a > > target feature, then the conditionalized form > > #-sb-xc-host > > #!+#.(cl:if ....) > > ((simple-array (unsigned-byte 63) (*)) ...) > > could be written as > > #!+(and (not sb-xc-host) :64-bit) > > ((simple-array (unsigned-byte 63) (*)) ...) > > > Alternatively, an escape from #!+ to distinguish target from host features, > e.g. 'foo or (quote :foo) to signify not-the-default, might do wonders. > > —♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• > http://fare.tunes.org > Give up all hope for a better yesterday, even a better just now. > Never give up hope for a better tomorrow. — Patri Friedman > |
From: Christophe R. <cs...@ca...> - 2013-09-18 10:27:17
|
Douglas Katzman <do...@go...> writes: > This function attempts to read an expression that resembles a similar one > in DUMP-I-VECTOR: Right. Whoops. I've rewritten DUMP-I-VECTOR to remove the specific problem (not a problem in practice because of the constraints on the cross-compiler, but even so) and make the function more comprehensible in general. > A few things would make this kind of construct more concise and legible: > 1. Avoid #![-+] when the feature expression following is just (AND) or (OR) > stuffed in by a read-time eval of an arbitrary Lisp form. It makes no > difference whether that "feature" is evaluated with respect to host or > target features. Better still, add a :64-bit feature which replaces the > somewhat obscure expression > (cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) > with just > #!+64-bit Or #!+#.(sb-cold:64-bit) if we want to avoid namespace issues, but yes. > 2. Avoid nesting of the macros - it's not very clear. Indeed. How did you find this case? I toyed this morning with trying to write something which prohibited nesting #- inside #!- (and the converse) but couldn't really convince myself that it was completely desireable. Thanks, Christophe |
From: Douglas K. <do...@go...> - 2013-09-18 11:27:13
|
I found this case because CCL totally chokes on it. (In addition to other error I mentioned about TYPECASE in general). In fact they disagree that SBCL's treatment of consecutive (let's not say "nested") conditionals is right. See bug report I filed: #1112: #[-+] reader macros don't nest correctly --------------------------------+------------------------------------------- Reporter: dkatzman | Owner: Type: defect | Status: new Priority: normal | Milestone: Component: ANSI CL Compliance | Version: trunk Keywords: | --------------------------------+------------------------------------------- This function prints (C), (B), (B), (A) as tested under SBCL and CLISP on x86/darwin. {{{ (defun test () (print (read-from-string "#-x86 #-darwin (a) (b) (c)")) (print (read-from-string "#-x86 #+darwin (a) (b) (c)")) (print (read-from-string "#+x86 #-darwin (a) (b) (c)")) (print (read-from-string "#+x86 #+darwin (a) (b) (c)")) (values)) }}} CCL prints (B), (C), (B), (A) by the following rationale: In the first test, 'x86' is true so a form must be discarded. 'darwin' is true so the '(a)' reads as NIL due to read-suppress being T. NIL is the expression skipped by the #-x86 making (b) the next expression. etc. This is probably what you want: {{{ Index: l1-reader.lisp ============= --- l1-reader.lisp (revision 15900) +++ l1-reader.lisp (working copy) @@ -2950,7 +2950,7 @@ (values))))) (defun read-feature (stream) - (let* ((f (let* ((*package* *keyword-package*)) + (let* ((f (let* ((*package* *keyword-package*) (*read-suppress* nil)) (read stream t nil t)))) (labels ((eval-feature (form) (cond ((atom form) }}} Clozure CL <ope...@cl...> 5:19 AM (2 hours ago) to openmcl-trac #1112: #[-+] reader macros don't nest correctly --------------------------------+------------------------------------------- Reporter: dkatzman | Owner: gb Type: defect | Status: assigned Priority: normal | Milestone: Component: ANSI CL Compliance | Version: trunk Keywords: | --------------------------------+------------------------------------------- Changes (by gb): * owner: => gb * status: new => assigned Comment: I don't know of anything in the spec that says anything about how nested conditionals like those in your example should be handled. If you know of such things, I'd be interested in hearing of them. You can certainly say that CCL differs from other implementations in its handling of cases like this; as I said, I'm not sure that that either behavior is any more or less correct than the other (or than other plausible behaviors.) <http://www.franz.com/support/documentation/8.2/doc/implementation.htm #nested-conditionals-3> discusses how Franz addressed the fact that their implementation had different behavior than other implementations (and than CCL), and I think that their solution is probably reasonable. (There's no compelling reason to be arbitrarily different from other implementations in this case, but changing an implementation's behavior could break existing code and there likely needs to be some simple way to revert to traditional behavior.) If we don't do this, it's likely only a matter of time before someone says "this behavior is incorrect, because it's not what I see in Acme Common Lisp", and it's not worth having that argument. On Wed, Sep 18, 2013 at 6:27 AM, Christophe Rhodes <cs...@ca...> wrote: > Douglas Katzman <do...@go...> writes: > > > This function attempts to read an expression that resembles a similar one > > in DUMP-I-VECTOR: > > Right. Whoops. I've rewritten DUMP-I-VECTOR to remove the specific > problem (not a problem in practice because of the constraints on the > cross-compiler, but even so) and make the function more comprehensible > in general. > > > A few things would make this kind of construct more concise and legible: > > 1. Avoid #![-+] when the feature expression following is just (AND) or > (OR) > > stuffed in by a read-time eval of an arbitrary Lisp form. It makes no > > difference whether that "feature" is evaluated with respect to host or > > target features. Better still, add a :64-bit feature which replaces the > > somewhat obscure expression > > (cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or)) > > with just > > #!+64-bit > > Or #!+#.(sb-cold:64-bit) if we want to avoid namespace issues, but yes. > > > 2. Avoid nesting of the macros - it's not very clear. > > Indeed. How did you find this case? I toyed this morning with trying > to write something which prohibited nesting #- inside #!- (and the > converse) but couldn't really convince myself that it was completely > desireable. > > Thanks, > > Christophe > |
From: Christophe R. <cs...@ca...> - 2013-09-18 11:23:37
|
Christophe Rhodes <cs...@ca...> writes: > Douglas Katzman <do...@go...> writes: > >> 2. Avoid nesting of the macros - it's not very clear. > > Indeed. How did you find this case? Ah, reading your previous messages more carefully I find that CCL complains when deducing that some clauses are unmatchable in TYPECASEs. Personally, I think that an error or even full WARNING under those circumstances is highly dubious, but it's only about 20 years since the concept of STYLE-WARNINGs (for code which is "conforming but nevertheless considered to be faulty or substandard") was introduced. However, we live in the real world, so probably we have to adapt our conditionals to avoid unmatchable clauses in cross-compiled TYPECASEs. I'll try to schedule investigating the CCL build "soon". Cheers, Christophe |
From: Douglas K. <do...@go...> - 2013-09-18 11:29:48
|
And by the way I think CCL's issue of non-reachable TYPECASE is totally bizarre. I mean a "warning" is "warning", right? But it's "Fatal". File foo.lisp: ========= (defun foo (x) (typecase x (integer 1) (fixnum 2))) ? (compile-file "/tmp/foo.lisp") (compile-file "/tmp/foo.lisp") ;Compiler warnings for "/tmp/foo.lisp" : ; In FOO: Clause (FIXNUM 2) ignored in TYPECASE form - shadowed by (INTEGER 1) . #P"/private/tmp/foo.dx32fsl" T T |
From: Christophe R. <cs...@ca...> - 2013-09-30 16:06:07
|
Christophe Rhodes <cs...@ca...> writes: > Christophe Rhodes <cs...@ca...> writes: > >> Douglas Katzman <do...@go...> writes: >> >>> 2. Avoid nesting of the macros - it's not very clear. >> >> Indeed. How did you find this case? > > Ah, reading your previous messages more carefully I find that CCL > complains when deducing that some clauses are unmatchable in TYPECASEs. > Personally, I think that an error or even full WARNING under those > circumstances is highly dubious, but it's only about 20 years since > the concept of STYLE-WARNINGs (for code which is "conforming but > nevertheless considered to be faulty or substandard") was introduced. > > However, we live in the real world, so probably we have to adapt our > conditionals to avoid unmatchable clauses in cross-compiled TYPECASEs. > I'll try to schedule investigating the CCL build "soon". So, I've had a go. There's an unworkaroundable bug in the 32-bit CCL, but I successfully built a 64-bit SBCL using 64-bit CCL as host, using ./make.sh 'lxccl64 -b' as the invocation, with the workaround I've just pushed regarding CCL's problem with compile-time type checking of structure type declarations. There are still plenty of warnings from the CCL build, but none of them appear fatal. It might be interesting to perform fasl comparison, too. Best, Christophe |
From: Stas B. <sta...@gm...> - 2013-09-18 15:12:32
|
Christophe Rhodes <cs...@ca...> writes: > I'll try to schedule investigating the CCL build "soon". I have managed to build with CCL by just wrapping one of the structures (I think descriptor) in genesis.lisp in eval-when, but I didn't think that SBCL should be blamed for that and couldn't extract a test-case for CCL. -- With best regards, Stas. |
From: Douglas K. <do...@go...> - 2013-09-18 15:21:17
|
Stas, here's a minimal example that crashes CCL so hard the compiler doesn't return the failure flag. (defstruct descriptor thing) (declaim (ftype (function ((or descriptor symbol) descriptor)) cold-set)) (defun cold-set (blah value) ;; (format t "Cold-set ~S ~S~%" blah value)) (defun make-fixnum-descriptor (num) (make-descriptor :thing num)) (defun finish-syms () (cold-set '*current-catch-block* (make-fixnum-descriptor 0))) ? (compile-file "/tmp/try.lisp") > Error: Unknown type specifier: DESCRIPTOR > While executing: CCL::%%TYPEP, in process listener(1). > Type :POP to abort, :R for a list of available restarts. > Type :? for other options. |
From: Stas B. <sta...@gm...> - 2013-09-18 15:32:03
|
Douglas Katzman <do...@go...> writes: > Stas, here's a minimal example that crashes CCL so hard the compiler > doesn't return the failure flag. > > (defstruct descriptor thing) > (declaim (ftype (function ((or descriptor symbol) descriptor)) cold-set)) > (defun cold-set (blah value) > ;; > > > (format t "Cold-set ~S ~S~%" blah value)) > (defun make-fixnum-descriptor (num) > (make-descriptor :thing num)) > (defun finish-syms () > (cold-set '*current-catch-block* (make-fixnum-descriptor 0))) > > > ? (compile-file "/tmp/try.lisp") >> Error: Unknown type specifier: DESCRIPTOR >> While executing: CCL::%%TYPEP, in process listener(1). >> Type :POP to abort, :R for a list of available restarts. >> Type :? for other options. Right, and CLHS says: "If a defstruct form appears as a top level form, the compiler must make the structure type name recognized as a valid type name in subsequent declarations (as for deftype) and make the structure slot readers known to setf." It's a CCL bug. A reduced test case: (defstruct a-type) (defun b () (the (or a-type symbol) t)) -- With best regards, Stas. |
From: Stas B. <sta...@gm...> - 2013-09-18 15:50:31
|
Stas Boukarev <sta...@gm...> writes: > Douglas Katzman <do...@go...> writes: > >> Stas, here's a minimal example that crashes CCL so hard the compiler >> doesn't return the failure flag. >> >> (defstruct descriptor thing) >> (declaim (ftype (function ((or descriptor symbol) descriptor)) cold-set)) >> (defun cold-set (blah value) >> ;; >> >> >> (format t "Cold-set ~S ~S~%" blah value)) >> (defun make-fixnum-descriptor (num) >> (make-descriptor :thing num)) >> (defun finish-syms () >> (cold-set '*current-catch-block* (make-fixnum-descriptor 0))) >> >> >> ? (compile-file "/tmp/try.lisp") >>> Error: Unknown type specifier: DESCRIPTOR >>> While executing: CCL::%%TYPEP, in process listener(1). >>> Type :POP to abort, :R for a list of available restarts. >>> Type :? for other options. > Right, and CLHS says: > "If a defstruct form appears as a top level form, the compiler must make > the structure type name recognized as a valid type name in subsequent > declarations (as for deftype) and make the structure slot readers known > to setf." > It's a CCL bug. > A reduced test case: > > (defstruct a-type) > (defun b () > (the (or a-type symbol) t)) Filed as http://trac.clozure.com/ccl/ticket/1113 -- With best regards, Stas. |