CL implementation questions
Jamison Hope
jrh@theptrgroup.com
Fri Apr 20 03:43:00 GMT 2012
Hi Charles,
On Apr 19, 2012, at 7:12 PM, Charles Turner wrote:
> On 13 April 2012 20:05, Per Bothner <per@bothner.com> wrote:
>> On 04/13/2012 11:38 AM, Charles Turner wrote:
>>> I should be able to simulate that by creating a new lexical scope
>>> for
>>> DECLARE:
>>>
>>> (defun car (x)
>>> (if (null x) nil (let () (declare (pair x)) (invoke x 'getCar))))
>>>
>>> This seems quite nasty, it's worse because DECLARE currently doesn't
>>> work properly in this case. It sets the type of declaration X to
>>> PAIR
>>> before runtime IIUC, so this version of CAR rejects inputs like '()
>>> because they're not of type PAIR.
>>
>> Technically this may be allowed by the Common Lisp spec (and even
>> do what
>> you need), but let's try the simpler case first with a separate
>> variable:
>>
>> (defun car (x)
>> (if (null x) nil (let ((xp x)) (declare (pair xp)) (invoke xp
>> 'getCar))))
>>
>> I suggest implementing CL "the" expression:
>>
>> (defun car (x)
>> (if (null x) nil (invoke (the pair x) 'getCar)))
>
> I have a similar hang up with THE as I do with DECLARE, how does one
> modify the remaining extent of a binding. I suppose it's possible to
> rewrite into the case of using a separate variable, but that seems to
> be missing your point. I'm also not completely clear on why we need
> THE at this time, other than as a nicer way of using a separate
> variable.
One advantage I see to THE when compared with DECLARE is that THE is
self-contained, only talking about the resultant value of its own
form, whereas DECLARE is sort of retroactively saying "oh by the way,
that variable back there somewhere? here's its type ___".
The reason that your DECLARE implementation doesn't do the right thing
for (let () (declare (pair x)) (invoke x 'getCar)) is because
decl = this.lexical.get(var);
doesn't stop when it hits the boundary of the LET, it goes all the way
back to the function parameter list and then sets the type for the
whole function. In order for that DECLARE only to apply to that LET,
you really need it to [implicitly] become
(let ((x x)) (declare (pair x)) ...)
i.e. you have to create a new Declaration that is a part of the
enclosing scope, iff that scope doesn't already have one, which
will subsume any bindings for your variable further out. You might
have to create your Declaration and pass it to LetExp.add() and
also to lexical.push() since it won't be done for you automatically
by Compilation.letEnter().
> With (THE value-type form), VALUE-TYPE is not evaluated, but FORM is.
> This seems to imply I should be extending Syntax rather than
> Procedure, but I'm not sure how to emit code for runtime from a syntax
> rewriter, which seems to be necessary in order to modify the extent as
> required.
I haven't looked into it all that closely, but it seems like THE -- in
the simple case -- should more-or-less translate to a checkcast or
coerce after the FORM. Maybe see how these get compiled:
(define-syntax the
(syntax-rules ()
((the type form)
((lambda () :: type form)))))
(define (foo n)
(the integer (* n 2)))
(define-simple-class myclass ())
(define (bar p x)
(the myclass (p x)))
or the "as" procedure as Per mentioned just now.
For the general case when we have some representation of CL type
specifiers like "(values integer float symbol t null list)" or
"(and list (not null))", we'll need something more complicated,
but we're not there yet.
--
Jamison Hope
The PTR Group
www.theptrgroup.com
More information about the Kawa
mailing list