forked from AbleScript/ablescript
Length by empty square braces
Reviewed-on: https://git.ablecorp.us:443/AbleScript/able-script/pulls/2
This commit is contained in:
commit
159a462b0a
|
@ -190,6 +190,7 @@ pub enum ExprKind {
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
index: Box<Expr>,
|
index: Box<Expr>,
|
||||||
},
|
},
|
||||||
|
Len(Box<Expr>),
|
||||||
Variable(String),
|
Variable(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,7 @@ impl ExecEnv {
|
||||||
.map(|x| x.borrow().clone())
|
.map(|x| x.borrow().clone())
|
||||||
.unwrap_or(Value::Nul)
|
.unwrap_or(Value::Nul)
|
||||||
}
|
}
|
||||||
|
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.
|
||||||
|
|
|
@ -195,10 +195,7 @@ impl<'source> Parser<'source> {
|
||||||
|
|
||||||
Token::LeftBracket => match buf.take() {
|
Token::LeftBracket => match buf.take() {
|
||||||
Some(buf) => Ok(Expr::new(
|
Some(buf) => Ok(Expr::new(
|
||||||
ExprKind::Index {
|
self.index_flow(buf)?,
|
||||||
expr: Box::new(buf),
|
|
||||||
index: Box::new(self.expr_flow(Token::RightBracket)?),
|
|
||||||
},
|
|
||||||
start..self.lexer.span().end,
|
start..self.lexer.span().end,
|
||||||
)),
|
)),
|
||||||
None => Ok(Expr::new(self.cart_flow()?, start..self.lexer.span().end)),
|
None => Ok(Expr::new(self.cart_flow()?, start..self.lexer.span().end)),
|
||||||
|
@ -279,6 +276,27 @@ impl<'source> Parser<'source> {
|
||||||
Ok(ExprKind::Cart(cart))
|
Ok(ExprKind::Cart(cart))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flow for indexing operations
|
||||||
|
///
|
||||||
|
/// Indexing with empty index resolves to length of expression, else it indexes
|
||||||
|
fn index_flow(&mut self, expr: Expr) -> Result<ExprKind, Error> {
|
||||||
|
let mut buf = None;
|
||||||
|
Ok(loop {
|
||||||
|
match self.checked_next()? {
|
||||||
|
Token::RightBracket => match buf {
|
||||||
|
Some(index) => {
|
||||||
|
break ExprKind::Index {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
index: Box::new(index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => break ExprKind::Len(Box::new(expr)),
|
||||||
|
},
|
||||||
|
token => buf = Some(self.parse_expr(token, &mut buf)?),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Flow for operators
|
/// Flow for operators
|
||||||
///
|
///
|
||||||
/// Generates operation from LHS buffer and next expression as RHS
|
/// Generates operation from LHS buffer and next expression as RHS
|
||||||
|
|
|
@ -122,36 +122,36 @@ 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 {
|
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 {
|
Functio::Bf {
|
||||||
instructions,
|
instructions,
|
||||||
tape_len,
|
tape_len,
|
||||||
} => (instructions.len() + tape_len) as _,
|
} => instructions.into_iter().map(|x| x as i32).sum::<i32>() * tape_len as i32,
|
||||||
Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _,
|
Functio::Able { params, body } => {
|
||||||
Functio::Chain { functios, kind } => {
|
params
|
||||||
let (lhs, rhs) = *functios;
|
.into_iter()
|
||||||
match kind {
|
.map(|x| x.bytes().map(|x| x as i32).sum::<i32>())
|
||||||
FunctioChainKind::Equal => {
|
.sum::<i32>()
|
||||||
Value::Int(Value::Functio(lhs).into_i32())
|
+ body.len() as 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 _,
|
Functio::Chain { functios, kind } => {
|
||||||
|
let (lf, rf) = *functios;
|
||||||
|
Value::Functio(lf).into_i32()
|
||||||
|
+ Value::Functio(rf).into_i32()
|
||||||
|
* match kind {
|
||||||
|
FunctioChainKind::Equal => -1,
|
||||||
|
FunctioChainKind::ByArity => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Functio::Eval(code) => code.bytes().map(|x| x as i32).sum(),
|
||||||
},
|
},
|
||||||
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 _,
|
Value::Cart(c) => c
|
||||||
|
.into_iter()
|
||||||
|
.map(|(i, v)| i.into_i32() * v.borrow().clone().into_i32())
|
||||||
|
.sum(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +410,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 {
|
||||||
|
|
Loading…
Reference in a new issue