1prelude! {}
2
3pub mod bounds;
4pub mod builtin;
5pub mod idx;
6pub mod structural;
7
8pub use bounds::Bounds;
9pub use structural::Structural;
10
11pub mod annot {
12 pub type Source = String;
13 pub type Key = String;
14 pub type Val = String;
15}
16
17#[derive(Debug, Clone)]
22pub struct Annot {
23 source: annot::Source,
24 details: HashMap<annot::Key, annot::Val>,
25}
26
27pub type Annots = Vec<Annot>;
28
29impl std::ops::Deref for Annot {
30 type Target = HashMap<annot::Key, annot::Val>;
31 fn deref(&self) -> &Self::Target {
32 &self.details
33 }
34}
35
36impl Annot {
37 pub fn with_capacity(source: impl Into<annot::Source>, details_capa: usize) -> Self {
38 Self {
39 source: source.into(),
40 details: HashMap::with_capacity(details_capa),
41 }
42 }
43
44 pub fn shrink_to_fit(&mut self) {
45 self.details.shrink_to_fit()
46 }
47
48 pub fn source(&self) -> &str {
49 &self.source
50 }
51 pub fn details(&self) -> &HashMap<annot::Key, annot::Val> {
52 &self.details
53 }
54
55 pub fn insert(&mut self, key: impl Into<annot::Key>, val: impl Into<annot::Val>) -> Res<()> {
57 let entry = self.details.entry(key.into());
58 use std::collections::hash_map::Entry::*;
59 match entry {
60 Vacant(entry) => {
61 entry.insert(val.into());
62 }
63 Occupied(entry) => {
64 let val = val.into();
65 let err = error!(@redef("annotation details key/value binding") entry.key())
66 .with_context(format!(
67 "trying to replace value `{}` with `{}`",
68 entry.get(),
69 val
70 ));
71 return Err(err);
72 }
73 }
74 Ok(())
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
80pub struct Path {
81 last: idx::Pack,
82 path: SmallVec<[idx::Pack; 8]>,
83}
84
85impl Path {
86 pub fn new(idx: idx::Pack) -> Self {
87 Self {
88 last: idx,
89 path: smallvec![],
90 }
91 }
92
93 pub fn of_idx(ctx: &Ctx, idx: idx::Pack) -> Self {
95 let last = idx;
96 let mut rev_path = smallvec!();
97
98 let mut current = &ctx[idx];
99
100 while let Some(parent) = current.sup() {
101 rev_path.push(parent);
102 current = &ctx[parent];
103 }
104 rev_path.reverse();
105 let path = rev_path;
106 Self { last, path }
107 }
108
109 pub fn iter<'me>(&'me self) -> impl Iterator<Item = idx::Pack> + 'me {
110 self.path.iter().cloned().chain(Some(self.last).into_iter())
111 }
112 pub fn iter_pref<'me>(&'me self) -> impl Iterator<Item = idx::Pack> + 'me {
113 self.path.iter().cloned()
114 }
115
116 pub fn len(&self) -> usize {
117 self.pref_len() + 1
118 }
119 pub fn pref_len(&self) -> usize {
120 self.path.len()
121 }
122
123 pub fn push(&mut self, idx: idx::Pack) {
124 let to_push = mem::replace(&mut self.last, idx);
125 self.path.push(to_push)
126 }
127 pub fn pop(&mut self) -> Option<idx::Pack> {
128 self.path
129 .pop()
130 .map(|new_last| mem::replace(&mut self.last, new_last))
131 }
132 pub fn last(&self) -> idx::Pack {
133 self.last
134 }
135 pub fn first(&self) -> idx::Pack {
136 self.path.get(0).cloned().unwrap_or(self.last)
137 }
138
139 fn resolve_relative_etype(
141 mut path: Path,
142 ctx: &mut Ctx,
143 s: impl AsRef<str>,
144 ) -> Res<idx::Class> {
145 let s = s.as_ref();
146 let mut bits = s.split("/").into_iter();
147 let mut next = bits.next();
148 let mut last = None;
149
150 while let Some(ident) = next {
151 next = bits.next();
152
153 if next.is_some() {
154 let p_idx = ctx.pack_idx_or_forward_ref(&path, ident)?;
155 path.push(p_idx);
156 } else {
157 last = Some(ident);
158 break;
159 }
160 }
161
162 if let Some(ident) = last {
163 ctx.get_class_idx_or_forward_ref_in(&path, ident)
164 } else {
165 bail!("illegal empty absolute `eType`: `{}`", s);
166 }
167 }
168
169 pub fn resolve_etype(ctx: &mut ctx::PathCtx, s: impl AsRef<str>) -> Res<idx::Class> {
173 let s = s.as_ref();
174 if let Some(idx) = ctx.ctx().try_parse_builtin_etype(s)? {
175 return Ok(idx);
176 }
177
178 let rel_pref = "#//";
179 if s.starts_with(rel_pref) {
180 let s = &s[rel_pref.len()..];
181 Self::resolve_relative_etype(ctx.path().clone(), ctx.ctx_mut(), s)
182 } else {
183 bail!("unsupported `eType` path `{}`", s);
184 }
185 }
186
187 pub fn display(&self, ctx: &idx::PackMap<Pack>) -> String {
188 let mut res = self.path.iter().fold(String::new(), |mut s, p_idx| {
189 s.push_str(ctx[*p_idx].name());
190 s.push_str("::");
191 s
192 });
193 res.push_str(ctx[self.last].name());
194 res
195 }
196 pub fn display_sep(&self, ctx: &idx::PackMap<Pack>) -> String {
197 let mut res = self.display(ctx);
198 res.push_str("::");
199 res
200 }
201}
202
203#[derive(Debug, Clone)]
205pub struct ELit {
206 name: String,
207 value: Option<String>,
208}
209
210pub type ELits = Vec<ELit>;
211
212impl ELit {
213 pub fn new(name: impl Into<String>, value: Option<impl Into<String>>) -> Self {
214 Self {
215 name: name.into(),
216 value: value.map(|s| s.into()),
217 }
218 }
219 pub fn new_name(name: impl Into<String>) -> Self {
220 Self {
221 name: name.into(),
222 value: None,
223 }
224 }
225
226 pub fn name(&self) -> &str {
227 &self.name
228 }
229 pub fn value(&self) -> Option<&str> {
230 self.value.as_ref().map(|s| s.as_str())
231 }
232}
233
234#[derive(Debug, Clone)]
235pub struct Param {
236 name: String,
237 bounds: Bounds,
238 typ: idx::Class,
239}
240
241pub type Params = Vec<Param>;
242
243impl Param {
244 pub fn new(name: impl Into<String>, bounds: impl Into<Bounds>, typ: idx::Class) -> Self {
245 Self {
246 name: name.into(),
247 bounds: bounds.into(),
248 typ,
249 }
250 }
251
252 pub fn name(&self) -> &str {
253 &self.name
254 }
255 pub fn bounds(&self) -> &Bounds {
256 &self.bounds
257 }
258 pub fn typ(&self) -> idx::Class {
259 self.typ
260 }
261}
262
263#[derive(Debug, Clone)]
264pub struct Operation {
265 name: String,
266 typ: Option<idx::Class>,
267 parameters: Params,
268}
269
270pub type Operations = Vec<Operation>;
271
272impl Operation {
273 pub fn with_capacity(
274 name: impl Into<String>,
275 typ: Option<idx::Class>,
276 param_capa: usize,
277 ) -> Self {
278 Self {
279 name: name.into(),
280 typ: typ,
281 parameters: Params::with_capacity(param_capa),
282 }
283 }
284 pub fn new(name: impl Into<String>, typ: Option<idx::Class>) -> Self {
285 Self::with_capacity(name, typ, 3)
286 }
287 pub fn add_parameter(&mut self, param: Param) {
288 self.parameters.push(param)
289 }
290
291 pub fn name(&self) -> &str {
292 &self.name
293 }
294 pub fn typ(&self) -> Option<idx::Class> {
295 self.typ
296 }
297 pub fn parameters(&self) -> &Params {
298 &self.parameters
299 }
300}
301
302#[derive(Debug)]
303pub struct Class {
304 pub idx: idx::Class,
305 pub path: Path,
306 concrete: bool,
307 is_interface: bool,
308 typ: String,
309 name: String,
310 inst_name: Option<String>,
311 literals: Vec<ELit>,
312 annotations: Annots,
313 sup: BTreeSet<idx::Class>,
314 sub: BTreeSet<idx::Class>,
315 structural: Vec<Structural>,
316 operations: Operations,
317}
318
319impl HasAnnots for Class {
320 fn annotations(&self) -> &Annots {
321 &self.annotations
322 }
323 fn annotations_mut(&mut self) -> &mut Annots {
324 &mut self.annotations
325 }
326}
327impl HasStructural for Class {
328 fn structural(&self) -> &[Structural] {
329 &self.structural
330 }
331 fn structural_mut(&mut self) -> &mut Vec<repr::Structural> {
332 &mut self.structural
333 }
334}
335
336impl Class {
337 pub fn new(
338 idx: idx::Class,
339 path: Path,
340 typ: impl Into<String>,
341 name: impl Into<String>,
342 inst_name: Option<impl Into<String>>,
343 is_abstract: Option<bool>,
344 is_interface: Option<bool>,
345 ) -> Self {
346 Self {
347 idx,
348 path,
349 typ: typ.into(),
350 name: name.into(),
351 inst_name: inst_name.map(Into::into),
352 concrete: !is_abstract.unwrap_or(false),
353 is_interface: is_interface.unwrap_or(false),
354 literals: ELits::with_capacity(7),
355 annotations: Annots::with_capacity(3),
356 sup: BTreeSet::new(),
357 sub: BTreeSet::new(),
358 structural: Vec::with_capacity(5),
359 operations: Operations::with_capacity(7),
360 }
361 }
362
363 pub fn shrink_to_fit(&mut self) {
364 let Self {
366 idx: _,
367 path: _,
368 typ: _,
369 name: _,
370 inst_name: _,
371 concrete: _,
372 is_interface: _,
373 literals,
374 annotations,
375 sup: _,
376 sub: _,
377 structural,
378 operations,
379 } = self;
380 literals.shrink_to_fit();
381 annotations.shrink_to_fit();
382 structural.shrink_to_fit();
383 operations.shrink_to_fit();
384 }
385
386 #[inline]
387 pub fn is_concrete(&self) -> bool {
388 self.concrete
389 }
390 #[inline]
391 pub fn is_interface(&self) -> bool {
392 self.is_interface
393 }
394 #[inline]
395 pub fn is_abstract(&self) -> bool {
396 !self.is_concrete()
397 }
398 #[inline]
399 pub fn name(&self) -> &str {
400 &self.name
401 }
402 #[inline]
403 pub fn inst_name(&self) -> Option<&str> {
404 self.inst_name.as_ref().map(|s| s.as_str())
405 }
406
407 pub fn annotations(&self) -> &Annots {
408 &self.annotations
409 }
410 pub fn add_annotation(&mut self, annot: Annot) {
411 self.annotations.push(annot)
412 }
413
414 pub fn literals(&self) -> &ELits {
415 &self.literals
416 }
417 pub fn add_literal(&mut self, lit: ELit) {
418 self.literals.push(lit)
419 }
420
421 pub fn operations(&self) -> &Operations {
422 &self.operations
423 }
424 pub fn add_operation(&mut self, op: Operation) {
425 self.operations.push(op)
426 }
427
428 pub fn typ(&self) -> &String {
429 &self.typ
430 }
431
432 pub fn sup(&self) -> &BTreeSet<idx::Class> {
433 &self.sup
434 }
435 pub fn add_sup(&mut self, sup: idx::Class) -> bool {
436 self.sup.insert(sup)
437 }
438
439 pub fn sub(&self) -> &BTreeSet<idx::Class> {
440 &self.sub
441 }
442 pub fn add_sub(&mut self, sub: idx::Class) -> bool {
443 self.sub.insert(sub)
444 }
445
446 pub fn structural(&self) -> &[Structural] {
447 &self.structural
448 }
449 pub fn add_structural(&mut self, val: impl Into<Structural>) {
450 self.structural.push(val.into())
451 }
452
453 pub fn display(&self, ctx: &Ctx) -> String {
454 format!("{}/{}", self.path.display(ctx.packs()), self.name)
455 }
456}
457
458#[derive(Debug, Clone)]
459pub struct Pack {
460 pub idx: idx::Pack,
461 sup: Option<idx::Pack>,
462 sub: BTreeSet<idx::Pack>,
463 name: String,
464 classes: BTreeSet<idx::Class>,
465 annotations: Annots,
466}
467
468impl Pack {
469 pub fn with_capacity(idx: idx::Pack, name: impl Into<String>, sup: Option<idx::Pack>) -> Self {
470 Self {
471 idx,
472 sup,
473 sub: BTreeSet::new(),
474 name: name.into(),
475 classes: BTreeSet::new(),
476 annotations: Annots::with_capacity(3),
477 }
478 }
479 pub fn new(idx: idx::Pack, name: impl Into<String>, sup: Option<idx::Pack>) -> Self {
480 Self::with_capacity(idx, name, sup)
481 }
482
483 pub fn is_empty(&self) -> bool {
485 self.sub.is_empty() && self.classes.is_empty() && self.annotations.is_empty()
486 }
487
488 pub fn path(&self, ctx: &Ctx) -> Path {
489 Path::of_idx(ctx, self.idx)
490 }
491
492 pub fn annotations(&self) -> &Annots {
493 &self.annotations
494 }
495 pub fn add_annotation(&mut self, annot: Annot) {
496 self.annotations.push(annot)
497 }
498
499 pub fn sup(&self) -> Option<idx::Pack> {
500 self.sup
501 }
502 pub fn set_sup(&mut self, sup: idx::Pack) -> Option<idx::Pack> {
503 mem::replace(&mut self.sup, Some(sup))
504 }
505 pub fn has_sup(&mut self, sup: idx::Pack) -> bool {
506 self.sup == Some(sup)
507 }
508
509 pub fn sub(&self) -> &BTreeSet<idx::Pack> {
510 &self.sub
511 }
512 pub fn add_sub(&mut self, sub: idx::Pack) -> bool {
513 self.sub.insert(sub)
514 }
515 pub fn has_sub(&self, sub: idx::Pack) -> bool {
516 self.sub.contains(&sub)
517 }
518
519 pub fn name(&self) -> &str {
520 &self.name
521 }
522
523 pub fn classes(&self) -> &BTreeSet<idx::Class> {
524 &self.classes
525 }
526 pub fn classes_insert(&mut self, idx: idx::Class) -> bool {
527 self.classes.insert(idx)
528 }
529}