Skip to content

constructor

IsaacShelton edited this page Nov 16, 2022 · 6 revisions

constructor

Constructors can be defined using the constructor keyword.

import basics
import random

pragma ignore_unused

struct Person (name String, uid int) {
    constructor(name String){
        this.name = name
        this.uid = randomInt(100)
    }
}

func toString(person Person) String {
    return person.name + " : id=" + person.uid
}

func main {
    randomize()

    john Person("John")                               // constructed (living on stack)

    james *Person = new Person("John")                // constructed (living on heap)
    defer delete james

    print("Constructed people:")
    print(john)
    print(*james)

    // --------- vs ---------

    uninitialized_guy Person = undef                  // undefined (living on stack)

    uninitialized_heap_guy *Person = new undef Person // undefined (living on heap)
    defer delete uninitialized_heap_guy

    unconstructed_guy Person                          // zero-initialized (living on stack)

    unconstructed_heap_guy *Person = new Person       // zero-initialized (living on heap)
    defer delete unconstructed_heap_guy

    print("Unconstructed people")
    print(unconstructed_guy)
    print(*unconstructed_heap_guy)

    print("Uninitialized people")
    print("(cannot print these, since their names would be garbage memory)")
}

You can also call a constructor like any other method, using value.__constructor__(arg1, arg2, argN). However, you are responsible for making sure the memory of the value is zero-initialized before-hand, since constructors are allowed to assume zero-initialization.

import basics

struct MyInteger (value int) {
    constructor(){
        this.value = 12435
    }
}

func main {
    my_integer MyInteger
    my_integer.__constructor__()

    // which is equivalent to

    /*
    my_integer MyInteger()
    */

    // -----------------------------

    print(my_integer.value)
}

Calling __constructor__ on memory that is not zero-initialized is type-dependant. Types are NOT REQUIRED to be able to be constructed on non zero-initialized memory. If uncertain, zero-initialize the memory before manual construction using something like memset(memory, 0, size_in_bytes)!

import basics

struct Person (name String, level int) {
    constructor(name String){
        this.name = name
        this.level = 1
    }
}

func main(){
    // Example of manually constructing values from garbage memory

    count usize = 100
    raw_memory *Person = new undef Person * count // equivalent to `malloc(sizeof Person * count)`

    repeat count {
        person *Person = &raw_memory[idx]

        memset(person, 0, sizeof Person)
        person.__constructor__("Abby")
    }

    each Person in [raw_memory, count] {
        printf("[%d] Hello %S\n", idx, it.name)
    }

    defer {
        each Person in [raw_memory, count], it.__defer__() // destroy each person (necessary because it contains `String` and so is not POD (plain-old-data))
        delete raw_memory                                  // equivalent to `free(raw_memory)`
    }
}

Clone this wiki locally