This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: CL implementation questions
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