Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
98 changes: 93 additions & 5 deletions src/Expr.lama
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,103 @@ fun evalList (c, exprs) {
esac
}

fun eval (c@[s, w], expr) {
failure ("evalExpr not implemented\n")
fun evalDecls(c, exprs) {
fun evalDecl(c@[s, w], e) {
case e of
Var(x) -> let s = s.addNames(x) in [s, w]
| Fun(name, args, body) -> let s = s.addFunction(name, args, body) in [s, w]
esac
}

foldl(evalDecl, c, exprs)
}

fun evalArgs(s, args) {
fun evalArg(s, [name, value]) {
s.addName(name, value)
}

foldl(evalArg, s, args)
}

fun eval (c@[st, w], expr) {
case expr of
Assn (expr1, expr2) ->
let [c@[st, w], {ref, v}] = evalList(c, {expr1, expr2}) in
case ref of
Ref (x) -> [[st <- [x, v], w], v]
| ElemRef (arr, idx) -> arr[idx] := v; [c, v]
esac
| Seq (expr1, expr2) -> let [c1, v] = eval(c, expr1) in eval(c1, expr2)
| Skip -> [c, Void]
| If (cond, expr1, expr2) -> let [c, v] = eval(c, cond) in if v then eval(c, expr1) else eval(c, expr2) fi
| While (cond, body) ->
let [c1, n] = eval(c, cond) in
if n != 0
then
let [c2, _] = eval(c1, body) in
eval(c2, While(cond, body))
else
[c1, 0]
fi
| DoWhile (cond, body) -> evalList(c, {body, While (cond, body)})
| Var (x) -> [c, lookup(st, x)]
| Ref (x) -> [c, Ref (x)]
| Const (n) -> [c, n]
| Binop (op, expr1, expr2) ->
let [c, {l, r}] = evalList(c, {expr1, expr2}) in
[c, evalOp(op, l, r)]
| Ignore (expr1) -> let [c, v] = eval(c, expr1) in [c, Void]
| Scope (decl, stmt) ->
let st = st.enterScope in
let c@[st, w] = evalDecls([st, w], decl) in
let [[st, w], x] = eval(c, stmt) in
[[st.leaveScope, w], x]
| Call (name, args) ->
let Fun (argNames, body) = st.lookup(name) in
let [c@[st, w], vs] = c.evalList(args) in
let stIn = st.enterFunction in
let stIn = evalArgs(stIn, zip(argNames, vs)) in
let [[stIn, w], v] = eval([stIn, w], body) in
[[st.leaveFunction(stIn.getGlobal), w], v]
| Builtin (x, exprs) ->
let [c@[st, w], vals] = evalList (c, exprs) in
let [v, w] = evalBuiltin (x, vals, w) in
[[st, w], v]
| String (v) -> [c, v]
| Array (exprs) -> let [c, vals] = evalList (c, exprs) in [c, listArray (vals)]
| Elem (ea, ei) ->
let [c, arr] = eval (c, ea) in
let [c, idx] = eval (c, ei) in
let arr =
case arr of
Sexp (_, arr) -> arr
| arr -> arr
esac
in
[c, arr[idx]]
| ElemRef (ea, ei) ->
let [c, arr] = eval (c, ea) in
let [c, idx] = eval (c, ei) in
let arr =
case arr of
Sexp (_, arr) -> arr
| arr -> arr
esac
in
[c, ElemRef (arr, idx)]
| Sexp (tag, exprs) ->
let [c, args] = evalList (c, exprs) in
[c, Sexp (tag, listArray (args))]
esac
}

-- Evaluates a program with a given input and returns an output
public fun evalExpr (input, expr) {
case eval ([emptyState ().enterScope.addName ("read", Fun ({}, External))
.addName ("write", Fun ({"a"}, External))
.addName ("length", Fun ({"a"}, External)), createWorld (input)], expr) of
case eval ([emptyState ().enterScope--.addName ("read", Fun ({}, External))
--.addName ("write", Fun ({"a"}, External))
--.addName ("length", Fun ({"a"}, External))
, createWorld (input)], expr) of
[c, _] -> c.snd.getOutput
esac
}
79 changes: 59 additions & 20 deletions src/Parser.lama
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ fun binop (op) {
]
}

--var elseStmt = memo $ eta syntax (
-- kElif e=exp kThen s1=exp s2=elseStmt {fun (a) {If(e(Val), s1(a), s2(a))}} |
-- kElse s2=exp kFi {fun (a) {s2(a)}} |
-- kFi {fun (a) {assertVoid(a, Skip, loc)}}
--);

