Some thoughts on an initial stdlib to get things going

This commit is contained in:
dcodeIO
2017-12-07 04:37:14 +01:00
parent 325ecf5165
commit 59dafc8d22
25 changed files with 196 additions and 280 deletions

17
std/array.d.ts vendored
View File

@ -1,17 +0,0 @@
/// <reference path="../assembly.d.ts" />
declare class Array<T> {
length: i32;
readonly capacity: i32;
readonly data: usize;
constructor(capacity: i32);
}
declare class Int8Array extends Array<i8> {}
declare class Int16Array extends Array<i16> {}
declare class Int32Array extends Array<i32> {}
declare class Uint8Array extends Array<u8> {}
declare class Uint16Array extends Array<u16> {}
declare class Uint32Array extends Array<u32> {}
declare class Float32Array extends Array<f32> {}
declare class Float64Array extends Array<f64> {}

6
std/carray.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference path="../assembly.d.ts" />
declare class CArray<T> {
[key: number]: T;
constructor(capacity: usize);
}

5
std/cstring.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference path="../assembly.d.ts" />
declare class CString extends CArray<u8> {
constructor(text: string);
}

10
std/error.d.ts vendored
View File

@ -1,10 +0,0 @@
/// <reference path="../assembly.d.ts" />
declare class Error {
message: string;
constructor(message: string);
}
declare class RangeError extends Error {}
declare class ReferenceError extends Error {}
declare class TypeError extends Error {}

View File

@ -1,17 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
class Array<T> {
length: i32;
readonly capacity: i32;
readonly data: usize;
constructor(capacity: i32) {
if (capacity < 0)
throw new RangeError("capacity out of bounds");
this.length = capacity;
this.capacity = capacity;
this.data = Memory.allocate(sizeof<T>() * capacity);
}
}

29
std/impl/carray.ts Normal file
View File

@ -0,0 +1,29 @@
/// <reference path="../../assembly.d.ts" />
/** A C-compatible Array class. */
@global()
class CArray<T> {
/** Constructs a new C-Array of the specified capacity. */
constructor(capacity: usize) {
return unsafe_cast<usize,this>(Memory.allocate(capacity * sizeof<T>()));
}
/** Gets the element at the specified index using bracket notation. */
@inline()
"[]"(index: usize): T {
return load<T>(unsafe_cast<this,usize>(this) + index * sizeof<T>());
}
/** Sets the element at the specified index using bracket notation. */
@inline()
"[]="(index: usize, value: T): T {
store<T>(unsafe_cast<this,usize>(this) + index * sizeof<T>(), value);
return value;
}
/** Disposes this instance and the memory associated with it. */
dispose(): void {
Memory.dispose(unsafe_cast<this,usize>(this));
}
}

47
std/impl/cstring.ts Normal file
View File

