Add parsing for list access
This commit is contained in:
parent
80a7700d68
commit
8c5ac0b89e
@ -205,6 +205,30 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn list_access() {
|
||||||
|
let input = "[1, 2, 3].0";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse(input),
|
||||||
|
Ok([Node::new(
|
||||||
|
Statement::PropertyAccess(
|
||||||
|
Box::new(Node::new(
|
||||||
|
Statement::List(vec![
|
||||||
|
Node::new(Statement::Constant(Value::integer(1)), (1, 2)),
|
||||||
|
Node::new(Statement::Constant(Value::integer(2)), (4, 5)),
|
||||||
|
Node::new(Statement::Constant(Value::integer(3)), (7, 8)),
|
||||||
|
]),
|
||||||
|
(0, 9)
|
||||||
|
)),
|
||||||
|
Box::new(Node::new(Statement::Constant(Value::integer(0)), (10, 11))),
|
||||||
|
),
|
||||||
|
(0, 11),
|
||||||
|
)]
|
||||||
|
.into())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn property_access() {
|
fn property_access() {
|
||||||
let input = "a.b";
|
let input = "a.b";
|
||||||
|
@ -119,6 +119,29 @@ impl Value {
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn list_access(&self, index: i64) -> Result<Value, ValueError> {
|
||||||
|
match self.inner().as_ref() {
|
||||||
|
ValueInner::List(list) => {
|
||||||
|
if index < 0 {
|
||||||
|
return Err(ValueError::IndexOutOfBounds {
|
||||||
|
value: self.clone(),
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(value) = list.get(index as usize) {
|
||||||
|
Ok(value.clone())
|
||||||
|
} else {
|
||||||
|
Err(ValueError::IndexOutOfBounds {
|
||||||
|
value: self.clone(),
|
||||||
|
index,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(ValueError::ExpectedList(self.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
@ -560,4 +583,6 @@ impl Ord for ValueInner {
|
|||||||
pub enum ValueError {
|
pub enum ValueError {
|
||||||
CannotAdd(Value, Value),
|
CannotAdd(Value, Value),
|
||||||
PropertyNotFound { value: Value, property: Identifier },
|
PropertyNotFound { value: Value, property: Identifier },
|
||||||
|
IndexOutOfBounds { value: Value, index: i64 },
|
||||||
|
ExpectedList(Value),
|
||||||
}
|
}
|
||||||
|
@ -110,17 +110,24 @@ impl Vm {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
let right_span = right.span;
|
let right_span = right.span;
|
||||||
let right = if let Statement::Identifier(identifier) = &right.statement {
|
|
||||||
identifier
|
|
||||||
} else {
|
|
||||||
return Err(VmError::ExpectedValue {
|
|
||||||
position: right_span,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = left.property_access(right)?;
|
if let Statement::Identifier(identifier) = &right.statement {
|
||||||
|
let value = left.property_access(identifier)?;
|
||||||
|
|
||||||
Ok(Some(value))
|
return Ok(Some(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Statement::Constant(value) = &right.statement {
|
||||||
|
if let Some(index) = value.as_integer() {
|
||||||
|
let value = left.list_access(index)?;
|
||||||
|
|
||||||
|
return Ok(Some(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(VmError::ExpectedIdentifierOrInteger {
|
||||||
|
position: right_span,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,6 +141,7 @@ pub enum VmError {
|
|||||||
// Anaylsis Failures
|
// Anaylsis Failures
|
||||||
// These should be prevented by running the analyzer before the VM
|
// These should be prevented by running the analyzer before the VM
|
||||||
ExpectedValue { position: Span },
|
ExpectedValue { position: Span },
|
||||||
|
ExpectedIdentifierOrInteger { position: (usize, usize) },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ParseError> for VmError {
|
impl From<ParseError> for VmError {
|
||||||
@ -152,6 +160,13 @@ impl From<ValueError> for VmError {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn list_access() {
|
||||||
|
let input = "[1, 2, 3][1]";
|
||||||
|
|
||||||
|
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(2))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn property_access() {
|
fn property_access() {
|
||||||
let input = "[1, 2, 3].length";
|
let input = "[1, 2, 3].length";
|
||||||
|
Loading…
Reference in New Issue
Block a user