1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
use std::{cell::RefCell, rc::Rc};
use crate::parse::ast::{
expression::Expression,
nodes::{BinaryOperator as BinOp, BlockNode, Literal, UnaryOperator as UnOp},
statement::Statement,
Program,
};
use anyhow::{anyhow, Result};
use super::{scope::Scope, value::Value};
pub struct Walker {
scope: Scope,
}
impl Walker {
pub fn new() -> Self {
Walker {
scope: Scope::new(),
}
}
pub fn walk(&mut self, program: &Program) {
self.scope.nest();
for statement in program.statements.iter() {
self.walk_statement(statement).expect("Runtime error.");
}
}
fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>> {
let result = match statement {
Statement::Expression(node) => {
self.walk_expression(node)?;
None
}
Statement::Print(node) => {
let result = self.walk_expression(node)?;
println!("{:?}", result);
None
}
Statement::Return(node) => Some(self.walk_expression(node)?),
};
Ok(result)
}
pub fn walk_expression(&mut self, node: &Expression) -> Result<Value> {
match node {
Expression::Binary { left, op, right } => {
// Assignment
// No difference between assignments for now.
if let BinOp::ConstAssign | BinOp::Assign = op {
let identifier = match left.as_ref() {
Expression::Identifier(i) => i,
_ => todo!("Lvalues can only be identifiers."),
};
let value = self.walk_expression(right)?;
self.scope.set_var(identifier, value.clone());
return Ok(value);
}
let left = self.walk_expression(left)?;
let right = self.walk_expression(right)?;
// Other operators
let new_value = match op {
BinOp::Plus => left.add(right),
BinOp::Minus => left.sub(right),
BinOp::Star => left.mul(right),
BinOp::Slash => left.div(right),
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),
// No structure access yet.
BinOp::Dot => todo!(),
_ => unreachable!(),
}?;
Ok(new_value)
}
Expression::Unary { op, right } => {
let value = self.walk_expression(right)?;
let new_value = match op {
UnOp::Plus => value,
UnOp::Minus => todo!(),
UnOp::Not => todo!("Implement boolean arithmetic."),
};
Ok(new_value)
}
Expression::Group(node) => self.walk_expression(node),
Expression::Literal(token) => {
let value = match token {
Literal::Int(int) => Value::Int(*int as i64),
Literal::Float(float) => Value::Float(*float as f64),
Literal::Str(string) => Value::Str(string.clone()),
Literal::Bool(bool) => Value::Bool(*bool),
};
Ok(value)
}
Expression::Block(block) => self.walk_block(block.as_ref()),
Expression::Fn(fn_node) => {
let node = fn_node.as_ref().clone();
Ok(Value::Fn(RefCell::new(Rc::new(node))))
}
Expression::If(if_node) => {
for conditional in &if_node.conditionals {
if let Value::Bool(bool) = self.walk_expression(&conditional.condition)? {
if bool {
return self.walk_block(&conditional.block);
}
} else {
return Err(anyhow!(
"If and Elif expressions can only take boolean values as conditions."
));
}
}
if let Some(else_conditional) = &if_node.else_block {
self.walk_block(else_conditional)
} else {
Ok(Value::Void)
}
}
Expression::Identifier(ident) => {
if let Some(value) = self.scope.get_var(ident) {
Ok(value)
} else {
Err(anyhow!("Unknown identifier: {}.", ident))
}
}
}
}
fn walk_block(&mut self, block: &BlockNode) -> Result<Value> {
self.scope.nest();
for statement in block.statements.iter() {
self.walk_statement(statement)?;
}
let result = if let Some(tail_expression) = &block.tail_expression {
Ok(self.walk_expression(tail_expression)?)
} else {
Ok(Value::Void)
};
self.scope.unnest();
result
}
}
|