Well, Able and Eval functios can now change loops flow!

trunk
ondra05 2022-07-01 23:12:59 +02:00
parent 4a2674a035
commit 32072e9dea
1 changed files with 36 additions and 23 deletions

View File

@ -282,8 +282,7 @@ impl ExecEnv {
}
Stmt::Call { expr, args } => {
let func = self.eval_expr(expr)?.into_functio();
self.fn_call(func, args, &stmt.span)?;
return self.fn_call(func, args, &stmt.span);
}
Stmt::Loop { body } => loop {
let res = self.eval_stmts_hs(body, true)?;
@ -396,7 +395,7 @@ impl ExecEnv {
func: Functio,
args: &[Spanned<Expr>],
span: &Range<usize>,
) -> Result<(), Error> {
) -> Result<HaltStatus, Error> {
// Arguments that are ExprKind::Variable are pass by
// reference; all other expressions are pass by value.
let args = args
@ -419,7 +418,7 @@ impl ExecEnv {
func: Functio,
args: &[ValueRef],
span: &Range<usize>,
) -> Result<(), Error> {
) -> Result<HaltStatus, Error> {
match func {
Functio::Bf {
instructions,
@ -446,6 +445,8 @@ impl ExecEnv {
stdout()
.write_all(&output)
.expect("Failed to write to stdout");
Ok(HaltStatus::Finished)
}
Functio::Able { params, body } => {
self.stack.push(Default::default());
@ -457,33 +458,45 @@ impl ExecEnv {
let res = self.eval_stmts_hs(&body, false);
self.stack.pop();
res?;
res
}
Functio::Builtin(b) => {
b.call(args).map_err(|e| Error::new(e, span.clone()))?;
Ok(HaltStatus::Finished)
}
Functio::Builtin(b) => b.call(args).map_err(|e| Error::new(e, span.clone()))?,
Functio::Chain { functios, kind } => {
use crate::value::functio::FunctioChainKind;
let (left_functio, right_functio) = *functios;
match kind {
FunctioChainKind::Equal => {
let (l, r) = args.split_at(args.len() / 2);
Ok(
match match kind {
FunctioChainKind::Equal => {
let (l, r) = args.split_at(args.len() / 2);
self.fn_call_with_values(left_functio, l, span)?;
self.fn_call_with_values(right_functio, r, span)?;
}
FunctioChainKind::ByArity => {
let (l, r) =
Self::deinterlace(args, (left_functio.arity(), right_functio.arity()));
(
self.fn_call_with_values(left_functio, l, span)?,
self.fn_call_with_values(right_functio, r, span)?,
)
}
FunctioChainKind::ByArity => {
let (l, r) = Self::deinterlace(
args,
(left_functio.arity(), right_functio.arity()),
);
self.fn_call_with_values(left_functio, &l, span)?;
self.fn_call_with_values(right_functio, &r, span)?;
}
};
}
Functio::Eval(code) => {
self.eval_stmts_hs(&crate::parser::parse(&code)?, false)?;
(
self.fn_call_with_values(left_functio, &l, span)?,
self.fn_call_with_values(right_functio, &r, span)?,
)
}
} {
(s, HaltStatus::Finished) => s,
(HaltStatus::Finished, s) => s,
(_, r) => r,
},
)
}
Functio::Eval(code) => self.eval_stmts_hs(&crate::parser::parse(&code)?, false),
}
Ok(())
}
fn deinterlace(args: &[ValueRef], arities: (usize, usize)) -> (Vec<ValueRef>, Vec<ValueRef>) {