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: [GSoC] Parameter protocols in CL


> One idea is to rewrite
>
> (lambda (&optional (var init-form supplied-p))
>   body)
>
> to
>
> (lambda (#!optional (tmp-var <unbound-marker>))
>   (let ((var (if (eq tmp-var <unbound-marker)
>                  init-form
>                  tmp-var)))
>     body))
>
> where <unbound-marker> is some special value that the user can usually
> not create, e.g. some of those in gnu.expr.Special.

I got the writeExternal stuff working a while ago, then ran into
another cross-language bug that took me ages to find. The problem was
that with DEFMACRO being defined in Scheme, and using a Scheme
instantiated Lambda, it wasn't recognising &optional as the symbol I'd
expect, instead it was just binding COMMON-LISP:&OPTIONAL as an
ordinary var. Given that my entry point was wondering why DEFPACKAGE
was throwing very strange "Syntax transform threw blah blah blah" it
took me a day or so to notice that until DEFMACRO is moved in the CL
ecosystem, with a more friendly Lambda, we'll have to use the Scheme
#! syntax in macro lambda lists...

I got a chance to do the transformation tonight, I have it working,
using an algorithm that generalises fairly easy to multiple LL
keywords, but wanted to check that the approach is sane (this is
currently just for &optional). Bascially I have this:

#|kawa:1|# ((lambda (x &optional (y 2 ysupp)) (list x y ysupp t)) 1 2)
(Lambda/2/fl:0 line:1:10
  (x/3/fl:40040(ignorable) #!optional
   (GS.2/6/fl:40040(ignorable) (Quote #!undefined)))
  (Let#3
    (({COMMON-LISP}:YSUPP/7/fl:40(ignorable) =
      (If (Apply (Quote #<procedure eq?>)
            (Ref/2/Declaration[GS.2/6])
            (Quote #!undefined))
        (Quote ())
        (Quote t))))
    (Let#4
      (({COMMON-LISP}:Y/5/fl:40040(ignorable) =
        (If (Apply (Quote #<procedure eq?>)
              (Ref/3/{COMMON-LISP}:YSUPP/Declaration[{COMMON-LISP}:YSUPP/7])
              (Quote t))
          (Ref/4/Declaration[GS.2/6])
          (Quote 2))))
      (Apply line:1:36 (Ref/10/Declaration[applyToArgs/2])
        (Ref/6/list)
        (Ref/7/Declaration[x/3])
        (Ref/8/{COMMON-LISP}:Y/Declaration[{COMMON-LISP}:Y/5])
        (Ref/9/{COMMON-LISP}:YSUPP/Declaration[{COMMON-LISP}:YSUPP/7])
        (Quote t)))))]
(1 2 t t)
; you get (1 2 () t) if you don't supply an argument too

The implementation is attached - that file is generally a bit of a
mess, and the implementation of the above has some obvious
initialisation/destruction errors. The rewriteAuxiallary method is
called from Lambda#rewriteBody (line 586) where the default is to just
call Translator#rewrite_body. This is the approach in english:

1) Scan the form looking for a supplied-p argument. If not found,
carry on as normal (currently two unnecessary LETs are created, easy
fix). Other wise, populate the next four entries of the rewriteHelper
array with the given variable, a default value, a supplied-p
declaration and a temporary declaration. This data structure is used
to generate the abstract syntax in #rewriteAuxillary

2) Create two LETs. The outer let holds all the supplied-p vars, the
inner let holds all the given variables which use the outer
supplied-p's to get their values. There might be some weird ANSI
issues, since IIUC, the supplied-p forms are allowed to assume
supplied-p forms appearing before them have been bound.

Kind regards,
Charles.

Attachment: OrdinaryLambda.java
Description: Binary data


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