This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]