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
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!
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
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!"
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))))
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