<commit_before>//
//  girtypereference.swift
//  libgir2swift
//
//  Created by <NAME> on 26/7/20.
//  Copyright © 2020 <NAME>. All rights reserved.
//
import Foundation

/// Reference to a GIR type.
public struct TypeReference: Hashable {
    /// The type referenced
    public let type: GIRType

    /// The identifier of this instance
    public let identifier: String?

    /// Whether or not the referenced type is `const`
    public var isConst: Bool = false

    /// Whether or not the referenced type is optional (nullable)
    public var isOptional: Bool = false

    /// Whether or not the referenced type is an array
    public var isArray: Bool = false

    /// Array of pointers (`true` if they are const, `false` if they are mutable)
    public var constPointers = [Bool]()

    /// The level of indirection,
    /// with `0` indicating the referenced type itself,
    /// `1` representing a pointer to an instance of the referenced type,
    /// `2` representing an array of pointers (or a pointer to a pointer), etc.
    public var indirectionLevel: Int { constPointers.count }

    /// Returns `true` if the receiver is a reference to `void`
    public var isVoid: Bool { return isAlias(of: .void) }

    /// returns the full C type including pointers and `const`
    public var fullCType: String {
        var ct = type.ctype + (constPointers.isEmpty ? "" : " ")
        for e in constPointers.enumerated() {
            ct = ct + (e.element || (e.offset == 0 && isConst) ? "const*" : "*")
        }
        return ct
    }

    /// returns the full type including pointers and  taking into account `const`
    @inlinable public var fullTypeName: String {
        let typeName = type.typeName.validSwift
        return embeddedType(named: typeName)
    }

    /// returns the full type including pointers and  taking into account `const`
    @inlinable public var fullUnderlyingTypeName: String {
        let typeName = type.typeName.validSwift.optionalWhenCallback
        return embeddedType(named: typeName)
    }

    /// returns the full C type including pointers and  taking into account `const`
    @inlinable public var fullUnderlyingCName: String {
        let typeName = type.ctype.validSwift
        return embeddedType(named: typeName)
    }

    /// returns the force-unwrapped, full type name
    @inlinable public var forceUnwrappedName: String {
        let name = fullTypeName
        guard !name.hasSuffix("!") && !name.hasSuffix("?") else { return name }
        return name + "!"
    }

    /// returns the full Swift type (e.g. class) including pointers and  taking into account `const`
    public var fullSwiftTypeName: String {
        let typeName = type.swiftName.validSwift
        return embeddedType(named: typeName)
    }

    public func embeddedType(named name: String) -> String {
        let k = constPointers.count - 1
        let prefix = (isArray ? "[" : "") + constPointers.enumerated().map {
            let i = min(k, $0.offset+1)
            let elementIsConst = ($0.offset == k && isConst) || constPointers[i]
            let element = "Unsafe" + (elementIsConst ? "" : "Mutable") + "Pointer<"
            return element
        }.joined()
        let innerSuffix: String
        if constPointers.count <= 1 {
            innerSuffix = ""
        } else {
            let s = constPointers.startIndex
            let e = constPointers.index(before: constPointers.endIndex)
            innerSuffix = constPointers[s..<e].map { _ in ">?" }.joined()
        }
        let outerSuffix = constPointers.isEmpty ? "" : (">" + (isOptional ? "?" : "!"))
        let suffix = innerSuffix + outerSuffix + (isArray ? "]" : "")
        let st = prefix + name + suffix
        return st
    }

    /// Cast from one type reference to another
    /// - Parameters:
    ///   - expression: The expression to cast
    ///   - source: The source type reference to cast from
    /// - Returns: The expression cast to the receiver type
    @inlinable public func cast(expression e: String, from source: TypeReference) -> String {
        guard self != source else { return e }
        let p = indirectionLevel == 0 ? 0 : max(1, indirectionLevel - source.indirectionLevel)
        // FIXME: this needs to check if this is a const -> mutating pointer cast
        let cast = type.cast(expression: e, from: source.type, pointerLevel: p, const: isConst)
        return cast
    }

    /// Reference to void type
    public static var void: TypeReference = TypeReference(type: GIR.voidType)

    /// Designated initialiser for a type reference
    /// - Parameters:
    ///   - type: The type to reference
    ///   - identifier: The identifier for this instance (e.g. C enum case name)
    ///   - isConst: Whether or not this reference is to a `const` instance
    ///   - isArray: Whether or not this is an array
    ///   - isOptional: Whether or not this instance is nullable
    ///   - constPointers: Array of booleans representing indirection levels (pointers), `true` if the pointer is `const`
    @inlinable
    public init(type: GIRType, identifier: String? = nil, isConst: Bool = false, isOptional: Bool = false, isArray: Bool = false, constPointers: [Bool] = []) {
        self.type = type
        self.identifier = identifier?.isEmpty ?? true ? nil : identifier
        self.isConst = isConst
        self.isOptional = isOptional
        self.isArray = isArray
        self.constPointers = constPointers
    }

    /// Create a single-indirection pointer to a given target
    /// - Parameter target: The target type to reference
    /// - Parameter isConst: Whether the target is `const`<commit_msg>Avoid cast from implicitly wrapped optional to non-optional target of same type<commit_after>//
//  girtypereference.swift
//  libgir2swift
//
//  Created by <NAME> on 26/7/20.
//  Copyright © 2020 <NAME>. All rights reserved.
//
import Foundation

/// Reference to a GIR type.
public struct TypeReference: Hashable {
    /// The type referenced
    public let type: GIRType

