240 likes | 378 Views
Operational Semantics. Operational Semantics (O.S.): Specify Semantics by specifying how each command is to be executed. One approach: Define an interpreter for the language. Meta-circular interpreter: Interpreter in the same language
E N D
Operational Semantics • Operational Semantics (O.S.):Specify Semantics by specifying how each command is to be executed. • One approach: Define an interpreter for the language. • Meta-circular interpreter: Interpreter in the same language • References:McCarthy and others: Lisp 1.5 programmer's manual CSE 755, part2
Lisp Basics • Data types: Atomic & non-atomic s-expressions • Atomic s-exp: • Numbers [we will use only integers] • Strings [we won't use them] • Symbols [i.e., identifiers]: • function names [built-in and user-defined] • parameter names • constants: T [for true], NIL [for false; also other key uses] • Non-atomic s-exp: If s1, s2 are s-exps, so is (s1 . s2) [so non-atomic s-exps are binary trees] CSE 755, part2
Lisp Basics (contd.) • Basic functions: • cons[ s1, s2 ] = (s1 . s2) • car[ (s1 . s2) ] = s1Note: car[ s ] gives error if s is atomic • cdr [ (s1 . s2) ] = s2Note: cdr[ s ] gives error if s is atomic • atom[ s ] = returns T/NIL if s is/isn't an atom • null[ s ] = returns T/NIL if s is/isn't the atom NIL • eq[ s1, s2] = ret. T/NIL if s1, s2 are/aren't the same atom(null, eq may give errors if applied to non-atoms) • plus[ s1, s2 ]: returns [s1 + s2] (must be numbers) • minus[ s1, s2 ]: returns [s1 s2] (must be numbers) • Etc. CSE 755, part2
Problem: Suppose we have four s-exps, s1, s2, s3, s4 that we want to keep together. Possible ways: ((s1 . s2) . (s3 . s4)) (s1 . (s2 . (s3 . s4))) (((s1 . s2) . s3) . s4) [what about (s1 . s2 . s3 . s4) ?] Standard solution: (s1 . (s2 . (s3 . (s4 . NIL)))) Notation: (s1 s2 s3 s4) denotes (s1 . (s2 . (s3 . (s4 . NIL)))) (s1 s2 s3) denotes (s1 . (s2 . (s3 . NIL))) Important: (s1 s2 s3) etc. is only a notation not a new type of s-exp ( ) denotes the atom NIL CSE 755, part2
Lisp Basics (contd.) • car[ (2 3) ] = 2 • cdr[(2 3) ] = ( 3 ) [Note: not 3 ] • cons[ 2 , 3 ] = (2 . 3) [Note: not (2 3) ] • cons[ 2 , ( 3 . NIL) ] = (2 . (3 . NIL))same: cons[ 2 , ( 3 ) ] = (2 . (3 . NIL))same: cons[ 2 , ( 3 ) ] = (2 3) • cons[ (s1 s2), (s3 s4) ] = ((s1 s2) . (s3 s4)) != (s1 s2 s3 s4) • cons[ (s1 . s2), (s3 s4) ] = ((s1 . s2) . (s3 s4)) = ((s1 . s2) s3 s4) [why?] • cons[ (s1 s2), (s3 . s4) ] ?cons[ (s1 . s2), (s3 . s4) ] ? CSE 755, part2
Lisp Basics (contd.) • eq[ T, T] = T • eq[ T, NIL] = NIL • eq[ NIL, ()] = T • eq[car[(2 . 3)], cdr[(3 . 2)]] = T • eq[(2 . 3), (3 . 2)] : error; arguments to eq must be atoms • eq[plus[2 , 3], minus[10, 5]] = T • null[T] = NIL • null[NIL] = T • null[car[(2)]] = NIL • null[cdr[(2)]] = T • atom[car[(2)]] = T • atom[cdr[(2)]] = T CSE 755, part2
Lisp (the prog. lang.) • Lisp is not an imperative language • Lisp is a functional programming language • So: • No "internal state" that changes as program is "executed" • In fact, no program variables whose values change over time! • A program has no "side-effects" • Lisp runs in eval-print mode: • Give the interpreter a Lisp Expression (not Lisp "program") • It evaluates it, prints the value • Waits for the next Lisp Expression CSE 755, part2
Types of Lisp Expressions 1. Constants: 4, T, NIL, "xyz" 2. Function application: (F a1 a2 a3 ... ) F is the function to be applied; a1, a2, ... the arguments The interpreter first evaluates each argument, then applies F to the resulting values Examples: (plus 2 3) will output 5 // plus may be called "+" (plus (plus 3 4) (plus 3 5)) will output 15 (car (3 . 4)) will output an error message! CSE 755, part2
Types of Lisp Exps. (contd.) 3. Quoted s-expressions: (quote s)where s is any s-exp, not necessarily a Lisp expression; The interpreter returns s as the value of (quote s) Examples: (car (3 . 4)) will output error (car (quote (3 . 4))) will output 3 (quote (3 . 4)) will output (3 . 4) (cons (quote (1 . 2)) (quote (3 .4))) will output ((1 . 2) . (3 . 4)) (quote (cons (1 . 2) (3 . 4))) will output ?? (plus (car (2 . 3) ) (cdr (2 . 3)) ) will output ?? (plus (quote (2 . 3) ) (quote 3) ) will output ?? CSE 755, part2
3. Quoted s-expressions: (quote s) looks like a function call [with quote being the function called] but it is not; quote is a special form ] 4. Conditional: (cond (b1 e1) (b2 e2) ... (bn en) )where each of b1, e1, b2, e2, ..., bn, en is a Lisp exp. To evaluate: first evaluate b1; if it evaluates to T [i.e., non-NIL], evaluate e1 and return the resulting value; if b1 evaluates to NIL, evaluate b2 and if it evaluates to non-NIL, evaluate e2 and return the resulting value; if b1 and b2 both evaluate to NIL, evaluate b3 and ... If b1, b2, ..., bn evaluate to NIL, error! CSE 755, part2
Types of Lisp Exps. (contd.) 4. Examples (cond (T NIL) (NIL T)) : evaluates to ?? (cond (NIL T) (T NIL)) : evaluates to ?? (cond (NIL T) (NIL NIL)) : evaluates to ?? (cond (T NIL) (T NIL)) : evaluates to ?? (cond ( (eq (plus 2 3) (minus 4 5)) 10 ) ( (eq (plus 2 3) (times 4 5)) 20 ) ( (eq (plus 2 3) (plus 4 5)) 30 ) ( T NIL ) ) : evaluates to ?? cond is also a special form; why? CSE 755, part2
Types of Lisp Exps. (contd.) 5. Function definition: (defun f (p1 p2 ...) fb)f is the name of the function being defined;p1, p2, ... are the formal parameters of f;fb is the body of the function -- itself a Lisp exp. The interpreter saves the definition of f for use when f is applied Example:(defun sum (x y) (plus x y) )defines a function named sum that has two parameters whose names are x, y [types?], and whose body is as given (sum 3 4) evaluates to 7 defun is also a special form; why? That's it! That is (essentially) all of Lisp! CSE 755, part2
Examples Examples:(defun equal (x y) ; x, y need not be atoms (cond ( (atom x) (cond ( (atom y) (eq x y) ) ( T NIL) ) ( (atom y) NIL) ((equal (car x) (car y)) (equal (cdr x) (cdr y)) ) (T NIL) ) ) Consider: (equal 4 4) (equal 4 (plus 2 2)) (equal (car (2 . 3)) (plus 1 1) ) [watch out!] CSE 755, part2
Examples:(defun equal (x y) (cond ( (atom x) (cond ( (atom y) (eq x y) ) ( T NIL) ) ( (atom y) NIL) ( (equal (car x) (car y)) (equal (cdr x) (cdr y)) ) (T NIL) ) ) "Design" notation: equal[x, y] = [ atom[x] [ atom[y] eq[x, y]; | T NIL; ] | atom[y] NIL; | equal[car[x], car[y]] equal[cdr[x], cdr[y]]; | T NIL; ] CSE 755, part2
Examples (contd.) xmemb[x, list] : is x a member of list? xmemb[x, list] = [ null[list] NIL; | eq[x, car[list]] T; | T xmemb[x, cdr[list]]; ] (defun xmemb (x list) (cond ( (null list) NIL) ( (eq x (car list)) T) ( T (xmemb x (cdr list)) ) ) ) CSE 755, part2
Examples (contd.) xunion[s1, s2] : s1, s2 are two lists; xunion must return s1 s2 xunion[s1, s2] = [ null[s1] s2; | null[s2] s1; | T [ xmemb[car[s1], s2] xunion[cdr[s1],s2]; | T cons[car[s1], xunion[cdr[s1],s2] ]; ] ] xunion[s1, s2] = [ null[s1] s2; | null[s2] s1; | xmemb[car[s1], s2] xunion[cdr[s1],s2]; | T cons[car[s1], xunion[cdr[s1],s2] ]; ] CSE 755, part2
Different styles in Lisp maxList[L] :: ; returns max of number in non-empty list L ; Functional: [ null[cdr[L]] car[L]; | >[car[L], maxList[cdr[L]] car[L]; | T maxList[cdr[L]] ] ; Functional but better: [ null[cdr[L]] car[L]; | T bigger[ car[L], maxList[cdr[L]]] ] // define bigger ; "imperative": maxList[L] = max2[car[L], cdr[L]] max2[x, L] = [ null[L] x; | >[x, car[L]] max2[x, cdr[L]]; | T max2[ car[L], cdr[L] ] ] CSE 755, part2
How Lisp expressions are eval'd • Atoms: Constants: simple; others: look up on a-list • Function application: (F a1 a2 a3 ... an) F is a function that expects n parameters; each ai is a Lisp expression; Evaluate each ai; bind that value aiv to pi, the corr. parameter, by adding (pi . aiv) to the a-list; then evaluate the body of F Note: If F is not a built-in function, get def. from d-list CSE 755, part2
How Lisp expressions are eval'd • (QUOTE S) : simply return S • (COND (b1 s1) ... (bn sn) ) : Eval. b1; if result is non-NIL, eval. s1 and return its value; else, eval. b2, if result is non-NIL, eval. s2 & return its val; ...; eval. bn, if non-NIL, eval. sn & return its val; if b1, ..., bn all eval to NIL, print error, escape to top; • (DEFUN F (p1 ... pn) fb) : add (F . ((p1 ... pn) . fb)) to d-list. CSE 755, part2
Lisp Interpreter Details Can be written in Lisp fairly easily ... one reason: Lisp functions and Lisp exps. are s-exps. • eval: evaluates a Lisp-exp. given current parameter bindings (a-list) and fn. definitions (d-list) • apply: applies a function to given set of argument values - gets the fn. definition from d-list, binds the formal pars to corr. arg.vals, then calls eval to evaluate the body of the fn. • evcon: evaluates a conditional Lisp-exp: Given ((b1 e1) (b2 e2) ...): uses eval to evaluate b1, b2, ... until one, bi, evaluates to non-NIL; uses eval to evaluate corr. ei and returns its value. • evlis: evaluates a list of Lisp-exps. CSE 755, part2
Lisp Interpreter Details (in Lisp) interpreter[dList] = eval[exp, NIL, dList] or better: output[ eval[input[], NIL, dList] ] evlis[list, aList, dList] = [ null[list] NIL; | T cons[ eval[car[list], aList, dList], evlis[cdr[list], ..,..] ] ] evcon[be, aList, dList] = // be is of form ((b1 e1) ... (bn en)) [ null[be] NIL; // better: error!; | eval[caar[be], aList, dList] eval[cadar[be], aList, dList]; | T evcon[cdr[be], aList, dList] ] CSE 755, part2
Lisp Interpreter Details (in Lisp) eval[ exp, aList, dList] = [ atom[exp] --> [ int[exp] --> exp | eq[exp,T] --> T | eq[exp,NIL] --> NIL | in[exp,aList] --> getVal[exp,aList] | T --> "unbound variable!" ] | atom[car[exp]] --> [ eq[car[exp],QUOTE] --> cadr[exp] | eq[car[exp],COND] --> evcon[cdr[exp], aList, dList] | eq[car[exp],DEFUN] --> "add to dList (state change!)" | T --> apply[car[exp], evlis[cdr[exp],aList,dList], aList, dList] ] | T --> "error!" ] CSE 755, part2
Lisp Interpreter Details (in Lisp) apply[ f, x, aList, dList] = [ atom[f] --> [ eq[f, CAR] --> caar[x]; // why? | eq[f, CDR] --> cdar[x]; | eq[f, CONS] --> cons[car[x], cdr[x]]; //?? | eq[f, ATOM] --> atom[car[x]]; | eq[f, NULL] --> null[car[x]]; | eq[f, EQ] --> eq[car[x], cadr[x]]; | T --> eval[ cdr[getval[f, dList]], addpairs[car[getval[f, dList]], x, aList], dList ] ; ]; | T --> "error!"; ] Elements on dList of form: (f . (pList . body) ) addpairs[pList,x,aList]: returns new a-list CSE 755, part2
Lisp Interpreter: Some comments • We assumed s-expressions have been implemented; no way to specify how to do this within Lisp • Fact that Lisp-expns (to be evaluated) & function bodies were s-exps: key in writing a meta-circular interpreter (mci) • The mci for Lisp defines its operational sem. since it tells us how Lisp-expns are to be evaluated -- but it assumes we have some basic knowledge about Lisp • You could change the o.s. of Lisp by rewriting appropriate parts of the main functions of the mci -- CLOS-MOP allows the Lisp programmer to do so! CSE 755, part2