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