function printlnI32(x: I32) = ( printI32(x); print("\n"); ); function printlnInt(x: Int) = ( printInt(x); print("\n"); ); function printI32(x: I32) = printInt(i32ToInt(x)); function printInt(x: Int) = ( let mag = log10(x); loop ( if mag == 0 then break; let base = pow(10, mag); let digit = x / base; print(stringForDigit(digit)); x = x % base; mag = mag - 1; ); print(stringForDigit(x % 10)); ); function stringForDigit(x: Int): String = if x == 0 then "0" else if x == 1 then "1" else if x == 2 then "2" else if x == 3 then "3" else if x == 4 then "4" else if x == 5 then "5" else if x == 6 then "6" else if x == 7 then "7" else if x == 8 then "8" else if x == 9 then "9" else trap(); function log10(x: Int): Int = ( let i = 0; loop ( if x < 10 then break; i = i + 1; x = x / 10; ); i ); function pow(base: Int, exp: Int): Int = ( let acc = 1; loop ( if exp == 0 then break; acc = acc * base; exp = exp - 1; ); acc ); function println(s: String) = ( print(s); print("\n"); ); mod rt ( // Start the heap at 1024. In practice this could probably be as low as we want. global BASE_PTR: I32 = 1024_I32; global HEAD_PTR: I32 = 1024_I32; /* Every struct has a header of an I32 as a refcount. */ // Allocate a new item. We do not deallocate anything yet. // lol. function allocateItem(objSize: I32, align: I32): I32 = ( if align < 4_I32 then std.abort("invalid alignment"); // Include the refcount header. let actualSize = 4_I32 + objSize; // Let's see whether we can fit the refcount into the align bits. // I happen to know that everything will always be at least 4 bytes aligned. let alignedPtr = std.alignUp(HEAD_PTR, align); let actualObjPtr = if (alignedPtr - HEAD_PTR) > align then ( alignedPtr - 4_I32 ) else ( // Take up the next spot. alignedPtr + align - 4_I32 ); let newHeadPtr = actualObjPtr + actualSize; if newHeadPtr > __memory_size() then ( // 16 pages, very arbitrary. let result = __memory_grow(16_I32); // If allocation failed we get -1. We don't have negative numbers yet, lol. if result > 100000000_I32 then ( std.abort("failed to grow memory"); ); ); 0_I32 ); ); function alignUp(x: I32, align: I32): I32 = (x + (align - 1_I32)) & !(align - 1_I32); function i32ToInt(x: I32): Int = __i32_extend_to_i64_u(x); function abort(message: String) = ( print("fatal error: "); print(message); println(".. aborting"); trap(); ); function main() = ( std.rt.allocateItem(100000000_I32, 8_I32); );