swamp_modules/
symtbl.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::modules::ModuleRef;
6use seq_map::SeqMap;
7use source_map_node::Node;
8use std::fmt::Debug;
9use std::rc::Rc;
10use swamp_semantic::prelude::*;
11use swamp_types::TypeRef;
12use swamp_types::prelude::*;
13use tiny_ver::TinyVersion;
14
15#[derive(Debug, Clone)]
16pub enum FuncDef {
17    Internal(InternalFunctionDefinitionRef),
18    Intrinsic(IntrinsicFunctionDefinitionRef),
19    External(ExternalFunctionDefinitionRef),
20}
21
22impl FuncDef {
23    #[must_use]
24    pub fn signature(&self) -> &Signature {
25        match self {
26            Self::Internal(internal) => &internal.signature,
27            Self::Intrinsic(intrinsic_fn) => &intrinsic_fn.signature,
28            Self::External(host_fn) => &host_fn.signature,
29        }
30    }
31}
32
33#[derive(Clone, Eq, PartialEq, Debug)]
34pub struct TypeParameterName {
35    pub resolved_node: Node,
36    pub assigned_name: String,
37}
38
39#[derive(Debug)]
40pub struct TypeParameter {
41    pub ty: TypeRef,
42    pub debug_name: String,
43}
44
45#[derive(Clone, Debug)]
46pub struct AliasType {
47    pub name: Option<Node>,
48    pub assigned_name: String,
49    pub ty: TypeRef,
50}
51
52#[derive(Clone, Debug)]
53pub enum Symbol {
54    Type(TypeRef),
55    Module(ModuleRef),
56    PackageVersion(TinyVersion),
57    Constant(ConstantRef),
58    FunctionDefinition(FuncDef),
59    Alias(AliasType),
60}
61
62impl Symbol {}
63
64impl Symbol {
65    #[must_use]
66    pub const fn is_basic_type(&self) -> bool {
67        matches!(
68            self,
69            Self::Type(..) | Self::Alias(..) | Self::FunctionDefinition(..)
70        )
71    }
72
73    #[must_use]
74    pub const fn is_alias_type(&self) -> bool {
75        matches!(self, Self::Alias(..))
76    }
77
78    pub(crate) const fn is_function(&self) -> bool {
79        matches!(self, Self::FunctionDefinition(..))
80    }
81}
82
83#[derive(Debug, Clone)]
84pub struct SymbolTable {
85    symbols: SeqMap<String, Symbol>,
86    module_path: Vec<String>,
87}
88
89impl SymbolTable {}
90
91impl SymbolTable {
92    #[must_use]
93    pub fn internal_functions(&self) -> Vec<InternalFunctionDefinitionRef> {
94        let mut v = Vec::new();
95
96        for (_name, sym) in &self.symbols {
97            if let Symbol::FunctionDefinition(func_def) = sym {
98                if let FuncDef::Internal(internal) = func_def {
99                    v.push(internal.clone());
100                }
101            }
102        }
103
104        v
105    }
106}
107
108impl SymbolTable {
109    #[must_use]
110    pub fn module_path(&self) -> Vec<String> {
111        self.module_path.clone()
112    }
113}
114
115pub type SymbolTableRef = Rc<SymbolTable>;
116
117impl SymbolTable {
118    #[must_use]
119    pub fn new(module_path: &[String]) -> Self {
120        Self {
121            symbols: SeqMap::default(),
122            module_path: module_path.to_vec(),
123        }
124    }
125
126    #[must_use]
127    pub fn is_empty(&self) -> bool {
128        self.symbols.is_empty()
129    }
130
131    #[must_use]
132    pub const fn symbols(&self) -> &SeqMap<String, Symbol> {
133        &self.symbols
134    }
135
136    #[must_use]
137    pub fn structs(&self) -> SeqMap<String, NamedStructType> {
138        let mut structs = SeqMap::new();
139
140        for (name, symbol) in &self.symbols {
141            if let Symbol::Type(ty) = symbol {
142                if let TypeKind::NamedStruct(struct_ref) = &*ty.kind {
143                    structs
144                        .insert(name.to_string(), struct_ref.clone())
145                        .unwrap();
146                }
147            }
148        }
149
150        structs
151    }
152
153    #[must_use]
154    pub fn enums(&self) -> SeqMap<String, EnumType> {
155        let mut enums = SeqMap::new();
156
157        for (name, symbol) in &self.symbols {
158            if let Symbol::Type(ty) = symbol {
159                if let TypeKind::Enum(enum_type) = &*ty.kind {
160                    enums.insert(name.to_string(), enum_type.clone()).unwrap();
161                }
162            }
163        }
164
165        enums
166    }
167
168    /// # Errors
169    ///
170    pub fn extend_from(&mut self, symbol_table: &Self) -> Result<(), SemanticError> {
171        for (name, symbol) in symbol_table.symbols() {
172            self.add_symbol(name, symbol.clone())?;
173        }
174        Ok(())
175    }
176
177    /// # Errors
178    ///
179    pub fn extend_basic_from(&mut self, symbol_table: &Self) -> Result<(), SemanticError> {
180        for (name, symbol) in symbol_table.symbols() {
181            if symbol.is_basic_type() {
182                self.add_symbol(name, symbol.clone())?;
183            }
184        }
185        Ok(())
186    }
187
188    /// # Errors
189    ///
190    pub fn extend_alias_from(&mut self, symbol_table: &Self) -> Result<(), SemanticError> {
191        for (name, symbol) in symbol_table.symbols() {
192            if symbol.is_alias_type() || symbol.is_function() {
193                self.add_symbol(name, symbol.clone())?;
194            }
195        }
196        Ok(())
197    }
198
199    pub fn extend_intrinsic_functions_from(
200        &mut self,
201        symbol_table: &Self,
202    ) -> Result<(), SemanticError> {
203        for (name, symbol) in symbol_table.symbols() {
204            if let Symbol::FunctionDefinition(func_def) = symbol {
205                if let FuncDef::Intrinsic(_intrinsic_def) = func_def {
206                    self.add_symbol(name, symbol.clone())?;
207                }
208            }
209        }
210        Ok(())
211    }
212
213    #[must_use]
214    pub fn get_package_version(&self, name: &str) -> Option<String> {
215        match self.get_symbol(name)? {
216            Symbol::PackageVersion(name) => Some(name.to_string()),
217            _ => None,
218        }
219    }
220
221    /// # Errors
222    ///
223    pub fn add_constant(&mut self, constant: Constant) -> Result<ConstantRef, SemanticError> {
224        let constant_ref = Rc::new(constant);
225
226        self.add_constant_link(constant_ref.clone())?;
227
228        Ok(constant_ref)
229    }
230
231    /// # Errors
232    ///
233    pub fn add_constant_link(&mut self, constant_ref: ConstantRef) -> Result<(), SemanticError> {
234        let name = constant_ref.assigned_name.clone();
235
236        self.symbols
237            .insert(name.to_string(), Symbol::Constant(constant_ref))
238            .map_err(|_| SemanticError::DuplicateConstName(name.to_string()))?;
239
240        Ok(())
241    }
242
243    /// # Errors
244    ///
245    pub fn add_alias(&mut self, alias_type: AliasType) -> Result<AliasType, SemanticError> {
246        self.add_alias_link(alias_type.clone())?;
247        Ok(alias_type)
248    }
249
250    /// # Errors
251    ///
252    pub fn add_alias_link(&mut self, alias_type_ref: AliasType) -> Result<(), SemanticError> {
253        let name = alias_type_ref.assigned_name.clone();
254        self.symbols
255            .insert(name.clone(), Symbol::Alias(alias_type_ref))
256            .map_err(|_| SemanticError::DuplicateStructName(name))?;
257
258        Ok(())
259    }
260
261    pub fn add_internal_function(
262        &mut self,
263        name: &str,
264        function: InternalFunctionDefinition,
265    ) -> Result<InternalFunctionDefinitionRef, SemanticError> {
266        if self.symbols.contains_key(&name.to_string()) {
267            return Err(SemanticError::DuplicateDefinition(name.to_string()));
268        }
269        let function_ref = Rc::new(function);
270        self.symbols
271            .insert(
272                name.to_string(),
273                Symbol::FunctionDefinition(FuncDef::Internal(function_ref.clone())),
274            )
275            .expect("todo: add seqmap error handling");
276        Ok(function_ref)
277    }
278
279    pub fn add_internal_function_link(
280        &mut self,
281        name: &str,
282        function_ref: InternalFunctionDefinitionRef,
283    ) -> Result<(), SemanticError> {
284        self.symbols
285            .insert(
286                name.to_string(),
287                Symbol::FunctionDefinition(FuncDef::Internal(function_ref)),
288            )
289            .expect("todo: add seqmap error handling");
290        Ok(())
291    }
292
293    #[must_use]
294    pub fn get_symbol(&self, name: &str) -> Option<&Symbol> {
295        self.symbols.get(&name.to_string())
296    }
297
298    pub fn add_symbol(&mut self, name: &str, symbol: Symbol) -> Result<(), SemanticError> {
299        self.symbols
300            .insert(name.to_string(), symbol)
301            .map_err(|_| SemanticError::DuplicateSymbolName(name.to_string()))
302    }
303
304    #[must_use]
305    pub fn get_type(&self, name: &str) -> Option<&TypeRef> {
306        if let Some(Symbol::Type(type_ref)) = self.get_symbol(name) {
307            Some(type_ref)
308        } else {
309            None
310        }
311    }
312
313    #[must_use]
314    pub fn get_struct(&self, name: &str) -> Option<&TypeRef> {
315        self.get_type(name)
316    }
317
318    #[must_use]
319    pub fn get_enum(&self, name: &str) -> Option<&TypeRef> {
320        self.get_type(name)
321    }
322
323    #[must_use]
324    pub fn get_enum_variant_type(
325        &self,
326        enum_type_name: &str,
327        variant_name: &str,
328    ) -> Option<EnumVariantType> {
329        self.get_enum(enum_type_name).as_ref().map_or_else(
330            || None,
331            |found_type| {
332                if let TypeKind::Enum(found_enum) = &*found_type.kind {
333                    found_enum.variants.get(&variant_name.to_string()).cloned()
334                } else {
335                    panic!("internal error: expected enum type")
336                }
337            },
338        )
339    }
340
341    #[must_use]
342    pub fn get_constant(&self, name: &str) -> Option<&ConstantRef> {
343        match self.get_symbol(name)? {
344            Symbol::Constant(constant) => Some(constant),
345            _ => None,
346        }
347    }
348
349    // Functions
350
351    #[must_use]
352    pub fn get_function(&self, name: &str) -> Option<&FuncDef> {
353        match self.get_symbol(name)? {
354            Symbol::FunctionDefinition(func_def) => Some(func_def),
355            _ => None,
356        }
357    }
358
359    #[must_use]
360    pub fn get_internal_function(&self, name: &str) -> Option<&InternalFunctionDefinitionRef> {
361        match self.get_function(name)? {
362            FuncDef::Internal(internal_fn) => Some(internal_fn),
363            FuncDef::External(_) => None,
364            FuncDef::Intrinsic(_) => None,
365        }
366    }
367
368    #[must_use]
369    pub fn get_intrinsic_function(&self, name: &str) -> Option<&IntrinsicFunctionDefinitionRef> {
370        match self.get_function(name)? {
371            FuncDef::Intrinsic(intrinsic_fn) => Some(intrinsic_fn),
372            _ => None,
373        }
374    }
375
376    #[must_use]
377    pub fn get_external_function_declaration(
378        &self,
379        name: &str,
380    ) -> Option<&ExternalFunctionDefinitionRef> {
381        match self.get_function(name)? {
382            FuncDef::External(external_def) => Some(external_def),
383            _ => None,
384        }
385    }
386
387    fn insert_symbol(&mut self, name: &str, symbol: Symbol) -> Result<(), SemanticError> {
388        self.symbols
389            .insert(name.to_string(), symbol)
390            .map_err(|_| SemanticError::DuplicateSymbolName(name.to_string()))
391    }
392
393    pub fn add_named_type(&mut self, ty: TypeRef) -> Result<(), SemanticError> {
394        let name = match &*ty.kind {
395            TypeKind::NamedStruct(named) => named.assigned_name.clone(),
396            TypeKind::Enum(enum_type) => enum_type.assigned_name.clone(),
397            _ => panic!("not a named type"),
398        };
399        self.insert_symbol(&name, Symbol::Type(ty))
400    }
401
402    pub fn add_external_function_declaration(
403        &mut self,
404        decl: ExternalFunctionDefinition,
405    ) -> Result<ExternalFunctionDefinitionRef, SemanticError> {
406        let decl_ref = Rc::new(decl);
407
408        self.add_external_function_declaration_link(decl_ref.clone())?;
409
410        Ok(decl_ref)
411    }
412
413    pub fn add_external_function_declaration_link(
414        &mut self,
415        decl_ref: ExternalFunctionDefinitionRef,
416    ) -> Result<(), SemanticError> {
417        self.insert_symbol(
418            &decl_ref.assigned_name,
419            Symbol::FunctionDefinition(FuncDef::External(decl_ref.clone())),
420        )
421        .map_err(|_| {
422            SemanticError::DuplicateExternalFunction(decl_ref.assigned_name.to_string())
423        })?;
424        Ok(())
425    }
426
427    pub fn add_module_link(&mut self, name: &str, ns: ModuleRef) -> Result<(), SemanticError> {
428        self.insert_symbol(name, Symbol::Module(ns))
429            .map_err(|_| SemanticError::DuplicateNamespaceLink(name.to_string()))?;
430        Ok(())
431    }
432
433    #[must_use]
434    pub fn get_module_link(&self, name: &str) -> Option<&ModuleRef> {
435        match self.get_symbol(name)? {
436            Symbol::Module(module_ref) => Some(module_ref),
437            _ => None,
438        }
439    }
440
441    pub fn add_package_version(
442        &mut self,
443        name: &str,
444        version: TinyVersion,
445    ) -> Result<(), SemanticError> {
446        self.insert_symbol(name, Symbol::PackageVersion(version))
447            .map_err(|_| SemanticError::DuplicateNamespaceLink(name.to_string()))?;
448        Ok(())
449    }
450
451    pub fn add_intrinsic_function(
452        &mut self,
453        function: IntrinsicFunctionDefinition,
454    ) -> Result<IntrinsicFunctionDefinitionRef, SemanticError> {
455        let function_ref = Rc::new(function);
456        self.symbols
457            .insert(
458                function_ref.name.clone(),
459                Symbol::FunctionDefinition(FuncDef::Intrinsic(function_ref.clone())),
460            )
461            .expect("todo: add seqmap error handling");
462
463        Ok(function_ref)
464    }
465}