From c95fbddbf11ed4fd7e8b00ff083041635811c3b2 Mon Sep 17 00:00:00 2001 From: Dmitrii Art Date: Thu, 8 Feb 2024 11:34:57 +0100 Subject: [PATCH 1/3] Add code from hw-1 --- src/Expr.lama | 25 ++++++++++++++++++++++++- src/SM.lama | 35 ++++++++++++++++++++++++++++++++--- src/Stmt.lama | 15 ++++++++++++++- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Expr.lama b/src/Expr.lama index b75803563..f0f9df534 100644 --- a/src/Expr.lama +++ b/src/Expr.lama @@ -14,5 +14,28 @@ import State; -- Binop (string, expr, expr) public fun evalExpr (st, expr) { - failure ("evalExpr not implemented\n") + case expr of + Var (x) -> st(x) + | Const (n) -> n + | Binop (op, e1, e2) -> evalBinop(op, evalExpr(st, e1), evalExpr(st, e2)) + esac + -- failure ("evalExpr not implemented\n") } + +public fun evalBinop(op, x, y) { + case op of + "+" -> x + y + | "-" -> x - y + | "*" -> x * y + | "/" -> x / y + | "%" -> x % y + | "<" -> x < y + | ">" -> x > y + | "<=" -> x <= y + | ">=" -> x >= y + | "==" -> x == y + | "!=" -> x != y + | "&&" -> x && y + | "||" -> x !! y + esac +} \ No newline at end of file diff --git a/src/SM.lama b/src/SM.lama index 5e9e82bd9..58f2636fa 100644 --- a/src/SM.lama +++ b/src/SM.lama @@ -27,7 +27,24 @@ public fun showSM (prg) { -- Stack machine interpreter. Takes an SM-configuration and a program, -- returns a final configuration fun eval (c, insns) { - failure ("SM eval not implemented\n") + foldl(fun (conf@[stack, st, w], ins) { + case ins of + READ -> + case readWorld(w) of + [v, wld] -> [v : stack, st, wld] + esac + | WRITE -> [tl(stack), st, writeWorld(hd(stack), w)] + | BINOP (op) -> + case stack of + y : x : rest -> [evalBinop(op, x, y) : rest, st, w] + | _ -> failure("Stack does not have enough elements. Required >=2 for BINOP.") + esac + | LD (x) -> [st(x) : stack, st, w] + | ST (x) -> [tl(stack), st <- [x, hd(stack)], w] + | CONST (n) -> [n : stack, st, w] + esac + }, c, insns) + -- failure ("SM eval not implemented\n") } -- Runs a stack machine for a given input and a given program, returns an output @@ -38,12 +55,24 @@ public fun evalSM (input, insns) { -- Compiles an expression into a stack machine code. -- Takes an expression, returns a list of stack machine instructions fun compileExpr (expr) { - failure ("compileExpr not implemented\n") + case expr of + Var (x) -> {LD (x)} + | Const (n) -> {CONST (n)} + | Binop (op, e1, e2) -> compileExpr(e1) +++ compileExpr(e2) +++ { BINOP (op) } + esac + -- failure ("compileExpr not implemented\n") } -- Compiles a statement into a stack machine code. -- Takes a statement, returns a list of stack machine -- instructions. public fun compileSM (stmt) { - failure ("compileSM not implemented\n") + case stmt of + Assn (x, expr) -> compileExpr(expr) +++ {ST (x)} + | Seq (stmt1, stmt2) -> compileSM(stmt1) +++ compileSM(stmt2) + | Skip -> {} + | Read (x) -> {READ, ST (x)} + | Write (expr) -> compileExpr(expr) +++ {WRITE} + esac + -- failure ("compileSM not implemented\n") } diff --git a/src/Stmt.lama b/src/Stmt.lama index 67ec6db9e..6edffeede 100644 --- a/src/Stmt.lama +++ b/src/Stmt.lama @@ -17,9 +17,22 @@ import World; -- Write (expr) | fun eval (c, stmt) { - failure ("Stmt eval not implemented\n") + -- c = [ state, world ] + case stmt of + Assn (x, expr) -> [c.fst <- [x, evalExpr(c.fst, expr)], c.snd] + | Seq (stmt1, stmt2) -> eval(eval(c, stmt1), stmt2) + | Skip -> c + | Read (x) -> + case readWorld(c.snd) of + [v, w] -> [c.fst <- [x, v], w] + esac + | Write (expr) -> [c.fst, writeWorld(evalExpr(c.fst, expr), c.snd)] + esac + + -- failure ("Stmt eval not implemented\n") } + -- Evaluates a program with a given input and returns an output public fun evalStmt (input, stmt) { eval ([emptyState, createWorld (input)], stmt).snd.getOutput From 183a54cb869430d8a1cecdfa093cb6e50e404319 Mon Sep 17 00:00:00 2001 From: Dmitrii Art Date: Thu, 8 Feb 2024 16:52:11 +0100 Subject: [PATCH 2/3] Add hw-2 implementation --- src/X86.lama | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/src/X86.lama b/src/X86.lama index 5d962f4bc..f1e23afc5 100644 --- a/src/X86.lama +++ b/src/X86.lama @@ -272,6 +272,79 @@ fun suffix (op) { esac } +fun compileAssociativeOp (op, x, y, env, code) { + if stackOpnd(x) && stackOpnd(y) then [env.push(y), code <+ Mov (x, eax) <+ Binop (op, eax, y)] + else [env.push(y), code <+ Binop (op, x, y)] + fi +} + +fun compileDivisionOp (op, x, y, env, code) { + -- we are actually doing (y / x) or (y % x) here + case op of + "/" -> [env.push(y), code <+ Mov (y, eax) <+ IDiv (x) <+ Mov (eax, y)] + | "%" -> [env.push(y), code <+ Mov (y, eax) <+ IDiv (x) <+ Mov (edx, y)] + esac +} + +fun compileLogicalOp (op, x, y, env, code) { + -- if y == 0: env.push(0) else: env.push(1) + -- if x == 0: env.push(0) else: env.push(1) + -- return env.pop2 -> [binx, biny, env]: compileBinop(op, binx, biny, env, code) + + fun compileConvertionIntToBoolean (pos, env, code) { + var dl = "%dl"; + + if stackOpnd(pos) then [env.push(pos), code <+ Mov(L (0), edx) <+ Mov (pos, eax) <+ Binop ("cmp", L (0), eax) <+ Set (suffix("!="), dl) <+ Mov (edx, pos)] + else [env.push(pos), code <+ Mov(L (0), edx) <+ Binop ("cmp", L (0), pos) <+ Set (suffix("!="), dl) <+ Mov (edx, pos)] + fi + } + + case compileConvertionIntToBoolean(y, env, code) of + [env, code] -> + case compileConvertionIntToBoolean(x, env, code) of + [env, code] -> + case env.pop2 of + [binx, biny, env] -> compileAssociativeOp(op, binx, biny, env, code) + esac + esac + esac +} + +fun compileComparisonOp(op, x, y, env, code) { + var dl = "%dl"; + + if (stackOpnd(x)) then [env.push(y), code <+ Mov (L (0), edx) <+ Mov (x, eax) <+ Binop ("cmp", eax, y) <+ Set (suffix(op), dl) <+ Mov (edx, y)] + else [env.push(y), code <+ Mov (L (0), edx) <+ Binop ("cmp", x, y) <+ Set (suffix(op), dl) <+ Mov (edx, y)] + fi +} + +fun compileBinop (op, env, code) { + case env.pop2 of + [x, y, env] -> + case op of + "+" -> compileAssociativeOp(op, x, y, env, code) + | "-" -> compileAssociativeOp(op, x, y, env, code) + | "*" -> compileAssociativeOp(op, x, y, env, code) + | "^" -> compileAssociativeOp(op, x, y, env, code) + + | "/" -> compileDivisionOp(op, x, y, env, code) + | "%" -> compileDivisionOp(op, x, y, env, code) + + | "&&" -> compileLogicalOp(op, x, y, env, code) + | "!!" -> compileLogicalOp(op, x, y, env, code) + + | "<" -> compileComparisonOp(op, x, y, env, code) + | "<=" -> compileComparisonOp(op, x, y, env, code) + | ">" -> compileComparisonOp(op, x, y, env, code) + | ">=" -> compileComparisonOp(op, x, y, env, code) + | "==" -> compileComparisonOp(op, x, y, env, code) + | "!=" -> compileComparisonOp(op, x, y, env, code) + + | _ -> failure ("codegeneration for binop %s is not yet implemented\n", op.string) + esac + 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) { @@ -289,12 +362,17 @@ fun compile (env, code) { esac | LD (x) -> case env.addGlobal (x).allocate of - [s, env] -> [env, code <+> move (env.loc (x), s)] - esac + [s, env] -> [env, code <+> move (env.loc (x), s)] + esac | ST (x) -> case env.addGlobal (x).pop of - [s, env] -> [env, code <+> move (s, env.loc (x))] - esac + [s, env] -> [env, code <+> move (s, env.loc (x))] + esac + | CONST (n) -> + case env.allocate of + [s, env] -> [env, code <+ Mov (L (n), s)] + esac + | BINOP (op) -> compileBinop(op, env, code) | _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string) esac }, [env, emptyBuffer ()], code) From 9908ae23ef8c590e5fd29fe9afd2fb6bce5c5503 Mon Sep 17 00:00:00 2001 From: Dmitrii Art Date: Mon, 11 Mar 2024 20:07:37 +0100 Subject: [PATCH 3/3] Add fixes to task A02 --- src/X86.lama | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/X86.lama b/src/X86.lama index f1e23afc5..224c15f48 100644 --- a/src/X86.lama +++ b/src/X86.lama @@ -281,8 +281,8 @@ fun compileAssociativeOp (op, x, y, env, code) { fun compileDivisionOp (op, x, y, env, code) { -- we are actually doing (y / x) or (y % x) here case op of - "/" -> [env.push(y), code <+ Mov (y, eax) <+ IDiv (x) <+ Mov (eax, y)] - | "%" -> [env.push(y), code <+ Mov (y, eax) <+ IDiv (x) <+ Mov (edx, y)] + "/" -> [env.push(y), code <+ Mov (y, eax) <+ Cltd <+ IDiv (x) <+ Mov (eax, y)] + | "%" -> [env.push(y), code <+ Mov (y, eax) <+ Cltd <+ IDiv (x) <+ Mov (edx, y)] esac } @@ -294,9 +294,7 @@ fun compileLogicalOp (op, x, y, env, code) { fun compileConvertionIntToBoolean (pos, env, code) { var dl = "%dl"; - if stackOpnd(pos) then [env.push(pos), code <+ Mov(L (0), edx) <+ Mov (pos, eax) <+ Binop ("cmp", L (0), eax) <+ Set (suffix("!="), dl) <+ Mov (edx, pos)] - else [env.push(pos), code <+ Mov(L (0), edx) <+ Binop ("cmp", L (0), pos) <+ Set (suffix("!="), dl) <+ Mov (edx, pos)] - fi + [env.push(pos), code <+ Mov(L (0), edx) <+ Binop ("cmp", L (0), pos) <+ Set (suffix("!="), dl) <+ Mov (edx, pos)] } case compileConvertionIntToBoolean(y, env, code) of @@ -313,7 +311,7 @@ fun compileLogicalOp (op, x, y, env, code) { fun compileComparisonOp(op, x, y, env, code) { var dl = "%dl"; - if (stackOpnd(x)) then [env.push(y), code <+ Mov (L (0), edx) <+ Mov (x, eax) <+ Binop ("cmp", eax, y) <+ Set (suffix(op), dl) <+ Mov (edx, y)] + if (stackOpnd(x) && stackOpnd(y)) then [env.push(y), code <+ Mov (L (0), edx) <+ Mov (x, eax) <+ Binop ("cmp", eax, y) <+ Set (suffix(op), dl) <+ Mov (edx, y)] else [env.push(y), code <+ Mov (L (0), edx) <+ Binop ("cmp", x, y) <+ Set (suffix(op), dl) <+ Mov (edx, y)] fi }