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 (program
1.0.0 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)? 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()?; let term: Term<Name> = term.try_into()?;
println!("{}", term.to_pretty()); 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, builtins::DefaultFunction,
debruijn::{self, Converter}, debruijn::{self, Converter},
machine::{ machine::{
cost_model::{ExBudget, CostModel}, cost_model::{CostModel, ExBudget},
Machine, Machine,
}, },
}; };
@ -406,11 +406,17 @@ impl From<Term<FakeNamedDeBruijn>> for Term<NamedDeBruijn> {
} }
impl Program<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 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 { pub struct Machine {
costs: CostModel, costs: CostModel,
ex_budget: ExBudget, pub ex_budget: ExBudget,
frames: Vec<Context>, frames: Vec<Context>,
slippage: u32, slippage: u32,
env: Vec<Value>, env: Vec<Value>,
unbudgeted_steps: [u32; 8], unbudgeted_steps: [u32; 8],
pub logs: Vec<String>,
} }
impl Machine { impl Machine {
@ -30,20 +31,16 @@ impl Machine {
frames: vec![Context::NoFrame], frames: vec![Context::NoFrame],
env: vec![], env: vec![],
unbudgeted_steps: [0; 8], unbudgeted_steps: [0; 8],
logs: vec![],
} }
} }
pub fn run( pub fn run(&mut self, term: &Term<NamedDeBruijn>) -> Result<Term<NamedDeBruijn>, Error> {
&mut self,
term: &Term<NamedDeBruijn>,
) -> Result<(Term<NamedDeBruijn>, usize, Vec<String>), Error> {
let startup_budget = self.costs.machine_costs.get(StepKind::StartUp); let startup_budget = self.costs.machine_costs.get(StepKind::StartUp);
self.spend_budget(startup_budget)?; self.spend_budget(startup_budget)?;
let res = self.compute(term)?; self.compute(term)
Ok((res, 0, vec![]))
} }
fn compute(&mut self, term: &Term<NamedDeBruijn>) -> Result<Term<NamedDeBruijn>, Error> { 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> { 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 // but honestly it should never be empty anyways because Machine
// is initialized with `Context::NoFrame`. // is initialized with `Context::NoFrame`.
let frame = self.frames.last().cloned().unwrap(); let frame = self.frames.last().cloned().unwrap();
@ -197,7 +194,9 @@ impl Machine {
match value { match value {
Value::Delay(body) => self.compute(&body), Value::Delay(body) => self.compute(&body),
Value::Builtin { fun, term, runtime } => { 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); println!("{:#?}", runtime);
todo!() todo!()
} }
@ -342,9 +341,14 @@ impl Value {
matches!(self, Value::Con(Constant::Integer(_))) 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 { pub fn to_ex_mem(&self) -> i64 {
match self { match self {
Value::Con(_) => todo!(), // TODO: this is not 1
Value::Con(_) => 1,
Value::Delay(_) => 1, Value::Delay(_) => 1,
Value::Lambda { .. } => 1, Value::Lambda { .. } => 1,
Value::Builtin { .. } => 1, Value::Builtin { .. } => 1,

View File

@ -569,7 +569,18 @@ impl BuiltinCosts {
DefaultFunction::EqualsString => todo!(), DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(), DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => 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::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(), DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(), DefaultFunction::FstPair => todo!(),

View File

@ -48,12 +48,16 @@ impl BuiltinRuntime {
self.args.len() == self.fun.arity() self.args.len() == self.fun.arity()
} }
pub fn is_all(&self) -> bool {
self.args.is_empty()
}
pub fn call(&self) -> Result<Value, Error> { pub fn call(&self) -> Result<Value, Error> {
self.fun.call(&self.args) self.fun.call(&self.args)
} }
pub fn push(&mut self, arg: Value) -> Result<(), Error> { 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); self.args.push(arg);
@ -102,7 +106,7 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(), DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(), DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => todo!(), DefaultFunction::DecodeUtf8 => todo!(),
DefaultFunction::IfThenElse => todo!(), DefaultFunction::IfThenElse => 3,
DefaultFunction::ChooseUnit => todo!(), DefaultFunction::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(), DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => 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 { match self {
DefaultFunction::AddInteger => { DefaultFunction::AddInteger => {
if arg.is_integer() { if arg.is_integer() {
@ -167,7 +175,17 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(), DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(), DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => 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::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(), DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(), DefaultFunction::FstPair => todo!(),
@ -237,7 +255,16 @@ impl DefaultFunction {
DefaultFunction::EqualsString => todo!(), DefaultFunction::EqualsString => todo!(),
DefaultFunction::EncodeUtf8 => todo!(), DefaultFunction::EncodeUtf8 => todo!(),
DefaultFunction::DecodeUtf8 => 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::ChooseUnit => todo!(),
DefaultFunction::Trace => todo!(), DefaultFunction::Trace => todo!(),
DefaultFunction::FstPair => todo!(), DefaultFunction::FstPair => todo!(),