Skip to content

Commit

Permalink
make eval consume
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankBro committed Jul 14, 2024
1 parent 3f29ccf commit f21e4ce
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 38 deletions.
4 changes: 4 additions & 0 deletions ordo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ criterion = "0.5.1"
[[bench]]
name = "infer_benchmark"
harness = false

[[bench]]
name = "eval_benchmark"
harness = false
67 changes: 67 additions & 0 deletions ordo/benches/eval_benchmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use ordo::{eval, infer, parser::Parser};

pub fn eval_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("eval");

let expr = "let a = 1 in a";
group.bench_function(expr, |b| {
b.iter(|| {
let source = black_box(expr);
let parsed = Parser::expr(source).unwrap();
let mut env = black_box(infer::Env::default());
let typed = env.infer(parsed).unwrap();
let mut env = black_box(eval::Env::default());
let result = env.eval(typed).unwrap();
black_box(result)
})
});

let expr = "2 + 3 * 4";
group.bench_function(expr, |b| {
b.iter(|| {
let source = black_box(expr);
let parsed = Parser::expr(source).unwrap();
let mut env = black_box(infer::Env::default());
let typed = env.infer(parsed).unwrap();
black_box(typed)
})
});

let expr = "let add(a, b) = a + b in add(2, 3)";
group.bench_function(expr, |b| {
b.iter(|| {
let source = black_box(expr);
let parsed = Parser::expr(source).unwrap();
let mut env = black_box(infer::Env::default());
let typed = env.infer(parsed).unwrap();
black_box(typed)
})
});

let expr = "let add({a, b}) = a + b in let a = 2 in let b = 3 in add({a, b})";
group.bench_function(expr, |b| {
b.iter(|| {
let source = black_box(expr);
let parsed = Parser::expr(source).unwrap();
let mut env = black_box(infer::Env::default());
let typed = env.infer(parsed).unwrap();
black_box(typed)
})
});

let expr =
"let safe_div(n, d) = if d == 0 then :div_by_zero {} else :ok (n / d) in safe_div(4, 2)";
group.bench_function(expr, |b| {
b.iter(|| {
let source = black_box(expr);
let parsed = Parser::expr(source).unwrap();
let mut env = black_box(infer::Env::default());
let typed = env.infer(parsed).unwrap();
black_box(typed)
})
});
}

