about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/interpret/mod.rs1
-rw-r--r--src/interpret/walker.rs150
-rw-r--r--src/main.rs10
3 files changed, 159 insertions, 2 deletions
diff --git a/src/interpret/mod.rs b/src/interpret/mod.rs
new file mode 100644
index 0000000..2544ca3
--- /dev/null
+++ b/src/interpret/mod.rs
@@ -0,0 +1 @@
+pub mod walker;
\ No newline at end of file
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
new file mode 100644
index 0000000..1602cd2
--- /dev/null
+++ b/src/interpret/walker.rs
@@ -0,0 +1,150 @@
+use std::{
+    fmt::Display,
+    ops::{Add, Div, Mul, Neg, Sub},
+};
+
+use crate::{lex::token::TokenVariant::*, parse::ast::Expression};
+use anyhow::Result;
+
+// No state for now.
+pub struct Walker {}
+
+impl Walker {
+    pub fn new() -> Self {
+        Walker {}
+    }
+
+    pub fn walk(&self, node: &Expression) -> Result<WalkValue> {
+        match node {
+            Expression::Binary { left, op, right } => {
+                let left_value = self.walk(left)?;
+                let right_value = self.walk(right)?;
+
+                let new_value = match op.variant {
+                    OpPlus => left_value + right_value,
+                    OpMinus => left_value - right_value,
+                    OpStar => left_value * right_value,
+                    OpSlash => left_value / right_value,
+                    _ => unreachable!(),
+                };
+
+                Ok(new_value)
+            }
+            Expression::Unary { op, right } => {
+                let value = self.walk(right)?;
+
+                let new_value = match op.variant {
+                    OpPlus => value,
+                    OpMinus => -value,
+                    OpNot => todo!("Implement boolean arithmetic."),
+                    _ => unreachable!(),
+                };
+
+                Ok(new_value)
+            }
+            Expression::Group(node) => self.walk(node),
+            Expression::Literal(token) => {
+                let value = match token.variant {
+                    Int(int) => WalkValue::Int(int as i64),
+                    Float(float) => WalkValue::Float(float as f64),
+                    _ => unreachable!(),
+                };
+
+                Ok(value)
+            }
+        }
+    }
+}
+
+pub enum WalkValue {
+    Float(f64),
+    Int(i64),
+}
+
+impl Add for WalkValue {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        match self {
+            Self::Float(float) => match rhs {
+                Self::Float(other_float) => Self::Float(float + other_float),
+                Self::Int(other_int) => Self::Float(float + other_int as f64),
+            },
+            Self::Int(int) => match rhs {
+                Self::Float(other_float) => Self::Float(int as f64 + other_float),
+                Self::Int(other_int) => Self::Int(int + other_int),
+            },
+        }
+    }
+}
+
+impl Sub for WalkValue {
+    type Output = Self;
+
+    fn sub(self, rhs: Self) -> Self::Output {
+        match self {
+            Self::Float(float) => match rhs {
+                Self::Float(other_float) => Self::Float(float - other_float),
+                Self::Int(other_int) => Self::Float(float - other_int as f64),
+            },
+            Self::Int(int) => match rhs {
+                Self::Float(other_float) => Self::Float(int as f64 - other_float),
+                Self::Int(other_int) => Self::Int(int - other_int),
+            },
+        }
+    }
+}
+
+impl Mul for WalkValue {
+    type Output = Self;
+
+    fn mul(self, rhs: Self) -> Self::Output {
+        match self {
+            Self::Float(float) => match rhs {
+                Self::Float(other_float) => Self::Float(float * other_float),
+                Self::Int(other_int) => Self::Float(float * other_int as f64),
+            },
+            Self::Int(int) => match rhs {
+                Self::Float(other_float) => Self::Float(int as f64 * other_float),
+                Self::Int(other_int) => Self::Int(int * other_int),
+            },
+        }
+    }
+}
+
+impl Div for WalkValue {
+    type Output = Self;
+
+    fn div(self, rhs: Self) -> Self::Output {
+        match self {
+            Self::Float(float) => match rhs {
+                Self::Float(other_float) => Self::Float(float / other_float),
+                Self::Int(other_int) => Self::Float(float / other_int as f64),
+            },
+            Self::Int(int) => match rhs {
+                Self::Float(other_float) => Self::Float(int as f64 / other_float),
+                Self::Int(other_int) => Self::Int(int / other_int),
+            },
+        }
+    }
+}
+
+impl Neg for WalkValue {
+    type Output = Self;
+
+    fn neg(self) -> Self::Output {
+        match self {
+            Self::Float(float) => Self::Float(-float),
+            Self::Int(int) => Self::Int(-int),
+        }
+    }
+}
+
+impl Display for WalkValue {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Float(float) => write!(f, "{}", float),
+            Self::Int(int) => write!(f, "{}", int),
+        }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 3fa6bbf..1825af5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,11 @@
+mod interpret;
 mod lex;
 mod parse;
 
 use lex::lexer::Lexer;
 
-use crate::parse::parser::Parser;
+use interpret::walker::Walker;
+use parse::parser::Parser;
 
 fn main() {
     let source = "1 * 2 + 3 + (-1)";
@@ -11,5 +13,9 @@ fn main() {
     let lexer = Lexer::new(source);
     let mut parser = Parser::new(lexer);
 
-    println!("{}", parser.parse().expect("Failed parsing."));
+    let node = parser.parse().expect("Failed parsing.");
+
+    let walker = Walker::new();
+    let result = walker.walk(&node).expect("Failed interpreting.");
+    println!("{}", result);
 }