export class Array { private __memory: usize; private __capacity: i32; length: i32; constructor(capacity: i32 = 0) { if (capacity < 0) throw new RangeError("invalid array length"); this.__capacity = this.length = capacity; this.__memory = capacity > 0 ? Heap.allocate(capacity * sizeof()) : 0; } @operator("[]") private __get(index: i32): T { if (index >= this.__capacity) throw new RangeError("index out of range"); return load(this.__memory + index * sizeof()); } @operator("[]=") private __set(index: i32, value: T): void { if (index >= this.__capacity) throw new RangeError("index out of range"); store(this.__memory + index * sizeof(), value); } indexOf(searchElement: T, fromIndex: i32 = 0): i32 { if (fromIndex >= this.__capacity) throw new RangeError("fromIndex out of range"); for (var index: usize = fromIndex, length: usize = min(this.length, this.__capacity); index < length; ++index) if (load(this.__memory + index * sizeof()) == searchElement) return index; return -1; } private __grow(capacity: i32): void { assert(capacity > this.__capacity); var newMemory = Heap.allocate((capacity * sizeof())); if (this.__memory) Heap.copy(newMemory, this.__memory, this.__capacity * sizeof()); Heap.dispose(this.__memory); this.__memory = newMemory; this.__capacity = capacity; } push(element: T): i32 { if (this.length >= this.__capacity) this.__grow(max(this.length + 1, this.__capacity * 2)); store(this.__memory + this.length * sizeof(), element); return ++this.length; } pop(): T { if (this.length < 1 || this.length > this.__capacity) throw new RangeError("index out of range"); --this.length; return load(this.__memory + this.length * sizeof()); } shift(): T { if (this.length < 1 || this.length > this.__capacity) throw new RangeError("index out of range"); var element = load(this.__memory); Heap.copy(this.__memory, this.__memory + sizeof(), (this.__capacity - 1) * sizeof()); Heap.fill(this.__memory + (this.__capacity - 1) * sizeof(), 0, sizeof()); --this.length; return element; } unshift(element: T): i32 { var capacity = this.__capacity; if (this.length >= capacity) this.__grow(max(this.length + 1, capacity * 2)); // FIXME: needs memmove (Heap.copy is just memcpy). it's also inefficient because // __grow copies and then unshift copies again. // Heap.copy(this.__memory + sizeof(), this.__memory, capacity * sizeof()); if (capacity) for (var index: usize = capacity; index > 0; --index) store(this.__memory + index * sizeof(), load(this.__memory + (index - 1) * sizeof())); store(this.__memory, element); return ++this.length; } } @explicit export class CArray { private constructor() {} @operator("[]") private __get(index: usize): T { return load(changetype(this) + index * sizeof()); } @operator("[]=") private __set(index: usize, value: T): void { store(changetype(this) + index * sizeof(), value); } }