0.1.0 #1
@@ -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)
|
|
||||||
|
|||||||
134
src/TraitExpressionBuilder.ts
Normal file
134
src/TraitExpressionBuilder.ts
Normal 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)
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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<{}, []>,
|
||||||
> {
|
> {
|
||||||
|
|||||||
Reference in New Issue
Block a user