about summary refs log tree commit diff
path: root/src/interpret/value.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-10-24 18:26:01 +0200
committerMel <einebeere@gmail.com>2021-10-24 18:26:01 +0200
commitaf34b3030a46805f42f04341f1ffb20d92fbb7ce (patch)
treeaffed084f5d1d31921b44142428f18d725ed2cea /src/interpret/value.rs
parent73c4808c44f75b7d6546f00f70779fcbf8e28754 (diff)
downloadrabbithole-af34b3030a46805f42f04341f1ffb20d92fbb7ce.tar.zst
rabbithole-af34b3030a46805f42f04341f1ffb20d92fbb7ce.zip
Array literals and array access
Diffstat (limited to 'src/interpret/value.rs')
-rw-r--r--src/interpret/value.rs40
1 files changed, 40 insertions, 0 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 },
 }