1
use merc_collections::IndexedSet;
2
use merc_syntax::DefId;
3
use merc_syntax::SortExpression;
4
use merc_syntax::UntypedDataSpecification;
5
use merc_syntax::apply_sort_expression;
6

            
7
use crate::WellTypedError;
8

            
9
/// Ensure that all DefIds in the data specification are resolved. Returns an
10
/// indexed set that indicates the mapping from sort identifiers to their
11
/// DefIds.
12
3
pub fn resolve_names(spec: &mut UntypedDataSpecification) -> Result<IndexedSet<String>, WellTypedError> {
13
    // Every sort declaration should have a unique name.
14
3
    let mut sorts = IndexedSet::new();
15

            
16
    // Assign unique IDs to all sort declarations
17
5
    for (i, sort) in spec.sort_declarations.iter_mut().enumerate() {
18
5
        sort.id = Some(DefId::new(i));
19

            
20
5
        if !sorts.insert(sort.identifier.clone()).1 {
21
            return Err(WellTypedError::DuplicateSortDeclaration {
22
                sort: sort.identifier.clone(),
23
            });
24
5
        }
25
    }
26

            
27
    // Resolve all sorts.
28
5
    map_sorts_in_spec(spec, |sort| resolve_sort_id(sort, &sorts))?;
29

            
30
3
    Ok(sorts)
31
3
}
32

            
33
// Apply a mapping function to every sort in the specification.
34
6
pub fn map_sorts_in_spec<E, F>(spec: &mut UntypedDataSpecification, mut f: F) -> Result<(), E>
35
6
where
36
6
    F: FnMut(&SortExpression) -> Result<SortExpression, E>,
37
{
38
10
    for sort in &mut spec.sort_declarations {
39
10
        if let Some(expr) = &sort.expr {
40
            // Only apply to type aliases.
41
6
            sort.expr = Some(f(expr)?);
42
4
        }
43
    }
44

            
45
6
    for constructor in &mut spec.constructor_declarations {
46
4
        constructor.sort = f(&constructor.sort)?;
47
    }
48

            
49
6
    for map in &mut spec.map_declarations {
50
        map.sort = f(&map.sort)?;
51
    }
52

            
53
6
    for equation in &mut spec.equation_declarations {
54
        for var in &mut equation.variables {
55
            var.sort = f(&var.sort)?;
56
        }
57
    }
58

            
59
6
    Ok(())
60
6
}
61

            
62
/// Replaces sort references of `identifier` in `sort` by the given `result_sort`.
63
5
fn resolve_sort_id(sort: &SortExpression, resolved: &IndexedSet<String>) -> Result<SortExpression, WellTypedError> {
64
9
    apply_sort_expression(sort.clone(), |expr| {
65
9
        if let SortExpression::Reference(name) = expr {
66
6
            if let Some(id) = resolved.index(name) {
67
6
                return Ok(Some(SortExpression::Resolved(name.clone(), DefId::new(*id))));
68
            }
69

            
70
            return Err(WellTypedError::UndefinedSort { sort: name.clone() });
71
3
        }
72

            
73
3
        Ok(None)
74
9
    })
75
5
}