This commit is contained in:
163
src/TraitExpression.ts
Normal file
163
src/TraitExpression.ts
Normal 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)
|
||||
)
|
||||
Reference in New Issue
Block a user