Trait refactoring
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Julien Valverdé
2024-02-04 00:26:09 +01:00
parent 8d29d9ba94
commit 0ff6b7896e
3 changed files with 46 additions and 69 deletions

163
src/TraitExpression.ts Normal file
View File

@@ -0,0 +1,163 @@
import { Call, Pipe, Tuples } from "hotscript"
import { AbstractClass, Class, Opaque } from "type-fest"
import { AbstractTag, Trait, TraitAbstractMembersFn, TraitApplierSuperTag, TraitImplClassFn, TraitImplInstanceFn } from "."
import { ExtendFn, ExtendableFn, SimplifyFn, StaticMembersFn } from "./util"
export class TraitExpression<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any, any>[],
> {
constructor(
readonly superclass: Super,
readonly traits: Traits,
) {}
get extends(): (
AbstractClass<
Pipe<[
InstanceType<Super>,
...Call<Tuples.Map<TraitImplInstanceFn>, Traits>,
], [
ExtendFn,
SimplifyFn,
]>,
ConstructorParameters<Super>
> &
Pipe<[
Super,
...Call<Tuples.Map<TraitImplClassFn>, Traits>,
], [
Tuples.Map<StaticMembersFn>,
ExtendFn,
SimplifyFn,
]>
) {
return this.traits.reduce(
(previous, trait) => trait.apply(previous),
this.superclass as Opaque<Super, TraitApplierSuperTag>,
) as any
}
subtrait<
SubtraitAbstract extends {},
SubtraitImplWithAbstract extends Class<{}>,
>(
abstract: (
abstract: Pipe<Traits, [
Tuples.Map<TraitAbstractMembersFn>,
SimplifyFn,
]>
) => Opaque<SubtraitAbstract, AbstractTag>,
// impl: ()
) {
}
}
export type Implements<Exp extends TraitExpression<any, any>> = (
Exp extends TraitExpression<any, infer Traits>
? Pipe<Traits, [
Tuples.Map<TraitAbstractMembersFn>,
ExtendFn,
SimplifyFn,
]>
: never
)
class TraitExpressionBuilder<
Super extends AbstractClass<{}>,
Traits extends Trait<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>[]
>(...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>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitAbstractMembersFn>, Traits>,
]>
)
type ImplInstanceExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any>[],
> = (
Call<ExtendableFn, [
InstanceType<Super>,
...Call<Tuples.Map<TraitImplInstanceFn>, Traits>,
]>
)
type ImplStaticMembersExtendable<
Super extends AbstractClass<{}>,
Traits extends Trait<any, any>[],
> = (
Pipe<[
Super,
...Call<Tuples.Map<TraitImplClassFn>, Traits>,
], [
Tuples.Map<StaticMembersFn>,
ExtendableFn,
]>
)
type GetTraitExpression<
Super extends AbstractClass<{}>,
Traits extends Trait<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 class NullTraitExpressionSuperclass {}
export const expression = new TraitExpressionBuilder(
new TraitExpression(NullTraitExpressionSuperclass, [] as const)
)