/// import { BLOCK, BLOCK_OVERHEAD, BLOCK_MAXSIZE } from "./rt/common"; import { idof } from "./builtins"; import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_HOLEYARRAY } from "./util/error"; // NOTE: DO NOT USE YET! // TODO: FixedArray with S being the static size, i.e. `new FixedArray`. // Then hard-wire this special type to the compiler and do static length checks instead :) export class FixedArray { [key: number]: T; constructor(length: i32) { if (length > BLOCK_MAXSIZE >>> alignof()) throw new RangeError(E_INVALIDLENGTH); if (isReference()) { if (!isNullable()) { if (length) throw new Error(E_HOLEYARRAY); } } var outSize = length << alignof(); var out = __alloc(outSize, idof>()); memory.fill(out, 0, outSize); return changetype>(out); // retains } get length(): i32 { return changetype(changetype(this) - BLOCK_OVERHEAD).rtSize >>> alignof(); } @operator("[]") private __get(index: i32): T { if (index >= this.length) throw new RangeError(E_INDEXOUTOFRANGE); return this.__unchecked_get(index); } @operator("[]=") private __set(index: i32, value: T): void { if (index >= this.length) throw new RangeError(E_INDEXOUTOFRANGE); return this.__unchecked_set(index, value); } @operator("{}") private __unchecked_get(index: i32): T { return load(changetype(this) + (index << alignof())); } @operator("{}=") private __unchecked_set(index: i32, value: T): void { if (isManaged()) { let offset = changetype(this) + (index << alignof()); let oldValue = load(offset); if (changetype(value) != oldValue) { store(offset, __retain(changetype(value))); __release(changetype(oldValue)); } } else { store(changetype(this) + (index << alignof()), value); } } // GC integration @unsafe private __traverse(cookie: u32): void { if (isManaged()) { let cur = changetype(this); let end = cur + changetype(changetype(this) - BLOCK_OVERHEAD).rtSize; while (cur < end) { let val = load(cur); if (isNullable()) { if (val) { __visit(val, cookie); __visit_members(val, cookie); } } else { __visit(val, cookie); __visit_members(val, cookie); } cur += sizeof(); } } } }