15.08.2013 Views

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

General Computer Science 320201 GenCS I & II Lecture ... - Kwarc

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

arguments to arithmetic operations are pushed to the stack in reverse order.<br />

fun compileE (e:exp, env:env) : code =<br />

case e of<br />

Con i => [con i]<br />

| Var i => [peek (lookup(i,env))]<br />

| Add(e1,e2) => compileE(e2, env) @ compileE(e1, env) @ [add]<br />

| Sub(e1,e2) => compileE(e2, env) @ compileE(e1, env) @ [sub]<br />

| Mul(e1,e2) => compileE(e2, env) @ compileE(e1, env) @ [mul]<br />

| Leq(e1,e2) => compileE(e2, env) @ compileE(e1, env) @ [leq]<br />

c○: Michael Kohlhase 302<br />

Compiling SW statements is only slightly more complicated: the constituent statements and expressions<br />

are compiled first, and then the resulting code fragments are combined by L(VM) control<br />

instructions (as the fragments already exist, the relative jump distances can just be looked up).<br />

For a sequence of statements, we just map compileS over it using the respective environment.<br />

Compiling SW Statements<br />

fun compileS (s:sta, env:env) : code =<br />

case s of<br />

Assign(i,e) => compileE(e, env) @ [poke (lookup(i,env))]<br />

| If(e,s1,s2) =><br />

let<br />

val ce = compileE(e, env)<br />

val cs1 = compileS(s1, env)<br />

val cs2 = compileS(s2, env)<br />

in<br />

ce @ [cjp (wlen cs1 + 4)] @ cs1 @ [jp (wlen cs2 + 2)] @ cs2<br />

end<br />

| While(e, s) =><br />

let<br />

val ce = compileE(e, env)<br />

val cs = compileS(s, env)<br />

in<br />

ce @ [cjp (wlen cs + 4)] @ cs @ [jp (~(wlen cs + wlen ce + 2))]<br />

end<br />

| Seq ss => foldr (fn (s,c) => compileS(s,env) @ c) nil ss<br />

c○: Michael Kohlhase 303<br />

As we anticipated above, the compileD function is more complex than the other two. It gives<br />

L(VM) program fragment and an environment as a value and takes a stack index as an additional<br />

argument. For every declaration, it extends the environment by the key/value pair k/v, where k<br />

is the variable name and v is the next stack index (it is incremented for every declaration). Then<br />

the expression of the declaration is compiled and prepended to the value of the recursive call.<br />

Compiling SW Declarations<br />

fun compileD (ds: declaration list, env:env, sa:index): code*env =<br />

case ds of<br />

nil => (nil,env)<br />

| (i,e)::dr => let<br />

val env’ = insert(i, sa+1, env)<br />

val (cdr,env’’) = compileD(dr, env’, sa+1)<br />

in<br />

168

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!