about summary refs log tree commit diff
path: root/src/interpret/walker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpret/walker.rs')
-rw-r--r--src/interpret/walker.rs125
1 files changed, 80 insertions, 45 deletions
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) => {