From: dc
Subject: Type inferencing code for CL
Date: 
Message-ID: <690c0855-ee40-4b1c-bd11-76e2206d4fc6@8g2000hse.googlegroups.com>
Hi,
I'm writing a small utility that allows me to write lispy code that
gets transformed into a pascal like scripting language. It can do some
quite useful things already and saves me a fair bit of typing, but I'd
really like it if I could do things like :-

(pasvar j)
(setv j "hello")
(pasvar k)
(setv k 123)

and I would get...

var j string;
var k integer;
j := 'hello';
k := 123;

...without having to say what type j and k are from the lisp code, ie.
I'd like it if my utility could work out what types j and k are.
Obviously, CL can do this, but I've not easily been able to find where
in SBCL this happens and I would have thought that people would have
done this sort of thing before for translation tools like this.

Does anyone know of a simple way to do type inferencing for a
destination language or perhaps where I could find one as a library?

Thanks & Regards
David

From: Pascal J. Bourguignon
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <87iquxaytm.fsf@hubble.informatimago.com>
dc <··············@pa.com.au> writes:

> Hi,
> I'm writing a small utility that allows me to write lispy code that
> gets transformed into a pascal like scripting language. It can do some
> quite useful things already and saves me a fair bit of typing, but I'd
> really like it if I could do things like :-
>
> (pasvar j)
> (setv j "hello")
> (pasvar k)
> (setv k 123)
>
> and I would get...
>
> var j string;
> var k integer;
> j := 'hello';
> k := 123;
>
> ...without having to say what type j and k are from the lisp code, ie.

Yes, that's called type inference.

(defun infer-types (program)
  (if (atom program)
      (list (list :result (type-of program)))
      (ecase (car program)
         ((progn)  
              (loop 
                 :with var-types = nil
                 :with result-type = nil
                 :for form in (cdr program)
                 :do (let ((types (infer-types form)))
                       (setf result-type (assoc :result types)
                             types (remove :result types :key (function car)))
                       (when types (setf var-types (nconc types var-types))))
                 :finally (return (cons result-type var-types))))
         ((pasvar) nil)
         ((setv) (list (list (cadr program) (type-of (caddr program)))
                       (list :result (type-of (caddr program))))))))
                          
(infer-types '(progn (pasvar j)
                     (setv j "hello")
                     (pasvar k)
                     (setv k 123)))
-->
((:RESULT (INTEGER 0 16777215)) (K (INTEGER 0 16777215)) (J (SIMPLE-BASE-STRING 5)))


> I'd like it if my utility could work out what types j and k are.
> Obviously, CL can do this, but I've not easily been able to find where
> in SBCL this happens and I would have thought that people would have
> done this sort of thing before for translation tools like this.
>
> Does anyone know of a simple way to do type inferencing for a
> destination language or perhaps where I could find one as a library?

http://en.wikipedia.org/wiki/Type_inference
http://web.archive.org/web/20050911123640/http://www.cs.berkeley.edu/~nikitab/courses/cs263/hm.html
http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2003-10/4153.html

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!
From: ·········@sneakemail.com
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <dc71c59e-7662-4230-8496-73ed498abe0f@k30g2000hse.googlegroups.com>
Pascal J. Bourguignon wrote:
> dc <··············@pa.com.au> writes:
>
> >
> > ...without having to say what type j and k are from the lisp code, ie.
>
> Yes, that's called type inference.
>
> (defun infer-types (program)
>   (if (atom program)
>       (list (list :result (type-of program)))
>       (ecase (car program)
>          ((progn)
>               (loop
>                  :with var-types = nil
>                  :with result-type = nil
>                  :for form in (cdr program)
>                  :do (let ((types (infer-types form)))
>                        (setf result-type (assoc :result types)
>                              types (remove :result types :key (function car)))
>                        (when types (setf var-types (nconc types var-types))))
>                  :finally (return (cons result-type var-types))))
>          ((pasvar) nil)
>          ((setv) (list (list (cadr program) (type-of (caddr program)))
>                        (list :result (type-of (caddr program))))))))
>
> (infer-types '(progn (pasvar j)
>                      (setv j "hello")
>                      (pasvar k)
>                      (setv k 123)))
> -->
> ((:RESULT (INTEGER 0 16777215)) (K (INTEGER 0 16777215)) (J (SIMPLE-BASE-STRING 5)))
>

