chore: switch discharge value back to the recursive form for simplicity

This commit is contained in:
rvcas 2023-04-12 20:20:28 -04:00 committed by Lucas
parent 564939ab61
commit ccc450659a
1 changed files with 76 additions and 148 deletions

View File

@ -1,33 +1,10 @@
use std::rc::Rc;
use crate::ast::{NamedDeBruijn, Term}; use crate::ast::{NamedDeBruijn, Term};
use super::value::{Env, Value}; use super::value::{Env, Value};
#[derive(Clone)]
enum PartialTerm {
Delay,
Lambda(Rc<NamedDeBruijn>),
Apply,
Force,
}
#[derive(Clone)]
enum DischargeStep {
DischargeValue(Value),
DischargeValueEnv(usize, Env, Rc<Term<NamedDeBruijn>>),
PopArgStack(PartialTerm),
}
pub(super) fn value_as_term(value: Value) -> Term<NamedDeBruijn> { pub(super) fn value_as_term(value: Value) -> Term<NamedDeBruijn> {
let mut stack = vec![DischargeStep::DischargeValue(value)]; match value {
Value::Con(x) => Term::Constant(x),
let mut arg_stack = vec![];
while let Some(stack_frame) = stack.pop() {
match stack_frame {
DischargeStep::DischargeValue(value) => match value {
Value::Con(x) => arg_stack.push(Term::Constant(x.clone())),
Value::Builtin { runtime, fun } => { Value::Builtin { runtime, fun } => {
let mut term = Term::Builtin(fun); let mut term = Term::Builtin(fun);
@ -38,122 +15,73 @@ pub(super) fn value_as_term(value: Value) -> Term<NamedDeBruijn> {
for arg in runtime.args { for arg in runtime.args {
term = term.apply(value_as_term(arg)); term = term.apply(value_as_term(arg));
} }
arg_stack.push(term)
} term
Value::Delay(body, env) => {
stack.push(DischargeStep::DischargeValueEnv(
0,
env.clone(),
Term::Delay(body.clone()).into(),
));
} }
Value::Delay(body, env) => with_env(0, env, Term::Delay(body)),
Value::Lambda { Value::Lambda {
parameter_name, parameter_name,
body, body,
env, env,
} => { } => with_env(
stack.push(DischargeStep::DischargeValueEnv(
0, 0,
env.clone(), env,
Term::Lambda { Term::Lambda {
parameter_name: parameter_name.clone(), parameter_name: NamedDeBruijn {
body: body.clone(), text: parameter_name.text.clone(),
index: 0.into(),
} }
.into(), .into(),
)); body,
}
}, },
DischargeStep::DischargeValueEnv(lam_cnt, env, term) => match term.as_ref() { ),
}
}
fn with_env(lam_cnt: usize, env: Env, term: Term<NamedDeBruijn>) -> Term<NamedDeBruijn> {
match term {
Term::Var(name) => { Term::Var(name) => {
let index: usize = name.index.into(); let index: usize = name.index.into();
if lam_cnt >= index { if lam_cnt >= index {
arg_stack.push(Term::Var(name.clone())); Term::Var(name)
} else { } else {
let env = env.get::<usize>(env.len() - (index - lam_cnt)).cloned(); env.get::<usize>(env.len() - (index - lam_cnt))
.cloned()
if let Some(v) = env { .map_or(Term::Var(name), value_as_term)
stack.push(DischargeStep::DischargeValue(v));
} else {
arg_stack.push(Term::Var(name.clone()));
}
} }
} }
Term::Lambda { Term::Lambda {
parameter_name, parameter_name,
body, body,
} => { } => {
stack.push(DischargeStep::PopArgStack(PartialTerm::Lambda( let body = with_env(lam_cnt + 1, env, body.as_ref().clone());
parameter_name.to_owned(),
)));
stack.push(DischargeStep::DischargeValueEnv(
lam_cnt + 1,
env,
body.to_owned(),
));
}
Term::Apply { function, argument } => {
stack.push(DischargeStep::PopArgStack(PartialTerm::Apply));
stack.push(DischargeStep::DischargeValueEnv(
lam_cnt,
env.clone(),
argument.to_owned(),
));
stack.push(DischargeStep::DischargeValueEnv(
lam_cnt,
env,
function.to_owned(),
));
}
Term::Delay(body) => {
stack.push(DischargeStep::PopArgStack(PartialTerm::Delay));
stack.push(DischargeStep::DischargeValueEnv(
lam_cnt,
env.clone(),
body.to_owned(),
));
}
Term::Force(body) => { Term::Lambda {
stack.push(DischargeStep::PopArgStack(PartialTerm::Force));
stack.push(DischargeStep::DischargeValueEnv(
lam_cnt,
env.clone(),
body.to_owned(),
));
}
rest => {
arg_stack.push(rest.to_owned());
}
},
DischargeStep::PopArgStack(term) => match term {
PartialTerm::Delay => {
let body = arg_stack.pop().unwrap();
arg_stack.push(Term::Delay(body.into()))
}
PartialTerm::Lambda(parameter_name) => {
let body = arg_stack.pop().unwrap();
arg_stack.push(Term::Lambda {
parameter_name, parameter_name,
body: body.into(), body: body.into(),
})
} }
PartialTerm::Apply => { }
let argument = arg_stack.pop().unwrap(); Term::Apply { function, argument } => {
let function = arg_stack.pop().unwrap(); let function = with_env(lam_cnt, env.clone(), function.as_ref().clone());
let argument = with_env(lam_cnt, env, argument.as_ref().clone());
arg_stack.push(function.apply(argument)); Term::Apply {
} function: function.into(),
PartialTerm::Force => { argument: argument.into(),
let body = arg_stack.pop().unwrap();
arg_stack.push(body.force())
}
},
} }
} }
arg_stack.pop().unwrap() Term::Delay(x) => {
let delay = with_env(lam_cnt, env, x.as_ref().clone());
Term::Delay(delay.into())
}
Term::Force(x) => {
let force = with_env(lam_cnt, env, x.as_ref().clone());
Term::Force(force.into())
}
rest => rest,
}
} }