AdeptLanguage / Adept

The Adept Programming Language
GNU General Public License v3.0
120 stars 8 forks source link

Add the Delphi Set data type #287

Closed ghost closed 7 months ago

ghost commented 7 months ago

It's to help porting of Delphi code.

IsaacShelton commented 7 months ago

It looks like delphi sets are just wrappers for 256-bit bitmasks, so they shouldn't be too bad to port. Something like this would probably work:

struct DelphiSet (mask 4 ulong) {
    func insert(value ubyte) {
        memory *ubyte = &this.mask as *ubyte
        memory[value / 8] |= 1 << (value % 8)
    }

    func remove(value ubyte) {
        memory *ubyte = &this.mask as *ubyte
        memory[value / 8] &= ~(1 << (value % 8))
    }

    func contains(value ubyte) bool {
        memory *ubyte = &this.mask as *ubyte
        return (memory[value / 8] & (1 << (value % 8))) != 0
    }

    func insert(value $T~__flat_enum__) {
        this.insert(value as ubyte)
    }

    func remove(value $T~__flat_enum__) {
        this.remove(value as ubyte)
    }

    func contains(value $T~__flat_enum__) bool {
        return this.contains(value as ubyte)
    }
}
import basics

enum Fruit (APPLE, BANANA, ORANGE)

func main {
    set DelphiSet

    printf("[!] Adding 13\n")
    set.insert(13ub)

    printf("[!] Adding Fruit::APPLE\n")
    set.insert(Fruit::APPLE)
    printf("  set.contains(Fruit::APPLE) = %b\n", set.contains(Fruit::APPLE))
    printf("  set.contains(Fruit::BANANA) = %b\n", set.contains(Fruit::BANANA))
    printf("  set.contains(13ub) = %b\n", set.contains(13ub))

    printf("[!] Removing Fruit::APPLE\n")
    set.remove(Fruit::APPLE)

    printf("  set.contains(Fruit::APPLE) = %b\n", set.contains(Fruit::APPLE))
    printf("  set.contains(Fruit::BANANA) = %b\n", set.contains(Fruit::BANANA))
    printf("  set.contains(13ub) = %b\n", set.contains(13ub))

    printf("[!] Adding Fruit::BANANA\n")
    set.insert(Fruit::BANANA)

    printf("  set.contains(Fruit::APPLE) = %b\n", set.contains(Fruit::APPLE))
    printf("  set.contains(Fruit::BANANA) = %b\n", set.contains(Fruit::BANANA))
    printf("  set.contains(13ub) = %b\n", set.contains(13ub))

    printf("[!] Removing 13ub\n")
    set.remove(13ub)

    printf("  set.contains(Fruit::APPLE) = %b\n", set.contains(Fruit::APPLE))
    printf("  set.contains(Fruit::BANANA) = %b\n", set.contains(Fruit::BANANA))
    printf("  set.contains(13ub) = %b\n", set.contains(13ub))
}
IsaacShelton commented 7 months ago

And if you need easy construction without declaring a variable, one way to do it would be like:

func empty() DelphiSet {
    set DelphiSet
    return set
}
import basics

func main {
    doSomething(empty() ~> DelphiSet)
}

func doSomething(set DelphiSet) {
    another_set DelphiSet = empty() ~> DelphiSet
}

The ~> operator can be used to request a specific return type which is how this style can work