Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/Expr.lama
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ import State;
-- Const (int) |
-- Binop (string, expr, expr)

public fun evalExpr (st, expr) {
failure ("evalExpr not implemented\n")
public fun evalExpr(st, expr) {
case expr of
Var(v) -> st(v)
| Const(i) -> i
| Binop(op, expr1, expr2) -> evalBinop(op, evalExpr(st, expr1), evalExpr(st, expr2))
esac
}

public fun evalBinop(op, expr1, expr2) {
case op of
"+" -> expr1 + expr2
| "-" -> expr1 - expr2
| "*" -> expr1 * expr2
| "/" -> expr1 / expr2
| "%" -> expr1 % expr2
| "<" -> expr1 < expr2
| ">" -> expr1 > expr2
| "<=" -> expr1 <= expr2
| ">=" -> expr1 >= expr2
| "==" -> expr1 == expr2
| "!=" -> expr1 != expr2
| "&&" -> expr1 && expr2
| "!!" -> expr1 !! expr2
esac
}
59 changes: 51 additions & 8 deletions src/Parser.lama
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,65 @@ import Ostap;
import Lexer;
import List;
import Fun;
import Matcher;

-- A parser of "something" in brackets; l, r are left and right
-- brackets as parsers, p --- a parser of "something"
fun inbr (l, p, r) {
syntax (-l p -r)
}

fun binop(l, op, r) {
Binop(op, l, r)
}

-- Primary expression
var primary = memo $ eta (decimal @ fun (x) {Const (stringInt (x))} |
lident @ fun (x) {Var (x)} |
inbr (s ("("), exp, s (")"))),
exp = memo $ eta (failure ("expression parsing not implemented\n"));
var primary = memo $ eta syntax (x=decimal {Const (stringInt (x))} |
x=lident {Var (x)} |
inbr[s("("), exp, s(")")]),
exp = memo $ eta (expr(
{ [Left, {
[s("!!"), binop],
[s("&&"), binop]}]
, [Nona, {
[s(">"), binop],
[s(">="), binop],
[s("=="), binop],
[s("<"), binop],
[s("<="), binop],
[s("!="), binop]}]
, [Left, {
[s("+"), binop],
[s("-"), binop]}]
, [Left, {
[s("*"), binop],
[s("/"), binop],
[s("%"), binop]}]
}, primary
));


var recursionIf = memo $ eta syntax (
kElif expr=exp kThen thn=parse els=recursionIf {If(expr, thn, els)} |
kElse s2=parse kFi {s2} |
kFi {Skip}
);

var stmt = memo $ eta syntax (
kWrite e=inbr[s("("), exp, s(")")] { Write(e) }|
kRead e=inbr[s("("), lident, s(")")] { Read(e) } |
kSkip {Skip} |
x=lident s[":="] y=exp { Assn(x, y) } |
kIf expr=exp kThen thn=parse els=recursionIf {If(expr, thn, els)} |
kThen {Skip} |
kWhile e=exp kDo s=parse kOd {While(e, s)} |
kDo s=parse kWhile e=exp kOd {DoWhile(e, s)} |
kFor i0=parse s[","] cond=exp s[","] step=parse kDo body=parse kOd {Seq(i0, While(cond, Seq(body, step)))}
);

var stmt = memo $ eta (failure ("statement parsing not implemented\n"));


-- Public top-level parser
public parse = stmt;
public parse = memo $ eta syntax (
stmt |
r=stmt s[";"] l=parse {Seq (r, l)}
);

97 changes: 95 additions & 2 deletions src/SM.lama
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,76 @@ fun initEvalEnv (insns) {
fun fromLabel (env, lab) {
env [0] (lab)
}
fun pushC (c, result){
c[0] := result : c[0]
}

fun popC (c){
case c[0] of
{} -> failure("empty stack")
| x: xs -> (
c[0] := xs;
x
)
esac
}
-- Stack machine interpreter. Takes an environment, an SM-configuration and a program,
-- returns a final configuration
fun eval (env, c, insns) {
failure ("SM eval not implemented\n")
case insns of
x: xs ->
case x of
LABEL(lb) -> eval(env, c, xs)
|JMP(l) -> eval(env, c, fromLabel(env,l))
|CJMP(exp,lb) -> (
var i = popC(c);
eval(env, c, case exp of
"z" -> if i == 0 then fromLabel(env,lb) else xs fi
|"nz" -> if i != 0 then fromLabel(env,lb) else xs fi
esac
)
)
| _ -> eval(env, processNoJmpInstr(c,x), xs)
esac
| {} -> c
esac
}



fun updateWorld (c, world){
c[2] := world
}
fun processNoJmpInstr (c, inst){
case inst of
READ -> let [result, world] = readWorld(c[2]) in (
pushC(c,result);
updateWorld(c, world);
c
)
| WRITE -> (
[c[0], c[1], writeWorld(popC(c), c[2])]
)
| BINOP(op) -> let y: x: ss = c[0] in (
var i = popC(c);
var j = popC(c);
pushC(c,evalBinop(op, i, j));
c
)
| LD(vr) -> (
pushC(c,c[1](vr));
c
)
| ST(vr) -> (
var i = popC(c);
c[1] := c[1] <- [vr, i];
c
)
| CONST(n) ->(
pushC(c,n);
c
)
esac
}

-- Runs a stack machine for a given input and a given program, returns an output
Expand Down Expand Up @@ -96,7 +161,11 @@ fun genLabels (env, n) {
-- 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(vr) -> singletonBuffer (LD (vr))
| Const(n) -> singletonBuffer (CONST (n))
| Binop(op, expr1, expr2) -> compileExpr(expr2) <+> compileExpr(expr1) <+ BINOP(op)
esac
}

-- Compiles a statement into a stack machine code.
Expand Down Expand Up @@ -137,6 +206,30 @@ public fun compileSM (stmt) {
esac
esac
esac
| If(expr,thn,els) ->
case env.genLabel of
[s2Lab, env] ->
case compile(lab, env, thn) of
[_, env, thnCode] -> (
case compile(lab, env, els) of
[_, env, elsCode] -> [true, env, compileExpr(expr) <+ CJMP ("z", s2Lab) <+> thnCode <+ JMP(lab) <+ LABEL(s2Lab) <+> elsCode]
esac
)
esac
esac
| While(expr, s) ->
case env.genLabels (2) of
[labelcontin, labelRepit, env] ->
case compile(labelcontin, env, s) of
[_,env, codeContinue] -> [false, env,
singletonBuffer (JMP (labelcontin)) <+ LABEL (labelRepit) <+> codeContinue
<+ LABEL (labelcontin) <+> compileExpr (expr) <+ CJMP ("nz", labelRepit)
]
esac
esac
| DoWhile(expr, s) ->
compile(lab, env, Seq(s, While(expr, s)))

| _ -> failure ("compileSM not implemented\n")
esac
}
Expand Down
21 changes: 19 additions & 2 deletions src/Stmt.lama
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,30 @@ import World;
-- Seq (stmt, stmt) |
-- Skip |
-- Read (string) |
-- Write (expr) |
-- Write (expr) | cout
-- If (expr, stmt, stmt) |
-- While (expr, stmt) |
-- DoWhile (stmt, expr)

fun eval (c, stmt) {
failure ("Stmt eval not implemented\n")
case stmt of
--Assn(name, val) -> c[0] := c[0] <- [name, evalExpr(c[0], val)]
Assn(name, test) -> c[0] := c[0] <- [name, evalExpr(c.fst, test)]
| Seq (inst1, inst2) -> eval(eval(c, inst1),inst2)
| Read(name) -> (
var i = readWorld(c[1]);
c[1] := i[1];
c[0] := c[0] <- [name, i[0]]
)
| Write(name) ->(
c[1] := writeWorld(evalExpr(c[0], name), c[1])
)
| If(expr, thn, els) -> if evalExpr(c[0], expr) != 0 then eval(c, thn) else eval(c, els) fi
| While(expr, body) -> if evalExpr(c[0], expr) != 0 then eval(eval(c, body), stmt) else c fi
| DoWhile (expr, body) -> eval(eval(c, body), While(expr, body))
| Skip -> c
esac;
c
}

-- Evaluates a program with a given input and returns an output
Expand Down
83 changes: 81 additions & 2 deletions src/X86_64.lama
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fun insnString (insn) {
| IDiv (s1) -> sprintf ("\tidivq\t%s\n", opndString (s1))
| Binop (op, s1, s2) -> sprintf ("\t%s\t%s,\t%s\n", binopString (op), opndString (s1), opndString (s2))
| Mov (s1, s2) -> sprintf ("\tmovq\t%s,\t%s\n", opndString (s1), opndString (s2))
| CMov (c, s1, s2) -> sprintf ("\tcmov%s\t%s,\t%s\n", c, opndString(s1), opndString(s2))
| Push (s) -> sprintf ("\tpushq\t%s\n", opndString (s))
| Pop (s) -> sprintf ("\tpopq\t%s\n", opndString (s))
| Ret -> "\tret\n"
Expand Down Expand Up @@ -242,7 +243,7 @@ fun dataDef (name) {
fun prologue (size) {
singletonBuffer (Push (rbp)) <+
Mov (rsp, rbp) <+
Binop ("-", L (wordSize*size), rsp)
Binop ("-", L ((wordSize * 2)*((size + 1) / 2)), rsp)
}

-- Generates function epilogue
Expand Down Expand Up @@ -292,6 +293,63 @@ fun suffix (op) {
esac
}

-- Check if in list
fun myCompare(l, r){
if compare(l,r) == 0 then
true
else
false
fi
}

-- fun pop (env) {
--fun move (from, to)
fun createBinop(op, code, env){
case env.pop2 of
[l, r, env] ->
case env.allocate of
[s, env] -> [
env,
if myCompare(op , "+") then
code <+ Mov(l, rax) <+ Binop(op,r,rax) <+ Mov(rax, s)
elif myCompare(op , "-") then
code <+ Mov(l, rax) <+ Binop(op,r,rax) <+ Mov(rax, s)
elif compare(op,"*") == 0 then
code <+ Mov(l, rax) <+ Binop(op,r,rax) <+ Mov(rax, s)
elif myCompare(op , "/") then
code <+ Mov(l, rax) <+ Cltd <+ IDiv(r) <+ Mov (rax, s)
elif myCompare(op , "%") then
code <+ Mov(l, rax) <+ Cltd <+ IDiv(r) <+ Mov (rdx, rax) <+ Mov (rax, s)
elif myCompare(op , "!!") then
code <+ Mov (L(1), r15) <+ Mov(L(0), rax)
<+ Mov (l, rdx) <+ Binop("cmp", L(0), rdx) <+ CMov("nz", r15, rax)
<+ Mov (r, rdx) <+ Binop("cmp", L(0), rdx) <+ CMov("nz", r15, rax) <+ Mov(rax, s)
elif myCompare(op, "&&") then
code <+ Mov (L(0), r15) <+ Mov(L(1), rax)
<+ Mov (l, rdx) <+ Binop("cmp", L(0), rdx) <+ CMov("z", r15, rax)
<+ Mov (r, rdx) <+ Binop("cmp", L(0), rdx) <+ CMov("z", r15, rax) <+ Mov(rax, s)
elif myCompare(op , "<") then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
elif myCompare(op , ">") then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
elif myCompare(op , "<=") then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
elif myCompare(op , ">=") then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
elif myCompare(op , "==")then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
elif myCompare(op , "!=") then
code <+ Binop("cmp", r, l) <+ Set(suffix (op), "%al") <+ Binop("&&", L(1), rax) <+ Mov(rax, s)
else
failure ("error operand"++op)
fi
]
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) {
Expand All @@ -307,6 +365,27 @@ fun compile (env, code) {
case env.pop of
[s, env] -> [env, code <+ Mov (s, rdi) <+ Call ("Lwrite")]
esac
| LD(x) ->
case env.allocate of
[s, env] -> [env, code <+> move(env.loc(x), s)]
esac
| ST(x) ->
case env.pop of
[s, env] -> [env.addGlobal(x), code <+> move(s, env.loc(x))]
esac
| CONST(vr) ->
case env.allocate of
[s, env] -> [env, code <+> move (L(vr), s)]
esac

| BINOP(op) ->
createBinop(op, code, env)
| LABEL(lab) -> [env, code <+ Label(lab)]
| JMP(lab) -> [env, code <+ Jmp(lab)]
| CJMP(exprType, lab) -> case env.pop of
[expr, env] -> [env, code <+ Binop("cmp", L (0), expr) <+ CJmp (exprType, lab)]
esac
| 1 -> [env, code]
| _ -> failure ("codegeneration for instruction %s is not yet implemented\n", i.string)
esac
}, [env, emptyBuffer ()], code)
Expand Down Expand Up @@ -338,4 +417,4 @@ public fun compileX86 (args, code) {

system ({"gcc -g -o ", args.getBaseName, " ", runtime, " ", asmFile}.stringcat)
esac
}
}