typir
Version:
General purpose type checking library
129 lines • 6.57 kB
TypeScript
/******************************************************************************
* 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 { GraphAlgorithms } from '../graph/graph-algorithms.js';
import { TypeEdge } from '../graph/type-edge.js';
import { TypeGraph } from '../graph/type-graph.js';
import { Type } from '../graph/type-node.js';
import { TypirSpecifics, TypirServices } from '../typir.js';
import { TypeEquality } from './equality.js';
/**
* Describes the possible conversion modes.
*
* IMPLICIT means coercion,
* e.g. in "3 + 'three'" the int value 3 is implicitly converted to the string value '3'.
* By default, this relation is transitive (this could be configured).
* Cycles are not allowed for this relation.
*
* EXPLICIT means casting,
* e.g. in "myValue as MyType" the value stored in the variable myValue is explicitly casted to MyType.
* By default, this relation is not transitive (this could be configured).
* Cycles are allowed for this relation.
*/
export type ConversionModeForSpecification =
/** The conversion is implicitly possible. In this case, the explicit conversion is possible as well (IMPLICIT => EXPLICIT). */
'IMPLICIT_EXPLICIT' |
/** The conversion is only explicitly possible */
'EXPLICIT';
export type ConversionMode = ConversionModeForSpecification |
/** no conversion possible at all (this is the default mode) */
'NONE' |
/** a type is always self-convertible to itself (implicitly or explicitly), in this case no conversion is necessary */
'SELF';
/**
* Manages conversions between different types.
* A conversion is a directed relationship between two types.
* If a source type can be converted to a target type, the source type could be assignable to the target type (depending on the conversion mode: target := source).
*/
export interface TypeConversion {
/**
* Defines the conversion relationship between two types.
* @param from the from/source type
* @param to the to/target type
* @param mode the desired conversion relationship between the two given types
* @throws an error, if a cycle was introduced
*/
markAsConvertible(from: Type, to: Type, mode: ConversionModeForSpecification): void;
/**
* Identifies the existing conversion relationship between two given types.
* @param from the from/source type
* @param to the to/target type
* @returns the existing conversion relationship between the two given types
*/
getConversion(from: Type, to: Type): ConversionMode;
/**
* Checks whether the given two types are implicitly (or explicitly) convertible.
* @param from the from/source type
* @param to the to/target type
* @returns true if the conversion is possible, false otherwise
*/
isImplicitExplicitConvertible(from: Type, to: Type): boolean;
/**
* Checks whether the given two types are (only) explicitly convertible.
* @param from the from/source type
* @param to the to/target type
* @returns true if the conversion is possible, false otherwise
*/
isExplicitConvertible(from: Type, to: Type): boolean;
/**
* Checks whether the given two types are not convertible (and are not equals).
* @param from the from/source type
* @param to the to/target type
* @returns true if the conversion is not possible, false otherwise
*/
isNoneConvertible(from: Type, to: Type): boolean;
/**
* Checks whether the given two types are (implicitly or explicitly) convertible, since they are equal.
* @param from the from/source type
* @param to the to/target type
* @returns true if the types are equal, false otherwise
*/
isSelfConvertible(from: Type, to: Type): boolean;
/**
* Checks whether the given two types are convertible (EXPLICIT or IMPLICIT or SELF).
* @param from the from/source type
* @param to the to/target type
* @returns true if the implicit or explicit conversion is possible or the types are equal, false otherwise
*/
isConvertible(from: Type, to: Type): boolean;
/**
* Returns all other types to which the given type can be recursively converted.
* @param from the source type, which is convertible to the returned types
* @param mode only conversion rules with the given conversion mode are considered
* @returns the set of recursively reachable types for conversion ("conversion targets")
*/
getConvertibleTo(from: Type, mode: ConversionModeForSpecification): Set<Type>;
}
/**
* Design decisions:
* - Do not store transitive relationships, since they must be removed, when types of the corresponding path are removed!
* - Store only EXPLICIT and IMPLICIT relationships, since this is not required, missing edges means NONE/SELF.
*/
export declare class DefaultTypeConversion<Specifics extends TypirSpecifics> implements TypeConversion {
protected readonly equality: TypeEquality;
protected readonly graph: TypeGraph;
protected readonly algorithms: GraphAlgorithms;
constructor(services: TypirServices<Specifics>);
markAsConvertible(from: Type, to: Type, mode: ConversionModeForSpecification): void;
protected isTransitive(mode: ConversionModeForSpecification): boolean;
getConversion(from: Type, to: Type): ConversionMode;
protected collectReachableTypes(from: Type, mode: ConversionModeForSpecification): Set<Type>;
protected existsEdgePath(from: Type, to: Type, mode: ConversionModeForSpecification): boolean;
protected isTransitivelyConvertable(from: Type, to: Type, mode: ConversionModeForSpecification): boolean;
isImplicitExplicitConvertible(from: Type, to: Type): boolean;
isExplicitConvertible(from: Type, to: Type): boolean;
isNoneConvertible(from: Type, to: Type): boolean;
isSelfConvertible(from: Type, to: Type): boolean;
isConvertible(from: Type, to: Type): boolean;
protected getConversionEdge(from: Type, to: Type): ConversionEdge | undefined;
getConvertibleTo(from: Type, mode: ConversionModeForSpecification): Set<Type>;
}
export interface ConversionEdge extends TypeEdge {
readonly $relation: 'ConversionEdge';
mode: ConversionMode;
}
export declare const ConversionEdge = "ConversionEdge";
export declare function isConversionEdge(edge: unknown): edge is ConversionEdge;
//# sourceMappingURL=conversion.d.ts.map