<commit_before>import structs/[ArrayList, List, HashMap]
import ../frontend/[Token, BuildParams]
import ../io/TabbedWriter
import Expression, Type, Visitor, Declaration, VariableDecl, ClassDecl,
    FunctionDecl, FunctionCall, Module, VariableAccess, Node,
    InterfaceImpl, Version, EnumDecl, BaseType, FuncType, OperatorDecl,
    Addon, Cast
import tinker/[Resolver, Response, Trail, Errors]

/**
   A type declaration - a class, a cover, an interface, an enum..

   A type declaration has a name, optionally an extern-name,
   optional generic type arguments, but also variables and functions.

   This is a base class containing many useful variables and methods, but
   the most interesting parts are in its subclasses ClassDecl, CoverDecl,
   InterfaceDecl, and EnumDecl.

   :author: <NAME> (nddrylliog)
 */
TypeDecl: abstract class extends Declaration {

    name = "", externName = null, doc = "" : String

    // generic type args, e.g. the T in List: class <T>
    typeArgs := ArrayList<VariableDecl> new()

    // internal state variables
    hasCheckedInheritance := false
    hasCheckedAbstract := false

    variables := HashMap<String, VariableDecl> new()

    // for classes, functions are contained in the meta-class.
    // for covers, they are directly in the cover decl.
    functions := HashMap<String, FunctionDecl> new()

    // interface types that this type implements
    interfaceTypes := ArrayList<Type> new()
    // InterfaceImpl is used for storing
    interfaceDecls := ArrayList<InterfaceImpl> new()

    thisDecl, thisRefDecl: VariableDecl

    instanceType: Type
    type: Type
    superType: Type = null

    module: Module = null

    isMeta := false
    meta : ClassDecl = null
    nonMeta : TypeDecl = null

    verzion: VersionSpec = null

    base: TypeDecl = null
    addons := ArrayList<Addon> new()

    _finishedGhosting := false

    // implicit conversions between types
    implicitConversions := ArrayList<OperatorDecl> new()

    init: func ~typeDeclNoSuper (=name, .token) {
        super(token)
        type = BaseType new("Class", token)
        instanceType = BaseType new(name, token)
        instanceType as BaseType ref = this
        thisDecl    = VariableDecl new(instanceType, "this", token)
        thisDecl owner = this
        thisRefDecl = VariableDecl new(ReferenceType new(instanceType, token), "this", token)
        thisRefDecl owner = this

        if(!isMeta) {
            meta = ClassDecl new(name + "Class", null, true, token)
            meta nonMeta = this
            meta thisDecl = this thisDecl
            meta setSuperType(BaseType new("Class", token))

            // if we access to "Dog", we access to an object of type "DogClass"
            type = meta getInstanceType()
            type as BaseType ref = meta
        }

        if(!isObjectClass()) {
            // by default, everyone inherits from object
            setSuperType(BaseType new("Object", token))
        }
    }

    clone: func -> This {
        // saving us a whole lot of trouble.
        Exception new(This, "Cloning a TypeDecl is unsupported") throw()
        null
    }

    debugCondition: inline func -> Bool {
        false
    }

    isAbstract: func -> Bool { false }

    init: func ~typeDecl (.name, .superType, .token) {
        init(name, token)
        setSuperType(superType)
    }

    writeSize: abstract func (w: TabbedWriter, instance: Bool)

    getBase: func -> TypeDecl {
        return isMeta ? base : getMeta() base
    }

    isAddon: func -> Bool { getBase() != null }

    getAddons: func -> ArrayList<Addon> {
        return isMeta ? getNonMeta() addons : addons
    }

    getFullName: func -> String {
        underName()
    }

    setSuperType: func(=superType) {
        if(!this isMeta && superType != null) {
            // TODO: there's probably a better way, but this works fine =)
            if(superType getName() == "Object" && name != "Class") {
                meta setSuperType(BaseType new("ClassClass", superType token))
            } else {
                meta setSuperType(BaseType new(superType getName() + "Class", superType token))
            }
        }
    }

    getSuperType: func -> Type { superType }

    addTypeArg: func (typeArg: VariableDecl) -> Bool {
        typeArg setOwner(this)
        getTypeArgs() add(typeArg)

        variables put(typeArg getName(), typeArg)
        true
    }

    isObjectClass: func -> Bool {
        name equals?("Object") || name equals?("ObjectClass")
    }

    isClassClass: func -> Bool {
        name equals?("Class") || name equals?("ClassClass")
    }

    isRootClass: func -> Bool {
        isObjectClass() || isClassClass()
    }

    addVariable: func (vDecl: VariableDecl) {
        if(vDecl isStatic() && !isMeta) {
            meta addVariable(vDecl)
        } else {
            variables put(vDecl name, vDecl)
            vDecl setOwner(this)
        }
    }

    addInterface: func (interfaceType: Type) {
        interfaceTypes add(interfaceType)
    }

    getInterfaceTypes: func -> List<Type>          { interfaceTypes }
    getInterfaceDecls: func -> List<InterfaceImpl> { interfaceDecls }

    hashName: static func (name, suffix: String) -> String {
        suffix ? "%s~%s" format(name toCString(), suffix toCString()) : name
    }

    hashName: static func ~fromFuncDecl (fDecl: FunctionDecl) -> String {
        This hashName(fDecl getName(), fDecl getSuffix())
    }

    addFunction: func (fDecl: FunctionDecl) {
        if(isMeta) {
            hash := hashName(fDecl)
            old := functions get(hash)
            if (old != null && fDecl getName() != "init") { /* init is an exception */
                if(old == fDecl) Exception new(This, "Replacing %s with %s, which is the same!" format (old getName() toCString(), fDecl getName() toCString())) throw()
                "redefinition of %s with %s (hash = %s, otherHash = %s)" printfln(old getName() toCString(), fDecl getName() toCString(), hash toCString(), hashName(old) toCString())
                token module params errorHandler onError(FunctionRedefinition new(old, fDecl))
                return
            }

            functions put(hash, fDecl)
            fDecl setOwner(getNonMeta())
        } else {
            meta addFunction(fDecl)
        }
    }

    removeFunction: func(fDecl: FunctionDecl) {
        if(isMeta) {
            functions remove(This hashName(fDecl))
        } else {
            meta removeFunction(fDecl)
        }
    }

    lookupFunction: func (fName, fSuffix: String) -> FunctionDecl {

        // quick lookup, if we're lucky (exact suffix or no suffix)
        fDecl : FunctionDecl = null
        fDecl = functions get(This hashName(fName, fSuffix))
        if(fDecl) return fDecl
<commit_msg>Die, debug code. Please? Thxalot.<commit_after>import structs/[ArrayList, List, HashMap]
import ../frontend/[Token, BuildParams]
import ../io/TabbedWriter
import Expression, Type, Visitor, Declaration, VariableDecl, ClassDecl,
    FunctionDecl, FunctionCall, Module, VariableAccess, Node,
    InterfaceImpl, Version, EnumDecl, BaseType, FuncType, OperatorDecl,
    Addon, Cast
import tinker/[Resolver, Response, Trail, Errors]

/**
   A type declaration - a class, a cover, an interface, an enum..

   A type declaration has a name, optionally an extern-name,
   optional generic type arguments, but also variables and functions.

   This is a base class containing many useful variables and methods, but
   the most interesting parts are in its subclasses ClassDecl, CoverDecl,
   InterfaceDecl, and EnumDecl.

   :author: <NAME> (nddrylliog)
 */
TypeDecl: abstract class extends Declaration {

    name = "", externName = null, doc = "" : String

    // generic type args, e.g. the T in List: class <T>
    typeArgs := ArrayList<VariableDecl> new()

    // internal state variables
    hasCheckedInheritance := false
    hasCheckedAbstract := false

    variables := HashMap<String, VariableDecl> new()

    // for classes, functions are contained in the meta-class.
    // for covers, they are directly in the cover decl.
    functions := HashMap<String, FunctionDecl> new()

    // interface types that this type implements
    interfaceTypes := ArrayList<Type> new()
    // InterfaceImpl is used for storing
    interfaceDecls := ArrayList<InterfaceImpl> new()

    thisDecl, thisRefDecl: VariableDecl

    instanceType: Type
    type: Type
    superType: Type = null

    module: Module = null

    isMeta := false
    meta : ClassDecl = null
    nonMeta : TypeDecl = null

    verzion: VersionSpec = null

    base: TypeDecl = null
    addons := ArrayList<Addon> new()

    _finishedGhosting := false

    // implicit conversions between types
    implicitConversions := ArrayList<OperatorDecl> new()

    init: func ~typeDeclNoSuper (=name, .token) {
        super(token)
        type = BaseType new("Class", token)
        instanceType = BaseType new(name, token)
        instanceType as BaseType ref = this
        thisDecl    = VariableDecl new(instanceType, "this", token)
        thisDecl owner = this
        thisRefDecl = VariableDecl new(ReferenceType new(instanceType, token), "this", token)
        thisRefDecl owner = this

        if(!isMeta) {
            meta = ClassDecl new(name + "Class", null, true, token)
            meta nonMeta = this
            meta thisDecl = this thisDecl
            meta setSuperType(BaseType new("Class", token))

            // if we access to "Dog", we access to an object of type "DogClass"
            type = meta getInstanceType()
            type as BaseType ref = meta
        }

        if(!isObjectClass()) {
            // by default, everyone inherits from object
            setSuperType(BaseType new("Object", token))
        }
    }

    clone: func -> This {
        // saving us a whole lot of trouble.
        Exception new(This, "Cloning a TypeDecl is unsupported") throw()
        null
    }

    debugCondition: inline func -> Bool {
        false
    }

    isAbstract: func -> Bool { false }

    init: func ~typeDecl (.name, .superType, .token) {
        init(name, token)
        setSuperType(superType)
    }

    writeSize: abstract func (w: TabbedWriter, instance: Bool)

    getBase: func -> TypeDecl {
        return isMeta ? base : getMeta() base
    }

    isAddon: func -> Bool { getBase() != null }

    getAddons: func -> ArrayList<Addon> {
        return isMeta ? getNonMeta() addons : addons
    }

    getFullName: func -> String {
        underName()
    }

    setSuperType: func(=superType) {
        if(!this isMeta && superType != null) {
            // TODO: there's probably a better way, but this works fine =)
            if(superType getName() == "Object" && name != "Class") {
                meta setSuperType(BaseType new("ClassClass", superType token))
            } else {
                meta setSuperType(BaseType new(superType getName() + "Class", superType token))
            }
        }
    }

    getSuperType: func -> Type { superType }

    addTypeArg: func (typeArg: VariableDecl) -> Bool {
        typeArg setOwner(this)
        getTypeArgs() add(typeArg)

        variables put(typeArg getName(), typeArg)
        true
    }

    isObjectClass: func -> Bool {
        name equals?("Object") || name equals?("ObjectClass")
    }

    isClassClass: func -> Bool {
        name equals?("Class") || name equals?("ClassClass")
    }

    isRootClass: func -> Bool {
        isObjectClass() || isClassClass()
    }

    addVariable: func (vDecl: VariableDecl) {
        if(vDecl isStatic() && !isMeta) {
            meta addVariable(vDecl)
        } else {
            variables put(vDecl name, vDecl)
            vDecl setOwner(this)
        }
    }

    addInterface: func (interfaceType: Type) {
        interfaceTypes add(interfaceType)
    }

    getInterfaceTypes: func -> List<Type>          { interfaceTypes }
    getInterfaceDecls: func -> List<InterfaceImpl> { interfaceDecls }

    hashName: static func (name, suffix: String) -> String {
        suffix ? "%s~%s" format(name toCString(), suffix toCString()) : name
    }

    hashName: static func ~fromFuncDecl (fDecl: FunctionDecl) -> String {
        This hashName(fDecl getName(), fDecl getSuffix())
    }

    addFunction: func (fDecl: FunctionDecl) {
        if(isMeta) {
            hash := hashName(fDecl)
            old := functions get(hash)
            if (old != null && fDecl getName() != "init") { /* init is an exception */
                if(old == fDecl) Exception new(This, "Replacing %s with %s, which is the same!" format (old getName() toCString(), fDecl getName() toCString())) throw()
                token module params errorHandler onError(FunctionRedefinition new(old, fDecl))
                return
            }

            functions put(hash, fDecl)
            fDecl setOwner(getNonMeta())
        } else {
            meta addFunction(fDecl)
        }
    }

    removeFunction: func(fDecl: FunctionDecl) {
        if(isMeta) {
            functions remove(This hashName(fDecl))
        } else {
            meta removeFunction(fDecl)
        }
    }

    lookupFunction: func (fName, fSuffix: String) -> FunctionDecl {

        // quick lookup, if we're lucky (exact suffix or no suffix)
        fDecl : FunctionDecl = null
        fDecl = functions get(This hashName(fName, fSuffix))
        if(fDecl) return fDecl

{'fraction_non_alphanumeric': 0.10409365446275445, 'fraction_numerical': 0.0, 'mean_word_length': 2.407520325203252, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6864701', 'n_tokens_mistral': 3822, 'n_tokens_neox': 3637, 'n_words': 1179}