Reimplement BF function declaration semantics

This commit is contained in:
Alex Bethel 2021-06-12 09:26:21 -05:00
parent ae3a7b7c8a
commit 1a8f17339e
2 changed files with 53 additions and 24 deletions

View file

@ -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<u8> = vec![];
for arg in args {
self.eval_expr(arg)?.bf_write(&mut input);
@ -236,7 +249,12 @@ impl ExecEnv {
println!("input = {:?}", input);
let mut output = vec![];
crate::brian::interpret_with_io(&body, &input as &[_], &mut output)
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(),

View file

@ -36,7 +36,10 @@ impl From<Abool> for bool {
#[derive(Debug, PartialEq, Clone)]
pub enum Functio {
BfFunctio(Vec<u8>),
BfFunctio {
instructions: Vec<u8>,
tape_len: usize,
},
AbleFunctio(Vec<Stmt>),
}
@ -94,10 +97,17 @@ impl Value {
}])
}),
Value::Functio(f) => stream.write_all(&[5]).and_then(|_| match f {
Functio::BfFunctio(f) => stream
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(&(f.len() as u32).to_le_bytes()))
.and_then(|_| stream.write_all(&f)),
.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")
)
}