TraitExpressionBuilder work
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Julien Valverdé
2024-02-04 04:26:20 +01:00
parent 2d32e4807d
commit bb5e85573c
4 changed files with 149 additions and 98 deletions

View File

@@ -8,18 +8,20 @@ export class TraitExpressionNullSuperclass {}
export class TraitExpression< export class TraitExpression<
Super extends AbstractClass<{}>, Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[], OwnTraits extends Trait<any, any, any>[],
AllTraits extends Trait<any, any, any>[],
> { > {
constructor( constructor(
readonly superclass: Super, readonly superclass: Super,
readonly traits: Traits, readonly ownTraits: OwnTraits,
readonly allTraits: AllTraits,
) {} ) {}
get extends(): ( get extends(): (
AbstractClass< AbstractClass<
Pipe<[ Pipe<[
InstanceType<Super>, InstanceType<Super>,
...Call<Tuples.Map<TraitOwnImplInstanceFn>, Traits>, ...Call<Tuples.Map<TraitOwnImplInstanceFn>, OwnTraits>,
], [ ], [
ExtendFn, ExtendFn,
SimplifyFn, SimplifyFn,
@@ -30,14 +32,14 @@ export class TraitExpression<
Pipe<[ Pipe<[
Super, Super,
...Call<Tuples.Map<TraitOwnImplClassFn>, Traits>, ...Call<Tuples.Map<TraitOwnImplClassFn>, OwnTraits>,
], [ ], [
Tuples.Map<StaticMembersFn>, Tuples.Map<StaticMembersFn>,
ExtendFn, ExtendFn,
SimplifyFn, SimplifyFn,
]> ]>
) { ) {
return this.traits.reduce( return this.ownTraits.reduce(
(previous, trait) => trait.apply(previous), (previous, trait) => trait.apply(previous),
this.superclass as Opaque<Super, TraitApplierSuperTag>, this.superclass as Opaque<Super, TraitApplierSuperTag>,
) as any ) as any
@@ -60,7 +62,11 @@ export class TraitExpression<
} }
} }
export const emptyTraitExpression = new TraitExpression(TraitExpressionNullSuperclass, [] as const) export const emptyTraitExpression = new TraitExpression(
TraitExpressionNullSuperclass,
[] as const,
[] as const,
)
interface PrependTraitSupertraitsFn extends Fn { interface PrependTraitSupertraitsFn extends Fn {
return: this["arg0"] extends Trait<any, any, any> return: this["arg0"] extends Trait<any, any, any>
@@ -95,93 +101,3 @@ export type Implements<Exp extends TraitExpression<any, any>> = (
]> ]>
: never : never
) )
class TraitExpressionBuilder<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> {
constructor(public expression: TraitExpression<Super, Traits>) {}
extends<
NewSuper extends AbstractClass<any>
>(superclass: NewSuper) {
return new TraitExpressionBuilder(
new TraitExpression(
superclass,
this.expression.traits,
)
)
}
expresses<
AppendTraits extends Trait<any, any, any>[]
>(...traits: AppendTraits) {
return new TraitExpressionBuilder(
new TraitExpression(
this.expression.superclass,
[...this.expression.traits, ...traits] as const,
)
)
}
get() {
return this.expression as GetTraitExpression<Super, Traits>
}
then<V>(fn: (expression: ReturnType<typeof this.get>) => V): V {
return fn(this.get())
}
}
type AbstractMembersExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitOwnAbstractFn>, Traits>,
]>
)
type ImplInstanceExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitOwnImplInstanceFn>, Traits>,
]>
)
type ImplStaticMembersExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Pipe<[
Super,
...Call<Tuples.Map<TraitOwnImplClassFn>, Traits>,
], [
Tuples.Map<StaticMembersFn>,
ExtendableFn,
]>
)
type GetTraitExpression<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Call<Tuples.IsEmpty, Traits> extends true
? "Cannot express an empty list of traits."
: AbstractMembersExtendable<Super, Traits> extends false
? "Type conflict between the traits abstract members and/or the superclass instance."
: ImplInstanceExtendable<Super, Traits> extends false
? "Type conflict between the traits implementation instances and/or the superclass instance."
: ImplStaticMembersExtendable<Super, Traits> extends false
? "Type conflict between the traits implementation static members and/or the superclass static members."
: TraitExpression<Super, Traits>
)
export const expression = new TraitExpressionBuilder(emptyTraitExpression)

