claw_resolver/
lib.rs

1#![allow(clippy::single_match)]
2
3mod expression;
4mod function;
5mod imports;
6mod statement;
7pub mod types;
8pub mod wit;
9
10use ast::{FunctionId, GlobalId};
11use claw_ast as ast;
12use claw_common::Source;
13
14use std::collections::HashMap;
15use wit::{ResolvedWit, WitError};
16
17use miette::{Diagnostic, SourceSpan};
18use thiserror::Error;
19
20pub use function::*;
21pub use imports::*;
22pub use types::*;
23
24pub struct ResolvedComponent {
25    pub src: Source,
26    pub component: ast::Component,
27    pub wit: ResolvedWit,
28    pub global_vals: HashMap<GlobalId, ast::Literal>,
29    pub imports: ImportResolver,
30    pub funcs: HashMap<FunctionId, ResolvedFunction>,
31}
32
33#[derive(Clone, Copy, Debug)]
34pub enum ItemId {
35    ImportFunc(ImportFuncId),
36    Type(ResolvedType),
37    Global(GlobalId),
38    Param(ParamId),
39    Local(LocalId),
40    Function(FunctionId),
41}
42
43#[derive(Error, Debug, Diagnostic)]
44pub enum ResolverError {
45    #[error("Failed to resolve")]
46    Base {
47        #[source_code]
48        src: Source,
49        #[label("This bit")]
50        span: SourceSpan,
51    },
52    #[error("Conflicting types inferred for expression {type_a} != {type_b}")]
53    TypeConflict {
54        #[source_code]
55        src: Source,
56        #[label("This bit")]
57        span: SourceSpan,
58
59        type_a: ResolvedType,
60        type_b: ResolvedType,
61    },
62    #[error("Failed to resolve name \"{ident}\"")]
63    NameError {
64        #[source_code]
65        src: Source,
66        #[label("Name referenced here")]
67        span: SourceSpan,
68        ident: String,
69    },
70    #[error("Function call with wrong number of arguments \"{ident}\"")]
71    CallArgumentsMismatch {
72        #[source_code]
73        src: Source,
74        #[label("Here")]
75        span: SourceSpan,
76        ident: String,
77    },
78    #[error("{0} is not yet supported")]
79    NotYetSupported(String),
80
81    #[error(transparent)]
82    #[diagnostic(transparent)]
83    Wit(#[from] WitError),
84}
85
86pub fn resolve(
87    src: Source,
88    comp: ast::Component,
89    wit: wit::ResolvedWit,
90) -> Result<ResolvedComponent, ResolverError> {
91    let mut mappings: HashMap<String, ItemId> = Default::default();
92
93    let mut imports = ImportResolver::default();
94    imports.resolve_imports(&comp, &wit)?;
95    for (name, import) in imports.mapping.iter() {
96        match import {
97            ImportItemId::Type(rtype) => {
98                mappings.insert(name.to_owned(), ItemId::Type(*rtype));
99            }
100            ImportItemId::Func(func) => {
101                mappings.insert(name.to_owned(), ItemId::ImportFunc(*func));
102            }
103        }
104    }
105
106    for (id, global) in comp.globals.iter() {
107        let name = comp.get_name(global.ident);
108        mappings.insert(name.to_owned(), ItemId::Global(id));
109    }
110    for (id, function) in comp.functions.iter() {
111        let name = comp.get_name(function.ident);
112        mappings.insert(name.to_owned(), ItemId::Function(id));
113    }
114
115    let mut global_vals: HashMap<GlobalId, ast::Literal> = HashMap::new();
116
117    for (id, global) in comp.globals.iter() {
118        let global_val = match comp.expr().get_exp(global.init_value) {
119            ast::Expression::Literal(literal) => literal.clone(),
120            _ => panic!("Only literal expressions allowed in global initializer"),
121        };
122        global_vals.insert(id, global_val);
123    }
124
125    let mut funcs: HashMap<FunctionId, ResolvedFunction> = HashMap::new();
126
127    for (id, function) in comp.functions.iter() {
128        let resolver = FunctionResolver::new(src.clone(), &comp, &imports, function, &mappings);
129        funcs.insert(id, resolver.resolve()?);
130    }
131
132    Ok(ResolvedComponent {
133        src,
134        component: comp,
135        wit,
136        global_vals,
137        imports,
138        funcs,
139    })
140}