Maybe now I can get rid of all those DECLARE forms in my code without
losing the speed. ;-)
From: dc
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <602806ea-658f-4b14-9b62-f1c19f7eb810@v26g2000prm.googlegroups.com>
On Jul 23, 4:39 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> dc <··············@pa.com.au> writes:
> > Hi,
> > I'm writing a small utility that allows me to write lispy code that
> > gets transformed into a pascal like scripting language. It can do some
> > quite useful things already and saves me a fair bit of typing, but I'd
> > really like it if I could do things like :-
>
> > (pasvar j)
> > (setv j "hello")
> > (pasvar k)
> > (setv k 123)
>
> > and I would get...
>
> > var j string;
> > var k integer;
> > j := 'hello';
> > k := 123;
>
> > ...without having to say what type j and k are from the lisp code, ie.
>
> Yes, that's called type inference.
>
> (defun infer-types (program)
>   (if (atom program)
>       (list (list :result (type-of program)))
>       (ecase (car program)
>          ((progn)  
>               (loop
>                  :with var-types = nil
>                  :with result-type = nil
>                  :for form in (cdr program)
>                  :do (let ((types (infer-types form)))
>                        (setf result-type (assoc :result types)
>                              types (remove :result types :key (function car)))
>                        (when types (setf var-types (nconc types var-types))))
>                  :finally (return (cons result-type var-types))))
>          ((pasvar) nil)
>          ((setv) (list (list (cadr program) (type-of (caddr program)))
>                        (list :result (type-of (caddr program))))))))
>
> (infer-types '(progn (pasvar j)
>                      (setv j "hello")
>                      (pasvar k)
>                      (setv k 123)))
> -->
> ((:RESULT (INTEGER 0 16777215)) (K (INTEGER 0 16777215)) (J (SIMPLE-BASE-STRING 5)))
>
> > I'd like it if my utility could work out what types j and k are.
> > Obviously, CL can do this, but I've not easily been able to find where
> > in SBCL this happens and I would have thought that people would have
> > done this sort of thing before for translation tools like this.
>
> > Does anyone know of a simple way to do type inferencing for a
> > destination language or perhaps where I could find one as a library?
>
> http://en.wikipedia.org/wiki/Type_inferencehttp://web.archive.org/web/20050911123640/http://www.cs.berkeley.edu/...http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2003-10/4153....
>
> --
> __Pascal Bourguignon__                    http://www.informatimago.com/
> I need a new toy.
> Tail of black dog keeps good time.
> Pounce! Good dog! Good dog!

Thanks !
That's great.
...However, when I do :-
(setv j 2.36)
(setv k j)

I get k back as a symbol.

It looks like the types collection is local to the progn case. Is it
okay to make it a passed parameter (default nil), so I can look up
existing vars (in this case j) from the code block?

Regards
DC
From: Pascal J. Bourguignon
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <87zlo19rhn.fsf@hubble.informatimago.com>
dc <··············@pa.com.au> writes:

> Thanks !
> That's great.
> ...However, when I do :-
> (setv j 2.36)
> (setv k j)
>
> I get k back as a symbol.
>
> It looks like the types collection is local to the progn case.  Is it
> okay to make it a passed parameter (default nil), so I can look up
> existing vars (in this case j) from the code block?

