aboutsummaryrefslogtreecommitdiff
path: root/src/interpret
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpret')
-rw-r--r--src/interpret/value.rs40
-rw-r--r--src/interpret/walker.rs39
2 files changed, 63 insertions, 16 deletions
diff --git a/src/interpret/value.rs b/src/interpret/value.rs
index 86fe094..1a7422b 100644
--- a/src/interpret/value.rs
+++ b/src/interpret/value.rs
@@ -10,6 +10,7 @@ pub enum Value {
Float(f64),
Int(i64),
Bool(bool),
+ Array(Vec<Value>),
Fn(Ref<FnNode>),
Void,
}
@@ -163,6 +164,28 @@ impl Value {
_ => Err(OperationError::NotType(self)),
}
}
+
+ pub fn subscript(self, index: Value) -> Result<Value, OperationError> {
+ let index = match index {
+ Value::Int(i) => i,
+ i => return Err(OperationError::ArrayIndexType(i)),
+ };
+
+ match self {
+ Value::Array(a) => {
+ if index < 0 || index as usize >= a.len() {
+ Err(OperationError::ArrayIndexOutOfRange {
+ index,
+ length: a.len(),
+ })
+ } else {
+ Ok(a[index as usize].clone())
+ }
+ }
+ // Maybe allow string subscripts?
+ x => Err(OperationError::ArrayType(x)),
+ }
+ }
}
impl Value {
@@ -172,6 +195,7 @@ impl Value {
Value::Float(_) => "Float",
Value::Int(_) => "Int",
Value::Bool(_) => "Bool",
+ Value::Array(_) => "Array",
Value::Fn(_) => "Fn",
Value::Void => "Void",
}
@@ -185,6 +209,16 @@ impl Display for Value {
Value::Float(v) => write!(f, "{}", v),
Value::Int(v) => write!(f, "{}", v),
Value::Bool(v) => write!(f, "{}", v),
+ Value::Array(a) => {
+ write!(
+ f,
+ "[{}]",
+ a.iter()
+ .map(|v| format!("{}", v))
+ .collect::<Vec<_>>()
+ .join(", ")
+ )
+ }
Value::Fn(v) => write!(f, "<fn {:?}>", v.as_ptr()),
Value::Void => write!(f, "<void>"),
}
@@ -207,4 +241,10 @@ pub enum OperationError {
NegType(Value),
#[error("Can't flip value '{0}' of type '{}'.", .0.type_name())]
NotType(Value),
+ #[error("Can't use value '{0}' of type '{}' as a subsript index.", .0.type_name())]
+ ArrayIndexType(Value),
+ #[error("Can't subscript value '{0}' of type '{}'.", .0.type_name())]
+ ArrayType(Value),
+ #[error("Array index '{index}' out of range for array of length '{length}'.")]
+ ArrayIndexOutOfRange { index: i64, length: usize },
}
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
index ac3a092..0177777 100644
--- a/src/interpret/walker.rs
+++ b/src/interpret/walker.rs
@@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc};
use crate::parse::ast::{
expression::Expression,
- nodes::{BinaryOperator as BinOp, BlockNode, Identifier, Literal, UnaryOperator as UnOp},
+ nodes::{BinaryOperator as BinOp, BlockNode, Identifier, SimpleLiteral, UnaryOperator as UnOp},
statement::Statement,
Program,
};
@@ -79,7 +79,7 @@ impl Walker {
let right = self.walk_expression(right)?;
// Other operators
- let new_value = match op {
+ match op {
BinOp::Plus => left.add(right),
BinOp::Minus => left.sub(right),
BinOp::Star => left.mul(right),
@@ -94,37 +94,44 @@ impl Walker {
BinOp::Dot => todo!(),
_ => unreachable!(),
}
- .map_err(WalkerError::OperationError)?;
-
- Ok(new_value)
+ .map_err(WalkerError::OperationError)
}
Expression::Unary { op, right } => {
let value = self.walk_expression(right)?;
- let new_value = match op {
+ match op {
UnOp::Minus => value.neg(),
UnOp::Not => value.not(),
}
- .map_err(WalkerError::OperationError)?;
-
- Ok(new_value)
+ .map_err(WalkerError::OperationError)
}
Expression::Call(_) => todo!("Calls not implemented yet."),
- Expression::ArrayAccess(_) => todo!("Arrays not implemented yet."),
+ Expression::ArrayAccess(node) => {
+ let array = self.walk_expression(&node.array)?;
+ let index = self.walk_expression(&node.index)?;
+ array.subscript(index).map_err(WalkerError::OperationError)
+ }
Expression::MemberAccess(_) => todo!("Structures not implemented yet."),
Expression::Group(node) => self.walk_expression(node),
- Expression::Literal(token) => {
+ Expression::ArrayLiteral(node) => {
+ let mut elements = Vec::new();
+ for expression in &node.elements {
+ elements.push(self.walk_expression(expression)?);
+ }
+ Ok(Value::Array(elements))
+ }
+ Expression::SimpleLiteral(token) => {
let value = match token {
- Literal::Int(int) => Value::Int(*int as i64),
- Literal::Float(float) => Value::Float(*float as f64),
- Literal::Str(string) => Value::Str(string.clone()),
- Literal::Bool(bool) => Value::Bool(*bool),
+ SimpleLiteral::Int(int) => Value::Int(*int as i64),
+ SimpleLiteral::Float(float) => Value::Float(*float as f64),
+ SimpleLiteral::Str(string) => Value::Str(string.clone()),
+ SimpleLiteral::Bool(bool) => Value::Bool(*bool),
};
Ok(value)
}
Expression::Block(block) => self.walk_block(block.as_ref()),
- Expression::Fn(fn_node) => {
+ Expression::FnLiteral(fn_node) => {
let node = fn_node.as_ref().clone();
Ok(Value::Fn(RefCell::new(Rc::new(node))))
}