- 130 Views
- Uploaded on
- Presentation posted in: General

Meta-interpreters

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

COSC 2P93 Prolog: Meta-interpreters

- Interpreted languages like Prolog can easily treat program code as data
- can use ‘clause’ to look at program code
- assert, retract, abolish to create/remove code
- =.., name, etc to look at terms themselves

- meta-programming: a program which treats program code as data
- the program code executed can be a different language than the code the meta-program is written in
- or it can be the same language

- meta-interpreter: a meta-program that executes a program(“source program”) , possibly written in that language itself
- can be used to enhance your language execution
- can create prototype languages as well

- Prolog is extremely useful for meta-programming

COSC 2P93 Prolog: Meta-interpreters

- op(Precedence, Code, Op).
- Precedence: numeric code indicating binding strength of operator
- smaller number = higher binding
- used when parentheses are missing

- Code: position and associativity
- prefix: fx, fy
- postfix: xf, yf
- infix: xfx, xfy, yfx, yfy
- “x”: argument must have ops of lower precedence
- “y”: argument must have ops of equal or lower precedence

- Op: characters for operator

- Precedence: numeric code indicating binding strength of operator

COSC 2P93 Prolog: Meta-interpreters

Example:

?- op(470, fy, 'not'). % prefix, binds strongest

?- op(475, xfy, 'and').% infix, binds stronger than ‘or’

?- op(480, xfy, 'or').% infix

can then write: not a and b or not c --> ((not a) and b) or (not c)

regular structure form: or( and( not(a), b ), not(c) )

COSC 2P93 Prolog: Meta-interpreters

- Example: a meta-interpreter for pure Prolog
solve( true ) :- !.

solve( not P ) :- !, \+ solve(P).

solve( (P, Q) ) :- !, solve(P), solve(Q).

solve( P ) :- clause(P, Body), solve(Body).

- each clause catches one possible case
- ‘true’ is used to represent the termination of a branch of execution
- note that clause(P, Body) returns P=parent(mary, bob), B=true for the fact: parent(mary, bob).

- the case for (P, Q) breaks up multiple goals; “,” is simply a built-in infix operator
- eg. solve((A, B, C, D)) = solve(P, Q) --> P = A, Q = (B, C, D) etc

- the cuts are needed so that, during backtracking, true, not P, and (P,Q) won’t be executed by the final case that uses clause

COSC 2P93 Prolog: Meta-interpreters

- The bulk of the work is done by ‘clause’
- clause actually does the unification of the current goal P with a clause
- upon backtracking, clause will backtrack and unify P with the next clause
- Note that, when P is unified with the clause Q :- B, the variable substitutions obtained via P=Q are automatically applied to B

- The interesting part of meta-interpreters is that you can alter the language behaviour
- Example: a meta-interpreter that selects goals from right-to-left
solve( true ) :- !.

solve( not P ) :- !, \+ solve(P).

solve( (P, Q) ) :- !, solve(Q), solve(P).

solve( P ) :- clause(P, Body), solve(Body).

COSC 2P93 Prolog: Meta-interpreters

- Example: A meta-interpreter that doesn’t do any backtracking
solve( true ) :- !.

solve( not P ) :- !, \+ solve(P).

solve( (P, Q) ) :- !, solve(P), solve(Q).

solve( P ) :- clause(P, Body), !, solve(Body).

- Example: adding some built-in predicates (no longer pure Prolog)
solve( true ) :- !.

solve( not P ) :- !, \+ solve(P).

solve( (P, Q) ) :- !, solve(P), solve(Q).

solve( write(X) ) :- !, write(X).

solve( read(X) ) :- !, read(X).

solve( P ) :- clause(P, Body), solve(Body).

COSC 2P93 Prolog: Meta-interpreters

- Example: print out a trace of your execution
solve( true ) :- !.

solve( not(P) ) :- !, \+ solve(P).

solve( (P, Q) ) :- !, solve(P), solve(Q).

solve( P ) :-

(write(‘calling ‘), write(P) ; write(P), write(‘fails’), nl, !, fail),

clause(P, Body),

write(‘...succeeds’), nl,

solve(Body).

COSC 2P93 Prolog: Meta-interpreters

- By creating new operators, you can even change the syntax of the source program -- great for creating a new language
- Example: a new syntax for Prolog
?- op(700, xfy, and).

?- op(800, xfx, if).

solve( true ) :- !.

solve( not P ) :- !, \+ solve(P).

solve( P and Q ) :- !, solve(P), solve(Q).

solve( P ) :- P if Body, solve(Body).

grandmother(X, Y) if mother(X, Z) and mother(Z, Y).

