about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-11-20 00:31:28 +0100
committerMel <einebeere@gmail.com>2021-11-20 00:31:28 +0100
commit395d086f0dce355ccdcf3da149c309826c539b48 (patch)
tree888ad59d8fcebcec0c04bcfd13364889c5047349 /src
parent334f70f5a2f63ec636ac1a8bc375ce51effba424 (diff)
downloadrabbithole-395d086f0dce355ccdcf3da149c309826c539b48.tar.zst
rabbithole-395d086f0dce355ccdcf3da149c309826c539b48.zip
Runtime types
Diffstat (limited to 'src')
-rw-r--r--src/interpret/mod.rs5
-rw-r--r--src/interpret/operator.rs300
-rw-r--r--src/interpret/scope.rs38
-rw-r--r--src/interpret/value.rs341
-rw-r--r--src/interpret/walker.rs125
-rw-r--r--src/main.rs5
-rw-r--r--src/types/bag.rs123
-rw-r--r--src/types/mod.rs42
8 files changed, 632 insertions, 347 deletions
diff --git a/src/interpret/mod.rs b/src/interpret/mod.rs
index 813f45d..7f1c844 100644
--- a/src/interpret/mod.rs
+++ b/src/interpret/mod.rs
@@ -1,3 +1,4 @@
 mod scope;
