This commit is contained in:
Mark Probst 2018-04-13 21:07:52 -07:00
Родитель d903bd0ccb
Коммит fb2375ba17
2 изменённых файлов: 64 добавлений и 84 удалений

Просмотреть файл

@ -12,7 +12,7 @@ import { ErrorMessage, messageAssert } from "./Messages";
export type PrimitiveStringTypeKind = "string" | "date" | "time" | "date-time";
export type PrimitiveTypeKind = "none" | "any" | "null" | "bool" | "integer" | "double" | PrimitiveStringTypeKind;
export type NamedTypeKind = "class" | "enum" | "union";
export type TypeKind = PrimitiveTypeKind | NamedTypeKind | "array" | "object" | "map" | "intersection" | "transformed";
export type TypeKind = PrimitiveTypeKind | NamedTypeKind | "array" | "object" | "map" | "intersection";
export function isPrimitiveStringTypeKind(kind: TypeKind): kind is PrimitiveStringTypeKind {
return kind === "string" || kind === "date" || kind === "time" || kind === "date-time";
@ -43,10 +43,41 @@ function orderedSetUnion<T>(sets: OrderedSet<OrderedSet<T>>): OrderedSet<T> {
return setArray[0].union(...setArray.slice(1));
}
export abstract class Type {
constructor(readonly typeRef: TypeRef, readonly kind: TypeKind) {}
export type Transformer = "parseInteger";
abstract get children(): OrderedSet<Type>;
export class Transformation {
constructor(readonly transformer: Transformer, private _targetRef?: TypeRef) {}
private getTargetRef(): TypeRef {
if (this._targetRef === undefined) {
return panic("Target type accessed before it was set");
}
return this._targetRef;
}
get targetType(): Type {
return this.getTargetRef().deref()[0];
}
}
export abstract class Type {
constructor(readonly typeRef: TypeRef, readonly kind: TypeKind, private _transformation?: Transformation) {}
setTransformation(transformation: Transformation): void {
assert(this._transformation === undefined, "Tried to set transformation twice");
this._transformation = transformation;
}
get transformation(): Transformation | undefined {
return this._transformation;
}
get children(): OrderedSet<Type> {
if (this._transformation === undefined) {
return OrderedSet();
}
return OrderedSet([this._transformation.targetType]);
}
directlyReachableTypes<T>(setForType: (t: Type) => OrderedSet<T> | null): OrderedSet<T> {
const set = setForType(this);
@ -72,7 +103,16 @@ export abstract class Type {
abstract get isNullable(): boolean;
abstract isPrimitive(): this is PrimitiveType;
abstract reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void;
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
const tform = this._transformation;
if (tform === undefined) {
builder.setTransformationAndFinish();
}
builder.setTransformationAndFinish(
new Transformation(tform.transformer, builder.reconstitute(tform.targetType.typeRef))
);
}
get debugPrintKind(): string {
return this.kind;
@ -89,7 +129,18 @@ export abstract class Type {
// This will only ever be called when `this` and `other` are not
// equal, but `this.kind === other.kind`.
protected abstract structuralEqualityStep(other: Type, queue: (a: Type, b: Type) => boolean): boolean;
protected structuralEqualityStep(other: Type, queue: (a: Type, b: Type) => boolean): boolean {
if (this._transformation !== undefined && other._transformation !== undefined) {
if (this._transformation.transformer !== other._transformation.transformer) {
return false;
}
return queue(this._transformation.targetType, other._transformation.targetType);
}
if ((this._transformation === undefined) !== (other._transformation === undefined)) {
return false;
}
return true;
}
structurallyCompatible(other: Type): boolean {
if (triviallyStructurallyCompatible(this, other)) return true;
@ -648,79 +699,3 @@ export class UnionType extends SetOperationType {
}
}
}
export type Transformer = "parseInteger";
export class TransformedType extends Type {
constructor(
typeRef: TypeRef,
readonly transformer: Transformer,
private _sourceRef?: TypeRef,
private _targetRef?: TypeRef
) {
super(typeRef, "transformed");
}
setTypes(sourceRef: TypeRef, targetRef: TypeRef): void {
messageAssert(
this._sourceRef === undefined && this._targetRef === undefined,
"Can only set transformed type source and target once"
);
this._sourceRef = sourceRef;
this._targetRef = targetRef;
}
private getSourceRef(): TypeRef {
if (this._sourceRef === undefined) {
return panic("Source type accessed before it was set");
}
return this._sourceRef;
}
get sourceType(): Type {
return this.getSourceRef().deref()[0];
}
private getTargetRef(): TypeRef {
if (this._targetRef === undefined) {
return panic("Target type accessed before it was set");
}
return this._targetRef;
}
get targetType(): Type {
return this.getTargetRef().deref()[0];
}
get children(): OrderedSet<Type> {
return OrderedSet([this.sourceType, this.targetType]);
}
get isNullable(): boolean {
return this.targetType.isNullable;
}
isPrimitive(): this is PrimitiveType {
return false;
}
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
const sourceRef = this.getSourceRef();
const targetRef = this.getTargetRef();
const maybeSource = builder.lookup(sourceRef);
const maybeTarget = builder.lookup(targetRef);
if (maybeSource === undefined || maybeTarget === undefined) {
builder.getUniqueTransformedType(this.transformer);
builder.setTransformedTypeTypes(builder.reconstitute(sourceRef), builder.reconstitute(targetRef));
} else {
builder.getTransformedType(this.transformer, maybeSource, maybeTarget);
}
}
protected structuralEqualityStep(other: TransformedType, queue: (a: Type, b: Type) => boolean): boolean {
if (this.transformer !== other.transformer) return false;
return queue(this.sourceType, other.sourceType) && queue(this.targetType, other.targetType);
}
}

Просмотреть файл

@ -16,8 +16,8 @@ import {
ClassProperty,
IntersectionType,
ObjectType,
TransformedType,
Transformer
Transformer,
Transformation
} from "./Type";
import { removeNullFromUnion } from "./TypeUtils";
import { TypeGraph } from "./TypeGraph";
@ -454,6 +454,11 @@ export class TypeBuilder {
}
}
setTransformation(ref: TypeRef, transformation: Transformation): void {
const type = ref.deref()[0];
type.setTransformation(transformation);
}
setLostTypeAttributes(): void {
return;
}