@@ -4,8 +4,17 @@ use crate::{lang::ast::*, runtime::Opcode};
4
4
#[ derive( Debug ) ]
5
5
pub enum CompileError { }
6
6
7
+ /// Compiles a single expression into a sequence of opcodes
8
+ pub fn compile_expression ( expression : & Expression ) -> Result < Vec < Opcode > , CompileError > {
9
+ let mut compiler = Compiler :: default ( ) ;
10
+
11
+ compiler. compile_expression ( expression) ?;
12
+
13
+ Ok ( compiler. instructions )
14
+ }
15
+
7
16
/// Compiles a set of [`Statement`]s into [`Opcode`]s.
8
- pub fn compile ( statements : & [ Statement ] ) -> Result < Vec < Opcode > , CompileError > {
17
+ pub fn compile_statements ( statements : & [ Statement ] ) -> Result < Vec < Opcode > , CompileError > {
9
18
let mut compiler = Compiler :: default ( ) ;
10
19
11
20
for statement in statements {
@@ -22,6 +31,7 @@ struct Compiler {
22
31
}
23
32
24
33
impl Compiler {
34
+ /// Compiles a single statement into a sequence of opcodes.
25
35
pub fn compile_statement ( & mut self , statement : & Statement ) -> Result < ( ) , CompileError > {
26
36
match statement {
27
37
Statement :: Expression ( expression) => {
@@ -38,22 +48,20 @@ impl Compiler {
38
48
Ok ( ( ) )
39
49
}
40
50
51
+ /// Compiles a single expression into a sequence of opcodes.
41
52
pub fn compile_expression ( & mut self , expression : & Expression ) -> Result < ( ) , CompileError > {
42
53
match expression {
43
54
Expression :: Literal ( literal) => {
44
55
let value = literal. clone ( ) ;
45
-
46
56
self . instructions . push ( Opcode :: Literal ( value) )
47
57
}
48
58
Expression :: Binary ( left, operator, right) => {
49
59
self . compile_expression ( left) ?;
50
60
self . compile_expression ( right) ?;
51
-
52
61
self . instructions . push ( Opcode :: Binary ( * operator) ) ;
53
62
}
54
63
Expression :: Unary ( operator, value) => {
55
64
self . compile_expression ( value) ?;
56
-
57
65
self . instructions . push ( Opcode :: Unary ( * operator) ) ;
58
66
}
59
67
}
@@ -68,21 +76,42 @@ mod tests {
68
76
69
77
use super :: * ;
70
78
71
- #[ test]
72
- fn test_compile_basic_program ( ) {
73
- let statements = vec ! [ Statement :: Return ( Expression :: Binary (
79
+ macro_rules! compile_test {
80
+ ( $name: ident, $statements: expr, $expected: expr) => {
81
+ #[ test]
82
+ fn $name( ) {
83
+ let instructions = compile_statements( $statements) . unwrap( ) ;
84
+ assert_eq!( instructions, $expected) ;
85
+ }
86
+ } ;
87
+ }
88
+
89
+ compile_test ! (
90
+ test_compile_basic_program,
91
+ & vec![ Statement :: Return ( Expression :: Binary (
74
92
Box :: new( Expression :: Literal ( Variant :: I64 ( 1 ) ) ) ,
75
93
BinaryOp :: Add ,
76
94
Box :: new( Expression :: Literal ( Variant :: I64 ( 2 ) ) ) ,
77
- ) ) ] ;
78
-
79
- let instructions = compile ( & statements) . unwrap ( ) ;
80
-
81
- assert_eq ! ( instructions, vec![
95
+ ) ) ] ,
96
+ vec![
82
97
Opcode :: Literal ( Variant :: I64 ( 1 ) ) ,
83
98
Opcode :: Literal ( Variant :: I64 ( 2 ) ) ,
84
99
Opcode :: Binary ( BinaryOp :: Add ) ,
85
100
Opcode :: Return ,
86
- ] ) ;
87
- }
101
+ ]
102
+ ) ;
103
+
104
+ compile_test ! (
105
+ test_compile_single_expression,
106
+ & vec![ Statement :: Expression ( Expression :: Binary (
107
+ Box :: new( Expression :: Literal ( Variant :: I64 ( 3 ) ) ) ,
108
+ BinaryOp :: Multiply ,
109
+ Box :: new( Expression :: Literal ( Variant :: I64 ( 4 ) ) ) ,
110
+ ) ) ] ,
111
+ vec![
112
+ Opcode :: Literal ( Variant :: I64 ( 3 ) ) ,
113
+ Opcode :: Literal ( Variant :: I64 ( 4 ) ) ,
114
+ Opcode :: Binary ( BinaryOp :: Multiply ) ,
115
+ ]
116
+ ) ;
88
117
}
0 commit comments