1
+ use std:: { collections:: HashMap , fmt:: { self , Debug } , fs} ;
2
+
3
+ use core:: {
4
+ ast:: {
5
+ Block , DeclSection , DesignatorItem , Expr , ProcedureDeclaration ,
6
+ Program , Stmt , TypeDeclaration , UnlabeledStmt , VarDeclaration ,
7
+ } ,
8
+ lexer:: { self , Lexer } ,
9
+ parser:: { Parser , ParserError } ,
10
+ sema:: SemanticError ,
11
+ } ;
12
+
13
+ #[ derive( Debug ) ]
14
+ pub enum CodegenError {
15
+ NotImplemented ,
16
+ UndefinedVariable ,
17
+ AssigmentToNotDefinedVariable ,
18
+ NoParentEnvironment ,
19
+ NotCallable ,
20
+ MismatchedTypes ,
21
+ MismathedArgumentsCount ,
22
+ AlreadyDefined ,
23
+ }
24
+
25
+ #[ derive( Debug , Clone ) ]
26
+ pub struct Var {
27
+ pub number : usize ,
28
+ pub use_count : usize ,
29
+ }
30
+
31
+ #[ derive( Debug , Clone ) ]
32
+ pub enum Instruction {
33
+ // Memory
34
+ Store ,
35
+ Load ,
36
+ LoadConstant { dst : Var , const_num : usize } ,
37
+
38
+ // Arithmetic operators
39
+ Add { dst : Var , src1 : Var , src2 : Var } ,
40
+ Sub { dst : Var , src1 : Var , src2 : Var } ,
41
+ Mul { dst : Var , src1 : Var , src2 : Var } ,
42
+ Div { dst : Var , src1 : Var , src2 : Var } ,
43
+ Mod { dst : Var , src1 : Var , src2 : Var } ,
44
+ Negate { dst : Var , src : Var } ,
45
+
46
+ // Login operators
47
+ LogAnd { dst : Var , src1 : Var , src2 : Var } ,
48
+ LogOr { dst : Var , src1 : Var , src2 : Var } ,
49
+ LogNot { dst : Var , src1 : Var , src2 : Var } ,
50
+ Eq { dst : Var , src1 : Var , src2 : Var } ,
51
+ Neq { dst : Var , src1 : Var , src2 : Var } ,
52
+ Lt { dst : Var , src1 : Var , src2 : Var } ,
53
+ Leq { dst : Var , src1 : Var , src2 : Var } ,
54
+ Gt { dst : Var , src1 : Var , src2 : Var } ,
55
+ Geq { dst : Var , src1 : Var , src2 : Var } ,
56
+ }
57
+
58
+ #[ derive( Debug , Clone ) ]
59
+ pub enum Constant {
60
+ Real ( f64 ) ,
61
+ Integer ( i64 ) ,
62
+ String ( String ) ,
63
+ Boolean ( bool ) ,
64
+ Null ,
65
+ }
66
+
67
+ pub struct CodeEmmiter {
68
+ pub instructions : Vec < Instruction > ,
69
+ pub number : usize ,
70
+ pub constants : Vec < Constant > ,
71
+ }
72
+
73
+ impl CodeEmmiter {
74
+ pub fn new ( ) -> Self {
75
+ CodeEmmiter {
76
+ instructions : vec ! [ ] ,
77
+ number : 0 ,
78
+ constants : vec ! [ ] ,
79
+ }
80
+ }
81
+
82
+ fn add_const ( & mut self , constant : Constant ) -> usize {
83
+ let num = self . constants . len ( ) ;
84
+ self . constants . push ( constant) ;
85
+ num
86
+ }
87
+
88
+ fn add_var ( & mut self , ) -> Var {
89
+ self . number += 1 ;
90
+ Var { number : self . number , use_count : 0 }
91
+ }
92
+
93
+ fn visit_expr ( & mut self , expr : & Box < Expr > ) -> Result < Var , CodegenError > {
94
+ match expr. as_ref ( ) {
95
+ Expr :: Binary { left, operator, right } => {
96
+ let src1 = self . visit_expr ( left) ?;
97
+ let src2 = self . visit_expr ( right) ?;
98
+ let dst = self . add_var ( ) ;
99
+ let inst = match operator. kind {
100
+ lexer:: TokenType :: Plus => Ok ( Instruction :: Add { dst : dst. clone ( ) , src1, src2 } ) ,
101
+ lexer:: TokenType :: Minus => Ok ( Instruction :: Sub { dst : dst. clone ( ) , src1, src2 } ) ,
102
+ lexer:: TokenType :: Star => Ok ( Instruction :: Mul { dst : dst. clone ( ) , src1, src2 } ) ,
103
+ lexer:: TokenType :: Slash => Ok ( Instruction :: Div { dst : dst. clone ( ) , src1, src2 } ) ,
104
+ _ => Err ( CodegenError :: NotImplemented ) ,
105
+ } ?;
106
+ self . instructions . push ( inst) ;
107
+ Ok ( dst)
108
+ } ,
109
+ Expr :: Unary { operator, right } => {
110
+ let src = self . visit_expr ( right) ?;
111
+ match operator. kind {
112
+ lexer:: TokenType :: Minus => {
113
+ let dst = self . add_var ( ) ;
114
+ let inst = Instruction :: Negate { dst : dst. clone ( ) , src } ;
115
+ self . instructions . push ( inst) ;
116
+ Ok ( dst)
117
+ } ,
118
+ _ => Err ( CodegenError :: NotImplemented ) ,
119
+ }
120
+ } ,
121
+ Expr :: Literal { value } => {
122
+ match value. kind {
123
+ lexer:: TokenType :: UnsignedInteger ( ref num) => {
124
+ match num. parse :: < i64 > ( ) {
125
+ Ok ( num) => {
126
+ let dst = self . add_var ( ) ;
127
+ let const_num = self . add_const ( Constant :: Integer ( num) ) ;
128
+ let inst = Instruction :: LoadConstant {
129
+ dst : dst. clone ( ) ,
130
+ const_num
131
+ } ;
132
+ self . instructions . push ( inst) ;
133
+ Ok ( dst)
134
+ } ,
135
+ Err ( _) => Err ( CodegenError :: NotImplemented ) ,
136
+ }
137
+ } ,
138
+ lexer:: TokenType :: UnsignedReal ( ref num) => {
139
+ match num. parse :: < f64 > ( ) {
140
+ Ok ( num) => {
141
+ let dst = self . add_var ( ) ;
142
+ let const_num = self . add_const ( Constant :: Real ( num) ) ;
143
+ let inst = Instruction :: LoadConstant { dst : dst. clone ( ) , const_num } ;
144
+ self . instructions . push ( inst) ;
145
+ Ok ( dst)
146
+ } ,
147
+ Err ( _) => Err ( CodegenError :: NotImplemented ) ,
148
+ }
149
+ } ,
150
+ lexer:: TokenType :: True => {
151
+ let dst = self . add_var ( ) ;
152
+ let const_num = self . add_const ( Constant :: Boolean ( true ) ) ;
153
+ let inst = Instruction :: LoadConstant { dst : dst. clone ( ) , const_num } ;
154
+ self . instructions . push ( inst) ;
155
+ Ok ( dst)
156
+ } ,
157
+ lexer:: TokenType :: False => {
158
+ let dst = self . add_var ( ) ;
159
+ let const_num = self . add_const ( Constant :: Boolean ( false ) ) ;
160
+ let inst = Instruction :: LoadConstant { dst : dst. clone ( ) , const_num } ;
161
+ self . instructions . push ( inst) ;
162
+ Ok ( dst)
163
+ } ,
164
+ lexer:: TokenType :: Nil => {
165
+ let dst = self . add_var ( ) ;
166
+ let const_num = self . add_const ( Constant :: Null ) ;
167
+ let inst = Instruction :: LoadConstant { dst : dst. clone ( ) , const_num } ;
168
+ self . instructions . push ( inst) ;
169
+ Ok ( dst)
170
+ } ,
171
+ lexer:: TokenType :: StringLiteral ( ref val) => {
172
+ let dst = self . add_var ( ) ;
173
+ let const_num = self . add_const ( Constant :: String ( val. clone ( ) ) ) ;
174
+ let inst = Instruction :: LoadConstant { dst : dst. clone ( ) , const_num } ;
175
+ self . instructions . push ( inst) ;
176
+ Ok ( dst)
177
+ } ,
178
+ _ => Err ( CodegenError :: NotImplemented ) ,
179
+ }
180
+ } ,
181
+ Expr :: Designator { designator } => Err ( CodegenError :: UndefinedVariable )
182
+ }
183
+ }
184
+
185
+ fn visit_type_declaration ( & mut self , _decl : & TypeDeclaration ) -> Result < ( ) , CodegenError > {
186
+ Ok ( ( ) )
187
+ }
188
+
189
+ fn visit_var_declaration ( & mut self , decl : & VarDeclaration ) -> Result < ( ) , CodegenError > {
190
+ Ok ( ( ) )
191
+ }
192
+
193
+ fn visit_procedure_declaration (
194
+ & mut self ,
195
+ decl : & Box < ProcedureDeclaration >
196
+ ) -> Result < ( ) , CodegenError > {
197
+ Ok ( ( ) )
198
+ }
199
+
200
+ fn visit_decl_section ( & mut self , section : & DeclSection ) -> Result < ( ) , CodegenError > {
201
+ match section {
202
+ DeclSection :: Type ( type_decl) => {
203
+ self . visit_type_declaration ( type_decl) ?;
204
+ Ok ( ( ) )
205
+ } ,
206
+ DeclSection :: Variable ( var_decl) => {
207
+ for decl in var_decl. iter ( ) {
208
+ self . visit_var_declaration ( decl) ?;
209
+ }
210
+ Ok ( ( ) )
211
+ } ,
212
+ DeclSection :: Procedure ( proc_decl) => {
213
+ self . visit_procedure_declaration ( proc_decl) ?;
214
+ Ok ( ( ) )
215
+ } ,
216
+ }
217
+ }
218
+
219
+ fn visit_statement ( & mut self , stmt : & Box < Stmt > ) -> Result < ( ) , CodegenError > {
220
+ match stmt. statement . as_ref ( ) {
221
+ UnlabeledStmt :: Assigment { left, right } => {
222
+ let _ident = & left. name ;
223
+ let _value = self . visit_expr ( right) ?;
224
+ Ok ( ( ) )
225
+ } ,
226
+ _ => Ok ( ( ) )
227
+ }
228
+ }
229
+
230
+ fn visit_block ( & mut self , block : & Box < Block > ) -> Result < ( ) , CodegenError > {
231
+ for section in block. decl_sections . iter ( ) {
232
+ self . visit_decl_section ( section) ?;
233
+ }
234
+ self . visit_statement ( & block. body )
235
+ }
236
+
237
+ pub fn visit_program ( & mut self , program : & Box < Program > ) -> Result < ( ) , CodegenError > {
238
+ self . visit_block ( & program. block )
239
+ }
240
+ }
0 commit comments