@lionweb/core 0.7.0-beta.2 → 0.7.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/deserializer.d.ts +2 -2
  3. package/dist/deserializer.d.ts.map +1 -1
  4. package/dist/deserializer.js +7 -10
  5. package/dist/deserializer.js.map +1 -1
  6. package/dist/extraction.d.ts.map +1 -1
  7. package/dist/functions.d.ts.map +1 -1
  8. package/dist/handler.d.ts +1 -1
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +0 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/m1/reference-utils.d.ts +1 -1
  14. package/dist/m1/reference-utils.d.ts.map +1 -1
  15. package/dist/m3/builtins.d.ts.map +1 -1
  16. package/dist/m3/builtins.js +2 -1
  17. package/dist/m3/builtins.js.map +1 -1
  18. package/dist/m3/constraints.d.ts.map +1 -1
  19. package/dist/m3/constraints.js +2 -2
  20. package/dist/m3/constraints.js.map +1 -1
  21. package/dist/m3/deserializer.d.ts.map +1 -1
  22. package/dist/m3/feature-resolvers.d.ts +23 -0
  23. package/dist/m3/feature-resolvers.d.ts.map +1 -0
  24. package/dist/m3/feature-resolvers.js +48 -0
  25. package/dist/m3/feature-resolvers.js.map +1 -0
  26. package/dist/m3/functions.d.ts +17 -1
  27. package/dist/m3/functions.d.ts.map +1 -1
  28. package/dist/m3/functions.js +21 -5
  29. package/dist/m3/functions.js.map +1 -1
  30. package/dist/m3/index.d.ts +2 -0
  31. package/dist/m3/index.d.ts.map +1 -1
  32. package/dist/m3/index.js +2 -0
  33. package/dist/m3/index.js.map +1 -1
  34. package/dist/m3/reference-checker.d.ts.map +1 -1
  35. package/dist/m3/serializer.d.ts.map +1 -1
  36. package/dist/{symbol-table.d.ts → m3/symbol-table.d.ts} +14 -14
  37. package/dist/m3/symbol-table.d.ts.map +1 -0
  38. package/dist/m3/symbol-table.js +43 -0
  39. package/dist/m3/symbol-table.js.map +1 -0
  40. package/dist/m3/types.d.ts.map +1 -1
  41. package/dist/references.d.ts +1 -1
  42. package/dist/references.d.ts.map +1 -1
  43. package/dist/serializer.d.ts +1 -1
  44. package/dist/serializer.d.ts.map +1 -1
  45. package/dist/serializer.js +20 -10
  46. package/dist/serializer.js.map +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/dist/writing.js +1 -1
  50. package/package.json +31 -31
  51. package/src/deserializer.ts +224 -0
  52. package/src/dynamic-facade.ts +63 -0
  53. package/src/extraction.ts +31 -0
  54. package/src/functions.ts +28 -0
  55. package/src/handler.ts +57 -0
  56. package/src/index.ts +13 -0
  57. package/src/m1/reference-utils.ts +106 -0
  58. package/src/m3/README.md +16 -0
  59. package/src/m3/builtins.ts +170 -0
  60. package/src/m3/constraints.ts +109 -0
  61. package/src/m3/deserializer.ts +38 -0
  62. package/src/m3/facade.ts +130 -0
  63. package/src/m3/factory.ts +98 -0
  64. package/src/m3/feature-resolvers.ts +72 -0
  65. package/src/m3/functions.ts +379 -0
  66. package/src/m3/index.ts +12 -0
  67. package/src/m3/lioncore.ts +139 -0
  68. package/src/m3/reference-checker.ts +38 -0
  69. package/src/m3/serializer.ts +13 -0
  70. package/src/m3/symbol-table.ts +125 -0
  71. package/src/m3/types.ts +325 -0
  72. package/src/reading.ts +55 -0
  73. package/src/references.ts +31 -0
  74. package/src/serializer.ts +244 -0
  75. package/src/types.ts +11 -0
  76. package/src/version.ts +5 -0
  77. package/src/writing.ts +79 -0
  78. package/dist/symbol-table.d.ts.map +0 -1
  79. package/dist/symbol-table.js +0 -66
  80. package/dist/symbol-table.js.map +0 -1
