diff --git a/src/interpret.rs b/src/interpret.rs index 5775f738..eb6bb2e4 100644 --- a/src/interpret.rs +++ b/src/interpret.rs @@ -208,16 +208,26 @@ impl ExecEnv { args: _, body: _, } => todo!(), - StmtKind::BfFunctio { .. } => todo!(), - // This is missing from StmtKind after the interpreter - // rewrite; presumably, parsing is not yet implemented for - // it. ~~Alex - // StmtKind::BfFDeclaration { iden, body } => { - // self.decl_var( - // &iden.0, - // Value::Functio(Functio::BfFunctio(body.as_bytes().into())), - // ); - // } + StmtKind::BfFunctio { + iden, + tape_len, + code, + } => { + self.decl_var( + &iden.iden, + Value::Functio(Functio::BfFunctio { + instructions: code.to_owned(), + tape_len: tape_len + .as_ref() + .map(|tape_len| { + self.eval_expr(tape_len) + .and_then(|v| v.to_i32(&stmt.span)) + .map(|len| len as usize) + }) + .unwrap_or(Ok(crate::brian::DEFAULT_TAPE_SIZE_LIMIT))?, + }), + ); + } StmtKind::If { cond, body } => { if self.eval_expr(cond)?.to_bool() { return self.eval_stmts_hs(&body.block, true); @@ -228,7 +238,10 @@ impl ExecEnv { match func { Value::Functio(func) => { match func { - Functio::BfFunctio(body) => { + Functio::BfFunctio { + instructions, + tape_len, + } => { let mut input: Vec = vec![]; for arg in args { self.eval_expr(arg)?.bf_write(&mut input); @@ -236,11 +249,16 @@ impl ExecEnv { println!("input = {:?}", input); let mut output = vec![]; - crate::brian::interpret_with_io(&body, &input as &[_], &mut output) - .map_err(|e| Error { - kind: ErrorKind::BfInterpretError(e), - span: stmt.span.clone(), - })?; + crate::brian::Interpreter::from_ascii_with_tape_limit( + &instructions, + &input as &[_], + tape_len, + ) + .interpret_with_output(&mut output) + .map_err(|e| Error { + kind: ErrorKind::BfInterpretError(e), + span: stmt.span.clone(), + })?; // I guess Brainfuck functions write // output to stdout? It's not quite diff --git a/src/variables.rs b/src/variables.rs index fe8d3589..978635cc 100644 --- a/src/variables.rs +++ b/src/variables.rs @@ -36,7 +36,10 @@ impl From for bool { #[derive(Debug, PartialEq, Clone)] pub enum Functio { - BfFunctio(Vec), + BfFunctio { + instructions: Vec, + tape_len: usize, + }, AbleFunctio(Vec), } @@ -94,10 +97,17 @@ impl Value { }]) }), Value::Functio(f) => stream.write_all(&[5]).and_then(|_| match f { - Functio::BfFunctio(f) => stream - .write_all(&[0]) - .and_then(|_| stream.write_all(&(f.len() as u32).to_le_bytes())) - .and_then(|_| stream.write_all(&f)), + Functio::BfFunctio { + instructions, + tape_len: _, + } => { + // NOTE(Alex): Tape length should maybe be taken + // into account here. + stream + .write_all(&[0]) + .and_then(|_| stream.write_all(&(instructions.len() as u32).to_le_bytes())) + .and_then(|_| stream.write_all(&instructions)) + } Functio::AbleFunctio(_) => { todo!() } @@ -148,11 +158,12 @@ impl Display for Value { Value::Bool(v) => write!(f, "{}", v), Value::Abool(v) => write!(f, "{}", v), Value::Functio(v) => match v { - Functio::BfFunctio(source) => { + Functio::BfFunctio { instructions, tape_len } => { write!( f, - "{}", - String::from_utf8(source.to_owned()) + "({}) {}", + tape_len, + String::from_utf8(instructions.to_owned()) .expect("Brainfuck functio source should be UTF-8") ) }