galvan_resolver/
lookup.rs1use galvan_ast::{FnDecl, Ident, MainDecl, SegmentedAsts, ToplevelItem, TypeDecl, TypeIdent};
2use std::collections::HashMap;
3use thiserror::Error;
4
5#[derive(Debug, Default)]
6pub struct LookupContext<'a> {
7 pub types: HashMap<TypeIdent, &'a ToplevelItem<TypeDecl>>,
9 pub functions: HashMap<FunctionId, &'a ToplevelItem<FnDecl>>,
15 pub main: Option<&'a ToplevelItem<MainDecl>>,
18}
19
20pub trait Lookup {
21 fn resolve_type(&self, name: &TypeIdent) -> Option<&ToplevelItem<TypeDecl>>;
22
23 fn resolve_function(
24 &self,
25 receiver: Option<&TypeIdent>,
26 name: &Ident,
27 labels: &[&str],
28 ) -> Option<&ToplevelItem<FnDecl>>;
29}
30
31#[derive(Debug, Error)]
33pub enum LookupError {
34 #[error("Type not found")]
35 TypeNotFound,
36 #[error("Function not found")]
37 FunctionNotFound,
38 #[error("Duplicate type")]
39 DuplicateType(TypeIdent),
40 #[error("Duplicate function")]
41 DuplicateFunction,
42}
43
44impl<'a> LookupContext<'a> {
45 pub fn new() -> Self {
46 Self::default()
47 }
48 pub fn add_from(&mut self, asts: &'a SegmentedAsts) -> Result<(), LookupError> {
49 for func in &asts.functions {
50 let func_id = FunctionId::new(None, &func.signature.identifier, &[]);
51 if self.functions.insert(func_id, func).is_some() {
52 return Err(LookupError::DuplicateFunction);
53 }
54 }
55
56 for type_decl in &asts.types {
57 if self
58 .types
59 .insert(type_decl.ident().clone(), type_decl)
60 .is_some()
61 {
62 return Err(LookupError::DuplicateType(type_decl.ident().clone()));
63 }
64 }
65
66 Ok(())
67 }
68
69 pub fn with(mut self, asts: &'a SegmentedAsts) -> Result<Self, LookupError> {
70 self.add_from(asts)?;
71 Ok(self)
72 }
73}
74
75impl Lookup for LookupContext<'_> {
76 fn resolve_type(&self, name: &TypeIdent) -> Option<&ToplevelItem<TypeDecl>> {
77 self.types.get(&name).copied()
78 }
79
80 fn resolve_function(
81 &self,
82 receiver: Option<&TypeIdent>,
83 name: &Ident,
84 labels: &[&str],
85 ) -> Option<&ToplevelItem<FnDecl>> {
86 let func_id = FunctionId::new(receiver, name, labels);
87 self.functions.get(&func_id).copied()
88 }
89}
90
91#[derive(Debug, Hash, PartialEq, Eq)]
92pub struct FunctionId(Box<str>);
93
94impl FunctionId {
95 fn new(receiver: Option<&TypeIdent>, fn_ident: &Ident, labels: &[&str]) -> Self {
96 let mut id = String::new();
97 if let Some(receiver) = receiver {
98 id.push_str(receiver.as_str());
99 id.push_str("::");
100 }
101 id.push_str(fn_ident.as_str());
102 if !labels.is_empty() {
103 id.push(':');
104 id.push_str(&labels.join(":"));
105 }
106
107 Self(id.into())
108 }
109}