1use thiserror::Error;
2use std::error::Error;
3
4use crate::{parsing::codegen::r#trait::SimpleCodeGen, preprocessing::ast::function_address::FunctionAddress};
5
6use super::{top_level::BasicBody, r#type::CortexType};
7
8#[derive(Clone)]
9pub struct PConditionBody {
10 pub(crate) condition: PExpression,
11 pub(crate) body: BasicBody,
12}
13impl SimpleCodeGen for PConditionBody {
14 fn codegen(&self, indent: usize) -> String {
15 let mut s = String::new();
16 s.push_str(&self.condition.codegen(indent));
17 s.push_str(" {\n");
18 s.push_str(&self.body.codegen(indent + 1));
19 s.push_str(&" ".repeat(indent));
20 s.push_str("}");
21 s
22 }
23}
24
25#[derive(Clone)]
26pub enum PExpression {
27 Number(f64),
28 Boolean(bool),
29 Void,
30 None,
31 String(String),
32 Char(u8),
33 PathIdent(PathIdent),
34 Call {
35 name: FunctionAddress,
36 args: Vec<PExpression>,
37 type_args: Option<Vec<CortexType>>,
38 },
39 Construction {
40 name: PathIdent,
41 type_args: Vec<CortexType>,
42 assignments: Vec<(String, PExpression)>,
43 },
44 IfStatement {
45 first: Box<PConditionBody>,
46 conds: Vec<PConditionBody>,
47 last: Option<Box<BasicBody>>,
48 },
49 UnaryOperation {
50 op: UnaryOperator,
51 exp: Box<PExpression>,
52 },
53 ListLiteral(Vec<PExpression>),
54 Bang(Box<PExpression>),
55 MemberAccess(Box<PExpression>, String),
56 MemberCall {
57 callee: Box<PExpression>,
58 member: String,
59 args: Vec<PExpression>,
60 type_args: Option<Vec<CortexType>>,
61 },
62 BinaryOperation {
63 left: Box<PExpression>,
64 op: BinaryOperator,
65 right: Box<PExpression>,
66 },
67 Tuple(Vec<PExpression>),
68}
69impl SimpleCodeGen for PExpression {
70 fn codegen(&self, indent: usize) -> String {
71 match self {
72 PExpression::Number(v) => format!("{}", v),
73 PExpression::Boolean(v) => format!("{}", v),
74 PExpression::String(v) => format!("\"{}\"", v),
75 PExpression::Void => String::from("void"),
76 PExpression::None => String::from("none"),
77 PExpression::PathIdent(path) => path.codegen(indent),
78 PExpression::Call{ name, args, type_args } => {
79 let mut s = String::new();
80 s.push_str(&name.codegen(indent));
81 if let Some(type_args) = type_args {
82 s.push_str("<");
83 s.push_str(&type_args.iter().map(|t| t.codegen(indent)).collect::<Vec<_>>().join(", "));
84 s.push_str(">");
85 }
86 s.push_str("(");
87 for (i, arg) in args.iter().enumerate() {
88 s.push_str(&arg.codegen(indent));
89 if i + 1 < args.len() {
90 s.push_str(", ");
91 }
92 }
93 s.push_str(")");
94 s
95 },
96 PExpression::Construction { name, type_args, assignments } => {
97 let mut s = String::new();
98 s.push_str(&name.codegen(0));
99 if type_args.len() > 0 {
100 s.push_str("<");
101 s.push_str(&type_args.iter().map(|s| s.codegen(0)).collect::<Vec<_>>().join(","));
102 s.push_str(">");
103 }
104 s.push_str(" { ");
105 for a in assignments {
106 s.push_str(&a.0);
107 s.push_str(": ");
108 s.push_str(&a.1.codegen(0));
109 s.push_str(", ");
110 }
111 s.push_str("}");
112 s
113 },
114 PExpression::IfStatement { first, conds, last } => {
115 let mut s = String::new();
116 let indent_prefix = " ".repeat(indent);
117 s.push_str(&indent_prefix);
118 s.push_str("if ");
119 s.push_str(&first.codegen(indent));
120 for c in conds {
121 s.push_str(" elif ");
122 s.push_str(&c.codegen(indent));
123 }
124 if let Some(body) = last {
125 s.push_str(" else {\n");
126 s.push_str(&body.codegen(indent + 1));
127 s.push_str(&indent_prefix);
128 s.push_str("}");
129 }
130 s
131 },
132 PExpression::UnaryOperation { op, exp } => {
133 format!("{}{}", op.codegen(indent), exp.codegen_as_sub(indent))
134 },
135 PExpression::ListLiteral(items) => {
136 let mut s = String::new();
137 s.push_str("[");
138 s.push_str(
139 &items
140 .iter()
141 .map(|e| e.codegen(0))
142 .collect::<Vec<_>>()
143 .join(", ")
144 );
145 s.push_str("]");
146 s
147 },
148 PExpression::Bang(ex) => format!("{}!", ex.codegen(indent)),
149 PExpression::BinaryOperation { left, op, right } => {
150 format!("{} {} {}", left.codegen_as_sub(indent), op.codegen(indent), right.codegen_as_sub(indent))
151 },
152 PExpression::MemberAccess(ex, member) => format!("{}.{}", ex.codegen_as_sub(indent), member),
153 PExpression::MemberCall { callee, member: member_name, args, type_args } => {
154 if let Some(type_args) = type_args {
155 format!("{}.{}<{}>({})",
156 callee.codegen_as_sub(indent),
157 member_name,
158 type_args.iter().map(|t| t.codegen(indent)).collect::<Vec<_>>().join(", "),
159 args.iter().map(|a| a.codegen(indent)).collect::<Vec<_>>().join(", ")
160 )
161 } else {
162 format!("{}.{}({})",
163 callee.codegen_as_sub(indent),
164 member_name,
165 args.iter().map(|a| a.codegen(indent)).collect::<Vec<_>>().join(", ")
166 )
167 }
168 },
169 PExpression::Tuple(items) => {
170 if items.len() == 1 {
171 format!("({},)", items.get(0).unwrap().codegen(indent))
172 } else {
173 format!("({})", items.iter().map(|i| i.codegen(indent)).collect::<Vec<_>>().join(", "))
174 }
175 },
176 PExpression::Char(c) => {
177 format!("'{}'", *c as char)
178 }
179 }
180 }
181}
182impl PExpression {
183 fn is_atomic(&self) -> bool {
184 match self {
185 PExpression::Number(_) | PExpression::Boolean(_) | PExpression::Void | PExpression::None |
186 PExpression::String(_) | PExpression::PathIdent(_) | PExpression::Call { name: _, args: _, type_args: _ } |
187 PExpression::Construction { name: _, type_args: _, assignments: _ } |
188 PExpression::IfStatement { first: _, conds: _, last: _ } | PExpression::MemberAccess(_, _) |
189 PExpression::ListLiteral(_) | PExpression::MemberCall { callee: _, member: _, args: _, type_args: _ } |
190 PExpression::Tuple(_) | PExpression::Char(_)
191 => true,
192
193 PExpression::UnaryOperation { op: _, exp: _ } | PExpression::Bang(_) |
194 PExpression::BinaryOperation { left: _, op: _, right: _ }
195 => false,
196 }
197 }
198 fn codegen_as_sub(&self, indent: usize) -> String {
199 let s = self.codegen(indent);
200 if !self.is_atomic() {
201 format!("({})", s)
202 } else {
203 s
204 }
205 }
206}
207
208#[derive(Clone)]
209pub struct Parameter {
210 pub(crate) name: String,
211 pub(crate) typ: CortexType,
212}
213impl SimpleCodeGen for Parameter {
214 fn codegen(&self, indent: usize) -> String {
215 let mut s = String::new();
216 s.push_str(&self.name);
217 s.push_str(": ");
218 s.push_str(&self.typ.codegen(indent));
219 s
220 }
221}
222impl Parameter {
223 pub fn named(name: &str, typ: CortexType) -> Self {
224 Parameter {
225 name: String::from(name),
226 typ: typ,
227 }
228 }
229
230 pub fn name(&self) -> &String {
231 &self.name
232 }
233 pub fn param_type(&self) -> &CortexType {
234 &self.typ
235 }
236}
237
238#[derive(Clone)]
239pub struct IdentExpression {
240 pub(crate) base: String,
241 pub(crate) chain: Vec<String>,
242}
243impl SimpleCodeGen for IdentExpression {
244 fn codegen(&self, _indent: usize) -> String {
245 let mut s = String::new();
246 s.push_str(&self.base);
247 for c in &self.chain {
248 s.push_str(".");
249 s.push_str(c);
250 }
251 s
252 }
253}
254impl IdentExpression {
255 pub fn is_simple(&self) -> bool {
256 self.chain.is_empty()
257 }
258
259 pub fn to_member_access_expr(self) -> PExpression {
260 let mut expr = PExpression::PathIdent(PathIdent::simple(self.base));
261 for link in self.chain {
262 expr = PExpression::MemberAccess(Box::new(expr), link);
263 }
264 expr
265 }
266
267 pub fn without_last(mut self) -> Result<IdentExpression, Box<dyn Error>> {
268 if self.chain.len() > 0 {
270 self.chain.remove(self.chain.len() - 1);
271 Ok(IdentExpression {
272 base: self.base,
273 chain: self.chain,
274 })
275 } else {
276 Ok(self)
277 }
278 }
279}
280
281#[derive(Clone)]
282pub enum OptionalIdentifier {
283 Ident(String), Ignore, }
286impl SimpleCodeGen for OptionalIdentifier {
287 fn codegen(&self, _: usize) -> String {
288 match self {
289 Self::Ident(s) => s.clone(),
290 Self::Ignore => String::from("~"),
291 }
292 }
293}
294
295#[derive(Clone, Debug, PartialEq, Eq, Hash)]
296pub struct PathIdent {
297 pub(crate) path: Vec<String>,
298}
299impl SimpleCodeGen for PathIdent {
300 fn codegen(&self, _: usize) -> String {
301 self.to_string("::")
302 }
303}
304#[derive(Error, Debug, PartialEq)]
305pub enum PathError {
306 #[error("Path is empty")]
307 PathEmpty,
308 #[error("Subtraction failed: item {0} does not match {1}")]
309 SubtractionFailed(String, String),
310}
311impl PathIdent {
312 pub fn simple(name: String) -> Self {
313 Self {
314 path: vec![name],
315 }
316 }
317 pub fn new(name: Vec<&str>) -> Self {
318 Self {
319 path: name.iter().map(|s| String::from(*s)).collect(),
320 }
321 }
322 pub fn continued(first: PathIdent, next: String) -> Self {
323 if first.is_empty() {
324 Self {
325 path: vec![next],
326 }
327 } else {
328 let mut path = first.path.clone();
329 path.push(next);
330 Self {
331 path: path,
332 }
333 }
334 }
335 pub fn empty() -> Self {
336 Self {
337 path: Vec::new(),
338 }
339 }
340 pub fn concat(first: &PathIdent, second: &PathIdent) -> Self {
341 if first.is_empty() {
342 second.clone()
343 } else if second.is_empty() {
344 first.clone()
345 } else {
346 let mut path = first.path.clone();
347 path.extend(second.path.clone());
348 Self {
349 path: path,
350 }
351 }
352 }
353
354 pub fn is_prefixed_by(&self, prefix: &PathIdent) -> bool {
355 if prefix.path.len() > self.path.len() {
356 return false;
357 }
358 for (i, p) in prefix.path.iter().enumerate() {
359 if *self.path.get(i).unwrap() != *p {
360 return false;
361 }
362 }
363 true
364 }
365
366 pub fn subtract(self, second: &PathIdent) -> Result<Self, PathError> {
367 if second.is_empty() {
368 Ok(self)
369 } else {
370 let mut path = self.path.clone();
371 for item in &second.path {
372 if let Some(first) = path.get(0) {
373 if first != item {
374 return Err(PathError::SubtractionFailed(first.clone(), item.clone()));
375 }
376 path.remove(0);
377 } else {
378 return Err(PathError::PathEmpty);
379 }
380 }
381 Ok(
382 Self {
383 path: path
384 }
385 )
386 }
387 }
388 pub fn subtract_if_possible(self, second: &PathIdent) -> Self {
389 if self.is_prefixed_by(second) {
390 self.subtract(second).unwrap()
391 } else {
392 self
393 }
394 }
395
396 pub fn without_last(&self) -> Self {
397 let mut new_vec = self.path.clone();
398 new_vec.remove(new_vec.len() - 1);
399 Self {
400 path: new_vec,
401 }
402 }
403
404 pub fn pop_front(&self) -> Result<PathIdent, PathError> {
405 if self.path.len() <= 0 {
406 Err(PathError::PathEmpty)
407 } else {
408 let new_path: Vec<String> = self.path.iter().skip(1).cloned().collect();
409 Ok(PathIdent {
410 path: new_path,
411 })
412 }
413 }
414 pub fn get_front(&self) -> Result<&String, PathError> {
415 if let Some(elem) = self.path.get(0) {
416 Ok(elem)
417 } else {
418 Err(PathError::PathEmpty)
419 }
420 }
421 pub fn get_back(&self) -> Result<&String, PathError> {
422 if let Some(elem) = self.path.get(self.path.len() - 1) {
423 Ok(elem)
424 } else {
425 Err(PathError::PathEmpty)
426 }
427 }
428 pub fn is_final(&self) -> bool {
431 if self.path.len() <= 0 {
432 false
433 } else {
434 self.path.len() == 1
435 }
436 }
437 pub fn is_empty(&self) -> bool {
438 self.path.len() <= 0
439 }
440
441 pub fn to_string(&self, separator: &str) -> String {
442 self.path.iter().cloned().collect::<Vec<_>>().join(separator)
443 }
444}
445
446#[derive(Clone)]
447pub enum UnaryOperator {
448 Negate,
449 Invert,
450}
451impl SimpleCodeGen for UnaryOperator {
452 fn codegen(&self, _indent: usize) -> String {
453 String::from(
454 match self {
455 UnaryOperator::Negate => "-",
456 UnaryOperator::Invert => "!",
457 }
458 )
459 }
460}
461
462#[derive(Clone)]
463pub enum BinaryOperator {
464 Add,
465 Subtract,
466 Multiply,
467 Divide,
468 Remainder,
469 LogicAnd,
470 LogicOr,
471 IsEqual,
472 IsNotEqual,
473 IsLessThan,
474 IsGreaterThan,
475 IsLessThanOrEqualTo,
476 IsGreaterThanOrEqualTo,
477}
478impl SimpleCodeGen for BinaryOperator {
479 fn codegen(&self, _: usize) -> String {
480 String::from(
481 match self {
482 BinaryOperator::Add => "+",
483 BinaryOperator::Subtract => "-",
484 BinaryOperator::Multiply => "*",
485 BinaryOperator::Divide => "/",
486 BinaryOperator::Remainder => "%",
487 BinaryOperator::LogicAnd => "&&",
488 BinaryOperator::LogicOr => "||",
489 BinaryOperator::IsEqual => "==",
490 BinaryOperator::IsNotEqual => "!=",
491 BinaryOperator::IsLessThan => "<",
492 BinaryOperator::IsGreaterThan => ">",
493 BinaryOperator::IsLessThanOrEqualTo => "<=",
494 BinaryOperator::IsGreaterThanOrEqualTo => ">=",
495 }
496 )
497 }
498}