Implemented [] as length operator

This commit is contained in:
Erin 2022-01-22 20:48:21 +01:00 committed by ondra05
parent 30ab0cf7da
commit 3f29fb09cd
2 changed files with 51 additions and 28 deletions

View file

@ -175,7 +175,7 @@ impl ExecEnv {
.map(|x| x.borrow().clone()) .map(|x| x.borrow().clone())
.unwrap_or(Value::Nul) .unwrap_or(Value::Nul)
} }
Len(_) => todo!("length"), Len(expr) => Value::Int(self.eval_expr(expr)?.len()),
// TODO: not too happy with constructing an artificial // TODO: not too happy with constructing an artificial
// Ident here. // Ident here.

View file

@ -122,36 +122,10 @@ impl Value {
match self { match self {
Value::Abool(a) => a as _, Value::Abool(a) => a as _,
Value::Bool(b) => b 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::Int(i) => i,
Value::Nul => consts::ANSWER, Value::Nul => consts::ANSWER,
Value::Str(text) => text.parse().unwrap_or(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, 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 { impl ops::Add for Value {