@@ -0,0 +1,130 @@
1
+ import { builtinFeatures } from "./builtins.js"
2
+ import { metaTypedBasedClassifierDeducerFor, qualifiedNameOf } from "./functions.js"
3
+ import { lioncore, metaConcepts, metaFeatures } from "./lioncore.js"
4
+ import { Reader } from "../reading.js"
5
+ import {
6
+ Annotation,
7
+ Classifier,
8
+ Concept,
9
+ Containment,
10
+ Enumeration,
11
+ EnumerationLiteral,
12
+ Interface,
13
+ Language,
14
+ M3Concept,
15
+ PrimitiveType,
16
+ Property,
17
+ Reference
18
+ } from "./types.js"
19
+ import { updateSettingsNameBased, Writer } from "../writing.js"
20
+
21
+ const { inamed_name } = builtinFeatures
22
+ const { ikeyed_key } = metaFeatures
23
+
24
+ export const lioncoreReader: Reader<M3Concept> = {
25
+ classifierOf: metaTypedBasedClassifierDeducerFor(lioncore),
26
+ getFeatureValue: (node, feature) =>
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ (node as any)[feature.name], // (mirrors name-based update of settings)
29
+ enumerationLiteralFrom: (value, _) => value as EnumerationLiteral | null
30
+ }
31
+
32
+ /**
33
+ * Alias for {@link lioncoreReader}, kept for backward compatibility, and to be deprecated and removed later.
34
+ */
35
+ export const lioncoreExtractionFacade = lioncoreReader
36
+
37
+ /**
38
+ * @return An implementation of {@link Writer} for instances of the LionCore M3 (so M2s).
39
+ */
40
+ export const lioncoreWriter: Writer<M3Concept> = {
41
+ nodeFor: (parent, classifier, id, propertySettings) => {
42
+ switch (classifier.key) {
43
+ case metaConcepts.annotation.key:
44
+ return new Annotation(
45
+ parent as Language,
46
+ propertySettings[inamed_name.key] as string,
47
+ propertySettings[ikeyed_key.key] as string,
48
+ id
49
+ )
50
+ case metaConcepts.concept.key:
51
+ return new Concept(
52
+ parent as Language,
53
+ propertySettings[inamed_name.key] as string,
54
+ propertySettings[ikeyed_key.key] as string,
55
+ id,
56
+ propertySettings[metaFeatures.concept_abstract.key] as boolean
57
+ )
58
+ case metaConcepts.interface.key:
59
+ return new Interface(
60
+ parent as Language,
61
+ propertySettings[inamed_name.key] as string,
62
+ propertySettings[ikeyed_key.key] as string,
63
+ id
64
+ )
65
+ case metaConcepts.containment.key:
66
+ return new Containment(
67
+ parent as Classifier,
68
+ propertySettings[inamed_name.key] as string,
69
+ propertySettings[ikeyed_key.key] as string,
70
+ id
71
+ )
72
+ case metaConcepts.enumeration.key:
73
+ return new Enumeration(
74
+ parent as Language,
75
+ propertySettings[inamed_name.key] as string,
76
+ propertySettings[ikeyed_key.key] as string,
77
+ id
78
+ )
79
+ case metaConcepts.enumerationLiteral.key:
80
+ return new EnumerationLiteral(
81
+ parent as Enumeration,
82
+ propertySettings[inamed_name.key] as string,
83
+ propertySettings[ikeyed_key.key] as string,
84
+ id
85
+ )
86
+ case metaConcepts.language.key:
87
+ return new Language(
88
+ propertySettings[inamed_name.key] as string,
89
+ propertySettings[metaFeatures.language_version.key] as string,
90
+ id,
91
+ propertySettings[metaFeatures.ikeyed_key.key] as string
92
+ )
93
+ case metaConcepts.primitiveType.key:
94
+ return new PrimitiveType(
95
+ parent as Language,
96
+ propertySettings[inamed_name.key] as string,
97
+ propertySettings[ikeyed_key.key] as string,
98
+ id
99
+ )
100
+ case metaConcepts.property.key:
101
+ return new Property(
102
+ parent as Classifier,
103
+ propertySettings[inamed_name.key] as string,
104
+ propertySettings[ikeyed_key.key] as string,
105
+ id
106
+ )
107
+ case metaConcepts.reference.key:
108
+ return new Reference(
109
+ parent as Classifier,
110
+ propertySettings[inamed_name.key] as string,
111
+ propertySettings[ikeyed_key.key] as string,
112
+ id
113
+ )
114
+ default:
115
+ throw new Error(
116
+ `don't know a node of concept ${qualifiedNameOf(classifier)} with key ${classifier.key} that's not in LionCore M3`
117
+ )
118
+ }
119
+ },
120
+ setFeatureValue: (node, feature, value) => {
121
+ updateSettingsNameBased(node as unknown as Record<string, unknown>, feature, value)
122
+ },
123
+ encodingOf: literal => literal
124
+ }
125
+
126
+ /**
127
+ * Alias for {@link lioncoreWriter}, kept for backward compatibility, and to be deprecated and removed later.
128
+ */
129
+ export const lioncoreInstantationFacade = lioncoreWriter
130
+
@@ -0,0 +1,98 @@
1
+ import { StringsMapper } from "@lionweb/ts-utils"
2
+ import { SingleRef } from "../references.js"
3
+ import {
4
+ Annotation,
5
+ Classifier,
6
+ Concept,
7
+ Containment,
8
+ Enumeration,
9
+ EnumerationLiteral,
10
+ Interface,
11
+ Language,
12
+ PrimitiveType,
13
+ Property,
14
+ Reference
15
+ } from "./types.js"
16
+
17
+
18
+ /**
19
+ * A factory that produces a {@link Language} instance,
20
+ * as well as {@link LanguageEntity entities} contained by that instance
21
+ * and {@link Feature features} of {@link Classifier classifiers}
22
+ * and {@link EnumerationLiteral enumeration literals} of {@link Enumeration enumerations}.
23
+ *
24
+ * The factory methods take care of proper containment.
25
+ * *Note:* also calling `havingEntities`, `havingFeatures`, and `havingLiterals` doesn't produce duplicates.
26
+ * (This is to stay backward compatible.)
27
+ */
28
+ export class LanguageFactory {
29
+
30
+ readonly id: StringsMapper
31
+ readonly key: StringsMapper
32
+ readonly language: Language
33
+
34
+ constructor(name: string, version: string, id: StringsMapper, key: StringsMapper) {
35
+ this.id = id
36
+ this.key = key
37
+ this.language = new Language(name, version, this.id(name), this.key(name))
38
+ }
39
+
40
+
41
+ annotation(name: string, extends_?: SingleRef<Annotation>): Annotation {
42
+ const annotation = new Annotation(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name), extends_)
43
+ this.language.havingEntities(annotation)
44
+ return annotation
45
+ }
46
+
47
+ concept(name: string, abstract: boolean, extends_?: SingleRef<Concept>): Concept {
48
+ const concept = new Concept(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name), abstract, extends_)
49
+ this.language.havingEntities(concept)
50
+ return concept
51
+ }
52
+
53
+ interface(name: string): Interface {
54
+ const intface = new Interface(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name))
55
+ this.language.havingEntities(intface)
56
+ return intface
57
+ }
58
+
59
+ enumeration(name: string): Enumeration {
60
+ const enumeration = new Enumeration(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name))
61
+ this.language.havingEntities(enumeration)
62
+ return enumeration
63
+ }
64
+
65
+ primitiveType(name: string): PrimitiveType {
66
+ const primitiveType = new PrimitiveType(this.language, name, this.key(this.language.name, name), this.id(this.language.name, name))
67
+ this.language.havingEntities(primitiveType)
68
+ return primitiveType
69
+ }
70
+
71
+
72
+ containment(classifier: Classifier, name: string): Containment {
73
+ const containment = new Containment(classifier, name, this.key(this.language.name, classifier.name, name), this.id(this.language.name, classifier.name, name))
74
+ classifier.havingFeatures(containment)
75
+ return containment
76
+ }
77
+
78
+ property(classifier: Classifier, name: string): Property {
79
+ const property = new Property(classifier, name, this.key(this.language.name, classifier.name, name), this.id(this.language.name, classifier.name, name))
80
+ classifier.havingFeatures(property)
81
+ return property
82
+ }
83
+
84
+ reference(classifier: Classifier, name: string): Reference {
85
+ const reference = new Reference(classifier, name, this.key(this.language.name, classifier.name, name), this.id(this.language.name, classifier.name, name))
86
+ classifier.havingFeatures(reference)
87
+ return reference
88
+ }
89
+
90
+
91
+ enumerationLiteral(enumeration: Enumeration, name: string): EnumerationLiteral {
92
+ const enumerationLiteral = new EnumerationLiteral(enumeration, name, this.key(this.language.name, enumeration.name, name), this.id(this.language.name, enumeration.name, name))
93
+ enumeration.havingLiterals(enumerationLiteral)
94
+ return enumerationLiteral
95
+ }
96
+
97
+ }
98
+
@@ -0,0 +1,72 @@
1
+ // Copyright 2025 TRUMPF Laser SE and other contributors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License")
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // SPDX-FileCopyrightText: 2025 TRUMPF Laser SE and other contributors
16
+ // SPDX-License-Identifier: Apache-2.0
17
+
18
+ import { LionWebJsonMetaPointer } from "@lionweb/json"
19
+
20
+ import { Classifier, Containment, Feature, Language, Property, Reference } from "./types.js"
21
+ import { MemoisingSymbolTable } from "./symbol-table.js"
22
+
23
+
24
+ /**
25
+ * Type def. for functions that resolve a {@link Feature feature} of the indicated sub-type
26
+ * from a feature's and a classifier's meta-pointers,
27
+ * throwing an {@link Error error} when the feature couldn't be resolved,
28
+ * or it isn't of the expected sub-type.
29
+ */
30
+ export type FeatureResolver<FT extends Feature> = (metaPointer: LionWebJsonMetaPointer, classifier: Classifier) => FT
31
+
32
+ /**
33
+ * Type def. for an object containing {@link FeatureResolver resolvers} for
34
+ * {@link Property properties}, {@link Containmnent containments}, and {@link Reference references}.
35
+ */
36
+ export type FeatureResolvers = {
37
+ resolvedPropertyFrom: FeatureResolver<Property>
38
+ resolvedContainmentFrom: FeatureResolver<Containment>
39
+ resolvedReferenceFrom: FeatureResolver<Reference>
40
+ }
41
+
42
+ /**
43
+ * @return an {@link FeatureResolvers object} for the given {@link Language languages}.
44
+ */
45
+ export const featureResolversFor = (languages: Language[]): FeatureResolvers => {
46
+ const symbolTable = new MemoisingSymbolTable(languages)
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ const featureResolverFor = <FT extends Feature>(featureClassConstructor: new (...args: any[]) => FT): FeatureResolver<FT> =>
49
+ (featureMetaPointer, classifier: Classifier) => {
50
+ const classifierMetaPointer = classifier.metaPointer()
51
+ const featureLocationMessage = () => `feature with meta-pointer ${JSON.stringify(featureMetaPointer)} on classifier with meta-pointer ${JSON.stringify(classifierMetaPointer)}`
52
+ const feature = symbolTable.featureMatching(classifierMetaPointer, featureMetaPointer)
53
+ if (feature === undefined) {
54
+ throw new Error(`couldn't resolve ${featureLocationMessage()}`) // fail early <== unrecoverable
55
+ }
56
+ if (feature.constructor !== featureClassConstructor) { // feature's type must match desired type *exactly* — cheaper to evaluate than "feature instanceof featureClassConstructor"
57
+ throw new Error(`${featureLocationMessage()} is not a ${featureClassConstructor.name} but a ${feature.constructor.name}`) // fail early <== unrecoverable
58
+ }
59
+ /*
60
+ * We could make this function memoising as well, to avoid having to perform these checks every resolution.
61
+ * That memoisation would involve a 6-deep lookup, in the feature's meta-pointer + container's classifier meta-pointer.
62
+ * The checks seem cheap enough to not be problematic performance-wise, though.
63
+ */
64
+ return feature as FT // valid <== feature.constructor === featureClassConstructor
65
+ }
66
+ return {
67
+ resolvedPropertyFrom: featureResolverFor(Property),
68
+ resolvedContainmentFrom: featureResolverFor(Containment),
69
+ resolvedReferenceFrom: featureResolverFor(Reference)
70
+ }
71
+ }
72
+
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Various functions on M3 models.
3
+ */
4
+
5
+
6
+ import { LionWebId, LionWebKey } from "@lionweb/json"
7
+ import { cycleWith, flatMapNonCyclingFollowing, sortByStringKey } from "@lionweb/ts-utils"
8
+ import { containmentChain } from "../functions.js"
9
+ import { ClassifierDeducer } from "../reading.js"
10
+ import { isRef, unresolved } from "../references.js"
11
+ import { Node } from "../types.js"
12
+ import {
13
+ Annotation,
14
+ Classifier,
15
+ Concept,
16
+ Containment,
17
+ DataType,
18
+ Enumeration,
19
+ Feature,
20
+ IKeyed,
21
+ IMetaTyped,
22
+ INamed,
23
+ Interface,
24
+ isINamed,
25
+ Language,
26
+ LanguageEntity,
27
+ Link,
28
+ M3Concept,
29
+ Property,
30
+ Reference
31
+ } from "./types.js"
32
+
33
+
34
+ /**
35
+ * @return The type of the given {@link Feature}
36
+ */
37
+ const type = (feature: Feature): Classifier | DataType | typeof unresolved =>
38
+ (feature as (Link | Property)).type
39
+
40
+
41
+ const isProperty = (feature: Feature): feature is Property =>
42
+ feature instanceof Property
43
+
44
+ const isContainment = (feature: Feature): feature is Containment =>
45
+ feature instanceof Containment
46
+
47
+ const isReference = (feature: Feature): feature is Reference =>
48
+ feature instanceof Reference
49
+
50
+ const isMultiple = (feature: Feature): feature is Link =>
51
+ feature instanceof Link && feature.multiple
52
+
53
+
54
+ /**
55
+ * The (names of the) metatypes of a feature.
56
+ */
57
+ type FeatureMetaType =
58
+ | "Containment"
59
+ | "Property"
60
+ | "Reference"
61
+
62
+ /**
63
+ * @return the (name of the) metatype of the given {@link Feature feature}.
64
+ */
65
+ const featureMetaType = (feature: Feature): FeatureMetaType => {
66
+ if (feature instanceof Containment) {
67
+ return "Containment"
68
+ }
69
+ if (feature instanceof Property) {
70
+ return "Property"
71
+ }
72
+ if (feature instanceof Reference) {
73
+ return "Reference"
74
+ }
75
+ throw new Error(`unhandled Feature sub type ${feature.constructor.name}`)
76
+ }
77
+
78
+
79
+ /**
80
+ * Determines whether a {@link Feature feature} is "relational",
81
+ * i.e. it's a {@link Link containment or reference}.
82
+ */
83
+ const isRelational = (feature: Feature): feature is Link =>
84
+ feature instanceof Link
85
+
86
+ /**
87
+ * @return the relations among the given {@link Feature features}.
88
+ */
89
+ const relations = (features: Feature[]): Link[] =>
90
+ features.filter(isRelational)
91
+
92
+ /**
93
+ * @return the non-relations among the given {@link Feature features}.
94
+ */
95
+ const nonRelationalFeatures = (features: Feature[]): Feature[] =>
96
+ features.filter((feature) => !isRelational(feature))
97
+
98
+
99
+ /**
100
+ * @return the relations of the given {@link LanguageEntity language element}.
101
+ */
102
+ const relationsOf = (element: LanguageEntity): Link[] =>
103
+ element instanceof Classifier
104
+ ? relations(element.features)
105
+ : []
106
+
107
+
108
+ /**
109
+ * @return The "things", i.e. {@link M3Concept}s, directly contained by the given "thing".
110
+ * These can be:
111
+ * {@link LanguageEntity language entities}, {@link Feature features}, and {@link EnumerationLiteral enumeration literals}
112
+ * (and all their sub types).
113
+ */
114
+ const directlyContaineds = (thing: M3Concept): M3Concept[] => {
115
+ if (thing instanceof Language) {
116
+ return thing.entities
117
+ }
118
+ if (thing instanceof Classifier) {
119
+ return thing.features as M3Concept[] // (cast is necessary because of presence of Feature#classifier getter...?)
120
+ }
121
+ if (thing instanceof Enumeration) {
122
+ return thing.literals
123
+ }
124
+ return []
125
+ }
126
+
127
+
128
+ /**
129
+ * @return All {@link M3Concept nodes} contained in this {@link Language language},
130
+ * including the language itself.
131
+ */
132
+ const allContaineds = (language: Language): M3Concept[] =>
133
+ [
134
+ language,
135
+ ...directlyContaineds(language),
136
+ ...directlyContaineds(language).flatMap(directlyContaineds)
137
+ ]
138
+
139
+
140
+ /**
141
+ * Performs a depth-first tree traversal of a language, "flatMapping" the `map` function on every node.
142
+ * It avoids visiting nodes twice (to avoid potential infinite loops), but doesn't report cycles.
143
+ */
144
+ const flatMap = <T>(language: Language, map: (t: M3Concept) => T[]): T[] =>
145
+ flatMapNonCyclingFollowing(map, directlyContaineds)(language)
146
+
147
+
148
+ /**
149
+ * @return string the name of the given {@link INamed named thing}.
150
+ */
151
+ const nameOf = <T extends INamed>({name}: T): string =>
152
+ name
153
+
154
+
155
+ /**
156
+ * @return the given named things sorted by name
157
+ */
158
+ export const nameSorted = <T extends INamed>(ts: T[]): T[] =>
159
+ sortByStringKey(ts, nameOf)
160
+
161
+
162
+ /**
163
+ * @return the concatenation of the names of the given nodes using the given separator.
164
+ */
165
+ const concatenateNamesOf = (separator: string, nodes: M3Concept[]): string =>
166
+ nodes
167
+ .filter(isINamed)
168
+ .map(nameOf)
169
+ .join(separator)
170
+ // !! slight overkill: every node in an M2 is an M3Concept, so IKeyed and INamed
171
+
172
+ /**
173
+ * @return the qualified name of the given {@link INamed named thing}.
174
+ */
175
+ const qualifiedNameOf = <T extends INamed & Node>(node: T, separator = "."): string =>
176
+ concatenateNamesOf(separator, containmentChain(node).reverse() as M3Concept[])
177
+
178
+
179
+ /**
180
+ * @return the {@link INamed named things} in this {@link Language language}
181
+ * (excluding the language itself)
182
+ */
183
+ const namedsOf = (language: Language): M3Concept[] =>
184
+ allContaineds(language).filter(isINamed)
185
+
186
+
187
+ /**
188
+ * @return the key of the given {@link INamed named thing}.
189
+ */
190
+ const keyOf = <T extends IKeyed>({key}: T): LionWebKey =>
191
+ key
192
+
193
+
194
+ type ConcreteClassifier = Concept | Annotation
195
+
196
+
197
+ /**
198
+ * Determines whether the given {@link LanguageEntity metamodel element} is
199
+ * *concrete*, i.e. is instantiable.
200
+ */
201
+ const isConcrete = (thing: LanguageEntity): thing is ConcreteClassifier =>
202
+ (thing instanceof Concept && !thing.abstract) || (thing instanceof Annotation)
203
+
204
+ /**
205
+ * Determines whether the given {@link LanguageEntity metamodel element} is a {@link Concept concept}
206
+ * which is a partition.
207
+ */
208
+ const isPartition = (thing: LanguageEntity): thing is Concept =>
209
+ thing instanceof Concept && thing.partition
210
+
211
+ /**
212
+ * @return an array of {@link Classifier classifiers} that it **directly** inherits from.
213
+ */
214
+ const inheritsDirectlyFrom = (classifier: Classifier): Classifier[] => {
215
+ if (classifier instanceof Concept || classifier instanceof Annotation) {
216
+ return [
217
+ ...(
218
+ isRef(classifier.extends)
219
+ ? [classifier.extends as Classifier]
220
+ : []
221
+ ),
222
+ ...classifier.implements
223
+ ]
224
+ }
225
+ if (classifier instanceof Interface) {
226
+ return classifier.extends
227
+ }
228
+ throw new Error(`classifier type ${typeof classifier} not handled`)
229
+ }
230
+
231
+ /**
232
+ * Alias for {@link inheritsDirectlyFrom}, kept for backward compatibility, and to be deprecated and removed later.
233
+ */
234
+ const inheritsFrom = inheritsDirectlyFrom;
235
+
236
+ /**
237
+ * @return an array that's either an inheritance cycle, or empty (meaning: no inheritance cycle).
238
+ */
239
+ const inheritanceCycleWith = (classifier: Classifier) =>
240
+ cycleWith(classifier, inheritsDirectlyFrom)
241
+
242
+ /**
243
+ * Alias for {@link inheritanceCycleWith}, kept for backward compatibility, and to be deprecated and removed later.
244
+ */
245
+ const inheritedCycleWith = inheritanceCycleWith;
246
+
247
+ /**
248
+ * @return *all* super types (through `extends` or `implements`) of the given {@link Classifier classifier}.
249
+ */
250
+ const allSuperTypesOf = (classifier: Classifier): Classifier[] =>
251
+ flatMapNonCyclingFollowing(inheritsDirectlyFrom, inheritsDirectlyFrom)(classifier)
252
+
253
+
254
+ /**
255
+ * @return *all* {@link Feature features} of the given {@link Classifier classifier},
256
+ * including the inherited ones.
257
+ */
258
+ const allFeaturesOf = (classifier: Classifier): Feature[] =>
259
+ flatMapNonCyclingFollowing((ci) => ci.features, inheritsDirectlyFrom)(classifier)
260
+
261
+
262
+ /**
263
+ * Determines whether the given {@link LanguageEntity language element} is an {@link Enumeration enumeration}.
264
+ */
265
+ const isEnumeration = (element: LanguageEntity): element is Enumeration =>
266
+ element instanceof Enumeration
267
+
268
+
269
+ /**
270
+ * @return a function that looks up a classifier from the given {@link Language language} by its ID.
271
+ */
272
+ const idBasedClassifierDeducerFor = (language: Language) =>
273
+ (id: LionWebId) =>
274
+ language.entities.find((element) => element instanceof Classifier && element.id === id) as Classifier
275
+
276
+ /**
277
+ * @return a function that looks up a classifier from the given {@link Language language} by its name.
278
+ */
279
+ const nameBasedClassifierDeducerFor = (language: Language) =>
280
+ (name: string) =>
281
+ language.entities.find((element) => element instanceof Classifier && element.name === name) as Classifier
282
+
283
+
284
+ /**
285
+ * @return a {@link ClassifierDeducer classifier deducer} that deduces the classifier of nodes by looking up
286
+ * the classifier in the given {@link Language language} by matching the node object's class name to classifiers' names.
287
+ * **Note** that this is not reliable when using bundlers who might minimize class names, and such.
288
+ */
289
+ const classBasedClassifierDeducerFor = <NT extends Node>(language: Language): ClassifierDeducer<NT> =>
290
+ (node: NT) => nameBasedClassifierDeducerFor(language)(node.constructor.name)
291
+
292
+
293
+ /**
294
+ * @return a {@link ClassifierDeducer classifier deducer} that deduces the classifier of nodes that implement {@link IMetaTyped}
295
+ * by looking up the classifier in the given {@link Language language} by matching the result of {@link IMetaTyped#metaType}
296
+ * to classifiers' names.
297
+ */
298
+ const metaTypedBasedClassifierDeducerFor = <NT extends Node & IMetaTyped>(language: Language): ClassifierDeducer<NT> =>
299
+ (node: NT) => nameBasedClassifierDeducerFor(language)(node.metaType())
300
+
301
+
302
+ /**
303
+ * @return all {@link Concept concepts} defined in the given {@link Language language}.
304
+ */
305
+ const conceptsOf = (language: Language): Concept[] =>
306
+ language.entities.filter((entity) => entity instanceof Concept) as Concept[]
307
+
308
+
309
+ const isInstantiableClassifier = (entity: LanguageEntity): boolean =>
310
+ entity instanceof Annotation
311
+ || (entity instanceof Concept && !entity.abstract)
312
+ // leaves out Interface and Concept { abstract: true }
313
+
314
+ /**
315
+ * @return an array of all instantiable {@link Classifier classifiers} of the given {@link Language language}.
316
+ */
317
+ const instantiableClassifiersOf = (language: Language): Classifier[] =>
318
+ language.entities.filter(isInstantiableClassifier) as Classifier[]
319
+
320
+
321
+ /**
322
+ * @return whether the two given {@link Classifiers classifiers} are the same (/identical by meta-pointer).
323
+ */
324
+ const areSameClassifiers = (left: Classifier, right: Classifier) =>
325
+ (left === right) || (
326
+ areSameLanguages(left.language, right.language) && left.key === right.key
327
+ )
328
+
329
+ /**
330
+ * @return whether the two given {@link Language languages} are the same (/identical by meta-pointer).
331
+ */
332
+ const areSameLanguages = (left: Language, right: Language) =>
333
+ (left === right) || (
334
+ left.key === right.key && left.version === right.version
335
+ )
336
+
337
+
338
+ export {
339
+ allContaineds,
340
+ allFeaturesOf,
341
+ allSuperTypesOf,
342
+ areSameClassifiers,
343
+ areSameLanguages,
344
+ classBasedClassifierDeducerFor,
345
+ concatenateNamesOf,
346
+ conceptsOf,
347
+ containmentChain,
348
+ directlyContaineds,
349
+ featureMetaType,
350
+ flatMap,
351
+ idBasedClassifierDeducerFor,
352
+ inheritanceCycleWith,
353
+ inheritedCycleWith,
354
+ inheritsFrom,
355
+ inheritsDirectlyFrom,
356
+ instantiableClassifiersOf,
357
+ isConcrete,
358
+ isContainment,
359
+ isEnumeration,
360
+ isMultiple,
361
+ isPartition,
362
+ isProperty,
363
+ isReference,
364
+ keyOf,
365
+ metaTypedBasedClassifierDeducerFor,
366
+ nameBasedClassifierDeducerFor,
367
+ nameOf,
368
+ namedsOf,
369
+ nonRelationalFeatures,
370
+ relations,
371
+ relationsOf,
372
+ type,
373
+ qualifiedNameOf
374
+ }
375
+
376
+ export type {
377
+ FeatureMetaType
378
+ }
379
+
@@ -0,0 +1,12 @@
1
+ export * from "./builtins.js"
2
+ export * from "./constraints.js"
3
+ export * from "./deserializer.js"
4
+ export * from "./facade.js"
5
+ export * from "./factory.js"
6
+ export * from "./feature-resolvers.js"
7
+ export * from "./functions.js"
8
+ export * from "./lioncore.js"
9
+ export * from "./reference-checker.js"
10
+ export * from "./serializer.js"
11
+ export * from "./symbol-table.js"
12
+ export * from "./types.js"