-- Helper parser: parses a (possible empty) list of items separated by ","
fun list0 (item) {
list0By (item, s(","))
Expand Down Expand Up @@ -104,6 +110,16 @@ fun distributeScope (expr, exprConstructor) {
| _ -> exprConstructor (expr)
esac
}

fun isBuiltin(name) {
case name of
"write" -> true
| "read" -> true
| "length" -> true
| "stringval" -> true
| _ -> false
esac
}

var primary = memo $ eta syntax (
-- S-expression
Expand All @@ -123,18 +139,41 @@ var primary = memo $ eta syntax (
-- decimal constant
loc=pos x=decimal {fun (a) {assertValue (a, Const (stringInt (x)), loc)}} |

-- identifier
loc=pos x=lident args=inbr[s("("), list0(syntax(e=exp {e(Val)})), s(")")]? {fun (a) {
case args of
None -> case a of
Ref -> Ref (x)
| Void -> Ignore (Var (x))
| _ -> Var (x)
esac
| Some (args) -> assertValue (a, Call (x, args), loc)
esac
}} |
$(failure ("the rest of primary parsing in not implemented\n"))),
-- identifier
loc=pos x=lident args=inbr[s("("), list0(syntax(e=exp {e(Val)})), s(")")]? {
fun (a) {
case args of
None -> case a of
Ref -> Ref (x)
| Void -> Ignore (Var (x))
| _ -> Var (x)
esac
| Some (args) -> assertValue (a,
if isBuiltin(x)
then Builtin (x, args)
else Call (x, args)
fi,
loc)
esac
}
} |
inbr[s("("), scopeExpr, s(")")] |
kSkip {fun (a) {assertVoid(a, Skip, loc)}} |
loc=pos kIf e=scopeExpr kThen s1=scopeExpr s2=elseStmt {fun (a) {If(e(Val), s1(a), s2(a))}} |
loc=pos kThen {fun (a) {assertVoid(a, Skip, loc)}} |
loc=pos kWhile e=scopeExpr kDo s=scopeExpr kOd {fun (a) {assertVoid(a, While (e(Val), s(Void)), loc)}} |
loc=pos kDo s=scopeExpr kWhile e=scopeExpr kOd {fun (a) {
distributeScope(s(Void), fun(s) {assertVoid(a, DoWhile(e(Val), s), loc)})
}} |
loc=pos kFor s1=scopeExpr s[","] e=scopeExpr s[","] s2=scopeExpr kDo s=scopeExpr kOd {fun (a) {
distributeScope(s1(Void), fun (s1) {assertVoid(a, Seq(s1, While (e(Val), Seq(s(Void), s2(Void)))), loc)})
}}
),
elseStmt = memo $ eta syntax (
kElif e=scopeExpr kThen s1=scopeExpr s2=elseStmt {fun (a) {If(e(Val), s1(a), s2(a))}} |
kElse s2=scopeExpr kFi {fun (a) {s2(a)}} |
kFi {fun (a) {assertVoid(a, Skip, loc)}}
),
basic = memo $ eta (expr ({[Right, {[s (":="),
fun (l, loc, r) {
fun (a) {assertValue (a, Assn (l (Ref), r (Val)), loc)}
Expand Down Expand Up @@ -170,14 +209,14 @@ var primary = memo $ eta syntax (
| _ -> Skip
esac)
}}),
definition = memo $ eta syntax (kVar ds=list[syntax (lident (s["="] e=basic {e (Val)})?)] s[";"] {Var (ds)} |
kFun name=lident
args=inbr[s("("), list0 (lident), s(")")]
body=inbr[s("{"), scopeExpr, s("}")] {
Fun (name, args, body (Weak))
}
),
exp = memo $ eta syntax (basic | s1=basic s[";"] s2=exp {fun (a) {Seq (s1 (Void), s2 (a))}});
definition = memo $ eta syntax (kVar ds=list[syntax (lident (s["="] e=basic {e (Val)})?)] s[";"] {Var (ds)} |
kFun name=lident
args=inbr[s("("), list0 (lident), s(")")]
body=inbr[s("{"), scopeExpr, s("}")] {
Fun (name, args, body (Weak))
}
),
exp = memo $ eta syntax (basic | s1=basic s[";"] s2=exp {fun (a) {Seq (s1 (Void), s2 (a))}});

-- Public top-level parser
public parse = syntax (s=scopeExpr {s (Void)});
Loading