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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
*.i
*.s
!Makefile
~/runrime/gc_runtime.s
~/runrime/gc_runtime.s
*.ast
12 changes: 11 additions & 1 deletion src/Builtins.lama
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,14 @@ public fun evalBuiltin (name, args, w) {
| _ ->
failure ("no builtin ""%s"" or it can not be applied to %s\n", name, args.string)
esac
}
}

public fun isBuiltin(name) {
case name of
"stringval" -> true
| "length" -> true
| "read" -> true
| "write" -> true
| _ -> false
esac
}
160 changes: 141 additions & 19 deletions src/Expr.lama
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import World;
import Lexer;
import Parser;
import Builtins;
import Values;

-- As association map which maps "\otimes" into "\oplus"
var ops = {
Expand Down Expand Up @@ -58,29 +59,15 @@ public fun evalOp (op, l, r) {
-- Sexp (string, expr list) |
-- Builtin (string, expr list)

-- Helper function: checks that given name designates a regular variable in
-- a given state
fun lookupVal (state, name) {
case state.lookup (name) of
x@Val (_) -> x
| _ -> error (sprintf ("the name ""%s"" does not designate a variable", name), getLoc (name))
esac
}

-- Helper function: checks that given name designates a function in
-- a given state
fun lookupFun (state, name) {
case state.lookup (name) of
x@Fun (_, _) -> x
| _ -> error (sprintf ("the name ""%s"" does not designate a function", name), getLoc (name))
esac
}

-- Helper function: adds a bunch of regular variables current scope
fun addNames (state, names) {
foldl (fun (s, name) {s.addName (name, Val (0))}, state, names)
}

fun addNamesValues (state, names, values) {
foldl (fun (s, [name, value]) { s.addName(name, value) }, state, zip(names, values))
}

-- Helper function: adds a function in current scope
fun addFunction (state, name, args, body) {
state.addName (name, Fun (args, body))
Expand All @@ -100,8 +87,143 @@ fun evalList (c, exprs) {
esac
}

fun evalRef(c, expr) {
let [c, out] = eval(c, expr) in
case out of
Ref(_) -> [c, out]
| ArrRef(_, _) -> [c, out]
| _ -> failure("Expected ref, got %s", out.string)
esac
}

fun evalVal(c, expr) {
let [c, out] = eval(c, expr) in
case out of
Val(x) -> [c, x]
| _ -> failure("Expected val, got %s", out.string)
esac
}

fun evalComposite(c, expr) {
let [c, out] = eval(c, expr) in
case out of
Composite(x) -> [c, x]
| _ -> failure("Expected composite, got %s", out.string)
esac
}

fun evalFun(c, expr) {
let [c, out] = eval(c, expr) in
case out of
Fun(u, f) -> [c, [u, f]]
| _ -> failure("Expected fun, got %s", out.string)
esac
}

fun evalObject(c, expr) {
let [c, out] = eval(c, expr) in
case out of
Val(x) -> [c, out]
| Composite(x) -> [c, out]
| _ -> failure("Expected obj, got %s", out.string)
esac
}

fun evalVoid(c, expr) {
let [c, out] = eval(c, expr) in
case out of
None -> [c, out]
| _ -> failure("Expected void, got %s", out.string)
esac
}

fun eval (c@[s, w], expr) {
failure ("evalExpr not implemented\n")
case expr of
Assn(to, from) ->
let [c, ref] = evalRef(c, to) in
let [[s, w], output] = evalObject(c, from) in
case ref of
Ref(ref) -> [[s <- [ref, output], w], output]
| ArrRef(arr, idx) -> (tryAssign(arr, idx, output); [[s, w], output])
esac
| Seq(fst, snd) ->
let [c, out] = evalVoid(c, fst) in eval(c, snd)
| Skip -> [c, None]
| If(cond, tru, fls) ->
let [c, check] = evalVal(c, cond) in
if check then eval(c, tru) else eval(c, fls) fi
| While(cond, code) -> (
var continue, temp;
temp := evalVal(c, cond); c := temp[0]; continue := temp[1];
while continue do
temp := evalVoid(c, code); c := temp[0];
temp := evalVal(c, cond); c := temp[0]; continue := temp[1]
od;
[c, None]
)
| DoWhile(cond, code) -> (
var continue = true, temp;
while continue do
temp := evalVoid(c, code); c := temp[0];
temp := evalVal(c, cond); c := temp[0]; continue := temp[1]
od;
[c, None]
)
| Var(name) -> [c, s.lookup(name)]
| Ref(name) -> [c, Ref(name)]
| Const(x) -> [c, Val(x)]
| Binop(op, left, right) ->
let [c, leftV] = evalVal(c, left) in
let [c, rightV] = evalVal(c, right) in
[c, Val(evalOp(op, leftV, rightV))]
| Ignore(expr) -> let [c, dropped] = eval(c, expr) in [c, None]
| Scope(decls, stmt) ->
let s = s.enterScope in
let c = evalDecls([s, w], decls) in
let [[s, w], x] = eval(c, stmt) in
let s = s.leaveScope in
[[s, w], x]
| Call(nm, args) ->
let [c, [argdefs, code]] = evalFun(c, Var(nm)) in
let [[s, w], xs] = c.evalList(args) in
let s1 = s in
case code of
External -> let [rv, w] = evalBuiltin(nm, map(unval, xs), w) in [[s, w], Val(rv)]
| _ ->
let s = s.enterFunction.addNamesValues(argdefs, xs) in
let [[s, w], rv] = eval([s, w], code) in
let s = s1.leaveFunction(s.getGlobal) in
[[s, w], rv]
esac
| String(string) -> [[s, w], Composite(string)]
| Elem(arr, idx) ->
let [c, arr] = evalComposite(c, arr) in
let [c, idx] = evalVal(c, idx) in
[[s, w], mkBox(tryRead(arr, idx))]
| ElemRef(arr, idx) ->
let [c, arr] = evalComposite(c, arr) in
let [c, idx] = evalVal(c, idx) in
[c, ArrRef(arr, idx)]
| Array(xs) ->
let [[s, w], xs] = c.evalList(xs) in
[[s, w], Composite(listArray(map(unval, xs)))]
| Sexp(tag, args) ->
let [[s, w], args] = c.evalList(args) in
[[s, w], Composite(Sexp(tag, listArray(map(unval, args))))]
| _ -> failure("Unknown instruction: %s\n", expr.string)
esac
}

fun evalDecls(c, exprs) {
fun oneDecl(c@[s, w], expr) {
case expr of
Var(xs) -> let s = s.addNames(xs) in [s, w]
| Fun(nm, args, code) -> let s = s.addFunction(nm, args, code) in [s, w]
| _ -> failure("Unknown declaration: %s", expr.string)
esac
}

foldl(oneDecl, c, exprs)
}

-- Evaluates a program with a given input and returns an output
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ Builtins.o: World.o

State.o: Lexer.o Parser.o

Expr.o: State.o Builtins.o
Expr.o: State.o Builtins.o Values.o

SM.o: State.o World.o Expr.o Parser.o Lexer.o Builtins.o
SM.o: State.o World.o Expr.o Parser.o Lexer.o Builtins.o Values.o

X86.o: SM.o Manifest.o

Expand Down
51 changes: 39 additions & 12 deletions src/Parser.lama
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ fun binop (op) {
]
}

fun mkElifs(kind, elseBr, elifs) {
case elifs of
[] -> elseBr
| {} -> elseBr
| x:xs -> If(x[0](Val), x[1](kind), mkElifs(kind, elseBr, xs))
esac
}
fun getOrSkip(x, kind, loc) {
case x of
None -> assertVoid(kind, Skip, loc)
| Some(x) -> x(kind)
esac
}

-- Helper parser: parses a (possible empty) list of items separated by ","
fun list0 (item) {
list0By (item, s(","))
Expand Down Expand Up @@ -121,20 +135,33 @@ var primary = memo $ eta syntax (
loc=pos x=chrlit {fun (a) {assertValue (a, Const (x), loc)}} |

-- decimal constant
loc=pos x=decimal {fun (a) {assertValue (a, Const (stringInt (x)), loc)}} |
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"))),
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
}} |
(* Assignment *)
loc=pos kIf e=scopeExpr kThen tru=scopeExpr elifs=(-kElif scopeExpr -kThen scopeExpr)* fls=(-kElse scopeExpr)? kFi
{fun(a) { distributeScope(e(Val), fun(x) { If(x, tru(a), mkElifs(a, getOrSkip(fls, a, loc), elifs))}) }} |
loc=pos kWhile e=scopeExpr kDo c=scopeExpr kOd
{fun(a) { assertVoid(a, While(e(Val), c(Void)), loc) }} |
loc=pos kDo c=scopeExpr kWhile e=scopeExpr kOd
{fun(a) { distributeScope(c(Void), fun(x) { assertVoid(a, DoWhile(e(Val), x), loc) }) }} |
loc=pos kSkip {fun(a) { assertVoid(a, Skip, loc) }} |
loc=pos kFor ini=scopeExpr s[","] cond=scopeExpr s[","] act=scopeExpr kDo c=scopeExpr kOd
{fun(a) { distributeScope(ini(Void), fun(x) { Seq(x, assertVoid(a, While(cond(Val), Seq(c(Void), act(Void))), loc)) }) } } |
e=inbr[s("("), scopeExpr, s(")")]
),
(* End *)
basic = memo $ eta (expr ({[Right, {[s (":="),
fun (l, loc, r) {
fun (a) {assertValue (a, Assn (l (Ref), r (Val)), loc)}
Expand Down
Loading