type Counter {
    value: i32 = defaultCount(),
    fn init(value: i32) -> Self {
        return Counter { value: value }
    }
    fn read(self: ref<Self>) -> i32 {
        return self.value
    }
    fn bump(self: mutref<Self>, amount: i32) -> Void {
        self.value = self.value + amount
    }
    fn checkedRead(self: ref<Self>) -> i32 raises [EmptyCounter] {
        if self.value == 0 {
            raise EmptyCounter
        }
        return self.value
    }
}

interface Readable<T: Type> {
    fn read(self: ref<T>) -> i32
}

choice Event {
    key: i32,
    quit,
}

fn defaultCount() -> i32 {
    return 41
}

fn add(left: i32, right: i32) -> i32 {
    return left + right
}

fn id<T: Type>(value: T) -> T {
    return value
}

fn wrap<T: Type>(value: T) -> T {
    return id(value)
}

fn readValue<T: Readable<T>>(value: ref<T>) -> i32 {
    return T.read(value)
}

fn risky(flag: Bool) -> i32 raises [BadInput] {
    if flag {
        raise BadInput
    }
    return 7
}

pub fn main(world: World) -> Void raises {
    var counter: Counter = Counter.init(41)
    let defaulted: Counter = Counter {}
    counter.bump(1)
    let total: i32 = add(id<i32>(40), 2)
    let wrapped: i32 = wrap<i32>(total)
    let size: usize = std.mem.len("zero")
    let event: Event = Event.key(total)
    let direct: i32 = Counter.read(&counter)
    let defaultedValue: i32 = Counter.read(&defaulted)
    let viaInterface: i32 = readValue<Counter>(&counter)
    let checked: i32 = check counter.checkedRead()
    let safe: i32 = check risky(false)
    if total == 42 && wrapped == 42 && size == 4 && defaultedValue == 41 && (direct == 42 && viaInterface == 42) && (checked == 42 && safe == 7) {
        check world.out.write("call resolution inspection ok\n")
    }
}
