diff --git a/src/ast/types.rs b/src/ast/types.rs index 56f9f21..1d5b295 100644 --- a/src/ast/types.rs +++ b/src/ast/types.rs @@ -244,11 +244,21 @@ impl Record { } } +impl Vector { + pub fn get(&self, index: usize) -> Result<&Ref, Error> { + match self.0.get(index) { + Some(v) => Ok(v), + None => Err(Error::IndexOutOfBounds(index)), + } + } +} + pub const UNIT_VALUE: Value = Value::Record(Record(BTreeMap::new())); pub const UNIT: Expr = Expr::Value(UNIT_VALUE); pub enum Error { LabelNotFound(Label), + IndexOutOfBounds(usize), } impl std::fmt::Display for Error { @@ -257,6 +267,9 @@ impl std::fmt::Display for Error { Error::LabelNotFound(a) => { write!(f, "Label not found: {a:?}") } + Error::IndexOutOfBounds(a) => { + write!(f, "Indexout of bounds: {a:?}") + } } } } diff --git a/src/interpret/interpret.rs b/src/interpret/interpret.rs index 5d8d221..206be30 100644 --- a/src/interpret/interpret.rs +++ b/src/interpret/interpret.rs @@ -149,6 +149,10 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result match eval_expr(expr_env, state, expr)? { ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()), + ast::Value::Vector(vec) if field.0.chars().all(char::is_numeric) => { + let index = field.0.parse::().unwrap(); + Ok(state.variables.get(vec.get(index)?).clone()) + } v => Err(Error::NotARecord(v, Backtrace::capture())), }, ast::Expr::Var(var) => { @@ -412,6 +416,10 @@ fn eval_expr_shallow( } ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? { ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())), + ast::Value::Vector(vec) if field.0.chars().all(char::is_numeric) => { + let index = field.0.parse::().unwrap(); + Ok(ast::Value::Ref(vec.get(index)?.clone())) + } v => Err(Error::NotARecord(v, Backtrace::capture())), }, _ => eval_expr(expr_env, state, expr), diff --git a/src/interpret/types.rs b/src/interpret/types.rs index e9a83ee..0a77212 100644 --- a/src/interpret/types.rs +++ b/src/interpret/types.rs @@ -10,6 +10,7 @@ pub enum Error { DuplicateEnvNames(ast::EnvName, Backtrace), DuplicateNames(ast::Name, Backtrace), NameNotFound(ast::Name, Env, Backtrace), + IndexOutOfBounds(usize, Backtrace), FieldNotFound(ast::Label, Backtrace), EnvNotFound(ast::EnvName, Backtrace), LastStatementNotAnExpr(Backtrace), @@ -26,6 +27,7 @@ impl PartialEq for Error { match (self, other) { (Error::DuplicateEnvNames(a1, _), Error::DuplicateEnvNames(a2, _)) => a1 == a2, (Error::DuplicateNames(a1, _), Error::DuplicateNames(a2, _)) => a1 == a2, + (Error::IndexOutOfBounds(a1, _), Error::IndexOutOfBounds(a2, _)) => a1 == a2, (Error::NameNotFound(a1, _, _), Error::NameNotFound(a2, _, _)) => a1 == a2, (Error::FieldNotFound(a1, _), Error::FieldNotFound(a2, _)) => a1 == a2, (Error::EnvNotFound(a1, _), Error::EnvNotFound(a2, _)) => a1 == a2, @@ -56,6 +58,7 @@ impl std::fmt::Display for Error { ) } Error::DuplicateNames(a, b) => write!(f, "Duplicate names: {a:?}\n{b}"), + Error::IndexOutOfBounds(a, b) => write!(f, "Index out of bounds: {a:?}\n{b}"), Error::NameNotFound(a, e, b) => write!( f, "Name not found: {a:?} in {:#?}\n{b}", @@ -86,6 +89,7 @@ impl From for Error { fn from(error: ast::Error) -> Error { match error { ast::Error::LabelNotFound(l) => Error::FieldNotFound(l, Backtrace::capture()), + ast::Error::IndexOutOfBounds(i) => Error::IndexOutOfBounds(i, Backtrace::capture()), } } }