import { Call, Fn, Pipe, Tuples } from "hotscript" import { AbstractClass, Class, Opaque } from "type-fest" import { AbstractTag, Trait, TraitApplierSuperTag } from "." import { ExtendFn, SimplifyFn, StaticMembersFn } from "./util" export class TraitExpressionNullSuperclass {} export class TraitExpression< Superclass extends AbstractClass<{}>, OwnTraits extends Trait[], AllTraits extends Trait[], > { constructor( readonly superclass: Superclass, readonly ownTraits: OwnTraits, readonly allTraits: AllTraits, ) {} get extends(): ( AbstractClass< Pipe<[ InstanceType, ...Call, OwnTraits>, ], [ ExtendFn, SimplifyFn, ]>, ConstructorParameters > & Pipe<[ Superclass, ...Call, OwnTraits>, ], [ Tuples.Map, ExtendFn, SimplifyFn, ]> ) { return this.allTraits.reduce( (previous, trait) => trait.apply(previous), this.superclass as Opaque, ) as any } subtrait< SubtraitAbstract extends {}, SubtraitImplWithAbstract extends Class<{}>, >( abstract: ( abstract: Pipe ) => Opaque, // impl: () ) { } } export namespace TraitExpression { export type Superclass = ( T extends TraitExpression ? Superclass : never ) export interface SuperclassFn extends Fn { return: TraitExpression.Superclass } export type OwnTraits = ( T extends TraitExpression ? OwnTraits : never ) export interface OwnTraitsFn extends Fn { return: TraitExpression.OwnTraits } export type AllTraits = ( T extends TraitExpression ? AllTraits : never ) export interface AllTraitsFn extends Fn { return: TraitExpression.AllTraits } } export type Implements> = ( Exp extends TraitExpression ? Pipe, ExtendFn, SimplifyFn, ]> : never ) export const emptyTraitExpression = new TraitExpression( TraitExpressionNullSuperclass, [] as const, [] as const, )