1use std::{
4 collections::HashMap,
5 error::Error,
6 fmt::Display,
7 ops::{Add, Div, Mul, Sub},
8};
9
10use crate::parser::ast::{BinaryOp, Expr, Literal, UnaryOp};
11
12#[derive(Debug, Default, Clone)]
14pub struct Interpretter<'a> {
15 context: HashMap<String, Literal<'a>>,
17}
18
19#[derive(Debug, Clone, Copy)]
21pub struct RuntimeError;
22
23impl Display for RuntimeError {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "Runtime Error")
26 }
27}
28
29impl Error for RuntimeError {}
30
31impl<'a> Interpretter<'a> {
32 pub fn eval(&mut self, ast: Expr<'a>) -> Result<Literal<'a>, RuntimeError> {
34 match ast {
35 Expr::Variable(var) => Ok(self.context[var]),
36 Expr::Print(node) => {
37 println!("{}", self.eval(*node)?);
38 Ok(Literal::Null)
39 }
40 Expr::Assignment(name, val) => {
41 let val = self.eval(*val)?;
42 self.context.insert(name.to_string(), val);
43 Ok(Literal::Null)
44 }
45 Expr::Literal(l) => Ok(l),
46 Expr::Grouping(inner) => self.eval(*inner),
47 Expr::Binary { op, left, right } => op.eval(self.eval(*left)?, self.eval(*right)?),
48 Expr::Unary { op, node } => op.eval(self.eval(*node)?),
49 }
50 }
51}
52
53impl BinaryOp {
54 pub fn eval<'a>(
56 &self,
57 left: Literal<'a>,
58 right: Literal<'a>,
59 ) -> Result<Literal<'a>, RuntimeError> {
60 match self {
61 Self::Add => left + right,
62 Self::Sub => left - right,
63 Self::Mul => left * right,
64 Self::Div => left / right,
65
66 Self::Gt => Ok(Literal::Bool(left.number()? > right.number()?)),
67 Self::Gte => Ok(Literal::Bool(left.number()? >= right.number()?)),
68 Self::Lt => Ok(Literal::Bool(left.number()? < right.number()?)),
69 Self::Lte => Ok(Literal::Bool(left.number()? <= right.number()?)),
70
71 Self::Eq => left.equals(&right),
72 Self::Neq => left.not_equals(&right),
73 }
74 }
75}
76
77impl UnaryOp {
78 pub fn eval<'a>(&self, node: Literal<'a>) -> Result<Literal<'a>, RuntimeError> {
80 match self {
81 Self::Neg => Ok(Literal::Number(-node.number()?)),
82 Self::Not => Ok(Literal::Bool(!node.bool()?)),
83 }
84 }
85}
86
87impl Add for Literal<'_> {
88 type Output = Result<Self, RuntimeError>;
89
90 fn add(self, rhs: Self) -> Self::Output {
91 match (self, rhs) {
92 (Self::Number(n1), Self::Number(n2)) => Ok(Literal::Number(n1 + n2)),
93
94 _ => Err(RuntimeError),
95 }
96 }
97}
98
99impl Sub for Literal<'_> {
100 type Output = Result<Self, RuntimeError>;
101 fn sub(self, rhs: Self) -> Self::Output {
102 match (self, rhs) {
103 (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 - n2)),
104
105 _ => Err(RuntimeError),
106 }
107 }
108}
109
110impl Mul for Literal<'_> {
111 type Output = Result<Self, RuntimeError>;
112 fn mul(self, rhs: Self) -> Self::Output {
113 match (self, rhs) {
114 (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 * n2)),
115
116 _ => Err(RuntimeError),
117 }
118 }
119}
120
121impl Div for Literal<'_> {
122 type Output = Result<Self, RuntimeError>;
123 fn div(self, rhs: Self) -> Self::Output {
124 match (self, rhs) {
125 (Self::Number(n1), Self::Number(n2)) => Ok(Self::Number(n1 / n2)),
126 _ => Err(RuntimeError),
127 }
128 }
129}
130
131impl<'a> Literal<'a> {
132 pub fn uint(&self) -> Result<usize, RuntimeError> {
135 match self {
136 Self::Number(n) if *n >= 0.0 && n.round() == *n => Ok(*n as usize),
137 _ => Err(RuntimeError),
138 }
139 }
140 pub fn number(&self) -> Result<f64, RuntimeError> {
142 match self {
143 Self::Number(n) => Ok(*n),
144 _ => Err(RuntimeError),
145 }
146 }
147
148 pub fn bool(&self) -> Result<bool, RuntimeError> {
150 match self {
151 Self::Bool(val) => Ok(*val),
152 Self::Number(0.0) => Ok(false),
153 Self::Number(_) => Ok(true),
154 _ => Err(RuntimeError),
155 }
156 }
157
158 pub fn equals(&self, other: &Self) -> Result<Literal<'a>, RuntimeError> {
160 match (self, other) {
161 (Self::Number(n1), Self::Number(n2)) => Ok(Self::Bool(n1 == n2)),
162 (Self::Bool(b1), Self::Bool(b2)) => Ok(Self::Bool(b1 == b2)),
163
164 (Self::Null, Self::Null) => Ok(Self::Bool(true)),
165
166 (crazy1, crazy2) => Ok(Literal::Bool(crazy1.to_string() == crazy2.to_string())),
167 }
168 }
169
170 pub fn not_equals(&self, other: &Self) -> Result<Literal<'a>, RuntimeError> {
172 match (self, other) {
173 (Self::Number(n1), Self::Number(n2)) => Ok(Self::Bool(n1 != n2)),
174 (Self::Bool(b1), Self::Bool(b2)) => Ok(Self::Bool(b1 != b2)),
175
176 (Self::Null, Self::Null) => Ok(Self::Bool(false)),
177
178 (crazy1, crazy2) => Ok(Literal::Bool(crazy1.to_string() != crazy2.to_string())),
179 }
180 }
181}