1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use super::{namespace::*, scope::*, type_ref::*, *};
use crate::ast;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Entity {
pub name: String,
pub attributes: Vec<EntityAttribute>,
pub constraints: Vec<TypeRef>,
pub supertypes: Vec<TypeRef>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EntityAttribute {
pub name: String,
pub ty: TypeRef,
pub optional: bool,
}
impl Legalize for EntityAttribute {
type Input = ast::EntityAttribute;
fn legalize(
ns: &Namespace,
ss: &Constraints,
scope: &Scope,
attr: &Self::Input,
) -> Result<Self, SemanticError> {
let ty = TypeRef::legalize(ns, ss, scope, &attr.ty)?;
let name = match &attr.name {
ast::AttributeDecl::Reference(name) => name.clone(),
_ => unimplemented!(),
};
Ok(EntityAttribute {
name,
ty,
optional: attr.optional,
})
}
}
impl Legalize for Entity {
type Input = ast::Entity;
fn legalize(
ns: &Namespace,
ss: &Constraints,
scope: &Scope,
entity: &ast::Entity,
) -> Result<Self, SemanticError> {
let name = entity.name.clone();
let attributes = entity
.attributes
.iter()
.map(|attr| EntityAttribute::legalize(ns, ss, scope, attr))
.collect::<Result<Vec<_>, _>>()?;
let supertypes = if let Some(supertypes) = &entity.subtype_of {
supertypes
.entity_references
.iter()
.map(|sup| TypeRef::from_path(ns, ss, &ns.resolve(scope, sup)?.0))
.collect::<Result<Vec<TypeRef>, _>>()?
} else {
Vec::new()
};
let path = Path::entity(scope, &entity.name);
let constraints = if let Some(instantiables) = ss.instantiables.get(&path) {
instantiables
.iter()
.filter_map(|pce| match pce.len() {
1 => Some(TypeRef::from_path(ns, ss, &pce[0])),
_ => None,
})
.collect::<Result<Vec<TypeRef>, SemanticError>>()?
} else {
Vec::new()
};
Ok(Entity {
name,
attributes,
constraints,
supertypes,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn legalize() {
let example = SyntaxTree::example();
let ns = Namespace::new(&example);
let ss = Constraints::new(&ns, &example).unwrap();
dbg!(&ns);
let entity = &example.schemas[0].entities[0];
let scope = Scope::root().pushed(ScopeType::Schema, &example.schemas[0].name);
let entity = Entity::legalize(&ns, &ss, &scope, entity).unwrap();
dbg!(&entity);
}
}