typir
Version:
General purpose type checking library
85 lines • 3.47 kB
JavaScript
/******************************************************************************
* Copyright 2024 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import { assertTrue } from '../../utils/utils.js';
import { MultiplicityType } from './multiplicity-type.js';
export const MULTIPLICITY_UNLIMITED = -1;
export const MultiplicityKindName = 'MultiplicityTypeKind';
/**
* Types of this kind constrain a type with lower bound and upper bound,
* e.g. ConstrainedType[1..*] or ConstrainedType[2..4].
*/
export class MultiplicityKind {
constructor(services, options) {
this.options = this.collectOptions(options);
this.$name = this.options.$name;
this.services = services;
this.services.infrastructure.Kinds.register(this);
}
collectOptions(options) {
return Object.assign({
// the default values:
$name: MultiplicityKindName, symbolForUnlimited: '*' }, options);
}
getMultiplicityType(typeDetails) {
const key = this.calculateIdentifier(typeDetails);
return this.services.infrastructure.Graph.getType(key);
}
createMultiplicityType(typeDetails) {
// check input
assertTrue(this.getMultiplicityType(typeDetails) === undefined);
if (!this.checkBounds(typeDetails.lowerBound, typeDetails.upperBound)) {
throw new Error();
}
// create the type with multiplicities
const typeWithMultiplicity = new MultiplicityType(this, this.calculateIdentifier(typeDetails), typeDetails);
this.services.infrastructure.Graph.addNode(typeWithMultiplicity);
this.registerInferenceRules(typeDetails, typeWithMultiplicity);
return typeWithMultiplicity;
}
registerInferenceRules(_typeDetails, _typeWithMultiplicity) {
// TODO
}
calculateIdentifier(typeDetails) {
return `${typeDetails.constrainedType.getIdentifier()}${this.printRange(typeDetails.lowerBound, typeDetails.upperBound)}`;
}
checkBounds(lowerBound, upperBound) {
// check range
if (lowerBound < 0 || upperBound < -1) {
return false;
}
// upper bound must not be lower than the lower bound
if (0 <= lowerBound && 0 <= upperBound && lowerBound > upperBound) {
return false;
}
return true;
}
printRange(lowerBound, upperBound) {
if (lowerBound === upperBound || (lowerBound === 0 && upperBound === MULTIPLICITY_UNLIMITED)) {
// [2..2] => [2], [0..*] => [*]
return `[${this.printBound(upperBound)}]`;
}
else {
// e.g. [1..3], [1..*]
return `[${this.printBound(lowerBound)}..${this.printBound(upperBound)}]`;
}
}
printBound(bound) {
return bound === MULTIPLICITY_UNLIMITED ? this.options.symbolForUnlimited : `${bound}`;
}
isBoundGreaterEquals(leftBound, rightBound) {
if (leftBound === MULTIPLICITY_UNLIMITED) {
return true;
}
if (rightBound === MULTIPLICITY_UNLIMITED) {
return false;
}
return leftBound >= rightBound;
}
}
export function isMultiplicityKind(kind) {
return kind instanceof MultiplicityKind;
}
//# sourceMappingURL=multiplicity-kind.js.map