@ -0,0 +1,47 @@
/// <reference path="../../assembly.d.ts" />
/** A C-compatible string class. */
@global()
class CString extends CArray<u8> {
/** Constructs a new C-String from a String. */
constructor(text: string) {
super(text.length * 2 + 1);
let idx: usize = unsafe_cast<this,usize>(this);
for (let i: usize = 0, k: usize = (<string>str).length; i < k; ++i) {
let u: i32 = text.charCodeAt(i);
if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k)
u = 0x10000 + ((u & 0x3FF) << 10) | (text.charCodeAt(++i) & 0x3FF);
if (u <= 0x7F)
store<u8>(idx++, u as u8);
else if (u <= 0x7FF) {
// TODO: maybe combine multiple stores into the next larger one
store<u8>(idx++, (0xC0 | (u >>> 6) ) as u8);
store<u8>(idx++, (0x80 | ( u & 63)) as u8);
} else if (u <= 0xFFFF) {
store<u8>(idx++, (0xE0 | (u >>> 12) ) as u8);
store<u8>(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
store<u8>(idx++, (0x80 | ( u & 63)) as u8);
} else if (u <= 0x1FFFFF) {
store<u8>(idx++, (0xF0 | (u >>> 18) ) as u8);
store<u8>(idx++, (0x80 | ((u >>> 12) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
store<u8>(idx++, (0x80 | ( u & 63)) as u8);
} else if (u <= 0x3FFFFFF) {
store<u8>(idx++, (0xF8 | (u >>> 24) ) as u8);
store<u8>(idx++, (0x80 | ((u >>> 18) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 12) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
store<u8>(idx++, (0x80 | ( u & 63)) as u8);
} else {
store<u8>(idx++, (0xFC | (u >>> 30) ) as u8);
store<u8>(idx++, (0x80 | ((u >>> 24) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 18) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 12) & 63)) as u8);
store<u8>(idx++, (0x80 | ((u >>> 6) & 63)) as u8);
store<u8>(idx++, (0x80 | ( u & 63)) as u8);
}
}
store<u8>(idx, 0);
}
}

View File

@ -1,20 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
class Error {
message: string;
constructor(message: string) {
this.message = message;
}
}
@global()
class RangeError extends Error {}
@global()
class ReferenceError extends Error {}
@global()
class TypeError extends Error {}

View File

@ -1,22 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
class Map<K,V> {
private keys: K[];
private values: V[];
constructor() {
this.keys = [];
this.values = [];
}
has(key: K): bool {
return false;
}
set(key: K, value: V): void {
}
clear(): void {
}
}

View File

@ -1,5 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
class Math {
}

View File

@ -1,27 +1,21 @@
/// <reference path="../../assembly.d.ts" />
const MEMORY_ALIGN_LOG2: usize = 3;
const MEMORY_ALIGN_SIZE: usize = 1 << MEMORY_ALIGN_LOG2;
const MEMORY_ALIGN_MASK: usize = MEMORY_ALIGN_SIZE - 1;
@global()
class Memory {
static allocate(size: usize): usize {
const ptr: usize = load<usize>(sizeof<usize>());
store<usize>(sizeof<usize>(), ptr + size);
const ptr: usize = HEAP_OFFSET;
HEAP_OFFSET += size;
if ((HEAP_OFFSET & MEMORY_ALIGN_MASK) != 0)
HEAP_OFFSET = (HEAP_OFFSET | MEMORY_ALIGN_MASK) + 1;
return ptr;
}
static free(ptr: usize): void {
}
static copy(src: usize, dst: usize, count: usize): void {
for (let i: usize = 0; i < count; ++i)
store<u8>(dst + i, load<u8>(src + i));
}
static compare(src: usize, dst: usize, count: usize): i32 {
for (let i: usize = 0; i < count; ++i) {
const d: i32 = (load<u8>(src + i) as i32) - (load<u8>(dst + i) as i32);
if (d) return d;
}
return 0;
static dispose(ptr: usize): void {
// just a big chunk of non-disposable memory for now
}
}

View File

@ -1,5 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
class Set<T> {
}

View File

@ -1,58 +0,0 @@
/// <reference path="../../assembly.d.ts" />
@global()
@allocates()
@operator("==", String.equals)
@operator("!=", String.notEquals)
@operator("+", String.concat)
class String {
readonly length: i32;
constructor(length: i32) {
if (length < 0)
throw new RangeError("invalid length");
const data: usize = Memory.allocate(4 + length);
store<i32>(data, length);
return classof<String>(data);
}
static fromCharCode(c1: i32 /* sic */, c2: i32 = -1): String {
throw new Error("not implemented");
}
static equals(a: String, b: String): bool {
const aLength: i32 = a.length;
return aLength == b.length && !Memory.compare(pointerof(a) + 4, pointerof(b) + 4, aLength << 1);
}
static notEquals(a: String, b: String): bool {
const aLength: i32 = a.length;
return aLength != b.length || Memory.compare(pointerof(a) + 4, pointerof(b) + 4, aLength << 1);
}
static concat(a: String, b: String): String {
const aLength: i32 = a.length;
const bLength: i32 = b.length;
const combinedLength: i32 = aLength + bLength;
if (combinedLength < 0)
throw new RangeError("invalid length");
const aByteLength: i32 = aLength << 1;
const bByteLength: i32 = bLength << 1;
const data: usize = Memory.allocate(4 + combinedLength);
store<i32>(data, combinedLength);
Memory.copy(pointerof(a) + 4, data + 4, aByteLength);
Memory.copy(pointerof(b) + 4, data + 4 + aByteLength, bByteLength);
return classof<String>(data);
}
charCodeAt(index: i32): u16 {
if (index < 0 || index > this.length)
throw new RangeError("index out of bounds");
return load<u32>(pointerof(this) + 4 + index << 1);
}
concat(other: String): String {
return String.concat(this, other);
}
}

View File

@ -4,12 +4,8 @@
"experimentalDecorators": true
},
"files": [
"array.ts",
"error.ts",
"map.ts",
"math.ts",
"memory.ts",
"set.ts",
"string.ts"
"carray.ts",
"cstring.ts",
"memory.ts"
]
}

1
std/map.d.ts vendored
View File

@ -1 +0,0 @@
/// <reference path="../assembly.d.ts" />

4
std/math.d.ts vendored
View File

@ -1,4 +0,0 @@
/// <reference path="../assembly.d.ts" />
declare class Math {
}

4
std/memory.d.ts vendored
View File

@ -2,7 +2,5 @@
declare class Memory {
static allocate(size: usize): usize;
static free(ptr: usize): void;
static copy(src: usize, dst: usize, count: usize): void;
static compare(src: usize, dst: usize, count: usize): i32;
static dispose(ptr: usize): void;
}

4
std/set.d.ts vendored
View File

@ -1,4 +0,0 @@
/// <reference path="../assembly.d.ts" />
declare class Set<T> {
}

11
std/string.d.ts vendored
View File

@ -1,11 +0,0 @@
/// <reference path="../assembly.d.ts" />
declare class String {
readonly length: i32;
constructor(length: i32);
static fromCharCode(c1: i32, c2?: i32);
static equals(a: string, b: string): bool;
static concat(a: string, b: string): string;
charCodeAt(index: i32): u16;
concat(other: string): string;
}

View File

@ -4,12 +4,8 @@
"experimentalDecorators": true
},
"files": [
"array.d.ts",
"error.d.ts",
"map.d.ts",
"math.d.ts",
"memory.d.ts",
"set.d.ts",
"string.d.ts"
"carray.d.ts",
"cstring.d.ts",
"memory.d.ts"
]
}