1use crate::stdlib::{cell::RefCell, collections::HashSet, ops::Range, rc::Rc};
2use crate::type_inference::infer_expression_type_detailed_errors;
3use core::str::FromStr;
4use core::unreachable;
5
6pub mod options;
7pub mod precompiled_ast;
8pub mod scope;
9pub mod scope_stack;
10use crate::ast::expressions::{
11 BinaryOperation, DatexExpressionData, Statements, TypeDeclaration,
12 VariableAccess, VariableAssignment, VariableDeclaration, VariableKind,
13};
14use crate::ast::expressions::{
15 DatexExpression, RemoteExecution, TypeDeclarationKind, VariantAccess,
16};
17use crate::ast::resolved_variable::ResolvedVariable;
18use crate::ast::type_expressions::{TypeExpressionData, TypeVariantAccess};
19use crate::types::definition::TypeDefinition;
20use crate::visitor::type_expression::visitable::TypeExpressionVisitResult;
21use crate::{
22 ast::spanned::Spanned,
23 compiler::error::{
24 CompilerError, DetailedCompilerErrors,
25 DetailedCompilerErrorsWithRichAst, ErrorCollector, MaybeAction,
26 SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst,
27 SpannedCompilerError, collect_or_pass_error,
28 },
29 global::operators::{BinaryOperator, binary::ArithmeticOperator},
30 libs::core::CoreLibPointerId,
31 references::type_reference::{NominalTypeDeclaration, TypeReference},
32 values::core_values::r#type::Type,
33 visitor::{
34 VisitAction,
35 expression::{ExpressionVisitor, visitable::ExpressionVisitResult},
36 type_expression::TypeExpressionVisitor,
37 },
38};
39use options::PrecompilerOptions;
40use precompiled_ast::AstMetadata;
41use precompiled_ast::RichAst;
42use precompiled_ast::VariableShape;
43use scope::NewScopeType;
44use scope_stack::PrecompilerScopeStack;
45
46pub struct Precompiler<'a> {
47 ast_metadata: Rc<RefCell<AstMetadata>>,
48 scope_stack: &'a mut PrecompilerScopeStack,
49 collected_errors: Option<DetailedCompilerErrors>,
50 is_first_level_expression: bool,
51}
52
53pub fn precompile_ast_simple_error(
56 ast: DatexExpression,
57 scope_stack: &mut PrecompilerScopeStack,
58 ast_metadata: Rc<RefCell<AstMetadata>>,
59) -> Result<RichAst, SpannedCompilerError> {
60 precompile_ast(
61 ast,
62 scope_stack,
63 ast_metadata,
64 PrecompilerOptions {
65 detailed_errors: false,
66 },
67 )
68 .map_err(|e| {
69 match e {
70 SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst::Simple(
71 error,
72 ) => error,
73 _ => unreachable!(), }
75 })
76}
77
78pub fn precompile_ast_detailed_errors(
81 ast: DatexExpression,
82 scope_stack: &mut PrecompilerScopeStack,
83 ast_metadata: Rc<RefCell<AstMetadata>>,
84) -> Result<RichAst, DetailedCompilerErrorsWithRichAst> {
85 precompile_ast(
86 ast,
87 scope_stack,
88 ast_metadata,
89 PrecompilerOptions {
90 detailed_errors: true,
91 },
92 )
93 .map_err(|e| {
94 match e {
95 SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst::Detailed(
96 error,
97 ) => error,
98 _ => unreachable!(), }
100 })
101}
102
103pub fn precompile_ast(
105 ast: DatexExpression,
106 scope_stack: &mut PrecompilerScopeStack,
107 ast_metadata: Rc<RefCell<AstMetadata>>,
108 options: PrecompilerOptions,
109) -> Result<RichAst, SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst> {
110 Precompiler::new(scope_stack, ast_metadata).precompile(ast, options)
111}
112
113impl<'a> Precompiler<'a> {
114 pub fn new(
115 scope_stack: &'a mut PrecompilerScopeStack,
116 ast_metadata: Rc<RefCell<AstMetadata>>,
117 ) -> Self {
118 Self {
119 ast_metadata,
120 scope_stack,
121 collected_errors: None,
122 is_first_level_expression: true,
123 }
124 }
125
126 fn collect_error(
129 &mut self,
130 error: SpannedCompilerError,
131 ) -> Result<(), SpannedCompilerError> {
132 match &mut self.collected_errors {
133 Some(collected_errors) => {
134 collected_errors.record_error(error);
135 Ok(())
136 }
137 None => Err(error),
138 }
139 }
140
141 fn collect_result<T>(
144 &mut self,
145 result: Result<T, SpannedCompilerError>,
146 ) -> Result<MaybeAction<T>, SpannedCompilerError> {
147 collect_or_pass_error(&mut self.collected_errors, result)
148 }
149
150 fn get_variable_and_update_metadata(
151 &mut self,
152 name: &str,
153 ) -> Result<usize, CompilerError> {
154 self.scope_stack.get_variable_and_update_metadata(
155 name,
156 &mut self.ast_metadata.borrow_mut(),
157 )
158 }
159
160 fn precompile(
162 mut self,
163 mut ast: DatexExpression,
164 options: PrecompilerOptions,
165 ) -> Result<RichAst, SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst>
166 {
167 if options.detailed_errors {
168 self.collected_errors = Some(DetailedCompilerErrors::default());
169 }
170
171 if let DatexExpressionData::TypeDeclaration(type_declaration) =
173 &mut ast.data
174 {
175 self.hoist_variable(type_declaration);
176 }
177
178 self.visit_datex_expression(&mut ast)?;
182
183 let mut rich_ast = RichAst {
184 metadata: self.ast_metadata,
185 ast,
186 };
187
188 if options.detailed_errors {
191 let type_res = infer_expression_type_detailed_errors(&mut rich_ast);
192
193 if let Some(collected_errors) = self.collected_errors.as_mut()
195 && let Err(type_errors) = type_res
196 {
197 collected_errors.append(type_errors.into());
198 }
199 }
200
201 if let Some(errors) = self.collected_errors
203 && errors.has_errors()
204 {
205 Err(
206 SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst::Detailed(
207 DetailedCompilerErrorsWithRichAst {
208 errors,
209 ast: rich_ast,
210 },
211 ),
212 )
213 } else {
214 Ok(rich_ast)
215 }
216 }
217
218 fn add_new_variable(&mut self, name: String, kind: VariableShape) -> usize {
221 let new_id = self.ast_metadata.borrow().variables.len();
222 let var_metadata =
223 self.scope_stack
224 .add_new_variable(name.clone(), new_id, kind);
225 self.ast_metadata.borrow_mut().variables.push(var_metadata);
226 new_id
227 }
228
229 fn resolve_variable(
233 &mut self,
234 name: &str,
235 ) -> Result<ResolvedVariable, CompilerError> {
236 if let Ok(id) = self.get_variable_and_update_metadata(name) {
238 Ok(ResolvedVariable::VariableId(id))
239 }
240 else if let Ok(core) = CoreLibPointerId::from_str(name) {
242 Ok(ResolvedVariable::PointerAddress(core.into()))
243 } else {
244 Err(CompilerError::UndeclaredVariable(name.to_string()))
245 }
246 }
247
248 fn scope_type_for_expression(
249 &mut self,
250 expr: &DatexExpression,
251 ) -> NewScopeType {
252 match &expr.data {
253 DatexExpressionData::RemoteExecution(_) => NewScopeType::None,
254 _ => NewScopeType::NewScope,
255 }
256 }
257
258 fn hoist_variable(&mut self, data: &mut TypeDeclaration) {
261 data.hoisted = true;
263
264 let type_id =
266 self.add_new_variable(data.name.clone(), VariableShape::Type);
267
268 let reference = match data.kind {
269 TypeDeclarationKind::Nominal => {
270 Rc::new(RefCell::new(TypeReference::nominal(
271 Type::UNIT,
272 NominalTypeDeclaration::from(data.name.clone()),
273 None,
274 )))
275 }
276 TypeDeclarationKind::Structural => Rc::new(RefCell::new(
277 TypeReference::anonymous(Type::UNIT, None),
278 )),
279 };
280
281 let type_def = Type::new(TypeDefinition::reference(reference), None);
283 {
284 self.ast_metadata
285 .borrow_mut()
286 .variable_metadata_mut(type_id)
287 .expect("TypeDeclaration should have variable metadata")
288 .var_type = Some(type_def.clone());
289 }
290 }
291}
292
293impl<'a> TypeExpressionVisitor<SpannedCompilerError> for Precompiler<'a> {
294 fn visit_literal_type(
295 &mut self,
296 literal: &mut String,
297 span: &Range<usize>,
298 ) -> TypeExpressionVisitResult<SpannedCompilerError> {
299 let resolved_variable = self.resolve_variable(literal)?;
300 Ok(VisitAction::Replace(match resolved_variable {
301 ResolvedVariable::VariableId(id) => {
302 TypeExpressionData::VariableAccess(VariableAccess {
303 id,
304 name: literal.to_string(),
305 })
306 .with_span(span.clone())
307 }
308 ResolvedVariable::PointerAddress(pointer_address) => {
309 TypeExpressionData::GetReference(pointer_address)
310 .with_span(span.clone())
311 }
312 }))
313 }
314 fn visit_variant_access_type(
315 &mut self,
316 variant_access: &mut TypeVariantAccess,
317 span: &Range<usize>,
318 ) -> TypeExpressionVisitResult<SpannedCompilerError> {
319 let _ = self.resolve_variable(&variant_access.name)?;
321 let literal =
322 format!("{}/{}", variant_access.name, variant_access.variant);
323
324 let resolved_variable = self.resolve_variable(&literal)?;
326 Ok(VisitAction::Replace(match resolved_variable {
327 ResolvedVariable::VariableId(id) => {
328 TypeExpressionData::VariableAccess(VariableAccess {
329 id,
330 name: literal,
331 })
332 .with_span(span.clone())
333 }
334 ResolvedVariable::PointerAddress(pointer_address) => {
335 TypeExpressionData::GetReference(pointer_address)
336 .with_span(span.clone())
337 }
338 }))
339 }
340}
341impl<'a> ExpressionVisitor<SpannedCompilerError> for Precompiler<'a> {
342 fn handle_expression_error(
345 &mut self,
346 error: SpannedCompilerError,
347 _expression: &DatexExpression,
348 ) -> Result<VisitAction<DatexExpression>, SpannedCompilerError> {
349 if let Some(collected_errors) = self.collected_errors.as_mut() {
350 collected_errors.record_error(error);
351 Ok(VisitAction::VisitChildren)
352 } else {
353 Err(error)
354 }
355 }
356
357 fn before_visit_datex_expression(&mut self, expr: &mut DatexExpression) {
358 match self.scope_type_for_expression(expr) {
359 NewScopeType::NewScopeWithNewRealm => {
360 self.scope_stack.push_scope();
361 self.scope_stack.increment_realm_index();
362 }
363 NewScopeType::NewScope => {
364 if !(self.scope_stack.scopes.len() == 1
366 && self.is_first_level_expression)
367 {
368 self.scope_stack.push_scope();
369 }
370 }
371 _ => {}
372 };
373
374 self.is_first_level_expression = false;
375 }
376
377 fn after_visit_datex_expression(&mut self, expr: &mut DatexExpression) {
378 match self.scope_type_for_expression(expr) {
379 NewScopeType::NewScope | NewScopeType::NewScopeWithNewRealm => {
380 if self.scope_stack.scopes.len() > 1 {
382 self.scope_stack.pop_scope();
383 }
384 }
385 _ => {}
386 };
387 }
388
389 fn visit_remote_execution(
390 &mut self,
391 remote_execution: &mut RemoteExecution,
392 _: &Range<usize>,
393 ) -> ExpressionVisitResult<SpannedCompilerError> {
394 self.visit_datex_expression(&mut remote_execution.left)?;
395
396 self.scope_stack.push_scope();
397 self.scope_stack.increment_realm_index();
398
399 self.visit_datex_expression(&mut remote_execution.right)?;
400 self.scope_stack.pop_scope();
401 Ok(VisitAction::SkipChildren)
402 }
403
404 fn visit_statements(
405 &mut self,
406 statements: &mut Statements,
407 _: &Range<usize>,
408 ) -> ExpressionVisitResult<SpannedCompilerError> {
409 let mut registered_names = HashSet::new();
410 for statements in statements.statements.iter_mut() {
411 if let DatexExpressionData::TypeDeclaration(type_declaration) =
412 &mut statements.data
413 {
414 let name = &type_declaration.name;
415 if registered_names.contains(name) {
416 self.collect_error(
417 CompilerError::InvalidRedeclaration(name.clone())
418 .into(),
419 )?
420 }
421 registered_names.insert(name.clone());
422 self.hoist_variable(type_declaration);
423 }
424 }
425 Ok(VisitAction::VisitChildren)
426 }
427
428 fn visit_type_declaration(
429 &mut self,
430 type_declaration: &mut TypeDeclaration,
431 _: &Range<usize>,
432 ) -> ExpressionVisitResult<SpannedCompilerError> {
433 let name = type_declaration.name.clone();
434 if type_declaration.hoisted {
435 let id = self
436 .get_variable_and_update_metadata(
437 &type_declaration.name.clone(),
438 )
439 .ok();
440 type_declaration.id = id;
441 } else {
442 type_declaration.id =
443 Some(self.add_new_variable(name, VariableShape::Type));
444 }
445 Ok(VisitAction::VisitChildren)
446 }
447
448 fn visit_binary_operation(
449 &mut self,
450 binary_operation: &mut BinaryOperation,
451 span: &Range<usize>,
452 ) -> ExpressionVisitResult<SpannedCompilerError> {
453 let operator = &binary_operation.operator;
454
455 if operator == &BinaryOperator::Arithmetic(ArithmeticOperator::Divide) {
457 let left = &mut binary_operation.left;
458 let right = &mut binary_operation.right;
459
460 let lit_left =
461 if let DatexExpressionData::Identifier(name) = &left.data {
462 name.clone()
463 } else {
464 return Ok(VisitAction::VisitChildren);
465 };
466 let lit_right =
467 if let DatexExpressionData::Identifier(name) = &right.data {
468 name.clone()
469 } else {
470 return Ok(VisitAction::VisitChildren);
471 };
472 let left_var = self.resolve_variable(lit_left.as_str());
474 let is_right_defined =
475 self.resolve_variable(lit_right.as_str()).is_ok();
476
477 if let Ok(left_var) = left_var {
479 if is_right_defined {
480 Ok(VisitAction::VisitChildren)
485 } else {
486 Ok(VisitAction::Replace(DatexExpression::new(
489 DatexExpressionData::VariantAccess(VariantAccess {
490 base: left_var,
491 name: lit_left,
492 variant: lit_right,
493 }),
494 span.clone(),
495 )))
496 }
497 } else {
498 Ok(VisitAction::VisitChildren)
499 }
500 } else {
501 Ok(VisitAction::VisitChildren)
502 }
503 }
504
505 fn visit_variable_declaration(
506 &mut self,
507 variable_declaration: &mut VariableDeclaration,
508 span: &Range<usize>,
509 ) -> ExpressionVisitResult<SpannedCompilerError> {
510 if let Some(existing_var_id) = self
512 .scope_stack
513 .get_active_scope()
514 .variable_ids_by_name
515 .get(&variable_declaration.name)
516 {
517 variable_declaration.id = Some(*existing_var_id);
518 return Err(SpannedCompilerError::new_with_span(
519 CompilerError::InvalidRedeclaration(
520 variable_declaration.name.clone(),
521 ),
522 span.clone(),
523 ));
524 }
525 variable_declaration.id = Some(self.add_new_variable(
526 variable_declaration.name.clone(),
527 VariableShape::Value(variable_declaration.kind),
528 ));
529 Ok(VisitAction::VisitChildren)
530 }
531
532 fn visit_variable_assignment(
533 &mut self,
534 variable_assignment: &mut VariableAssignment,
535 span: &Range<usize>,
536 ) -> ExpressionVisitResult<SpannedCompilerError> {
537 let res = self
538 .get_variable_and_update_metadata(&variable_assignment.name)
539 .map_err(|error| {
540 SpannedCompilerError::new_with_span(error, span.clone())
541 });
542 let action = self.collect_result(res)?;
543 if let MaybeAction::Do(new_id) = action {
544 let var_shape = self
547 .ast_metadata
548 .borrow()
549 .variable_metadata(new_id)
550 .unwrap()
551 .shape;
552 variable_assignment.id = Some(new_id);
553 if let VariableShape::Value(VariableKind::Const) = var_shape {
554 self.collect_error(SpannedCompilerError::new_with_span(
555 CompilerError::AssignmentToConst(
556 variable_assignment.name.clone(),
557 ),
558 span.clone(),
559 ))?;
560 };
561 }
562 Ok(VisitAction::VisitChildren)
563 }
564
565 fn visit_identifier(
566 &mut self,
567 identifier: &mut String,
568 span: &Range<usize>,
569 ) -> ExpressionVisitResult<SpannedCompilerError> {
570 let result = self.resolve_variable(identifier).map_err(|error| {
571 SpannedCompilerError::new_with_span(error, span.clone())
572 });
573 let action = self.collect_result(result)?;
574 if let MaybeAction::Do(resolved_variable) = action {
575 return Ok(VisitAction::Replace(match resolved_variable {
576 ResolvedVariable::VariableId(id) => {
577 DatexExpressionData::VariableAccess(VariableAccess {
578 id,
579 name: identifier.clone(),
580 })
581 .with_span(span.clone())
582 }
583 ResolvedVariable::PointerAddress(pointer_address) => {
584 DatexExpressionData::GetReference(pointer_address)
585 .with_span(span.clone())
586 }
587 }));
588 }
589 Ok(VisitAction::SkipChildren)
590 }
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596 use crate::ast::expressions::{CreateRef, Deref};
597 use crate::ast::resolved_variable::ResolvedVariable;
598 use crate::ast::src_id::SrcId;
599 use crate::ast::type_expressions::{StructuralMap, TypeExpressionData};
600 use crate::parser::Parser;
601 use crate::references::reference::ReferenceMutability;
602 use crate::stdlib::assert_matches::assert_matches;
603 use crate::values::core_values::integer::Integer;
604 use crate::values::pointer::PointerAddress;
605
606 fn precompile(
607 ast: DatexExpression,
608 options: PrecompilerOptions,
609 ) -> Result<RichAst, SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst>
610 {
611 let mut scope_stack = PrecompilerScopeStack::default();
612 let ast_metadata = Rc::new(RefCell::new(AstMetadata::default()));
613 Precompiler::new(&mut scope_stack, ast_metadata)
614 .precompile(ast, options)
615 }
616
617 #[test]
618 fn test_precompiler_visit() {
619 let options = PrecompilerOptions::default();
620 let ast = Parser::parse_with_default_options(
621 "var x: integer = 34; var y = 10; x + y",
622 )
623 .unwrap();
624 let res = precompile(ast, options).unwrap();
625 println!("{:#?}", res.ast);
626 }
627
628 #[test]
629 fn property_access() {
630 let options = PrecompilerOptions::default();
631 let ast =
632 Parser::parse_with_default_options("var x = {a: 1}; x.a").unwrap();
633 precompile(ast, options).expect("Should precompile without errors");
634 }
635
636 #[test]
637 fn property_access_assignment() {
638 let options = PrecompilerOptions::default();
639 let ast =
640 Parser::parse_with_default_options("var x = {a: 1}; x.a = 2;")
641 .unwrap();
642 precompile(ast, options).expect("Should precompile without errors");
643 }
644
645 #[test]
646 fn undeclared_variable_error() {
647 let options = PrecompilerOptions {
648 detailed_errors: true,
649 };
650 let ast = Parser::parse_with_default_options("x + 10").unwrap();
651 let result = precompile(ast, options);
652 println!("{:#?}", result);
653 assert!(result.is_err());
654 }
655
656 #[test]
657 fn duplicate_variable_error() {
658 let options = PrecompilerOptions {
659 detailed_errors: false,
660 };
661 let ast = Parser::parse_with_default_options("var x = 1; var x = 2;")
662 .unwrap();
663 let result = precompile(ast, options);
664 assert_matches!(result.unwrap_err(), SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst::Simple(SpannedCompilerError{span, error: CompilerError::InvalidRedeclaration(name)}) if name == "x");
665 }
666
667 #[test]
668 fn invalid_type_redeclaration() {
669 let src = r#"
670 type A = integer;
671 type A = text; // redeclaration error
672 "#;
673 let ast = Parser::parse_with_default_options(src).unwrap();
674 let result = precompile(ast, PrecompilerOptions::default());
675 assert!(result.is_err());
676 assert_matches!(
677 result,
678 Err(SimpleCompilerErrorOrDetailedCompilerErrorWithRichAst::Simple(SpannedCompilerError{span, error: CompilerError::InvalidRedeclaration(name)})) if name == "A"
679 );
680 }
681
682 fn parse_unwrap(src: &str) -> DatexExpression {
683 let src_id = SrcId::test();
684 Parser::parse_with_default_options(src).unwrap()
685 }
686
687 fn parse_and_precompile_spanned_result(
688 src: &str,
689 ) -> Result<RichAst, SpannedCompilerError> {
690 let mut scope_stack = PrecompilerScopeStack::default();
691 let ast_metadata = Rc::new(RefCell::new(AstMetadata::default()));
692 let ast = Parser::parse_with_default_options(src)?;
693 precompile_ast_simple_error(ast, &mut scope_stack, ast_metadata)
694 }
695
696 fn parse_and_precompile(src: &str) -> Result<RichAst, CompilerError> {
697 parse_and_precompile_spanned_result(src).map_err(|e| e.error)
698 }
699
700 #[test]
701 fn undeclared_variable() {
702 let result = parse_and_precompile_spanned_result("x + 42");
703 assert!(result.is_err());
704 assert_matches!(
705 result,
706 Err(SpannedCompilerError{ error: CompilerError::UndeclaredVariable(var_name), span })
707 if var_name == "x" && span == Some((0..1))
708 );
709 }
710
711 #[test]
712 fn nominal_type_declaration() {
713 let result = parse_and_precompile("type User = {a: integer}; User");
714 assert!(result.is_ok());
715 let rich_ast = result.unwrap();
716 assert_eq!(
717 rich_ast.ast,
718 DatexExpressionData::Statements(Statements::new_unterminated(
719 vec![
720 DatexExpressionData::TypeDeclaration(TypeDeclaration {
721 id: Some(0),
722 name: "User".to_string(),
723 definition: TypeExpressionData::StructuralMap(
724 StructuralMap(vec![(
725 TypeExpressionData::Text("a".to_string())
726 .with_default_span(),
727 TypeExpressionData::GetReference(
728 CoreLibPointerId::Integer(None).into()
729 )
730 .with_default_span(),
731 )])
732 )
733 .with_default_span(),
734 hoisted: true,
735 kind: TypeDeclarationKind::Nominal,
736 })
737 .with_default_span(),
738 DatexExpressionData::VariableAccess(VariableAccess {
739 id: 0,
740 name: "User".to_string()
741 })
742 .with_default_span()
743 ]
744 ))
745 .with_default_span()
746 );
747 let metadata = rich_ast.metadata.borrow();
748 let var_meta = metadata.variable_metadata(0).unwrap();
749 assert_eq!(var_meta.shape, VariableShape::Type);
750 println!("{:#?}", var_meta);
751 }
752
753 #[test]
754 fn scoped_variable() {
755 let result = parse_and_precompile("(var z = 42;z); z");
756 assert!(result.is_err());
757 assert_matches!(
758 result,
759 Err(CompilerError::UndeclaredVariable(var_name))
760 if var_name == "z"
761 );
762 }
763
764 #[test]
765 fn core_types() {
766 let result = parse_and_precompile("boolean");
767 assert_matches!(
768 result,
769 Ok(
770 RichAst {
771 ast: DatexExpression { data: DatexExpressionData::GetReference(pointer_id), ..},
772 ..
773 }
774 ) if pointer_id == CoreLibPointerId::Boolean.into()
775 );
776 let result = parse_and_precompile("integer");
777 assert_matches!(
778 result,
779 Ok(
780 RichAst {
781 ast: DatexExpression { data: DatexExpressionData::GetReference(pointer_id), ..},
782 ..
783 }
784 ) if pointer_id == CoreLibPointerId::Integer(None).into()
785 );
786
787 let result = parse_and_precompile("integer/u8");
788 assert_eq!(
789 result.unwrap().ast,
790 DatexExpressionData::VariantAccess(VariantAccess {
791 base: ResolvedVariable::PointerAddress(
792 CoreLibPointerId::Integer(None).into()
793 ),
794 name: "integer".to_string(),
795 variant: "u8".to_string(),
796 })
797 .with_default_span()
798 );
799 }
800
801 #[test]
802 fn variant_access() {
803 let result =
805 parse_and_precompile("integer/u8").expect("Precompilation failed");
806 assert_eq!(
807 result.ast,
808 DatexExpressionData::VariantAccess(VariantAccess {
809 base: ResolvedVariable::PointerAddress(
810 CoreLibPointerId::Integer(None).into()
811 ),
812 name: "integer".to_string(),
813 variant: "u8".to_string(),
814 })
815 .with_default_span()
816 );
817
818 let result = parse_and_precompile("integer/invalid").unwrap();
820 assert_eq!(
821 result.ast,
822 DatexExpressionData::VariantAccess(VariantAccess {
823 base: ResolvedVariable::PointerAddress(
824 CoreLibPointerId::Integer(None).into()
825 ),
826 name: "integer".to_string(),
827 variant: "invalid".to_string(),
828 })
829 .with_default_span()
830 );
831
832 let result = parse_and_precompile("invalid/u8");
834 assert_matches!(result, Err(CompilerError::UndeclaredVariable(var_name)) if var_name == "invalid");
835
836 let result = parse_and_precompile("type User/admin = {}; User/admin");
838 assert!(result.is_err());
839 assert_matches!(result, Err(CompilerError::UndeclaredVariable(var_name)) if var_name == "User");
840
841 let result = parse_and_precompile(
843 "type User = {}; type User/admin = {}; User/admin",
844 );
845 assert!(result.is_ok());
846 let rich_ast = result.unwrap();
847 assert_eq!(
848 rich_ast.ast,
849 DatexExpressionData::Statements(Statements::new_unterminated(
850 vec![
851 DatexExpressionData::TypeDeclaration(TypeDeclaration {
852 id: Some(0),
853 name: "User".to_string(),
854 definition: TypeExpressionData::StructuralMap(
855 StructuralMap(vec![])
856 )
857 .with_default_span(),
858 hoisted: true,
859 kind: TypeDeclarationKind::Nominal,
860 })
861 .with_default_span(),
862 DatexExpressionData::TypeDeclaration(TypeDeclaration {
863 id: Some(1),
864 name: "User/admin".to_string(),
865 definition: TypeExpressionData::StructuralMap(
866 StructuralMap(vec![])
867 )
868 .with_default_span(),
869 hoisted: true,
870 kind: TypeDeclarationKind::Nominal
871 })
872 .with_default_span(),
873 DatexExpressionData::VariantAccess(VariantAccess {
874 base: ResolvedVariable::VariableId(0),
875 name: "User".to_string(),
876 variant: "admin".to_string(),
877 })
878 .with_default_span()
879 ]
880 ))
881 .with_default_span()
882 );
883
884 let result = parse_and_precompile("var a = 42; var b = 69; a/b");
886 assert!(result.is_ok());
887 let statements = if let DatexExpressionData::Statements(stmts) =
888 result.unwrap().ast.data
889 {
890 stmts
891 } else {
892 core::panic!("Expected statements");
893 };
894 assert_eq!(
895 *statements.statements.get(2).unwrap(),
896 DatexExpressionData::BinaryOperation(BinaryOperation {
897 operator: BinaryOperator::Arithmetic(
898 ArithmeticOperator::Divide
899 ),
900 left: Box::new(
901 DatexExpressionData::VariableAccess(VariableAccess {
902 id: 0,
903 name: "a".to_string()
904 })
905 .with_default_span()
906 ),
907 right: Box::new(
908 DatexExpressionData::VariableAccess(VariableAccess {
909 id: 1,
910 name: "b".to_string()
911 })
912 .with_default_span()
913 ),
914 ty: None
915 })
916 .with_default_span()
917 );
918
919 let result = parse_and_precompile("var a = 10; type b = 42; a/b");
921 assert!(result.is_ok());
922 let statements = if let DatexExpressionData::Statements(stmts) =
923 result.unwrap().ast.data
924 {
925 stmts
926 } else {
927 core::panic!("Expected statements");
928 };
929 assert_eq!(
930 *statements.statements.get(2).unwrap(),
931 DatexExpressionData::BinaryOperation(BinaryOperation {
932 operator: BinaryOperator::Arithmetic(
933 ArithmeticOperator::Divide
934 ),
935 left: Box::new(
936 DatexExpressionData::VariableAccess(VariableAccess {
937 id: 1,
938 name: "a".to_string()
939 })
940 .with_default_span()
941 ),
942 right: Box::new(
943 DatexExpressionData::VariableAccess(VariableAccess {
944 id: 0,
945 name: "b".to_string()
946 })
947 .with_default_span()
948 ),
949 ty: None
950 })
951 .with_default_span()
952 );
953 }
954
955 #[test]
956 fn test_type_declaration_assigment() {
957 let result = parse_and_precompile("type MyInt = 1; var x = MyInt;");
958 assert!(result.is_ok());
959 let rich_ast = result.unwrap();
960 assert_eq!(
961 rich_ast.ast,
962 DatexExpressionData::Statements(Statements::new_terminated(vec![
963 DatexExpressionData::TypeDeclaration(TypeDeclaration {
964 id: Some(0),
965 name: "MyInt".to_string(),
966 definition: TypeExpressionData::Integer(Integer::from(1))
967 .with_default_span(),
968 hoisted: true,
969 kind: TypeDeclarationKind::Nominal
970 })
971 .with_default_span(),
972 DatexExpressionData::VariableDeclaration(VariableDeclaration {
973 id: Some(1),
974 kind: VariableKind::Var,
975 name: "x".to_string(),
976 init_expression: Box::new(
978 DatexExpressionData::VariableAccess(VariableAccess {
979 id: 0,
980 name: "MyInt".to_string()
981 })
982 .with_default_span()
983 ),
984 type_annotation: None,
985 })
986 .with_default_span(),
987 ]))
988 .with_default_span()
989 )
990 }
991
992 #[test]
993 fn test_type_declaration_hoisted_assigment() {
994 let result = parse_and_precompile("var x = MyInt; type MyInt = 1;");
995 assert!(result.is_ok());
996 let rich_ast = result.unwrap();
997 assert_eq!(
998 rich_ast.ast,
999 DatexExpressionData::Statements(Statements::new_terminated(vec![
1000 DatexExpressionData::VariableDeclaration(VariableDeclaration {
1001 id: Some(1),
1002 kind: VariableKind::Var,
1003 name: "x".to_string(),
1004 init_expression: Box::new(
1006 DatexExpressionData::VariableAccess(VariableAccess {
1007 id: 0,
1008 name: "MyInt".to_string()
1009 })
1010 .with_default_span()
1011 ),
1012 type_annotation: None,
1013 })
1014 .with_default_span(),
1015 DatexExpressionData::TypeDeclaration(TypeDeclaration {
1016 id: Some(0),
1017 name: "MyInt".to_string(),
1018 definition: TypeExpressionData::Integer(Integer::from(1))
1019 .with_default_span(),
1020 hoisted: true,
1021 kind: TypeDeclarationKind::Nominal
1022 })
1023 .with_default_span(),
1024 ]))
1025 .with_default_span()
1026 )
1027 }
1028
1029 #[test]
1030 fn test_type_declaration_hoisted_cross_assigment() {
1031 let result = parse_and_precompile("type x = MyInt; type MyInt = x;");
1032 assert!(result.is_ok());
1033 let rich_ast = result.unwrap();
1034 assert_eq!(
1035 rich_ast.ast,
1036 DatexExpressionData::Statements(Statements::new_terminated(vec![
1037 DatexExpressionData::TypeDeclaration(TypeDeclaration {
1038 id: Some(0),
1039 name: "x".to_string(),
1040 definition: TypeExpressionData::VariableAccess(
1041 VariableAccess {
1042 id: 1,
1043 name: "MyInt".to_string()
1044 }
1045 )
1046 .with_default_span(),
1047 hoisted: true,
1048 kind: TypeDeclarationKind::Nominal
1049 })
1050 .with_default_span(),
1051 DatexExpressionData::TypeDeclaration(TypeDeclaration {
1052 id: Some(1),
1053 name: "MyInt".to_string(),
1054 definition: TypeExpressionData::VariableAccess(
1055 VariableAccess {
1056 id: 0,
1057 name: "x".to_string()
1058 }
1059 )
1060 .with_default_span(),
1061 hoisted: true,
1062 kind: TypeDeclarationKind::Nominal
1063 })
1064 .with_default_span(),
1065 ]))
1066 .with_default_span()
1067 )
1068 }
1069
1070 #[test]
1071 fn test_type_invalid_nested_type_declaration() {
1072 let result = parse_and_precompile(
1073 "type x = NestedVar; (1; type NestedVar = x;)",
1074 );
1075 assert_matches!(result, Err(CompilerError::UndeclaredVariable(var_name)) if var_name == "NestedVar");
1076 }
1077
1078 #[test]
1079 fn test_type_valid_nested_type_declaration() {
1080 let result =
1081 parse_and_precompile("type x = 10; (1; type NestedVar = x;)");
1082 assert!(result.is_ok());
1083 let rich_ast = result.unwrap();
1084 assert_eq!(
1085 rich_ast.ast,
1086 DatexExpressionData::Statements(Statements::new_unterminated(
1087 vec![
1088 DatexExpressionData::TypeDeclaration(TypeDeclaration {
1089 id: Some(0),
1090 name: "x".to_string(),
1091 definition: TypeExpressionData::Integer(
1092 Integer::from(10).into()
1093 )
1094 .with_default_span(),
1095 hoisted: true,
1096 kind: TypeDeclarationKind::Nominal
1097 })
1098 .with_default_span(),
1099 DatexExpressionData::Statements(
1100 Statements::new_terminated(vec![
1101 DatexExpressionData::Integer(Integer::from(1))
1102 .with_default_span(),
1103 DatexExpressionData::TypeDeclaration(
1104 TypeDeclaration {
1105 id: Some(1),
1106 name: "NestedVar".to_string(),
1107 definition:
1108 TypeExpressionData::VariableAccess(
1109 VariableAccess {
1110 id: 0,
1111 name: "x".to_string()
1112 }
1113 )
1114 .with_default_span(),
1115 hoisted: true,
1116 kind: TypeDeclarationKind::Nominal
1117 }
1118 )
1119 .with_default_span(),
1120 ])
1121 )
1122 .with_default_span()
1123 ]
1124 ))
1125 .with_default_span()
1126 )
1127 }
1128
1129 #[test]
1130 fn test_core_reference_type() {
1131 let result = parse_and_precompile("type x = integer");
1132 assert!(result.is_ok());
1133 let rich_ast = result.unwrap();
1134 assert_eq!(
1135 rich_ast.ast,
1136 DatexExpressionData::TypeDeclaration(TypeDeclaration {
1137 id: Some(0),
1138 name: "x".to_string(),
1139 definition: TypeExpressionData::GetReference(
1140 PointerAddress::from(CoreLibPointerId::Integer(None))
1141 )
1142 .with_default_span(),
1143 hoisted: true,
1144 kind: TypeDeclarationKind::Nominal
1145 })
1146 .with_default_span()
1147 );
1148 }
1149
1150 #[test]
1151 fn test_deref() {
1152 let result = parse_and_precompile("const x = &42; *x");
1153 assert!(result.is_ok());
1154 let rich_ast = result.unwrap();
1155 assert_eq!(
1156 rich_ast.ast,
1157 DatexExpressionData::Statements(Statements::new_unterminated(
1158 vec![
1159 DatexExpressionData::VariableDeclaration(
1160 VariableDeclaration {
1161 id: Some(0),
1162 kind: VariableKind::Const,
1163 name: "x".to_string(),
1164 init_expression: Box::new(
1165 DatexExpressionData::CreateRef(CreateRef {
1166 mutability: ReferenceMutability::Immutable,
1167 expression: Box::new(
1168 DatexExpressionData::Integer(
1169 Integer::from(42)
1170 )
1171 .with_default_span()
1172 )
1173 })
1174 .with_default_span(),
1175 ),
1176 type_annotation: None,
1177 }
1178 )
1179 .with_default_span(),
1180 DatexExpressionData::Deref(Deref {
1181 expression: Box::new(
1182 DatexExpressionData::VariableAccess(
1183 VariableAccess {
1184 id: 0,
1185 name: "x".to_string()
1186 }
1187 )
1188 .with_default_span()
1189 )
1190 })
1191 .with_default_span(),
1192 ]
1193 ))
1194 .with_default_span()
1195 );
1196 }
1197}