From 553854cfd8e9d12bc35d429721622d63a609bf8d Mon Sep 17 00:00:00 2001 From: Arina Ivanova Date: Mon, 18 Nov 2024 02:11:02 +0300 Subject: [PATCH] first try --- src/Expr.lama | 27 ++++++++++++++++++-- src/SM.lama | 44 ++++++++++++++++++++++++-------- src/Stmt.lama | 17 +++++++++++-- src/X86_64.lama | 67 ++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 132 insertions(+), 23 deletions(-) diff --git a/src/Expr.lama b/src/Expr.lama index b758035636..ac6ca68f90 100644 --- a/src/Expr.lama +++ b/src/Expr.lama @@ -13,6 +13,29 @@ import State; -- Const (int) | -- Binop (string, expr, expr) -public fun evalExpr (st, expr) { - failure ("evalExpr not implemented\n") +public fun evalOp (op, l, r) { + case op of + "+" -> l + r + | "-" -> l - r + | "*" -> l * r + | "/" -> l / r + | "%" -> l % r + | ">" -> l > r + | "<" -> l < r + | ">=" -> l >= r + | "<=" -> l <= r + | "==" -> l == r + | "!=" -> l != r + | "&&" -> l && r + | "!!" -> l !! r + | op -> failure ("undefined operation ""%s""\n", op) + esac } + +public fun evalExpr (st, expr) { + case expr of + Var (strr) -> st (strr) + | Const (n) -> n + | Binop (op, exprL, exprR) -> evalOp(op, evalExpr(st, exprL), evalExpr(st, exprR)) + esac +} \ No newline at end of file diff --git a/src/SM.lama b/src/SM.lama index 5e9e82bd9e..5ce83d0dce 100644 --- a/src/SM.lama +++ b/src/SM.lama @@ -11,12 +11,12 @@ import Fun; -- string representation. public fun showSMInsn (i) { case i of - READ -> sprintf ("READ") - | WRITE -> sprintf ("WRITE") - | BINOP (s) -> sprintf ("BINOP %s", s) - | LD (x) -> sprintf ("LD %s", x) - | ST (x) -> sprintf ("ST %s", x) - | CONST (n) -> sprintf ("CONST %d", n) + READ -> sprintf ("READ") + | WRITE -> sprintf ("WRITE") + | BINOP (s) -> sprintf ("BINOP %s", s) + | LD (x) -> sprintf ("LD %s", x) + | ST (x) -> sprintf ("ST %s", x) + | CONST (n) -> sprintf ("CONST %d", n) esac } @@ -27,7 +27,21 @@ 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") + case insns of + {} -> c + | i:ns -> + case c of + [stack, s, w] -> case i of + READ -> case readWorld(w) of [z, w1] -> eval ([z:stack, s, w1], ns) esac + | WRITE -> case stack of z:stack1 -> eval ([stack1, s, writeWorld(z, w)], ns) esac + | BINOP (op) -> case stack of y:x:stack1 -> eval ([(evalOp(op, x, y)):stack1, s, w], ns) esac + | LD (x) -> eval([s(x):stack, s, w], ns) + | ST (strr) -> case stack of z:stack1 -> eval ([stack1, s <- [strr, z], w], ns) esac + | CONST (n) -> eval ([n:stack, s, w], ns) + esac + | _ -> failure ("no SM-comfiguration") + esac + esac } -- Runs a stack machine for a given input and a given program, returns an output @@ -38,12 +52,22 @@ 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, exprL, exprR) -> compileExpr(exprL) +++ compileExpr(exprR) +++ {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 (strr, expr) -> compileExpr(expr) +++ {ST (strr)} + | Seq (stmt1, stmt2) -> compileSM(stmt1) +++ compileSM(stmt2) + | Read (strr) -> {READ, ST (strr)} + | Write (expr) -> compileExpr(expr) +++ {WRITE} + | Skip -> {} + esac +} \ No newline at end of file diff --git a/src/Stmt.lama b/src/Stmt.lama index 67ec6db9e6..5f76b22754 100644 --- a/src/Stmt.lama +++ b/src/Stmt.lama @@ -17,10 +17,23 @@ import World; -- Write (expr) | fun eval (c, stmt) { - failure ("Stmt eval not implemented\n") + case c of [s, w] -> + case stmt of + Assn (strr, expr) -> [s <- [strr, evalExpr (s, expr)], w] + | Seq (stmt1, stmt2) -> eval(eval(c, stmt1), stmt2) + | Skip -> c + | Read (strr) -> + case readWorld (w) of + [z, w1] -> [s <- [strr, z], w1] + | _ -> failure ("no world") + esac + | Write (expr) -> [s, writeWorld(evalExpr(s, expr), w)] + esac + | _ -> failure ("no configuration") + esac } -- Evaluates a program with a given input and returns an output public fun evalStmt (input, stmt) { eval ([emptyState, createWorld (input)], stmt).snd.getOutput -} +} \ No newline at end of file diff --git a/src/X86_64.lama b/src/X86_64.lama index 9c03745cb8..03a20c3efa 100644 --- a/src/X86_64.lama +++ b/src/X86_64.lama @@ -292,19 +292,68 @@ fun compile (env, code) { fun ([env, scode], i) { var code = scode <+ Meta ("# " ++ showSMInsn (i) ++ "\n"); case i of - READ -> - case env.allocate of - [s, env] -> [env, code <+ Call ("Lread") <+ Mov (rax, s)] - esac - | WRITE -> - case env.pop of - [s, env] -> [env, code <+ Mov (s, rdi) <+ Call ("Lwrite")] - esac - | _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string) + READ -> + case env.allocate of + [s, env] -> [env, code <+ Call ("Lread") <+ Mov (rax, s)] + esac + | WRITE -> + case env.pop of + [s, env] -> [env, code <+ Mov (s, rdi) <+ Call ("Lwrite")] + esac + | LD (x) -> + case env.addGlobal(x).allocate of + [s, env] -> [env, code <+ Mov (env.loc(x), s)] + esac + | ST(x) -> + case env.addGlobal (x).pop of + [s, env] -> [env, code <+ Mov (s, env.loc (x))] + esac + | CONST(x) -> + case env.allocate of + [s, env] -> [env, code <+ Mov (L (x), s)] + esac + | BINOP (op) -> + case env.pop2 of + [x, y, env] -> + case env.allocate of + [s, env] -> [env, myBinop(code, x, y, op, s)] + esac + esac + | _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string) esac }, [env, emptyBuffer ()], code) } + +fun myBinop(code, x, y, op, s) { + case op of + "+" -> code <+ Binop (op, x, y) + | "-" -> code <+ Binop (op, x, y) + | "*" -> code <+ Binop (op, x, y) + | "/" -> code <+ Mov (y, rax) <+ IDiv (x) <+ Mov (rax, y) + | "%" -> code <+ Mov (y, rax) <+ IDiv (x) <+ Mov (rdx, y) + + | ">" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + | "<" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + | ">=" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + | "<=" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + | "==" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + | "!=" -> code <+ Binop("^", rdx, rdx) <+ Binop("cmp", x, y) <+ Set(suffix(op), "%dl") <+ Mov (rdx, s) + + | "&&" -> code + <+ Binop("^", rdx, rdx) <+ Binop("cmp", rdx, x) <+ Set(suffix("!="), "%dl") + <+ Binop("^", rax, rax) <+ Binop("cmp", rax, y) <+ Set(suffix("!="), "%al") + <+ Binop(op, rdx, rax) + <+ Mov (rax, s) + | "||" -> code + <+ Binop("^", rdx, rdx) <+ Binop("cmp", rdx, x) <+ Set(suffix("!="), "%dl") + <+ Binop("^", rax, rax) <+ Binop("cmp", rax, y) <+ Set(suffix("!="), "%al") + <+ Binop(op, rdx, rax) + <+ Mov (rax, s) + esac +} + + -- A top-level codegeneration function. Takes a stack machine program -- and returns x86 listing as a string public fun compileX86 (code) {