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
8 changes: 6 additions & 2 deletions runtime64/runtime.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# include <stdio.h>

void Lwrite (long x) {
# define ALIGN_STACK asm ("andq $0xFFFFFFFFFFFFFFF0,%rsp")

void Lwrite (long x) {
ALIGN_STACK;
printf ("%ld\n", x);
}

long Lread () {
long result;


ALIGN_STACK;
scanf ("%ld", &result);

return result;
Expand Down
91 changes: 52 additions & 39 deletions src/Expr.lama
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
-- Expression evaluator

import List;
import State;
import World;

-- As association map which maps "\otimes" into "\oplus"
var ops = {
["+" , infix + ],
["-" , infix - ],
["*" , infix * ],
["/" , infix / ],
["%" , infix % ],
["==", infix ==],
["!=", infix !=],
["<" , infix < ],
["<=", infix <=],
[">" , infix > ],
[">=", infix >=],
["&&", infix &&],
["!!", infix !!]
};

var ops = {["+", infix +],
["-", infix -],
["*", infix *],
["/", infix /],
["%", infix %],
["==", infix ==],
["!=", infix !=],
["<", infix <],
["<=", infix <=],
[">", infix >],
[">=", infix >=],
["&&", infix &&],
["!!", infix !!]};
-- The evaluator for infix operators: takes an operator as a string
-- and two operand values, and returns the result
public fun evalOp (op, l, r) {
case assoc (ops, op) of
Some (f) -> f (l, r)
esac
case assoc(ops, op) of
Some(f) -> f(l, r)
esac
}

-- Evaluates an expression "expr" in a configuration "c".
-- A configuration is a pair of a state "s" and a world "w".
-- Returns a final configuration (if any)
Expand All @@ -48,29 +43,47 @@ public fun evalOp (op, l, r) {
-- Const (int) |
-- Binop (string, expr, expr) |
-- Ignore (expr)

-- Evaluates a list of expressions, properly threading a configurations.
-- Returns the final configuration and the list of values
fun evalList (c, exprs) {
case foldl (fun ([c, vals], e) {
case eval (c, e) of
[c, v] -> [c, v : vals]
esac
},
[c, {}],
exprs) of
[c, vals] -> [c, reverse (vals)]
esac
case foldl(fun ([c, vals], e) {
case eval(c, e) of
[c, v] -> [c, v : vals]
esac
}, [c, {}], exprs) of
[c, vals] -> [c, reverse(vals)]
esac
}

fun eval (c@[s, w], expr) {
failure ("evalExpr not implemented\n")
case expr of
Var(v) -> [c, s(v)]
| Ref(r) -> [c, Ref(r)]
| Const(i) -> [c, i]
| Skip -> [c, 0]
| Binop(op, expr1, expr2) -> let [c, {l, r}] = evalList(c, {expr1, expr2}) in [c, evalOp(op, l, r)]
| Assn(expr1, expr2) -> let [c@[s, w], {Ref(l), r}] = evalList(c, {expr1, expr2}) in [[s <- [l, r], w], r]
| Seq(expr1, expr2) -> let [c, v] = eval(c, expr1) in eval(c, expr2)
| Read(varname) -> let [r, w] = readWorld(w) in [[s <- [varname, r], w], 0]
| Write(expr1) -> let [c@[s, w], ref] = eval(c, expr1) in [[s, writeWorld(ref, w)], 0]
| If(cond, expr1, expr2) -> let [c, v] = eval(c, cond) in if v then eval(c, expr1) else eval(c, expr2) fi
| While(cond, expr) -> case eval(c, cond) of
[c, 0] -> [c, 0]
| [c, _] -> let [c, _] = eval(c, expr) in eval(c, While(cond, expr))
esac
| DoWhile(cond, expr) -> eval(c, Seq(expr, While(cond, expr)))
| Ignore(expr) -> [eval(c, expr)[0], 0]
| _ -> [c, 0]
esac
}


-- expr = Var (string) |
-- Const (int) |
-- Binop (string, expr, expr)
-- Evaluates a program with a given input and returns an output
public fun evalExpr (input, expr) {
case eval ([emptyState, createWorld (input)], expr) of
[c, _] -> c.snd.getOutput
esac
}
case eval([emptyState, createWorld(input)], expr) of
[c, _] -> c.snd.getOutput
| Var(v) -> input(v)
| Const(i) -> i
| Binop(op, expr1, expr2) -> evalOp(op, evalExpr(input, expr1), evalExpr(input, expr2))
esac
}
119 changes: 68 additions & 51 deletions src/Parser.lama
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-- Parser

import Ostap;
import Lexer;
import List;
Expand All @@ -10,73 +9,91 @@ import Collection;

-- Signals an error; takes an error message and location info
fun error (msg, loc) {
failure ("%s at %d:%d\n", msg, loc.fst, loc.snd)
failure("%s at %d:%d\n", msg, loc.fst, loc.snd)
}

-- An attribute-processing functions
-- Attributes are:
-- Val --- a plain value (aka "rvalue")
-- Ref --- a reference to a mutable cell (aka "lvalue")
-- Void --- no value (aka "void"/"unit")

-- Checks if a plain value "val" can be used in the context described by
-- the attribute "atr".
fun assertValue (atr, v, loc) {
case atr of
Ref -> error ("reference expected", loc)
| Void -> Ignore (v)
| _ -> v
esac
case atr of
Ref -> error("reference expected", loc)
| Void -> Ignore(v)
| _ -> v
esac
}

fun assertVoid (atr, v, loc) {
case atr of
Void -> v
| Val -> error ("value expected", loc)
| _ -> error ("reference expected", loc)
esac
case atr of
Void -> v
| Val -> error("value expected", loc)
| _ -> error("reference expected", loc)
esac
}

-- 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)
syntax (-l p -r)
}

