Try out recursion for environment and frames
Co-authored-by: rvcas <x@rvcas.dev>
This commit is contained in:
parent
be38d1eebe
commit
234ab7c7cb
|
@ -1,5 +1,5 @@
|
||||||
(program
|
(program
|
||||||
1.0.0
|
1.0.0
|
||||||
[ (force (builtin ifThenElse)) (con string "yo") (con integer 3) (con integer 4) ]
|
[ (builtin subtractInteger ) (con integer 7) (con integer 4) ]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,7 @@ use self::{cost_model::CostModel, error::Type, runtime::BuiltinRuntime};
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
costs: CostModel,
|
costs: CostModel,
|
||||||
pub ex_budget: ExBudget,
|
pub ex_budget: ExBudget,
|
||||||
frames: Vec<Context>,
|
|
||||||
slippage: u32,
|
slippage: u32,
|
||||||
env: Vec<Value>,
|
|
||||||
unbudgeted_steps: [u32; 8],
|
unbudgeted_steps: [u32; 8],
|
||||||
pub logs: Vec<String>,
|
pub logs: Vec<String>,
|
||||||
}
|
}
|
||||||
|
@ -28,8 +26,6 @@ impl Machine {
|
||||||
costs,
|
costs,
|
||||||
ex_budget: initial_budget,
|
ex_budget: initial_budget,
|
||||||
slippage,
|
slippage,
|
||||||
frames: vec![Context::NoFrame],
|
|
||||||
env: vec![],
|
|
||||||
unbudgeted_steps: [0; 8],
|
unbudgeted_steps: [0; 8],
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
}
|
}
|
||||||
|
@ -40,22 +36,27 @@ impl Machine {
|
||||||
|
|
||||||
self.spend_budget(startup_budget)?;
|
self.spend_budget(startup_budget)?;
|
||||||
|
|
||||||
self.compute(term)
|
self.compute(Context::NoFrame, vec![], term)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute(&mut self, term: &Term<NamedDeBruijn>) -> Result<Term<NamedDeBruijn>, Error> {
|
fn compute(
|
||||||
|
&mut self,
|
||||||
|
context: Context,
|
||||||
|
env: Vec<Value>,
|
||||||
|
term: &Term<NamedDeBruijn>,
|
||||||
|
) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
match term {
|
match term {
|
||||||
Term::Var(name) => {
|
Term::Var(name) => {
|
||||||
self.step_and_maybe_spend(StepKind::Var)?;
|
self.step_and_maybe_spend(StepKind::Var)?;
|
||||||
|
|
||||||
let val = self.lookup_var(name.clone())?;
|
let val = self.lookup_var(name.clone(), env)?;
|
||||||
|
|
||||||
self.return_compute(val)
|
self.return_compute(context, val)
|
||||||
}
|
}
|
||||||
Term::Delay(body) => {
|
Term::Delay(body) => {
|
||||||
self.step_and_maybe_spend(StepKind::Delay)?;
|
self.step_and_maybe_spend(StepKind::Delay)?;
|
||||||
|
|
||||||
self.return_compute(Value::Delay(*body.clone()))
|
self.return_compute(context, Value::Delay(*body.clone(), env))
|
||||||
}
|
}
|
||||||
Term::Lambda {
|
Term::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
|
@ -63,29 +64,33 @@ impl Machine {
|
||||||
} => {
|
} => {
|
||||||
self.step_and_maybe_spend(StepKind::Lambda)?;
|
self.step_and_maybe_spend(StepKind::Lambda)?;
|
||||||
|
|
||||||
self.return_compute(Value::Lambda {
|
self.return_compute(
|
||||||
|
context,
|
||||||
|
Value::Lambda {
|
||||||
parameter_name: parameter_name.clone(),
|
parameter_name: parameter_name.clone(),
|
||||||
body: *body.clone(),
|
body: *body.clone(),
|
||||||
})
|
env,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Term::Apply { function, argument } => {
|
Term::Apply { function, argument } => {
|
||||||
self.step_and_maybe_spend(StepKind::Apply)?;
|
self.step_and_maybe_spend(StepKind::Apply)?;
|
||||||
|
|
||||||
self.push_frame(Context::FrameApplyArg(*argument.clone()));
|
self.compute(
|
||||||
|
Context::FrameApplyArg(env.clone(), *argument.clone(), Box::new(context)),
|
||||||
self.compute(function)
|
env,
|
||||||
|
function,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Term::Constant(x) => {
|
Term::Constant(x) => {
|
||||||
self.step_and_maybe_spend(StepKind::Constant)?;
|
self.step_and_maybe_spend(StepKind::Constant)?;
|
||||||
|
|
||||||
self.return_compute(Value::Con(x.clone()))
|
self.return_compute(context, Value::Con(x.clone()))
|
||||||
}
|
}
|
||||||
Term::Force(body) => {
|
Term::Force(body) => {
|
||||||
self.step_and_maybe_spend(StepKind::Force)?;
|
self.step_and_maybe_spend(StepKind::Force)?;
|
||||||
|
|
||||||
self.push_frame(Context::FrameForce);
|
self.compute(Context::FrameForce(Box::new(context)), env, body)
|
||||||
|
|
||||||
self.compute(body)
|
|
||||||
}
|
}
|
||||||
Term::Error => Err(Error::EvaluationFailure),
|
Term::Error => Err(Error::EvaluationFailure),
|
||||||
Term::Builtin(fun) => {
|
Term::Builtin(fun) => {
|
||||||
|
@ -93,42 +98,29 @@ impl Machine {
|
||||||
|
|
||||||
let runtime: BuiltinRuntime = (*fun).into();
|
let runtime: BuiltinRuntime = (*fun).into();
|
||||||
|
|
||||||
self.return_compute(Value::Builtin {
|
self.return_compute(
|
||||||
|
context,
|
||||||
|
Value::Builtin {
|
||||||
fun: *fun,
|
fun: *fun,
|
||||||
term: term.clone(),
|
term: term.clone(),
|
||||||
runtime,
|
runtime,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_compute(&mut self, value: Value) -> Result<Term<NamedDeBruijn>, Error> {
|
fn return_compute(
|
||||||
// frames should never be empty anyways because Machine
|
&mut self,
|
||||||
// is initialized with `Context::NoFrame`.
|
context: Context,
|
||||||
let frame = self
|
value: Value,
|
||||||
.frames
|
) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
.last()
|
match context {
|
||||||
.cloned()
|
Context::FrameApplyFun(function, ctx) => self.apply_evaluate(*ctx, function, value),
|
||||||
.expect("frames should never be empty");
|
Context::FrameApplyArg(arg_var_env, arg, ctx) => {
|
||||||
|
self.compute(Context::FrameApplyFun(value, ctx), arg_var_env, &arg)
|
||||||
match frame {
|
|
||||||
Context::FrameApplyFun(function) => {
|
|
||||||
self.pop_frame();
|
|
||||||
|
|
||||||
self.apply_evaluate(function, value)
|
|
||||||
}
|
|
||||||
Context::FrameApplyArg(arg) => {
|
|
||||||
self.pop_frame();
|
|
||||||
|
|
||||||
self.push_frame(Context::FrameApplyFun(value));
|
|
||||||
|
|
||||||
self.compute(&arg)
|
|
||||||
}
|
|
||||||
Context::FrameForce => {
|
|
||||||
self.pop_frame();
|
|
||||||
|
|
||||||
self.force_evaluate(value)
|
|
||||||
}
|
}
|
||||||
|
Context::FrameForce(ctx) => self.force_evaluate(*ctx, value),
|
||||||
Context::NoFrame => {
|
Context::NoFrame => {
|
||||||
if self.unbudgeted_steps[7] > 0 {
|
if self.unbudgeted_steps[7] > 0 {
|
||||||
self.spend_unbudgeted_steps()?;
|
self.spend_unbudgeted_steps()?;
|
||||||
|
@ -145,57 +137,76 @@ impl Machine {
|
||||||
match value {
|
match value {
|
||||||
Value::Con(x) => Term::Constant(x),
|
Value::Con(x) => Term::Constant(x),
|
||||||
Value::Builtin { term, .. } => term,
|
Value::Builtin { term, .. } => term,
|
||||||
Value::Delay(body) => self.discharge_value_env(Term::Delay(Box::new(body))),
|
Value::Delay(body, env) => self.discharge_value_env(env, Term::Delay(Box::new(body))),
|
||||||
Value::Lambda {
|
Value::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
body,
|
body,
|
||||||
} => self.discharge_value_env(Term::Lambda {
|
env,
|
||||||
|
} => self.discharge_value_env(
|
||||||
|
env,
|
||||||
|
Term::Lambda {
|
||||||
parameter_name: NamedDeBruijn {
|
parameter_name: NamedDeBruijn {
|
||||||
text: parameter_name.text,
|
text: parameter_name.text,
|
||||||
index: 0.into(),
|
index: 0.into(),
|
||||||
},
|
},
|
||||||
body: Box::new(body),
|
body: Box::new(body),
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discharge_value_env(&mut self, term: Term<NamedDeBruijn>) -> Term<NamedDeBruijn> {
|
fn discharge_value_env(
|
||||||
fn rec(lam_cnt: usize, t: Term<NamedDeBruijn>, this: &mut Machine) -> Term<NamedDeBruijn> {
|
&mut self,
|
||||||
match t {
|
env: Vec<Value>,
|
||||||
|
term: Term<NamedDeBruijn>,
|
||||||
|
) -> Term<NamedDeBruijn> {
|
||||||
|
let mut lam_cnt = 0;
|
||||||
|
let mut term = term;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
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 {
|
||||||
Term::Var(name)
|
return Term::Var(name);
|
||||||
} else {
|
} else {
|
||||||
this.env
|
return env
|
||||||
.get::<usize>(index - lam_cnt - 1)
|
.get::<usize>(index - lam_cnt)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map_or(Term::Var(name), |v| this.discharge_value(v))
|
.map_or(Term::Var(name), |v| self.discharge_value(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Term::Lambda {
|
Term::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
body,
|
body,
|
||||||
} => Term::Lambda {
|
} => {
|
||||||
|
term = *body;
|
||||||
|
lam_cnt += 1;
|
||||||
|
|
||||||
|
return Term::Lambda {
|
||||||
parameter_name,
|
parameter_name,
|
||||||
body: Box::new(rec(lam_cnt + 1, *body, this)),
|
body: Box::new(rec(lam_cnt + 1, *body, env, this)),
|
||||||
},
|
};
|
||||||
|
}
|
||||||
Term::Apply { function, argument } => Term::Apply {
|
Term::Apply { function, argument } => Term::Apply {
|
||||||
function: Box::new(rec(lam_cnt, *function, this)),
|
function: Box::new(rec(lam_cnt, *function, env, this)),
|
||||||
argument: Box::new(rec(lam_cnt, *argument, this)),
|
argument: Box::new(rec(lam_cnt, *argument, env, this)),
|
||||||
},
|
},
|
||||||
|
|
||||||
Term::Delay(x) => Term::Delay(Box::new(rec(lam_cnt, *x, this))),
|
Term::Delay(x) => Term::Delay(Box::new(rec(lam_cnt, *x, env, this))),
|
||||||
Term::Force(x) => Term::Force(Box::new(rec(lam_cnt, *x, this))),
|
Term::Force(x) => Term::Force(Box::new(rec(lam_cnt, *x, env, this))),
|
||||||
rest => rest,
|
rest => rest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rec(0, term, self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_evaluate(&mut self, value: Value) -> Result<Term<NamedDeBruijn>, Error> {
|
fn force_evaluate(
|
||||||
|
&mut self,
|
||||||
|
context: Context,
|
||||||
|
value: Value,
|
||||||
|
) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
match value {
|
match value {
|
||||||
Value::Delay(body) => self.compute(&body),
|
Value::Delay(body, env) => self.compute(context, env, &body),
|
||||||
Value::Builtin {
|
Value::Builtin {
|
||||||
fun,
|
fun,
|
||||||
term,
|
term,
|
||||||
|
@ -208,7 +219,7 @@ impl Machine {
|
||||||
|
|
||||||
let res = self.eval_builtin_app(fun, force_term, runtime)?;
|
let res = self.eval_builtin_app(fun, force_term, runtime)?;
|
||||||
|
|
||||||
self.return_compute(res)
|
self.return_compute(context, res)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BuiltinTermArgumentExpected(force_term))
|
Err(Error::BuiltinTermArgumentExpected(force_term))
|
||||||
}
|
}
|
||||||
|
@ -219,15 +230,17 @@ impl Machine {
|
||||||
|
|
||||||
fn apply_evaluate(
|
fn apply_evaluate(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
context: Context,
|
||||||
function: Value,
|
function: Value,
|
||||||
argument: Value,
|
argument: Value,
|
||||||
) -> Result<Term<NamedDeBruijn>, Error> {
|
) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
match function {
|
match function {
|
||||||
Value::Lambda { body, .. } => {
|
Value::Lambda { body, env, .. } => {
|
||||||
self.env.push(argument);
|
let mut e = env;
|
||||||
let term = self.compute(&body)?;
|
|
||||||
self.env.pop();
|
e.push(argument);
|
||||||
Ok(term)
|
|
||||||
|
self.compute(context, e, &body)
|
||||||
}
|
}
|
||||||
Value::Builtin {
|
Value::Builtin {
|
||||||
fun,
|
fun,
|
||||||
|
@ -246,7 +259,7 @@ impl Machine {
|
||||||
|
|
||||||
let res = self.eval_builtin_app(fun, t, runtime)?;
|
let res = self.eval_builtin_app(fun, t, runtime)?;
|
||||||
|
|
||||||
self.return_compute(res)
|
self.return_compute(context, res)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedBuiltinTermArgument(t))
|
Err(Error::UnexpectedBuiltinTermArgument(t))
|
||||||
}
|
}
|
||||||
|
@ -272,17 +285,8 @@ impl Machine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_frame(&mut self, frame: Context) {
|
fn lookup_var(&mut self, name: NamedDeBruijn, env: Vec<Value>) -> Result<Value, Error> {
|
||||||
self.frames.push(frame);
|
env.get::<usize>(env.len() - usize::from(name.index))
|
||||||
}
|
|
||||||
|
|
||||||
fn pop_frame(&mut self) {
|
|
||||||
self.frames.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lookup_var(&mut self, name: NamedDeBruijn) -> Result<Value, Error> {
|
|
||||||
self.env
|
|
||||||
.get::<usize>(usize::from(name.index) - 1)
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(Error::OpenTermEvaluated(Term::Var(name)))
|
.ok_or(Error::OpenTermEvaluated(Term::Var(name)))
|
||||||
}
|
}
|
||||||
|
@ -330,19 +334,20 @@ impl Machine {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Context {
|
enum Context {
|
||||||
FrameApplyFun(Value),
|
FrameApplyFun(Value, Box<Context>),
|
||||||
FrameApplyArg(Term<NamedDeBruijn>),
|
FrameApplyArg(Vec<Value>, Term<NamedDeBruijn>, Box<Context>),
|
||||||
FrameForce,
|
FrameForce(Box<Context>),
|
||||||
NoFrame,
|
NoFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Con(Constant),
|
Con(Constant),
|
||||||
Delay(Term<NamedDeBruijn>),
|
Delay(Term<NamedDeBruijn>, Vec<Value>),
|
||||||
Lambda {
|
Lambda {
|
||||||
parameter_name: NamedDeBruijn,
|
parameter_name: NamedDeBruijn,
|
||||||
body: Term<NamedDeBruijn>,
|
body: Term<NamedDeBruijn>,
|
||||||
|
env: Vec<Value>,
|
||||||
},
|
},
|
||||||
Builtin {
|
Builtin {
|
||||||
fun: DefaultFunction,
|
fun: DefaultFunction,
|
||||||
|
@ -375,7 +380,7 @@ impl Value {
|
||||||
Constant::Unit => 1,
|
Constant::Unit => 1,
|
||||||
Constant::Bool(_) => 1,
|
Constant::Bool(_) => 1,
|
||||||
},
|
},
|
||||||
Value::Delay(_) => 1,
|
Value::Delay(_, _) => 1,
|
||||||
Value::Lambda { .. } => 1,
|
Value::Lambda { .. } => 1,
|
||||||
Value::Builtin { .. } => 1,
|
Value::Builtin { .. } => 1,
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,7 +542,16 @@ impl BuiltinCosts {
|
||||||
.cpu
|
.cpu
|
||||||
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
||||||
},
|
},
|
||||||
DefaultFunction::SubtractInteger => todo!(),
|
DefaultFunction::SubtractInteger => ExBudget {
|
||||||
|
mem: self
|
||||||
|
.subtract_integer
|
||||||
|
.mem
|
||||||
|
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
||||||
|
cpu: self
|
||||||
|
.subtract_integer
|
||||||
|
.cpu
|
||||||
|
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
||||||
|
},
|
||||||
DefaultFunction::MultiplyInteger => todo!(),
|
DefaultFunction::MultiplyInteger => todo!(),
|
||||||
DefaultFunction::DivideInteger => todo!(),
|
DefaultFunction::DivideInteger => todo!(),
|
||||||
DefaultFunction::QuotientInteger => todo!(),
|
DefaultFunction::QuotientInteger => todo!(),
|
||||||
|
@ -550,7 +559,16 @@ impl BuiltinCosts {
|
||||||
DefaultFunction::ModInteger => todo!(),
|
DefaultFunction::ModInteger => todo!(),
|
||||||
DefaultFunction::EqualsInteger => todo!(),
|
DefaultFunction::EqualsInteger => todo!(),
|
||||||
DefaultFunction::LessThanInteger => todo!(),
|
DefaultFunction::LessThanInteger => todo!(),
|
||||||
DefaultFunction::LessThanEqualsInteger => todo!(),
|
DefaultFunction::LessThanEqualsInteger => ExBudget {
|
||||||
|
mem: self
|
||||||
|
.less_than_equals_integer
|
||||||
|
.mem
|
||||||
|
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
||||||
|
cpu: self
|
||||||
|
.less_than_equals_integer
|
||||||
|
.cpu
|
||||||
|
.cost(args[0].to_ex_mem(), args[1].to_ex_mem()),
|
||||||
|
},
|
||||||
DefaultFunction::AppendByteString => todo!(),
|
DefaultFunction::AppendByteString => todo!(),
|
||||||
DefaultFunction::ConsByteString => todo!(),
|
DefaultFunction::ConsByteString => todo!(),
|
||||||
DefaultFunction::SliceByteString => todo!(),
|
DefaultFunction::SliceByteString => todo!(),
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl DefaultFunction {
|
||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
DefaultFunction::AddInteger => 2,
|
DefaultFunction::AddInteger => 2,
|
||||||
DefaultFunction::SubtractInteger => todo!(),
|
DefaultFunction::SubtractInteger => 2,
|
||||||
DefaultFunction::MultiplyInteger => todo!(),
|
DefaultFunction::MultiplyInteger => todo!(),
|
||||||
DefaultFunction::DivideInteger => todo!(),
|
DefaultFunction::DivideInteger => todo!(),
|
||||||
DefaultFunction::QuotientInteger => todo!(),
|
DefaultFunction::QuotientInteger => todo!(),
|
||||||
|
@ -79,7 +79,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::ModInteger => todo!(),
|
DefaultFunction::ModInteger => todo!(),
|
||||||
DefaultFunction::EqualsInteger => todo!(),
|
DefaultFunction::EqualsInteger => todo!(),
|
||||||
DefaultFunction::LessThanInteger => todo!(),
|
DefaultFunction::LessThanInteger => todo!(),
|
||||||
DefaultFunction::LessThanEqualsInteger => todo!(),
|
DefaultFunction::LessThanEqualsInteger => 2,
|
||||||
DefaultFunction::AppendByteString => todo!(),
|
DefaultFunction::AppendByteString => todo!(),
|
||||||
DefaultFunction::ConsByteString => todo!(),
|
DefaultFunction::ConsByteString => todo!(),
|
||||||
DefaultFunction::SliceByteString => todo!(),
|
DefaultFunction::SliceByteString => todo!(),
|
||||||
|
@ -138,7 +138,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::ModInteger => todo!(),
|
DefaultFunction::ModInteger => todo!(),
|
||||||
DefaultFunction::EqualsInteger => todo!(),
|
DefaultFunction::EqualsInteger => todo!(),
|
||||||
DefaultFunction::LessThanInteger => todo!(),
|
DefaultFunction::LessThanInteger => todo!(),
|
||||||
DefaultFunction::LessThanEqualsInteger => todo!(),
|
DefaultFunction::LessThanEqualsInteger => 0,
|
||||||
DefaultFunction::AppendByteString => todo!(),
|
DefaultFunction::AppendByteString => todo!(),
|
||||||
DefaultFunction::ConsByteString => todo!(),
|
DefaultFunction::ConsByteString => todo!(),
|
||||||
DefaultFunction::SliceByteString => todo!(),
|
DefaultFunction::SliceByteString => todo!(),
|
||||||
|
@ -189,7 +189,7 @@ impl DefaultFunction {
|
||||||
pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> {
|
pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> {
|
||||||
match self {
|
match self {
|
||||||
DefaultFunction::AddInteger => arg.expect_type(Type::Integer),
|
DefaultFunction::AddInteger => arg.expect_type(Type::Integer),
|
||||||
DefaultFunction::SubtractInteger => todo!(),
|
DefaultFunction::SubtractInteger => arg.expect_type(Type::Integer),
|
||||||
DefaultFunction::MultiplyInteger => todo!(),
|
DefaultFunction::MultiplyInteger => todo!(),
|
||||||
DefaultFunction::DivideInteger => todo!(),
|
DefaultFunction::DivideInteger => todo!(),
|
||||||
DefaultFunction::QuotientInteger => todo!(),
|
DefaultFunction::QuotientInteger => todo!(),
|
||||||
|
@ -197,7 +197,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::ModInteger => todo!(),
|
DefaultFunction::ModInteger => todo!(),
|
||||||
DefaultFunction::EqualsInteger => todo!(),
|
DefaultFunction::EqualsInteger => todo!(),
|
||||||
DefaultFunction::LessThanInteger => todo!(),
|
DefaultFunction::LessThanInteger => todo!(),
|
||||||
DefaultFunction::LessThanEqualsInteger => todo!(),
|
DefaultFunction::LessThanEqualsInteger => arg.expect_type(Type::Integer),
|
||||||
DefaultFunction::AppendByteString => todo!(),
|
DefaultFunction::AppendByteString => todo!(),
|
||||||
DefaultFunction::ConsByteString => todo!(),
|
DefaultFunction::ConsByteString => todo!(),
|
||||||
DefaultFunction::SliceByteString => todo!(),
|
DefaultFunction::SliceByteString => todo!(),
|
||||||
|
@ -266,7 +266,16 @@ impl DefaultFunction {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::SubtractInteger => todo!(),
|
DefaultFunction::SubtractInteger => {
|
||||||
|
let args = (&args[0], &args[1]);
|
||||||
|
|
||||||
|
match args {
|
||||||
|
(Value::Con(Constant::Integer(arg1)), Value::Con(Constant::Integer(arg2))) => {
|
||||||
|
Ok(Value::Con(Constant::Integer(arg1 - arg2)))
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
DefaultFunction::MultiplyInteger => todo!(),
|
DefaultFunction::MultiplyInteger => todo!(),
|
||||||
DefaultFunction::DivideInteger => todo!(),
|
DefaultFunction::DivideInteger => todo!(),
|
||||||
DefaultFunction::QuotientInteger => todo!(),
|
DefaultFunction::QuotientInteger => todo!(),
|
||||||
|
@ -274,7 +283,16 @@ impl DefaultFunction {
|
||||||
DefaultFunction::ModInteger => todo!(),
|
DefaultFunction::ModInteger => todo!(),
|
||||||
DefaultFunction::EqualsInteger => todo!(),
|
DefaultFunction::EqualsInteger => todo!(),
|
||||||
DefaultFunction::LessThanInteger => todo!(),
|
DefaultFunction::LessThanInteger => todo!(),
|
||||||
DefaultFunction::LessThanEqualsInteger => todo!(),
|
DefaultFunction::LessThanEqualsInteger => {
|
||||||
|
let args = (&args[0], &args[1]);
|
||||||
|
|
||||||
|
match args {
|
||||||
|
(Value::Con(Constant::Integer(arg1)), Value::Con(Constant::Integer(arg2))) => {
|
||||||
|
Ok(Value::Con(Constant::Bool(arg1 <= arg2)))
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
DefaultFunction::AppendByteString => todo!(),
|
DefaultFunction::AppendByteString => todo!(),
|
||||||
DefaultFunction::ConsByteString => todo!(),
|
DefaultFunction::ConsByteString => todo!(),
|
||||||
DefaultFunction::SliceByteString => todo!(),
|
DefaultFunction::SliceByteString => todo!(),
|
||||||
|
|
Loading…
Reference in New Issue