Commit Graph

58 Commits

Author SHA1 Message Date
Simon Forman 6888c71b69 blep. 2020-01-28 10:37:13 -08:00
Simon Forman 5b6bd42ebe A start on machine code generation.
Just the initial messing around...
2020-01-28 10:21:37 -08:00
Simon Forman b323402c9b Fix a bug in step.
You think it would be easy to find all the places where the type tags are needed.
2020-01-27 12:56:26 -08:00
Simon Forman 6e8151a0b2 docs, formatter 2020-01-27 11:54:24 -08:00
Simon Forman 714aa59c43 Fix a bug in rest.
It didn't tag the tail list as a list.

Also, spell out bool for true cases.
2020-01-26 17:06:21 -08:00
Simon Forman ab0a378b56 Minor cleanup.
I feel like I should keep the un-partially-reduced thun/4 but
you can still read it, and the reduced forms are more efficient.
(And not too much more wordy.)
2020-01-26 16:50:49 -08:00
Simon Forman 76de590d27 Experiments with partial reduction are very promising.
Functions become clauses like these:

    thun(symbol(rolldown), [], [C, A, B|D], [A, B, C|D]).
    thun(symbol(rolldown), [A|B], [E, C, D|F], G) :-
        thun(A, B, [C, D, E|F], G).
    thun(symbol(dupd), [], [A, B|C], [A, B, B|C]).
    thun(symbol(dupd), [A|B], [C, D|E], F) :-
        thun(A, B, [C, D, D|E], F).
    thun(symbol(over), [], [B, A|C], [A, B, A|C]).7
    thun(symbol(over), [A|B], [D, C|E], F) :-
        thun(A, B, [C, D, C|E], F).


Definitions become

    thun(symbol(of), A, D, E) :-
        append([symbol(swap), symbol(at)], A, [B|C]),
        thun(B, C, D, E).
    thun(symbol(pam), A, D, E) :-
        append([list([symbol(i)]), symbol(map)], A, [B|C]),
        thun(B, C, D, E).
    thun(symbol(popd), A, D, E) :-
        append([list([symbol(pop)]), symbol(dip)], A, [B|C]),
        thun(B, C, D, E).


These are tail-recursive and allow for better indexing so I would expect
them to be more efficient than the originals.

Notice the difference between the original thun/4 rule for definitions
and this other one that actually works.

    thun(symbol(Def),   E, Si, So) :- def(Def, Body), append(Body, E,    E o),    thun(Eo, Si, So).
    thun(symbol(Def),   E, Si, So) :- def(Def, Body), append(Body, E, [T|Eo]), thun(T, Eo, Si, So)


The latter reduces to:

    thun(symbol(A), C, F, G) :-
        def(A, B),
        append(B, C, [D|E]),
        thun(D, E, F, G).


We want something like...

    thun(symbol(B), [], A, D) :- def(B, [H|C]), thun(H, C, A, D).
    thun(symbol(A), [H|E0], Si, So) :-
        def(A, [DH|DE]),
        append(DE, [H|E0], E),
        thun(DH, E, Si, So).

But it's good enough.  The earlier version doesn't transform into
correct code:

    thun(symbol(B), D, A, A) :- def(B, C), append(C, D, []).
    thun(symbol(A), C, F, G) :- def(A, B), append(B, C, [D|E]), thun(D, E, F, G).

It would probably be good to investigate what goes wrong there.)

It doesn't seem to work right for thun/4 combinator rules either.  Dunno what's
up there.
2020-01-26 13:21:47 -08:00
Simon Forman ef6d271c85 Partial reduction of thun/3 in the thun/4 relation.
It mostly works.
2020-01-26 12:48:38 -08:00
Simon Forman 0af0fb7e8e Map combinator works with types. 2020-01-26 10:15:32 -08:00
Simon Forman e0a36eab8b Remove '==' from definitions. (Bools)
I decided that the conceptual simplicity of omitting '==' is more useful
than the cosmetic value of keeping it.  The defs.txt file is now just one
definition per line with the first symbol giving the name.

Also, bools are literals.
2020-01-26 09:48:30 -08:00
Simon Forman 2aa1765b89 Proper types, checking, inference.
When I first translated Joy into Prolog I was so blown away by the Prolog
unification over list structures and Triska's CLP(FD) semantics for math
(both in the sense that he wrote CLP(FD) for SWI Prolog and he suggested
it for Joy-in-Prolog specifically) that I didn't realize that it wasn't
quite type inference.

It's kind of like type inference, in that lists are handled correctly and
the CLP(FD) library creates and maintains a kind of context for
constraints, which are sort-of like "dependent types" if you squint a
little.  But you can still do things like 'cons' a number to a number and
get (a Prolog term) like [2|3] which is almost certainly a bug.

