@@ -4,8 +4,17 @@ use crate::{lang::ast::*, runtime::Opcode};
44#[ derive( Debug ) ]
55pub enum CompileError { }
66
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+
716/// 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 > {
918 let mut compiler = Compiler :: default ( ) ;
1019
1120 for statement in statements {
@@ -22,6 +31,7 @@ struct Compiler {
2231}
2332
2433impl Compiler {
34+ /// Compiles a single statement into a sequence of opcodes.
2535 pub fn compile_statement ( & mut self , statement : & Statement ) -> Result < ( ) , CompileError > {
2636 match statement {
2737 Statement :: Expression ( expression) => {
@@ -38,22 +48,20 @@ impl Compiler {
3848 Ok ( ( ) )
3949 }
4050
51+ /// Compiles a single expression into a sequence of opcodes.
4152 pub fn compile_expression ( & mut self , expression : & Expression ) -> Result < ( ) , CompileError > {
4253 match expression {
4354 Expression :: Literal ( literal) => {
4455 let value = literal. clone ( ) ;
45-
4656 self . instructions . push ( Opcode :: Literal ( value) )
4757 }
4858 Expression :: Binary ( left, operator, right) => {
4959 self . compile_expression ( left) ?;
5060 self . compile_expression ( right) ?;
51-
5261 self . instructions . push ( Opcode :: Binary ( * operator) ) ;
5362 }
5463 Expression :: Unary ( operator, value) => {
5564 self . compile_expression ( value) ?;
56-
5765 self . instructions . push ( Opcode :: Unary ( * operator) ) ;
5866 }
5967 }
@@ -68,21 +76,42 @@ mod tests {
6876
6977 use super :: * ;
7078
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 (
7492 Box :: new( Expression :: Literal ( Variant :: I64 ( 1 ) ) ) ,
7593 BinaryOp :: Add ,
7694 Box :: new( Expression :: Literal ( Variant :: I64 ( 2 ) ) ) ,
77- ) ) ] ;
78-
79- let instructions = compile ( & statements) . unwrap ( ) ;
80-
81- assert_eq ! ( instructions, vec![
95+ ) ) ] ,
96+ vec![
8297 Opcode :: Literal ( Variant :: I64 ( 1 ) ) ,
8398 Opcode :: Literal ( Variant :: I64 ( 2 ) ) ,
8499 Opcode :: Binary ( BinaryOp :: Add ) ,
85100 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+ ) ;
88117}
0 commit comments