pulsar_ir/
generator.rs

1// Copyright (C) 2024 Ethan Uppal. All rights reserved.
2use 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                &params,
261                ret,
262                pure_token.is_some(),
263                &body
264            )),
265            _ => None
266        }
267    }
268}