    /// The identifier of this instance
    public let identifier: String?

    /// Whether or not the referenced type is `const`
    public var isConst: Bool = false

    /// Whether or not the referenced type is optional (nullable)
    public var isOptional: Bool = false

    /// Whether or not the referenced type is an array
    public var isArray: Bool = false

    /// Array of pointers (`true` if they are const, `false` if they are mutable)
    public var constPointers = [Bool]()

    /// The level of indirection,
    /// with `0` indicating the referenced type itself,
    /// `1` representing a pointer to an instance of the referenced type,
    /// `2` representing an array of pointers (or a pointer to a pointer), etc.
    public var indirectionLevel: Int { constPointers.count }

    /// Returns `true` if the receiver is a reference to `void`
    public var isVoid: Bool { return isAlias(of: .void) }

    /// returns the full C type including pointers and `const`
    public var fullCType: String {
        var ct = type.ctype + (constPointers.isEmpty ? "" : " ")
        for e in constPointers.enumerated() {
            ct = ct + (e.element || (e.offset == 0 && isConst) ? "const*" : "*")
        }
        return ct
    }

    /// returns the full type including pointers and  taking into account `const`
    @inlinable public var fullTypeName: String {
        let typeName = type.typeName.validSwift
        return embeddedType(named: typeName)
    }

    /// returns the full type including pointers and  taking into account `const`
    @inlinable public var fullUnderlyingTypeName: String {
        let typeName = type.typeName.validSwift.optionalWhenCallback
        return embeddedType(named: typeName)
    }

    /// returns the full C type including pointers and  taking into account `const`
    @inlinable public var fullUnderlyingCName: String {
        let typeName = type.ctype.validSwift
        return embeddedType(named: typeName)
    }

    /// returns the force-unwrapped, full type name
    @inlinable public var forceUnwrappedName: String {
        let name = fullTypeName
        guard !name.hasSuffix("!") && !name.hasSuffix("?") else { return name }
        return name + "!"
    }

    /// returns the full Swift type (e.g. class) including pointers and  taking into account `const`
    public var fullSwiftTypeName: String {
        let typeName = type.swiftName.validSwift
        return embeddedType(named: typeName)
    }

    public func embeddedType(named name: String) -> String {
        let k = constPointers.count - 1
        let prefix = (isArray ? "[" : "") + constPointers.enumerated().map {
            let i = min(k, $0.offset+1)
            let elementIsConst = ($0.offset == k && isConst) || constPointers[i]
            let element = "Unsafe" + (elementIsConst ? "" : "Mutable") + "Pointer<"
            return element
        }.joined()
        let innerSuffix: String
        if constPointers.count <= 1 {
            innerSuffix = ""
        } else {
            let s = constPointers.startIndex
            let e = constPointers.index(before: constPointers.endIndex)
            innerSuffix = constPointers[s..<e].map { _ in ">?" }.joined()
        }
        let outerSuffix = constPointers.isEmpty ? "" : (">" + (isOptional ? "?" : "!"))
        let suffix = innerSuffix + outerSuffix + (isArray ? "]" : "")
        let st = prefix + name + suffix
        return st
    }

    /// Cast from one type reference to another
    /// - Parameters:
    ///   - expression: The expression to cast
    ///   - source: The source type reference to cast from
    /// - Returns: The expression cast to the receiver type
    @inlinable public func cast(expression e: String, from source: TypeReference) -> String {
        guard self != source && (constPointers != source.constPointers || source.type.name != (type.name + "!")) else { return e }
        let p = indirectionLevel == 0 ? 0 : max(1, indirectionLevel - source.indirectionLevel)
        // FIXME: this needs to check if this is a const -> mutating pointer cast
        let cast = type.cast(expression: e, from: source.type, pointerLevel: p, const: isConst)
        return cast
    }

    /// Reference to void type
    public static var void: TypeReference = TypeReference(type: GIR.voidType)

    /// Designated initialiser for a type reference
    /// - Parameters:
    ///   - type: The type to reference
    ///   - identifier: The identifier for this instance (e.g. C enum case name)
    ///   - isConst: Whether or not this reference is to a `const` instance
    ///   - isArray: Whether or not this is an array
    ///   - isOptional: Whether or not this instance is nullable
    ///   - constPointers: Array of booleans representing indirection levels (pointers), `true` if the pointer is `const`
    @inlinable
    public init(type: GIRType, identifier: String? = nil, isConst: Bool = false, isOptional: Bool = false, isArray: Bool = false, constPointers: [Bool] = []) {
        self.type = type
        self.identifier = identifier?.isEmpty ?? true ? nil : identifier
        self.isConst = isConst
        self.isOptional = isOptional
        self.isArray = isArray
        self.constPointers = constPointers
    }

    /// Create a single-indirection pointer to a given target
    /// - Parameter target: The target type to reference
    /// - Parameter isConst: Whether the target is `const`
{'fraction_non_alphanumeric': 0.10405381792766032, 'fraction_numerical': 0.0038441376900227153, 'mean_word_length': 2.426219694702185, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, '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': '6877436', 'n_tokens_mistral': 3252, 'n_tokens_neox': 3077, 'n_words': 1166}