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
17 changes: 16 additions & 1 deletion src/Builtins.lama
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
-- Builtins
import World;
import List;

fun exprToStr(e) {
case e of
Sexp(tag, args) -> if compare(args, {}) then
tag ++ " (" ++ foldl(fun(s, arg) {
if compare(s, "") then s ++ ", " ++ exprToStr(arg)
else exprToStr(arg)
fi
}, "", args) ++ ")"
else tag
fi |
_ -> e.string
esac
}

public fun evalBuiltin (name, args, w) {
case [name, args] of
["stringval", {a}] -> [a.string, w]
["stringval", {a}] -> [exprToStr(a), w]
| ["length" , {a@#array}] -> [a.length, w]
| ["length" , {a@#string}] -> [a.length, w]
| ["read" , {}] -> readWorld (w)
Expand Down
97 changes: 96 additions & 1 deletion src/Expr.lama
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,104 @@ fun evalList (c, exprs) {
esac
}

fun matchSexp(c@[s, w], val, sexpr) {
case sexpr of
Sexp(setag, sexprs) -> case setag of
"_" -> c |
_ -> case val of
Sexp(vtag, vals) -> if compare(vtag, setag) == 0 && size(vals) == size(sexprs) then
foldl(fun (c, [val, sexpr]) {
case c of
None -> None |
_ -> matchSexp(c, val, sexpr)
esac}, c, zip(vals, sexprs))
else None
fi |
_ -> None
esac
esac |
Var(x) -> [addName(s, x) <- [x, Val(val)], w]
esac
}

(* Assignment *)
fun eval (c@[s, w], expr) {
failure ("evalExpr not implemented\n")
case expr of
Assn (x, e) -> case evalList(c, {x, e}) of
[[s, w], {Ref(x), a}] -> [[s <- [x, Val(a)], w], a] |
[c, {ElemRef(arr, i), a}] -> arr[i] := a;[c, a]
esac |
Skip -> [c, Void] |
If (cond, e1, e2) -> case eval(c, cond) of
[c, val] -> if val then eval(c, e1) else eval(c, e2) fi
esac |
While (cond, body) -> case eval(c, cond) of
[c, val] -> if val then case eval(c, body) of [c, _] -> eval(c, expr) esac
else [c, Void]
fi
esac |
Repeat (body, cond) -> case evalList(c, {body, cond}) of
[c, _:val:_] -> if val then [c, Void] else eval(c, expr) fi
esac |
Seq (e1, e2) -> case evalList(c, {e1, e2}) of [c, _:res:_] -> [c, res] esac |
Var (x) -> [c, case s.lookupVal(x) of Val(v) -> v esac] |
Ref (x) -> [c, Ref(x)] |
Const (val) -> [c, val] |
Binop (op, lhs, rhs) -> case evalList(c, {lhs, rhs}) of
[c, lval:rval:_] -> [c, evalOp(op, lval, rval)]
esac |
Ignore (e) -> [eval(c, e).fst, Void] |
Scope(defs, e) -> case evalList([s.enterScope, w], defs) of
[c, _] -> case eval(c, e) of
[[s, w], val] -> [[s.leaveScope, w], val]
esac
esac |
Local(vars) -> [[s.addNames(vars), w], Void] |
Fun (f, args, body) -> [[s.addFunction(f, args, body), w], Void] |
Call (f, exprs) -> case s.lookupFun(f) of
Fun(args, body) -> case evalList(c, exprs) of
[[s, w], vals] -> case body of
External -> case evalBuiltin(f, vals, w) of
[res, w] -> [[s, w], res]
esac |
_ -> local s2 = foldl(fun (s1, [arg, val]) {
s1.addName(arg, Val(val))
}, s.enterFunction, zip(args, vals));
case eval([s2, w], body) of
[[s2, w], res] -> [[s.leaveFunction(s2.getGlobal), w], res]
esac
esac
esac
esac |
String(str) -> [c, str] |
Array (exprs) -> case evalList(c, exprs) of
[c, vals] -> [c, listArray(vals)]
esac |
Elem(arrExpr, indexExpr) -> case evalList(c, {arrExpr, indexExpr}) of
[c, {arr, index}] -> [c, arr[index]]
esac |
ElemRef(arrExpr, indexExpr) -> case evalList(c, {arrExpr, indexExpr}) of
[c, {arr, index}] -> [c, ElemRef(arr, index)]
esac |
Builtin(f, args) -> case evalList(c, args) of
[[s, w], vals] -> case evalBuiltin(f, vals, w) of
[res, w] -> [[s, w], res]
esac
esac |
Sexp(tag, args) -> case evalList(c, args) of
[c, vals] -> [c, Sexp(tag, vals)]
esac |
Case (x, pats) -> case eval(c, x) of
[c, val] -> case find(fun ([pat, _]) {
compare(matchSexp([enterScope(s), w], val, pat), None)
}, pats) of
None -> failure("Matching failed %s\n", val.string) |
Some([pat, e]) -> case eval(matchSexp([enterScope(s), w], val, pat), e) of
[[s, w], val] -> [[leaveScope(s), w], val]
esac
esac
esac
esac
}
(* End *)

Expand Down
4 changes: 3 additions & 1 deletion src/Lexer.lama
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public rSkip = createRegexp ("skip\\b", "skip"),
rCase = createRegexp ("case\\b", """case"""),
rOf = createRegexp ("of\\b", """of"""),
rEsac = createRegexp ("esac\\b", """esac"""),
rLength = createRegexp ("length\\b", """length""");
rLength = createRegexp ("length\\b", """length"""),
rString = createRegexp ("string\\b", """string""");

local whiteSpace = token (rWhiteSpace);

Expand All @@ -97,6 +98,7 @@ public kSkip = s (rSkip),
kOf = s (rOf),
kEsac = s (rEsac),
kLength = s (rLength),
kString = s (rString),
decimal = s (rDecimal),
chrlit = syntax (x=s[rChar] {case substring (x, 1, x.length - 2) of
"\\t" -> '\t'
Expand Down
44 changes: 39 additions & 5 deletions src/Parser.lama
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,38 @@ local primary = memo $ eta syntax (
esac
}} |
(* Assignment *)
$(failure ("the rest of primary parsing in not implemented\n"))),
loc=pos kSkip {fun(a) {assertVoid(a, Skip, loc)}} |
loc=pos kIf cond=exp kThen s1=exp s2=elseBranch {fun (a) {If (cond(Val), s1(a), s2(a))}} |
loc=pos kWhile cond=exp kDo body=scopeExpr kOd {
fun (a) { assertVoid(a, While (cond(Val), body(Void)), loc) }
} |
loc=pos kRepeat body=scopeExpr kUntil cond=inbr[s("("), exp, s(")")] {
fun (a) {
case body(Void) of
Scope(defs, e) -> assertVoid(a, Scope(defs, Repeat (e, cond(Val))), loc)
esac
}
} |
loc=pos kFor init=scopeExpr s[","] cond=exp s[","] step=exp kDo body=scopeExpr kOd {
fun (a) {
case init(Void) of
Scope(defs, e) -> assertVoid(a, Scope(defs, Seq (e, While (cond(Val), Seq (body(Void), step(Void))))), loc)
esac
}
} |
inbr[s("("), exp, s(")")] |
inbr[s("{"), scopeExpr, s("}")] |
loc=pos x=sexpLhs {fun (a) { assertValue (a, Sexp(x, {}), loc)}} |
loc=pos x=uident y=inbr[s("("), list0(syntax (e=exp {e(Val)})), s(")")] {fun (a) {assertValue (a, Sexp(x, y), loc)}} |
loc=pos kCase x=exp kOf pats=list0By[caseBranch, s("|")] kEsac {fun (a) { Case(x(Val), map(fun ([p, e]) {[p(Val), e(a)]}, pats)) }}
),
sexpLhs = memo $ eta syntax (uident|s["_"]),
caseBranch = memo $ eta syntax (loc=pos p=primary s["->"] e=exp {[p, e]}),
elseBranch = memo $ eta syntax (
loc=pos kFi {fun (a) { assertVoid(a, Skip, loc)}} |
-kElse exp -kFi|
kElif cond=exp kThen s1=exp s2=elseBranch {fun (a) {If (cond (Val), s1 (a), s2 (a))}}
),
(* End *)
basic = memo $ eta (expr ({[Right, singleton ([s (":="),
fun (l, loc, r) {
Expand All @@ -143,11 +174,14 @@ local primary = memo $ eta syntax (
[Left , map (binop, {"*", "/", "%"})]
},
postfix)),
postfix = memo $ eta syntax (loc=pos e=primary ps=(i=inbr[s("["), exp, s("]")] {Index (i (Val))} |
-s["."] kLength {Length}
)* {fun (a) {foldl (fun (e, p) {
postfixOp = memo $ eta syntax (i=inbr[s("["), exp, s("]")] {Index (i (Val))} |
-s["."] kLength {Length} |
-s["."] kString {String}
),
postfix = memo $ eta syntax (loc=pos e=primary ps= postfixOp* {fun (a) {foldl (fun (e, p) {
case p of
Length -> fun (a) {assertValue (a, Builtin ("length", singleton (e (Val))), loc)}
| String -> fun (a) {assertValue (a, Builtin ("stringval", singleton (e (Val))), loc)}
| Index (i) ->
fun (a) {
case a of
Expand All @@ -161,7 +195,7 @@ local primary = memo $ eta syntax (
),
scopeExpr = memo $ eta syntax (ds=definition* e=exp? {fun (a) {fun (e) {
case ds of
{} -> e
{} -> Scope({}, e)
| _ -> expandScope (ds, e)
esac
} (case e of
Expand Down
Loading