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