mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-13 01:50:41 +01:00
Indexing matrices by ⟦⟧
This commit is contained in:
parent
e2271b7005
commit
df26046e1d
@ -23,7 +23,7 @@ pub enum Expr {
|
||||
Piecewise(Vec<ConditionalPiece>),
|
||||
Vector(Vec<Expr>),
|
||||
Matrix(Vec<Vec<Expr>>),
|
||||
Indexer(Box<Expr>, Box<Expr>),
|
||||
Indexer(Box<Expr>, Vec<Expr>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -126,7 +126,7 @@ pub(crate) fn eval_expr(
|
||||
Expr::Piecewise(pieces) => eval_piecewise(context, pieces, unit),
|
||||
Expr::Vector(values) => eval_vector(context, values),
|
||||
Expr::Matrix(rows) => eval_matrix(context, rows),
|
||||
Expr::Indexer(var, index) => eval_indexer(context, var, index, unit),
|
||||
Expr::Indexer(var, indexes) => eval_indexer(context, var, indexes, unit),
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,19 +582,42 @@ fn eval_matrix(context: &mut Context, rows: &Vec<Vec<Expr>>) -> Result<KalkValue
|
||||
fn eval_indexer(
|
||||
context: &mut Context,
|
||||
var: &Expr,
|
||||
index: &Expr,
|
||||
indexes: &[Expr],
|
||||
unit: &str,
|
||||
) -> Result<KalkValue, CalcError> {
|
||||
let var_value = eval_expr(context, var, unit)?;
|
||||
if let KalkValue::Vector(values) = var_value {
|
||||
let index_value = eval_expr(context, index, unit)?.to_f64() as usize;
|
||||
if let Some(value) = values.get(index_value) {
|
||||
Ok(value.clone())
|
||||
} else {
|
||||
Err(CalcError::ItemOfIndexDoesNotExist(index_value))
|
||||
match var_value {
|
||||
KalkValue::Vector(values) => {
|
||||
if indexes.len() != 1 {
|
||||
return Err(CalcError::IncorrectAmountOfIndexes(indexes.len(), 1));
|
||||
}
|
||||
|
||||
let index_value = eval_expr(context, &indexes[0], unit)?.to_f64() as usize;
|
||||
if let Some(value) = values.get(index_value) {
|
||||
Ok(value.clone())
|
||||
} else {
|
||||
Err(CalcError::ItemOfIndexDoesNotExist(vec![index_value]))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(CalcError::CanOnlyIndexVectors)
|
||||
KalkValue::Matrix(rows) => {
|
||||
if indexes.len() != 2 {
|
||||
return Err(CalcError::IncorrectAmountOfIndexes(indexes.len(), 2));
|
||||
}
|
||||
|
||||
let row_index = eval_expr(context, &indexes[0], unit)?.to_f64() as usize;
|
||||
let column_index = eval_expr(context, &indexes[1], unit)?.to_f64() as usize;
|
||||
if let Some(row) = rows.get(row_index) {
|
||||
if let Some(value) = row.get(column_index) {
|
||||
return Ok(value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Err(CalcError::ItemOfIndexDoesNotExist(vec![
|
||||
row_index,
|
||||
column_index,
|
||||
]))
|
||||
}
|
||||
_ => Err(CalcError::CanOnlyIndexVectors),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,8 @@ pub enum CalcError {
|
||||
ExpectedDx,
|
||||
ExpectedIf,
|
||||
IncorrectAmountOfArguments(usize, String, usize),
|
||||
ItemOfIndexDoesNotExist(usize),
|
||||
IncorrectAmountOfIndexes(usize, usize),
|
||||
ItemOfIndexDoesNotExist(Vec<usize>),
|
||||
InconsistentColumnWidths,
|
||||
InvalidNumberLiteral(String),
|
||||
InvalidOperator,
|
||||
@ -134,7 +135,11 @@ impl ToString for CalcError {
|
||||
"Expected {} arguments for function {}, but got {}.",
|
||||
expected, func, got
|
||||
),
|
||||
CalcError::ItemOfIndexDoesNotExist(index) => format!("Item of index {} does not exist.", index),
|
||||
CalcError::IncorrectAmountOfIndexes(expected, got) => format!(
|
||||
"Expected {} indexes but got {}.",
|
||||
expected, got
|
||||
),
|
||||
CalcError::ItemOfIndexDoesNotExist(indexes) => format!("Item of index ⟦{}⟧ does not exist.", indexes.iter().map(|x| x.to_string()).collect::<Vec<String>>().join(", ")),
|
||||
CalcError::InconsistentColumnWidths => format!("Inconsistent column widths. Matrix columns must be the same size."),
|
||||
CalcError::InvalidNumberLiteral(x) => format!("Invalid number literal: '{}'.", x),
|
||||
CalcError::InvalidOperator => format!("Invalid operator."),
|
||||
@ -566,9 +571,15 @@ fn parse_indexer(context: &mut Context) -> Result<Expr, CalcError> {
|
||||
|
||||
if match_token(context, TokenKind::OpenDoubleBracket) {
|
||||
advance(context);
|
||||
let right = Box::new(parse_expr(context)?);
|
||||
let mut indexes = vec![parse_expr(context)?];
|
||||
while match_token(context, TokenKind::Comma) {
|
||||
advance(context);
|
||||
indexes.push(parse_expr(context)?);
|
||||
}
|
||||
|
||||
consume(context, TokenKind::ClosedDoubleBracket)?;
|
||||
return Ok(Expr::Indexer(Box::new(left), right));
|
||||
|
||||
return Ok(Expr::Indexer(Box::new(left), indexes));
|
||||
}
|
||||
|
||||
Ok(left)
|
||||
@ -771,7 +782,7 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
||||
|
||||
Ok(Expr::Indexer(
|
||||
Box::new(Expr::Var(Identifier::from_full_name(&var_name))),
|
||||
Box::new(lowered_expr),
|
||||
vec![lowered_expr],
|
||||
))
|
||||
} else if context.parsing_unit_decl {
|
||||
context.unit_decl_base_unit = Some(identifier.full_name);
|
||||
|
Loading…
Reference in New Issue
Block a user