“That's a very interesting topic and nice write-up, thank you for sharing!” (comment)
recommended by 2 users | 2019 | triska on: The Meta-Circular Evaluator (2016) | compilers | original thread |
triska on Mar 3, 2019 | on: The Meta-Circular Evaluator (2016) | view on HN

That's a very interesting topic and nice write-up, thank you for sharing!

For comparison, here is a small interpreter for a subset of Prolog, written in Prolog:

    mi([]).
    mi([G|Gs]) :-
            clause_(G, Body),
            mi(Body),
            mi(Gs).

This states that: First, the empty conjunction (of goals) is true, and second, if there is at least one goal left, than the conjunction is true if there is a suitable clause whose body evaluates to true, and the same holds for all remaining goals.

For example, we can define append/3 as follows in this representation:

    clause_(append([], Ys, Ys), []).
    clause_(append([X|Xs], Ys, [X|Zs]), [append(Xs,Ys,Zs)]).

and then evaluate it with our interpreter:

    ?- mi([append([a,b,c], [d,e], Ls)]).
    Ls = [a, b, c, d, e].

Characteristically, it also works in other directions. For example:

    ?- mi([append([a,b,c], Rs, [a,b,c,d,e])]).
    Rs = [d, e].

and also:

    ?- mi([append(As, Bs, [x,y])]).
    As = [],
    Bs = [x, y] ;
    As = [x],
    Bs = [y] ;
    As = [x, y],
    Bs = [] ;
    false.

Now the point: The clauses of the meta-interpreter itself can also be stated in this form, namely as:

    clause_(mi([]), []).
    clause_(mi([G|Gs]), [clause_(G,Body),mi(Body),mi(Gs)]).

Now we only have to define what clause_/2 means, which we can do with:

    clause_(clause_(G, Body), []) :- clause_(G, Body).

And now we can use our meta-interpreter to evaluate its own code as it interprets a program, arbitrarily deeply layered:

   ?- mi([mi([mi([append([a,b,c],[d,e],Ls)])])]).
   Ls = [a, b, c, d, e].

Hence, Prolog admits a meta-circular evaluator in at most 5 lines of code. With a better representation for clauses (using list differences), you can reduce the interpreter to 4 lines of code and at the same time make it tail-recursive.

2 users recommended this comment. What they said:
sevensor Apr 22, 2019 | on: Ask HN: What Hacker News comments have you bookmarked? | context

https://news.ycombinator.com/item?id=19294191 : A meta-circular evaluator in Prolog. (User triska's comment history is full of gems.)

https://news.ycombinator.com/item?id=17020655 : A question I had asked about interfacing Excel, which provoked some useful responses. I now use this as my authoritative list of ways to extend Excel's functionality.

https://news.ycombinator.com/item?id=18314265 : Fascinating comment about, well, all kinds of stuff, but mainly PostScript. (DonHopkins. Another user whose comment history is a seam of gold.)

https://news.ycombinator.com/item?id=16014573 : Great post about the history of terminals and terminal emulators. (JdeBP)

https://news.ycombinator.com/item?id=15027372 : Introduction to the market for produce by the produce buyer for a small grocery. (LightRailTycoon)

Tomte Apr 14, 2021 | on: Ask HN: What are some of your favourite comments on Hacker… | context