1use super::{
3 basic_block::BasicBlockCell,
4 control_flow_graph::ControlFlowGraph,
5 label::{Label, LabelName, LabelVisibility},
6 operand::Operand,
7 variable::Variable,
8 Ir
9};
10use pulsar_frontend::{
11 ast::{Expr, ExprValue, Node, NodeValue, Param},
12 token::{Token, TokenType},
13 ty::Type
14};
15use pulsar_utils::environment::Environment;
16use std::fmt::Display;
17
18pub enum GeneratedTopLevel {
19 Function {
20 label: Label,
21 args: Vec<Type>,
22 ret: Box<Type>,
23 is_pure: bool,
24 cfg: ControlFlowGraph
25 }
26}
27
28impl Display for GeneratedTopLevel {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match &self {
31 Self::Function {
32 label,
33 args,
34 ret,
35 is_pure,
36 cfg
37 } => {
38 writeln!(
39 f,
40 "{} {}({}) -> {}:",
41 if *is_pure { "pure " } else { "" },
42 label,
43 args.iter()
44 .map(|ty| ty.to_string())
45 .collect::<Vec<_>>()
46 .join(", "),
47 ret
48 )?;
49 write!(f, "{}", cfg)
50 }
51 }
52 }
53}
54
55pub struct Generator {
56 program: Box<dyn Iterator<Item = Node>>,
57 env: Environment<String, Variable>
58}
59
60impl Generator {
61 pub fn new(program: Vec<Node>) -> Self {
62 Self {
63 program: Box::new(program.into_iter()),
64 env: Environment::new()
65 }
66 }
67
68 fn gen_expr(&mut self, expr: &Expr, block: BasicBlockCell) -> Operand {
69 match &expr.value {
70 ExprValue::ConstantInt(value) => Operand::Constant(*value),
71 ExprValue::InfixBop(lhs, op, rhs) => {
72 let lhs = self.gen_expr(lhs, block.clone());
73 let rhs = self.gen_expr(rhs, block.clone());
74 let result = Variable::new();
75 match op.ty {
76 TokenType::Plus => {
77 block.as_mut().add(Ir::Add(result, lhs, rhs))
78 }
79 TokenType::Times => {
80 block.as_mut().add(Ir::Mul(result, lhs, rhs))
81 }
82 _ => todo!()
83 }
84 Operand::Variable(result)
85 }
86 ExprValue::BoundName(name) => {
87 Operand::Variable(*self.env.find(name.value.clone()).unwrap())
88 }
89 ExprValue::Call(name, args) => {
90 let mut arg_operands = vec![];
91 let mut arg_tys = vec![];
92 for arg in args {
93 arg_tys.push(arg.ty.clone_out());
94 let arg_operand = self.gen_expr(arg, block.clone());
95 arg_operands.push(arg_operand);
96 }
97 let result_opt = if expr.ty.clone_out() == Type::Unit {
98 None
99 } else {
100 Some(Variable::new())
101 };
102 block.as_mut().add(Ir::Call(
103 result_opt,
104 LabelName::from_native(
105 name.value.clone(),
106 &arg_tys,
107 &Box::new(expr.ty.clone_out())
108 ),
109 arg_operands
110 ));
111 result_opt.map_or(Operand::Constant(0), |result| {
112 Operand::Variable(result)
113 })
114 }
115 ExprValue::PostfixBop(array, op1, index, op2)
116 if op1.ty == TokenType::LeftBracket
117 && op2.ty == TokenType::RightBracket =>
118 {
119 let array_operand = self.gen_expr(array, block.clone());
120 let index_operand = self.gen_expr(index, block.clone());
121 let result = Variable::new();
122 block.as_mut().add(Ir::Load {
123 result,
124 value: array_operand,
125 index: index_operand
126 });
127 Operand::Variable(result)
128 }
129 ExprValue::ArrayLiteral(elements, _) => {
130 let (element_type, element_count) =
131 expr.ty.as_ref().as_array_type();
132 let element_size = element_type.as_ref().size();
133 let element_count = element_count as usize;
134
135 let result = Variable::new();
136 block.as_mut().add(Ir::LocalAlloc(
137 result,
138 element_size,
139 element_count
140 ));
141 for (i, element) in elements.iter().enumerate() {
142 let element_operand = self.gen_expr(element, block.clone());
143 block.as_mut().add(Ir::Store {
144 result,
145 value: element_operand,
146 index: Operand::Constant(i as i64)
147 });
148 }
149 for i in elements.len()..element_count {
150 block.as_mut().add(Ir::Store {
151 result,
152 value: Operand::Constant(0),
153 index: Operand::Constant(i as i64)
154 });
155 }
156 Operand::Variable(result)
157 }
158 ExprValue::HardwareMap(_, parallel_factor, f, arr) => {
159 let (element_type, element_count) =
160 expr.ty.as_ref().as_array_type();
161 let element_size = element_type.as_ref().size();
162 let element_count = element_count as usize;
163
164 let arr_operand = self.gen_expr(arr, block.clone());
165
166 let result = Variable::new();
167 block.as_mut().add(Ir::LocalAlloc(
168 result,
169 element_size,
170 element_count
171 ));
172
173 block.as_mut().add(Ir::Map {
174 result,
175 parallel_factor: *parallel_factor,
176 f: LabelName::from_native(
177 f.value.clone(),
178 &vec![Type::Int64],
179 &Box::new(Type::Int64)
180 ),
181 input: arr_operand,
182 length: element_count
183 });
184
185 Operand::Variable(result)
186 }
187 _ => todo!()
188 }
189 }
190
191 fn gen_node(&mut self, node: &Node, block: BasicBlockCell) {
192 match &node.value {
193 NodeValue::LetBinding {
194 name,
195 hint: _,
196 value
197 } => {
198 let value_operand = self.gen_expr(value, block.clone());
199 let name_var = Variable::new();
200 self.env.bind(name.value.clone(), name_var);
201 block.as_mut().add(Ir::Assign(name_var, value_operand));
202 }
203 NodeValue::Return {
204 keyword_token: _,
205 value
206 } => {
207 let value_operand = value
208 .as_ref()
209 .map(|value| self.gen_expr(value.as_ref(), block.clone()));
210 block.as_mut().add(Ir::Return(value_operand));
211 }
212 _ => {}
213 }
214 }
215
216 fn gen_func(
217 &mut self, name: &Token, params: &Vec<Param>, ret: Type, is_pure: bool,
218 body: &Vec<Node>
219 ) -> GeneratedTopLevel {
220 self.env.push();
221 let cfg = ControlFlowGraph::new();
222 let entry = cfg.entry();
223 for (name, _) in params {
224 let param_var = Variable::new();
225 self.env.bind(name.value.clone(), param_var);
226 entry.as_mut().add(Ir::GetParam(param_var));
227 }
228 for node in body {
229 self.gen_node(node, entry.clone());
230 }
231 self.env.pop();
232 let arg_tys = params.iter().map(|(_, ty)| ty.clone()).collect();
233 let ret_ty = Box::new(ret);
234 GeneratedTopLevel::Function {
235 label: Label::from(
236 LabelName::from_native(name.value.clone(), &arg_tys, &ret_ty),
237 LabelVisibility::Private
238 ),
239 args: arg_tys,
240 ret: ret_ty,
241 is_pure,
242 cfg
243 }
244 }
245}
246
247impl Iterator for Generator {
248 type Item = GeneratedTopLevel;
249
250 fn next(&mut self) -> Option<GeneratedTopLevel> {
251 match self.program.next()?.value {
252 NodeValue::Function {
253 name,
254 params,
255 ret,
256 pure_token,
257 body
258 } => Some(self.gen_func(
259 &name,
260 ¶ms,
261 ret,
262 pure_token.is_some(),
263 &body
264 )),
265 _ => None
266 }
267 }
268}