# Joy in Prolog (again)

## Martin Young — 2000-08-08 17:16:16

    Folks,

    As promised (threatened) my implementation of Joy (in Prolog) is on the web

    here:

    http://www.endotether.clara.net/martin/joy

    Enjoy.

    --

    Martin Young  working for  STMicroelectronics at     `(o)_(o)' The fat wise /

    1000 Aztec West, Almondsbury, Bristol, BS32 4SQ.      (  V  ) owl eats only >

    +44 1454 462 523    `v'      Martin.Young@...      `.___,' clean mice.  /

                       _(_)_                             -="==="=============='

## phimvt@lurac.latrobe.edu.au — 2000-08-24 08:46:52

    PicoJoy-in-Prolog

    Martin Young in his message 9-AUG-2000 supplied a pointer,

            http://www.endotether.clara.net/martin/joy

    to his page on a version of Joy-in-Prolog. I have not yet had

    the time to study it in depth, but it reminded me to dig out

    an antique version of my own. It does not have a proper scanner

    and lexer in the way Martin's has, and consequently it is

    rather awful to use (see the short doc inside). I do have

    a better scanner and parser which a friend wrote for me, and they

    allow Joy lists to be written without the irritating commas in

    Prolog lists. So they are a definite improvement, but

    still do not quite live up to the "offical" Joy syntax. Moreover,

    they are rather long, longer than this cut-down version, and so

    I did not include them. I'll send them out if anyone wants them,

    but as I said, Martin's solution to the syntax problem is probably

    better.

       I call this thing  PicoJoy  because it is a cut-down version

    of what I used to call  MicroJoy . Any experienced Prolog writer

    should have no problem extending it. I hope Martin and perhaps

    others can make use of it. It runs under MU-Prolog (from Melbourne

    University), and probably under any other standard Prolog.

        Manfred

    /* file: picojoy.pl                  A tiniest Joy-in-Prolog */

    /* Run Prolog, then  "consult('picojoy.pl')."  this file.

       To enter the picojoy loop, type  "picojoy."  .

       After the prompt, enter Joy programs

        1)  items separated by commas

        2)  program inside square bracket

        3)  program terminated by a period.

       All this is inconvenient; it is necessary because picojoy

       simply uses the prolog read/1 and write/1.

       Two Examples:   [3, 5, +].    [ [2,3,4], [dup,+], map ].

       or Definition:     [ foo, ==, bar, baz, zonk ].

       Output is the whole stack.

       To exit the loop, after the prompt type  stop. (no brackets).

       Now you are back in prolog. Typically  end.  or  EOF  exits.

    */

    					/* "outer interpreter" */

    picojoy :-

    	write('picojoy version 00.00') ,

    	repeat,

    	nl,

    	write('j: ') ,

    	read(P) ,

    	(	P == stop, !

    	;

    		P = [ HEAD,(==)|BODY ],

    		asserta((

    		    exe(HEAD,(X,Y)) :-

    			 exelist(BODY,(X,Y)) )),

    		fail

    	;

    		exelist(P , ([], Y)) ,

    		write(Y),

    		fail

    	) .

    					/* "inner interpreter" */

    exelist([] , (X, X)) .

    exelist(R1.R , (X, Z)) :-

    	exe(R1 , (X, Y)) ,

    	exelist(R , (Y, Z)) .

    					/* literals */

    exe(true , (S, true.S)) .

    exe(false , (S, false.S)) .

    exe([] , (S, [].S)) .

    exe(L1.L , (S, (L1.L).S)) .

    exe(I , (S, I.S)) :-

    	integer(I) .

    					/* operators */

    exe(stack , (S, S.S)) .

    exe(unstack , (L.S, L)) .

    exe(pop , (S1.S, S)) .

    exe(dup , (S1.S, S1.S1.S)) .

    exe(swap , (S1.S2.S, S2.S1.S)) .

    exe(cons , (L.L1.S, (L1.L).S)) .

    exe(null , ([].S, true.S)) :-

    	! .

    exe(null , (X.S, false.S)) .

    exe(uncons , ((L1.L).S, L.L1.S)) .

    exe(unit , (S1.S, (S1.[]).S)) .

    exe(pair , (S1.S2.S, (S2.S1.[]).S)) .

    exe(unpair , ((L1.L2.L).S, L2.L1.S)) .

    exe(concat , (L.[].S, L.S)) .

    exe(concat , (L.(M1.M).S, (M1.N).S)) :-

    	exe(concat , (L.M.S, N.S)) .

    exe(shunt , (L.[].S, L.S)) .

    exe(shunt , (L.(M1.M).S, N.S)) :-

    	exe(shunt , ((M1.L).M.S, N.S)) .

    exe(reverse , (L.S, M.S)) :-

    	exe(shunt , ([].L.S, M.S)) .

    exe(size , ([].S, 0.S)) .

    exe(size , ((L1.L).S, N.S)) :-

    	exe(size , (L.S, N1.S)) ,

    	N is N1 + 1 .

    exe(+ , (X.Y.S, Z.S)) :-

    	Z is Y + X .

    exe(= , (X.Y.S, true.S)) :-

    	Y = X .

    exe(= , (X.Y.S, false.S)) :-

    	not (Y = X) .

    exe(< , (X.Y.S, true.S)) :-

    	Y < X .

    exe(< , (X.Y.S, false.S)) :-

    	not (Y < X) .

    exe(first , ((L1.L).S, L1.S)) .

    exe(second , ((L1.L2.L).S, L2.S)) .

    exe(rest , ((L1.L).S, L.S)) .

    					/* combinators */

    exe(i , (P.S, T)) :-

    	exelist(P , (S, T)) .

    exe(dip , (P.S1.S, S1.T)) :-

    	exelist(P , (S, T)) .

    exe(nullary , (P.S, X.S)) :-

    	exelist(P , (S, X.T)) .

    exe(map , (P.[].S, [].S)) .

    exe(map , (P.(L1.L).S, (M1.M).S)) :-

    	exelist(P , (L1.S, M1.T)) ,

    	exe(map , (P.L.S, M.U)) .

    exe(step , (P.[].S, S)) .

    exe(step , (P.(L1.L).S, U)) :-

    	exelist(P , (L1.S, T)) ,

    	exe(step , (P.L.T, U)) .

    exe(sieve , (TEST.[].S, [].[].S)) .

    exe(sieve , (TEST.(L1.L).S, N.(L1.M).S)) :-

    	exelist(TEST , (L1.S, true.T)) ,

    	!,

    	exe(sieve , (TEST.L.S, N.M.S)) .

    exe(sieve , (TEST.(L1.L).S, (L1.N).M.S)) :-

    	exe(sieve , (TEST.L.S, N.M.S)) .

    exe(filter , (TEST.[].S, [].S)) .

    exe(filter , (TEST.(L1.L).S, (L1.M).S)) :-

    	exelist(TEST , (L1.S, true.T)) ,

    	!,

    	exe(filter , (TEST.L.S, M.S)) .

    exe(filter , (TEST.(L1.L).S, M.S)) :-

    	exe(filter , (TEST.L.S, M.S)) .

    exe(infra , (P.L.S, M.S)) :-

    	exelist(P , (L, M)) .

    exe(ifte , (ELSEPART.THENPART.IFPART.S, T)) :-

    	exelist(IFPART , (S, true.U)) ,

    	!,

    	exelist(THENPART , (S, T)) .

    exe(ifte , (ELSEPART.THENPART.IFPART.S, T)) :-

    	exelist(ELSEPART , (S, T)) .

    exe(linrec , (REC2.REC1.EXIT.IF.S, T)) :-

    	exelist(IF , (S, true.U)) ,

    	!,

    	exelist(EXIT , (S, T)) .

    exe(linrec , (REC2.REC1.EXIT.IF.S, T)) :-

    	exelist(REC1 , (S, U)) ,

    	exe(linrec , (REC2.REC1.EXIT.IF.U, V)) ,

    	exelist(REC2 , (V, T)) .

    exe(listing, (S,S)) :- listing.

    /* end of file picojoy.pl */