diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2d5a868e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.i +*.o +*.s diff --git a/README.md b/README.md index d212fdfc..2f544432 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# compiler-2020 -A supplementary repository for the course on compilers. +# HW 6 diff --git a/runtime/runtime.c b/runtime/runtime.c index aadeee93..3997a3ab 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -71,11 +71,11 @@ void* Bsta (int i, void *v, void *x) { return v; } -void Lwrite (int x) { +void Bwrite (int x) { printf ("%d\n", x); } -int Lread () { +int Bread () { int result; scanf ("%d", &result); diff --git a/src/Expr.lama b/src/Expr.lama index 0dc1a5de..4f17200b 100644 --- a/src/Expr.lama +++ b/src/Expr.lama @@ -99,11 +99,107 @@ fun evalList (c, exprs) { esac } -(* Assignment *) -fun eval (c@[s, w], expr) { - failure ("evalExpr not implemented\n") +fun dvar(v) { + case v of + Var(x) -> x + | _ -> failure("not a var") + esac +} + +fun eval (c@[state, world], expr) { + case expr of + Read(x) -> case readWorld(world) of [val, nworld] -> + [[ + state<-[x, Var(val)], + nworld + ], + Void + ] + esac + | Write(expr) -> + case eval(c, expr) of [[state, world], res] -> + [[ + state, + writeWorld(res, world) + ], + Void] + esac + | Assn(x, expr) -> case evalList(c, {x, expr}) of [[state, world], var:res:_] -> + [ + [ + case var of + Ref(x) -> state<-[x, Var(res)] | + ElemRef(arr, i) -> arr[i] := res; state + esac, + world + ], + res + ] + esac + | Seq(stmt1, stmt2) -> + eval( + eval(c, stmt1).fst, + stmt2 + ) + | If(cond, stmt, estmt) -> case eval(c, cond) of + [newConf, 0] -> case estmt of None -> [newConf, Void] | _ -> eval(newConf, estmt) esac | + [newConf, _] -> eval(newConf, stmt) + esac + | While(cond, stmt) -> case eval(c, cond) of + [newConf, 0] -> [newConf, Void] | + [newConf, _] -> eval(eval(newConf, stmt).fst, While(cond, stmt)) + esac + | Rep(stmt, cond) -> + case eval(c, stmt).fst of newConf -> + case eval(newConf, cond) of + [newConf1, 0] -> eval(newConf1, Rep(stmt, cond)) | + [newConf1, _] -> [newConf1, Void] + esac + esac + | Skip -> [c, Void] + | Const(n) -> [c, n] + | Var(x) -> [c, state.lookup(x).dvar] + | Binop(op, lefto, righto) -> case evalList(c, {lefto, righto}) of [c, a:b:_] -> + [c, evalOp(op, a, b)] + esac + | Ref(x) -> [c, Ref(x)] + | Ignore(expr) -> [eval(c, expr).fst, Void] + | Scope(defs, expr) -> case evalList([state.enterScope, world], defs) of [c, _] -> + case eval(c, expr) of [[s, w], res] -> [[s.leaveScope, w], res] esac + esac + | Local(vars) -> [[state.addNames(vars), world], Void] + | Fun(name, args, body) -> [[state.addFunction(name, args, body), world], Void] + | Call(f, argExps) -> case c.evalList(argExps) of [[s, w], argVals] -> case state.lookup(f) of Fun(args, body) -> + case body of + External -> case evalBuiltin(f, argVals, w) of [res, w] -> [[s, w], res] esac| + _ -> local news = foldl( + fun (olds, [arg, val]) {olds.addName(arg, Var(val))}, + s.enterFunction, + zip(args, argVals) + ); + case eval([news, w], + body + ) of [[sres, w], res] -> + [[s.leaveFunction(sres.getGlobal), w], res] + esac + esac + esac esac + | ElemRef(arr, i) -> case evalList(c, {arr, i}) of + [c, {arrRes, ires}] -> [c, ElemRef(arrRes, ires)] + esac + | Elem(arr, i) -> case evalList(c, {arr, i}) of + [c, {arrRes, ires}] -> [c, arrRes[ires]] + esac + | String(s) -> [c, s] + | Array(exps) -> case evalList(c, exps) of [c, ress] -> [c, listArray(ress)] esac + | Builtin(name, args) -> case evalList(c, args) of [[s, w], argRes] -> + case evalBuiltin(name, argRes, w) of [res, w] -> + [[s, w], res] + esac + esac + esac } -(* End *) + -- Evaluates a program with a given input and returns an output public fun evalExpr (input, expr) { diff --git a/src/Lexer.lama b/src/Lexer.lama index fc6847d4..af788a27 100644 --- a/src/Lexer.lama +++ b/src/Lexer.lama @@ -79,6 +79,7 @@ public kSkip = s (rSkip), kElif = s (rElif), kFi = s (rFi), kWhile = s (rWhile), + kRead = s (rRead), kDo = s (rDo), kOd = s (rOd), kRepeat = s (rRepeat), diff --git a/src/Parser.lama b/src/Parser.lama index d994f51c..150c96d3 100644 --- a/src/Parser.lama +++ b/src/Parser.lama @@ -74,7 +74,7 @@ fun expandScope (defs, expr) { foldr (fun ([defs, expr], def) { case def of [ident, None] -> [ident : defs, expr] - | [ident, Some (value)] -> [ident : defs, Seq (Ignore (Assn (Ref (ident), value)), expr)] + | [ident, Some (value)] -> [ident : defs, Seq (Ignore (Assn (Ref (ident), value(Val))), expr)] esac }, [{}, expr], @@ -129,8 +129,44 @@ local primary = memo $ eta syntax ( | Some (args) -> assertValue (a, Call (x, args)) esac }} | -(* Assignment *) - $(failure ("the rest of primary parsing in not implemented\n"))), + bexp=inbr[s("("), exp, s(")")] {fun(a) {bexp(a)} } | + loc=pos kSkip {fun(a) {assertVoid(a, Skip, loc)} } | + + kIf c=exp kThen s=scopeExpr ot=elifStmt kFi {fun(a) {If(c(Val), s(a), ot(a))} } | + loc=pos kIf c=exp kThen s=scopeExpr kFi {fun(a) {assertVoid(a, If(c(Val), s(Void), None), loc)}} | + loc=pos kWhile c=exp kDo s=scopeExpr kOd {fun(a) { assertVoid(a, While(c(Val), s(Void)), loc)} }| + loc=pos kFor i=scopeExpr s[","] c=exp s[","] s=exp kDo ot=scopeExpr kOd + { fun(a) { + distributeScope(i(Void), + fun(e) { assertVoid( + a, + Seq(e, While(c(Val), Seq(ot(Void), s(Void)))), + loc + ) + } + ) + }} | + loc=pos kRepeat b=scopeExpr kUntil c=inbr[s("("), exp, s(")")] { + fun(a) { + distributeScope(b(Void), fun(e) {assertVoid(a, Rep(e, c(Val)), loc) }) + } + }| + se=inbr[s("{"), scopeExpr, s("}")] {fun(a) {se(a)}} + ), + varDef = memo $ eta syntax ( + x=lident v=(-s["="] basic)? {[x, v]} + ), + funDef = memo $ eta syntax ( + kFun name=lident args=inbr[s("("), list0(lident), s(")")] body=inbr[s("{"), scopeExpr, s("}")] {Fun(name, args, body(Weak))} + ), + def = memo $ eta syntax ( + kLocal l=list[varDef] s[";"] {Local(l)} | + funDef + ), + scopeExpr = memo $ eta syntax ( + defs=def+ e=exp? {fun(a) {expandScope(defs, case e of None -> Skip | Some(ee) -> ee(a) esac)}} | + e=exp {fun (a) {e(a)}} + ), (* End *) basic = memo $ eta (expr ({[Right, singleton ([s (":="), fun (l, loc, r) { @@ -158,25 +194,14 @@ local primary = memo $ eta syntax ( esac }, e, ps) (a) }} - ), - scopeExpr = memo $ eta syntax (ds=definition* e=exp? {fun (a) {fun (e) { - case ds of - {} -> e - | _ -> expandScope (ds, e) - esac - } (case e of - Some (e) -> e (a) - | _ -> Skip - esac) - }}), - definition = memo $ eta syntax (kLocal ds=list[syntax (lident (s["="] e=basic {e (Val)})?)] s[";"] {Local (ds)} | - kFun name=lident - args=inbr[s("("), list0 (lident), s(")")] - body=inbr[s("{"), scopeExpr, s("}")] { - Fun (name, args, body (Weak)) - } - ), + ), exp = memo $ eta syntax (basic | s1=basic s[";"] s2=exp {fun (a) {Seq (s1 (Void), s2 (a))}}); -- Public top-level parser public parse = syntax (s=scopeExpr {s (Void)}); + +local elifStmt = syntax ( + kElif e=exp kThen s=scopeExpr ot=elifStmt {fun(a) { If(e(Val), s(a), ot(a))} } | + loc=pos kElif e=exp kThen s=scopeExpr {fun(a) { assertVoid(a, If(e(Val), s(Void), e(Void)), loc) }} | + kElse s=scopeExpr { fun(a) {s(a)} } +); diff --git a/src/SM.lama b/src/SM.lama index 0af2a8de..5705893d 100644 --- a/src/SM.lama +++ b/src/SM.lama @@ -122,8 +122,89 @@ fun eval (env, w, insns) { -- Core interpreter: takes a configuration and a program, returns a configuration (* Assignment *) - fun eval (c@[st, cst, s, w], insns) { - failure ("SM interpreter is not implemented\n") + fun eval (c@[stack, cst, state, world], insns) { + case insns of (x:tail) -> + case x of + JMP(l) -> eval(c, fromLabel(env, l)) + | CJMP(cond, l) -> case stack of (t:rest) -> + if (compare(cond, "z") == 0 && t == 0 !! compare(cond, "nz") == 0 && t != 0) + then eval([rest, cst, state, world], fromLabel(env, l)) + else eval([rest, cst, state, world], tail) + fi + esac + | LABEL(l) -> eval(c, tail) + | CALL(f,_) -> eval([stack, [state, tail]:cst, state, world], env.fromLabel(f)) + | END -> case cst of + [ostate, oinsns]:cst -> eval([stack, cst, ostate, world], oinsns) + | _ -> c + esac + | _ -> + local nconf; + nconf := + case x of + BINOP(op) -> + case stack of (a:b:rest) -> + [(evalOp(op, b, a):rest), cst, state, world] + esac + | CONST(n) -> [(n:stack), cst, state, world] + | LD(x) -> [(state.lookup(x)):stack, cst, state, world] + | ST(x) -> + case stack of (t:rest) -> + [rest, cst, state.assign(x, t); state, world] + esac + + | READ -> case readWorld(world) of [n, nworld] -> + [(n:stack), cst, state, nworld] + esac + | WRITE -> + case stack of (t:rest) -> { + local nworld; + nworld := writeWorld(t, world); + [rest, cst, state, nworld] + } + esac + | STI -> case stack of (res:var:rest) -> + [(res:rest), cst, state.assign(var, res); state, world] + esac + | LDA(x) -> + [(x:stack), cst, state, world] + | DROP -> case stack of (_:rest) -> + [rest, cst, state, world] | _ -> failure(insns.string) + esac + | BEGIN(_, nargs, nlocs) -> case stack.take(nargs) of [rest, vals] -> + local nstate = foldl( + fun([state1, n], val) { + [ + state1.assign(Arg(n), val); state1, + n + 1 + ] + }, + [makeState(nargs, nlocs), 0], + vals + )[0]; + [rest, cst, nstate, world] + esac + | GLOBAL(x) -> assign(state, Glb(x), 0); [stack, cst, state, world] + | ARRAY(l) -> case take(stack, l) of [stack, elems] -> + [listArray(elems):stack, cst, state, world] + esac + | ELEM -> case stack of i:arr:stack -> + [arr[i]:stack, cst, state, world] + esac + | STA -> case stack of val:i:arr:stack -> + arr[i] := val; [val:stack, cst, state, world] + esac + | STRING(s) -> [s:stack, cst, state, world] + | BUILTIN(name, narg) -> case take(stack, narg) of [stack, args] -> + case evalBuiltin(name, args, world) of [res, world] -> + [res:stack, cst, state, world] + esac + esac + esac; + eval(nconf, tail) + esac + | _ -> c + esac } (* End *) @@ -352,7 +433,228 @@ fun addVars (env, names) { -- environment (use env.beginFun) and register arguments -- (use env.addArg). -public fun compileSM (expr) { - failure ("compileSM not implemented\n") +public fun compileSM (stmt) { + case compileSmWithEnv(stmt, initCompEnv().enterScope.addFun("read", Builtin, 0).addFun("write", Builtin, 1)) of [insns, env] -> + compileFuncs( + singleton(LABEL("main")) +++ + singleton(BEGIN("main", 0, env.getLocals)) +++ + insns +++ + singleton(END) + , + env.endScope + )[0] + esac +} + +fun compileFuncs (insns, env) { + case env.getFuns of + [{}, env] -> [insns, env] | + [funcs, env] -> case foldl ( + fun ([insns, env], Fun (name, args, body, state)) { + case addArgs(env.beginFun(state), args) of env -> + case compileSmWithEnv(body, env) of [bodyInsns, env] -> + [ + insns +++ + singleton(LABEL(name)) +++ + singleton(BEGIN(name, args.size, env.getLocals)) +++ + bodyInsns +++ + singleton(END) + , + env + ] + esac + esac + }, + [insns, env], + funcs + ) of [insns, env] -> + compileFuncs (insns, env) + esac + esac +} + +fun compileSmWithEnv(stmt, env) { + compileSmWithEnvAndLbl(stmt, env, false, "") +} + +fun compileSmWithEnvAndLbl(stmt, env, shouldJump, lblToJump) { + local additional = if shouldJump then singleton(JMP(lblToJump)) else {} fi; + case stmt of + Assn(x, expr) -> case compileSmWithEnv(x, env) of [ins1, env1] -> + case compileSmWithEnv(expr, env1) of [ins2, env2] -> + [ins1 +++ ins2 +++ + case x of ElemRef(_, _) -> singleton(STA) | _ -> singleton(STI) esac + +++ additional, env2] + esac + esac + | Seq(stmt1, stmt2) -> case compileSmWithEnv(stmt1, env) of [res1, env1] -> + case compileSmWithEnvAndLbl(stmt2, env1, shouldJump, lblToJump) of [res2, env2] -> + [res1 +++ res2, env2] + esac + esac + | Skip -> [{} +++ additional, env] + | If(cond, stmt, estmt) -> + case genLabels(env, 2) of [lbl1, lbl2, nenv] -> + case compileSmWithEnv(cond, nenv) of [ins1, env0] -> + case + if (shouldJump) + then compileSmWithEnvAndLbl(stmt, env0, shouldJump, lblToJump) + else compileSmWithEnvAndLbl(stmt, env0, true, lbl2) + fi of [res1, env1] -> + + local res2, env2; + case estmt of + None -> res2 := {}; env2 := env1 + | _ -> case compileSmWithEnv(estmt, env1) of [res3, env3] -> res2 := res3; env2 := env3 esac + esac; + [ + ins1 +++ + singleton(CJMP("z", lbl1)) +++ + res1 +++ + singleton(LABEL(lbl1)) +++ + res2 +++ + if (shouldJump) then additional else singleton(LABEL(lbl2)) fi + , + env2 + ] + esac + esac + esac + | While(cond, stmt) -> + case genLabels(env, 2) of [lbl1, lbl2, nenv] -> + case compileSmWithEnv(cond, nenv) of [ins1, env0] -> + case compileSmWithEnv(stmt, env0) of [res1, env1] -> + [ + singleton(JMP(lbl2)) +++ + singleton(LABEL(lbl1)) +++ + res1 +++ + singleton(LABEL(lbl2)) +++ + ins1 +++ + singleton(CJMP("nz", lbl1)) +++ + additional + , + env1 + ] + esac + esac + esac + | Rep(stmt, cond) -> + case genLabels(env, 1) of [lbl1, nenv] -> + case compileSmWithEnv(stmt, nenv) of [res1, env1] -> + case compileSmWithEnv(cond, env1) of [ins1, env0] -> + [ + singleton(LABEL(lbl1)) +++ + res1 +++ + ins1 +++ + singleton(CJMP("z", lbl1)) +++ + additional + , + env0 + ] + esac + esac + esac + | Ignore(expr) -> case compileSmWithEnv(expr, env) of [ins1, env1] -> + [ + ins1 +++ + singleton(DROP) +++ + additional, + env1 + ] + esac + | Const(n) -> + [ + singleton(CONST(n)) +++ + additional, + env + ] + | Var(x) -> + [ + singleton(LD(env.lookupVar(x))) +++ + additional, + env + ] + | Binop(op, lefto, righto) -> + case compileSmWithEnv(lefto, env) of [ins1, env1] -> case compileSmWithEnv(righto, env1) of [ins2, env2] -> + [ + ins1 +++ + ins2 +++ + singleton(BINOP(op)) +++ + additional, + env2 + ] + esac esac + | Ref(x) -> + [ + singleton(LDA(env.lookupVar(x))) +++ + additional, + env + ] + | Scope(defs, expr) -> case foldl(fun([env, funcs, glob], def) { + case def of + Local(vars) -> [env.addVars(vars), funcs, if env.isGlobal then (map(fun (var) {GLOBAL(var)}, vars)) +++ glob else glob fi] | + Fun (name, args, body) -> case genFunLabel(env, name) of + [fn, env] -> [env.addFun(name, fn, size(args)), [fn, args, body]:funcs, glob] + esac + esac + }, [env.beginScope, {}, {}], defs) of + [env, funcs, glob] -> case compileSmWithEnv( + expr, + foldl(fun(env, [f, args, body]) { + rememberFun(env, f, args, body) + }, + env, + funcs + ) + ) of + [insns1, env1] -> [glob +++ insns1 +++ additional, env1.endScope] + esac + esac + | Call (f, argExprs) -> + case foldl(fun([insns, env], expr) { + case compileSmWithEnv(expr, env) of [insns1, env1] -> [insns +++ insns1, env1] esac + }, [{}, env], argExprs) of + [insns, env] -> + case lookupFun(env, f) of + Fun(Builtin, _) -> + [insns +++ singleton(BUILTIN(f, argExprs.size)) +++ additional, env] + | Fun(fn, n) -> + [insns +++ singleton(CALL(fn, n)) +++ additional, env] + esac + esac + | ElemRef(arr, i) -> case compileSmWithEnv(arr, env) of [arrRes, env] -> + case compileSmWithEnv(i, env) of [ires, env] -> + [arrRes +++ ires +++ additional, env] + esac esac + | Elem(arr, i) -> case compileSmWithEnv(arr, env) of [arrRes, env] -> + case compileSmWithEnv(i, env) of [ires, env] -> + [arrRes +++ ires +++ singleton(ELEM) +++ additional, env] + esac esac + | Array(arr) -> case foldl( + fun([arrRes, env], elem) { + case compileSmWithEnv(elem, env) of [eres, env] -> [arrRes +++ eres, env] esac + }, + [{}, env], + arr + ) of [arrRes, env] -> + [arrRes +++ singleton(ARRAY(arr.size)) +++ additional, env] + esac + | String(x) -> [singleton(STRING(x)) +++ additional, env] + | Builtin(name, args) -> case compileList(env, args) of [res, env] -> + [res +++ singleton(BUILTIN(name, args.size)) +++ additional, env] + esac + + esac } (* End *) + + +fun compileList(env, args) { + foldl( + fun([res, env], elem) { + case compileSmWithEnv(elem, env) of [eres, env] -> [res +++ eres, env] esac + }, + [{}, env], + args + ) +} diff --git a/src/Util.lama b/src/Util.lama new file mode 100644 index 00000000..720f9b07 --- /dev/null +++ b/src/Util.lama @@ -0,0 +1,26 @@ +-- Various utilities. +import List; + +-- Flattens lists of lists of S-expressions of arbitrary depth. +public fun deepFlatten (l) { + local res = [0, {}], curr = [res]; + + fun append (x) { + local new = x : {}; + + curr [0][1] := new; + curr [0] := new + } + + fun traverse (l) { + case l of + _ : _ -> iter (traverse, l) + | {} -> skip + | _ -> append (l) + esac + } + + traverse (l); + + res [1] +} \ No newline at end of file diff --git a/src/X86.lama b/src/X86.lama index 6cc80df0..846962d1 100644 --- a/src/X86.lama +++ b/src/X86.lama @@ -82,7 +82,6 @@ fun insnString (insn) { | I (n, x) -> sprintf ("%d(%s)", n, opndString (x)) esac } - case insn of Cltd -> "\tcltd\n" | Set (suf, s) -> sprintf ("\tset%s\t%s\n", suf, s) @@ -418,6 +417,7 @@ fun memOpnd (opnd) { case opnd of S (_) -> true | M (_) -> true + | I (_, _) -> true | _ -> false esac } @@ -482,6 +482,24 @@ fun suffix (op) { esac } +public fun eq(a, b) { + if (compare(a, b) == 0) then 1 else 0 fi +} + + +public fun contains(l, a) { + case l of (x:xs) -> + if (eq(x, a)) then true + else contains(xs, a) + fi + | {} -> false + esac +} + + fun callf(env, name, narg, code) { + case env.call(name, narg) of [env, ncode] -> [env, code <+> ncode] esac + } + -- Compiles stack machine code into a list of x86 instructions. Takes an environment -- and stack machine code, returns an updated environment and x86 code. fun compile (env, code) { @@ -490,14 +508,6 @@ fun compile (env, code) { fun ([env, scode], i) { local code = scode <+ Meta ("# " ++ showSMInsn (i) ++ "\n"); case i of - READ -> - case env.allocate of - [s, env] -> [env, code <+ Call ("Lread") <+ Mov (eax, s)] - esac - | WRITE -> - case env.pop of - [s, env] -> [env, code <+ Push (s) <+ Call ("Lwrite") <+ Pop (eax)] - esac (* Assignment *) -- Some guidelines for generating function calls: @@ -516,8 +526,75 @@ fun compile (env, code) { -- env.enterFunction to create a proper environment; -- 2. generate epilogue for END instruction. + CONST(n) -> + case env.allocate of + [s, env] -> [env, code <+> move(L(n), s)] + esac + | LD(x) -> + case env.allocate of + [s, env] -> [env, code <+> move(env.loc(x), s)] + esac + | ST(x) -> + case env.pop of + [c, env] -> [env, code <+> move(c, env.loc(x))] + esac + | DROP -> + case env.pop of [_, env] -> [env, code] + esac + | LDA(x) -> + case env.allocate of [s, env] -> + [env, code <+ Lea(env.loc(x), s)] + esac + | STI -> + case env.pop of [val, env] -> case env.peek of addr -> + [env, code <+> move(val, I(0, addr)) <+> move(val, addr)] + esac esac + + | LABEL(l) -> [ + if env.isBarrier then env.retrieveStack(l) else env fi, code <+ Label(l) + ] + | JMP(l) -> [env.setStack(l).setBarrier, code <+ Jmp(l)] + | CJMP(cond, l) -> + case env.pop of + [s, env] -> + [env.setStack(l), + code <+ Binop("cmp", L(0), s) <+ CJmp(cond, l) + ] + esac + | GLOBAL(x) -> [env.addGlobal(x), code] + | BEGIN(fl, nargs, nlocs) -> [env.enterFunction(fl, nlocs), code <+> prologue(fl)] + | END -> case env.epilogue of [env, end] -> [env, code <+> end] esac + | CALL(fl, nargs) -> case call(env, fl, nargs) of [env, ncode] -> [env, code <+> ncode] esac + | ARRAY(l) -> callf(env, "Barray", l, code) + | ELEM -> callf(env, "Belem", 2, code) + | STA -> callf(env, "Bsta", 2, code) + | STRING(s) -> case env.addString(s) of [env, name] -> + case env.allocate of [s, env] -> case call(env, "Bstring", 1) of [env, ncode] -> + [env, code <+> move(M("$" ++ name), s) <+> ncode] + esac esac esac + | BUILTIN(name, narg) -> callf(env, "B" ++ name, narg, code) + | BINOP(op) -> + case env.pop2 of + [a, b, env] -> case env.allocate of [n, newEnv] -> + if ({"==", ">", "<", "!=", ">=", "<="}.contains(op)) then + [newEnv, code <+> move(b, eax) <+ Binop("cmp", a, eax) <+> move(L(0), eax) <+ Set(suffix(op), "%al") <+> move(eax, n)] + elif (eq(op, "/")) then + [newEnv, code <+> move(b, eax) <+ Cltd <+ IDiv(a) <+> move(eax, n)] + elif (eq(op, "%")) then + [newEnv, code <+> move(b, eax) <+ Cltd <+ IDiv(a) <+> move(edx, n)] + elif (eq(op, "!!")) then + [newEnv, code <+> move(b, eax) <+ Binop(op, a, eax) <+> move(L(0), edx) <+ Binop("cmp", eax, edx) <+> move(L(0), eax) <+ Set("ne", "%al") <+> move(eax, n) ] + elif (eq(op, "&&")) then + [newEnv, + code <+> move(L(0), eax) <+> move(L(0), edx) <+ Binop("cmp", a, eax) + <+ Set("ne", "%al") <+ Binop("cmp", b, edx) <+ Set("ne", "%dl") <+ Binop(op, eax, edx) <+> move(edx, n) + ] + else + [newEnv, code <+> move(b, eax) <+ Binop(op, a, eax) <+> move(eax, n)] + fi + esac + esac | _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string) - (* End *) esac }, [env, emptyBuffer ()], code) }