sdml_tera/
context.rs

1/*!
2This module provides SDML to Value functions for constructing template contexts.
3
4Note that the created context values *are not* intended as a direct 1:1 representation of either the
5published surface syntax grammar or the Rust model. The form is simplified for use in the template
6language using the following guidelines.
7
81. Reduce layers in the model that do not add value; i.e. [Identifier` in the Rust model has an
9   inner `value` field.
102. Where an `Option<T>` field is `None` do not add a key in the generated object.
113. Where a `Vec<T>` field `is_empty` do not add a key in the generated object.
124. Use the key `"__type"` as a discriminator where the content of an object is ambiguous, especially
13   in arrays.
145. Only add `source_span` values for major objects such as definitions, not for individual names
15   etc.
16
17The upshot of this is that an `if` statement in a template is used to check for presence of a value
18before you use it. The following demonstrates this pattern for optional fields and  possibly empty
19collections.
20
21```md
22{% if module.base_uri -%}
23 *Base URI*: {{ module.base_uri }}
24{%- endif %}
25
26{% if module.annotations -%}
27  {% for ann in module.annotations -%}
28    {{ ann.name }}
29  {%- endfor %}
30{%- endif %}
31```
32
33 */
34
35use sdml_core::model::annotations::{Annotation, AnnotationProperty, HasAnnotations};
36use sdml_core::model::constraints::{
37    AtomicSentence, BinaryBooleanSentence, BooleanSentence, Constraint, ConstraintBody,
38    ConstraintSentence, EnvironmentDef, EnvironmentDefBody, Equation, FunctionDef,
39    FunctionSignature, FunctionType, FunctionTypeReferenceInner, Inequation,
40    PredicateSequenceMember, PredicateValue, QuantifiedSentence, SequenceOfPredicateValues,
41    SimpleSentence, Subject, Term, UnaryBooleanSentence, Variables,
42};
43use sdml_core::model::definitions::{
44    DatatypeDef, Definition, EntityDef, EnumDef, EventDef, HasMembers, HasVariants, MethodDef,
45    PropertyDef, RdfDef, StructureDef, TypeClassDef, TypeVariable, UnionDef,
46};
47use sdml_core::model::members::{Member, MemberDef, MemberKind};
48use sdml_core::model::modules::{Module, ModuleBody};
49use sdml_core::model::values::{
50    MappingValue, SequenceMember, SequenceOfValues, SimpleValue, Value as SdmlValue,
51    ValueConstructor,
52};
53use sdml_core::model::{HasBody, HasName, HasNameReference, HasOptionalBody, HasSourceSpan};
54use sdml_core::stdlib::is_library_module;
55use sdml_core::store::ModuleStore;
56use tera::{Map, Value};
57
58// ------------------------------------------------------------------------------------------------
59// Public Functions
60// ------------------------------------------------------------------------------------------------
61
62///
63/// Convert a SDML `Module` into a context object, in the form shown as JSON below.
64///
65/// ```json
66/// {
67///   "__type": "module",
68///   "name": "Identifier",
69///   "is_library_module": true,
70///   "source_file": "Path",            // optional
71///   "source_span": {
72///     "start": 0,
73///     "end": 10,
74///   }, // optional
75///   "base_uri": "absolute-uri",       // optional
76///   "version_info": "string",         // optional
77///   "version_uri": "absolute-uri",    // optional
78///   "imports": [],                    // optional
79///   "annotations": [],                // optional
80///   "definitions": []                 // optional
81/// }
82/// ```
83///
84/// # Import Object
85///
86/// Module import:
87///
88/// ```json
89/// {
90///   "module": "Identifier",
91///   "version_uri": "absolute-uri"     // optional
92/// }
93/// ```
94///
95/// Member import:
96///
97/// ```json
98/// {
99///   "module": "Identifier",
100///   "member": "Identifier"
101/// }
102/// ```
103///
104pub fn module_to_value(module: &Module, _cache: &impl ModuleStore) -> (String, Value) {
105    let mut value = Map::default();
106
107    value.insert(KEY_META_TYPE.into(), VAL_MT_MODULE.into());
108    value.insert(KEY_NAME.into(), module.name().to_string().into());
109    value.insert(
110        KEY_IS_LIBRARY_MODULE.into(),
111        is_library_module(module.name()).into(),
112    );
113
114    add_source_span(module, &mut value);
115
116    if let Some(source_file) = module.source_file() {
117        value.insert(
118            KEY_SOURCE_FILE.into(),
119            Value::String(source_file.to_string_lossy().into_owned()),
120        );
121    }
122    if let Some(base_uri) = module.base_uri() {
123        value.insert(KEY_BASE_URI.into(), Value::String(base_uri.to_string()));
124    }
125    if let Some(version_info) = module.version_info() {
126        value.insert(
127            KEY_VERSION_INFO.into(),
128            Value::String(version_info.to_string()),
129        );
130    }
131    if let Some(version_uri) = module.version_uri() {
132        value.insert(
133            KEY_VERSION_URI.into(),
134            Value::String(version_uri.to_string()),
135        );
136    }
137
138    add_module_body(module.body(), &mut value);
139
140    (module.name().to_string(), value.into())
141}
142
143///
144/// Convert a SDML `AnnotationProperty` into a context object, in the form shown as JSON below.
145///
146/// ```json
147/// {
148///     "__type": "property",
149///     "source_span": {},              // optional
150///     "name": "IdentifierReference",  // optional
151///     "value": {}
152/// }
153/// ```
154///
155pub fn annotation_property_to_value(property: &AnnotationProperty) -> Value {
156    let mut property_map = Map::default();
157
158    add_source_span(property, &mut property_map);
159    property_map.insert(KEY_META_TYPE.into(), VAL_MT_PROPERTY.into());
160    property_map.insert(
161        KEY_NAME.into(),
162        property.name_reference().to_string().into(),
163    );
164    property_map.insert(KEY_VALUE.into(), value_to_value(property.value()));
165
166    property_map.into()
167}
168
169///
170/// Convert a SDML `Value` into a context object, in the form shown as JSON below.
171///
172/// # Simple Value
173///
174/// ```json
175/// {
176///     "__type": "boolean|double|decimal|integer|unsigned|string|uri|binary",
177///     "value": ...
178/// }
179/// ```
180///
181/// # Value Constructor
182///
183/// ```json
184/// {
185///     "__type": "constructor",
186///     "type_ref": "IdentifierReference",
187///     "value": {}
188/// }
189/// ```
190///
191/// # Mapping
192///
193/// ```json
194/// {
195///     "__type": "mapping",
196///     "domain": {},
197///     "range": {}
198/// }
199/// ```
200///
201/// # Reference
202///
203/// ```json
204/// {
205///     "__type": "type_ref",
206///     "value": "IdentifierReference",
207/// }
208/// ```
209///
210/// # Sequence
211///
212/// ```json
213/// {
214///     "__type": "sequence",
215///     "members": []
216/// }
217/// ```
218///
219pub fn value_to_value(value: &SdmlValue) -> Value {
220    let mut value_map = Map::default();
221
222    match value {
223        SdmlValue::Simple(v) => add_simple_value(v, &mut value_map),
224        SdmlValue::ValueConstructor(v) => add_value_constructor(v, &mut value_map),
225        SdmlValue::Mapping(v) => add_mapping_value(v, &mut value_map),
226        SdmlValue::Reference(v) => {
227            value_map.insert(KEY_META_TYPE.into(), KEY_TYPE_REF.into());
228            value_map.insert(KEY_VALUE.into(), v.to_string().into());
229        }
230        SdmlValue::List(vs) => add_value_list(vs, &mut value_map),
231    }
232
233    value_map.into()
234}
235
236///
237/// Convert a SDML `Constraint` into a context object, in the form shown as JSON below.
238///
239/// ## Informal Constraint
240///
241/// ```json
242/// {
243///     "__type": "informal",
244///     "source_span": {},              // optional
245///     "name": "Identifier",
246///     "value": "string",
247///     "language": ""                  // optional
248/// }
249/// ```
250///
251/// ## Formal Constraint
252///
253/// ```json
254/// {
255///     "__type": "formal",
256///     "source_span": {},             // optional
257///     "name": "Identifier",
258///     "definitions": [],             // optional
259///     "sentence": {}
260/// }
261/// ```
262///
263pub fn annotation_constraint_to_value(constraint: &Constraint) -> Value {
264    let mut constraint_map = Map::default();
265
266    add_source_span(constraint, &mut constraint_map);
267    constraint_map.insert(KEY_NAME.into(), constraint.name().to_string().into());
268
269    match constraint.body() {
270        ConstraintBody::Informal(v) => {
271            constraint_map.insert(KEY_META_TYPE.into(), "informal".into());
272            constraint_map.insert(KEY_VALUE.into(), v.value().to_string().into());
273            if let Some(language) = v.language() {
274                constraint_map.insert("language".into(), language.to_string().into());
275            }
276        }
277        ConstraintBody::Formal(v) => {
278            constraint_map.insert(KEY_META_TYPE.into(), "formal".into());
279            if v.has_definitions() {
280                let mut definitions: Vec<Value> = Vec::default();
281                for definition in v.definitions() {
282                    add_definition(definition, &mut definitions);
283                }
284                constraint_map.insert("definitions".into(), definitions.into());
285            }
286            let mut sentence_map = Map::default();
287            add_constraint_sentence(v.body(), &mut sentence_map);
288            constraint_map.insert("sentence".into(), sentence_map.into());
289        }
290    }
291
292    constraint_map.into()
293}
294
295///
296/// Convert a SDML `DatatypeDef` into a context object, in the form shown as JSON below.
297///
298/// ```json
299/// {
300///     "__type": "datatype",
301///     "source_span": {},              // optional
302///     "name": "Identifier",
303///     "is_opaque": false,
304///     "base_type": "IdentifierReference",
305///     "annotations": []               // optional
306/// }
307/// ```
308///
309pub fn datatype_to_value(defn: &DatatypeDef) -> Value {
310    let mut defn_map = Map::default();
311
312    add_source_span(defn, &mut defn_map);
313    defn_map.insert(KEY_META_TYPE.into(), "datatype".into());
314    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
315    defn_map.insert("is_opaque".into(), defn.is_opaque().into());
316    defn_map.insert("base_type".into(), defn.base_type().to_string().into());
317
318    if let Some(body) = defn.body() {
319        add_annotations(body, &mut defn_map);
320    }
321
322    defn_map.into()
323}
324
325///
326/// Convert a SDML `EntityDef` into a context object, in the form shown as JSON below.
327///
328/// ```json
329/// {
330///     "__type": "entity",
331///     "source_span": {},              // optional
332///     "name": "Identifier",
333///     "identity": {},
334///     "annotations": [],              // optional
335///     "members": []                   // optional
336/// }
337/// ```
338///
339/// For `identity`, see MemberDef and for `members` see Member, in [`member_to_value`].
340///
341pub fn entity_to_value(defn: &EntityDef) -> Value {
342    let mut defn_map = Map::default();
343
344    add_source_span(defn, &mut defn_map);
345    defn_map.insert(KEY_META_TYPE.into(), "entity".into());
346    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
347
348    if let Some(body) = defn.body() {
349        defn_map.insert("identity".into(), member_to_value(body.identity()));
350
351        add_annotations(body, &mut defn_map);
352
353        if body.has_members() {
354            let mut members: Vec<Value> = Vec::default();
355
356            for member in body.members() {
357                members.push(member_to_value(member));
358            }
359
360            defn_map.insert("members".into(), members.into());
361        }
362    }
363
364    defn_map.into()
365}
366
367///
368/// Convert a SDML `Member` into a context object, in the form shown as JSON below.
369///
370///
371/// A member is either a reference to a property or a definition of a new member.
372///
373/// # Property Reference
374///
375/// ```json
376/// {
377///     "__type": "reference",
378///     "type_ref": "IdentifierReference",
379/// }
380/// ```
381///
382/// # Member Definition
383///
384/// ```json
385/// {
386///     "__type": "definition",
387///     "source_span": {},              // optional
388///     "name": "Identifier",
389///     "cardinality": {
390///         "ordering": "",
391///         "uniqueness": "",
392///         "min_occurs": 1,
393///         "max_occurs": 0             // optional
394///     },
395///     "type_ref": "IdentifierReference"
396/// }
397/// ```
398///
399pub fn member_to_value(defn: &Member) -> Value {
400    let mut defn_map = Map::default();
401
402    add_source_span(defn, &mut defn_map);
403
404    match defn.kind() {
405        MemberKind::Reference(v) => {
406            defn_map.insert(KEY_META_TYPE.into(), "reference".into());
407            defn_map.insert("type_ref".into(), v.to_string().into());
408        }
409        MemberKind::Definition(v) => {
410            defn_map.insert(KEY_META_TYPE.into(), "definition".into());
411            add_member_def(v, &mut defn_map)
412        }
413    }
414
415    defn_map.into()
416}
417
418///
419/// Convert a SDML `EnumDef` into a context object, in the form shown as JSON below.
420///
421/// ```json
422/// {
423///     "__type": "enum",
424///     "source_span": {},              // optional
425///     "name": "Identifier",
426///     "annotations": [],
427///     "variants": [                   // optional
428///         {
429///             "name": "Identifier",
430///             "annotations": []       // optional
431///         }
432///     ]
433/// }
434/// ```
435///
436pub fn enum_to_value(defn: &EnumDef) -> Value {
437    let mut defn_map = Map::default();
438
439    add_source_span(defn, &mut defn_map);
440    defn_map.insert(KEY_META_TYPE.into(), "enum".into());
441    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
442
443    if let Some(body) = defn.body() {
444        add_annotations(body, &mut defn_map);
445
446        if body.has_variants() {
447            let mut variants: Vec<Value> = Vec::default();
448            for variant in body.variants() {
449                let mut variant_map = Map::default();
450                add_source_span(variant, &mut variant_map);
451                variant_map.insert(KEY_NAME.into(), variant.name().to_string().into());
452                if let Some(body) = variant.body() {
453                    add_annotations(body, &mut variant_map);
454                }
455                variants.push(variant_map.into());
456            }
457            defn_map.insert("variants".into(), variants.into());
458        }
459    }
460
461    defn_map.into()
462}
463
464///
465/// Convert a SDML `EventDef` into a context object, in the form shown as JSON below.
466///
467/// ```json
468/// {
469///     "__type": "event",
470///     "source_span": {},              // optional
471///     "name": "Identifier",
472///     "source_ref": "IdentifierReference",
473///     "annotations": [],              // optional
474///     "members": []                   // optional
475/// }
476/// ```
477///
478/// For `members`, see [`member_to_value`].
479///
480pub fn event_to_value(defn: &EventDef) -> Value {
481    let mut defn_map = Map::default();
482
483    add_source_span(defn, &mut defn_map);
484    defn_map.insert(KEY_META_TYPE.into(), "event".into());
485    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
486    defn_map.insert("source_ref".into(), defn.event_source().to_string().into());
487
488    if let Some(body) = defn.body() {
489        add_annotations(body, &mut defn_map);
490        if body.has_members() {
491            let mut members: Vec<Value> = Vec::default();
492
493            for member in body.members() {
494                members.push(member_to_value(member));
495            }
496
497            defn_map.insert("members".into(), members.into());
498        }
499    }
500
501    defn_map.into()
502}
503
504///
505/// Convert a SDML `PropertyDef` into a context object, in the form shown as JSON below.
506///
507/// ```json
508/// {
509///     "__type": "property",
510///     "source_span": {},              // optional
511///     "name": "Identifier",
512///     "annotations": [],              // optional
513///     "member": {}
514/// }
515/// ```
516///
517/// For `member` see member definition in [`member_to_value`].
518///
519pub fn property_to_value(defn: &PropertyDef) -> Value {
520    let mut defn_map = Map::default();
521
522    add_source_span(defn, &mut defn_map);
523    defn_map.insert(KEY_META_TYPE.into(), "property".into());
524    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
525
526    let mut member_map = Map::default();
527    add_member_def(defn.member_def(), &mut member_map);
528    defn_map.insert("member".into(), member_map.into());
529
530    defn_map.into()
531}
532
533///
534/// Convert a SDML `RdfDef` into a context object, in the form shown as JSON below.
535///
536/// ```json
537/// {
538///     "__type": "rdf",
539///     "source_span": {},              // optional
540///     "name": "Identifier",
541///     "annotations": []               // optional
542/// }
543/// ```
544///
545pub fn rdf_to_value(defn: &RdfDef) -> Value {
546    let mut defn_map = Map::default();
547
548    add_source_span(defn, &mut defn_map);
549    defn_map.insert(KEY_META_TYPE.into(), "rdf".into());
550    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
551
552    add_annotations(defn.body(), &mut defn_map);
553
554    defn_map.into()
555}
556
557///
558/// Convert a SDML `StructureDef` into a context object, in the form shown as JSON below.
559///
560/// ```json
561/// {
562///     "__type": "structure",
563///     "source_span": {},              // optional
564///     "name": "Identifier",
565///     "annotations": [],              // optional
566///     "members": []                   // optional
567/// }
568/// ```
569///
570/// For `members`, see [`member_to_value`].
571///
572pub fn structure_to_value(defn: &StructureDef) -> Value {
573    let mut defn_map = Map::default();
574
575    add_source_span(defn, &mut defn_map);
576    defn_map.insert(KEY_META_TYPE.into(), "structure".into());
577    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
578
579    if let Some(body) = defn.body() {
580        add_annotations(body, &mut defn_map);
581        if body.has_members() {
582            let mut members: Vec<Value> = Vec::default();
583
584            for member in body.members() {
585                members.push(member_to_value(member));
586            }
587
588            defn_map.insert("members".into(), members.into());
589        }
590    }
591
592    defn_map.into()
593}
594
595///
596/// Convert a SDML `TypeClassDef` into a context object, in the form shown as JSON below.
597///
598/// ```json
599/// {
600///     "__type": "type_class",
601///     "source_span": {},              // optional
602///     "name": "Identifier",
603///     "variables": [],                // optional
604///     "annotations": [],              // optional
605///     "methods": []                   // optional
606/// }
607/// ```
608///
609/// ## Variable
610///
611/// TBD
612///
613/// ## Method
614///
615/// TBD
616///
617pub fn type_class_to_value(defn: &TypeClassDef) -> Value {
618    let mut defn_map = Map::default();
619
620    add_source_span(defn, &mut defn_map);
621    defn_map.insert(KEY_META_TYPE.into(), "type_class".into());
622    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
623
624    if defn.has_variables() {
625        let mut variables: Vec<Value> = Vec::default();
626        for variable in defn.variables() {
627            add_type_variable(variable, &mut variables);
628        }
629        defn_map.insert("variables".into(), variables.into());
630    }
631
632    if let Some(body) = defn.body() {
633        add_annotations(body, &mut defn_map);
634        if body.has_methods() {
635            let mut methods: Vec<Value> = Vec::default();
636            for method in body.methods() {
637                add_type_method(method, &mut methods);
638            }
639            defn_map.insert("methods".into(), methods.into());
640        }
641    }
642
643    defn_map.into()
644}
645
646///
647/// Convert a SDML `UnionDef` into a context object, in the form shown as JSON below.
648///
649/// ```json
650/// {
651///     "__type": "union",
652///     "source_span": {},              // optional
653///     "name": "Identifier",
654///     "annotations": [],              // optional
655///     "variants": [                   // optional
656///         {
657///             "name": "IdentifierReference",
658///             "rename": "Identifier",
659///             "annotations": []
660///         }
661///     ]
662/// }
663/// ```
664///
665pub fn union_to_value(defn: &UnionDef) -> Value {
666    let mut defn_map = Map::default();
667
668    add_source_span(defn, &mut defn_map);
669    defn_map.insert(KEY_META_TYPE.into(), "union".into());
670    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
671
672    if let Some(body) = defn.body() {
673        add_annotations(body, &mut defn_map);
674
675        if body.has_variants() {
676            let mut variants: Vec<Value> = Vec::default();
677            for variant in body.variants() {
678                let mut variant_map = Map::default();
679                variant_map.insert(KEY_NAME.into(), variant.name().to_string().into());
680                if let Some(rename) = variant.rename() {
681                    variant_map.insert("rename".into(), rename.to_string().into());
682                }
683                if let Some(body) = variant.body() {
684                    add_annotations(body, &mut variant_map);
685                }
686                variants.push(variant_map.into());
687            }
688            defn_map.insert("variants".into(), variants.into());
689        }
690    }
691
692    defn_map.into()
693}
694
695// ------------------------------------------------------------------------------------------------
696// Private Values
697// ------------------------------------------------------------------------------------------------
698
699const KEY_META_TYPE: &str = "__type";
700
701const VAL_MT_MODULE: &str = "module";
702const VAL_MT_PROPERTY: &str = "property";
703const VAL_MT_BOOLEAN: &str = "boolean";
704const VAL_MT_DOUBLE: &str = "double";
705const VAL_MT_DECIMAL: &str = "decimal";
706const VAL_MT_INTEGER: &str = "integer";
707const VAL_MT_UNSIGNED: &str = "unsigned";
708const VAL_MT_STRING: &str = "string";
709const VAL_MT_URI: &str = "uri";
710const VAL_MT_BINARY: &str = "binary";
711const VAL_MT_CONSTRUCTOR: &str = "constructor";
712const VAL_MT_MAPPING: &str = "mapping";
713const VAL_MT_MAPPING_TYPE: &str = "mapping_type";
714const VAL_MT_SEQUENCE: &str = "sequence";
715const VAL_MT_TYPE_REF: &str = "type_ref";
716
717const KEY_NAME: &str = "name";
718const KEY_VALUE: &str = "value";
719const KEY_TYPE_REF: &str = VAL_MT_TYPE_REF;
720
721const KEY_IS_LIBRARY_MODULE: &str = "is_library_module";
722const KEY_BASE_URI: &str = "base_uri";
723const KEY_VERSION_INFO: &str = "version_info";
724const KEY_VERSION_URI: &str = "version_uri";
725const KEY_MODULE: &str = "module";
726const KEY_MEMBER: &str = "member";
727const KEY_MEMBERS: &str = "members";
728const KEY_IMPORTS: &str = "imports";
729const KEY_DEFINITIONS: &str = "definitions";
730const KEY_START: &str = "start";
731const KEY_END: &str = "end";
732const KEY_SOURCE_FILE: &str = "source_file";
733const KEY_SOURCE_SPAN: &str = "source_span";
734const KEY_ANNOTATIONS: &str = "annotations";
735const KEY_DOMAIN: &str = "domain";
736const KEY_RANGE: &str = "range";
737const KEY_TYPE: &str = "type";
738
739// ------------------------------------------------------------------------------------------------
740// Private Functions
741// ------------------------------------------------------------------------------------------------
742
743fn add_module_body(body: &ModuleBody, value: &mut Map<String, Value>) {
744    // imports
745    if body.has_imports() {
746        let mut imports: Vec<Value> = Vec::default();
747        for (module_name, maybe_version) in body.imported_module_versions() {
748            let mut imported = Map::default();
749            imported.insert(KEY_MODULE.into(), module_name.to_string().into());
750            if let Some(version) = maybe_version {
751                imported.insert(KEY_VERSION_URI.into(), version.to_string().into());
752            }
753            imports.push(imported.into());
754        }
755
756        for member_name in body.imported_types() {
757            let mut imported = Map::default();
758            imported.insert(KEY_MODULE.into(), member_name.module().to_string().into());
759            imported.insert(KEY_MEMBER.into(), member_name.member().to_string().into());
760            imports.push(imported.into());
761        }
762        value.insert(KEY_IMPORTS.into(), imports.into());
763    }
764
765    // annotations
766    add_annotations(body, value);
767
768    // definitions
769    if body.has_definitions() {
770        let mut definitions: Vec<Value> = Vec::default();
771
772        for definition in body.definitions() {
773            match definition {
774                Definition::Datatype(v) => definitions.push(datatype_to_value(v)),
775                Definition::Entity(v) => definitions.push(entity_to_value(v)),
776                Definition::Enum(v) => definitions.push(enum_to_value(v)),
777                Definition::Event(v) => definitions.push(event_to_value(v)),
778                Definition::Property(v) => definitions.push(property_to_value(v)),
779                Definition::Rdf(v) => definitions.push(rdf_to_value(v)),
780                Definition::Structure(v) => definitions.push(structure_to_value(v)),
781                Definition::TypeClass(v) => definitions.push(type_class_to_value(v)),
782                Definition::Union(v) => definitions.push(union_to_value(v)),
783            }
784        }
785
786        value.insert(KEY_DEFINITIONS.into(), definitions.into());
787    }
788}
789
790fn add_source_span(annotated: &impl HasSourceSpan, value: &mut Map<String, Value>) {
791    if let Some(source_span) = annotated.source_span() {
792        let mut span_value = Map::default();
793        span_value.insert(
794            KEY_START.into(),
795            Value::Number(source_span.start().byte().into()),
796        );
797        span_value.insert(
798            KEY_END.into(),
799            Value::Number(source_span.end().byte().into()),
800        );
801        value.insert(KEY_SOURCE_SPAN.into(), span_value.into());
802    }
803}
804
805fn add_annotations(annotated: &impl HasAnnotations, value: &mut Map<String, Value>) {
806    if annotated.has_annotations() {
807        let mut annotations: Vec<Value> = Vec::default();
808
809        for annotation in annotated.annotations() {
810            match annotation {
811                Annotation::Property(v) => annotations.push(annotation_property_to_value(v)),
812                Annotation::Constraint(v) => annotations.push(annotation_constraint_to_value(v)),
813            }
814        }
815
816        value.insert(KEY_ANNOTATIONS.into(), annotations.into());
817    }
818}
819
820fn add_simple_value(value: &SimpleValue, value_map: &mut Map<String, Value>) {
821    match value {
822        SimpleValue::Boolean(v) => {
823            value_map.insert(KEY_META_TYPE.into(), VAL_MT_BOOLEAN.into());
824            value_map.insert(KEY_VALUE.into(), (*v).into());
825        }
826        SimpleValue::Double(v) => {
827            value_map.insert(KEY_META_TYPE.into(), VAL_MT_DOUBLE.into());
828            value_map.insert(KEY_VALUE.into(), (*v.as_ref()).into());
829        }
830        SimpleValue::Decimal(v) => {
831            value_map.insert(KEY_META_TYPE.into(), VAL_MT_DECIMAL.into());
832            value_map.insert(KEY_VALUE.into(), v.to_string().into());
833        }
834        SimpleValue::Integer(v) => {
835            value_map.insert(KEY_META_TYPE.into(), VAL_MT_INTEGER.into());
836            value_map.insert(KEY_VALUE.into(), (*v).into());
837        }
838        SimpleValue::Unsigned(v) => {
839            value_map.insert(KEY_META_TYPE.into(), VAL_MT_UNSIGNED.into());
840            value_map.insert(KEY_VALUE.into(), (*v).into());
841        }
842        SimpleValue::String(v) => {
843            value_map.insert(KEY_META_TYPE.into(), VAL_MT_STRING.into());
844            value_map.insert(KEY_VALUE.into(), v.to_string().into());
845        }
846        SimpleValue::IriReference(v) => {
847            value_map.insert(KEY_META_TYPE.into(), VAL_MT_URI.into());
848            value_map.insert(KEY_VALUE.into(), v.to_string().into());
849        }
850        SimpleValue::Binary(_) => {
851            value_map.insert(KEY_META_TYPE.into(), VAL_MT_BINARY.into());
852            // TODO: hex encode here
853            value_map.insert(KEY_VALUE.into(), "...".into());
854        }
855    }
856}
857
858fn add_value_constructor(value: &ValueConstructor, value_map: &mut Map<String, Value>) {
859    value_map.insert(KEY_META_TYPE.into(), VAL_MT_CONSTRUCTOR.into());
860
861    value_map.insert(KEY_TYPE_REF.into(), value.type_name().to_string().into());
862
863    let mut simple_value_map = Map::default();
864    add_simple_value(value.value(), &mut simple_value_map);
865    value_map.insert(KEY_VALUE.into(), simple_value_map.into());
866}
867
868fn add_mapping_value(value: &MappingValue, value_map: &mut Map<String, Value>) {
869    value_map.insert(KEY_META_TYPE.into(), VAL_MT_MAPPING.into());
870
871    let mut domain_map = Map::default();
872    add_simple_value(value.domain(), &mut domain_map);
873    value_map.insert(KEY_DOMAIN.into(), domain_map.into());
874
875    value_map.insert(KEY_RANGE.into(), value_to_value(value.range()));
876}
877
878fn add_value_list(value: &SequenceOfValues, value_map: &mut Map<String, Value>) {
879    value_map.insert(KEY_META_TYPE.into(), VAL_MT_SEQUENCE.into());
880
881    let mut members: Vec<Value> = Vec::default();
882    for member in value.iter() {
883        let mut value_map = Map::default();
884        match member {
885            SequenceMember::Simple(v) => add_simple_value(v, &mut value_map),
886            SequenceMember::ValueConstructor(v) => add_value_constructor(v, &mut value_map),
887            SequenceMember::Mapping(v) => add_mapping_value(v, &mut value_map),
888            SequenceMember::Reference(v) => {
889                value_map.insert(KEY_META_TYPE.into(), VAL_MT_TYPE_REF.into());
890                value_map.insert(KEY_TYPE_REF.into(), v.to_string().into());
891            }
892        }
893        members.push(value_map.into());
894    }
895
896    value_map.insert("members".into(), members.into());
897}
898
899fn add_predicate_value_list(value: &SequenceOfPredicateValues, value_map: &mut Map<String, Value>) {
900    value_map.insert(KEY_META_TYPE.into(), VAL_MT_SEQUENCE.into());
901
902    let mut members: Vec<Value> = Vec::default();
903    for member in value.iter() {
904        let mut value_map = Map::default();
905        match member {
906            PredicateSequenceMember::Simple(v) => add_simple_value(v, &mut value_map),
907            PredicateSequenceMember::ValueConstructor(v) => {
908                add_value_constructor(v, &mut value_map)
909            }
910            PredicateSequenceMember::Mapping(v) => add_mapping_value(v, &mut value_map),
911            PredicateSequenceMember::Reference(v) => {
912                value_map.insert(KEY_META_TYPE.into(), VAL_MT_TYPE_REF.into());
913                value_map.insert(KEY_TYPE_REF.into(), v.to_string().into());
914            }
915        }
916        members.push(value_map.into());
917    }
918
919    value_map.insert(KEY_MEMBERS.into(), members.into());
920}
921
922fn add_definition(defn: &EnvironmentDef, value: &mut Vec<Value>) {
923    let mut defn_map = Map::default();
924
925    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
926
927    match defn.body() {
928        EnvironmentDefBody::Function(v) => add_function(v, &mut defn_map),
929        EnvironmentDefBody::Value(v) => match v {
930            PredicateValue::Simple(v) => add_simple_value(v, &mut defn_map),
931            PredicateValue::Sequence(v) => add_predicate_value_list(v, &mut defn_map),
932        },
933        EnvironmentDefBody::Sentence(v) => add_constraint_sentence(v, &mut defn_map),
934    }
935
936    value.push(defn_map.into());
937}
938
939fn add_function(defn: &FunctionDef, value: &mut Map<String, Value>) {
940    value.insert(KEY_META_TYPE.into(), "function".into());
941
942    add_function_signature(defn.signature(), value);
943
944    add_constraint_sentence(defn.body(), value);
945}
946
947fn add_function_signature(defn: &FunctionSignature, value: &mut Map<String, Value>) {
948    if defn.has_parameters() {
949        let mut parameters: Vec<Value> = Vec::default();
950
951        for parameter in defn.parameters() {
952            let mut param_map = Map::default();
953            param_map.insert(KEY_NAME.into(), parameter.name().to_string().into());
954            add_function_type(parameter.target_type(), &mut param_map);
955            parameters.push(param_map.into());
956        }
957
958        value.insert("parameters".into(), parameters.into());
959    }
960
961    let mut type_map = Map::default();
962    add_function_type(defn.target_type(), &mut type_map);
963    value.insert(KEY_TYPE.into(), type_map.into());
964}
965
966fn add_function_type(defn: &FunctionType, value: &mut Map<String, Value>) {
967    let cardinality = defn.target_cardinality();
968    let mut cardinality_map = Map::default();
969    if let Some(ordering) = cardinality.ordering() {
970        cardinality_map.insert("ordering".into(), ordering.to_string().into());
971    }
972    if let Some(uniqueness) = cardinality.uniqueness() {
973        cardinality_map.insert("uniqueness".into(), uniqueness.to_string().into());
974    }
975    if let Some(range) = cardinality.range() {
976        cardinality_map.insert("min_occurs".into(), range.min_occurs().into());
977        if let Some(max_occurs) = range.max_occurs() {
978            cardinality_map.insert("max_occurs".into(), max_occurs.into());
979        }
980    }
981    value.insert("cardinality".into(), cardinality_map.into());
982
983    let mut type_map = Map::default();
984    let target_type = defn.target_type();
985    type_map.insert("is_optional".into(), target_type.is_optional().into());
986    match target_type.inner() {
987        FunctionTypeReferenceInner::Wildcard => {
988            type_map.insert(KEY_META_TYPE.into(), "wildcard".into());
989        }
990        FunctionTypeReferenceInner::Reference(v) => {
991            type_map.insert(KEY_META_TYPE.into(), VAL_MT_TYPE_REF.into());
992            type_map.insert(KEY_TYPE_REF.into(), v.to_string().into());
993        }
994        FunctionTypeReferenceInner::MappingType(v) => {
995            type_map.insert(KEY_META_TYPE.into(), VAL_MT_MAPPING_TYPE.into());
996            type_map.insert(KEY_DOMAIN.into(), v.domain().to_string().into());
997            type_map.insert(KEY_RANGE.into(), v.range().to_string().into());
998        }
999    }
1000
1001    value.insert("type".into(), type_map.into());
1002}
1003
1004fn add_constraint_sentence(defn: &ConstraintSentence, value: &mut Map<String, Value>) {
1005    match defn {
1006        ConstraintSentence::Simple(v) => match v {
1007            SimpleSentence::Atomic(v) => add_atomic_sentence(v, value),
1008            SimpleSentence::Equation(v) => add_equation(v, value),
1009            SimpleSentence::Inequation(v) => add_inequation(v, value),
1010        },
1011        ConstraintSentence::Boolean(v) => match v {
1012            BooleanSentence::Unary(v) => add_unary_boolean(v, value),
1013            BooleanSentence::Binary(v) => add_binary_boolean(v, value),
1014        },
1015        ConstraintSentence::Quantified(v) => add_quantified_sentence(v, value),
1016    }
1017}
1018
1019fn add_atomic_sentence(defn: &AtomicSentence, value: &mut Map<String, Value>) {
1020    value.insert(KEY_META_TYPE.into(), "atomic_sentence".into());
1021
1022    value.insert("function".into(), term_to_value(defn.predicate()));
1023
1024    if defn.has_arguments() {
1025        let mut arguments: Vec<Value> = Vec::default();
1026        for argument in defn.arguments() {
1027            arguments.push(term_to_value(argument));
1028        }
1029        value.insert("arguments".into(), arguments.into());
1030    }
1031}
1032
1033fn add_equation(defn: &Equation, value: &mut Map<String, Value>) {
1034    value.insert(KEY_META_TYPE.into(), "equation".into());
1035    value.insert("lhs".into(), term_to_value(defn.left_operand()));
1036    value.insert("rhs".into(), term_to_value(defn.right_operand()));
1037}
1038
1039fn add_inequation(defn: &Inequation, value: &mut Map<String, Value>) {
1040    value.insert("type".into(), "ineqation".into());
1041    value.insert("lhs".into(), term_to_value(defn.left_operand()));
1042    value.insert("relation".into(), defn.relation().to_string().into());
1043    value.insert("rhs".into(), term_to_value(defn.right_operand()));
1044}
1045
1046fn add_unary_boolean(defn: &UnaryBooleanSentence, value: &mut Map<String, Value>) {
1047    value.insert(KEY_META_TYPE.into(), "unary_boolean_sentence".into());
1048
1049    value.insert("operator".into(), defn.operator().to_string().into());
1050
1051    let mut sentence_map = Map::default();
1052    add_constraint_sentence(defn.operand(), &mut sentence_map);
1053    value.insert("operand".into(), sentence_map.into());
1054}
1055
1056fn add_binary_boolean(defn: &BinaryBooleanSentence, value: &mut Map<String, Value>) {
1057    value.insert(KEY_META_TYPE.into(), "binary_boolean_sentence".into());
1058
1059    let mut sentence_map = Map::default();
1060    add_constraint_sentence(defn.left_operand(), &mut sentence_map);
1061    value.insert("lhs".into(), sentence_map.into());
1062
1063    value.insert("operator".into(), defn.operator().to_string().into());
1064
1065    let mut sentence_map = Map::default();
1066    add_constraint_sentence(defn.right_operand(), &mut sentence_map);
1067    value.insert("rhs".into(), sentence_map.into());
1068}
1069
1070fn add_quantified_sentence(defn: &QuantifiedSentence, value: &mut Map<String, Value>) {
1071    value.insert(KEY_META_TYPE.into(), "quantified_sentence".into());
1072
1073    let mut binding_map = Map::default();
1074    let variable_binding = defn.binding();
1075    binding_map.insert(
1076        "quantifier".into(),
1077        variable_binding.quantifier().to_string().into(),
1078    );
1079    if let Some(binding) = variable_binding.binding() {
1080        binding_map.insert("name".into(), binding.name().to_string().into());
1081        binding_map.insert("source".into(), term_to_value(binding.source()));
1082    }
1083    value.insert("binding".into(), binding_map.into());
1084
1085    let mut sentence_map = Map::default();
1086    add_constraint_sentence(defn.body(), &mut sentence_map);
1087    value.insert("sentence".into(), sentence_map.into());
1088}
1089
1090fn term_to_value(defn: &Term) -> Value {
1091    let mut term_map = Map::default();
1092    match defn {
1093        Term::Sequence(v) => {
1094            term_map.insert(KEY_META_TYPE.into(), "sequence_builder".into());
1095
1096            match v.variables() {
1097                Variables::Named(v) => {
1098                    let mut names: Vec<Value> = Vec::default();
1099                    for name in v.names() {
1100                        names.push(name.to_string().into());
1101                    }
1102                    term_map.insert("named".into(), names.into());
1103                }
1104                Variables::Mapping(v) => {
1105                    term_map.insert("domain".into(), v.domain().to_string().into());
1106                    term_map.insert("range".into(), v.range().to_string().into());
1107                }
1108            }
1109
1110            let mut sentence_map = Map::default();
1111            add_quantified_sentence(v.body(), &mut sentence_map);
1112            term_map.insert("sentence".into(), sentence_map.into());
1113        }
1114        Term::Function(v) => {
1115            term_map.insert(KEY_META_TYPE.into(), "function".into());
1116            term_map.insert("function".into(), term_to_value(v.function()));
1117            if v.has_arguments() {
1118                let mut arguments: Vec<Value> = Vec::default();
1119                for argument in v.arguments() {
1120                    arguments.push(term_to_value(argument));
1121                }
1122                term_map.insert("arguments".into(), arguments.into());
1123            }
1124        }
1125        Term::Composition(v) => {
1126            term_map.insert(KEY_META_TYPE.into(), "composition".into());
1127            term_map.insert(
1128                "subject".into(),
1129                match v.subject() {
1130                    Subject::ReservedSelf => "self".into(),
1131                    Subject::Identifier(v) => v.to_string().into(),
1132                },
1133            );
1134            if v.has_function_names() {
1135                let mut functions: Vec<Value> = Vec::default();
1136                for function in v.function_names() {
1137                    functions.push(function.to_string().into());
1138                }
1139                term_map.insert("functions".into(), functions.into());
1140            }
1141        }
1142        Term::Identifier(v) => {
1143            term_map.insert(KEY_META_TYPE.into(), "reference".into());
1144            term_map.insert("name".into(), v.to_string().into());
1145        }
1146        Term::ReservedSelf => {
1147            term_map.insert(KEY_META_TYPE.into(), "self".into());
1148        }
1149        Term::Value(v) => match v {
1150            PredicateValue::Simple(v) => add_simple_value(v, &mut term_map),
1151            PredicateValue::Sequence(v) => add_predicate_value_list(v, &mut term_map),
1152        },
1153    }
1154    term_map.into()
1155}
1156
1157fn add_member_def(defn: &MemberDef, defn_map: &mut Map<String, Value>) {
1158    defn_map.insert(KEY_NAME.into(), defn.name().to_string().into());
1159    let cardinality = defn.target_cardinality();
1160    let mut cardinality_map = Map::default();
1161    if let Some(ordering) = cardinality.ordering() {
1162        cardinality_map.insert("ordering".into(), ordering.to_string().into());
1163    }
1164    if let Some(uniqueness) = cardinality.uniqueness() {
1165        cardinality_map.insert("uniqueness".into(), uniqueness.to_string().into());
1166    }
1167    cardinality_map.insert("min_occurs".into(), cardinality.min_occurs().into());
1168    if let Some(max_occurs) = cardinality.max_occurs() {
1169        cardinality_map.insert("max_occurs".into(), max_occurs.into());
1170    }
1171    defn_map.insert("cardinality".into(), cardinality_map.into());
1172    defn_map.insert(KEY_TYPE_REF.into(), defn.target_type().to_string().into());
1173    if let Some(body) = defn.body() {
1174        add_annotations(body, defn_map);
1175    }
1176}
1177
1178fn add_type_variable(defn: &TypeVariable, value: &mut Vec<Value>) {
1179    let mut var_map = Map::default();
1180
1181    var_map.insert(KEY_NAME.into(), defn.name().to_string().into());
1182    // TODO: cardinality
1183    // TODO: restrictions
1184
1185    value.push(var_map.into());
1186}
1187
1188fn add_type_method(defn: &MethodDef, value: &mut Vec<Value>) {
1189    let mut var_map = Map::default();
1190
1191    var_map.insert(KEY_NAME.into(), defn.name().to_string().into());
1192    // TODO: signature
1193    // TODO: body
1194    // TODO: annotations
1195
1196    value.push(var_map.into());
1197}