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