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