Hi Tim,
Your Joy implementation looks really interesting.
One thing I'd suggest trying out is implementing as much of the Joy
library as possible in Joy itself. Then you'd have a .joy file that
you would load in a top-level form. Also a set of unit tests would be
nice, to ensure that everything works. I'd like to incorporate your
code into extra/ eventually, because it touches a lot of things --
quotation generation, PEGs, data strctures, and so on -- if it has a
good test suite, having the tests run every time a Factor binary is
built and tested would help weed out bugs in the VM and Factor
compiler.
You'll find that Joy has some design decisions which really limit how
much the implementation can compile ahead of time. There are two
problems for implementors: lists and quotations are the same in Joy,
and unless you use linked lists as the data structure for both Joy
quotations and the Joy stack, your implementation will have bad
algorithmic complexity for certain operations that are cheap in the
real C Joy. Even if you don't care about the 'infra' combinator being
efficient, then you'll still have to use a list for the data stack
eventually, since not all Joy code has statically inferrable stack
effects.
So first of all, instead of compiling Joy lists to Factor quotations
ahead of time, you could use a hybrid representation where a Joy list
is just a real, single-linked list, but the first time it gets called
as a Joy quotation, the list is compiled into a Factor quotation which
is then cached somewhere in case this list instance gets called again.
The simplest approach to doing that would be to define a custom 'cons'
type which has *three* slots:
TUPLE: joy-cons { car read-only } { cdr read-only } compiled-quot ;
: joy-cons ( car cdr -- cons ) f \ joy-cons boa ;
When you call a Joy quotation, you check if its had its quot computed,
and if not, you compile it "just in time". Since most lists don't get
called, and are just used as data, you won't be calling the compiler
most of the time, and the space usage of an extra slot that's almost
always f isn't a big deal here.
However one caveat is that you can no longer pass Joy quotations to
Factor combinators directly; instead, you have wrap them with '[ _
joy-call ].
Secondly, I see you compile Joy's ifte as Factor's ifte 'smart
combinator', but that's not exactly the thing, because Joy permits
code like [1] [2] [3 4] ifte. If you want to support the general case,
you'll need to switch to using lists for the Joy data stack, too. This
will also give you an efficient implementation of Joy's 'infra'
combinator (Factor's with-datastack is semantically equivalent but its
not O(1)).
When the Joy data stack is a list, each compiled Joy quotation then
takes one input and produce one output on the Factor side. Joy stack
shuffling would become tuple slot access and tuple construction.
'ifte' would really save/restore the stack at runtime. Once you do
this, all the same tricks that work in real Joy would work in Factor
Joy.
Of course it would introduce a lot of overhead, but really that's the
core issue here, Joy's semantics are such that switching the datastack
must be very cheap, but this has to be done at the expense of
everything else.
These two changes would make your implementation a lot more complex,
in return for getting that last 20% of Joy to work correctly and
efficiently. If you actually implement all that, it would be great. If
not, having a clean and simple compiler for the sane subset of Joy you
have right now is good too. All the large enterprise Joy applications
in the real-world have static stack effects mostly anyway. ;-)
Slava
On Wed, Aug 19, 2009 at 1:26 AM, Tim Wawrzynczak<[email protected]> wrote:
> Hi list,
>
> I would post this to concatenative, but my membership there has been pending
> for over a month...
>
> As some of you know, I've been working on a Joy -> Factor compiler and
> interpreter, and I have
> successfully gotten the compiler to compile Manfred's lazy lists library.
> I'm working on getting
> all his provided Joy library files to work correctly, and then maybe I'll
> release it or something.
>
> The source is at: http://github.com/inforichland/Joy/tree/master
>
> An example session:
>
> ( scratchpad ) USING: joy.compiler joy.parser io.encodings.utf8 io.files ;
> ( scratchpad ) "lazlib.joy" ascii file-contents
> Data Stack: ...
> ( scratchpad ) parse-joy compile call
>
> This will produce a Factor quotation (as well as have defined all the words
> defined in that file), so you want to 'call' (note above) the quotation.
> If you want to run code using previously used DEFINEs, then call "Squares 15
> Take" parse-joy @compile call (for example).
>
> Feel free to try it out !
>
> The "interpreter" is also kinda working, but has fewer words builtin than
> the compiler.
>
> If you have any comments or question, feel free to let me know; I'm also
> inforichland on #concatenative
>
> Cheers,
> - Tim
>
> PS Slava, when you think it's ready enough, I'll add it to my /extra factor
> tree @ github, and let you know so you can put it in the main repo.
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
> trial. Simplify your report design, integration and deployment - and focus
> on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july
> _______________________________________________
> Factor-talk mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/factor-talk
>
>
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Factor-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/factor-talk