diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index 044e9e3d..bb79d335 100644 --- a/ablescript/src/interpret.rs +++ b/ablescript/src/interpret.rs @@ -175,7 +175,7 @@ impl ExecEnv { .map(|x| x.borrow().clone()) .unwrap_or(Value::Nul) } - Len(_) => todo!("length"), + Len(expr) => Value::Int(self.eval_expr(expr)?.len()), // TODO: not too happy with constructing an artificial // Ident here. diff --git a/ablescript/src/variables.rs b/ablescript/src/variables.rs index 5d42a198..9b85c184 100644 --- a/ablescript/src/variables.rs +++ b/ablescript/src/variables.rs @@ -122,36 +122,10 @@ impl Value { match self { Value::Abool(a) => a as _, Value::Bool(b) => b as _, - Value::Functio(func) => match func { - // Compares lengths of functions: - // BfFunctio - Sum of lengths of instructions and length of tape - // AbleFunctio - Sum of argument count and body length - // Eval - Length of input code - Functio::Bf { - instructions, - tape_len, - } => (instructions.len() + tape_len) as _, - Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _, - Functio::Chain { functios, kind } => { - let (lhs, rhs) = *functios; - match kind { - FunctioChainKind::Equal => { - Value::Int(Value::Functio(lhs).into_i32()) - + Value::Int(Value::Functio(rhs).into_i32()) - } - FunctioChainKind::ByArity => { - Value::Int(Value::Functio(lhs).into_i32()) - * Value::Int(Value::Functio(rhs).into_i32()) - } - } - .into_i32() - } - Functio::Eval(s) => s.len() as _, - }, Value::Int(i) => i, Value::Nul => consts::ANSWER, Value::Str(text) => text.parse().unwrap_or(consts::ANSWER), - Value::Cart(c) => c.len() as _, + _ => self.len() as _, } } @@ -410,6 +384,55 @@ impl Value { Value::Cart(c) => c, } } + + /// Get a lenght of a value + pub fn len(&self) -> i32 { + match self { + Value::Nul => 0, + Value::Str(s) => s.len() as _, + Value::Int(i) => i.count_zeros() as _, + Value::Bool(b) if *b => -2, + Value::Bool(_) => 2, + Value::Abool(a) => match a { + Abool::Never => -3, + Abool::Sometimes => { + if rand::thread_rng().gen() { + 3 + } else { + -3 + } + } + Abool::Always => 3, + }, + Value::Functio(f) => match f { + // Compares lengths of functions: + // BfFunctio - Sum of lengths of instructions and length of tape + // AbleFunctio - Sum of argument count and body length + // Eval - Length of input code + Functio::Bf { + instructions, + tape_len, + } => (instructions.len() + tape_len) as _, + Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _, + Functio::Chain { functios, kind } => { + let (lhs, rhs) = *functios.clone(); + match kind { + FunctioChainKind::Equal => { + Value::Int(Value::Functio(lhs).into_i32()) + + Value::Int(Value::Functio(rhs).into_i32()) + } + FunctioChainKind::ByArity => { + Value::Int(Value::Functio(lhs).into_i32()) + * Value::Int(Value::Functio(rhs).into_i32()) + } + } + .into_i32() + } + Functio::Eval(s) => s.len() as _, + }, + Value::Cart(c) => c.len() as _, + } + } } impl ops::Add for Value {