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
|
use std::{cell::RefCell, rc::Rc};
use crate::parse::ast::{
expression::Expression,
nodes::{BinaryOperator as BinOp, Literal, UnaryOperator as UnOp},
statement::Statement,
Program,
};
use anyhow::{anyhow, Result};
use super::{scope::Scope, value::Value};
// No state for now.
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)
}
fn walk_expression(&mut self, node: &Expression) -> Result<Value> {
match node {
Expression::Binary { left, op, right } => {
let new_value = match op {
BinOp::Plus => self
.walk_expression(left)?
.add(self.walk_expression(right)?),
BinOp::Minus => self
.walk_expression(left)?
.sub(self.walk_expression(right)?),
BinOp::Star => self
.walk_expression(left)?
.mul(self.walk_expression(right)?),
BinOp::Slash => self
.walk_expression(left)?
.div(self.walk_expression(right)?),
// No difference between assignments for now.
BinOp::Assign | BinOp::ConstAssign => {
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());
Ok(value)
}
// Boolean logic comes later.
BinOp::Eq | BinOp::Neq | BinOp::Gt | BinOp::Gte | BinOp::Lt | BinOp::Lte => {
todo!()
}
// No structure access yet.
BinOp::Dot => todo!(),
}?;
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()),
};
Ok(value)
}
Expression::Block(block) => {
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
}
Expression::Fn(fn_node) => {
let node = fn_node.as_ref().clone();
Ok(Value::Fn(RefCell::new(Rc::new(node))))
}
Expression::If(_) => todo!(),
Expression::Identifier(ident) => {
if let Some(value) = self.scope.get_var(ident) {
Ok(value)
} else {
Err(anyhow!("Unknown identifier: {}.", ident))
}
}
}
}
}
|