From e8848ca3222404d300a4f33a2417f304aaffc0e9 Mon Sep 17 00:00:00 2001 From: Mell0r Date: Thu, 12 Sep 2024 01:19:41 +0300 Subject: [PATCH] done --- src/Expr.lama | 22 ++++++++++++++++++++-- src/SM.lama | 42 +++++++++++++++++++++++++++++++++++++----- src/Stmt.lama | 16 ++++++++++++---- src/X86.lama | 39 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/src/Expr.lama b/src/Expr.lama index b758035636..ec406f3060 100644 --- a/src/Expr.lama +++ b/src/Expr.lama @@ -14,5 +14,23 @@ import State; -- Binop (string, expr, expr) public fun evalExpr (st, expr) { - failure ("evalExpr not implemented\n") -} + case expr of + Var (varName) -> st (varName) + | Const (c) -> c + | Binop (op, expr1, expr2) -> case op of + "+" -> evalExpr(st, expr1) + evalExpr(st, expr2) + | "-" -> evalExpr(st, expr1) - evalExpr(st, expr2) + | "*" -> evalExpr(st, expr1) * evalExpr(st, expr2) + | "/" -> evalExpr(st, expr1) / evalExpr(st, expr2) + | "%" -> evalExpr(st, expr1) % evalExpr(st, expr2) + | ">" -> evalExpr(st, expr1) > evalExpr(st, expr2) + | "<" -> evalExpr(st, expr1) < evalExpr(st, expr2) + | "<=" -> evalExpr(st, expr1) <= evalExpr(st, expr2) + | ">=" -> evalExpr(st, expr1) >= evalExpr(st, expr2) + | "==" -> evalExpr(st, expr1) == evalExpr(st, expr2) + | "!=" -> evalExpr(st, expr1) != evalExpr(st, expr2) + | "&&" -> evalExpr(st, expr1) && evalExpr(st, expr2) + | "!!" -> evalExpr(st, expr1) !! evalExpr(st, expr2) + esac + esac +} \ No newline at end of file diff --git a/src/SM.lama b/src/SM.lama index 5e9e82bd9e..c4d90cfe38 100644 --- a/src/SM.lama +++ b/src/SM.lama @@ -27,7 +27,28 @@ 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 ([stack, state, world], i) { + case i of + BINOP (op) -> case stack of + y : x : stackRem -> [evalExpr(state, Binop (op, Const (x), Const (y))) : stackRem, state, world] + esac + | CONST (value) -> [value : stack, state, world] + | READ -> case readWorld (world) of + [value, worldNew] -> [value : stack, state, worldNew] + esac + | WRITE -> case stack of + value : stackRem -> [stackRem, state, writeWorld(value, world)] + esac + | LD (varName) -> [state(varName) : stack, state, world] + | ST (varName) -> case stack of + value : stackRem -> [stackRem, state <- [varName, value], world] + esac + esac + }, + c, + insns + ) } -- Runs a stack machine for a given input and a given program, returns an output @@ -36,14 +57,25 @@ public fun evalSM (input, insns) { } -- Compiles an expression into a stack machine code. --- Takes an expression, returns a list of stack machine instructions +-- Takes an expression, returns a list (of, possibly, lists) +-- of stack machine instructions fun compileExpr (expr) { - failure ("compileExpr not implemented\n") + case expr of + Var (varName) -> {LD (varName)} + | Const (value) -> {CONST (value)} + | Binop (op, expr1, expr2) -> compileExpr(expr1) +++ compileExpr(expr2) +++ {BINOP (op)} + esac } -- 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 (varName, varExpr) -> compileExpr(varExpr) +++ {ST (varName)} + | Read (destName) -> {READ, ST (destName)} + | Write (expr) -> compileExpr(expr) +++ {WRITE} + | Seq (stmt1, stmt2) -> compileSM(stmt1) +++ compileSM(stmt2) + | Skip -> {} + esac +} \ No newline at end of file diff --git a/src/Stmt.lama b/src/Stmt.lama index 67ec6db9e6..331accc5f3 100644 --- a/src/Stmt.lama +++ b/src/Stmt.lama @@ -16,11 +16,19 @@ import World; -- Read (string) | -- Write (expr) | -fun eval (c, stmt) { - failure ("Stmt eval not implemented\n") +fun eval (c@[s, w], stmt) { + case stmt of + Assn (varName, varExpr) -> [s <- [varName, evalExpr(s, varExpr)], w] + | Seq (stmt1, stmt2) -> eval(eval(c, stmt1), stmt2) + | Skip -> c + | Read (destName) -> case readWorld(w) of + [value, wNew] -> [s <- [destName, value], wNew] + esac + | Write (expr) -> [s, writeWorld(evalExpr(s, expr), w)] + esac } -- Evaluates a program with a given input and returns an output public fun evalStmt (input, stmt) { - eval ([emptyState, createWorld (input)], stmt).snd.getOutput -} + eval ([emptyState, createWorld(input)], stmt).snd.getOutput +} \ No newline at end of file diff --git a/src/X86.lama b/src/X86.lama index 5d962f4bcf..77089c2b28 100644 --- a/src/X86.lama +++ b/src/X86.lama @@ -272,6 +272,25 @@ fun suffix (op) { esac } +-- Puts operations in different types according to the way they compile into x86. +fun getOpType(op) { + case op of + "+" -> ResInSnd + | "-" -> ResInSnd + | "*" -> ResInSnd + | "/" -> Div + | "%" -> Mod + | ">=" -> Cmp + | "==" -> Cmp + | "!=" -> Cmp + | "<=" -> Cmp + | ">" -> Cmp + | "<" -> Cmp + | "!!" -> Bit + | "&&" -> Bit + 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) { @@ -295,7 +314,25 @@ fun compile (env, code) { case env.addGlobal (x).pop of [s, env] -> [env, code <+> move (s, env.loc (x))] esac - | _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string) + | CONST (x) -> case env.allocate of + [s, env] -> [env, code <+> move(L(x), s)] + esac + | BINOP (op) -> case env.pop2 of + [x, y, env] -> case env.allocate of + [dest, env] -> case getOpType(op) of + ResInSnd -> [env, code <+ Binop (op, x, y) <+> move(y, dest)] + | Div -> [env, code <+> move(y, eax) <+> move(L(0), edx) <+ IDiv (x) <+> move(eax, dest)] + | Mod -> [env, code <+> move(y, eax) <+> move(L(0), edx) <+ IDiv (x) <+> move(edx, dest)] + | Cmp -> [env, code <+ Binop ("cmp", x, y) <+ Set (suffix(op), "%al") <+> move(eax, dest)] + | Bit -> [ + env, + code <+ Binop ("cmp", L(0), x) <+ Set ("ne", "%al") + <+ Binop ("cmp", L(0), y) <+ Set ("ne", "%bl") + <+ Binop (op, eax, ebx) <+> move (ebx, dest) + ] + esac + esac + esac esac }, [env, emptyBuffer ()], code) }