1use crate::Analyzer;
7use crate::err::{Error, ErrorKind};
8use seq_map::SeqMap;
9use std::rc::Rc;
10use swamp_script_semantic::{
11 ExternalFunctionDefinition, Function, InternalFunctionDefinition, LocalIdentifier, UseItem,
12};
13
14use swamp_script_types::prelude::*;
15
16impl Analyzer<'_> {
17 fn general_import(
18 &mut self,
19 path: &[String],
20 import_items: &swamp_script_ast::ImportItems,
21 node: &swamp_script_ast::Node,
22 ) -> Result<(), Error> {
23 let found_module = self
24 .shared
25 .get_module(path)
26 .ok_or_else(|| self.create_err(ErrorKind::UnknownModule, node))?
27 .clone();
28
29 match import_items {
30 swamp_script_ast::ImportItems::Nothing => {
31 let last_name = path.last().unwrap();
32 self.shared
33 .lookup_table
34 .add_module_link(last_name, found_module.clone())
35 .map_err(|err| self.create_err(ErrorKind::SemanticError(err), node))?;
36 }
37 swamp_script_ast::ImportItems::Items(items) => {
38 for ast_items in items {
39 match ast_items {
40 swamp_script_ast::ImportItem::Identifier(node) => {
41 let ident_resolved_node = self.to_node(&node.0);
42 let ident = UseItem::Identifier(ident_resolved_node.clone());
43 let ident_text =
44 self.get_text_resolved(&ident_resolved_node).to_string();
45 if let Some(found_symbol) =
46 found_module.namespace.symbol_table.get_symbol(&ident_text)
47 {
48 self.shared
49 .lookup_table
50 .add_symbol(&ident_text, found_symbol.clone())
51 .map_err(|err| {
52 self.create_err(ErrorKind::SemanticError(err), &node.0)
53 })?;
54 } else {
55 return Err(self.create_err_resolved(
56 ErrorKind::UnknownTypeReference,
57 &ident_resolved_node,
58 ));
59 }
60 ident
61 }
62 swamp_script_ast::ImportItem::Type(node) => {
63 let ident_resolved_node = self.to_node(&node.0);
64 let ident_text =
65 self.get_text_resolved(&ident_resolved_node).to_string();
66 if let Some(found_symbol) =
67 found_module.namespace.symbol_table.get_symbol(&ident_text)
68 {
69 self.shared
70 .lookup_table
71 .add_symbol(&ident_text, found_symbol.clone())
72 .map_err(|err| {
73 self.create_err(ErrorKind::SemanticError(err), &node.0)
74 })?;
75 } else {
76 return Err(self.create_err_resolved(
77 ErrorKind::UnknownTypeReference,
78 &ident_resolved_node,
79 ));
80 }
81 UseItem::TypeIdentifier(self.to_node(&node.0))
82 }
83 };
84 }
85 }
86 swamp_script_ast::ImportItems::All => {
87 self.shared
88 .lookup_table
89 .extend_from(&found_module.namespace.symbol_table)?;
90 }
91 }
92
93 Ok(())
94 }
95
96 fn analyze_mod_definition(
97 &mut self,
98 mod_definition: &swamp_script_ast::Mod,
99 ) -> Result<(), Error> {
100 let mut path = Vec::new();
101 for ast_node in &mod_definition.module_path.0 {
102 path.push(self.get_text(ast_node).to_string());
103 }
104
105 let mut nodes_copy = path.clone();
106 nodes_copy.insert(0, "crate".to_string());
107
108 self.general_import(
109 &nodes_copy,
110 &mod_definition.items,
111 &mod_definition.module_path.0[0],
112 )
113 }
114
115 fn analyze_use_definition(
116 &mut self,
117 use_definition: &swamp_script_ast::Use,
118 ) -> Result<(), Error> {
119 let mut nodes = Vec::new();
120 for ast_node in &use_definition.module_path.0 {
121 nodes.push(self.to_node(ast_node));
122 }
123
124 let path: Vec<String> = nodes
125 .iter()
126 .map(|node| {
127 let text = self.get_text_resolved(node);
128 text.to_string()
129 })
130 .collect();
131
132 self.general_import(
133 &path,
134 &use_definition.items,
135 &use_definition.module_path.0[0],
136 )
137 }
138
139 fn analyze_enum_type_definition(
140 &mut self,
141 enum_type_name: &swamp_script_ast::LocalTypeIdentifier,
142 ast_variants: &[swamp_script_ast::EnumVariantType],
143 ) -> Result<EnumTypeRef, Error> {
144 let mut resolved_variants = SeqMap::new();
145
146 let parent_number = self.shared.state.allocate_number();
147
148 let enum_parent = EnumType {
149 name: self.to_node(&enum_type_name.0),
150 assigned_name: self.get_text(&enum_type_name.0).to_string(),
151 module_path: vec![],
152 type_id: parent_number,
153 variants: SeqMap::default(),
154 };
155
156 let parent_ref = self
157 .shared
158 .definition_table
159 .add_enum_type(enum_parent)
160 .map_err(|err| self.create_err(ErrorKind::SemanticError(err), &enum_type_name.0))?;
161 self.shared
162 .lookup_table
163 .add_enum_type_link(parent_ref.clone())
164 .map_err(|err| self.create_err(ErrorKind::SemanticError(err), &enum_type_name.0))?;
165
166 for (container_index_usize, ast_variant_type) in ast_variants.iter().enumerate() {
167 let variant_name_node = match ast_variant_type {
168 swamp_script_ast::EnumVariantType::Simple(name) => name,
169 swamp_script_ast::EnumVariantType::Tuple(name, _) => name,
170 swamp_script_ast::EnumVariantType::Struct(name, _) => name,
171 };
172
173 let number = self.shared.state.allocate_number();
174
175 let common = EnumVariantCommon {
176 name: self.to_node(variant_name_node),
177 number,
178 assigned_name: self.get_text(variant_name_node).to_string(),
179 container_index: container_index_usize as u8,
180 owner: parent_ref.clone(),
181 };
182
183 let variant_type = match ast_variant_type {
184 swamp_script_ast::EnumVariantType::Simple(_variant_name_node) => {
185 let simple_ref = EnumVariantSimpleType { common };
186 EnumVariantType::Nothing(EnumVariantSimpleTypeRef::from(simple_ref))
187 }
188 swamp_script_ast::EnumVariantType::Tuple(_variant_name_node, types) => {
189 let mut vec = Vec::new();
190 for tuple_type in types {
191 let resolved_type = self.analyze_type(tuple_type)?;
192 vec.push(resolved_type);
193 }
194
195 let resolved_tuple_type = EnumVariantTupleType {
196 common,
197 fields_in_order: vec,
198 };
199 let resolved_tuple_type_ref = Rc::new(resolved_tuple_type);
200
201 EnumVariantType::Tuple(resolved_tuple_type_ref)
202 }
203 swamp_script_ast::EnumVariantType::Struct(
204 _variant_name_node,
205 ast_struct_fields,
206 ) => {
207 let mut fields = SeqMap::new();
208
209 for (_index, field_with_type) in ast_struct_fields.fields.iter().enumerate() {
210 let resolved_type = self.analyze_type(&field_with_type.field_type)?;
212 let field_name_str =
213 self.get_text(&field_with_type.field_name.0).to_string();
214
215 let resolved_field = StructTypeField {
216 identifier: Some(self.to_node(&field_with_type.field_name.0)),
217 field_type: resolved_type,
218 };
219
220 fields.insert(field_name_str, resolved_field).map_err(|_| {
221 self.create_err(
222 ErrorKind::DuplicateFieldName,
223 &field_with_type.field_name.0,
224 )
225 })?;
226 }
227
228 let enum_variant_struct_type = EnumVariantStructType {
229 common,
230 anon_struct: AnonymousStructType::new(fields),
231 };
232
233 let enum_variant_struct_type_ref = Rc::new(enum_variant_struct_type);
234
235 EnumVariantType::Struct(enum_variant_struct_type_ref)
236 }
237 };
238
239 let variant_name_str = self.get_text(variant_name_node).to_string();
240
241 resolved_variants
242 .insert(variant_name_str, variant_type.into())
243 .map_err(|_| self.create_err(ErrorKind::DuplicateFieldName, variant_name_node))?;
244 }
245
246 parent_ref.borrow_mut().variants = resolved_variants;
247
248 Ok(parent_ref)
249 }
250
251 pub fn analyze_alias_type_definition(
254 &mut self,
255 ast_alias: &swamp_script_ast::AliasType,
256 ) -> Result<AliasTypeRef, Error> {
257 let resolved_type = self.analyze_type(&ast_alias.referenced_type)?;
258
259 let alias_name_str = self.get_text(&ast_alias.identifier.0).to_string();
260 let resolved_alias = AliasType {
261 name: self.to_node(&ast_alias.identifier.0),
262 assigned_name: alias_name_str,
263 referenced_type: resolved_type,
264 };
265
266 let resolved_alias_ref = self
267 .shared
268 .definition_table
269 .add_alias(resolved_alias)
270 .map_err(|err| {
271 self.create_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0)
272 })?;
273 self.shared
274 .lookup_table
275 .add_alias_link(resolved_alias_ref.clone())
276 .map_err(|err| {
277 self.create_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0)
278 })?;
279
280 Ok(resolved_alias_ref)
281 }
282
283 pub fn analyze_anonymous_struct_type(
286 &mut self,
287 ast_struct: &swamp_script_ast::AnonymousStructType,
288 ) -> Result<AnonymousStructType, Error> {
289 let resolved_fields = self.analyze_anonymous_struct_type_fields(&ast_struct.fields)?;
290
291 let resolved_anon_struct = AnonymousStructType::new_and_sort_fields(&resolved_fields);
292
293 Ok(resolved_anon_struct)
294 }
295
296 pub fn analyze_anonymous_struct_type_fields(
299 &mut self,
300 ast_struct_fields: &[swamp_script_ast::StructTypeField],
301 ) -> Result<SeqMap<String, StructTypeField>, Error> {
302 let mut resolved_fields = SeqMap::new();
303
304 for (_index, field_name_and_type) in ast_struct_fields.iter().enumerate() {
305 let resolved_type = self.analyze_type(&field_name_and_type.field_type)?;
306 let name_string = self.get_text(&field_name_and_type.field_name.0).to_string();
307
308 let field_type = StructTypeField {
309 identifier: Some(self.to_node(&field_name_and_type.field_name.0)),
310 field_type: resolved_type,
311 };
312
313 resolved_fields
314 .insert(name_string, field_type)
315 .map_err(|_| {
316 self.create_err(
317 ErrorKind::DuplicateFieldName,
318 &field_name_and_type.field_name.0,
319 )
320 })?;
321 }
322
323 Ok(resolved_fields)
324 }
325
326 pub fn analyze_named_struct_type_definition(
329 &mut self,
330 ast_struct_def: &swamp_script_ast::NamedStructDef,
331 ) -> Result<(), Error> {
332 let struct_name_str = self.get_text(&ast_struct_def.identifier.0).to_string();
333
334 let fields =
335 self.analyze_anonymous_struct_type_fields(&ast_struct_def.struct_type.fields)?;
336
337 let analyzed_anonymous_struct = AnonymousStructType::new(fields); let named_struct_type = NamedStructType {
340 name: self.to_node(&ast_struct_def.identifier.0),
341 anon_struct_type: analyzed_anonymous_struct,
342 assigned_name: struct_name_str,
343 type_id: self.shared.state.allocate_number(),
344 };
345
346 let struct_ref = self
347 .shared
348 .definition_table
349 .add_struct(named_struct_type)
350 .map_err(|err| {
351 self.create_err(ErrorKind::SemanticError(err), &ast_struct_def.identifier.0)
352 })?;
353
354 self.shared
355 .lookup_table
356 .add_struct_link(struct_ref)
357 .map_err(|err| {
358 self.create_err(ErrorKind::SemanticError(err), &ast_struct_def.identifier.0)
359 })?;
360
361 Ok(())
362 }
363
364 pub(crate) fn analyze_function_definition(
365 &mut self,
366 function: &swamp_script_ast::Function,
367 ) -> Result<Function, Error> {
368 let func = match function {
369 swamp_script_ast::Function::Internal(function_data) => {
370 let parameters = self.analyze_parameters(&function_data.declaration.params)?;
371 let return_type = if let Some(found) = &function_data.declaration.return_type {
372 self.analyze_type(found)?
373 } else {
374 Type::Unit
375 };
376
377 self.scope.return_type = return_type.clone();
378
379 for param in ¶meters {
381 self.create_local_variable_resolved(
382 ¶m.node.as_ref().unwrap().name,
383 param.node.as_ref().unwrap().is_mutable.as_ref(),
384 ¶m.resolved_type.clone(),
385 )?;
386 }
387 let function_name = self.get_text(&function_data.declaration.name).to_string();
388 let statements =
389 self.analyze_function_body_expression(&function_data.body, &return_type)?;
390 self.scope.return_type = Type::Unit;
391
392 let internal = InternalFunctionDefinition {
393 signature: Signature {
394 parameters,
395 return_type: Box::new(return_type),
396 },
397 body: statements,
398 name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
399 assigned_name: self.get_text(&function_data.declaration.name).to_string(),
400 };
401
402 let function_ref = self
403 .shared
404 .definition_table
405 .add_internal_function(&function_name, internal)
406 .map_err(|err| {
407 self.create_err(
408 ErrorKind::SemanticError(err),
409 &function_data.declaration.name,
410 )
411 })?;
412
413 self.shared
414 .lookup_table
415 .add_internal_function_link(&function_name, function_ref.clone())
416 .map_err(|err| {
417 self.create_err(
418 ErrorKind::SemanticError(err),
419 &function_data.declaration.name,
420 )
421 })?;
422
423 Function::Internal(function_ref)
424 }
425 swamp_script_ast::Function::External(ast_signature) => {
426 let parameters = self.analyze_parameters(&ast_signature.params)?;
427 let external_return_type = if let Some(found) = &ast_signature.return_type {
428 self.analyze_type(found)?
429 } else {
430 Type::Unit
431 };
432
433 let return_type = external_return_type;
434 let external_function_id = self.shared.state.allocate_external_function_id();
435
436 let external = ExternalFunctionDefinition {
437 assigned_name: self.get_text(&ast_signature.name).to_string(),
438 signature: Signature {
439 parameters,
440 return_type: Box::new(return_type),
441 },
442 name: Some(self.to_node(&ast_signature.name)),
443 id: external_function_id,
444 };
445
446 let function_ref = self
447 .shared
448 .definition_table
449 .add_external_function_declaration(external)
450 .map_err(|err| {
451 self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
452 })?;
453
454 self.shared
455 .lookup_table
456 .add_external_function_declaration_link(function_ref.clone())
457 .map_err(|err| {
458 self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
459 })?;
460
461 Function::External(function_ref)
462 }
463 };
464
465 Ok(func)
466 }
467
468 pub fn analyze_definition(
471 &mut self,
472 ast_def: &swamp_script_ast::Definition,
473 ) -> Result<(), Error> {
474 match ast_def {
475 swamp_script_ast::Definition::NamedStructDef(ast_struct) => {
476 self.analyze_named_struct_type_definition(ast_struct)?
477 }
478 swamp_script_ast::Definition::AliasDef(alias_def) => {
479 self.analyze_alias_type_definition(alias_def)?;
480 }
481 swamp_script_ast::Definition::EnumDef(identifier, variants) => {
482 self.analyze_enum_type_definition(
483 &swamp_script_ast::LocalTypeIdentifier(identifier.clone()),
484 variants,
485 )?;
486 }
487 swamp_script_ast::Definition::FunctionDef(function) => {
488 let resolved_return_type = self.analyze_return_type(function)?;
489 self.start_function(resolved_return_type);
490 self.analyze_function_definition(function)?;
491 self.stop_function();
492 }
493 swamp_script_ast::Definition::ImplDef(type_identifier, functions) => {
494 self.analyze_impl_definition(type_identifier, functions)?;
495 }
496 swamp_script_ast::Definition::Mod(mod_info) => self.analyze_mod_definition(mod_info)?,
497 swamp_script_ast::Definition::Use(use_info) => self.analyze_use_definition(use_info)?,
498 swamp_script_ast::Definition::Constant(const_info) => {
499 self.analyze_constant_definition(const_info)?;
500 }
501 };
502
503 Ok(())
504 }
505
506 fn analyze_impl_definition(
507 &mut self,
508 named_type_node: &swamp_script_ast::Node,
509 functions: &[swamp_script_ast::Function],
510 ) -> Result<(), Error> {
511 let qualified = swamp_script_ast::QualifiedTypeIdentifier {
512 name: swamp_script_ast::LocalTypeIdentifier(named_type_node.clone()),
513 module_path: None,
514 generic_params: vec![],
515 };
516
517 let type_to_attach_to = self.analyze_named_type(&qualified)?;
518 let function_refs: Vec<&swamp_script_ast::Function> = functions.iter().collect();
519 self.analyze_impl_functions(&type_to_attach_to, &function_refs)?;
520
521 Ok(())
522 }
523
524 pub fn analyze_impl_functions(
525 &mut self,
526 type_to_attach_to: &Type,
527 functions: &[&swamp_script_ast::Function],
528 ) -> Result<(), Error> {
529 self.shared
530 .state
531 .associated_impls
532 .prepare(type_to_attach_to);
533
534 for function in functions {
535 let new_return_type = self.analyze_return_type(function)?;
536 self.start_function(new_return_type);
537
538 let function_name = match function {
539 swamp_script_ast::Function::Internal(function_with_body) => {
540 &function_with_body.declaration
541 }
542 swamp_script_ast::Function::External(external_declaration) => external_declaration,
543 };
544
545 let function_name_str = self.get_text(&function_name.name).to_string();
546
547 let resolved_function = self.analyze_impl_func(function, type_to_attach_to)?;
548
549 let resolved_function_ref = Rc::new(resolved_function);
550
551 self.stop_function();
552
553 self.shared
554 .state
555 .associated_impls
556 .add_member_function(type_to_attach_to, &function_name_str, resolved_function_ref)
557 .map_err(|err| {
558 self.create_err(ErrorKind::SemanticError(err), &function_name.name)
559 })?;
560 }
561
562 Ok(())
563 }
564
565 fn analyze_impl_func(
566 &mut self,
567 function: &swamp_script_ast::Function,
568 self_type: &Type,
569 ) -> Result<Function, Error> {
570 let resolved_fn = match function {
571 swamp_script_ast::Function::Internal(function_data) => {
572 let mut parameters = Vec::new();
573
574 if let Some(found_self) = &function_data.declaration.self_parameter {
575 parameters.push(TypeForParameter {
576 name: self.get_text(&found_self.self_node).to_string(),
577 resolved_type: self_type.clone(),
578 is_mutable: found_self.is_mutable.is_some(),
579 node: Option::from(ParameterNode {
580 name: self.to_node(&found_self.self_node),
581 is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
582 }),
583 });
584 }
585
586 for param in &function_data.declaration.params {
587 let resolved_type = self.analyze_type(¶m.param_type)?;
588
589 parameters.push(TypeForParameter {
590 name: self.get_text(¶m.variable.name).to_string(),
591 resolved_type,
592 is_mutable: param.variable.is_mutable.is_some(),
593 node: Option::from(ParameterNode {
594 name: self.to_node(¶m.variable.name),
595 is_mutable: self
596 .to_node_option(Option::from(¶m.variable.is_mutable)),
597 }),
598 });
599 }
600
601 let return_type =
602 self.analyze_maybe_type(Option::from(&function_data.declaration.return_type))?;
603
604 for param in ¶meters {
605 self.create_local_variable_resolved(
606 ¶m.node.as_ref().unwrap().name,
607 param.node.as_ref().unwrap().is_mutable.as_ref(),
608 ¶m.resolved_type.clone(),
609 )?;
610 }
611
612 let statements =
613 self.analyze_function_body_expression(&function_data.body, &return_type)?;
614
615 let internal = InternalFunctionDefinition {
616 signature: Signature {
617 parameters,
618 return_type: Box::new(return_type),
619 },
620 body: statements,
621 name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
622 assigned_name: self.get_text(&function_data.declaration.name).to_string(),
623 };
624
625 let internal_ref = Rc::new(internal);
626
627 Function::Internal(internal_ref)
628 }
629
630 swamp_script_ast::Function::External(signature) => {
631 let mut parameters = Vec::new();
632
633 if let Some(found_self) = &signature.self_parameter {
634 parameters.push(TypeForParameter {
635 name: self.get_text(&found_self.self_node).to_string(),
636 resolved_type: self_type.clone(),
637 is_mutable: found_self.is_mutable.is_some(),
638 node: Option::from(ParameterNode {
639 name: self.to_node(&found_self.self_node),
640 is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
641 }),
642 });
643 }
644
645 for param in &signature.params {
647 let resolved_type = self.analyze_type(¶m.param_type)?;
648
649 parameters.push(TypeForParameter {
650 name: self.get_text(¶m.variable.name).to_string(),
651 resolved_type,
652 is_mutable: param.variable.is_mutable.is_some(),
653 node: Option::from(ParameterNode {
654 name: self.to_node(¶m.variable.name),
655 is_mutable: self
656 .to_node_option(Option::from(¶m.variable.is_mutable)),
657 }),
658 });
659 }
660
661 let return_type = self.analyze_maybe_type(Option::from(&signature.return_type))?;
662
663 let external = ExternalFunctionDefinition {
664 assigned_name: self.get_text(&signature.name).to_string(),
665 name: Some(self.to_node(&signature.name)),
666 signature: Signature {
667 parameters,
668 return_type: Box::new(return_type),
669 },
670 id: 0,
671 };
672
673 let external_ref = Rc::new(external);
674
675 Function::External(external_ref)
676 }
677 };
678 Ok(resolved_fn)
679 }
680}