criterion_group!(benches, eval_benchmark);
criterion_main!(benches);
2 changes: 1 addition & 1 deletion ordo/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ impl Env {
pub fn process(&mut self, source: &str) -> Result<Output> {
let expr = Parser::repl(source)?;
let typed_expr = self.infer.infer(expr.clone())?;
let value = self.eval.eval(&expr)?;
let ty = self.infer.ty_to_string(typed_expr.ty()).unwrap();
let value = self.eval.eval(typed_expr)?;
let val = value.to_string();
Ok(Output { ty, val })
}
Expand Down
62 changes: 31 additions & 31 deletions ordo/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::BTreeMap;

use itertools::Itertools;

use crate::expr::{Expr, ExprAt, IntBinOp, Pattern, PatternAt, OK_LABEL};
use crate::expr::{Expr, ExprTypedAt, IntBinOp, Pattern, PatternTypedAt, OK_LABEL};

#[derive(Debug)]
pub enum Error {
Expand All @@ -17,8 +17,8 @@ pub enum Error {
LabelNotFound(String),
NoCase,
UnwrapNotVariant(Value),
PatternRecordRestNotEmpty(ExprAt),
InvalidPattern(ExprAt),
PatternRecordRestNotEmpty(ExprTypedAt),
InvalidPattern(ExprTypedAt),
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -46,8 +46,8 @@ type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Clone, Debug, PartialEq)]
pub struct Function {
env: Env,
params: Vec<PatternAt>,
body: ExprAt,
params: Vec<PatternTypedAt>,
body: ExprTypedAt,
}

impl fmt::Display for Function {
Expand All @@ -62,11 +62,10 @@ impl Function {
if self.params.len() != args.len() {
return Err(Error::UnexpectedNumberOfArguments);
}
for (i, arg) in args.into_iter().enumerate() {
let param = &self.params[i];
for (arg, param) in args.into_iter().zip(self.params.clone().into_iter()) {
self.env.eval_pattern(param, arg)?;
}
self.env.eval_inner(&self.body)
self.env.eval_inner(self.body.clone())
}
}

Expand Down Expand Up @@ -108,37 +107,37 @@ impl Value {
Value::Record(labels)
}

fn as_bool(&self) -> Result<bool> {
fn as_bool(self) -> Result<bool> {
match self {
Value::Bool(b) => Ok(*b),
Value::Bool(b) => Ok(b),
_ => Err(Error::NotBool(self.clone())),
}
}

fn as_int(&self) -> Result<i64> {
fn as_int(self) -> Result<i64> {
match self {
Value::Int(i) => Ok(*i),
Value::Int(i) => Ok(i),
_ => Err(Error::NotInt(self.clone())),
}
}

fn as_function(&self) -> Result<Function> {
fn as_function(self) -> Result<Function> {
match self {
Value::Function(fun) => Ok(fun.clone()),
Value::Function(fun) => Ok(fun),
_ => Err(Error::NotFunction(self.clone())),
}
}

fn as_record(&self) -> Result<&BTreeMap<String, Value>> {
fn as_record(self) -> Result<BTreeMap<String, Value>> {
match self {
Value::Record(record) => Ok(record),
_ => Err(Error::NotRecord(self.clone())),
}
}

fn as_variant(&self) -> Result<(&String, &Value)> {
fn as_variant(self) -> Result<(String, Value)> {
match self {
Value::Variant(label, value) => Ok((label, value)),
Value::Variant(label, value) => Ok((label, *value)),
_ => Err(Error::NotVariant(self.clone())),
}
}
Expand All @@ -164,13 +163,13 @@ pub struct Env {
}

impl Env {
pub fn eval(&mut self, expr: &ExprAt) -> Result<Value> {
pub fn eval(&mut self, expr: ExprTypedAt) -> Result<Value> {
let wrap = self.eval_inner(expr)?;
Ok(wrap.value())
}

fn eval_pattern(&mut self, pattern: &PatternAt, value: Value) -> Result<()> {
match pattern.expr.as_ref() {
fn eval_pattern(&mut self, pattern: PatternTypedAt, value: Value) -> Result<()> {
match *pattern.expr {
Pattern::Var(var) => {
self.vars.insert(var.clone(), value);
}
Expand All @@ -179,12 +178,12 @@ impl Env {
Expr::RecordEmpty => (),
_ => return Err(Error::PatternRecordRestNotEmpty(rest.clone())),
}
let labels_value = match value {
let mut labels_value = match value {
Value::Record(labels) => labels,
_ => return Err(Error::NotRecord(value)),
};
for (label, label_pattern) in labels {
match labels_value.get(label) {
match labels_value.remove(&label) {
None => return Err(Error::LabelNotFound(label.clone())),
Some(label_value) => {
self.eval_pattern(label_pattern, label_value.clone())?
Expand All @@ -197,10 +196,10 @@ impl Env {
Ok(())
}

fn eval_inner(&mut self, expr: &ExprAt) -> Result<Wrap> {
match expr.expr.as_ref() {
Expr::Bool(b) => Ok(Wrap::Value(Value::Bool(*b))),
Expr::Int(i) => Ok(Wrap::Value(Value::Int(*i))),
fn eval_inner(&mut self, expr: ExprTypedAt) -> Result<Wrap> {
match *expr.expr {
Expr::Bool(b) => Ok(Wrap::Value(Value::Bool(b))),
Expr::Int(i) => Ok(Wrap::Value(Value::Int(i))),
Expr::IntBinOp(op, lhs, rhs) => {
let lhs = match self.eval_inner(lhs)? {
Wrap::Value(value) => value.as_int()?,
Expand Down Expand Up @@ -243,7 +242,7 @@ impl Env {
Expr::Var(s) => {
let value = self
.vars
.get(s)
.get(&s)
.ok_or_else(|| Error::VarNotFound(s.clone()))?;
Ok(Wrap::Value(value.clone()))
}
Expand Down Expand Up @@ -284,7 +283,7 @@ impl Env {
};
let record = record.as_record()?;
let val = record
.get(label)
.get(&label)
.ok_or_else(|| Error::LabelNotFound(label.clone()))?;
Ok(Wrap::Value(val.clone()))
}
Expand All @@ -311,7 +310,7 @@ impl Env {
};
let record = record.as_record()?;
let mut record = record.clone();
record.remove(label);
record.remove(&label);
Ok(Wrap::Value(Value::Record(record)))
}
Expr::RecordEmpty => Ok(Wrap::Value(Value::Record(BTreeMap::new()))),
Expand Down Expand Up @@ -381,7 +380,7 @@ impl Env {

#[cfg(test)]
mod tests {
use crate::parser::Parser;
use crate::{infer, parser::Parser};

use super::{Env, Value};

Expand All @@ -403,7 +402,8 @@ mod tests {
];
for (expr_str, expected) in cases {
let expr = Parser::expr(expr_str).unwrap();
let actual = Env::default().eval(&expr).unwrap();
let expr = infer::Env::default().infer(expr).unwrap();
let actual = Env::default().eval(expr).unwrap();
assert_eq!(expected, actual);
}
}
Expand Down
4 changes: 2 additions & 2 deletions ordo/src/tests/ifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ fn pass(source_expr: &str, source_ty: &str, expected_val: Value) {
let expected = env.replace_ty_constants_with_vars(forall, ty);
let expr = Parser::expr(source_expr).unwrap();
let typed_expr = env.infer(expr.clone()).unwrap();
let actual = typed_expr.context.ty.ty;
let actual = typed_expr.context.ty.ty.clone();
let expected_ty = env.ty_to_string(&expected).unwrap();
let actual_ty = env.ty_to_string(&actual).unwrap();
assert_eq!(expected_ty, actual_ty);
let mut env = eval::Env::default();
let actual_val = env.eval(&expr).unwrap();
let actual_val = env.eval(typed_expr).unwrap();
assert_eq!(expected_val, actual_val);
}

Expand Down
8 changes: 4 additions & 4 deletions ordo/src/tests/unwraps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ impl Env {
let expected_ty = self.infer.replace_ty_constants_with_vars(forall, ty);
let expr = Parser::repl(source).unwrap();
let typed_expr = self.infer.infer(expr.clone()).unwrap();
let actual_ty = typed_expr.context.ty.ty;
let actual_ty = typed_expr.context.ty.ty.clone();
let expected_ty = self.infer.ty_to_string(&expected_ty).unwrap();
let actual_ty = self.infer.ty_to_string(&actual_ty).unwrap();
assert_eq!(expected_ty, actual_ty);
let _ = self.eval.eval(&expr).unwrap();
let _ = self.eval.eval(typed_expr).unwrap();
}
}

Expand All @@ -47,11 +47,11 @@ fn pass(source: &str, source_ty: &str, expected_val: Value) {
let expected_ty = env.infer.replace_ty_constants_with_vars(forall, ty);
let expr = Parser::expr(source).unwrap();
let typed_expr = env.infer.infer(expr.clone()).unwrap();
let actual_ty = typed_expr.context.ty.ty;
let actual_ty = typed_expr.context.ty.ty.clone();
let expected_ty = env.infer.ty_to_string(&expected_ty).unwrap();
let actual_ty = env.infer.ty_to_string(&actual_ty).unwrap();
assert_eq!(expected_ty, actual_ty);
let actual_val = env.eval.eval(&expr).unwrap();
let actual_val = env.eval.eval(typed_expr).unwrap();
assert_eq!(expected_val, actual_val);
}

Expand Down

0 comments on commit f21e4ce

Please sign in to comment.