xenon_codegen/
lib.rs

1use core::fmt;
2use enum_as_inner::EnumAsInner;
3
4pub mod attribute;
5pub mod case;
6pub mod r#enum;
7pub mod expression;
8pub mod function;
9pub mod identifier;
10pub mod if_statement;
11pub mod r#impl;
12pub mod loop_statement;
13pub mod module;
14pub mod return_statement;
15pub mod scope;
16pub mod statement;
17pub mod r#struct;
18pub mod switch_statement;
19pub mod r#trait;
20pub mod r#type;
21pub mod r#unsafe;
22pub mod variable_assignment;
23pub mod variable_definition;
24pub mod while_statement;
25
26/// Defines the visibility of its owner
27#[derive(Debug, Clone, EnumAsInner, Default)]
28pub enum Visibility {
29    Public,
30    #[default]
31    Private,
32}
33impl fmt::Display for Visibility {
34    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        if self.is_private() {
36            match write!(fmt, "private") {
37                Ok(_) => (),
38                Err(e) => return Err(e),
39            }
40        } else if self.is_public() {
41            match write!(fmt, "public") {
42                Ok(_) => (),
43                Err(e) => return Err(e),
44            }
45        }
46        Ok(())
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use core::panic;
53    use std::{thread::Scope, vec};
54
55    use galvanic_test::test_suite;
56
57    use crate::{
58        Visibility, attribute::Attribute, expression::UnaryOperation, identifier::IdentifierAccess,
59        loop_statement::LoopStatement, module::Module, statement, r#type::Type,
60    };
61
62    test_suite! {
63        name attribute;
64        use crate::attribute::Attribute;
65
66        test attribute_test() {
67            let attribute = Attribute::new("attribute");
68            assert!(attribute.to_string() == "#[attribute]\n");
69        }
70
71        test attribute_test_with_value() {
72            let mut attribute = Attribute::new("attribute");
73            attribute.value = Some(String::from("value"));
74            assert!(attribute.to_string() == "#[attribute(value)]\n");
75        }
76    }
77
78    test_suite! {
79        name case;
80        use crate::{expression::{Expression, IntegerLiteral}, case::Case, scope::Scope};
81
82        test case_test() {
83            let case = Case::new(
84                Expression::IntegerLiteral(IntegerLiteral::new(0)),
85                Scope::new(),
86            );
87            assert!(case.to_string() == "case 0 {\n}");
88        }
89    }
90
91    test_suite! {
92        name r#enum;
93        use crate::{r#enum::Enum, Visibility};
94
95        test private_enum_test() {
96            let enu = Enum::new("test".to_string());
97            assert!(enu.to_string() == "private enum test {}");
98        }
99
100        test public_enum_test() {
101            let mut enu = Enum::new("test".to_string());
102            enu.visibility = Visibility::Public;
103            assert!(enu.to_string() == "public enum test {}");
104        }
105    }
106
107    test_suite! {
108        name expressions;
109        use crate::{expression::{Expression, IntegerLiteral, FloatLiteral, StringLiteral, BooleanLiteral, Parentheses, UnaryOperation, BinaryOperation}};
110
111        test integer_literal_test() {
112            let int = IntegerLiteral::new(10);
113            assert!(int.to_string() == "10");
114        }
115
116        test float_literal_test() {
117            let float = FloatLiteral::new(1.0);
118            assert!(float.to_string() == "1");
119        }
120
121        test string_literal_test() {
122            let string = StringLiteral::new("Hello World!".to_string());
123            assert!(string.to_string() == "\"Hello World!\"");
124        }
125
126        test boolean_literal_test() {
127            let bol = BooleanLiteral::new(true);
128            assert!(bol.to_string() == "true");
129        }
130
131        test parentheses_test() {
132            let par = Parentheses::new(Expression::IntegerLiteral(IntegerLiteral::new(12)));
133            assert!(par.to_string() == "(12)");
134        }
135
136        test unary_operation_test() {
137            let una = UnaryOperation::new("-".to_string(), Expression::IntegerLiteral(IntegerLiteral::new(42)));
138            assert!(una.to_string() == "-42");
139        }
140
141        test binary_operation_test() {
142            let bin = BinaryOperation::new(Expression::IntegerLiteral(IntegerLiteral::new(2)), "+".to_string(), Expression::IntegerLiteral(IntegerLiteral::new(2)));
143            assert!(bin.to_string() == "2 + 2");
144        }
145    }
146
147    test_suite! {
148        name function;
149        use crate::{Visibility, function::Function, r#type::{Type, TypeType}, identifier::{Access, IdentifierAccess}, statement::Statement, scope::Scope};
150
151        test public_function() {
152            let mut func = Function::new("test".to_string(), Type::new(IdentifierAccess::Access(Access::new("void".to_string())), TypeType::Normal), Statement::Scope(Scope::new()));
153            func.visibility = Visibility::Public;
154            assert!(func.to_string() == "public fn test() -> void {\n}");
155        }
156
157        test private_function() {
158            let func = Function::new("test".to_string(), Type::new(IdentifierAccess::Access(Access::new("void".to_string())), TypeType::Normal), Statement::Scope(Scope::new()));
159            assert!(func.to_string() == "private fn test() -> void {\n}");
160        }
161    }
162
163    test_suite! {
164        name identifier;
165        use crate::{identifier::{IdentifierAccess, Access, FunctionCall}, expression::{Expression, BinaryOperation, IntegerLiteral}};
166
167        test access() {
168            let ident = Access::new("identifier".to_string());
169            assert!(ident.to_string() == "identifier");
170        }
171
172        test function_call() {
173            let mut ident = FunctionCall::new("func".to_string(), vec![]);
174            ident.arguments.push(Expression::BinaryOperation(BinaryOperation::new(Expression::IntegerLiteral(IntegerLiteral::new(2)), "+".to_string(), Expression::IntegerLiteral(IntegerLiteral::new(2)))));
175            assert!(ident.to_string() == "func(2 + 2)");
176        }
177
178        test access_and_deref() {
179            let mut ident = Access::new("one".to_string());
180            ident.child = Some(Box::new(IdentifierAccess::DerefAccess(Access::new("two".to_string()))));
181            assert!(ident.to_string() == "one->two")
182        }
183    }
184
185    test_suite! {
186        name if_statement;
187        use crate::{if_statement::IfStatement, expression::{Expression, BooleanLiteral}, scope::Scope, statement::Statement};
188
189        test if_statement() {
190            let statement = IfStatement::new(Expression::BooleanLiteral(BooleanLiteral::new(true)), Statement::Scope(Scope::new()));
191            assert!(statement.to_string() == "if (true) {\n}")
192        }
193
194        test else_statement() {
195            let mut statement = IfStatement::new(Expression::BooleanLiteral(BooleanLiteral::new(true)), Statement::Scope(Scope::new()));
196            statement.else_body = Some(Box::new(Statement::Scope(Scope::new())));
197            assert!(statement.to_string() == "if (true) {\n}\nelse {\n}")
198        }
199    }
200
201    test_suite! {
202        name r#impl;
203        use crate::{r#impl::Impl, r#type::{Type, TypeType}, identifier::{IdentifierAccess, Access}, r#trait::Trait};
204
205        test r#impl() {
206            let imp = Impl::new(Type::new(IdentifierAccess::Access(Access::new("Test".to_string())), TypeType::Normal));
207            assert!(imp.to_string() == "impliment Test {\n}");
208        }
209
210        test impl_for() {
211            let mut imp = Impl::new(Type::new(IdentifierAccess::Access(Access::new("Test".to_string())), TypeType::Normal));
212            imp.r#trait = Some(Type::new(IdentifierAccess::Access(Access::new("Treat".to_string())), TypeType::Normal));
213            assert!(imp.to_string() == "impliment Treat for Test {\n}");
214        }
215    }
216
217    test_suite! {
218        name loop_statement;
219        use crate::{loop_statement::LoopStatement, statement::Statement, scope::Scope};
220
221        test loop_statement() {
222            let lop = LoopStatement::new(Statement::Scope(Scope::new()));
223            assert!(lop.to_string() == "loop {\n}")
224        }
225    }
226
227    test_suite! {
228        name module;
229        use crate::{module::{Module, ModuleItem}, Visibility};
230
231        test public_module() {
232            let mut modu = Module::new("test".to_string());
233            modu.visibility = Visibility::Public;
234            assert!(modu.to_string() == "public module test {}");
235        }
236
237        test private_module() {
238            let modu = Module::new("test".to_string());
239            assert!(modu.to_string() == "private module test {}");
240        }
241    }
242
243    test_suite! {
244        name return_statement;
245        use crate::{return_statement::ReturnStatement, expression::{Expression, IntegerLiteral}};
246
247        test return_no_value() {
248            let ret = ReturnStatement::new();
249            assert!(ret.to_string() == "return;");
250        }
251
252        test return_value() {
253            let mut ret = ReturnStatement::new();
254            ret.value = Some(Expression::IntegerLiteral(IntegerLiteral::new(0)));
255            assert!(ret.to_string() == "return 0;");
256        }
257    }
258
259    test_suite! {
260        name scope;
261        use crate::scope::Scope;
262
263        test scope_test() {
264            let scope = Scope::new();
265            assert!(scope.to_string() == "{\n}");
266        }
267    }
268
269    test_suite! {
270        name r#struct;
271        use crate::{Visibility, r#struct::Struct, r#type::{Type, TypeType}, identifier::{IdentifierAccess, Access}};
272
273        test public_struct() {
274            let mut struc = Struct::new(Type::new(IdentifierAccess::Access(Access::new("Test".to_string())), TypeType::Normal));
275            struc.visibility = Visibility::Public;
276            assert!(struc.to_string() == "public struct Test {\n}");
277        }
278
279        test private_struct() {
280            let struc = Struct::new(Type::new(IdentifierAccess::Access(Access::new("Test".to_string())), TypeType::Normal));
281            assert!(struc.to_string() == "private struct Test {\n}");
282        }
283    }
284
285    test_suite! {
286        name switch_statement;
287        use crate::{switch_statement::SwitchStatement, expression::{Expression, IntegerLiteral}};
288
289        test switch_statement() {
290            let statement = SwitchStatement::new(Expression::IntegerLiteral(IntegerLiteral::new(0)));
291            assert!(statement.to_string() == "switch (0) {\n}")
292        }
293    }
294
295    test_suite! {
296        name r#trait;
297        use crate::{r#trait::Trait, r#type::{Type, TypeType}, identifier::{IdentifierAccess, Access}, Visibility};
298
299        test public_trait() {
300            let mut trai = Trait::new(Type::new(IdentifierAccess::Access(Access::new("Trait".to_string())), TypeType::Normal));
301            trai.visibility = Visibility::Public;
302            assert!(trai.to_string() == "public trait Trait {\n}");
303        }
304
305        test private_trait() {
306            let trai = Trait::new(Type::new(IdentifierAccess::Access(Access::new("Trait".to_string())), TypeType::Normal));
307            assert!(trai.to_string() == "private trait Trait {\n}");
308        }
309    }
310
311    test_suite! {
312        name r#type;
313        use crate::{r#type::{Type, TypeType}, identifier::{IdentifierAccess, Access}};
314
315        test r#type() {
316            let typ = Type::new(IdentifierAccess::Access(Access::new("Type".to_string())), TypeType::Normal);
317            assert!(typ.to_string() == "Type")
318        }
319
320        test generic_type() {
321            let mut typ = Type::new(IdentifierAccess::Access(Access::new("Type".to_string())), TypeType::Normal);
322            typ.generic_child = Some(Box::new(Type::new(IdentifierAccess::Access(Access::new("Type".to_string())), TypeType::Normal)));
323            assert!(typ.to_string() == "Type<Type>")
324        }
325    }
326
327    test_suite! {
328        name r#unsafe;
329        use crate::{r#unsafe::Unsafe, scope::Scope, statement::Statement};
330
331        test r#unsafe() {
332            let unsaf = Unsafe::new(Statement::Scope(Scope::new()));
333            assert!(unsaf.to_string() == "unsafe {\n}");
334        }
335    }
336
337    test_suite! {
338        name variable_assignment;
339        use crate::{variable_assignment::VariableAssignment, identifier::{IdentifierAccess, Access}, expression::{Expression, IntegerLiteral}};
340
341        test variable_assignment() {
342            let var_ass = VariableAssignment::new(IdentifierAccess::Access(Access::new("x".to_string())), "=".to_string(), Expression::IntegerLiteral(IntegerLiteral::new(0)));
343            assert!(var_ass.to_string() == "x = 0")
344        }
345    }
346
347    test_suite! {
348        name variable_definition;
349        use crate::{variable_definition::VariableDefinition, r#type::{Type, TypeType}, identifier::{IdentifierAccess, Access}};
350
351        test variable_definition() {
352            let mut var_def = VariableDefinition::new("variable".to_string());
353            var_def.ty = Some(Type::new(IdentifierAccess::Access(Access::new("i32".to_string())), TypeType::Normal));
354            assert!(var_def.to_string() == "let variable: i32");
355        }
356    }
357
358    test_suite! {
359        name while_statement;
360        use crate::{statement::Statement, while_statement::WhileStatement, scope::Scope, expression::{Expression, BooleanLiteral}};
361
362        test while_statement() {
363            let statement = WhileStatement::new(Expression::BooleanLiteral(BooleanLiteral::new(true)), Statement::Scope(Scope::new()));
364            assert!(statement.to_string() == "while (true) {\n}");
365        }
366    }
367}