1use crate::parse::parsing::*;
2use crate::semantics::analysis::{FunctionSignature, Scope, StructSignature, Symbol};
3use crate::utils::location::Location;
4use crate::utils::typesafe::*;
5use std::collections::{HashMap, HashSet};
6
7#[derive(Debug, Clone)]
8pub enum AnalyserError {
9 TypeError { location: Location, message: String },
10 SemanticError { location: Location, message: String },
11}
12impl AnalyserError {
13 pub fn type_error(location: Location, message: impl Into<String>) -> Self {
14 AnalyserError::TypeError {
15 location,
16 message: message.into(),
17 }
18 }
19 pub fn semantic_error(location: Location, message: impl Into<String>) -> Self {
20 AnalyserError::SemanticError {
21 location,
22 message: message.into(),
23 }
24 }
25}
26
27fn contains_generic_param(ty: &Type) -> bool {
28 match ty {
29 Type::GenericParam(_) => true,
30 Type::Ptr(inner) => contains_generic_param(inner),
31 Type::Array { element_type, .. } => contains_generic_param(element_type),
32 Type::GenericInstance { args, .. } => args.iter().any(contains_generic_param),
33 _ => false,
34 }
35}
36
37#[derive(Debug)]
38pub struct Analyser {
39 pub scopes: Vec<Scope>,
40 pub current_scope: usize,
41 pub functions: HashMap<String, FunctionSignature>,
42 pub structs: HashMap<String, StructSignature>,
43 pub constants: HashMap<String, (Type, Expr)>,
44 current_return_type: Option<Type>,
45 loop_depth: usize,
46 pub current_generic_params: Vec<String>,
47}
48
49impl Analyser {
50 pub fn new() -> Self {
51 Self {
52 scopes: vec![Scope {
53 symbols: HashMap::new(),
54 parent: None,
55 }],
56 current_scope: 0,
57 functions: HashMap::new(),
58 structs: HashMap::new(),
59 constants: HashMap::new(),
60 current_return_type: None,
61 loop_depth: 0,
62 current_generic_params: Vec::new(),
63 }
64 }
65
66 pub fn enter_scope(&mut self) {
67 let parent_idx = self.current_scope;
68 let new_scope = Scope {
69 symbols: HashMap::new(),
70 parent: Some(parent_idx),
71 };
72 self.scopes.push(new_scope);
73 self.current_scope = self.scopes.len() - 1;
74 }
75
76 pub fn leave_scope(&mut self) {
77 let parent = self.scopes[self.current_scope]
78 .parent
79 .expect("Attempted to leave global scope");
80
81 self.scopes.pop();
82 self.current_scope = parent;
83 }
84
85 fn substitute_type(&self, ty: &Type, mapping: &HashMap<String, Type>) -> Type {
86 match ty {
87 Type::GenericParam(name) => mapping
88 .get(name)
89 .cloned()
90 .unwrap_or_else(|| Type::GenericParam(name.clone())),
91 Type::Struct(name) => mapping.get(name).cloned().unwrap_or_else(|| ty.clone()),
92 Type::Ptr(inner) => Type::Ptr(Box::new(self.substitute_type(inner, mapping))),
93 Type::Array { element_type, size } => Type::Array {
94 element_type: Box::new(self.substitute_type(element_type, mapping)),
95 size: *size,
96 },
97 Type::GenericInstance { name, args } => {
98 let substituted_args = args
99 .iter()
100 .map(|arg| self.substitute_type(arg, mapping))
101 .collect();
102 Type::GenericInstance {
103 name: name.clone(),
104 args: substituted_args,
105 }
106 }
107 _ => ty.clone(),
108 }
109 }
110
111 fn instantiate_generic_types(
112 &mut self,
113 ty: &Type,
114 span: &Location,
115 ) -> Result<Type, AnalyserError> {
116 match ty {
117 Type::Ptr(inner) => {
118 let inst = self.instantiate_generic_types(inner, span)?;
119 Ok(Type::Ptr(Box::new(inst)))
120 }
121 Type::Array { element_type, size } => {
122 let inst = self.instantiate_generic_types(element_type, span)?;
123 Ok(Type::Array {
124 element_type: Box::new(inst),
125 size: *size,
126 })
127 }
128 Type::GenericInstance { name, args } => {
129 let mut resolved_args = Vec::new();
130 for arg in args {
131 resolved_args.push(self.instantiate_generic_types(arg, span)?);
132 }
133
134 if resolved_args.iter().any(contains_generic_param) {
135 return Ok(Type::GenericInstance {
136 name: name.clone(),
137 args: resolved_args,
138 });
139 }
140
141 let template = self
142 .structs
143 .get(name)
144 .ok_or_else(|| AnalyserError::SemanticError {
145 location: span.clone(),
146 message: format!("Semantic Error: Generic struct '{}' not found.", name),
147 })?
148 .clone();
149
150 if template.generic_params.len() != resolved_args.len() {
151 return Err(AnalyserError::TypeError {
152 location: span.clone(),
153 message: format!(
154 "Type Error: Struct '{}' expects {} type parameters, found {}",
155 name,
156 template.generic_params.len(),
157 resolved_args.len()
158 ),
159 });
160 }
161
162 let mangled = mangle_name(name, &resolved_args);
163
164 if !self.structs.contains_key(&mangled) {
165 let mapping: HashMap<String, Type> = template
166 .generic_params
167 .iter()
168 .cloned()
169 .zip(resolved_args.iter().cloned())
170 .collect();
171
172 let mut fresh_fields = HashMap::new();
173 for (f_name, f_type) in &template.fields {
174 let substituted = self.substitute_type(f_type, &mapping);
175 fresh_fields.insert(f_name.clone(), substituted);
176 }
177
178 self.structs.insert(
179 mangled.clone(),
180 StructSignature {
181 generic_params: Vec::new(),
182 fields: fresh_fields,
183 location: span.clone(),
184 },
185 );
186 }
187
188 Ok(Type::Struct(mangled))
189 }
190 Type::GenericParam(p) => Ok(Type::GenericParam(p.clone())),
191 _ => Ok(ty.clone()),
192 }
193 }
194
195 fn declare_variable(
196 &mut self,
197 name: &str,
198 data_type: Type,
199 span: Location,
200 ) -> Result<(), AnalyserError> {
201 let scope = &mut self.scopes[self.current_scope];
202 if scope.symbols.contains_key(name) {
203 return Err(AnalyserError::SemanticError {
204 location: span,
205 message: format!(
206 "Semantic Error: Variable '{}' already declared in this scope.",
207 name
208 ),
209 });
210 }
211 scope.symbols.insert(
212 name.to_string(),
213 Symbol {
214 name: name.to_string(),
215 ty: data_type,
216 },
217 );
218 Ok(())
219 }
220
221 fn resolve_variable(&self, name: &str) -> Option<&Symbol> {
222 let mut current = self.current_scope;
223 loop {
224 if let Some(symbol) = self.scopes[current].symbols.get(name) {
225 return Some(symbol);
226 }
227 match self.scopes[current].parent {
228 Some(p) => current = p,
229 None => break,
230 }
231 }
232 None
233 }
234
235 fn validate_type_exists(&self, ty: &Type, span: &Location) -> Result<(), AnalyserError> {
236 match ty {
237 Type::Struct(name) => {
238 if self.current_generic_params.contains(name) {
239 return Ok(());
240 }
241
242 if !self.structs.contains_key(name) {
243 return Err(AnalyserError::SemanticError {
244 location: span.clone(),
245 message: format!(
246 "Semantic Error: Type '{}' is used here but never defined.",
247 name
248 ),
249 });
250 }
251 }
252 Type::GenericInstance { name, args } => {
253 if !self.structs.contains_key(name) {
254 return Err(AnalyserError::SemanticError {
255 location: span.clone(),
256 message: format!(
257 "Semantic Error: Generic Struct '{}' is used here but never defined.",
258 name
259 ),
260 });
261 }
262 for arg in args {
263 self.validate_type_exists(arg, span)?;
264 }
265 }
266 Type::Ptr(inner) => {
267 self.validate_type_exists(inner, span)?;
268 }
269 Type::Array { element_type, .. } => {
270 self.validate_type_exists(element_type, span)?;
271 }
272 _ => {}
273 }
274 Ok(())
275 }
276
277 fn declare_struct(
278 &mut self,
279 name: &str,
280 generic_params: Vec<String>,
281 fields: HashMap<String, Type>,
282 location: Location,
283 ) -> Result<(), AnalyserError> {
284 if let Some(existing) = self.structs.get(name) {
285 return Err(AnalyserError::SemanticError {
286 location,
287 message: format!(
288 "Semantic Error: Struct '{}' is already defined at [{}]",
289 name, existing.location
290 ),
291 });
292 }
293
294 self.structs.insert(
295 name.to_string(),
296 StructSignature {
297 generic_params,
298 fields,
299 location,
300 },
301 );
302
303 Ok(())
304 }
305
306 fn declare_function(
307 &mut self,
308 name: &str,
309 generic_params: Vec<String>,
310 param_types: Vec<Type>,
311 return_type: Type,
312 location: Location,
313 ) -> Result<(), AnalyserError> {
314 if let Some(existing) = self.functions.get(name) {
315 return Err(AnalyserError::SemanticError {
316 location,
317 message: format!(
318 "Semantic Error: Function '{}' is already defined at [{}]",
319 name, existing.location
320 ),
321 });
322 }
323
324 self.functions.insert(
325 name.to_string(),
326 FunctionSignature {
327 generic_params,
328 param_types,
329 return_type,
330 location,
331 },
332 );
333
334 Ok(())
335 }
336
337 fn resolve_function(&self, name: &str) -> Option<&FunctionSignature> {
338 self.functions.get(name)
339 }
340
341 pub fn check_truthiness(&self, ty: &Type) -> bool {
342 is_truthy_type(ty)
343 }
344
345 pub fn check_expr(
346 &mut self,
347 expr: &Expr,
348 expected_type: Option<&Type>,
349 ) -> Result<Type, AnalyserError> {
350 match &expr.kind {
351 ExprKind::Sizeof { .. } => Ok(Type::Int),
352 ExprKind::Cast { left, right } => {
353 let leftty = self.check_expr(left.as_ref(), None)?;
354 if types_compatible(&leftty, right) {
355 return Ok(right.clone());
356 }
357 Err(AnalyserError::type_error(
358 expr.span.clone(),
359 format!(
360 "Cannot cast '{}' to '{}'",
361 type_to_string(&leftty),
362 type_to_string(right)
363 ),
364 ))
365 }
366 ExprKind::Literal(lit) => match lit {
367 Literal::Int(_) => {
368 if let Some(Type::UInt) = expected_type {
369 Ok(Type::UInt)
370 } else {
371 Ok(Type::Int)
372 }
373 }
374 Literal::String(_) => Ok(Type::Str),
375 Literal::Bool(_) => Ok(Type::Bool),
376 Literal::Char(_) => Ok(Type::Char),
377 Literal::Arr { elements } => {
378 let expected_elem_ty = match expected_type {
379 Some(Type::Array { element_type, .. }) => Some(&**element_type),
380 _ => None,
381 };
382
383 let element_type = if elements.is_empty() {
384 if let Some(elem_ty) = expected_elem_ty {
385 elem_ty.clone()
386 } else {
387 return Err(AnalyserError::type_error(
388 expr.span.clone(),
389 "Cannot infer the type of an empty array literal without explicit type context."
390 .to_string(),
391 ));
392 }
393 } else {
394 self.check_expr(&elements[0], expected_elem_ty)?
395 };
396
397 for el in elements {
398 let el_type = self.check_expr(el, Some(&element_type))?;
399 if !types_equal(&element_type, &el_type) {
400 return Err(AnalyserError::type_error(
401 el.span.clone(),
402 format!(
403 "Heterogeneous array literals are not allowed. Expected elements of type '{}', found '{}'.",
404 type_to_string(&element_type),
405 type_to_string(&el_type)
406 ),
407 ));
408 }
409 }
410
411 Ok(Type::Array {
412 element_type: Box::new(element_type),
413 size: elements.len(),
414 })
415 }
416 },
417 ExprKind::Field { base, field } => {
418 let base_type = self.check_expr(base, None)?;
419
420 match base_type {
421 Type::Struct(struct_name) => {
422 let signature = self.structs.get(&struct_name).ok_or_else(|| {
423 AnalyserError::semantic_error(
424 expr.span.clone(),
425 format!(
426 "Attempted to access field '{}' on undefined struct '{}'.",
427 field, struct_name
428 ),
429 )
430 })?;
431
432 let field_type = signature.fields.get(field).ok_or_else(|| {
433 AnalyserError::semantic_error(
434 expr.span.clone(),
435 format!("Struct '{}' has no field named '{}'.", struct_name, field),
436 )
437 })?;
438
439 Ok(field_type.clone())
440 }
441 Type::GenericInstance { name, args } => {
442 let signature = self.structs.get(&name).ok_or_else(|| {
443 AnalyserError::semantic_error(
444 expr.span.clone(),
445 format!(
446 "Attempted to access field '{}' on undefined struct '{}'.",
447 field, name
448 ),
449 )
450 })?;
451
452 let raw_field_type = signature.fields.get(field).ok_or_else(|| {
453 AnalyserError::semantic_error(
454 expr.span.clone(),
455 format!("Struct '{}' has no field named '{}'.", name, field),
456 )
457 })?;
458
459 let mapping: HashMap<String, Type> = signature
460 .generic_params
461 .iter()
462 .cloned()
463 .zip(args.iter().cloned())
464 .collect();
465
466 Ok(self.substitute_type(raw_field_type, &mapping))
467 }
468 _ => Err(AnalyserError::type_error(
469 expr.span.clone(),
470 format!(
471 "Cannot access a field on non-struct type '{}'.",
472 type_to_string(&base_type)
473 ),
474 )),
475 }
476 }
477 ExprKind::StructLiteral {
478 struct_name,
479 generic_args,
480 fields,
481 } => {
482 let concrete_ty = if generic_args.is_empty() {
483 let template = self.structs.get(struct_name).ok_or_else(|| {
484 AnalyserError::semantic_error(
485 expr.span.clone(),
486 format!("Undefined struct '{}'.", struct_name),
487 )
488 })?;
489 if !template.generic_params.is_empty() {
490 return Err(AnalyserError::type_error(
491 expr.span.clone(),
492 format!("Struct '{}' requires generic arguments.", struct_name),
493 ));
494 }
495 Type::Struct(struct_name.clone())
496 } else {
497 let generic_ty = Type::GenericInstance {
498 name: struct_name.clone(),
499 args: generic_args.clone(),
500 };
501 self.validate_type_exists(&generic_ty, &expr.span)?;
502 self.instantiate_generic_types(&generic_ty, &expr.span)?
503 };
504
505 let concrete_name = match &concrete_ty {
506 Type::Struct(name) => name.clone(),
507 _ => {
508 return Err(AnalyserError::type_error(
509 expr.span.clone(),
510 format!("Expected concrete struct type, got {:?}", concrete_ty),
511 ));
512 }
513 };
514 let struct_def = self
515 .structs
516 .get(&concrete_name)
517 .ok_or_else(|| {
518 AnalyserError::semantic_error(
519 expr.span.clone(),
520 format!("Instantiated struct '{}' not found.", concrete_name),
521 )
522 })?
523 .clone();
524
525 if fields.len() != struct_def.fields.len() {
526 return Err(AnalyserError::type_error(
527 expr.span.clone(),
528 format!(
529 "Struct '{}' expects {} fields, found {}.",
530 concrete_name,
531 struct_def.fields.len(),
532 fields.len()
533 ),
534 ));
535 }
536
537 let mut seen_fields = HashSet::new();
538 for (field_name, field_expr) in fields {
539 if !seen_fields.insert(field_name) {
540 return Err(AnalyserError::semantic_error(
541 field_expr.span.clone(),
542 format!("Duplicate field '{}' in struct literal.", field_name),
543 ));
544 }
545
546 let expected_ty = struct_def.fields.get(field_name).ok_or_else(|| {
547 AnalyserError::semantic_error(
548 field_expr.span.clone(),
549 format!(
550 "Field '{}' does not exist in struct '{}'.",
551 field_name, concrete_name
552 ),
553 )
554 })?;
555
556 let actual_ty = self.check_expr(field_expr, Some(expected_ty))?;
557 if !types_equal(expected_ty, &actual_ty) {
558 return Err(AnalyserError::type_error(
559 field_expr.span.clone(),
560 format!(
561 "Field '{}' expects type '{}', but found '{}'.",
562 field_name,
563 type_to_string(expected_ty),
564 type_to_string(&actual_ty)
565 ),
566 ));
567 }
568 }
569
570 Ok(concrete_ty)
571 }
572 ExprKind::Index { base, index } => {
573 let base_type = self.check_expr(base, None)?;
574 let index_type = self.check_expr(index, Some(&Type::Int))?;
575
576 if !is_integer(&index_type) {
577 return Err(AnalyserError::type_error(
578 index.span.clone(),
579 format!(
580 "Array index must be an integer, found '{}'.",
581 type_to_string(&index_type)
582 ),
583 ));
584 }
585
586 match base_type {
587 Type::Array { element_type, .. } => Ok(*element_type),
588 Type::Ptr(inner_type) => Ok(*inner_type),
589 _ => Err(AnalyserError::type_error(
590 expr.span.clone(),
591 format!(
592 "Cannot index into non-indexable type '{}'.",
593 type_to_string(&base_type)
594 ),
595 )),
596 }
597 }
598 ExprKind::Identifier(name) => {
599 if let Some(symbol) = self.resolve_variable(name) {
600 Ok(symbol.ty.clone())
601 } else if let Some((const_type, _)) = self.constants.get(name) {
602 Ok(const_type.clone())
603 } else {
604 Err(AnalyserError::semantic_error(
605 expr.span.clone(),
606 format!("Symbol '{}' is used before definition.", name),
607 ))
608 }
609 }
610 ExprKind::Call {
611 callee,
612 generic_args,
613 args,
614 } => {
615 let template = self
616 .resolve_function(&callee.value)
617 .ok_or_else(|| {
618 AnalyserError::semantic_error(
619 callee.location.clone(),
620 format!("Call to undefined function '{}'", callee.value),
621 )
622 })?
623 .clone();
624
625 let mut resolved_func_name = callee.value.clone();
626
627 if !template.generic_params.is_empty() || !generic_args.is_empty() {
628 if template.generic_params.len() != generic_args.len() {
629 return Err(AnalyserError::type_error(
630 expr.span.clone(),
631 format!(
632 "Function '{}' expects {} type parameters, found {}",
633 callee.value,
634 template.generic_params.len(),
635 generic_args.len()
636 ),
637 ));
638 }
639
640 let mut inst_args = Vec::new();
641 for g_arg in generic_args {
642 inst_args.push(self.instantiate_generic_types(g_arg, &callee.location)?);
643 }
644
645 resolved_func_name = mangle_name(&callee.value, &inst_args);
646
647 if !self.functions.contains_key(&resolved_func_name) {
648 let mut mapping: HashMap<String, Type> = HashMap::new();
649 for (param_name, concrete_type) in
650 template.generic_params.iter().zip(&inst_args)
651 {
652 mapping.insert(param_name.clone(), concrete_type.clone());
653 mapping
654 .insert(format!("gparam__{}", param_name), concrete_type.clone());
655 }
656
657 let substituted_return =
658 self.substitute_type(&template.return_type, &mapping);
659 let fresh_return =
660 self.instantiate_generic_types(&substituted_return, &callee.location)?;
661
662 let mut fresh_params = Vec::new();
663 for p_ty in &template.param_types {
664 let substituted_param = self.substitute_type(p_ty, &mapping);
665 let fully_resolved_param = self
666 .instantiate_generic_types(&substituted_param, &callee.location)?;
667 fresh_params.push(fully_resolved_param);
668 }
669
670 self.functions.insert(
671 resolved_func_name.clone(),
672 FunctionSignature {
673 generic_params: Vec::new(),
674 param_types: fresh_params,
675 return_type: fresh_return,
676 location: template.location.clone(),
677 },
678 );
679 }
680 }
681
682 let sig = self.functions.get(&resolved_func_name).unwrap();
683
684 if args.len() != sig.param_types.len() {
685 return Err(AnalyserError::type_error(
686 expr.span.clone(),
687 format!(
688 "Function '{}' expects {} argument(s), found {}",
689 callee.value,
690 sig.param_types.len(),
691 args.len()
692 ),
693 ));
694 }
695
696 let param_types = sig.param_types.clone();
697 let return_type = sig.return_type.clone();
698
699 for (i, (arg, expected)) in args.iter().zip(param_types.iter()).enumerate() {
700 let arg_type = self.check_expr(arg, Some(expected))?;
701 match (expected, &arg_type) {
702 (
703 Type::Array {
704 element_type: expected_elem,
705 ..
706 },
707 Type::Array {
708 element_type: actual_elem,
709 ..
710 },
711 ) => {
712 if **expected_elem != Type::Any
713 && !types_equal(expected_elem, actual_elem)
714 {
715 return Err(AnalyserError::type_error(
716 arg.span.clone(),
717 format!(
718 "Argument {} to '{}' expects array of '{}', found array of '{}'",
719 i + 1,
720 callee.value,
721 type_to_string(expected_elem),
722 type_to_string(actual_elem),
723 ),
724 ));
725 }
726 }
727
728 (Type::Array { .. }, _) => {
729 return Err(AnalyserError::type_error(
730 arg.span.clone(),
731 format!(
732 "Argument {} to '{}' expects '{}', found '{}'",
733 i + 1,
734 callee.value,
735 type_to_string(expected),
736 type_to_string(&arg_type),
737 ),
738 ));
739 }
740
741 _ => {
742 if !types_equal(expected, &arg_type) {
743 return Err(AnalyserError::type_error(
744 arg.span.clone(),
745 format!(
746 "Argument {} to '{}' expects '{}', found '{}'",
747 i + 1,
748 callee.value,
749 type_to_string(expected),
750 type_to_string(&arg_type),
751 ),
752 ));
753 }
754 }
755 }
756 }
757
758 Ok(return_type)
759 }
760
761 ExprKind::Binary { left, op, right } => {
762 let left_type = self.check_expr(left, None)?;
763 let right_type = self.check_expr(right, Some(&left_type))?;
764
765 match op {
766 BinaryOp::Add => {
767 if is_integer(&left_type) && is_integer(&right_type) {
768 if left_type == right_type {
769 Ok(left_type)
770 } else {
771 Err(AnalyserError::type_error(
772 expr.span.clone(),
773 format!(
774 "Cannot add mismatched integer types '{}' and '{}'",
775 type_to_string(&left_type),
776 type_to_string(&right_type)
777 ),
778 ))
779 }
780 } else if Type::Str != left_type && Type::Str != right_type {
781 Ok(Type::Str)
782 } else {
783 Err(AnalyserError::type_error(
784 expr.span.clone(),
785 format!(
786 "Cannot add type '{}' and '{}'",
787 type_to_string(&left_type),
788 type_to_string(&right_type)
789 ),
790 ))
791 }
792 }
793 BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => {
794 if is_integer(&left_type) && is_integer(&right_type) {
795 if types_equal(&left_type, &right_type) {
796 Ok(left_type)
797 } else {
798 Err(AnalyserError::type_error(
799 expr.span.clone(),
800 format!(
801 "Mixed-type integer arithmetic ('{}' and '{}') is not allowed",
802 type_to_string(&left_type),
803 type_to_string(&right_type)
804 ),
805 ))
806 }
807 } else {
808 Err(AnalyserError::type_error(
809 expr.span.clone(),
810 format!(
811 "Operator '{:?}' expects integers, but found '{}' and '{}'",
812 op,
813 type_to_string(&left_type),
814 type_to_string(&right_type)
815 ),
816 ))
817 }
818 }
819 BinaryOp::Eq
820 | BinaryOp::NEq
821 | BinaryOp::Gt
822 | BinaryOp::GtE
823 | BinaryOp::And
824 | BinaryOp::Or
825 | BinaryOp::Lt
826 | BinaryOp::LtE => {
827 if types_equal(&left_type, &right_type) {
828 Ok(Type::Bool)
829 } else {
830 Err(AnalyserError::type_error(
831 expr.span.clone(),
832 format!(
833 "Cannot compare incompatible types '{}' and '{}'",
834 type_to_string(&left_type),
835 type_to_string(&right_type)
836 ),
837 ))
838 }
839 }
840 }
841 }
842 ExprKind::Unary { op, expr: sub_expr } => {
843 let expr_type = self.check_expr(sub_expr, None)?;
844 match op {
845 UnaryOp::Positive | UnaryOp::Negative => {
846 if is_signed_integer(&expr_type) {
847 Ok(expr_type)
848 } else {
849 Err(AnalyserError::type_error(
850 expr.span.clone(),
851 format!(
852 "Unary sign operators are only supported on signed integers, found '{}'",
853 type_to_string(&expr_type)
854 ),
855 ))
856 }
857 }
858 UnaryOp::Not => {
859 if expr_type == Type::Bool {
860 Ok(Type::Bool)
861 } else {
862 Err(AnalyserError::type_error(
863 expr.span.clone(),
864 format!(
865 "Unary boolean operator expects 'bool', found '{}'",
866 type_to_string(&expr_type)
867 ),
868 ))
869 }
870 }
871 UnaryOp::AddressOf => Ok(Type::Ptr(Box::new(expr_type))),
872 UnaryOp::Deref => match expr_type {
873 Type::Ptr(inner_type) => Ok(*inner_type),
874 _ => Err(AnalyserError::type_error(
875 expr.span.clone(),
876 format!(
877 "Cannot dereference non-pointer type '{}'",
878 type_to_string(&expr_type)
879 ),
880 )),
881 },
882 }
883 }
884 }
885 }
886
887 pub fn check_stmt(&mut self, stmt: &Stmt) -> Result<(), AnalyserError> {
888 match stmt {
889 Stmt::Use { .. } => unreachable!(),
890
891 Stmt::Struct {
892 name,
893 generic_params,
894 fields,
895 } => {
896 let mut struct_fields = HashMap::new();
897
898 let prev_generic_params =
899 std::mem::replace(&mut self.current_generic_params, generic_params.clone());
900
901 for field in fields {
902 let field_type = match &field.ptype {
903 Some(t) => t.clone(),
904 None => Type::Any,
905 };
906
907 if struct_fields.contains_key(&field.name.value) {
908 return Err(AnalyserError::SemanticError {
909 location: field.name.location.clone(),
910 message: format!(
911 "Semantic Error: Struct '{}' contains duplicate field '{}'",
912 name.value, field.name.value
913 ),
914 });
915 }
916
917 struct_fields.insert(field.name.value.clone(), field_type);
918 }
919
920 self.declare_struct(
921 &name.value,
922 generic_params.clone(),
923 struct_fields,
924 name.location.clone(),
925 )?;
926
927 self.current_generic_params = prev_generic_params;
928
929 Ok(())
930 }
931
932 Stmt::Break { location } => {
933 if self.loop_depth == 0 {
934 return Err(AnalyserError::SemanticError {
935 location: location.clone(),
936 message:
937 "Semantic Error: Break statement must be in a while loop statement"
938 .to_string(),
939 });
940 }
941 Ok(())
942 }
943
944 Stmt::Extern {
945 name,
946 rttype,
947 generic_params,
948 params,
949 } => {
950 let return_type = match rttype {
951 Some(rt) => {
952 let instantiated = self.instantiate_generic_types(rt, &name.location)?;
953 self.validate_type_exists(&instantiated, &name.location)?;
954 instantiated
955 }
956 None => Type::Void,
957 };
958
959 let prev_generic_params =
960 std::mem::replace(&mut self.current_generic_params, generic_params.clone());
961
962 let mut param_types = Vec::new();
963 for param in params {
964 let ptype = match ¶m.ptype {
965 Some(pt) => {
966 let instantiated =
967 self.instantiate_generic_types(pt, ¶m.name.location)?;
968 self.validate_type_exists(&instantiated, ¶m.name.location)?;
969 instantiated
970 }
971 None => Type::Any,
972 };
973 param_types.push(ptype);
974 }
975
976 self.current_generic_params = prev_generic_params;
977
978 self.declare_function(
979 &name.value,
980 generic_params.clone(),
981 param_types,
982 return_type,
983 name.location.clone(),
984 )?;
985 Ok(())
986 }
987
988 Stmt::Constant { name, vtype, expr } => {
989 if self.current_return_type.is_some() {
990 return Err(AnalyserError::SemanticError {
991 location: name.location.clone(),
992 message: format!(
993 "Semantic Error: Constant '{}' cannot be defined inside a function.",
994 name.value
995 ),
996 });
997 }
998
999 let const_type = match (vtype, expr) {
1000 (Some(explicit_type), expr_node) => {
1001 let instantiated =
1002 self.instantiate_generic_types(explicit_type, &name.location)?;
1003 self.validate_type_exists(&instantiated, &name.location)?;
1004 let expr_type = self.check_expr(expr_node, Some(&instantiated))?;
1005 if !types_equal(&instantiated, &expr_type) {
1006 return Err(AnalyserError::TypeError {
1007 location: expr_node.span.clone(),
1008 message: format!(
1009 "Type Error: Constant '{}' declared as '{}' but initialiser has type '{}'",
1010 name.value,
1011 type_to_string(&instantiated),
1012 type_to_string(&expr_type)
1013 ),
1014 });
1015 }
1016 instantiated
1017 }
1018 (None, expr_node) => self.check_expr(expr_node, None)?,
1019 };
1020
1021 if self.constants.contains_key(&name.value) {
1022 return Err(AnalyserError::SemanticError {
1023 location: name.location.clone(),
1024 message: format!(
1025 "Semantic Error: Constant '{}' already defined.",
1026 name.value
1027 ),
1028 });
1029 }
1030
1031 self.constants
1032 .insert(name.value.clone(), (const_type, expr.clone()));
1033
1034 Ok(())
1035 }
1036
1037 Stmt::Assignment { ident, vtype, expr } => {
1038 let variable_type = match (vtype, expr) {
1039 (Some(explicit_type), Some(expr_node)) => {
1040 let instantiated =
1041 self.instantiate_generic_types(explicit_type, &ident.location)?;
1042 self.validate_type_exists(&instantiated, &ident.location)?;
1043 let expr_type = self.check_expr(expr_node, Some(&instantiated))?;
1044
1045 if !types_equal(&instantiated, &expr_type) {
1046 return Err(AnalyserError::type_error(
1047 expr_node.span.clone(),
1048 format!(
1049 "Variable '{}' declared as '{}' but assigned type '{}'",
1050 ident.value,
1051 type_to_string(&instantiated),
1052 type_to_string(&expr_type)
1053 ),
1054 ));
1055 }
1056 instantiated
1057 }
1058 (Some(explicit_type), None) => {
1059 let instantiated =
1060 self.instantiate_generic_types(explicit_type, &ident.location)?;
1061 self.validate_type_exists(&instantiated, &ident.location)?;
1062 instantiated
1063 }
1064 (None, Some(expr_node)) => self.check_expr(expr_node, None)?,
1065 (None, None) => {
1066 return Err(AnalyserError::semantic_error(
1067 ident.location.clone(),
1068 format!(
1069 "Variable '{}' declared without an explicit type or initializer expression.",
1070 ident.value
1071 ),
1072 ));
1073 }
1074 };
1075
1076 if let Some(existing_symbol) = self.resolve_variable(&ident.value) {
1077 if !types_equal(&existing_symbol.ty, &variable_type) {
1078 return Err(AnalyserError::type_error(
1079 ident.location.clone(),
1080 format!(
1081 "Cannot reassign type '{}' to variable '{}' of type '{}'",
1082 type_to_string(&variable_type),
1083 ident.value,
1084 type_to_string(&existing_symbol.ty)
1085 ),
1086 ));
1087 }
1088 } else {
1089 self.declare_variable(&ident.value, variable_type, ident.location.clone())?;
1090 }
1091
1092 Ok(())
1093 }
1094
1095 Stmt::DerefReassignment { target, expr } => {
1096 let target_resolved_type = self.check_expr(target, None)?;
1097 let expr_type = self.check_expr(expr, Some(&target_resolved_type))?;
1098
1099 if !types_equal(&target_resolved_type, &expr_type) {
1100 return Err(AnalyserError::type_error(
1101 expr.span.clone(),
1102 format!(
1103 "Cannot assign type '{}' to target location of type '{}'",
1104 type_to_string(&expr_type),
1105 type_to_string(&target_resolved_type)
1106 ),
1107 ));
1108 }
1109
1110 Ok(())
1111 }
1112
1113 Stmt::Reassignment { ident, expr } => {
1114 let expected_ty = self
1115 .resolve_variable(&ident.value)
1116 .map(|symbol| symbol.ty.clone())
1117 .ok_or_else(|| {
1118 AnalyserError::semantic_error(
1119 ident.location.clone(),
1120 format!("Cannot reassign to undefined variable '{}'", ident.value),
1121 )
1122 })?;
1123
1124 let expr_type = self.check_expr(expr, Some(&expected_ty))?;
1125
1126 if !types_equal(&expected_ty, &expr_type) {
1127 return Err(AnalyserError::type_error(
1128 expr.span.clone(),
1129 format!(
1130 "Cannot assign type '{}' to variable '{}' of type '{}'",
1131 type_to_string(&expr_type),
1132 ident.value,
1133 type_to_string(&expected_ty)
1134 ),
1135 ));
1136 }
1137
1138 Ok(())
1139 }
1140
1141 Stmt::Expr(expr) => {
1142 self.check_expr(expr, None)?;
1143 Ok(())
1144 }
1145
1146 Stmt::While { cond, body } => {
1147 let cond_type = self.check_expr(cond, None)?;
1148 if !self.check_truthiness(&cond_type) {
1149 return Err(AnalyserError::type_error(
1150 cond.span.clone(),
1151 format!(
1152 "'while' condition is not truthy, found '{}'",
1153 type_to_string(&cond_type)
1154 ),
1155 ));
1156 }
1157 self.enter_scope();
1158 self.loop_depth += 1;
1159 for block_stmt in body {
1160 self.check_stmt(block_stmt)?;
1161 }
1162 self.leave_scope();
1163 self.loop_depth -= 1;
1164 Ok(())
1165 }
1166
1167 Stmt::For {
1168 init,
1169 cond,
1170 step,
1171 body,
1172 } => {
1173 self.enter_scope();
1174
1175 self.check_stmt(init.as_ref())?;
1176
1177 let cond_type = self.check_expr(cond, None)?;
1178 if !self.check_truthiness(&cond_type) {
1179 self.leave_scope();
1180 return Err(AnalyserError::type_error(
1181 cond.span.clone(),
1182 format!(
1183 "'for' condition is not truthy, found '{}'",
1184 type_to_string(&cond_type)
1185 ),
1186 ));
1187 }
1188
1189 for block_stmt in body {
1190 self.check_stmt(block_stmt)?;
1191 }
1192
1193 self.check_stmt(step.as_ref())?;
1194
1195 self.leave_scope();
1196
1197 Ok(())
1198 }
1199
1200 Stmt::If {
1201 cond,
1202 then_branch,
1203 else_if_branches,
1204 else_branch,
1205 } => {
1206 let cond_type = self.check_expr(cond, None)?;
1207 if !self.check_truthiness(&cond_type) {
1208 return Err(AnalyserError::type_error(
1209 cond.span.clone(),
1210 format!(
1211 "'if' condition is not truthy, found '{}'",
1212 type_to_string(&cond_type)
1213 ),
1214 ));
1215 }
1216
1217 self.enter_scope();
1218 for block_stmt in then_branch {
1219 self.check_stmt(block_stmt)?;
1220 }
1221 self.leave_scope();
1222
1223 for (cond, body) in else_if_branches {
1224 let cond_type = self.check_expr(cond, None)?;
1225 if !self.check_truthiness(&cond_type) {
1226 return Err(AnalyserError::type_error(
1227 cond.span.clone(),
1228 format!(
1229 "'elseif' condition is not truthy, found '{}'",
1230 type_to_string(&cond_type)
1231 ),
1232 ));
1233 }
1234
1235 self.enter_scope();
1236 for body_stmt in body {
1237 self.check_stmt(body_stmt)?;
1238 }
1239 self.leave_scope();
1240 }
1241
1242 if let Some(else_stmts) = else_branch {
1243 self.enter_scope();
1244 for block_stmt in else_stmts {
1245 self.check_stmt(block_stmt)?;
1246 }
1247 self.leave_scope();
1248 }
1249
1250 Ok(())
1251 }
1252 Stmt::Function {
1253 name,
1254 public: _,
1255 rttype,
1256 generic_params,
1257 params,
1258 body,
1259 } => {
1260 let is_generic = !generic_params.is_empty();
1261
1262 let return_type = match rttype {
1263 Some(rt) => {
1264 if is_generic {
1265 rt.clone()
1266 } else {
1267 let instantiated =
1268 self.instantiate_generic_types(rt, &name.location)?;
1269 self.validate_type_exists(&instantiated, &name.location)?;
1270 instantiated
1271 }
1272 }
1273 None => Type::Void,
1274 };
1275
1276 let prev_generic_params =
1277 std::mem::replace(&mut self.current_generic_params, generic_params.clone());
1278
1279 let mut param_types = Vec::new();
1280 for param in params {
1281 let ptype = match ¶m.ptype {
1282 Some(pt) => {
1283 if is_generic {
1284 pt.clone()
1285 } else {
1286 let instantiated =
1287 self.instantiate_generic_types(pt, ¶m.name.location)?;
1288 self.validate_type_exists(&instantiated, ¶m.name.location)?;
1289 instantiated
1290 }
1291 }
1292 None => Type::Any,
1293 };
1294 param_types.push(ptype);
1295 }
1296
1297 self.declare_function(
1298 &name.value,
1299 generic_params.clone(),
1300 param_types.clone(),
1301 return_type.clone(),
1302 name.location.clone(),
1303 )?;
1304
1305 self.enter_scope();
1306 for (param, ptype) in params.iter().zip(param_types) {
1307 self.declare_variable(¶m.name.value, ptype, param.name.location.clone())?;
1308 }
1309
1310 let prev_return_type = self.current_return_type.replace(return_type.clone());
1311 let mut returns = false;
1312 for block_stmt in body {
1313 if let Stmt::Return { .. } = block_stmt {
1314 returns = true;
1315 }
1316 self.check_stmt(block_stmt)?;
1317 }
1318 self.current_return_type = prev_return_type;
1319
1320 if return_type != Type::Void && !returns {
1321 return Err(AnalyserError::TypeError {
1322 location: name.location.clone(),
1323 message: format!(
1324 "Type Error: Function '{}' must return a value of type '{}'",
1325 name.value,
1326 type_to_string(&return_type)
1327 ),
1328 });
1329 }
1330
1331 self.current_generic_params = prev_generic_params;
1332 self.leave_scope();
1333 Ok(())
1334 }
1335
1336 Stmt::Return { value, span } => {
1337 let expected = self.current_return_type.clone().ok_or_else(|| {
1338 AnalyserError::SemanticError {
1339 location: span.clone(),
1340 message: "Semantic Error: 'return' used outside of a function".to_string(),
1341 }
1342 })?;
1343
1344 let actual_type = match value {
1345 Some(e) => self.check_expr(e, Some(&expected))?,
1346 None => Type::Void,
1347 };
1348
1349 if !types_equal(&expected, &actual_type) {
1350 return Err(AnalyserError::TypeError {
1351 location: span.clone(),
1352 message: format!(
1353 "Function expects return type '{}', found '{}'",
1354 type_to_string(&expected),
1355 type_to_string(&actual_type)
1356 ),
1357 });
1358 }
1359
1360 Ok(())
1361 }
1362 }
1363 }
1364
1365 pub fn analyse(&mut self, program: &Program) -> Result<(), AnalyserError> {
1366 for stmt in &program.statements {
1367 self.check_stmt(stmt)?;
1368 }
1369 Ok(())
1370 }
1371}
1372impl Default for Analyser {
1373 fn default() -> Self {
1374 Self::new()
1375 }
1376}