View File

@@ -0,0 +1,134 @@
import { Call, Fn, Pipe, Tuples } from "hotscript"
import { AbstractClass } from "type-fest"
import { Trait, TraitExpression, TraitOwnAbstractFn, TraitOwnImplClassFn, TraitOwnImplInstanceFn, TraitSupertraitsFn, emptyTraitExpression } from "."
import { ExtendableFn, StaticMembersFn } from "./util"
class TraitExpressionBuilder<
Super extends AbstractClass<{}>,
OwnTraits extends Trait<any, any, any>[],
AllTraits extends Trait<any, any, any>[],
> {
constructor(public expression: TraitExpression<Super, OwnTraits, AllTraits>) {}
extends<
NewSuper extends AbstractClass<any>
>(superclass: NewSuper) {
return new TraitExpressionBuilder(
new TraitExpression(
superclass,
this.expression.ownTraits,
this.expression.allTraits,
)
)
}
expresses<
Traits extends Trait<any, any, any>[]
>(
...traits: Traits
) {
return new TraitExpressionBuilder(
new TraitExpression(
this.expression.superclass,
[...this.expression.ownTraits, ...traits] as const,
[
...this.expression.allTraits,
...this.spreadSupertraits(traits) as SpreadTraitsHierarchy<Traits>,
] as const,
)
)
}
private spreadSupertraits<
Traits extends Trait<
TraitExpression<any, any, Trait<any, any, any>[]>,
any,
any
>[]
>(
traits: Traits
) {
return traits.flatMap(trait => [
...trait.superExpression.allTraits,
trait,
])
}
get() {
return this.expression as GetTraitExpression<Super, OwnTraits, AllTraits>
}
then<V>(fn: (expression: ReturnType<typeof this.get>) => V): V {
return fn(this.get())
}
}
type SpreadTraitsHierarchy<Traits extends Trait<any, any, any>[]> = (
Call<
Tuples.FlatMap<PrependTraitSupertraitsFn>,
Traits
>
)
interface PrependTraitSupertraitsFn extends Fn {
return: this["arg0"] extends Trait<any, any, any>
? [
...Call<TraitSupertraitsFn, this["arg0"]>,
this["arg0"],
]
: never
}
type AbstractMembersExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitOwnAbstractFn>, Traits>,
]>
)
type ImplInstanceExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitOwnImplInstanceFn>, Traits>,
]>
)
type ImplStaticMembersExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> = (
Pipe<[
Super,
...Call<Tuples.Map<TraitOwnImplClassFn>, Traits>,
], [
Tuples.Map<StaticMembersFn>,
ExtendableFn,
]>
)
type GetTraitExpression<
Super extends AbstractClass<{}>,
OwnTraits extends Trait<any, any, any>[],
AllTraits extends Trait<any, any, any>[],
> = (
Call<Tuples.IsEmpty, OwnTraits> extends true
? "Cannot express an empty list of traits."
: AbstractMembersExtendable<Super, OwnTraits> extends false
? "Type conflict between the traits abstract members and/or the superclass instance."
: ImplInstanceExtendable<Super, OwnTraits> extends false
? "Type conflict between the traits implementation instances and/or the superclass instance."
: ImplStaticMembersExtendable<Super, OwnTraits> extends false
? "Type conflict between the traits implementation static members and/or the superclass static members."
: TraitExpression<Super, OwnTraits, AllTraits>
)
export const expression = new TraitExpressionBuilder(emptyTraitExpression)

View File

@@ -1,3 +1,4 @@
export * from "./TraitExpression" export * from "./TraitExpression"
export * from "./TraitExpressionBuilder"
export * from "./abstract" export * from "./abstract"
export * from "./trait" export * from "./trait"

View File

@@ -28,7 +28,7 @@ type RemoveAbstractFromImplClass<
export class Trait< export class Trait<
Super extends TraitExpression<typeof TraitExpressionNullSuperclass, any>, Super extends TraitExpression<typeof TraitExpressionNullSuperclass, Trait<any, any, any>[], Trait<any, any, any>[]>,
Abstract extends {}, Abstract extends {},
ImplClass extends Class<{}, []>, ImplClass extends Class<{}, []>,
> { > {