So I went through and added type "tags" as Prolog terms: int/1, list/1,
and symbol/1.  The parser assigns them and all the primitive functions
and combinators use them (and so all the definitions do too.)  With this
information Prolog can e.g. prevent attempts to add numbers and lists, and
so on.

This also allows for the thun/3 relation to be implemented a little more
efficiently (without much loss of beauty) by looking ahead one term in
the pending expression and dispatching on structural "type" in a thun/4
relation.  I miss the elegance of the previous version, but this lets
Prolog index on the structural type tags that the parser produces.

(This might mess up tail recursion because now we have a loop between
thun/3 and thun/4 but we can eliminate that problem by partial reduction
on thun/3.  TODO.)

Now that literals are tagged by the parser there's no need for literal/1.
2020-01-26 08:43:52 -08:00
Simon Forman 6e6e52d206 Don't assert defs twice.
Each definition is getting parsed with the name of the next one as part
of its body, then the next one fails to parse and the thing backtracks.
So each definition (but the last) gets asserted twice.

    def(--,[1,-,?])
    def(--,[1,-])
    def(?,[dup,bool,++])
    def(?,[dup,bool])
    def(++,[1,+,anamorphism])
    def(++,[1,+])
    def(anamorphism,[[pop,[]],swap,[dip,swons],genrec,app1])
    def(anamorphism,[[pop,[]],swap,[dip,swons],genrec])
    def(app1,[grba,infrst,app2])
    def(app1,[grba,infrst])
    def(app2,[[grba,swap,grba,swap],dip,[infrst],cons,ii,app3])
    def(app2,[[grba,swap,grba,swap],dip,[infrst],cons,ii])