fun binop (op) {
[syntax (pos -s[op]), fun (l, loc, r) {
fun (a) {
assertValue (a, Binop (op, l (Val), r (Val)), loc)
}
}
]
[syntax (pos -s[op]), fun (l, loc, r) {fun (a) {assertValue(a, Binop(op, l(Val), r(Val)), loc)}}]
}

var primary = memo $ eta syntax (
-- decimal constant
loc=pos x=decimal {fun (a) {assertValue (a, Const (stringInt (x)), loc)}} |

-- identifier
x=lident {fun (a) {
case a of
Ref -> Ref (x)
| Void -> Ignore (Var (x))
| _ -> Var (x)
esac
}} |
$(failure ("the rest of primary parsing in not implemented\n"))),
basic = memo $ eta (expr ({[Right, {[s (":="),
fun (l, loc, r) {
fun (a) {assertValue (a, Assn (l (Ref), r (Val)), loc)}
}]}],
[Left , map (binop, {"!!"})],
[Left , map (binop, {"&&"})],
[Nona , map (binop, {"==", "!=", "<", ">", "<=", ">="})],
[Left , map (binop, {"+", "-"})],
[Left , map (binop, {"*", "/", "%"})]
},
primary)),
exp = memo $ eta syntax (basic | s1=basic s[";"] s2=exp {fun (a) {Seq (s1 (Void), s2 (a))}});

var primary = memo $ eta syntax (
-- decimal constant
loc=pos x=decimal {fun (a) {assertValue(a, Const(stringInt(x)), loc)}} |

-- identifier
x=lident {
fun (a) {
case a of
Ref -> Ref(x)
| Void -> Ignore(Var(x))
| _ -> Var(x)
esac
}
} |

inbr[s("("), exp, s(")")] |

kRead e=inbr[s("("), lident, s(")")] {fun (a) {assertVoid(a, Read(e), loc)}} |

kWrite e=inbr[s("("), exp, s(")")] {fun (a) {assertVoid(a, Write(e(Val)), loc)}} |

kSkip {fun (a) {assertVoid(a, Skip, loc)}} |

kIf e=exp kThen s1=exp s2=ifTail {fun (a) {If(e(Val), s1(a), s2(a))}} |

kThen {fun (a) {assertVoid(a, Skip, loc)}} |

kWhile e=exp kDo s=exp kOd {fun (a) {assertVoid(a, While(e(Val), s(Void)), loc)}} |

kDo s=exp kWhile e=exp kOd {fun (a) {assertVoid(a, DoWhile(e(Val), s(Void)), loc)}} |

kFor i0=exp s[","] cond=exp s[","] step=exp kDo body=exp kOd {
fun (a) {assertVoid(a, Seq(i0(Void), While(cond(Val), Seq(body(Void), step(Void)))), loc)}
}
),
basic = memo $ eta (
expr({[Right, {[s(":="), fun (l, loc, r) {fun (a) {assertValue(a, Assn(l(Ref), r(Val)), loc)}}]}],
[Left, map(binop, {"!!"})],
[Left, map(binop, {"&&"})],
[Nona, map(binop, {"==", "!=", "<", ">", "<=", ">="})],
[Left, map(binop, {"+", "-"})],
[Left, map(binop, {"*", "/", "%"})]}, primary)
),
exp = memo $ eta syntax (
basic |
s1=basic s[";"] s2=exp {fun (a) {Seq(s1(Void), s2(a))}}
),
ifTail = memo $ eta syntax (
kElif e=exp kThen s1=exp s2=ifTail {fun (a) {If(e(Val), s1(a), s2(a))}} |

kElse s2=exp kFi {fun (a) {s2(a)}} |

kFi {fun (a) {assertVoid(a, Skip, loc)}}
);
-- Public top-level parser
public parse = syntax (s=exp {s (Void)});
public parse = syntax (s=exp {s(Void)});
Loading