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
4 changes: 2 additions & 2 deletions runtime64/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void* Bsta (void *x, long i, void *v) {
return v;
}

void Lwrite (long x) {
void Lwrite (long x) {
ALIGN_STACK;
printf ("%ld\n", x);
}
Expand All @@ -115,7 +115,7 @@ long Lread () {
long result;

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

return result;
}
Expand Down
151 changes: 98 additions & 53 deletions src/Expr.lama
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-- Expression evaluator

import List;
import Array;
import State;
Expand All @@ -9,30 +8,26 @@ import Parser;
import Builtins;

-- 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 @@ -57,58 +52,108 @@ public fun evalOp (op, l, r) {
-- ElemRef (expr, expr) |
-- 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
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
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)
foldl(fun (s, name) {s.addName(name, Val(0))}, state, names)
}

-- Helper function: adds a function in current scope
fun addFunction (state, name, args, body) {
state.addName (name, Fun (args, body))
state.addName(name, Fun(args, body))
}
fun addDecs (state, decs) {
foldl(fun (s, dec) {
case dec of
Var(names) -> s.addNames(names)
| Fun(name, args, body) -> s.addFunction(name, args, body)
esac
}, state, decs)
}
fun addArgs (state, args, vals) {
foldl(fun (s, [arg, value]) {s.addName(arg, Val(value))}, state, zip(args, vals))
}

-- 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, vl] -> [c, vl : vals]
esac
},
[c, {}],
exprs) of
[c, vals] -> [c, reverse (vals)]
esac
case foldl(fun ([c, vals], e) {
case eval(c, e) of
[c, vl] -> [c, vl : 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) -> lookupVal(s, v);
let Val(x) = lookup(s, v) in [c, x]
| Ref(r) -> lookupVal(s, r);
[c, Ref(r)]
| String(s) -> [c, s]
| Elem(arr, i) -> let [c, arr] = eval(c, arr) in
let [c, i] = eval(c, i) in
let arr = case arr of
Sexp(_, arr) -> arr
| arr -> arr
esac in [c, arr[i]]
| Const(i) -> [c, i]
| Skip -> [c, None]
| Binop(op, expr1, expr2) -> let [c, {l, r}] = evalList(c, {expr1, expr2}) in [c, evalOp(op, l, r)]
| Assn(expr1, expr2) -> let [[s, w], {ref, v}] = evalList(c, {expr1, expr2}) in
case ref of
Ref(r) -> lookupVal(s, r);
[[s <- [r, Val(v)], w], v]
| ElemRef(arr, idx) -> arr[idx] := v;
[[s, w], v]
esac
| ElemRef(arr, i) -> let [c, arr] = eval(c, arr) in
let [c, i] = eval(c, i) in
let arr = case arr of
Sexp(_, arr) -> arr
| arr -> arr
esac in [c, ElemRef(arr, i)]
| Sexp(tag, exprs) -> let [c, args] = evalList(c, exprs) in [c, Sexp(tag, listArray(args))]
| Seq(expr1, expr2) -> let [c, v] = eval(c, expr1) in eval(c, expr2)
| 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, None]
| [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], None]
| Scope(d, e) -> let [[s, w], v] = eval([s.enterScope.addDecs(d), w], e) in [[s.leaveScope, w], v]
| Call(f, expr) -> lookupFun(s, f);
let [[s, w], vals] = evalList(c, expr) in
let Fun(args, body) = s.lookup(f) in
let [[ss, w], v] = eval([s.enterFunction.addArgs(args, vals), w], body) in
[[leaveFunction(s, getGlobal(ss)), w], v]
| Builtin(f, expr) -> let [[s, w], vals] = evalList(c, expr) in let [v, w] = evalBuiltin(f, vals, w) in [[s, w], v]
| Array(exprs) -> let [c, vals] = evalList(c, exprs) in [c, listArray(vals)]
| _ -> failure("yo dumbass in expr.lama %s \n", expr.string)
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
[c, _] -> c.snd.getOutput
esac
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
}
Loading