feat: impl ifThenElse kinda

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
rvcas 2022-07-15 19:40:56 -04:00 committed by Kasey White
parent 83b9294ac1
commit 22f90bf07f
6 changed files with 82 additions and 25 deletions

View File

@ -1,4 +1,4 @@
(program
1.0.0
[ (force (builtin ifThenElse)) (con bool True) (con integer 1) (con string "yo") ]
[ (builtin ifThenElse) (con bool True) (con integer 1) (con string "yo") ]
)

View File

@ -92,12 +92,21 @@ fn main() -> anyhow::Result<()> {
Program::<NamedDeBruijn>::try_from(prog)?
};
let term = program.eval()?;
let (term, cost, _logs) = program.eval();
match term {
Ok(term) => {
let term: Term<Name> = term.try_into()?;
println!("{}", term.to_pretty());
}
Err(err) => {
eprintln!("{}", err);
}
}
println!("Costs - memory: {} & cpu: {}", cost.mem, cost.cpu);
}
},
}

View File

@ -4,7 +4,7 @@ use crate::{
builtins::DefaultFunction,
debruijn::{self, Converter},
machine::{
cost_model::{ExBudget, CostModel},
cost_model::{CostModel, ExBudget},
Machine,
},
};
@ -406,11 +406,17 @@ impl From<Term<FakeNamedDeBruijn>> for Term<NamedDeBruijn> {
}
impl Program<NamedDeBruijn> {
pub fn eval(&self) -> Result<Term<NamedDeBruijn>, crate::machine::Error> {
pub fn eval(
&self,
) -> (
Result<Term<NamedDeBruijn>, crate::machine::Error>,
ExBudget,
Vec<String>,
) {
let mut machine = Machine::new(CostModel::default(), ExBudget::default(), 200);
let (term, _, _) = machine.run(&self.term)?;
let term = machine.run(&self.term);
Ok(term)
(term, machine.ex_budget, machine.logs)
}
}

View File

@ -14,11 +14,12 @@ use self::{cost_model::CostModel, runtime::BuiltinRuntime};
pub struct Machine {
costs: CostModel,
ex_budget: ExBudget,
pub ex_budget: ExBudget,
frames: Vec<Context>,
slippage: u32,
env: Vec<Value>,
unbudgeted_steps: [u32; 8],
pub logs: Vec<String>,
}
impl Machine {
@ -30,20 +31,16 @@ impl Machine {
frames: vec![Context::NoFrame],
env: vec![],
unbudgeted_steps: [0; 8],
logs: vec![],
}
}
pub fn run(
&mut self,
term: &Term<NamedDeBruijn>,
) -> Result<(Term<NamedDeBruijn>, usize, Vec<String>), Error> {
pub fn run(&mut self, term: &Term<NamedDeBruijn>) -> Result<Term<NamedDeBruijn>, Error> {
let startup_budget = self.costs.machine_costs.get(StepKind::StartUp);
self.spend_budget(startup_budget)?;
let res = self.compute(term)?;
Ok((res, 0, vec![]))
self.compute(term)
}
fn compute(&mut self, term: &Term<NamedDeBruijn>) -> Result<Term<NamedDeBruijn>, Error> {
@ -106,7 +103,7 @@ impl Machine {
}
fn return_compute(&mut self, value: Value) -> Result<Term<NamedDeBruijn>, Error> {
// TODO: avoid unwrap if possible and just return an err when None
// avoid unwrap if possible and just return an err when None
// but honestly it should never be empty anyways because Machine
// is initialized with `Context::NoFrame`.
let frame = self.frames.last().cloned().unwrap();
@ -197,7 +194,9 @@ impl Machine {
match value {
Value::Delay(body) => self.compute(&body),
Value::Builtin { fun, term, runtime } => {
let force_term = Term::Force(Box::new(term));
let force_term = Term::Force(Box::new(dbg!(term)));
if runtime.is_all() {}
println!("{:#?}", runtime);
todo!()
}
@ -342,9 +341,14 @@ impl Value {
matches!(self, Value::Con(Constant::Integer(_)))
}
pub fn is_bool(&self) -> bool {
matches!(self, Value::Con(Constant::Bool(_)))
}
pub fn to_ex_mem(&self) -> i64 {
match self {
Value::Con(_) => todo!(),
// TODO: this is not 1
Value::Con(_) => 1,
Value::Delay(_) => 1,
Value::Lambda { .. } => 1,
Value::Builtin { .. } => 1,

View File

@ -569,7 +569,18 @@ impl BuiltinCosts {
DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(),
DefaultFunction::IfThenElse => ExBudget {
mem: self.if_then_else.mem.cost(
args[0].to_ex_mem(),
args[1].to_ex_mem(),
args[2].to_ex_mem(),
),
cpu: self.if_then_else.cpu.cost(
args[0].to_ex_mem(),
args[1].to_ex_mem(),
args[2].to_ex_mem(),
),
},
DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(),

View File

@ -48,12 +48,16 @@ impl BuiltinRuntime {
self.args.len() == self.fun.arity()
}
pub fn is_all(&self) -> bool {
self.args.is_empty()
}
pub fn call(&self) -> Result<Value, Error> {
self.fun.call(&self.args)
}
pub fn push(&mut self, arg: Value) -> Result<(), Error> {
self.fun.check_type(&arg)?;
self.fun.check_type(&arg, &self.args)?;
self.args.push(arg);
@ -102,7 +106,7 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(),
DefaultFunction::IfThenElse => 3,
DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(),
@ -131,7 +135,11 @@ impl DefaultFunction {
}
}
pub fn check_type(&self, arg: &Value) -> Result<(), Error> {
pub fn force_count() -> i32 {
3
}
pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> {
match self {
DefaultFunction::AddInteger => {
if arg.is_integer() {
@ -167,7 +175,17 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(),
DefaultFunction::IfThenElse => {
if args.is_empty() {
if arg.is_bool() {
return Ok(());
} else {
todo!("type error")
}
}
Ok(())
}
DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(),
@ -237,7 +255,16 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(),
DefaultFunction::IfThenElse => match args[0] {
Value::Con(Constant::Bool(condition)) => {
if condition {
Ok(args[1].clone())
} else {
Ok(args[2].clone())
}
}
_ => todo!("handle error"),
},
DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(),