1use thiserror::Error;
2
3use crate::parsing::codegen::r#trait::SimpleCodeGen;
4
5use super::{top_level::BasicBody, r#type::CortexType};
6
7macro_rules! operator_struct {
8 ($name:ident, $item: ty) => {
9 #[derive(Clone)]
10 pub struct $name {
11 pub(crate) first: $item,
12 pub(crate) rest: Vec<(BinaryOperator, $item)>,
13 }
14
15 impl SimpleCodeGen for $name {
16 fn codegen(&self, indent: usize) -> String {
17 let mut s = String::new();
18 s.push_str(&self.first.codegen(indent));
19 for (op, item) in &self.rest {
20 s.push_str(" ");
21 s.push_str(&op.codegen(indent));
22 s.push_str(" ");
23 s.push_str(&item.codegen(indent));
24 }
25 s
26 }
27 }
28 }
29}
30
31operator_struct!(MulResult, Primary);
32operator_struct!(SumResult, MulResult);
33operator_struct!(EqResult, SumResult);
34operator_struct!(Expression, EqResult);
35
36#[derive(Clone)]
37pub struct Primary {
38 pub(crate) atom: Atom,
39 pub(crate) tail: ExpressionTail,
40}
41impl SimpleCodeGen for Primary {
42 fn codegen(&self, indent: usize) -> String {
43 let mut s = String::new();
44 s.push_str(&self.atom.codegen(indent));
45 s.push_str(&self.tail.codegen(indent));
46 s
47 }
48}
49
50#[derive(Clone)]
51pub struct ConditionBody {
52 pub(crate) condition: Expression,
53 pub(crate) body: BasicBody,
54}
55impl SimpleCodeGen for ConditionBody {
56 fn codegen(&self, indent: usize) -> String {
57 let mut s = String::new();
58 s.push_str(&self.condition.codegen(indent));
59 s.push_str(" {\n");
60 s.push_str(&self.body.codegen(indent + 1));
61 s.push_str(&" ".repeat(indent));
62 s.push_str("}");
63 s
64 }
65}
66
67#[derive(Clone)]
68pub enum Atom {
69 Number(f64),
70 Boolean(bool),
71 Void,
72 Null,
73 String(String),
74 PathIdent(PathIdent),
75 Call(PathIdent, Vec<Expression>),
76 StructConstruction {
77 name: PathIdent,
78 assignments: Vec<(String, Expression)>
79 },
80 IfStatement {
81 first: Box<ConditionBody>,
82 conds: Vec<ConditionBody>,
83 last: Option<Box<BasicBody>>,
84 },
85 UnaryOperation {
86 op: UnaryOperator,
87 exp: Box<Expression>,
88 },
89 Expression(Box<Expression>),
90}
91impl SimpleCodeGen for Atom {
92 fn codegen(&self, indent: usize) -> String {
93 match self {
94 Atom::Number(v) => format!("{}", v),
95 Atom::Boolean(v) => format!("{}", v),
96 Atom::String(v) => format!("\"{}\"", v),
97 Atom::Void => String::from("void"),
98 Atom::Null => String::from("null"),
99 Atom::PathIdent(path) => path.codegen(indent),
100 Atom::Expression(expr) => format!("({})", expr.codegen(indent)),
101 Atom::Call(path, args) => {
102 let mut s = String::new();
103 s.push_str(&path.codegen(indent));
104 s.push_str("(");
105 for (i, arg) in args.iter().enumerate() {
106 s.push_str(&arg.codegen(indent));
107 if i + 1 < args.len() {
108 s.push_str(", ");
109 }
110 }
111 s.push_str(")");
112 s
113 },
114 Atom::StructConstruction { name, assignments } => {
115 let mut s = String::new();
116 s.push_str(&name.codegen(0));
117 s.push_str(" { ");
118 for a in assignments {
119 s.push_str(&a.0);
120 s.push_str(": ");
121 s.push_str(&a.1.codegen(0));
122 s.push_str(", ");
123 }
124 s.push_str("}");
125 s
126 },
127 Atom::IfStatement { first, conds, last } => {
128 let mut s = String::new();
129 let indent_prefix = " ".repeat(indent);
130 s.push_str(&indent_prefix);
131 s.push_str("if ");
132 s.push_str(&first.codegen(indent));
133 for c in conds {
134 s.push_str(" elif ");
135 s.push_str(&c.codegen(indent));
136 }
137 if let Some(body) = last {
138 s.push_str(" else {\n");
139 s.push_str(&body.codegen(indent + 1));
140 s.push_str(&indent_prefix);
141 s.push_str("}");
142 }
143 s
144 },
145 Atom::UnaryOperation { op, exp } => {
146 let mut s = String::new();
147 s.push_str(&op.codegen(indent));
148 s.push_str(&exp.codegen(indent));
149 s
150 },
151 }
152 }
153}
154
155#[derive(Clone)]
156pub enum ExpressionTail {
157 None,
158 PostfixBang {
159 next: Box<ExpressionTail>,
160 },
161 MemberAccess {
162 member: String,
163 next: Box<ExpressionTail>,
164 },
165}
166impl SimpleCodeGen for ExpressionTail {
167 fn codegen(&self, indent: usize) -> String {
168 match self {
169 ExpressionTail::None => String::new(),
170 ExpressionTail::PostfixBang { next } => {
171 let next = next.codegen(indent);
172 format!("!{}", next)
173 },
174 ExpressionTail::MemberAccess { member, next } => {
175 let next = next.codegen(indent);
176 format!(".{}{}", member, next)
177 },
178 }
179 }
180}
181
182#[derive(Clone)]
183pub struct Parameter {
184 pub(crate) name: String,
185 pub(crate) typ: CortexType,
186}
187impl SimpleCodeGen for Parameter {
188 fn codegen(&self, indent: usize) -> String {
189 let mut s = String::new();
190 s.push_str(&self.name);
191 s.push_str(": ");
192 s.push_str(&self.typ.codegen(indent));
193 s
194 }
195}
196impl Parameter {
197 pub fn named(name: &str, typ: CortexType) -> Self {
198 Parameter {
199 name: String::from(name),
200 typ: typ,
201 }
202 }
203
204 pub fn name(&self) -> &String {
205 &self.name
206 }
207 pub fn param_type(&self) -> &CortexType {
208 &self.typ
209 }
210}
211
212#[derive(Clone)]
213pub struct IdentExpression {
214 pub(crate) base: PathIdent,
215 pub(crate) chain: Vec<String>,
216}
217impl SimpleCodeGen for IdentExpression {
218 fn codegen(&self, indent: usize) -> String {
219 let mut s = String::new();
220 s.push_str(&self.base.codegen(indent));
221 for c in &self.chain {
222 s.push_str(".");
223 s.push_str(c);
224 }
225 s
226 }
227}
228impl IdentExpression {
229 pub fn is_simple(&self) -> bool {
230 self.chain.is_empty()
231 }
232}
233
234#[derive(Clone)]
235pub enum OptionalIdentifier {
236 Ident(String), Ignore, }
239impl SimpleCodeGen for OptionalIdentifier {
240 fn codegen(&self, _: usize) -> String {
241 match self {
242 Self::Ident(s) => s.clone(),
243 Self::Ignore => String::from("~"),
244 }
245 }
246}
247
248#[derive(Clone, Debug, PartialEq)]
249pub struct PathIdent {
250 pub(crate) path: Vec<String>,
251}
252impl SimpleCodeGen for PathIdent {
253 fn codegen(&self, _: usize) -> String {
254 let mut s = String::new();
255 for (i, p) in self.path.iter().enumerate() {
256 s.push_str(p);
257 if i + 1 < self.path.len() {
258 s.push_str("::");
259 }
260 }
261 s
262 }
263}
264#[derive(Error, Debug, PartialEq)]
265pub enum PathError {
266 #[error("Path is empty")]
267 PathEmpty,
268}
269impl PathIdent {
270 pub fn simple(name: String) -> Self {
271 Self {
272 path: vec![name],
273 }
274 }
275 pub fn new(name: Vec<&str>) -> Self {
276 Self {
277 path: name.iter().map(|s| String::from(*s)).collect(),
278 }
279 }
280 pub fn continued(first: PathIdent, next: String) -> Self {
281 let mut path = first.path.clone();
282 path.push(next);
283 Self {
284 path: path,
285 }
286 }
287
288 pub fn pop_front(&self) -> Result<PathIdent, PathError> {
289 if self.path.len() <= 0 {
290 Err(PathError::PathEmpty)
291 } else {
292 let new_path: Vec<String> = self.path.iter().skip(1).cloned().collect();
293 Ok(PathIdent {
294 path: new_path,
295 })
296 }
297 }
298 pub fn get_front(&self) -> Result<&String, PathError> {
299 if let Some(elem) = self.path.get(0) {
300 Ok(elem)
301 } else {
302 Err(PathError::PathEmpty)
303 }
304 }
305 pub fn get_back(&self) -> Result<&String, PathError> {
306 if let Some(elem) = self.path.get(self.path.len() - 1) {
307 Ok(elem)
308 } else {
309 Err(PathError::PathEmpty)
310 }
311 }
312 pub fn is_final(&self) -> Result<bool, PathError> {
315 if self.path.len() <= 0 {
316 Err(PathError::PathEmpty)
317 } else {
318 Ok(self.path.len() == 1)
319 }
320 }
321 pub fn is_empty(&self) -> bool {
322 self.path.len() <= 0
323 }
324}
325
326#[derive(Clone)]
327pub enum UnaryOperator {
328 Negate,
329 Invert,
330}
331impl SimpleCodeGen for UnaryOperator {
332 fn codegen(&self, _indent: usize) -> String {
333 String::from(
334 match self {
335 UnaryOperator::Negate => "-",
336 UnaryOperator::Invert => "!",
337 }
338 )
339 }
340}
341
342#[derive(Clone)]
343pub enum BinaryOperator {
344 Add,
345 Subtract,
346 Multiply,
347 Divide,
348 Remainder,
349 LogicAnd,
350 LogicOr,
351 IsEqual,
352 IsNotEqual,
353 IsLessThan,
354 IsGreaterThan,
355 IsLessThanOrEqualTo,
356 IsGreaterThanOrEqualTo,
357}
358impl SimpleCodeGen for BinaryOperator {
359 fn codegen(&self, _: usize) -> String {
360 String::from(
361 match self {
362 BinaryOperator::Add => "+",
363 BinaryOperator::Subtract => "-",
364 BinaryOperator::Multiply => "*",
365 BinaryOperator::Divide => "/",
366 BinaryOperator::Remainder => "%",
367 BinaryOperator::LogicAnd => "&&",
368 BinaryOperator::LogicOr => "||",
369 BinaryOperator::IsEqual => "==",
370 BinaryOperator::IsNotEqual => "!=",
371 BinaryOperator::IsLessThan => "<",
372 BinaryOperator::IsGreaterThan => ">",
373 BinaryOperator::IsLessThanOrEqualTo => "<=",
374 BinaryOperator::IsGreaterThanOrEqualTo => ">=",
375 }
376 )
377 }
378}