Yes, you will have to implement whatever it takes.  
Have a look at:
"Compiler Principles Techniques and Tools", Aho et al. 
http://dragonbook.stanford.edu/


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"A TRUE Klingon warrior does not comment his code!"
From: dc
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <0d7909ab-43f6-4c41-abe4-1a79e7bbde40@a8g2000prf.googlegroups.com>
On Jul 29, 3:41 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> dc <··············@pa.com.au> writes:
> > Thanks !
> > That's great.
> > ...However, when I do :-
> > (setv j 2.36)
> > (setv k j)
>
> > I get k back as a symbol.
>
> > It looks like the types collection is local to the progn case.  Is it
> > okay to make it a passed parameter (default nil), so I can look up
> > existing vars (in this case j) from the code block?
>
> Yes, you will have to implement whatever it takes.  
> Have a look at:
> "Compiler Principles Techniques and Tools", Aho et al.http://dragonbook.stanford.edu/
>
> --
> __Pascal Bourguignon__                    http://www.informatimago.com/
>
> "A TRUE Klingon warrior does not comment his code!"

Hi Pascal,
I fiddled a little with your code and got it so that it can look up
previous definitions. It simply assumes that if I have
(setv j 2.3)
(setv k j)
...then k will have the same type as j.

It's somewhat simplistic in that if I want to set k to something like
(+ 2.3 j), it won't work. But I might fiddle with it some more and see
if I can get it to work.

Here are my changes.

(defun infer-types (program &optional (existing-types nil))
  (if (atom program)
      (list (list :result (type-of program)))
      (ecase (car program)
         ((progn)
              (loop
                 :with var-types = nil
                 :with result-type = nil
                 :for form in (cdr program)
                 :do (let ((types (infer-types form var-types)))
                       (setf result-type (assoc :result types)
                             types (remove :result types :key
(function car)))
                       (when types (setf var-types (nconc types var-
types))))
                 :finally (return (cons result-type var-types))))
         ((pasvar) nil)
         ((setv) (progn
		   (let* ((var-type (type-of (caddr program)))
			  (sym-name (caddr program))
			  (existing-var (cadr (assoc sym-name existing-types))))
		     (list (list (cadr program) (if existing-var
						    existing-var
						    var-type))
			   (list :result (type-of (caddr program))))))))))

(format t "types are ~A~%"
	(infer-types '(progn
			     (setv k "ab")
			     (setv j k)
			     (setv q j)
			     (setv ab 3)
			     (setv kk abc)
			     (setv c "hello"))))

types are ((RESULT (SIMPLE-ARRAY CHARACTER (5)))
             (C (SIMPLE-ARRAY CHARACTER (5))) (KK SYMBOL)
             (AB (INTEGER 0 536870911)) (Q (SIMPLE-ARRAY CHARACTER
(2)))
             (J (SIMPLE-ARRAY CHARACTER (2))) (K (SIMPLE-ARRAY
CHARACTER (2))))
From: Mark Tarver
Subject: Re: Type inferencing code for CL
Date: 
Message-ID: <fc0f6577-d494-4dcb-9068-a9fcfe873aae@c65g2000hsa.googlegroups.com>
On 23 Jul, 04:05, dc <··············@pa.com.au> wrote:
> Hi,
> I'm writing a small utility that allows me to write lispy code that
> gets transformed into a pascal like scripting language. It can do some
> quite useful things already and saves me a fair bit of typing, but I'd
> really like it if I could do things like :-
>
> (pasvar j)
> (setv j "hello")
> (pasvar k)
> (setv k 123)
>
> and I would get...
>
> var j string;
> var k integer;
> j := 'hello';
> k := 123;
>
> ...without having to say what type j and k are from the lisp code, ie.
> I'd like it if my utility could work out what types j and k are.
> Obviously, CL can do this, but I've not easily been able to find where
> in SBCL this happens and I would have thought that people would have
> done this sort of thing before for translation tools like this.
>
> Does anyone know of a simple way to do type inferencing for a
> destination language or perhaps where I could find one as a library?
>
> Thanks & Regards
> David

Have a look at 'The Ten Cent Lisp Type Checker'.

http://www.lambdassociates.org/studies/study02.htm

Mark