-mod value;
-pub mod walker;
+mod operator;
+pub mod value;
+pub mod walker;
\ No newline at end of file
diff --git a/src/interpret/operator.rs b/src/interpret/operator.rs
new file mode 100644
index 0000000..78ebe75
--- /dev/null
+++ b/src/interpret/operator.rs
@@ -0,0 +1,300 @@
+use thiserror::Error;
+
+use crate::{parse::ast::expression::Expression, types::bag::TypeBag};
+
+use super::{
+    value::{Value, ValueVariant},
+    walker::{Walker, WalkerError},
+};
+
+pub struct ValueOperator<'types> {
+    types: &'types TypeBag,
+}
+
+impl<'t> ValueOperator<'t> {
+    pub fn new(types: &'t TypeBag) -> Self {
+        ValueOperator { types }
+    }
+
+    pub fn add(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Str(ref l) => match rhs.variant {
+                ValueVariant::Str(r) => Ok(Value::str(format!("{}{}", l, r), self.types)),
+                ValueVariant::Float(r) => Ok(Value::str(format!("{}{}", l, r), self.types)),
+                ValueVariant::Int(r) => Ok(Value::str(format!("{}{}", l, r), self.types)),
+                _ => Err(OperationError::AddTypes(lhs, rhs)),
+            },
+            ValueVariant::Float(l) => match rhs.variant {
+                ValueVariant::Str(r) => Ok(Value::str(l.to_string() + &r, self.types)),
+                ValueVariant::Float(r) => Ok(Value::float(l + r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::float(l + r as f64, self.types)),
+                _ => Err(OperationError::AddTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(l) => match rhs.variant {
+                ValueVariant::Str(r) => Ok(Value::str(l.to_string() + &r, self.types)),
+                ValueVariant::Float(r) => Ok(Value::float(l as f64 + r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::int(l + r, self.types)),
+                _ => Err(OperationError::AddTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::AddTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn sub(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Float(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l - r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::float(l - r as f64, self.types)),
+                _ => Err(OperationError::SubTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l as f64 - r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::int(l - r, self.types)),
+                _ => Err(OperationError::SubTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::SubTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn mul(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Float(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l * r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::float(l * r as f64, self.types)),
+                _ => Err(OperationError::MulTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l as f64 * r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::int(l * r, self.types)),
+                _ => Err(OperationError::MulTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::MulTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn div(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Float(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l / r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::float(l / r as f64, self.types)),
+                _ => Err(OperationError::DivTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::float(l as f64 / r, self.types)),
+                ValueVariant::Int(r) => Ok(Value::float(l as f64 / r as f64, self.types)),
+                _ => Err(OperationError::DivTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::DivTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn eq(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Str(l) => match rhs.variant {
+                ValueVariant::Str(r) => Ok(Value::bool(l == r, self.types)),
+                _ => Ok(Value::bool(false, self.types)),
+            },
+            ValueVariant::Float(l) => match rhs.variant {
+                ValueVariant::Float(r) => Ok(Value::bool(l == r, self.types)),
+                _ => Ok(Value::bool(false, self.types)),
+            },
+            ValueVariant::Int(l) => match rhs.variant {
+                ValueVariant::Int(r) => Ok(Value::bool(l == r, self.types)),
+                _ => Ok(Value::bool(false, self.types)),
+            },
+            ValueVariant::Bool(l) => match rhs.variant {
+                ValueVariant::Bool(r) => Ok(Value::bool(l == r, self.types)),
+                _ => Ok(Value::bool(false, self.types)),
+            },
+            _ => Ok(Value::bool(false, self.types)),
+        }
+    }
+
+    pub fn neq(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        if let Ok(Value {
+            variant: ValueVariant::Bool(value),
+            ..
+        }) = self.eq(lhs, rhs)
+        {
+            Ok(Value::bool(!value, self.types))
+        } else {
+            unreachable!()
+        }
+    }
+
+    pub fn gt(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Float(r) => match rhs.variant {
+                ValueVariant::Float(l) => Ok(Value::bool(r > l, self.types)),
+                ValueVariant::Int(l) => Ok(Value::bool(r > l as f64, self.types)),
+                _ => Err(OperationError::CompareTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(r) => match rhs.variant {
+                ValueVariant::Float(l) => Ok(Value::bool(r as f64 > l, self.types)),
+                ValueVariant::Int(l) => Ok(Value::bool(r > l, self.types)),
+                _ => Err(OperationError::CompareTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::CompareTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn gte(&self, lhs: Value, rhs: Value) -> Result<Value, OperationError> {
+        match lhs.variant {
+            ValueVariant::Float(r) => match rhs.variant {
+                ValueVariant::Float(l) => Ok(Value::bool(r >= l, self.types)),
+                ValueVariant::Int(l) => Ok(Value::bool(r >= l as f64, self.types)),
+                _ => Err(OperationError::CompareTypes(lhs, rhs)),
+            },
+            ValueVariant::Int(r) => match rhs.variant {
+                ValueVariant::Float(l) => Ok(Value::bool(r as f64 >= l, self.types)),
+                ValueVariant::Int(l) => Ok(Value::bool(r >= l, self.types)),
+                _ => Err(OperationError::CompareTypes(lhs, rhs)),
+            },
+            _ => Err(OperationError::CompareTypes(lhs, rhs)),
+        }
+    }
+
+    pub fn neg(&self, val: Value) -> Result<Value, OperationError> {
+        match val.variant {
+            ValueVariant::Float(float) => Ok(Value::float(-float, self.types)),
+            ValueVariant::Int(int) => Ok(Value::int(-int, self.types)),
+            _ => Err(OperationError::NegType(val)),
+        }
+    }
+
+    pub fn not(&self, val: Value) -> Result<Value, OperationError> {
+        match val.variant {
+            ValueVariant::Bool(bool) => Ok(Value::bool(bool, self.types)),
+            _ => Err(OperationError::NotType(val)),
+        }
+    }
+
+    pub fn subscript(&self, val: Value, index: Value) -> Result<Value, OperationError> {
+        let index = match index.variant {
+            ValueVariant::Int(i) => i,
+            _ => return Err(OperationError::ArrayIndexType(index)),
+        };
+
+        match val.variant {
+            ValueVariant::Array(a) => {
+                let array = a.borrow();
+                if index < 0 || index as usize >= array.len() {
+                    Err(OperationError::ArrayIndexOutOfRange {
+                        index,
+                        length: array.len(),
+                    })
+                } else {
+                    Ok(array[index as usize].clone())
+                }
+            }
+            // Maybe allow string subscripts?
+            _ => Err(OperationError::ArrayType(val)),
+        }
+    }
+
+    pub fn subscript_assign(
+        &self,
+        val: &mut Value,
+        index: Value,
+        value: Value,
+    ) -> Result<Value, OperationError> {
+        let index = match index.variant {
+            ValueVariant::Int(i) => i,
+            _ => return Err(OperationError::ArrayIndexType(index)),
+        };
+
+        match &val.variant {
+            ValueVariant::Array(a) => {
+                let mut array = a.borrow_mut();
+                if index < 0 || index as usize >= array.len() {
+                    Err(OperationError::ArrayIndexOutOfRange {
+                        index,
+                        length: array.len(),
+                    })
+                } else {
+                    array[index as usize] = value;
+                    Ok(array[index as usize].clone())
+                }
+            }
+            _ => Err(OperationError::ArrayType(val.clone())),
+        }
+    }
+
+    pub fn call(&self, val: &Value, arguments: Vec<Value>) -> Result<Value, WalkerError> {
+        let called = match &val.variant {
+            ValueVariant::Fn(i) => i,
+            _ => {
+                return Err(WalkerError::OperationError(OperationError::CallableType(
+                    val.clone(),
+                )))
+            }
+        }
+        .borrow();
+
+        // FIXME: Currently closures are able to re-assign values from the upper scopes.
+        // This is good behaviour, until a closure re-assigns a value that was declared after
+        // the closure even existed.
+        // Minimal reproducible example:
+        // ```rh
+        // closure = fn { y = 10; };
+        // y = 1;
+        // closure();
+        // print y;
+        // ```
+        // Expected: 1
+        // Actual: 10
+        let mut scope = called.scope.clone();
+        scope.nest();
+
+        let parameters = &called.node.header.parameters;
+
+        if parameters.len() != arguments.len() {
+            return Err(WalkerError::OperationError(
+                OperationError::WrongArgumentCount(parameters.len(), arguments.len()),
+            ));
+        }
+
+        for (argument, parameter) in arguments.into_iter().zip(parameters.iter()) {
+            scope.set_var_shadowed(&parameter.identifier, argument);
+        }
+
+        // Yes, we create a new walker for every function call,
+        // it's *way* easier that way.
+        let mut walker = Walker::new(scope, self.types.clone());
+        let result = walker.walk_expression(&Expression::Block(Box::new(called.node.body.clone())));
+
+        if let Err(WalkerError::Return(returned)) = result {
+            Ok(returned)
+        } else {
+            result
+        }
+    }
+}
+
+#[derive(Error, Debug)]
+pub enum OperationError {
+    #[error("Can't add value '{0}' of type '{}' to value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
+    AddTypes(Value, Value),
+    #[error("Can't subtract value '{1}' of type '{}' from value '{0}' of type '{}'.", .1.type_name(), .0.type_name())]
+    SubTypes(Value, Value),
+    #[error("Can't multiply value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
+    MulTypes(Value, Value),
+    #[error("Can't divide value '{0}' of type '{}' by value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
+    DivTypes(Value, Value),
+    #[error("Can't compare value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
+    CompareTypes(Value, Value),
+    #[error("Can't negate value '{0}' of type '{}'.", .0.type_name())]
+    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 },
+    #[error("Can't call value '{0}' of type '{}'.", .0.type_name())]
+    CallableType(Value),
+    #[error("Function expects {0} arguments, but {1} were given.")]
+    WrongArgumentCount(usize, usize),
+}
diff --git a/src/interpret/scope.rs b/src/interpret/scope.rs
index 0db34c2..3813cab 100644
--- a/src/interpret/scope.rs
+++ b/src/interpret/scope.rs
@@ -1,5 +1,8 @@
-use super::value::Value;
-use crate::parse::ast::nodes::Identifier;
+use super::value::{Value, ValueVariant};
+use crate::{
+    parse::ast::nodes::Identifier,
+    types::{bag::TypeBag, TypeVariant},
+};
 use std::{cell::RefCell, collections::HashMap, rc::Rc};
 use thiserror::Error;
 
@@ -82,10 +85,10 @@ impl ScopeChain {
         }
     }
 
-    pub fn get_var(&self, ident: &str) -> Result<Value, ScopeError> {
+    pub fn get_var(&self, ident: &str, types: &TypeBag) -> Result<Value, ScopeError> {
         for scope in self.scopes.iter().rev() {
             if let Some(value) = scope.get(ident) {
-                return Ok(value.get_value());
+                return Ok(value.get_value(types));
             }
         }
         Err(ScopeError::UnknownIdentifier(ident.to_string()))
@@ -111,19 +114,32 @@ enum AssignedValue {
 }
 
 impl AssignedValue {
-    fn get_value(&self) -> Value {
+    fn get_value(&self, types: &TypeBag) -> Value {
         match self {
             Self::Mutable(value) => value.clone(),
-            Self::Constant(value) => match value {
-                Value::Array(reference) => {
+            Self::Constant(value) => match &value.variant {
+                ValueVariant::Array(reference) => {
                     let underlying_value = reference.borrow().clone();
-                    Value::Array(Rc::new(RefCell::new(underlying_value)))
+
+                    Value {
+                        variant: ValueVariant::Array(Rc::new(RefCell::new(underlying_value))),
+                        // FIXME: Give arrays actual type instead of void.
+                        typ: types.create_type(TypeVariant::Array(types.void())),
+                    }
                 }
-                Value::Fn(reference) => {
+                ValueVariant::Fn(reference) => {
                     let underlying_value = reference.borrow().clone();
-                    Value::Fn(Rc::new(RefCell::new(underlying_value)))
+
+                    Value {
+                        variant: ValueVariant::Fn(Rc::new(RefCell::new(underlying_value))),
+                        // FIXME: Give functions actual types.
+                        typ: types.create_type(TypeVariant::Fn {
+                            parameters: HashMap::new(),
+                            returns: types.void(),
+                        }),
+                    }
                 }
-                x => x.clone(),
+                _ => value.clone(),
             },
         }
     }
diff --git a/src/interpret/value.rs b/src/interpret/value.rs
index d108c68..45c177d 100644
--- a/src/interpret/value.rs
+++ b/src/interpret/value.rs
@@ -1,298 +1,90 @@
-use crate::parse::ast::{expression::Expression, nodes::FnNode};
-use std::{cell::RefCell, fmt::Display, rc::Rc};
-use thiserror::Error;
-
-use super::{
-    scope::ScopeChain,
-    walker::{Walker, WalkerError},
+use crate::{
+    parse::ast::nodes::{FnNode, Identifier},
+    types::{bag::TypeBag, Type},
 };
+use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc};
+
+use super::scope::ScopeChain;
 
 type ReferenceOnCopy<T> = Rc<RefCell<T>>;
 
 #[derive(Clone, Debug)]
-pub enum Value {
+pub struct Value {
+    pub variant: ValueVariant,
+    pub typ: Type,
+}
+
+#[derive(Clone, Debug)]
+pub enum ValueVariant {
     Str(String),
     Float(f64),
     Int(i64),
     Bool(bool),
     Array(ReferenceOnCopy<Vec<Value>>),
     Fn(ReferenceOnCopy<FnValue>),
+    Data(HashMap<Identifier, Value>),
     Void,
 }
 
 impl Value {
-    pub fn add(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Str(ref l) => match rhs {
-                Value::Str(r) => Ok(Value::Str(format!("{}{}", l, r))),
-                Value::Float(r) => Ok(Value::Str(format!("{}{}", l, r))),
-                Value::Int(r) => Ok(Value::Str(format!("{}{}", l, r))),
-                r => Err(OperationError::AddTypes(self, r)),
-            },
-            Value::Float(l) => match rhs {
-                Value::Str(r) => Ok(Value::Str(l.to_string() + &r)),
-                Value::Float(r) => Ok(Value::Float(l + r)),
-                Value::Int(r) => Ok(Value::Float(l + r as f64)),
-                r => Err(OperationError::AddTypes(self, r)),
-            },
-            Value::Int(l) => match rhs {
-                Value::Str(r) => Ok(Value::Str(l.to_string() + &r)),
-                Value::Float(r) => Ok(Value::Float(l as f64 + r)),
-                Value::Int(r) => Ok(Value::Int(l + r)),
-                r => Err(OperationError::AddTypes(self, r)),
-            },
-            _ => Err(OperationError::AddTypes(self, rhs)),
-        }
-    }
-
-    pub fn sub(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l - r)),
-                Value::Int(r) => Ok(Value::Float(l - r as f64)),
-                r => Err(OperationError::SubTypes(self, r)),
-            },
-            Value::Int(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l as f64 - r)),
-                Value::Int(r) => Ok(Value::Int(l - r)),
-                r => Err(OperationError::SubTypes(self, r)),
-            },
-            _ => Err(OperationError::SubTypes(self, rhs)),
-        }
-    }
-
-    pub fn mul(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l * r)),
-                Value::Int(r) => Ok(Value::Float(l * r as f64)),
-                r => Err(OperationError::MulTypes(self, r)),
-            },
-            Value::Int(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l as f64 * r)),
-                Value::Int(r) => Ok(Value::Int(l * r)),
-                r => Err(OperationError::MulTypes(self, r)),
-            },
-            _ => Err(OperationError::MulTypes(self, rhs)),
-        }
-    }
-
-    pub fn div(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l / r)),
-                Value::Int(r) => Ok(Value::Float(l / r as f64)),
-                r => Err(OperationError::DivTypes(self, r)),
-            },
-            Value::Int(l) => match rhs {
-                Value::Float(r) => Ok(Value::Float(l as f64 / r)),
-                Value::Int(r) => Ok(Value::Float(l as f64 / r as f64)),
-                r => Err(OperationError::DivTypes(self, r)),
-            },
-            _ => Err(OperationError::DivTypes(self, rhs)),
-        }
-    }
-
-    pub fn eq(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Str(l) => match rhs {
-                Value::Str(r) => Ok(Value::Bool(l == r)),
-                _ => Ok(Value::Bool(false)),
-            },
-            Value::Float(l) => match rhs {
-                Value::Float(r) => Ok(Value::Bool(l == r)),
-                _ => Ok(Value::Bool(false)),
-            },
-            Value::Int(l) => match rhs {
-                Value::Int(r) => Ok(Value::Bool(l == r)),
-                _ => Ok(Value::Bool(false)),
-            },
-            Value::Bool(l) => match rhs {
-                Value::Bool(r) => Ok(Value::Bool(l == r)),
-                _ => Ok(Value::Bool(false)),
-            },
-            _ => Ok(Value::Bool(false)),
-        }
-    }
-
-    pub fn neq(self, rhs: Value) -> Result<Value, OperationError> {
-        if let Ok(Value::Bool(value)) = self.eq(rhs) {
-            Ok(Value::Bool(!value))
-        } else {
-            unreachable!()
-        }
-    }
-
-    pub fn gt(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(r) => match rhs {
-                Value::Float(l) => Ok(Value::Bool(r > l)),
-                Value::Int(l) => Ok(Value::Bool(r > l as f64)),
-                r => Err(OperationError::CompareTypes(self, r)),
-            },
-            Value::Int(r) => match rhs {
-                Value::Float(l) => Ok(Value::Bool(r as f64 > l)),
-                Value::Int(l) => Ok(Value::Bool(r > l)),
-                r => Err(OperationError::CompareTypes(self, r)),
-            },
-            _ => Err(OperationError::CompareTypes(self, rhs)),
+    pub fn str(val: String, types: &TypeBag) -> Self {
+        Self {
+            variant: ValueVariant::Str(val),
+            typ: types.str(),
         }
     }
 
-    pub fn gte(self, rhs: Value) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(r) => match rhs {
-                Value::Float(l) => Ok(Value::Bool(r >= l)),
-                Value::Int(l) => Ok(Value::Bool(r >= l as f64)),
-                r => Err(OperationError::CompareTypes(self, r)),
-            },
-            Value::Int(r) => match rhs {
-                Value::Float(l) => Ok(Value::Bool(r as f64 >= l)),
-                Value::Int(l) => Ok(Value::Bool(r >= l)),
-                r => Err(OperationError::CompareTypes(self, r)),
-            },
-            _ => Err(OperationError::CompareTypes(self, rhs)),
+    pub fn int(val: i64, types: &TypeBag) -> Self {
+        Self {
+            variant: ValueVariant::Int(val),
+            typ: types.int(),
         }
     }
 
-    pub fn neg(self) -> Result<Value, OperationError> {
-        match self {
-            Value::Float(float) => Ok(Value::Float(-float)),
-            Value::Int(int) => Ok(Value::Int(-int)),
-            _ => Err(OperationError::NegType(self)),
+    pub fn float(val: f64, types: &TypeBag) -> Self {
+        Self {
+            variant: ValueVariant::Float(val),
+            typ: types.float(),
         }
     }
 
-    pub fn not(self) -> Result<Value, OperationError> {
-        match self {
-            Value::Bool(bool) => Ok(Value::Bool(bool)),
-            _ => Err(OperationError::NotType(self)),
+    pub fn bool(val: bool, types: &TypeBag) -> Self {
+        Self {
+            variant: ValueVariant::Bool(val),
+            typ: types.bool(),
         }
     }
 
-    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) => {
-                let array = a.borrow();
-                if index < 0 || index as usize >= array.len() {
-                    Err(OperationError::ArrayIndexOutOfRange {
-                        index,
-                        length: array.len(),
-                    })
-                } else {
-                    Ok(array[index as usize].clone())
-                }
-            }
-            // Maybe allow string subscripts?
-            x => Err(OperationError::ArrayType(x.clone())),
-        }
-    }
-
-    pub fn subscript_assign(
-        &mut self,
-        index: Value,
-        value: Value,
-    ) -> Result<Value, OperationError> {
-        let index = match index {
-            Value::Int(i) => i,
-            i => return Err(OperationError::ArrayIndexType(i)),
-        };
-
-        match self {
-            Value::Array(a) => {
-                let mut array = a.borrow_mut();
-                if index < 0 || index as usize >= array.len() {
-                    Err(OperationError::ArrayIndexOutOfRange {
-                        index,
-                        length: array.len(),
-                    })
-                } else {
-                    array[index as usize] = value;
-                    Ok(array[index as usize].clone())
-                }
-            }
-            x => Err(OperationError::ArrayType(x.clone())),
+    pub fn void(types: &TypeBag) -> Self {
+        Self {
+            variant: ValueVariant::Void,
+            typ: types.void(),
         }
     }
 
-    pub fn call(&self, arguments: Vec<Value>) -> Result<Value, WalkerError> {
-        let called = match self {
-            Value::Fn(i) => i,
-            i => {
-                return Err(WalkerError::OperationError(OperationError::CallableType(
-                    i.clone(),
-                )))
-            }
-        }
-        .borrow();
-
-        // FIXME: Currently closures are able to re-assign values from the upper scopes.
-        // This is good behaviour, until a closure re-assigns a value that was declared after
-        // the closure even existed.
-        // Minimal reproducible example:
-        // ```rh
-        // closure = fn { y = 10; };
-        // y = 1;
-        // closure();
-        // print y;
-        // ```
-        // Expected: 1
-        // Actual: 10
-        let mut scope = called.scope.clone();
-        scope.nest();
-
-        let parameters = &called.node.header.parameters;
-
-        if parameters.len() != arguments.len() {
-            return Err(WalkerError::OperationError(
-                OperationError::WrongArgumentCount(parameters.len(), arguments.len()),
-            ));
-        }
-
-        for (argument, parameter) in arguments.into_iter().zip(parameters.iter()) {
-            scope.set_var_shadowed(&parameter.identifier, argument);
-        }
-
-        // Yes, we create a new walker for every function call,
-        // it's *way* easier that way.
-        let mut walker = Walker::new_with_scope(scope);
-        let result = walker.walk_expression(&Expression::Block(Box::new(called.node.body.clone())));
-
-        if let Err(WalkerError::Return(returned)) = result {
-            Ok(returned)
-        } else {
-            result
-        }
-    }
-}
-
-impl Value {
     pub fn type_name(&self) -> &'static str {
-        match self {
-            Value::Str(_) => "Str",
-            Value::Float(_) => "Float",
-            Value::Int(_) => "Int",
-            Value::Bool(_) => "Bool",
-            Value::Array(_) => "Array",
-            Value::Fn(_) => "Fn",
-            Value::Void => "Void",
+        // TODO: Base this off of the type.
+        match self.variant {
+            ValueVariant::Str(_) => "Str",
+            ValueVariant::Float(_) => "Float",
+            ValueVariant::Int(_) => "Int",
+            ValueVariant::Bool(_) => "Bool",
+            ValueVariant::Array(_) => "Array",
+            ValueVariant::Fn(_) => "Fn",
+            ValueVariant::Void => "Void",
+            _ => todo!(),
         }
     }
 }
 
 impl Display for Value {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            Value::Str(v) => write!(f, "{}", v),
-            Value::Float(v) => write!(f, "{}", v),
-            Value::Int(v) => write!(f, "{}", v),
-            Value::Bool(v) => write!(f, "{}", v),
-            Value::Array(a) => {
+        match &self.variant {
+            ValueVariant::Str(v) => write!(f, "{}", v),
+            ValueVariant::Float(v) => write!(f, "{}", v),
+            ValueVariant::Int(v) => write!(f, "{}", v),
+            ValueVariant::Bool(v) => write!(f, "{}", v),
+            ValueVariant::Array(a) => {
                 write!(
                     f,
                     "[{}]",
@@ -303,8 +95,9 @@ impl Display for Value {
                         .join(", ")
                 )
             }
-            Value::Fn(v) => write!(f, "<fn {:?}>", v.as_ptr()),
-            Value::Void => write!(f, "<void>"),
+            ValueVariant::Fn(v) => write!(f, "<fn {:?}>", v.as_ptr()),
+            ValueVariant::Void => write!(f, "<void>"),
+            _ => todo!(),
         }
     }
 }
@@ -315,30 +108,4 @@ pub struct FnValue {
     pub scope: ScopeChain,
 }
 
-#[derive(Error, Debug)]
-pub enum OperationError {
-    #[error("Can't add value '{0}' of type '{}' to value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
-    AddTypes(Value, Value),
-    #[error("Can't subtract value '{1}' of type '{}' from value '{0}' of type '{}'.", .1.type_name(), .0.type_name())]
-    SubTypes(Value, Value),
-    #[error("Can't multiply value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
-    MulTypes(Value, Value),
-    #[error("Can't divide value '{0}' of type '{}' by value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
-    DivTypes(Value, Value),
-    #[error("Can't compare value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
-    CompareTypes(Value, Value),
-    #[error("Can't negate value '{0}' of type '{}'.", .0.type_name())]
-    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 },
-    #[error("Can't call value '{0}' of type '{}'.", .0.type_name())]
-    CallableType(Value),
-    #[error("Function expects {0} arguments, but {1} were given.")]
-    WrongArgumentCount(usize, usize),
-}
+pub type ValueMap = HashMap<Identifier, Value>;
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
index 15ab37d..171f4d1 100644
--- a/src/interpret/walker.rs
+++ b/src/interpret/walker.rs
@@ -1,7 +1,10 @@
-use std::{cell::RefCell, rc::Rc};
+use std::{cell::RefCell, collections::HashMap, rc::Rc};
 
 use crate::{
-    interpret::value::FnValue,
+    interpret::{
+        operator::ValueOperator,
+        value::{FnValue, ValueVariant},
+    },
     parse::ast::{
         expression::Expression,
         nodes::{
@@ -10,27 +13,32 @@ use crate::{
         statement::Statement,
         Program,
     },
+    types::{bag::TypeBag, TypeVariant},
 };
 use thiserror::Error;
 
 use super::{
+    operator::OperationError,
     scope::{ScopeChain, ScopeError},
-    value::{OperationError, Value},
+    value::Value,
 };
 
 pub struct Walker {
+    types: TypeBag,
     scope: ScopeChain,
 }
 
 impl Walker {
-    pub fn new() -> Self {
+    // Should preferably be called only once.
+    pub fn root() -> Self {
         Walker {
             scope: ScopeChain::new(),
+            types: TypeBag::new(),
         }
     }
 
-    pub fn new_with_scope(scope: ScopeChain) -> Self {
-        Walker { scope }
+    pub fn new(scope: ScopeChain, types: TypeBag) -> Self {
+        Walker { scope, types }
     }
 
     pub fn walk(&mut self, program: &Program) {
@@ -85,17 +93,17 @@ impl Walker {
                 // Short-circuting operators
                 if let BinOp::And | BinOp::Or = op {
                     let left_value = self.walk_expression(left)?;
-                    let is_left_true = match left_value {
-                        Value::Bool(bool) => bool,
+                    let is_left_true = match left_value.variant {
+                        ValueVariant::Bool(bool) => bool,
                         _ => return Err(WalkerError::WrongAndOrType),
                     };
 
                     if let BinOp::And = op {
                         if !is_left_true {
-                            return Ok(Value::Bool(false));
+                            return Ok(Value::bool(false, &self.types));
                         }
                     } else if is_left_true {
-                        return Ok(Value::Bool(true));
+                        return Ok(Value::bool(true, &self.types));
                     }
 
                     return self.walk_expression(right);
@@ -104,19 +112,21 @@ impl Walker {
                 let left = self.walk_expression(left)?;
                 let right = self.walk_expression(right)?;
 
+                let exe = ValueOperator::new(&self.types);
+
                 // Other operators
                 match op {
-                    BinOp::Plus => left.add(right),
-                    BinOp::Minus => left.sub(right),
-                    BinOp::Star => left.mul(right),
-                    BinOp::Slash => left.div(right),
+                    BinOp::Plus => exe.add(left, right),
+                    BinOp::Minus => exe.sub(left, right),
+                    BinOp::Star => exe.mul(left, right),
+                    BinOp::Slash => exe.div(left, right),
                     BinOp::Dot => todo!("Structures not implemented yet."),
-                    BinOp::Eq => left.eq(right),
-                    BinOp::Neq => left.neq(right),
-                    BinOp::Gt => left.gt(right),
-                    BinOp::Gte => left.gte(right),
-                    BinOp::Lt => right.gt(left),
-                    BinOp::Lte => right.gte(left),
+                    BinOp::Eq => exe.eq(left, right),
+                    BinOp::Neq => exe.neq(left, right),
+                    BinOp::Gt => exe.gt(left, right),
+                    BinOp::Gte => exe.gte(left, right),
+                    BinOp::Lt => exe.gt(right, left),
+                    BinOp::Lte => exe.gte(right, left),
 
                     _ => unreachable!(),
                 }
@@ -125,9 +135,11 @@ impl Walker {
             Expression::Unary { op, right } => {
                 let value = self.walk_expression(right)?;
 
+                let exe = ValueOperator::new(&self.types);
+
                 match op {
-                    UnOp::Minus => value.neg(),
-                    UnOp::Not => value.not(),
+                    UnOp::Minus => exe.neg(value),
+                    UnOp::Not => exe.not(value),
                 }
                 .map_err(WalkerError::OperationError)
             }
@@ -139,12 +151,16 @@ impl Walker {
                     argument_values.push(self.walk_expression(argument_node)?);
                 }
 
-                called.call(argument_values)
+                let exe = ValueOperator::new(&self.types);
+                exe.call(&called, argument_values)
             }
             Expression::ArrayAccess(node) => {
                 let array = self.walk_expression(&node.array)?;
                 let index = self.walk_expression(&node.index)?;
-                array.subscript(index).map_err(WalkerError::OperationError)
+
+                let exe = ValueOperator::new(&self.types);
+                exe.subscript(array, index)
+                    .map_err(WalkerError::OperationError)
             }
             Expression::MemberAccess(_) => todo!("Structures not implemented yet."),
             Expression::Group(node) => self.walk_expression(node),
@@ -153,13 +169,19 @@ impl Walker {
                 for expression in &node.elements {
                     elements.push(self.walk_expression(expression)?);
                 }
-                Ok(Value::Array(Rc::new(RefCell::new(elements))))
+                Ok(Value {
+                    variant: ValueVariant::Array(Rc::new(RefCell::new(elements))),
+                    // FIXME: Use actual type.
+                    typ: self
+                        .types
+                        .create_type(TypeVariant::Array(self.types.void())),
+                })
             }
             Expression::SimpleLiteral(token) => {
                 let value = match token {
-                    SimpleLiteral::Int(int) => Value::Int(*int as i64),
-                    SimpleLiteral::Float(float) => Value::Float(*float as f64),
-                    SimpleLiteral::Bool(bool) => Value::Bool(*bool),
+                    SimpleLiteral::Int(int) => Value::int(*int as i64, &self.types),
+                    SimpleLiteral::Float(float) => Value::float(*float as f64, &self.types),
+                    SimpleLiteral::Bool(bool) => Value::bool(*bool, &self.types),
                 };
 
                 Ok(value)
@@ -177,15 +199,24 @@ impl Walker {
                     };
                 }
 
-                Ok(Value::Str(buffer))
+                Ok(Value::str(buffer, &self.types))
             }
-            Expression::FnLiteral(node) => Ok(Value::Fn(Rc::new(RefCell::new(FnValue {
-                node: node.as_ref().clone(),
-                scope: self.scope.clone(),
-            })))),
+            Expression::FnLiteral(node) => Ok(Value {
+                variant: ValueVariant::Fn(Rc::new(RefCell::new(FnValue {
+                    node: node.as_ref().clone(),
+                    scope: self.scope.clone(),
+                }))),
+                // FIXME: Use actual type here.
+                typ: self.types.create_type(TypeVariant::Fn {
+                    parameters: HashMap::new(),
+                    returns: self.types.void(),
+                }),
+            }),
             Expression::If(if_node) => {
                 for conditional in &if_node.conditionals {
-                    if let Value::Bool(bool) = self.walk_expression(&conditional.condition)? {
+                    if let ValueVariant::Bool(bool) =
+                        self.walk_expression(&conditional.condition)?.variant
+                    {
                         if bool {
                             return self.walk_block(&conditional.block);
                         }
@@ -197,17 +228,19 @@ impl Walker {
                 if let Some(else_conditional) = &if_node.else_block {
                     self.walk_block(else_conditional)
                 } else {
-                    Ok(Value::Void)
+                    Ok(Value::void(&self.types))
                 }
             }
             Expression::Loop(loop_node) => {
                 if let Some(condition) = &loop_node.condition {
                     loop {
-                        if let Value::Bool(should_repeat) = self.walk_expression(condition)? {
+                        if let ValueVariant::Bool(should_repeat) =
+                            self.walk_expression(condition)?.variant
+                        {
                             if should_repeat {
                                 match self.walk_block(&loop_node.body) {
                                     Err(WalkerError::LoopBreak(loop_value)) => {
-                                        return Ok(loop_value.unwrap_or(Value::Void));
+                                        return Ok(loop_value.unwrap_or(Value::void(&self.types)));
                                     }
                                     // Do nothing for continue and continue looping of course, you dummy.
                                     Err(WalkerError::LoopContinue) => {}
@@ -216,7 +249,7 @@ impl Walker {
                                     _ => {}
                                 }
                             } else {
-                                return Ok(Value::Void);
+                                return Ok(Value::void(&self.types));
                             }
                         } else {
                             return Err(WalkerError::WrongLoopConditionType);
@@ -227,7 +260,7 @@ impl Walker {
                     loop {
                         match self.walk_block(&loop_node.body) {
                             Err(WalkerError::LoopBreak(loop_value)) => {
-                                break Ok(loop_value.unwrap_or(Value::Void));
+                                break Ok(loop_value.unwrap_or(Value::void(&self.types)));
                             }
                             Err(WalkerError::LoopContinue) => {}
                             Err(x) => return Err(x),
@@ -236,9 +269,10 @@ impl Walker {
                     }
                 }
             }
-            Expression::Identifier(ident) => {
-                self.scope.get_var(ident).map_err(WalkerError::ScopeError)
-            }
+            Expression::Identifier(ident) => self
+                .scope
+                .get_var(ident, &self.types)
+                .map_err(WalkerError::ScopeError),
         }
     }
 
@@ -252,7 +286,7 @@ impl Walker {
         let result = if let Some(tail_expression) = &block.tail_expression {
             Ok(self.walk_expression(tail_expression)?)
         } else {
-            Ok(Value::Void)
+            Ok(Value::void(&self.types))
         };
 
         self.scope.unnest();
@@ -274,8 +308,9 @@ impl Walker {
                 let index = self.walk_expression(&node.index)?;
                 let value = self.walk_expression(rvalue)?;
 
-                array
-                    .subscript_assign(index, value)
+                let exe = ValueOperator::new(&self.types);
+
+                exe.subscript_assign(&mut array, index, value)
                     .map_err(WalkerError::OperationError)
             }
             Expression::Identifier(ident) => {
diff --git a/src/main.rs b/src/main.rs
index 9128cdb..0df0483 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@ use std::{env, fs, path::Path};
 mod interpret;
 mod lex;
 mod parse;
+mod types;
 
 use lex::lexer::Lexer;
 
@@ -27,7 +28,7 @@ fn file(filename: impl AsRef<Path>) {
     let mut parser = Parser::new(lexer);
 
     let node = parser.parse().expect("Failed parsing.");
-    let mut walker = Walker::new();
+    let mut walker = Walker::root();
 
     walker.walk(&node);
 }
@@ -35,7 +36,7 @@ fn file(filename: impl AsRef<Path>) {
 fn repl() {
     const PROMPT: &str = "🐇: ";
 
-    let mut walker = Walker::new();
+    let mut walker = Walker::root();
 
     let mut input_buffer;
 
diff --git a/src/types/bag.rs b/src/types/bag.rs
new file mode 100644
index 0000000..30202fd
--- /dev/null
+++ b/src/types/bag.rs
@@ -0,0 +1,123 @@
+use std::{cell::RefCell, collections::HashMap};
+
+use super::{RefValueMap, Type, TypeVariant};
+
+#[derive(Clone)]
+pub struct TypeBag {
+    global_associated_values: &'static GlobalAssociatedValues,
+    atomic_types: AtomicTypes,
+}
+
+impl TypeBag {
+    pub fn new() -> Self {
+        // Hehe don't mind me
+        let leaked_values: &'static GlobalAssociatedValues =
+            Box::leak(Box::new(GlobalAssociatedValues::new()));
+        let atomic_types = AtomicTypes::new(&leaked_values);
+
+        TypeBag {
+            global_associated_values: leaked_values,
+            atomic_types,
+        }
+    }
+
+    pub fn create_type(&self, variant: TypeVariant) -> Type {
+        let global_associated_values_for_type = match variant {
+            TypeVariant::Fn { .. } => &self.global_associated_values.fn_values,
+            TypeVariant::Array(_) => &self.global_associated_values.array_values,
+            TypeVariant::Tuple(_) => &self.global_associated_values.tuple_values,
+            TypeVariant::Data { .. } => &self.global_associated_values.data_values,
+            TypeVariant::Str
+            | TypeVariant::Int
+            | TypeVariant::Float
+            | TypeVariant::Bool
+            | TypeVariant::Void => panic!("There should only be one type {:?}.", variant),
+            TypeVariant::Face(_) | TypeVariant::Var(_) => todo!("Implement abstract types."),
+        };
+
+        Type {
+            variant: Box::new(variant),
+            global_associated_values: global_associated_values_for_type,
+        }
+    }
+
+    pub fn str(&self) -> Type {
+        self.atomic_types.str_type.clone()
+    }
+
+    pub fn int(&self) -> Type {
+        self.atomic_types.int_type.clone()
+    }
+
+    pub fn float(&self) -> Type {
+        self.atomic_types.float_type.clone()
+    }
+
+    pub fn bool(&self) -> Type {
+        self.atomic_types.bool_type.clone()
+    }
+
+    pub fn void(&self) -> Type {
+        self.atomic_types.void_type.clone()
+    }
+}
+
+struct GlobalAssociatedValues {
+    str_values: RefValueMap,
+    int_values: RefValueMap,
+    float_values: RefValueMap,
+    bool_values: RefValueMap,
+    void_values: RefValueMap,
+    fn_values: RefValueMap,
+    array_values: RefValueMap,
+    tuple_values: RefValueMap,
+    data_values: RefValueMap,
+}
+
+impl GlobalAssociatedValues {
+    fn new() -> Self {
+        GlobalAssociatedValues {
+            str_values: Self::create_value_map(),
+            int_values: Self::create_value_map(),
+            float_values: Self::create_value_map(),
+            bool_values: Self::create_value_map(),
+            void_values: Self::create_value_map(),
+            fn_values: Self::create_value_map(),
+            array_values: Self::create_value_map(),
+            tuple_values: Self::create_value_map(),
+            data_values: Self::create_value_map(),
+        }
+    }
+
+    fn create_value_map() -> RefValueMap {
+        RefCell::new(HashMap::new())
+    }
+}
+
+#[derive(Clone)]
+struct AtomicTypes {
+    str_type: Type,
+    int_type: Type,
+    float_type: Type,
+    bool_type: Type,
+    void_type: Type,
+}
+
+impl AtomicTypes {
+    fn new(values: &'static GlobalAssociatedValues) -> Self {
+        AtomicTypes {
+            str_type: Self::create_single_type(TypeVariant::Str, &values.str_values),
+            int_type: Self::create_single_type(TypeVariant::Int, &values.int_values),
+            float_type: Self::create_single_type(TypeVariant::Float, &values.float_values),
+            bool_type: Self::create_single_type(TypeVariant::Bool, &values.bool_values),
+            void_type: Self::create_single_type(TypeVariant::Void, &values.void_values),
+        }
+    }
+
+    fn create_single_type(variant: TypeVariant, values: &'static RefValueMap) -> Type {
+        Type {
+            variant: Box::new(variant),
+            global_associated_values: values,
+        }
+    }
+}
diff --git a/src/types/mod.rs b/src/types/mod.rs
new file mode 100644
index 0000000..f3257eb
--- /dev/null
+++ b/src/types/mod.rs
@@ -0,0 +1,42 @@
+pub mod bag;
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+
+use crate::interpret::value::ValueMap;
+use crate::parse::ast::nodes::Identifier;
+
+#[derive(Debug, Clone)]
+pub struct Type {
+    variant: Box<TypeVariant>,
+    global_associated_values: &'static RefValueMap,
+}
+
+#[derive(Debug, Clone)]
+pub enum TypeVariant {
+    // Concrete types
+    Str,
+    Int,
+    Float,
+    Bool,
+    Void,
+    Fn {
+        parameters: TypeMap,
+        returns: Type,
+    },
+    Array(Type),
+    Tuple(Vec<Type>),
+    Data {
+        data: TypeMap,
+        associated_values: RefValueMap,
+    },
+    // TODO: Implement abstract types.
+    // These should also definitely have `associated_values`,
+    // but as they're not implemented yet...
+    Face(TypeMap),
+    Var(TypeMap),
+}
+
+type TypeMap = HashMap<Identifier, Type>;
+
+type RefValueMap = RefCell<ValueMap>;
\ No newline at end of file