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

This commit is contained in:
Erin 2022-07-01 23:12:59 +02:00 committed by ondra05
parent 472b41cf16
commit e883010580

View file

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