...and so on.
2020-01-25 16:13:06 -08:00
Simon Forman 1ecb5be278 Change back to CLP(FD) semantics.
Minor changes to parser to make it less logical but a little firmer.
(E.g. ints can't be backtracked into becoming symbols!)
2020-01-25 15:50:50 -08:00
Simon Forman 36ec93e46b Docs and minor cleanup to the grammar. 2020-01-25 14:35:44 -08:00
Simon Forman 3751107a09 Modify error reporting a lil; words word. 2019-11-07 07:54:04 -08:00
Simon Forman aae0e91c44 assert_defs/1 got upset about not finding combo/5 2019-08-12 21:08:17 -07:00
Simon Forman 10a23c5c68 Also don't shadow combinators.
(I realized that the way defs are parsed now means that each def
(but the last) is first asserted with the wrong definition expression
(it includes the symbol of the following definition at the end) and
then the parser figures out that there's another defintion following
and re-asserts the correct expression.  It would be nice to fix that
but it's kind of a PITA.  I used to build a list of definitions and
then assert them all at the end.  For now there aren't enough defs to
justify the extra work.
2019-08-09 16:58:34 -07:00
Simon Forman cbf2af18e5 Prevent definitions from shadowing functions. 2019-08-09 16:53:40 -07:00
Simon Forman 49491bceef Demo grow/shrink. 2019-08-09 16:37:33 -07:00
Simon Forman b9ae00cecb A few more functions.
reverse, shift, shunt, take, split_at
2019-08-09 07:26:37 -07:00
Simon Forman 712f0a0267 merge 2019-08-07 23:36:38 -07:00
Simon Forman 976b8302be grow/shrink as DCGs. 2019-08-07 23:28:28 -07:00
Simon Forman 4ea77cf1be Integer DCGs that work in both directions. 2019-08-07 11:40:49 -07:00
Simon Forman 0048ee212d loop combinator handles ambiguity.
remove some old notes.
2019-08-04 09:28:01 -07:00
Simon Forman 3b1a89d1c4 Minor refactor.
crbo/4 to to_fixed_point/3
2019-08-03 19:01:00 -07:00
Simon Forman cb0078f3bc Gnarly fun with metaprogramming. 2019-08-03 17:56:25 -07:00
Simon Forman 2ba9242b76 Comparisions are literals too.
Also a bunch of reformatting.

Maybe I can modify the term_expansion/2 to also write the literal/1 clauses for math and comps?
2019-07-22 10:25:34 -07:00
Simon Forman df94c8feed Minor cleanup. 2019-07-21 18:48:11 -07:00
Simon Forman c1442945a6 Assert definitions as they are read.
Instead of building a list then asserting them all after parsing.
2019-07-21 14:13:48 -07:00
Simon Forman 32d5953f29 Implement map combinator. 2019-07-21 08:28:56 -07:00
Simon Forman 1b5d1c0b82 Remove cuts from branch combinator. 2019-07-20 19:34:56 -07:00
Simon Forman 206f49598e Add mod, gcd, and hypot; term_expansion for math ops. 2019-07-20 19:26:11 -07:00
Simon Forman ae769d2341 Fold try_both_branches/4 into branch combo. 2019-07-20 17:36:58 -07:00
Simon Forman 230288c02c Replace ? with plain ol' def/2.
As much fun as it was using ? as an operator, now that all the defs live in a text file you don't see it in the Prolog code anymore.

This way I get to use sweet sweet ASCII (except for the ? symbol in the copyright notice.)
2019-07-20 17:32:03 -07:00
Simon Forman 7354911d05 WTF error handler.
Made it check that the unknown term really isn't a literal, definition, function, or combinator.
2019-07-20 17:19:35 -07:00
Simon Forman 2a66e7fb47 If I comment out the WTF handler...
...then the branch combinator works as intended.  (Although the constraint-based stuff was also cool, it would have captured information from the comparison.)


?- joy(`[32 >] [++] [--] ifte`, Si, So).
Si = [_6598|_6600],
So = [_6598+1|_6600] ;
Si = [_6598|_6600],
So = [_6598-1|_6600] ;
false.

?- sjc(hmm, `[32 >] [++] [--] ifte`).
func(hmm, [A|B], [A+1|B]).
true ;
func(hmm, [A|B], [A-1|B]).
true ;
false.
2019-07-20 16:57:19 -07:00
Simon Forman 714bf2cab6 Try to handle expressions in branch combinator.
If the expression isn't 'true' or 'false' atoms then we assume it's a comparison expression and try to check its truth value.

If this fails then it will try both branches, to allow for e.g. compilation.  THis almost works, but there's a choice point or something that gets hit before it tries the false path,

?- joy(` [32 >] [++] [--] ifte`, Si, So).
Si = [_2076|_2078],
So = [_2076+1|_2078] ;
wtf? +
Si = [_2076|_2078],
So = [[+], 1, _2076|_2078] ;
Si = [_2076|_2078],
So = [_2076-1|_2078] ;
wtf? -
Si = [_2076|_2078],
So = [[-], 1, _2076|_2078] ;
wtf? branch
Si = [_2076|_2078],
So = [[branch], [++], [--], _2076>32, _2076|_2078] ;
wtf? swap
Si = [_2076|_2078],
So = [[swap, branch], [--], [++], _2076>32, _2076|_2078] ;
wtf? first
Si = [_2076|_2078],
So = [[first, [++], [--], swap, branch], [_2076>32|_2078], _2076|_2078]


etc...
2019-07-20 16:45:28 -07:00
Simon Forman c676dce2f9 Handle exceptions in comparison ops.
You can't compare logic vars, so just bunt.
2019-07-20 16:38:48 -07:00
Simon Forman 47ae7b2328 More readable genrec.
Explicit quoting is slightly more overhead but worth it I think to show what's going on more clearly.
2019-07-16 09:53:48 -07:00
Simon Forman efeaa7b8e1 A little helper function to see compiled expressions.
Example from ordered binary tree notebook:

    ?- sjc(tree_add_Ee, `pop swap rolldown rrest ccons`).
    func(tree_add_Ee, [_, [_, _|C], A, B|D], [[A, B|C]|D]).
    true .
2019-07-16 09:46:55 -07:00
Simon Forman 6d92b8801f Clear out CLP(FD) functions.
I like them but then you are constrained (pun intended) to only using integers.  I'll probably bring them back at some point, either as an alternate implementation or their own commands.
2019-07-16 08:59:24 -07:00
Simon Forman 731b49973c Opps! Here's the implementation of bool. 2019-07-16 08:42:45 -07:00
Simon Forman 06b81914eb Change comparison ops to not use CLP(FD). 2019-07-15 23:02:08 -07:00
Simon Forman 84584a949c Implement genrec combinator. 2019-07-15 20:55:41 -07:00
Simon Forman 9ebc64541a Move all definitions to defs.txt. 2019-07-15 16:11:49 -07:00
Simon Forman ee395e91f1 Retract previous definitions before asserting new ones. 2019-07-15 16:01:59 -07:00
Simon Forman 4fefc04da3 Load definitions from a file.
This paves the way to regularize the defs between Python and Prolog (and and future other) implementations.
2019-07-15 15:53:07 -07:00
Simon Forman 087c141c72 Parse joy definitions from text.
This way a definitions file can be shared between Python Joy and Prolog Joy.
2019-07-15 12:53:48 -07:00
Simon Forman 166355dccf New combinator infrst == infra first
Three uses means it's time for a refactor.
2019-07-15 12:28:01 -07:00
Simon Forman 4ea1a5527e nullary combinator as definition.
That eliminates all the recursive calls to thun/3 (outside of thun itself, which is tail recursive.)  That means that this Joy interpreter is now fully CPS.

All state is contained in the stack and expression, nothing is hidden in the Prolog "call stack".
2019-07-15 11:20:13 -07:00