Presentation is loading. Please wait.

Presentation is loading. Please wait.

Meta-interpreters Interpreted languages like Prolog can easily treat program code as data Interpreted languages like Prolog can easily treat program code.

Similar presentations


Presentation on theme: "Meta-interpreters Interpreted languages like Prolog can easily treat program code as data Interpreted languages like Prolog can easily treat program code."— Presentation transcript:

1 Meta-interpreters Interpreted languages like Prolog can easily treat program code as data Interpreted languages like Prolog can easily treat program code as data can use ‘clause’ to look at program code can use ‘clause’ to look at program code assert, retract, abolish to create/remove code assert, retract, abolish to create/remove code =.., name, etc to look at terms themselves =.., name, etc to look at terms themselves meta-programming: a program which treats program code as data 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 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 or it can be the same language meta-interpreter: a meta-program that executes a program(“source program”), possibly written in that language itself 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 be used to enhance your language execution can create prototype languages as well can create prototype languages as well Prolog is extremely useful for meta-programming Prolog is extremely useful for meta-programming 1COSC 2P93 Prolog: Meta-interpreters

2 User-defined operators op(Precedence, Code, Op). op(Precedence, Code, Op). Precedence: numeric code indicating binding strength of operator Precedence: numeric code indicating binding strength of operator smaller number = higher binding smaller number = higher binding used when parentheses are missing used when parentheses are missing Code: position and associativity Code: position and associativity prefix: fx, fy prefix: fx, fy postfix: xf, yf postfix: xf, yf infix: xfx, xfy, yfx, yfy infix: xfx, xfy, yfx, yfy “x”: argument must have ops of lower precedence “x”: argument must have ops of lower precedence “y”: argument must have ops of equal or lower precedence “y”: argument must have ops of equal or lower precedence Op: characters for operator Op: characters for operator 2COSC 2P93 Prolog: Meta-interpreters

3 User-defined operators 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) ) 3COSC 2P93 Prolog: Meta-interpreters

4 Meta-interpreter Example: a meta-interpreter for pure Prolog 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 each clause catches one possible case ‘true’ is used to represent the termination of a branch of execution ‘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). 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 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 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 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 4COSC 2P93 Prolog: Meta-interpreters

5 Meta-interpreters The bulk of the work is done by ‘clause’ The bulk of the work is done by ‘clause’ clause actually does the unification of the current goal P with a 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 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 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 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 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). 5COSC 2P93 Prolog: Meta-interpreters

6 Meta-interpreters Example: A meta-interpreter that doesn’t do any backtracking 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) 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). 6COSC 2P93 Prolog: Meta-interpreters

7 Meta-interpreters Example: print out a trace of your execution 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), (write(‘calling ‘), write(P) ; write(P), write(‘fails’), nl, !, fail), clause(P, Body), clause(P, Body), write(‘...succeeds’), nl, write(‘...succeeds’), nl, solve(Body). solve(Body). 7COSC 2P93 Prolog: Meta-interpreters

8 Meta-interpreters By creating new operators, you can even change the syntax of the source program -- great for creating a new language 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 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: Note how ‘if’ is just another predicate name: same as: if(grandmother(X,Y), (mother(X,Z), mother(Z,Y)). same as: if(grandmother(X,Y), (mother(X,Z), mother(Z,Y)). we essentially let the meta-level Prolog do the backtracking for us! we essentially let the meta-level Prolog do the backtracking for us! 8COSC 2P93 Prolog: Meta-interpreters

9 Metainterpreters Example: a metainterpreter that constructs a logical proof tree 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 arg 2 contains pattern of proof Would be nice to print it out in a legible form... Would be nice to print it out in a legible form... 9COSC 2P93 Prolog: Meta-interpreters

10 Metainterps prettyprint(E) :- prettyprint2(E, 0). prettyprint2(not A, Indent) :- !, !, nl, tab(Indent), nl, tab(Indent), write('NOT '), prettyprint2(A, Indent). write('NOT '), prettyprint2(A, Indent). prettyprint2((A,B), Indent) :- !, !, prettyprint2(A, Indent), prettyprint2(A, Indent), nl, tab(Indent), write('AND'), nl, tab(Indent), write('AND'), prettyprint2(B, Indent). prettyprint2(B, Indent). prettyprint2(A <== true, Indent) :- !, !, nl, tab(Indent), nl, tab(Indent), write(A), write(A), write(' <== TRUE'). write(' <== TRUE'). 10COSC 2P93 Prolog: Meta-interpreters

11 Prettyprint (cont) prettyprint2(A <== P, Indent) :- !, !, nl, tab(Indent), nl, tab(Indent), write(A), write(' <== '), write(A), write(' <== '), Indent2 is Indent+3, Indent2 is Indent+3, prettyprint2(P, Indent2). prettyprint2(P, Indent2). prettyprint2(A, Indent) :- nl, tab(Indent), nl, tab(Indent), write(A). write(A). 11COSC 2P93 Prolog: Meta-interpreters

12 Another metainterpreter: “C” This example interprets a C-like language. This example interprets a C-like language. Grammar of language (Backus-Naur Form, or BNF): 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: Implement via operators (“:=“, “;”) and structures: if(B, E, F) and while(B, E) Memory: list of variable/value pairs: Memory: list of variable/value pairs: [(a, 0), (flag, 1), (value, 2014),...] [(a, 0), (flag, 1), (value, 2014),...] 12COSC 2P93 Prolog: Meta-interpreters

13 C metainterpreter: “interp3” Idea: each statement in language affects the state of memory Idea: each statement in language affects the state of memory To interpret a program, determine how each statement changes memory To interpret a program, determine how each statement changes memory This is an “operational semantics” approach. This is an “operational semantics” approach. eg. memory before: [(a, 1), (b, 2), (c, 5)] a := b*c a := b*c memory after: [(a, 10), (b, 2), (c, 5)] 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 if B = true then interpret(E, Mem1) to create Mem2 and interpret(while(B, E), Mem2) to create MemF and interpret(while(B, E), Mem2) to create MemF 13COSC 2P93 Prolog: Meta-interpreters

14 interp3 code examples ?- 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. fail. 14COSC 2P93 Prolog: Meta-interpreters

15 interp3 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)). 15COSC 2P93 Prolog: Meta-interpreters

16 interp3 interp( while(B, E), Init, Final) :- !, (interpBool(B, Init) -> interp(E, Init, Tmp), interp( while(B, E), Tmp, Final) ; Init = Final). 16COSC 2P93 Prolog: Meta-interpreters

17 interp3: arithmetic 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 -, *,... 17COSC 2P93 Prolog: Meta-interpreters

18 interp3: boolean interpBool(true, _) :- !. interpBool(false, _) :- !, fail. interpBool(A > B, Init) :- interpArith(A, Init, ValA), interpArith(B, Init, ValB), !, ValA > ValB. 18COSC 2P93 Prolog: Meta-interpreters

19 interp3 ?- 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)] 19COSC 2P93 Prolog: Meta-interpreters


Download ppt "Meta-interpreters Interpreted languages like Prolog can easily treat program code as data Interpreted languages like Prolog can easily treat program code."

Similar presentations


Ads by Google