# ----------------
# Meta-interpreter
# ----------------
#
# Inspired by https://www.metalevel.at/acomip/

@prefix list: <http://www.w3.org/2000/10/swap/list#>.
@prefix log: <http://www.w3.org/2000/10/swap/log#>.
@prefix var: <http://www.w3.org/2000/10/swap/var#>.
@prefix : <http://example.org/#>.

# meta-interpreter rules
[ log:graph (
    [ log:triple (() :mi ())]
)] log:isImpliedBy true.

[ log:graph (
    [ log:triple (() :mi var:A)]
)] log:isImpliedBy  [ log:graph (
    [ log:triple (var:A list:firstRest (var:G var:Gs))]
    [ log:triple (() :headBody (var:G var:Goals var:Gs))]
    [ log:triple (() :mi var:Goals)]
)].

# general head-body rules
[ log:graph (
    [ log:triple (() :headBody ([ log:graph (
        [ log:triple (() :mi ())]
    )] var:Rs var:Rs))]
)] log:isImpliedBy true.

[ log:graph (
    [ log:triple (() :headBody ([ log:graph (
        [ log:triple (() :mi var:A)]
    )] var:B var:Rs))]
)] log:isImpliedBy [ log:graph (
    [ log:triple (var:A list:firstRest (var:G var:Gs))]
    [ log:triple (var:B list:firstRest ([ log:graph (
        [ log:triple (() :headBody (var:G var:Goals var:Gs))]
    )] var:C))]
    [ log:triple (var:C list:firstRest ([ log:graph (
        [ log:triple (() :mi var:Goals)]
    )] var:Rs))]
)].

[ log:graph (
    [ log:triple (() :headBody ([ log:graph (
        [ log:triple (() :headBody (var:Head var:Goals0 var:Goals))]
    )] var:Rs var:Rs))]
)] log:isImpliedBy [ log:graph (
    [ log:triple (() :headBody (var:Head var:Goals0 var:Goals))]
)].

# natnum head-body rules
[ log:graph (
    [ log:triple (() :headBody ([ log:graph (
        [ log:triple (() :natnum (0))]
    )] var:Rs var:Rs))]
)] log:isImpliedBy true.

[ log:graph (
    [ log:triple (() :headBody ([ log:graph (
        [ log:triple (() :natnum (:s var:X))]
    )] var:A var:Rs))]
)] log:isImpliedBy [ log:graph (
    [ log:triple (var:A list:firstRest ([ log:graph (
        [ log:triple (() :natnum var:X)]
    )] var:Rs))]
)].

# query
[ log:graph (
    [ log:triple (() :mi ([ log:graph (
        [ log:triple (() :mi ([ log:graph (
            [ log:triple (() :mi ([ log:graph (
                [ log:triple (() :natnum (:s (:s (:s (:s (:s (0)))))))]
            )]))]
        )]))]
    )]))]
)] log:impliesAnswer [ log:graph (
    [ log:triple (() :natnum (:s (:s (:s (:s (:s (0)))))))]
)].
