* The progress of hacking guile and prolog
@ 2010-10-21 20:23 Stefan Israelsson Tampe
2010-11-03 23:43 ` Ludovic Courtès
0 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-10-21 20:23 UTC (permalink / raw)
To: guile-devel
Hi,
I think it's good to discuss what I do with the prolog and unifer. So this
is what I've been doing.
1. Incorporate a theorem prover for extension and playing
2. Kanren like hygienic macro package
3. Make the c-code variables printable and hence much less segfaults at bt :-)
e.g. robustify
4. Hygienify the fast umatcher.
5. try to design a type checker mimiking typed racket.
6. Play with compiled guile vm code to check for speed
7. Redesign and unugglify and improve the main prolog compiler
8. Introduce interesting features like higher order functional behavior.
9. Move the code over closer to guile Head.
Hew oh well, thats feels like a lot, let's check it out.
1. The theorem prover (leanCop) is a nice exercise to incorporate and use
because it uses quite a lot of prolog features and beeing able to compile that
into working code led me back to read up about some of my ignorantic parts of
prolog I've not setled here how to solve it. the thing is that one meld the
operator parser in prolog to whatever one may like and use that to parse
general code. I really don't like that the core languge changes behavior as
you parse language x, and added a feature where the parser enters a new
context e.g. the parsing language x and hence one can separate the two. This
is
not iso behavior although you can still modify the core language. There will
be incompabilities but you can give the users some advice how to avoid these
by using parenthesises. I think that this is a design choise for the better
though. Anyhow with some luck there will be a code prover for guile in a
couple of years :-)
2. Kanren is a nice way to program like with prolog, but using code more true
to scheme. So I've been working with a hygienic macro package that should
give such a feature. These macros will then be used in the prolog compiler
to beutyfy it. I reallt think that this is the right way and really like
what I've churn out so far.
3. The speedy umatch thingy was quite terrible to work with because it entered
these home cooked c variables into guile which just segfaulted when trying to
print it. (ugly) Anyway the print routine was hacked in my repo to print the
it better. Still there probably are some dragons sleeping here but at least
the coding experience is much better.
4. The umatch hackity hack was turned into a much more hygienic creature. Not
perfect but at least it should now play much nicer with the macro system. The
key issue was that everything was a defmacro (i did not now better then) and
the matcher introduced syntactics from outer s(pace)cope so it was not to just
bless the beast with (datum->syntax). One needed to take the x in
(syntax->datum x) and split it up, tryying to keep bits of syntactic
information to transfer it into the old macro compiler. Here comes a
pretty cool hack actually. Consider the following module:
-----------------------------------------------------------
(define-module (ice-9 syntax-matcher)
#:use-module (ice-9 match-phd-lookup)
#:export (match-syntax-hack))
(define (syntax-null? x ) (null? (syntax->datum1 x)))
(define (syntax-equal? x y) (equal? (syntax->datum1 x) y))
(define (syntax-id x)
(define (syntax? x) (not (eq? x (syntax->datum1 x))))
(if (pair? x)
x
(let ((r (syntax->datum1 x)))
(if (pair? r)
(let ((h (if (syntax? (car r)) (car r) (datum->syntax x (car r))))
(l (if (syntax? (cdr r)) (cdr r) (datum->syntax x (cdr
r)))))
(cons h l))
x))))
(make-phd-matcher match-syntax-hack ( (car cdr pair? syntax-null?
syntax-equal? syntax-id) ()))
------------------------------------------------------------
syntax->datum1 transfer a syntax object to a datum for only it's root, e.g. it
does not try to make everything a datum.
id is a lookup creature and match-phd-lookup is a modded match generator that
uses custom lookup or syntax-id as I call it. it's just an unpacking command
that is done befor car cdr and pair? is executes like
(let ((v (lookup v))) (if (pair? v) (f (car v) (cdr v))))
so it's a stupid efficiency hack so that we don't lookup all the time. Now
syntax id will open up a pair and if some of them it's children is not of a
syntax kind it will bless the child with the syntax of the parent syntax
object. Now with this matcher I want to chop up the following structure
(arg1 ... argn ((pat1, ..., patn code) ...))
and can then use:
(define (my-unsyntax X)
(define (unsyntax2 X)
(define (unsyntax3 X)
(define (unsyntax4 X)
(match-syntax-hack X
(('unquote X) (list 'unquote X))
(('uunquote X) (list 'uunquote X))
(('? X) (list '? X))
(('= X P) (list '= X (unsyntax4 P)))
(('? X P ) (list '? X (unsyntax4 P)))
((H . L) (cons (unsyntax4 H) (unsyntax4 L)))
( H (syntax->datum1 H))))
(match-syntax-hack X
((Code) (cons Code '()))
((M . L) (cons (unsyntax4 M) (unsyntax3 L)))))
(match-syntax-hack X
((X . L) (cons (unsyntax3 X) (unsyntax2 L)))
(() '())))
(match-syntax-hack X
( (X) (cons (unsyntax2 X) '()))
( (X . L) (cons X (my-unsyntax L)))))
It's not perfect syntaction but it is vastly better then before and the code
is yum yum.
5) Typechecking is for safty and optimisation, in the end it can be cool to
have and I'm working to understand all sides of this and have a pretty good
idea what is needed. It will be a goos testcase for the code.
6) I copied the glil->assembly compiler and modded the code to spit out
c-code in stead of assembly. For functions which does not call other scheme
functions except in tail call manner this should be quite fast to adapt. And
of cause loops becomes wickedly fast when compiling this way. Wingo:s example
without consing tok 7ns for each loop on my machine. (For cleaned up C it
should be less then 1 ns) Kind of interesting and a nice playground to try
out optimisations directed by type inference.
7,8,9. No more to say but that you rock, upgrading to guile head was really
a nice experience.
Now I will continue to struggle with these topics for some time (I also hope
to return to the postpone topic but to get the core in shape has higher
priority)
Happy Hacking : - )
/Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-10-21 20:23 The progress of hacking guile and prolog Stefan Israelsson Tampe
@ 2010-11-03 23:43 ` Ludovic Courtès
2010-11-04 2:40 ` Noah Lavine
` (2 more replies)
0 siblings, 3 replies; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-03 23:43 UTC (permalink / raw)
To: guile-devel
Hi Stefan,
Lots of stuff here, which is why I took the time to read it. :-)
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> 1. The theorem prover (leanCop) is a nice exercise
[...]
> 2. Kanren is a nice way to program like with prolog,
Great that you’re mentioning them. It looks like there’s a lot of
interesting work that’s been done around Kanren, such as the “toy” type
inference engine and, better, αleanTAP. I don’t grok it all I’m glad
you’re looking at it from a Guile perspective. :-)
> 4. The umatch hackity hack was turned into a much more hygienic creature.
Funny sentence. :-)
> 5) Typechecking is for safty and optimisation, in the end it can be cool to
> have and I'm working to understand all sides of this and have a pretty good
> idea what is needed. It will be a goos testcase for the code.
Yes, if the type inference engine that comes with Kanren could somehow
be hooked into Guile’s compiler, so that it can emit type-mismatch
warnings or determine whether type-checks can be optimized away (which
would require changes in the VM), that’d be great.
What’s amazing is that Kanren + type-inference.scm weigh in at “only”
~3,500 SLOC.
> 6) I copied the glil->assembly compiler and modded the code to spit out
> c-code in stead of assembly. For functions which does not call other scheme
> functions except in tail call manner this should be quite fast to adapt. And
> of cause loops becomes wickedly fast when compiling this way. Wingo:s example
> without consing tok 7ns for each loop on my machine.
Interesting. Is it a sufficiently isolated change that you could point
us to?
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-03 23:43 ` Ludovic Courtès
@ 2010-11-04 2:40 ` Noah Lavine
2010-11-10 17:55 ` Stefan Israelsson Tampe
` (4 more replies)
2010-11-04 17:57 ` Stefan Israelsson Tampe
2010-11-05 21:19 ` Stefan Israelsson Tampe
2 siblings, 5 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-04 2:40 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guile-devel
Hello all,
Not to derail the thread of discussion, but I've had an idea for a
feature bouncing around that I think might hook into this. I think
that Guile should offer optional static checking - not just of types,
but of everything that we can check. It could be used partly for
optimization, but partly also as a way to verify that you're reasoning
about the program correctly. (Like assert, but you prove things
correct.) For instance,
(define (map func list)
(check (= (arity func) 1))
....)
or
(define (search-binary-search-tree tree key)
(check (binary-search-tree? tree) ; or whatever conditions make sense
....)
I'm afraid I don't know much about how theorem provers like that would
be used to make static checkers, but is there a way to use LeanCOP or
Kanren to provide something like this? I think the easiest interface
would be one where you could put arbitrary Scheme code in check
statements, but the prover would be able to reject it as "unable to
check this", in which case it could insert a runtime check (if you
asked it to).
On a completely different note, I'm now looking at writing a compiler
for a subset of C, which could eventually become a JIT compiler. If we
could attach your GLIL->C compiler to that, it could produce a full
Scheme->machine code compiler in Guile.
Noah
On Wed, Nov 3, 2010 at 7:43 PM, Ludovic Courtès <ludo@gnu.org> wrote:
> Hi Stefan,
>
> Lots of stuff here, which is why I took the time to read it. :-)
>
> Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
>
>> 1. The theorem prover (leanCop) is a nice exercise
>
> [...]
>
>> 2. Kanren is a nice way to program like with prolog,
>
> Great that you’re mentioning them. It looks like there’s a lot of
> interesting work that’s been done around Kanren, such as the “toy” type
> inference engine and, better, αleanTAP. I don’t grok it all I’m glad
> you’re looking at it from a Guile perspective. :-)
>
>> 4. The umatch hackity hack was turned into a much more hygienic creature.
>
> Funny sentence. :-)
>
>> 5) Typechecking is for safty and optimisation, in the end it can be cool to
>> have and I'm working to understand all sides of this and have a pretty good
>> idea what is needed. It will be a goos testcase for the code.
>
> Yes, if the type inference engine that comes with Kanren could somehow
> be hooked into Guile’s compiler, so that it can emit type-mismatch
> warnings or determine whether type-checks can be optimized away (which
> would require changes in the VM), that’d be great.
>
> What’s amazing is that Kanren + type-inference.scm weigh in at “only”
> ~3,500 SLOC.
>
>> 6) I copied the glil->assembly compiler and modded the code to spit out
>> c-code in stead of assembly. For functions which does not call other scheme
>> functions except in tail call manner this should be quite fast to adapt. And
>> of cause loops becomes wickedly fast when compiling this way. Wingo:s example
>> without consing tok 7ns for each loop on my machine.
>
> Interesting. Is it a sufficiently isolated change that you could point
> us to?
>
> Thanks,
> Ludo’.
>
>
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-03 23:43 ` Ludovic Courtès
2010-11-04 2:40 ` Noah Lavine
@ 2010-11-04 17:57 ` Stefan Israelsson Tampe
2010-11-05 21:19 ` Stefan Israelsson Tampe
2 siblings, 0 replies; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-04 17:57 UTC (permalink / raw)
To: guile-devel
On Thursday, November 04, 2010 12:43:54 am Ludovic Courtès wrote:
> Hi Stefan,
>
> Lots of stuff here, which is why I took the time to read it. :-)
>
> Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> > 1. The theorem prover (leanCop) is a nice exercise
>
> [...]
>
> > 2. Kanren is a nice way to program like with prolog,
>
> Great that you’re mentioning them. It looks like there’s a lot of
> interesting work that’s been done around Kanren, such as the “toy” type
> inference engine and, better, αleanTAP. I don’t grok it all I’m glad
> you’re looking at it from a Guile perspective. :-)
Yes, but I would like to be more true to it then I am right now. So is it
enough to reproduce minikanren? Also I've reading in on racklog so I guess
what I have right now is correct conceptually but not syntactically. But of
cause this can be fixed. So If you think it is worthwhile I will download the
minikanren sorce hack on.
> > 4. The umatch hackity hack was turned into a much more hygienic creature.
>
> Funny sentence. :-)
Well I have two versions one based on the match-phd and is not touching guiles
internals and is based on passing continuations closures and has the property
that all calls are tail calls for basic prolog usage patterns. Also note that
this principle is not as expensive that one may think if you take into acount
a system that inline functions acording to findings from profiling. So in
principle all this pushing parameters to the heap could be mitigated. The
other
one is the hackety hack that tend to be fast on the vm.
> > 5) Typechecking is for safty and optimisation, in the end it can be cool
> > to have and I'm working to understand all sides of this and have a
> > pretty good idea what is needed. It will be a goos testcase for the
> > code.
>
> Yes, if the type inference engine that comes with Kanren could somehow
> be hooked into Guile’s compiler, so that it can emit type-mismatch
> warnings or determine whether type-checks can be optimized away (which
> would require changes in the VM), that’d be great.
Notes.
1. It's when compilers start to work you will gain from removing
type checks. It's probably not worth it in vm land
2. If a function is used like (f 0.1) in function g and you recompile
function f to just allow only fixnums you may end up with havoc. So
either function dependencies is tracked or you use the racket way of
executing code if going down this optimizing path in a safe way.
3. Of cause local entities can be tracked and optimized away and maybe
we should stick to only that.
> What’s amazing is that Kanren + type-inference.scm weigh in at “only”
> ~3,500 SLOC.
Hence is a powerful concept :-)
Hmm I'm also keen to match what typed racket does. I will look into this.
> > 6) I copied the glil->assembly compiler and modded the code to spit out
> > c-code in stead of assembly. For functions which does not call other
> > scheme functions except in tail call manner this should be quite fast to
> > adapt. And of cause loops becomes wickedly fast when compiling this way.
> > Wingo:s example without consing tok 7ns for each loop on my machine.
>
> Interesting. Is it a sufficiently isolated change that you could point
> us to?
Uhmm, I was just curious to se what the overhead of dispatching
instructions in a goto-loop would give when I did it. But just think of it
as a tool that just inline the c-code behind some simple vm instructions in
stead of the actual vm-instructions. Actually all prolog vanilla prolog
code should be able to be compiled quite effectively this way cause it's
all tail calls. I'm not sure my code is that interesting though Probably the
idea is more interesting and should be discussed. The basic idea is to pair
the c-code generation with the glil->assembly code so that the compiling
function and all it's internal lambda get's corresponding c-function quite
automagically and then be gcc:d into linkable code and hooked int these
functions vm part that now just act like a trampoline into C land.
Do you see it?
Have fun
Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-03 23:43 ` Ludovic Courtès
2010-11-04 2:40 ` Noah Lavine
2010-11-04 17:57 ` Stefan Israelsson Tampe
@ 2010-11-05 21:19 ` Stefan Israelsson Tampe
2010-11-19 23:11 ` GLIL->C compilation Ludovic Courtès
2 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-05 21:19 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1: Type: Text/Plain, Size: 2387 bytes --]
Ok, for the c generator, here are some code attached. I would
just study this there is bit's still missing and you need to wait for me to
dig up the details. My point is to suggest ideas for what can be done.
I don't assume that this is it. But it's a nice playing ground.
So it is a hack, here is what I do.
(use modules (language glil compile-assembly))
(set! *compile-to-c* #t)
(define (f N)
(set! <c-dummy> '<c-code-tag>) ;; This tagg!! initiate the compiler
;; and c-fkn will use the
;; <c-code-tag> slot :-)
(let loop ((I N) (X 0))
(if (eq? I 0)
X (loop
(- I 1) (+ X 1)))))
(generate-c-fkns "fkn")
Then in a sub-directory called cboost from the starting directory you find
fkn.c and a makefile. e.g.
Makefile:
=========
libguile-fkn.so : fkn.c
gcc -shared -O2 -o libguile-fkn.so -fPIC fkn.c
fkn.c:
======
#include "cfkn.h"
#define LOCAL_REF(i) fp[i]
#define LOCAL_SET(i,v) fp[i] = (v)
void cfkn3676(SCM *fp, SCM **spp)
{
/* setup of environment */
SCM *objects, *free, program, *sp, sss[100];
sp = sss;
program = fp[-1];
objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program));
free = SCM_PROGRAM_FREE_VARIABLES(program);
/* compiled section */
LCASE3666:
goto L3668;
LCASE3665:
sp++; *sp = LOCAL_REF(1);
sp++; *sp = SCM_I_MAKINUM(0);
sp-=2; if(!scm_is_eq(sp[1],sp[2])) goto L3669;
sp++; *sp = LOCAL_REF(2);
RETURN;
L3669:
sp++; *sp = LOCAL_REF(1);
SUB1;
sp++; *sp = LOCAL_REF(2);
ADD1;
LOCAL_SET(2,*sp) ; sp--;
LOCAL_SET(1,*sp) ; sp--;
goto LCASE3665;
L3668:
sp++; *sp = LOCAL_REF(0);
sp++; *sp = SCM_I_MAKINUM(0);
LOCAL_SET(2,*sp) ; sp--;
LOCAL_SET(1,*sp) ; sp--;
goto LCASE3665;
}
void init_fkn.c()
{
SCM cfkn3676_sym;
cfkn3676_sym = scm_from_locale_symbol("cfkn3676");
printf("loading fkn %s as adres %x.\n","cfkn3676",&cfkn3676);
scm_define(cfkn3676_sym,SCM_PACK(((scm_t_bits) &cfkn3676) | 2));
}
So compileing and loading the shared library into guile you should be able
to issue (f 1000000) and get a correct and fast result.
I'm did not find my cfkn.h file but I'll send you the stuff I have. I modify
glil->assembly and add offload some bit's into an extra file into the same
directory also a vm-instruction is added to be able to start the c-code.
Have fun
Stefan
[-- Attachment #2: compile2c.tar.gz --]
[-- Type: application/x-compressed-tar, Size: 9983 bytes --]
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-04 2:40 ` Noah Lavine
@ 2010-11-10 17:55 ` Stefan Israelsson Tampe
2010-11-11 19:10 ` Noah Lavine
2010-11-11 16:26 ` Ludovic Courtès
` (3 subsequent siblings)
4 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-10 17:55 UTC (permalink / raw)
To: guile-devel
On Thursday, November 04, 2010 03:40:09 am Noah Lavine wrote:
> Hello all,
>
> Not to derail the thread of discussion, but I've had an idea for a
> feature bouncing around that I think might hook into this. I think
> that Guile should offer optional static checking - not just of types,
> but of everything that we can check. It could be used partly for
> optimization, but partly also as a way to verify that you're reasoning
> about the program correctly. (Like assert, but you prove things
> correct.) For instance,
>
> (define (map func list)
> (check (= (arity func) 1))
> ....)
>
> or
> (define (search-binary-search-tree tree key)
> (check (binary-search-tree? tree) ; or whatever conditions make sense
> ....)
>
> I'm afraid I don't know much about how theorem provers like that would
> be used to make static checkers, but is there a way to use LeanCOP or
> Kanren to provide something like this? I think the easiest interface
> would be one where you could put arbitrary Scheme code in check
> statements, but the prover would be able to reject it as "unable to
> check this", in which case it could insert a runtime check (if you
> asked it to).
I think that we have similar synaptical fireworks here. The actual
implementation and syntax should be a result of understanding the line of
reasoning in these theorem povers and checkers. So let my try to explain what
I'm heading. I will try to write a little about where I am in a few days and
we can continue the discussion then.
> On a completely different note, I'm now looking at writing a compiler
> for a subset of C, which could eventually become a JIT compiler. If we
> could attach your GLIL->C compiler to that, it could produce a full
> Scheme->machine code compiler in Guile.
Shall we say that you implement a JIT compiler and I progress with the glil->c
stuff. I was uncertain an a little afraid that I toed you here.
/Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-04 2:40 ` Noah Lavine
2010-11-10 17:55 ` Stefan Israelsson Tampe
@ 2010-11-11 16:26 ` Ludovic Courtès
2010-11-11 19:13 ` Noah Lavine
2010-11-11 19:15 ` Noah Lavine
2010-11-15 23:10 ` Typechecking I Stefan Israelsson Tampe
` (2 subsequent siblings)
4 siblings, 2 replies; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-11 16:26 UTC (permalink / raw)
To: guile-devel
Hi,
Noah Lavine <noah.b.lavine@gmail.com> writes:
> On a completely different note, I'm now looking at writing a compiler
> for a subset of C, which could eventually become a JIT compiler. If we
> could attach your GLIL->C compiler to that, it could produce a full
> Scheme->machine code compiler in Guile.
Interesting. I thought you were going rather to compile a subset of
Scheme to C, which could be used to implement VM instructions, no?
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-10 17:55 ` Stefan Israelsson Tampe
@ 2010-11-11 19:10 ` Noah Lavine
0 siblings, 0 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-11 19:10 UTC (permalink / raw)
To: Stefan Israelsson Tampe; +Cc: guile-devel
Hello,
> I think that we have similar synaptical fireworks here. The actual
> implementation and syntax should be a result of understanding the line of
> reasoning in these theorem povers and checkers. So let my try to explain what
> I'm heading. I will try to write a little about where I am in a few days and
> we can continue the discussion then.
Great!
> Shall we say that you implement a JIT compiler and I progress with the glil->c
> stuff. I was uncertain an a little afraid that I toed you here.
That sounds good. In general though, please don't worry about treading
on my territory or anything like that. I will be happy as long as
Guile gets new features, and I am fine not being the person who writes
them.
Noah
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-11 16:26 ` Ludovic Courtès
@ 2010-11-11 19:13 ` Noah Lavine
2010-11-11 19:15 ` Noah Lavine
1 sibling, 0 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-11 19:13 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guile-devel
Yes, that's right. I was unclear. I am intending to come up with a
language that I can compile to C, to implement VM instructions. I
meant I would compile something to C, not from it to machine code.
Just to clarify, it probably won't be a subset of Scheme (although one
could compile a subset of Scheme to this language). I was thinking of
something more like register transfer language, so the compiler will
be very simple.
Noah
On Thu, Nov 11, 2010 at 11:26 AM, Ludovic Courtès <ludo@gnu.org> wrote:
> Hi,
>
> Noah Lavine <noah.b.lavine@gmail.com> writes:
>
>> On a completely different note, I'm now looking at writing a compiler
>> for a subset of C, which could eventually become a JIT compiler. If we
>> could attach your GLIL->C compiler to that, it could produce a full
>> Scheme->machine code compiler in Guile.
>
> Interesting. I thought you were going rather to compile a subset of
> Scheme to C, which could be used to implement VM instructions, no?
>
> Thanks,
> Ludo’.
>
>
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-11 16:26 ` Ludovic Courtès
2010-11-11 19:13 ` Noah Lavine
@ 2010-11-11 19:15 ` Noah Lavine
1 sibling, 0 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-11 19:15 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guile-devel
> Interesting. I thought you were going rather to compile a subset of
> Scheme to C, which could be used to implement VM instructions, no?
Yes, that was my plan, sorry. I want to compile things to C, not from
C to machine code.
Also, to clarify, I am looking at compiling not a subset of C, but
something like register transfer language. That way the compiler can
be very simple and hopefully obviously correct.
Noah
^ permalink raw reply [flat|nested] 33+ messages in thread
* Typechecking I
2010-11-04 2:40 ` Noah Lavine
2010-11-10 17:55 ` Stefan Israelsson Tampe
2010-11-11 16:26 ` Ludovic Courtès
@ 2010-11-15 23:10 ` Stefan Israelsson Tampe
2010-11-20 11:46 ` Andy Wingo
2010-11-20 11:25 ` The progress of hacking guile and prolog Andy Wingo
2010-11-20 11:26 ` Andy Wingo
4 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-15 23:10 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1: Type: Text/Plain, Size: 4998 bytes --]
Hi,
Ok, here is a first step to analyse code.
Note,
attached to the mail is a modul /put it at a suitable place and fixup the
reference for the module. Then use e.g. (check '(if 1 1 1)) and you will get
the output you see further down in the email.
We will assume that local variables in the following is gensymed to be unique
and no name clashes apear.
For typechecking i find it interesting to consider an equational approach
first. e.g. translate code to an equation system.
let's take a first simple step here and and assume that the typecheck function
just finds the equation we need to solve in order to understand type
consistency and discovery. we will assume that typecheck is of the form
(typecheck Eq Code Type) or in short
Eq is current equational state,
Code the code to draw equations out of.
Type the type associated with the result of Code
******************* Item I *******************************
[let X Y Z] : T
Translates to
(typecheck (typecheck Eq Y X) Z T)
Example of equation generation:
(let x 1 x):
((= integer x) (= x Texp))
(let x 1 (let y x y)):
((= integer x) (= x y) (= y Texp))
TODO: Note: (= y x) should be more nicer for the understanding!!!
This is not earthshaken. But I think it is wise to handle first such an
translational step in order to write a solver in kanren or prolog or racklog
or guilelog :-) for the more general case.
******************* Item II ***************************
[begin x ... xx] : T
(typecheck x e) o ... o (typecheck xx T)
the symbol e will mean an anything object so that essentially [= e x] is true
for all x. You could say everything that we have not assigned a type to has
type e and then (the idea) is that the all scheme expression should
typecheck. It remains to define the properties and rules associated with e to
make this work. The target is to be able to gradually mix typed expressions
with untyped expression.
Example:
(begin 1 "a" 1):
((= integer e)
(= string e)
(= integer Texp))
******************* Item III ****************************
[lambda [x ...] code]
What to look up for here is that essentialle every usage of a lambda inside
a function has to, to be general, have a unique set of equations and do a
unique deduction. This can be expensive, but is the correct way to treat the
typechecking of the lambda. So we must tell the solver later on that we are
going to treat a lambda, e.g. x ... will be a unique version at every usage
of the lambda the directive for the solver is (lambda vars res equation)
lambda conceptually translates to an abstraction of an equations.
Example
(lambda (x y) x):
((= (lambda (x y) Tlam6583
((= x Tlam6583))) Texp))
********************** Item IV **************************
[apply f [x ...]] : T
First of all we need to deduce the equation of f, to yield a lambda. e.g.
(typecheck f [lamda [ArgType(x) ...] ResType]) o
(typecheck x [arg ArgType(x)] ) o ... o
(add-equation [= [res ResType] T])
so
1. define the functional signatur.
2. find the equations typececked to [arg X], arg is a directive to the solver
to tell it that we are equating a function argument why? well the equality
needs to be treated differnetly in order to be correct.
3. the same reason for the addition of the last equation. we need to inform
the
solver that ResType is of a result type.
Example:
(apply (lambda (x y) x) (1 2)) :
((= (lambda (x y) Tlam6954 ((= x Tlam6954))) ;; a lambda type abstraction
(lambda (Targ6951 Targ6952) Tres6953)) ;; a lambda type
(= integer (arg Targ6951))
(= integer (arg Targ6952))
(= (res Tres6953) Texp))
Can you see how res and arg differ
(= T (arg (or A B C))) ; argument can be A or B or C
(= T (res (or A B C))) ; function produces A or B or C
**************** Item V *************
[if P X Y] : T
(integer? X) makes a promise that if true then X is an integer and
is a string. Consider (= (res A) (arg integer)) if the result of a function
is anything it follows that it can't unify with an argument that has to
take an inte integer as in the case
(+ (g X) 1) and g is not typehcecked and we cannot ussume anything
about it hence the typecheck should fail. On the other hand
(if (integer? (g X)) (+ (g X) 1) #f) should be able to typecheck
against (or integer boolean) and here we would have an equality of the
type (= (validated integer) (res A)) and then A=integer in the rest of the
equations in the or.
Example:
(let x 1 (if (integer? x) "a" 2))
=================================
(= integer x)
(or ((= x (validated integer)) (= string Texp))
((= x (validated (not integer)))
(= integer Texp))))
So maybe it's an unessesary step but at least I appriciate this little
transformation to get an understanding the subject. I'll will now work
a little with solving the equations.
And yes, all tree-il is not included, but I fix the complexity at this level
and move over to solving the equations.
Play around and have fun
/Stefan
[-- Attachment #2: equationalize.scm --]
[-- Type: text/x-scheme, Size: 9222 bytes --]
(define-module (language prolog typecheck equationalize)
#:use-module (srfi srfi-1 )
#:use-module (ice-9 pretty-print )
#:use-module (ice-9 match )
#:use-module (ice-9 receive )
#:export (equationalize check))
;; the main function is equationalize, which takes a format that should be derived from
;; tree-il representation with suitable tags to be able to communicate to the compiler
;; about type-checking conclusions. For know it's just a toy translator. The idea is to
;; translate this code to a set of equations that later on is fed into the typechecker and
;; is a good starting point to see the type structure
;;
;; (equationalize Bindings Equations Code Outer-type)
;; To get the equations of (if 1 1 1) you would write
;; (recieve (Bind Eq) (equationalize '() '() '(if 1 1 1) 'T-outer) ...)
;;
;; the language have just a few functions implemented for illustration
;; (number? X),(integer? X), (symbol? X), (char? X), (string? X)., (boolean? X).
;; plain simple (if X Y Z) (let Var Val Code) (lambda (x ...) code) is available as
;; well. functions application should be written as (apply symbol? X).
;; and or and not is supported as is because they are special
;;
;; So currently not that exciting but it is very instructive to play with a few expressions
;; an look att the corresponding equations that results. esiest is to use the check function
;; like (check Code) e.g. (check `(if 1 1 1)) which produces the type equation,
;;(if 1 1 1)
;;((or ((= 1 boolean) (= integer Texp))
;; ((not (= 1 boolean)) (= integer Texp))))
;;Have a play!
(define (pp X) (begin (pretty-print X) X))
(define union (lambda (x y) (lset-union eq? x y)))
;;**************************** PRELUDE TO TYPECHECKING ***********************
;;This is just to kill of receive nesting buitifies the code alot
(define-syntax rlet
(syntax-rules ()
((_ (((a ...) c) . l) code ...)
(receive (a ...) c
(rlet l code ...)))
((_ ((a c) . l) code ...)
(let ((a c))
(rlet l code ...)))
((_ () code ...) (begin code ...))))
(define (compute-type Const Code)
(define (type? X) (and (symbol? X) (char-upper-case? (car (string->list (symbol->string X))))))
(define (gen-map Code Bind Lam)
(match Code
([X . L] (gen-map X Bind (lambda (Bind) (gen-map L Bind Lam))))
((? type? X) (if (member X Bind)
(Lam Bind)
(let ((T (Const)))
(Lam (cons (cons X T) Bind)))))
(_ (Lam Bind))))
(define (make-rep X Bind)
(match X
([X . L] (cons (make-rep X Bind) (make-rep L Bind)))
([] '[])
(X (let ((R (assoc-ref Bind X)))
(if R R X)))))
(make-rep Code (gen-map Code '() (lambda (x) x))))
;;typecheck will create a list of equation that defines the rules for the predicates, the rules are
;; [= A B] A and B should unify
;; [and A B] [A B] A holds and B holds
;; [or A B] A holds or B holds
;; [not A] A is not true
;; [arg A] A is an argument variable
;; [res A] A is the result of a function
;; e Accepts everything
(define (equationalize Bind Eq Expr Tp)
;;(pp Expr)
(match Expr
(['let X V Code] (rlet (((Bind Eq) (equationalize Bind Eq V X)))
(equationalize (cons X Bind) Eq Code Tp )))
(['lambda V Code] (rlet (( Tlam (gensym "Tlam"))
((Bind-lam Eq-lam) (equationalize (append V Bind) '() Code Tlam)))
(values Bind (cons `(= (lambda ,V ,Tlam ,Eq-lam) ,Tp) Eq))))
(['if P X Y] (rlet ((F (equationalize-bool Bind '() P))
((Bind1 Eq1) (F #t))
((Bind0 Eq0) (F #f))
((Bind1 Eq1) (equationalize Bind1 Eq1 X Tp))
((Bind0 Eq0) (equationalize Bind0 Eq0 Y Tp)))
(values (union Bind0 Bind1) (append `((or ,(reverse Eq1) ,(reverse Eq0))) Eq))))
(['apply F A] (rlet ((Ta (map (lambda x (gensym "Targ")) A))
(Tr (gensym "Tres"))
((Bind Eq) (equationalize Bind Eq F `[lambda ,Ta ,Tr]))
((Bind Eq) (equationalize-arg Bind Eq A Ta)))
(values Bind (cons `[= [res ,Tr] ,Tp] Eq))))
(['begin A] (equationalize Bind Eq A Tp))
(['begin A . L] (rlet (((Bind Eq) (equationalize Bind Eq A 'e)))
(equationalize Bind Eq (cons 'begin L) Tp)))
((? symbol? X) (if (member X Bind)
(values Bind (cons `(= ,X ,Tp) Eq))
(let ((Ts (symbol-property X ':type)))
(if Ts
(values Bind (cons `(= ,(compute-type (lambda () (gensym "T")) Ts) ,Tp) Eq))
(values Bind (cons `(= e ,Tp) Eq))))))
(('quote (? symbol?)) (values Bind (cons `(= symbol ,Tp) Eq)))
((? integer?) (values Bind (cons `(= integer ,Tp) Eq)))
((? boolean?) (values Bind (cons `(= boolean ,Tp) Eq)))
((? number? ) (values Bind (cons `(= number ,Tp) Eq)))
((? char? ) (values Bind (cons `(= character ,Tp) Eq)))
((? string? ) (values Bind (cons `(= string ,Tp) Eq)))))
(define (check X)
(rlet ((A X)
((Ba Ea) (equationalize '() '() A 'Texp)))
(pp A)
(pp (reverse Ea)))
#t)
(define typemap '((+ (lambda (number number) number))
(id (lam (A) A))
(- (lambda (number number) number))))
(map (lambda (x) (match x ((Sym T) (set-symbol-property! Sym ':type T))))
typemap)
(define (equationalize-arg Bind Eq Xs Tps)
(match `(,Xs ,Tps)
(([X . Xs] [Tp . Tps]) (rlet (((Bind Eq) (equationalize Bind Eq X (list 'arg Tp))))
(equationalize-arg Bind Eq Xs Tps)))
(([] [] ) (values Bind Eq))))
(define *predtypes*
'((string? string )
(symbol? symbol )
(integer? integer )
(number? number )
(boolean? boolean )
(char? char )))
(define (equationalize-bool Bind Eq Expr)
(define (pred? X)
(define (f L)
(if (pair? L)
(if (eq? X (caar L))
#t
(f (cdr L)))
#f))
(f *predtypes*))
(define (type-of-pred X)
(define (f L)
(if (pair? L)
(if (eq? X (caar L))
(cadar L)
(f (cdr L)))
#f))
(f *predtypes*))
;;(pk Expr)
(match Expr
(['and X Y] (let ((F1 (equationalize-bool Bind Eq X))
(F2 (equationalize-bool Bind Eq Y)))
(lambda (X)
(if X
(rlet (((Bind1 Eq1) (F1 #t))
((Bind2 Eq2) (F2 #t)))
(values (union Bind1 Bind2) `(and ,Eq1 ,Eq2)))
(rlet (((Bind1 Eq1) (F1 #f))
((Bind2 Eq2) (F2 #f)))
(values (union Bind1 Bind2) `(or ,Eq1 ,Eq2)))))))
(['or X Y] (let ((F1 (equationalize-bool Bind Eq X))
(F2 (equationalize-bool Bind Eq Y)))
(lambda (X)
(if X
(rlet (((Bind1 Eq1) (F1 #t))
((Bind2 Eq2) (F2 #t)))
(values (union Bind1 Bind2) `(or ,Eq1 ,Eq2)))
(rlet (((Bind1 Eq1) (F1 #f))
((Bind2 Eq2) (F2 #f)))
(values (union Bind1 Bind2) `(and ,Eq1 ,Eq2)))))))
(['not X ] (let ((F (equationalize-bool Bind Eq X)))
(lambda (X)
(if X (F #f) (F #t)))))
([(? pred? String?) X] (lambda (P)
(if P
(equationalize Bind Eq X `(validated ,(type-of-pred String?)))
(equationalize Bind Eq X `(validated (not ,(type-of-pred String?)))))))
(X (lambda (P)
(if P
(values Bind (cons `[= ,X boolean] Eq))
(values Bind (cons `[not [= ,X boolean]] Eq)))))))
^ permalink raw reply [flat|nested] 33+ messages in thread
* GLIL->C compilation
2010-11-05 21:19 ` Stefan Israelsson Tampe
@ 2010-11-19 23:11 ` Ludovic Courtès
2010-11-19 23:20 ` Stefan Israelsson Tampe
0 siblings, 1 reply; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-19 23:11 UTC (permalink / raw)
To: guile-devel
Hi,
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> #include "cfkn.h"
> #define LOCAL_REF(i) fp[i]
> #define LOCAL_SET(i,v) fp[i] = (v)
> void cfkn3676(SCM *fp, SCM **spp)
> {
> /* setup of environment */
> SCM *objects, *free, program, *sp, sss[100];
> sp = sss;
> program = fp[-1];
> objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program));
> free = SCM_PROGRAM_FREE_VARIABLES(program);
> /* compiled section */
> LCASE3666:
>
>
> goto L3668;
> LCASE3665:
> sp++; *sp = LOCAL_REF(1);
> sp++; *sp = SCM_I_MAKINUM(0);
> sp-=2; if(!scm_is_eq(sp[1],sp[2])) goto L3669;
> sp++; *sp = LOCAL_REF(2);
[...]
Comparing this to the VM’s bytecode interpreter should show the overhead
incurred by instruction dispatch.
Did you try to measure this? That’d be interesting.
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: GLIL->C compilation
2010-11-19 23:11 ` GLIL->C compilation Ludovic Courtès
@ 2010-11-19 23:20 ` Stefan Israelsson Tampe
2010-11-19 23:56 ` Ludovic Courtès
0 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-19 23:20 UTC (permalink / raw)
To: guile-devel
On Saturday, November 20, 2010 12:11:16 am Ludovic Courtès wrote:
> Hi,
>
> Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> > #include "cfkn.h"
> > #define LOCAL_REF(i) fp[i]
> > #define LOCAL_SET(i,v) fp[i] = (v)
> > void cfkn3676(SCM *fp, SCM **spp)
> > {
> >
> > /* setup of environment */
> > SCM *objects, *free, program, *sp, sss[100];
> > sp = sss;
> > program = fp[-1];
> > objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program));
> > free = SCM_PROGRAM_FREE_VARIABLES(program);
> > /* compiled section */
> >
> > LCASE3666:
> > goto L3668;
> > LCASE3665:
> > sp++; *sp = LOCAL_REF(1);
> > sp++; *sp = SCM_I_MAKINUM(0);
> > sp-=2; if(!scm_is_eq(sp[1],sp[2])) goto L3669;
> > sp++; *sp = LOCAL_REF(2);
>
> [...]
>
> Comparing this to the VM’s bytecode interpreter should show the overhead
> incurred by instruction dispatch.
>
> Did you try to measure this? That’d be interesting.
>
> Thanks,
> Ludo’.
Yes on one of my machine one loop takes about 6ns for the compiled one and
about 50ns for the bytcode, say a factor of 7-10 for simple tasks, but
remember
this is for rather trivial work.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: GLIL->C compilation
2010-11-19 23:20 ` Stefan Israelsson Tampe
@ 2010-11-19 23:56 ` Ludovic Courtès
2010-11-20 12:18 ` Andy Wingo
0 siblings, 1 reply; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-19 23:56 UTC (permalink / raw)
To: guile-devel
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> On Saturday, November 20, 2010 12:11:16 am Ludovic Courtès wrote:
>> Hi,
>>
>> Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
>> > #include "cfkn.h"
>> > #define LOCAL_REF(i) fp[i]
>> > #define LOCAL_SET(i,v) fp[i] = (v)
>> > void cfkn3676(SCM *fp, SCM **spp)
>> > {
>> >
>> > /* setup of environment */
>> > SCM *objects, *free, program, *sp, sss[100];
>> > sp = sss;
>> > program = fp[-1];
>> > objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program));
>> > free = SCM_PROGRAM_FREE_VARIABLES(program);
>> > /* compiled section */
>> >
>> > LCASE3666:
>> > goto L3668;
>> > LCASE3665:
>> > sp++; *sp = LOCAL_REF(1);
>> > sp++; *sp = SCM_I_MAKINUM(0);
>> > sp-=2; if(!scm_is_eq(sp[1],sp[2])) goto L3669;
>> > sp++; *sp = LOCAL_REF(2);
>>
>> [...]
>>
>> Comparing this to the VM’s bytecode interpreter should show the overhead
>> incurred by instruction dispatch.
>>
>> Did you try to measure this? That’d be interesting.
>>
>> Thanks,
>> Ludo’.
>
> Yes on one of my machine one loop takes about 6ns for the compiled one and
> about 50ns for the bytcode, say a factor of 7-10 for simple tasks, but
> remember
> this is for rather trivial work.
Woow, I didn’t expect so much.
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-04 2:40 ` Noah Lavine
` (2 preceding siblings ...)
2010-11-15 23:10 ` Typechecking I Stefan Israelsson Tampe
@ 2010-11-20 11:25 ` Andy Wingo
2010-11-24 1:54 ` Noah Lavine
2010-11-20 11:26 ` Andy Wingo
4 siblings, 1 reply; 33+ messages in thread
From: Andy Wingo @ 2010-11-20 11:25 UTC (permalink / raw)
To: Noah Lavine; +Cc: Ludovic Courtès, guile-devel
Hi Noah,
On Thu 04 Nov 2010 03:40, Noah Lavine <noah.b.lavine@gmail.com> writes:
> I think that Guile should offer optional static checking - not just of
> types, but of everything that we can check.
It seems like you're really asking for *dynamic* checking -- not only
checking properties that can be proved statically, without running the
program, but also runtime properties.
In this regard, I have a positive impression of the work that people are
doing on "contracts", especially the Racket folks.
http://docs.racket-lang.org/reference/contracts.html
Happy reading,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-04 2:40 ` Noah Lavine
` (3 preceding siblings ...)
2010-11-20 11:25 ` The progress of hacking guile and prolog Andy Wingo
@ 2010-11-20 11:26 ` Andy Wingo
4 siblings, 0 replies; 33+ messages in thread
From: Andy Wingo @ 2010-11-20 11:26 UTC (permalink / raw)
To: Noah Lavine; +Cc: Ludovic Courtès, guile-devel
Hi again,
The more apropos link to Racket's contracts would probably be:
http://docs.racket-lang.org/guide/contracts.html
Cheers,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Typechecking I
2010-11-15 23:10 ` Typechecking I Stefan Israelsson Tampe
@ 2010-11-20 11:46 ` Andy Wingo
0 siblings, 0 replies; 33+ messages in thread
From: Andy Wingo @ 2010-11-20 11:46 UTC (permalink / raw)
To: Stefan Israelsson Tampe; +Cc: guile-devel
Hi,
Just some superficial notes while reading your code :)
On Tue 16 Nov 2010 00:10, Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> (define-module (language prolog typecheck equationalize)
> #:use-module (srfi srfi-1 )
> #:use-module (ice-9 pretty-print )
> #:use-module (ice-9 match )
> #:use-module (ice-9 receive )
> #:export (equationalize check))
Thanks for making it depend on only modules in Guile :-)
The extra spaces before the close-parens should be removed, though.
> (define-syntax rlet
This is usually known as let-values, fwiw.
> (define (compute-type Const Code)
> (define (type? X) (and (symbol? X) (char-upper-case? (car (string->list (symbol->string X))))))
Try to keep your lines to less than 80 characters, please :)
> (define (gen-map Code Bind Lam)
> (match Code
> ([X . L] (gen-map X Bind (lambda (Bind) (gen-map L Bind Lam))))
The conventional indentation for this is:
(match Code
([X . L] ...))
If your emacs doesn't do this, add this to your .emacs:
(put 'match 'scheme-indent-function 1)
> (define (check X)
> (rlet ((A X)
> ((Ba Ea) (equationalize '() '() A 'Texp)))
> (pp A)
Likewise for rlet -- though it should be just let*-values, if it were a
macro of your own, you could add a similar block to the .emacs.
> (match Expr
> (['and X Y] (let ((F1 (equationalize-bool Bind Eq X))
> (F2 (equationalize-bool Bind Eq Y)))
> (lambda (X)
> (if X
> (rlet (((Bind1 Eq1) (F1 #t))
> ((Bind2 Eq2) (F2 #t)))
> (values (union Bind1 Bind2) `(and ,Eq1 ,Eq2)))
> (rlet (((Bind1 Eq1) (F1 #f))
> ((Bind2 Eq2) (F2 #f)))
> (values (union Bind1 Bind2) `(or ,Eq1 ,Eq2)))))))
>
> (['or X Y] (let ((F1 (equationalize-bool Bind Eq X))
> (F2 (equationalize-bool Bind Eq Y)))
>
Here again, much more conventional would be
(match Expr
(['and X Y]
(let ((F1 (equationalize-bool Bind Eq X))
(F2 (equationalize-bool Bind Eq Y)))
(lambda (X)
(if X
(rlet (((Bind1 Eq1) (F1 #t))
((Bind2 Eq2) (F2 #t)))
(values (union Bind1 Bind2) `(and ,Eq1 ,Eq2)))
(rlet (((Bind1 Eq1) (F1 #f))
((Bind2 Eq2) (F2 #f)))
(values (union Bind1 Bind2) `(or ,Eq1 ,Eq2)))))))
(['or X Y]
...))
Your style is has gotten a lot more readable, for which I am grateful :)
There is still some small ways to go yet, though.
Syntactically yours,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: GLIL->C compilation
2010-11-19 23:56 ` Ludovic Courtès
@ 2010-11-20 12:18 ` Andy Wingo
0 siblings, 0 replies; 33+ messages in thread
From: Andy Wingo @ 2010-11-20 12:18 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guile-devel
On Sat 20 Nov 2010 00:56, ludo@gnu.org (Ludovic Courtès) writes:
>> Yes on one of my machine one loop takes about 6ns for the compiled one and
>> about 50ns for the bytcode, say a factor of 7-10 for simple tasks, but
>> remember
>> this is for rather trivial work.
>
> Woow, I didn’t expect so much.
I would expect it, yes. Something aroung 5x for dispatch, with more if
the compiler decided to inline more things across "instruction"
boundaries.
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-20 11:25 ` The progress of hacking guile and prolog Andy Wingo
@ 2010-11-24 1:54 ` Noah Lavine
2010-11-24 16:45 ` Stefan Israelsson Tampe
` (3 more replies)
0 siblings, 4 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-24 1:54 UTC (permalink / raw)
To: Andy Wingo; +Cc: guile-devel
Hello,
That might make sense. The documentation certainly looks interesting.
What I'm thinking of is like racket contracts, but with the idea of
"trusted modules", which might involve static checking. For instance,
if the contract is that map's second parameter is a list, you'd
normally want to check that. But if a module that used map could
guarantee that it would always pass a list as the second argument,
then you'd arrange things so the second module could skip the type
check.
I'm curious in general though whether it would be possible and
worthwhile to statically check programmer-defined ideas, as long as
the interface is easy enough to use. For instance, what if you could
ask Guile to check that your tree structure always remained a binary
tree? Or better, what if you wrote a GUI program and checked that the
callbacks you passed to the GUI library would always return? (I know
it's not possible in general, but I think it will work for a subset of
procedures that will include some interesting ones.)
Noah
On Sat, Nov 20, 2010 at 6:25 AM, Andy Wingo <wingo@pobox.com> wrote:
> Hi Noah,
>
> On Thu 04 Nov 2010 03:40, Noah Lavine <noah.b.lavine@gmail.com> writes:
>
>> I think that Guile should offer optional static checking - not just of
>> types, but of everything that we can check.
>
> It seems like you're really asking for *dynamic* checking -- not only
> checking properties that can be proved statically, without running the
> program, but also runtime properties.
>
> In this regard, I have a positive impression of the work that people are
> doing on "contracts", especially the Racket folks.
>
> http://docs.racket-lang.org/reference/contracts.html
>
> Happy reading,
>
> Andy
> --
> http://wingolog.org/
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-24 1:54 ` Noah Lavine
@ 2010-11-24 16:45 ` Stefan Israelsson Tampe
2010-11-24 18:00 ` piper schemigan Stefan Israelsson Tampe
` (2 subsequent siblings)
3 siblings, 0 replies; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-24 16:45 UTC (permalink / raw)
To: guile-devel
Hi Noah,
On Wednesday, November 24, 2010 02:54:37 am Noah Lavine wrote:
> Hello,
>
> That might make sense. The documentation certainly looks interesting.
>
> What I'm thinking of is like racket contracts, but with the idea of
> "trusted modules", which might involve static checking. For instance,
> if the contract is that map's second parameter is a list, you'd
> normally want to check that. But if a module that used map could
> guarantee that it would always pass a list as the second argument,
> then you'd arrange things so the second module could skip the type
> check.
Sure static typechecking can save some time, but also note that it can bring
in applications that would not be on a scheme platform without static
typechecking/proofing due to code safety reason imaginable or not
(again static versus dynamic). An intersting note, one here stories about
codebases around a popular dynamically p.l. where the test harness grow out
of bounds and where the major part of it is test that the static typechecker
would have been performed by default in both a much faster manner and also
more rigourusly. Personally I prefere dynamic - but that is from my usage
pattern which is mainly smaller programs that automate. Form this I'm
wondering if the people in this hersay really take advantage
of testing only the relevant parts of the code in light of done changes.
> I'm curious in general though whether it would be possible and
> worthwhile to statically check programmer-defined ideas, as long as
> the interface is easy enough to use. For instance, what if you could
> ask Guile to check that your tree structure always remained a binary
> tree? Or better, what if you wrote a GUI program and checked that the
> callbacks you passed to the GUI library would always return? (I know
> it's not possible in general, but I think it will work for a subset of
> procedures that will include some interesting ones.)
Yep I agree with you here.
Here is an idea:
You can try to say something like this function argument will never be
returned or kept in a closure etc. Then you might allocate that object from
the stack. Again it is not always ways to proove this but sometimes you
can. So the function argument could be of a proved not proved and don't know
and you can make sure to use the safe way. Then you can guide a user to prove
that it is indeed so or let the user say it is so or just take the safe path
and allocate from the heap. There is a nice pattern here that one could employ
when there is a compiler for guile (without compiler the speedup is not that
exiting on a relative scale). Process the code and builed up the result using
a tail call paraadigm, e.g. there is a parameter res that is constructed. Then
at the end return (heapify (revers ret)) and transfere the constructed ret
object to the heap by trying to fill a continuous segment on the heap by cons
cells that is linked appropriated. That way you get some work to align objects
on the heap, allocate a big chunk at the time and the overall performance
scale and is performat. I would say that 99% of the code I write that use or
could use this pattern can be typechecked to proove that res could be builed
up from stack elements. The typical usage scenario here is to speed up
functional (no mutating) code transformations.
Have fun
Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* piper schemigan
2010-11-24 1:54 ` Noah Lavine
2010-11-24 16:45 ` Stefan Israelsson Tampe
@ 2010-11-24 18:00 ` Stefan Israelsson Tampe
2010-11-24 20:18 ` Andreas Rottmann
2010-11-25 21:17 ` Ludovic Courtès
2010-11-25 21:26 ` The progress of hacking guile and prolog Ludovic Courtès
2010-11-26 10:45 ` Andy Wingo
3 siblings, 2 replies; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-24 18:00 UTC (permalink / raw)
To: guile-devel
Hi,
I'm very used to take the standart output and pipe it to grep and friends.
So I searched for this feature and I think scsh is the correct way to make
this happen. But it have been bitrotted.
So I've hacked the sorces to.
Use guile syntax-define and cut out defmacro and friends
Use guile modules whenever possible keeping the interface as
intact as possible, e.g use,
(ice-9 optargs)
(ice-9 regexp)
(srfi srfi-9)
(srfi srfi-9 gnu)
In stead of the scsh bag of software for these cases.
There are a few issues that I found
1. the macro run uses unquote out of a visble backquote and guile barfs
2. I was not able to use the | symbol.
Any useful comments?
Regards
Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: piper schemigan
2010-11-24 18:00 ` piper schemigan Stefan Israelsson Tampe
@ 2010-11-24 20:18 ` Andreas Rottmann
2010-11-25 21:17 ` Ludovic Courtès
1 sibling, 0 replies; 33+ messages in thread
From: Andreas Rottmann @ 2010-11-24 20:18 UTC (permalink / raw)
To: Stefan Israelsson Tampe; +Cc: guile-devel
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> Hi,
>
> I'm very used to take the standart output and pipe it to grep and friends.
> So I searched for this feature and I think scsh is the correct way to make
> this happen. But it have been bitrotted.
>
> So I've hacked the sorces to.
>
> Use guile syntax-define and cut out defmacro and friends
>
Yay for getting rid of defmacro!
> Use guile modules whenever possible keeping the interface as
> intact as possible, e.g use,
>
> (ice-9 optargs)
> (ice-9 regexp)
> (srfi srfi-9)
> (srfi srfi-9 gnu)
>
> In stead of the scsh bag of software for these cases.
>
> There are a few issues that I found
> 1. the macro run uses unquote out of a visble backquote and guile
> barfs
>
Please provide a more detailed explanation -- what exactly did you try
and what was the exact error did message you did get? It is indeed
possible to write macros that behave as its input was implicitly
backquoted, e.g.:
(define-syntax run
(syntax-rules ()
((_ command args ...)
(begin
(display (cons `command `(args ...)))
(newline)))))
scheme@(guile-user)> (run "echo" ,(+ 1 2))
(echo 3)
> 2. I was not able to use the | symbol.
>
I just checked, and on both Guile HEAD (from recent git) and Guile
1.8.7, `|' is a valid symbol, although it is not valid according to R5RS
and R6RS. What difficulties are you experiencing exactly?
Regards, Rotty
--
Andreas Rottmann -- <http://rotty.yi.org/>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: piper schemigan
2010-11-24 18:00 ` piper schemigan Stefan Israelsson Tampe
2010-11-24 20:18 ` Andreas Rottmann
@ 2010-11-25 21:17 ` Ludovic Courtès
2010-11-26 22:18 ` Stefan Israelsson Tampe
1 sibling, 1 reply; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-25 21:17 UTC (permalink / raw)
To: guile-devel
+1 for reviving Guile-SCSH!
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-24 1:54 ` Noah Lavine
2010-11-24 16:45 ` Stefan Israelsson Tampe
2010-11-24 18:00 ` piper schemigan Stefan Israelsson Tampe
@ 2010-11-25 21:26 ` Ludovic Courtès
2010-11-26 16:41 ` Noah Lavine
2010-11-26 10:45 ` Andy Wingo
3 siblings, 1 reply; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-25 21:26 UTC (permalink / raw)
To: guile-devel
Hi!
Noah Lavine <noah.b.lavine@gmail.com> writes:
> What I'm thinking of is like racket contracts, but with the idea of
> "trusted modules", which might involve static checking. For instance,
> if the contract is that map's second parameter is a list, you'd
> normally want to check that. But if a module that used map could
> guarantee that it would always pass a list as the second argument,
> then you'd arrange things so the second module could skip the type
> check.
In Guile, modules are dynamic by nature: they are assembled at run-time
(everything is “dynamically linked”). My feeling is that cross-module
static analysis doesn’t fit well in this framework.
> I'm curious in general though whether it would be possible and
> worthwhile to statically check programmer-defined ideas, as long as
> the interface is easy enough to use. For instance, what if you could
> ask Guile to check that your tree structure always remained a binary
> tree?
I think you’ll be interested in dependent types:
https://secure.wikimedia.org/wikipedia/en/wiki/Dependent_types
Though I’d recommend working on JIT for Guile before you get stuck in a
meta-circular Curry-Howardish enlightenment period. :-)
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-24 1:54 ` Noah Lavine
` (2 preceding siblings ...)
2010-11-25 21:26 ` The progress of hacking guile and prolog Ludovic Courtès
@ 2010-11-26 10:45 ` Andy Wingo
3 siblings, 0 replies; 33+ messages in thread
From: Andy Wingo @ 2010-11-26 10:45 UTC (permalink / raw)
To: Noah Lavine; +Cc: guile-devel
Hi Noah,
On Wed 24 Nov 2010 02:54, Noah Lavine <noah.b.lavine@gmail.com> writes:
> What I'm thinking of is like racket contracts, but with the idea of
> "trusted modules", which might involve static checking.
Yeah, definitely. Like the interface between typed and untyped code in
racket, also. I don't know very much about the relationship between
types and contracts, though.
> I'm curious in general though whether it would be possible and
> worthwhile to statically check programmer-defined ideas, as long as
> the interface is easy enough to use. For instance, what if you could
> ask Guile to check that your tree structure always remained a binary
> tree? Or better, what if you wrote a GUI program and checked that the
> callbacks you passed to the GUI library would always return? (I know
> it's not possible in general, but I think it will work for a subset of
> procedures that will include some interesting ones.)
It's certainly interesting! As I understand things (which is not very
far), Racket allows for this via other "languages". Guile could do that
too. We might need some more generic support for this kind of thing in
the compiler infrastructure or in tree-il or whatever, but I would like
to make it possible to experiment with these linguistic ideas, with the
kind of isolation provided by modules.
Cheers,
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: The progress of hacking guile and prolog
2010-11-25 21:26 ` The progress of hacking guile and prolog Ludovic Courtès
@ 2010-11-26 16:41 ` Noah Lavine
0 siblings, 0 replies; 33+ messages in thread
From: Noah Lavine @ 2010-11-26 16:41 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: guile-devel
Hello,
> Though I’d recommend working on JIT for Guile before you get stuck in a
> meta-circular Curry-Howardish enlightenment period. :-)
I agree. :-)
Noah
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: piper schemigan
2010-11-25 21:17 ` Ludovic Courtès
@ 2010-11-26 22:18 ` Stefan Israelsson Tampe
2010-11-28 22:30 ` Guile-SCSH Ludovic Courtès
0 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-26 22:18 UTC (permalink / raw)
To: guile-devel
On Thursday, November 25, 2010 10:17:44 pm Ludovic Courtès wrote:
> +1 for reviving Guile-SCSH!
>
> Ludo’.
yay,
Well all this stems from me littering development code with printf or pk's
or pretty-pk's and then add tags to it. Then I usually work in bash and
mongle the output at my will. So now I have this is guile and are so pleased
that I can do
(use-modules (scsh syntax))
and then write
(run (| (begin (the-schem-fun)) '(grep abc) '(tee debug.log)))
Oh well, actually, I would probably make a macro and/or mod the reader
and add the autoquoting as in the original scsh, to be able to do
(the-schem-fun) | (grep abc) (tee debug.log)
So from my personal view I'm sort of very close to the goal.
But all of scsh have not been imported (yet) the reason is that I want to get
a core that is stable. you can easilly with a little misstake make guile and
actually the whole shell session go down. So, the core has to be worked on for
some time. I've just made it work I do not understand the codebase and tests
has to be made. I do not, personally, like the idea to incorporate all of scsh
in one go. I would divede the package into a base where the basic
functionality is in and that sit's closer to the guile core. Then as time goes
we can add the SRE regexps, and so on. to another package, further away.
Maybe I need to put in some more packages I don't now, but my sense tells me
that it it wise to startup small and solid in stead of fat and ugly :-).
Anyhow, I just checked in the current scsh in module/scsh in
http://gitorious.org/guile-unify if there is a package you would like thean
give me a hint.
A note, you need to quote a lot of things explicitly and there are bugs and
debug outputs - e.g. a bit premature, but I would like you to have a
possibility to express ideas, ok if none, great if some.
Actually I noticed that the codebase seem to be needing to include all
packages into the namespace before e.g. using defmacro's and then need to
have the symbols generated by the macro in the namespace. As small as it
sounds, the imporvemnet on this is soo great, I can now just ask for the
run macro from the (scsh syntax) package and it should work. This is far
better then all of scsh working in my book.
Your milage may vary, keep up the good work and a happy weekend to you.
/stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Guile-SCSH
2010-11-26 22:18 ` Stefan Israelsson Tampe
@ 2010-11-28 22:30 ` Ludovic Courtès
2010-11-28 23:02 ` Guile-SCSH Stefan Israelsson Tampe
0 siblings, 1 reply; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-28 22:30 UTC (permalink / raw)
To: guile-devel
Hi!
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> Anyhow, I just checked in the current scsh in module/scsh in
> http://gitorious.org/guile-unify if there is a package you would like thean
> give me a hint.
How about keeping it separate from your other work?
I noticed that Gary Houston’s Guile-SCSH page at
<http://arglist.com/guile/> vanished, but you might want to get in touch
with him...
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Guile-SCSH
2010-11-28 22:30 ` Guile-SCSH Ludovic Courtès
@ 2010-11-28 23:02 ` Stefan Israelsson Tampe
2010-11-28 23:24 ` Guile-SCSH Jose A. Ortega Ruiz
0 siblings, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-28 23:02 UTC (permalink / raw)
To: guile-devel
On Sunday, November 28, 2010 11:30:05 pm Ludovic Courtès wrote:
> Hi!
>
> Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
> > Anyhow, I just checked in the current scsh in module/scsh in
> > http://gitorious.org/guile-unify if there is a package you would like
> > thean give me a hint.
>
> How about keeping it separate from your other work?
Yea,
I think I understand your point.
I was a bit lazy and post it on the repo that I already had.
Hmm, the thing is that I do a small change in (system repl) due to
exit capturing, I do not want to clone the whole repo. SO untill that is
fixed in a good way I will keep it on the repo.
> I noticed that Gary Houston’s Guile-SCSH page at
> <http://arglist.com/guile/> vanished, but you might want to get in touch
> with him...
I will try.
> Thanks,
> Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Guile-SCSH
2010-11-28 23:02 ` Guile-SCSH Stefan Israelsson Tampe
@ 2010-11-28 23:24 ` Jose A. Ortega Ruiz
2010-11-29 18:56 ` Guile-SCSH Stefan Israelsson Tampe
2010-11-29 21:26 ` http://gitorious.org/guile-scsh/guile-scsh Stefan Israelsson Tampe
0 siblings, 2 replies; 33+ messages in thread
From: Jose A. Ortega Ruiz @ 2010-11-28 23:24 UTC (permalink / raw)
To: guile-devel
On Mon, Nov 29 2010, Stefan Israelsson Tampe wrote:
[...]
>> I noticed that Gary Houston’s Guile-SCSH page at
>> <http://arglist.com/guile/> vanished, but you might want to get in touch
>> with him...
>
> I will try.
I wrote him back in the day and he sent me a tar with guile-scsh source
code. Let me know if you'd like me to sent it to you, or if it'd be
better to post it here.
Cheers,
jao
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: Guile-SCSH
2010-11-28 23:24 ` Guile-SCSH Jose A. Ortega Ruiz
@ 2010-11-29 18:56 ` Stefan Israelsson Tampe
2010-11-29 21:26 ` http://gitorious.org/guile-scsh/guile-scsh Stefan Israelsson Tampe
1 sibling, 0 replies; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-29 18:56 UTC (permalink / raw)
To: guile-devel
Hi Jao,
You can send it to me, that's fine. I'll put a repo on gitorious and
add that code there together with my suggested alternatives.
Regards
Stefan
On Monday, November 29, 2010 12:24:28 am Jose A. Ortega Ruiz wrote:
> On Mon, Nov 29 2010, Stefan Israelsson Tampe wrote:
>
> [...]
>
> >> I noticed that Gary Houston’s Guile-SCSH page at
> >> <http://arglist.com/guile/> vanished, but you might want to get in touch
> >> with him...
> >
> > I will try.
>
> I wrote him back in the day and he sent me a tar with guile-scsh source
> code. Let me know if you'd like me to sent it to you, or if it'd be
> better to post it here.
>
> Cheers,
> jao
^ permalink raw reply [flat|nested] 33+ messages in thread
* http://gitorious.org/guile-scsh/guile-scsh
2010-11-28 23:24 ` Guile-SCSH Jose A. Ortega Ruiz
2010-11-29 18:56 ` Guile-SCSH Stefan Israelsson Tampe
@ 2010-11-29 21:26 ` Stefan Israelsson Tampe
2010-11-30 23:21 ` Guile-Facade Ludovic Courtès
1 sibling, 1 reply; 33+ messages in thread
From: Stefan Israelsson Tampe @ 2010-11-29 21:26 UTC (permalink / raw)
To: guile-devel
Ok I put the code in a repo of it's own.
So now this thingie is isolated.
I don't now what to do about the licesning, I kept
the COPYING as I should though.
To use it, store it in a %load-path directory
try
(use-modules (scsh syntax))
and then
(run (| (begin (pk 'wow) (pk 'vov)) (grep o)))
So, a slight improvement on system :-)
should behave acording to spec.
Have fun
Stefan
^ permalink raw reply [flat|nested] 33+ messages in thread
* Guile-Facade
2010-11-29 21:26 ` http://gitorious.org/guile-scsh/guile-scsh Stefan Israelsson Tampe
@ 2010-11-30 23:21 ` Ludovic Courtès
0 siblings, 0 replies; 33+ messages in thread
From: Ludovic Courtès @ 2010-11-30 23:21 UTC (permalink / raw)
To: guile-devel
Hi!
Thanks for setting up the repo!
I also realized that Clinton once mentioned Guile-Facade on IRC, which
is a Guile-SCSH revival, AIUI:
http://unknownlamer.org/darcsweb/browse?r=guile-facade;a=summary
Perhaps he can comment. :-)
Ludo’.
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2010-11-30 23:21 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-21 20:23 The progress of hacking guile and prolog Stefan Israelsson Tampe
2010-11-03 23:43 ` Ludovic Courtès
2010-11-04 2:40 ` Noah Lavine
2010-11-10 17:55 ` Stefan Israelsson Tampe
2010-11-11 19:10 ` Noah Lavine
2010-11-11 16:26 ` Ludovic Courtès
2010-11-11 19:13 ` Noah Lavine
2010-11-11 19:15 ` Noah Lavine
2010-11-15 23:10 ` Typechecking I Stefan Israelsson Tampe
2010-11-20 11:46 ` Andy Wingo
2010-11-20 11:25 ` The progress of hacking guile and prolog Andy Wingo
2010-11-24 1:54 ` Noah Lavine
2010-11-24 16:45 ` Stefan Israelsson Tampe
2010-11-24 18:00 ` piper schemigan Stefan Israelsson Tampe
2010-11-24 20:18 ` Andreas Rottmann
2010-11-25 21:17 ` Ludovic Courtès
2010-11-26 22:18 ` Stefan Israelsson Tampe
2010-11-28 22:30 ` Guile-SCSH Ludovic Courtès
2010-11-28 23:02 ` Guile-SCSH Stefan Israelsson Tampe
2010-11-28 23:24 ` Guile-SCSH Jose A. Ortega Ruiz
2010-11-29 18:56 ` Guile-SCSH Stefan Israelsson Tampe
2010-11-29 21:26 ` http://gitorious.org/guile-scsh/guile-scsh Stefan Israelsson Tampe
2010-11-30 23:21 ` Guile-Facade Ludovic Courtès
2010-11-25 21:26 ` The progress of hacking guile and prolog Ludovic Courtès
2010-11-26 16:41 ` Noah Lavine
2010-11-26 10:45 ` Andy Wingo
2010-11-20 11:26 ` Andy Wingo
2010-11-04 17:57 ` Stefan Israelsson Tampe
2010-11-05 21:19 ` Stefan Israelsson Tampe
2010-11-19 23:11 ` GLIL->C compilation Ludovic Courtès
2010-11-19 23:20 ` Stefan Israelsson Tampe
2010-11-19 23:56 ` Ludovic Courtès
2010-11-20 12:18 ` Andy Wingo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).