An example of such a meta-circular Prolog interpreter is:
mi([]).
mi([G0|Gs0]) :-
clause(G0, Rs, Gs0),
mi(Rs).
It can interpret pure Prolog code, a Turing-complete subset of first-order predicate logic. For example, given the following clauses: clause(natnum(0), Rs, Rs).
clause(natnum(s(X)), [natnum(X)|Rs], Rs).
It yields: ?- mi([natnum(X)]).
X = 0
; X = s(0)
; X = s(s(0))
; X = s(s(s(0)))
; X = s(s(s(s(0))))
; ... .
The meta-interpreter's own code can also be represented in this way: clause(mi([]), Rs, Rs).
clause(mi([G0|Gs0]), [clause(G0,Rs,Gs0),mi(Rs)|Ls], Ls).
clause(clause(Head, Rs0, Rs), Ls, Ls) :- clause(Head, Rs0, Rs).
And now it can interpret its own source code, interpreting any given program, arbitrarily deeply nested. For example: ?- mi([mi([mi([natnum(X)])])]).
X = 0
; X = s(0)
; X = s(s(0))
; X = s(s(s(0)))
; ... .
Tested with Scryer Prolog.*I'm not at all comfortable with Tromp's abandoning SK for lambda calculus in his search for a principled choice of UTM for Algorithmic Information Theory. His justification seems to be that lambda is "more expressive" than sk, but that begs the question: To express _what_?
Yann LeCun responded: "I can construct a computer for which the shortest program that generates this bit string has length 1."
To which I posed this question: "Why do mathematicians spend centuries asking for their minimum set of axioms but, not even Wolfram's acolytes ask for the shortest meta-circular description of a universal computational structure?"