- Note how ‘if’ is just another predicate name:
- same as: if(grandmother(X,Y), (mother(X,Z), mother(Z,Y)).
- we essentially let the meta-level Prolog do the backtracking for us!

COSC 2P93 Prolog: Meta-interpreters

- Example: a metainterpreter that constructs a logical proof tree
solve(true, true) :- !.

solve(not P, (not Proof)) :- !, \+ solve(P, Proof).

solve((P, Q), (ProofP, ProofQ)) :- !, solve(P, ProofP), solve(Q, ProofQ).

solve(P, (P <== ProofP)) :- clause(P, Body), solve(Body, ProofP).

- arg 2 contains pattern of proof
- Would be nice to print it out in a legible form...

COSC 2P93 Prolog: Meta-interpreters

prettyprint(E) :- prettyprint2(E, 0).

prettyprint2(not A, Indent) :-

!,

nl, tab(Indent),

write('NOT '), prettyprint2(A, Indent).

prettyprint2((A,B), Indent) :-

!,

prettyprint2(A, Indent),

nl, tab(Indent), write('AND'),

prettyprint2(B, Indent).

prettyprint2(A <== true, Indent) :-

!,

nl, tab(Indent),

write(A),

write(' <== TRUE').

COSC 2P93 Prolog: Meta-interpreters

prettyprint2(A <== P, Indent) :-

!,

nl, tab(Indent),

write(A), write(' <== '),

Indent2 is Indent+3,

prettyprint2(P, Indent2).

prettyprint2(A, Indent) :-

nl, tab(Indent),

write(A).

COSC 2P93 Prolog: Meta-interpreters

- This example interprets a C-like language.
- Grammar of language (Backus-Naur Form, or BNF):
E ::= V := A | E;E | if(B, E, E) | while(B, E)

A ::= var | const | A+A | A-A | A*A

B ::= true | false | A>A | A=A | A>=A

- Implement via operators (“:=“, “;”) and structures:
if(B, E, F) and while(B, E)

- Memory: list of variable/value pairs:
- [(a, 0), (flag, 1), (value, 2014), ...]

COSC 2P93 Prolog: Meta-interpreters

- Idea: each statement in language affects the state of memory
- To interpret a program, determine how each statement changes memory
- This is an “operational semantics” approach.
eg. memory before: [(a, 1), (b, 2), (c, 5)]

a := b*c

memory after: [(a, 10), (b, 2), (c, 5)]

eg. E1;E2 where initial memory = Mem1

interpret(E1, Mem1) to generate Mem2

then interpret (E2, Mem2) to generate MemFinal

eg. while(B, E): let init memory = Mem1

if B = true then interpret(E, Mem1) to create Mem2

and interpret(while(B, E), Mem2) to create MemF

COSC 2P93 Prolog: Meta-interpreters

?- op(600, xfy, ':=').

interp( (Var := A), Init, Final ) :-

interpArith(A, Init, Val),

assign(Var, Val, Init, Final).

% assign(Var, Val, Before, After):

% replaces current (Var, OldVal) pair in with new (Var, Val) pair.

assign(Var, Val, MemBefore, MemAfter) :-

append(A, [(Var, _)|B], MemBefore),

append(A, [(Var,Val)|B], MemAfter),

!.

assign(Var, _, _, _) :-

!,

write('Error in assignment: '), write(Var), write(' not found.'), nl,

fail.

COSC 2P93 Prolog: Meta-interpreters

interp( (E;F), Init, Final ) :-

!,

interp(E, Init, Tmp),

interp(F, Tmp, Final).

interp( if(B, E, F), Init, Final ) :-

!,

(interpBool(B, Init) ->

interp(E, Init, Final)

;

interp(F, Init, Final)).

COSC 2P93 Prolog: Meta-interpreters

interp( while(B, E), Init, Final) :-

!,

(interpBool(B, Init) ->

interp(E, Init, Tmp),

interp( while(B, E), Tmp, Final)

;

Init = Final).

COSC 2P93 Prolog: Meta-interpreters

interpArith(A, _, A) :-

integer(A),

!.

interpArith(V, Init, Val) :-

member((V,Val), Init),

!.

interpArith(A+B, Init, Val) :-

interpArith(A, Init, ValA),

interpArith(B, Init, ValB),

Val is ValA + ValB,

!.

% similar for -, *, ...

COSC 2P93 Prolog: Meta-interpreters

interpBool(true, _) :- !.

interpBool(false, _) :- !, fail.

interpBool(A > B, Init) :-

interpArith(A, Init, ValA),

interpArith(B, Init, ValB),

!,

ValA > ValB.

COSC 2P93 Prolog: Meta-interpreters

?- test(A,B,C).

A = (a:=2;b:=3;a:=4),

B = [(a,0),(b,0),(c,0)],

C = [(a,4),(b,3),(c,0)]

A = (a:=2+1;b:=10-a;if(a>b+a,c:=5,c:= -5)),

B = [(a,0),(b,0),(c,0)],

C = [(a,3),(b,7),(c,-5)]

A = (a:=2;b:=10;c:=1;while(b>0,(c:=c*a;b:=b-1))),

B = [(a,0),(b,0),(c,0)],

C = [(a,2),(b,0),(c,1024)]