toilscript 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +94 -0
- package/README.md +114 -0
- package/bin/asc.js +35 -0
- package/bin/asinit.js +468 -0
- package/dist/asc.d.ts +4 -0
- package/dist/toilscript.d.ts +4 -0
- package/dist/transform.cjs +1 -0
- package/dist/transform.d.ts +1 -0
- package/dist/transform.js +1 -0
- package/lib/binaryen.d.ts +2 -0
- package/lib/binaryen.js +2 -0
- package/package.json +114 -0
- package/std/README.md +6 -0
- package/std/assembly/array.ts +550 -0
- package/std/assembly/arraybuffer.ts +77 -0
- package/std/assembly/atomics.ts +127 -0
- package/std/assembly/bindings/asyncify.ts +16 -0
- package/std/assembly/bindings/dom.ts +291 -0
- package/std/assembly/bindings/node.ts +6 -0
- package/std/assembly/bitflags.ts +53 -0
- package/std/assembly/builtins.ts +2650 -0
- package/std/assembly/byteslice.ts +177 -0
- package/std/assembly/compat.ts +2 -0
- package/std/assembly/console.ts +42 -0
- package/std/assembly/crypto.ts +9 -0
- package/std/assembly/dataview.ts +181 -0
- package/std/assembly/date.ts +375 -0
- package/std/assembly/diagnostics.ts +11 -0
- package/std/assembly/encoding.ts +151 -0
- package/std/assembly/endian.ts +45 -0
- package/std/assembly/error.ts +44 -0
- package/std/assembly/fixedarray.ts +173 -0
- package/std/assembly/fixedmap.ts +326 -0
- package/std/assembly/fixedset.ts +275 -0
- package/std/assembly/function.ts +42 -0
- package/std/assembly/index.d.ts +2891 -0
- package/std/assembly/iterator.ts +35 -0
- package/std/assembly/map.ts +269 -0
- package/std/assembly/math.ts +3289 -0
- package/std/assembly/memory.ts +123 -0
- package/std/assembly/number.ts +388 -0
- package/std/assembly/object.ts +36 -0
- package/std/assembly/performance.ts +9 -0
- package/std/assembly/pointer.ts +80 -0
- package/std/assembly/polyfills.ts +27 -0
- package/std/assembly/process.ts +50 -0
- package/std/assembly/reference.ts +48 -0
- package/std/assembly/regexp.ts +12 -0
- package/std/assembly/rt/README.md +83 -0
- package/std/assembly/rt/common.ts +81 -0
- package/std/assembly/rt/index-incremental.ts +2 -0
- package/std/assembly/rt/index-memory.ts +1 -0
- package/std/assembly/rt/index-minimal.ts +2 -0
- package/std/assembly/rt/index-stub.ts +1 -0
- package/std/assembly/rt/index.d.ts +37 -0
- package/std/assembly/rt/itcms.ts +419 -0
- package/std/assembly/rt/memory-runtime.ts +94 -0
- package/std/assembly/rt/rtrace.ts +15 -0
- package/std/assembly/rt/stub.ts +133 -0
- package/std/assembly/rt/tcms.ts +254 -0
- package/std/assembly/rt/tlsf.ts +592 -0
- package/std/assembly/rt.ts +90 -0
- package/std/assembly/set.ts +225 -0
- package/std/assembly/shared/feature.ts +68 -0
- package/std/assembly/shared/runtime.ts +13 -0
- package/std/assembly/shared/target.ts +11 -0
- package/std/assembly/shared/tsconfig.json +11 -0
- package/std/assembly/shared/typeinfo.ts +72 -0
- package/std/assembly/staticarray.ts +423 -0
- package/std/assembly/string.ts +850 -0
- package/std/assembly/symbol.ts +114 -0
- package/std/assembly/table.ts +16 -0
- package/std/assembly/tsconfig.json +6 -0
- package/std/assembly/typedarray.ts +1954 -0
- package/std/assembly/uri.ts +17 -0
- package/std/assembly/util/bytes.ts +107 -0
- package/std/assembly/util/casemap.ts +497 -0
- package/std/assembly/util/error.ts +58 -0
- package/std/assembly/util/hash.ts +117 -0
- package/std/assembly/util/math.ts +1922 -0
- package/std/assembly/util/memory.ts +290 -0
- package/std/assembly/util/number.ts +873 -0
- package/std/assembly/util/sort.ts +313 -0
- package/std/assembly/util/string.ts +1202 -0
- package/std/assembly/util/uri.ts +275 -0
- package/std/assembly/vector.ts +4 -0
- package/std/assembly.json +16 -0
- package/std/portable/index.d.ts +461 -0
- package/std/portable/index.js +416 -0
- package/std/portable.json +11 -0
- package/std/types/assembly/index.d.ts +1 -0
- package/std/types/assembly/package.json +3 -0
- package/std/types/portable/index.d.ts +1 -0
- package/std/types/portable/package.json +3 -0
- package/tsconfig-base.json +13 -0
- package/util/README.md +23 -0
- package/util/browser/fs.js +1 -0
- package/util/browser/module.js +5 -0
- package/util/browser/path.js +520 -0
- package/util/browser/process.js +59 -0
- package/util/browser/url.js +23 -0
- package/util/cpu.d.ts +9 -0
- package/util/cpu.js +42 -0
- package/util/find.d.ts +6 -0
- package/util/find.js +20 -0
- package/util/node.d.ts +21 -0
- package/util/node.js +34 -0
- package/util/options.d.ts +70 -0
- package/util/options.js +262 -0
- package/util/terminal.d.ts +52 -0
- package/util/terminal.js +35 -0
- package/util/text.d.ts +26 -0
- package/util/text.js +114 -0
- package/util/tsconfig.json +9 -0
- package/util/web.d.ts +11 -0
- package/util/web.js +33 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/// <reference path="./rt/index.d.ts" />
|
|
2
|
+
|
|
3
|
+
import { Runtime } from "shared/runtime";
|
|
4
|
+
import { BLOCK_MAXSIZE } from "./rt/common";
|
|
5
|
+
import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_EMPTYARRAY, E_CAPACITYEXCEEDED } from "./util/error";
|
|
6
|
+
|
|
7
|
+
// Pre-allocated contiguous array with fixed capacity.
|
|
8
|
+
// Single buffer, no dynamic growth, zero GC overhead under runtime=memory.
|
|
9
|
+
|
|
10
|
+
@final
|
|
11
|
+
export class FixedArray<T> {
|
|
12
|
+
[key: number]: T;
|
|
13
|
+
|
|
14
|
+
private dataPtr: usize = 0;
|
|
15
|
+
private capacity_: i32 = 0;
|
|
16
|
+
private length_: i32 = 0;
|
|
17
|
+
|
|
18
|
+
constructor(capacity: i32) {
|
|
19
|
+
if (<u32>capacity > <u32>BLOCK_MAXSIZE >>> alignof<T>()) throw new RangeError(E_INVALIDLENGTH);
|
|
20
|
+
|
|
21
|
+
let bufferSize = <usize>capacity << alignof<T>();
|
|
22
|
+
let ptr: usize;
|
|
23
|
+
if (ASC_RUNTIME == Runtime.Memory) {
|
|
24
|
+
ptr = __alloc(bufferSize);
|
|
25
|
+
} else {
|
|
26
|
+
ptr = __new(bufferSize, idof<ArrayBuffer>());
|
|
27
|
+
}
|
|
28
|
+
if (ASC_RUNTIME != Runtime.Incremental) {
|
|
29
|
+
memory.fill(ptr, 0, bufferSize);
|
|
30
|
+
}
|
|
31
|
+
this.dataPtr = ptr;
|
|
32
|
+
this.capacity_ = capacity;
|
|
33
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
34
|
+
__link(changetype<usize>(this), ptr, false);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get length(): i32 {
|
|
39
|
+
return this.length_;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
set length(value: i32) {
|
|
43
|
+
if (<u32>value > <u32>this.capacity_) throw new RangeError(E_INVALIDLENGTH);
|
|
44
|
+
this.length_ = value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get capacity(): i32 {
|
|
48
|
+
return this.capacity_;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@operator("[]") private __get(index: i32): T {
|
|
52
|
+
if (<u32>index >= <u32>this.length_) throw new RangeError(E_INDEXOUTOFRANGE);
|
|
53
|
+
return load<T>(this.dataPtr + (<usize>index << alignof<T>()));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@unsafe @operator("{}") private __uget(index: i32): T {
|
|
57
|
+
return load<T>(this.dataPtr + (<usize>index << alignof<T>()));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@operator("[]=") private __set(index: i32, value: T): void {
|
|
61
|
+
if (<u32>index >= <u32>this.length_) throw new RangeError(E_INDEXOUTOFRANGE);
|
|
62
|
+
this.__uset(index, value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@unsafe @operator("{}=") private __uset(index: i32, value: T): void {
|
|
66
|
+
store<T>(this.dataPtr + (<usize>index << alignof<T>()), value);
|
|
67
|
+
if (isManaged<T>()) {
|
|
68
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
69
|
+
__link(changetype<usize>(this), changetype<usize>(value), true);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
push(value: T): i32 {
|
|
75
|
+
let len = this.length_;
|
|
76
|
+
if (len >= this.capacity_) throw new Error(E_CAPACITYEXCEEDED);
|
|
77
|
+
store<T>(this.dataPtr + (<usize>len << alignof<T>()), value);
|
|
78
|
+
if (isManaged<T>()) {
|
|
79
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
80
|
+
__link(changetype<usize>(this), changetype<usize>(value), true);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
let newLen = len + 1;
|
|
84
|
+
this.length_ = newLen;
|
|
85
|
+
return newLen;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
pop(): T {
|
|
89
|
+
let len = this.length_;
|
|
90
|
+
if (len <= 0) throw new Error(E_EMPTYARRAY);
|
|
91
|
+
let newLen = len - 1;
|
|
92
|
+
let value = load<T>(this.dataPtr + (<usize>newLen << alignof<T>()));
|
|
93
|
+
this.length_ = newLen;
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
swapDelete(index: i32): void {
|
|
98
|
+
let len = this.length_;
|
|
99
|
+
if (<u32>index >= <u32>len) throw new RangeError(E_INDEXOUTOFRANGE);
|
|
100
|
+
let newLen = len - 1;
|
|
101
|
+
if (index != newLen) {
|
|
102
|
+
let data = this.dataPtr;
|
|
103
|
+
let deletedOff = <usize>index << alignof<T>();
|
|
104
|
+
let lastOff = <usize>newLen << alignof<T>();
|
|
105
|
+
store<T>(data + deletedOff, load<T>(data + lastOff));
|
|
106
|
+
}
|
|
107
|
+
this.length_ = newLen;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
indexOf(value: T, fromIndex: i32 = 0): i32 {
|
|
111
|
+
let length = this.length_;
|
|
112
|
+
if (length == 0 || fromIndex >= length) return -1;
|
|
113
|
+
if (fromIndex < 0) fromIndex = max(length + fromIndex, 0);
|
|
114
|
+
let data = this.dataPtr;
|
|
115
|
+
while (fromIndex < length) {
|
|
116
|
+
if (load<T>(data + (<usize>fromIndex << alignof<T>())) == value) return fromIndex;
|
|
117
|
+
++fromIndex;
|
|
118
|
+
}
|
|
119
|
+
return -1;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
includes(value: T, fromIndex: i32 = 0): bool {
|
|
123
|
+
return this.indexOf(value, fromIndex) >= 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
|
|
127
|
+
let len = this.length_;
|
|
128
|
+
start = start < 0 ? max(len + start, 0) : min(start, len);
|
|
129
|
+
end = end < 0 ? max(len + end, 0) : min(end, len);
|
|
130
|
+
let data = this.dataPtr;
|
|
131
|
+
if (isManaged<T>()) {
|
|
132
|
+
for (let i = start; i < end; ++i) {
|
|
133
|
+
store<usize>(data + (<usize>i << alignof<T>()), changetype<usize>(value));
|
|
134
|
+
}
|
|
135
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
136
|
+
__link(changetype<usize>(this), changetype<usize>(value), false);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
for (let i = start; i < end; ++i) {
|
|
140
|
+
store<T>(data + (<usize>i << alignof<T>()), value);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
clear(): void {
|
|
147
|
+
this.length_ = 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
toString(): string {
|
|
151
|
+
return "[object FixedArray]";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// RT integration
|
|
155
|
+
|
|
156
|
+
@unsafe private __visit(cookie: u32): void {
|
|
157
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
158
|
+
let data = this.dataPtr;
|
|
159
|
+
if (data) {
|
|
160
|
+
if (isManaged<T>()) {
|
|
161
|
+
let cur = data;
|
|
162
|
+
let end = cur + (<usize>this.length_ << alignof<T>());
|
|
163
|
+
while (cur < end) {
|
|
164
|
+
let val = load<usize>(cur);
|
|
165
|
+
if (val) __visit(val, cookie);
|
|
166
|
+
cur += sizeof<usize>();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
__visit(data, cookie);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/// <reference path="./rt/index.d.ts" />
|
|
2
|
+
|
|
3
|
+
import { HASH } from "./util/hash";
|
|
4
|
+
import { Runtime } from "shared/runtime";
|
|
5
|
+
import { E_KEYNOTFOUND } from "./util/error";
|
|
6
|
+
|
|
7
|
+
// Open-addressing hash map with linear probing.
|
|
8
|
+
// Single contiguous buffer, cache-friendly, zero GC overhead under runtime=memory.
|
|
9
|
+
|
|
10
|
+
// @ts-ignore: decorator
|
|
11
|
+
@inline const SLOT_EMPTY: u8 = 0;
|
|
12
|
+
// @ts-ignore: decorator
|
|
13
|
+
@inline const SLOT_OCCUPIED: u8 = 1;
|
|
14
|
+
// @ts-ignore: decorator
|
|
15
|
+
@inline const SLOT_DELETED: u8 = 2;
|
|
16
|
+
|
|
17
|
+
// @ts-ignore: decorator
|
|
18
|
+
@inline const FM_INITIAL_CAPACITY: i32 = 16;
|
|
19
|
+
|
|
20
|
+
// Max load factor 75% = 3/4
|
|
21
|
+
// @ts-ignore: decorator
|
|
22
|
+
@inline const FM_LOAD_N: i32 = 3;
|
|
23
|
+
// @ts-ignore: decorator
|
|
24
|
+
@inline const FM_LOAD_D: i32 = 4;
|
|
25
|
+
|
|
26
|
+
/** Structure of a FixedMap slot. */
|
|
27
|
+
@unmanaged class FixedMapSlot<K,V> {
|
|
28
|
+
hash: u32;
|
|
29
|
+
state: u8;
|
|
30
|
+
key: K;
|
|
31
|
+
value: V;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Computes the alignment of a slot. */
|
|
35
|
+
// @ts-ignore: decorator
|
|
36
|
+
@inline
|
|
37
|
+
function FM_SLOT_ALIGN<K,V>(): usize {
|
|
38
|
+
const maxkv = sizeof<K>() > sizeof<V>() ? sizeof<K>() : sizeof<V>();
|
|
39
|
+
const maxAll = maxkv > sizeof<u32>() ? maxkv : sizeof<u32>();
|
|
40
|
+
return maxAll - 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Computes the aligned size of a slot. */
|
|
44
|
+
// @ts-ignore: decorator
|
|
45
|
+
@inline
|
|
46
|
+
function FM_SLOT_SIZE<K,V>(): usize {
|
|
47
|
+
const align = FM_SLOT_ALIGN<K,V>();
|
|
48
|
+
return (offsetof<FixedMapSlot<K,V>>() + align) & ~align;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@final
|
|
52
|
+
export class FixedMap<K,V> {
|
|
53
|
+
|
|
54
|
+
private dataPtr: usize = 0;
|
|
55
|
+
private _capacity: i32 = 0;
|
|
56
|
+
private capacityMask: u32 = 0;
|
|
57
|
+
private _count: i32 = 0;
|
|
58
|
+
private _entriesUsed: i32 = 0;
|
|
59
|
+
|
|
60
|
+
constructor(initialCapacity: i32 = FM_INITIAL_CAPACITY) {
|
|
61
|
+
if (initialCapacity < 4) initialCapacity = 4;
|
|
62
|
+
let cap: i32 = 4;
|
|
63
|
+
while (cap < initialCapacity) cap <<= 1;
|
|
64
|
+
|
|
65
|
+
let bufferSize = <usize>cap * FM_SLOT_SIZE<K,V>();
|
|
66
|
+
let ptr: usize;
|
|
67
|
+
if (ASC_RUNTIME == Runtime.Memory) {
|
|
68
|
+
ptr = __alloc(bufferSize);
|
|
69
|
+
} else {
|
|
70
|
+
ptr = __new(bufferSize, idof<ArrayBuffer>());
|
|
71
|
+
}
|
|
72
|
+
memory.fill(ptr, 0, bufferSize);
|
|
73
|
+
this.dataPtr = ptr;
|
|
74
|
+
this._capacity = cap;
|
|
75
|
+
this.capacityMask = <u32>(cap - 1);
|
|
76
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
77
|
+
__link(changetype<usize>(this), ptr, false);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get size(): i32 {
|
|
82
|
+
return this._count;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
has(key: K): bool {
|
|
86
|
+
return this.findSlot(key, HASH<K>(key)) != -1;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@operator("[]")
|
|
90
|
+
get(key: K): V {
|
|
91
|
+
let idx = this.findSlot(key, HASH<K>(key));
|
|
92
|
+
if (idx == -1) throw new Error(E_KEYNOTFOUND);
|
|
93
|
+
let slot = changetype<FixedMapSlot<K,V>>(
|
|
94
|
+
this.dataPtr + <usize>idx * FM_SLOT_SIZE<K,V>()
|
|
95
|
+
);
|
|
96
|
+
return slot.value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@operator("[]=")
|
|
100
|
+
set(key: K, value: V): this {
|
|
101
|
+
// Check load factor before insert
|
|
102
|
+
if (this._entriesUsed * FM_LOAD_D >= this._capacity * FM_LOAD_N) {
|
|
103
|
+
this.rehash(
|
|
104
|
+
this._count * 2 > this._capacity
|
|
105
|
+
? this._capacity << 1
|
|
106
|
+
: this._capacity
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let hashCode = HASH<K>(key);
|
|
111
|
+
let mask = this.capacityMask;
|
|
112
|
+
let start = hashCode & mask;
|
|
113
|
+
let i = start;
|
|
114
|
+
let data = this.dataPtr;
|
|
115
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
116
|
+
let firstDeleted: i32 = -1;
|
|
117
|
+
|
|
118
|
+
do {
|
|
119
|
+
let slot = changetype<FixedMapSlot<K,V>>(data + <usize>i * slotSize);
|
|
120
|
+
let state = slot.state;
|
|
121
|
+
|
|
122
|
+
if (state == SLOT_OCCUPIED) {
|
|
123
|
+
if (slot.hash == hashCode && slot.key == key) {
|
|
124
|
+
slot.value = value;
|
|
125
|
+
if (isManaged<V>()) {
|
|
126
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
127
|
+
__link(changetype<usize>(this), changetype<usize>(value), true);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
} else if (state == SLOT_EMPTY) {
|
|
133
|
+
let insertIdx: u32 = firstDeleted != -1 ? <u32>firstDeleted : i;
|
|
134
|
+
let insertSlot = changetype<FixedMapSlot<K,V>>(data + <usize>insertIdx * slotSize);
|
|
135
|
+
insertSlot.hash = hashCode;
|
|
136
|
+
insertSlot.state = SLOT_OCCUPIED;
|
|
137
|
+
insertSlot.key = key;
|
|
138
|
+
insertSlot.value = value;
|
|
139
|
+
++this._count;
|
|
140
|
+
if (firstDeleted == -1) ++this._entriesUsed;
|
|
141
|
+
if (isManaged<K>()) {
|
|
142
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
143
|
+
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (isManaged<V>()) {
|
|
147
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
148
|
+
__link(changetype<usize>(this), changetype<usize>(value), true);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return this;
|
|
152
|
+
} else { // DELETED
|
|
153
|
+
if (firstDeleted == -1) firstDeleted = <i32>i;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
i = (i + 1) & mask;
|
|
157
|
+
} while (i != start);
|
|
158
|
+
|
|
159
|
+
// All slots are OCCUPIED or DELETED (shouldn't happen with load factor check)
|
|
160
|
+
// Insert at firstDeleted if available
|
|
161
|
+
if (firstDeleted != -1) {
|
|
162
|
+
let insertSlot = changetype<FixedMapSlot<K,V>>(data + <usize>firstDeleted * slotSize);
|
|
163
|
+
insertSlot.hash = hashCode;
|
|
164
|
+
insertSlot.state = SLOT_OCCUPIED;
|
|
165
|
+
insertSlot.key = key;
|
|
166
|
+
insertSlot.value = value;
|
|
167
|
+
++this._count;
|
|
168
|
+
if (isManaged<K>()) {
|
|
169
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
170
|
+
__link(changetype<usize>(this), changetype<usize>(key), true);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (isManaged<V>()) {
|
|
174
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
175
|
+
__link(changetype<usize>(this), changetype<usize>(value), true);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
delete(key: K): bool {
|
|
183
|
+
let idx = this.findSlot(key, HASH<K>(key));
|
|
184
|
+
if (idx == -1) return false;
|
|
185
|
+
let slot = changetype<FixedMapSlot<K,V>>(
|
|
186
|
+
this.dataPtr + <usize>idx * FM_SLOT_SIZE<K,V>()
|
|
187
|
+
);
|
|
188
|
+
slot.state = SLOT_DELETED;
|
|
189
|
+
--this._count;
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
clear(): void {
|
|
194
|
+
memory.fill(this.dataPtr, 0, <usize>this._capacity * FM_SLOT_SIZE<K,V>());
|
|
195
|
+
this._count = 0;
|
|
196
|
+
this._entriesUsed = 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
keys(): K[] {
|
|
200
|
+
let data = this.dataPtr;
|
|
201
|
+
let cap = this._capacity;
|
|
202
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
203
|
+
let keys = new Array<K>(this._count);
|
|
204
|
+
let length = 0;
|
|
205
|
+
for (let i = 0; i < cap; ++i) {
|
|
206
|
+
let slot = changetype<FixedMapSlot<K,V>>(data + <usize>i * slotSize);
|
|
207
|
+
if (slot.state == SLOT_OCCUPIED) {
|
|
208
|
+
unchecked(keys[length++] = slot.key);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
keys.length = length;
|
|
212
|
+
return keys;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
values(): V[] {
|
|
216
|
+
let data = this.dataPtr;
|
|
217
|
+
let cap = this._capacity;
|
|
218
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
219
|
+
let values = new Array<V>(this._count);
|
|
220
|
+
let length = 0;
|
|
221
|
+
for (let i = 0; i < cap; ++i) {
|
|
222
|
+
let slot = changetype<FixedMapSlot<K,V>>(data + <usize>i * slotSize);
|
|
223
|
+
if (slot.state == SLOT_OCCUPIED) {
|
|
224
|
+
unchecked(values[length++] = slot.value);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
values.length = length;
|
|
228
|
+
return values;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
toString(): string {
|
|
232
|
+
return "[object FixedMap]";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@inline
|
|
236
|
+
private findSlot(key: K, hashCode: u32): i32 {
|
|
237
|
+
let mask = this.capacityMask;
|
|
238
|
+
let start = hashCode & mask;
|
|
239
|
+
let i = start;
|
|
240
|
+
let data = this.dataPtr;
|
|
241
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
242
|
+
do {
|
|
243
|
+
let slot = changetype<FixedMapSlot<K,V>>(data + <usize>i * slotSize);
|
|
244
|
+
let state = slot.state;
|
|
245
|
+
if (state == SLOT_EMPTY) return -1;
|
|
246
|
+
if (state == SLOT_OCCUPIED && slot.hash == hashCode && slot.key == key) {
|
|
247
|
+
return <i32>i;
|
|
248
|
+
}
|
|
249
|
+
i = (i + 1) & mask;
|
|
250
|
+
} while (i != start);
|
|
251
|
+
return -1;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private rehash(newCapacity: i32): void {
|
|
255
|
+
let oldData = this.dataPtr;
|
|
256
|
+
let oldCapacity = this._capacity;
|
|
257
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
258
|
+
let newMask = <u32>(newCapacity - 1);
|
|
259
|
+
let bufferSize = <usize>newCapacity * slotSize;
|
|
260
|
+
|
|
261
|
+
let newData: usize;
|
|
262
|
+
if (ASC_RUNTIME == Runtime.Memory) {
|
|
263
|
+
newData = __alloc(bufferSize);
|
|
264
|
+
} else {
|
|
265
|
+
newData = __new(bufferSize, idof<ArrayBuffer>());
|
|
266
|
+
}
|
|
267
|
+
memory.fill(newData, 0, bufferSize);
|
|
268
|
+
|
|
269
|
+
for (let i = 0; i < oldCapacity; ++i) {
|
|
270
|
+
let oldSlot = changetype<FixedMapSlot<K,V>>(oldData + <usize>i * slotSize);
|
|
271
|
+
if (oldSlot.state == SLOT_OCCUPIED) {
|
|
272
|
+
let h = oldSlot.hash;
|
|
273
|
+
let j = h & newMask;
|
|
274
|
+
while (changetype<FixedMapSlot<K,V>>(newData + <usize>j * slotSize).state != SLOT_EMPTY) {
|
|
275
|
+
j = (j + 1) & newMask;
|
|
276
|
+
}
|
|
277
|
+
let newSlot = changetype<FixedMapSlot<K,V>>(newData + <usize>j * slotSize);
|
|
278
|
+
newSlot.hash = h;
|
|
279
|
+
newSlot.state = SLOT_OCCUPIED;
|
|
280
|
+
newSlot.key = oldSlot.key;
|
|
281
|
+
newSlot.value = oldSlot.value;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this.dataPtr = newData;
|
|
286
|
+
this._capacity = newCapacity;
|
|
287
|
+
this.capacityMask = newMask;
|
|
288
|
+
this._entriesUsed = this._count;
|
|
289
|
+
|
|
290
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
291
|
+
__link(changetype<usize>(this), newData, false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// RT integration
|
|
296
|
+
|
|
297
|
+
@unsafe private __visit(cookie: u32): void {
|
|
298
|
+
if (ASC_RUNTIME != Runtime.Memory) {
|
|
299
|
+
let data = this.dataPtr;
|
|
300
|
+
if (data) {
|
|
301
|
+
if (isManaged<K>() || isManaged<V>()) {
|
|
302
|
+
let cap = this._capacity;
|
|
303
|
+
let slotSize = FM_SLOT_SIZE<K,V>();
|
|
304
|
+
for (let i = 0; i < cap; ++i) {
|
|
305
|
+
let slot = changetype<FixedMapSlot<K,V>>(data + <usize>i * slotSize);
|
|
306
|
+
if (slot.state == SLOT_OCCUPIED) {
|
|
307
|
+
if (isManaged<K>()) {
|
|
308
|
+
let val = changetype<usize>(slot.key);
|
|
309
|
+
if (isNullable<K>()) {
|
|
310
|
+
if (val) __visit(val, cookie);
|
|
311
|
+
} else __visit(val, cookie);
|
|
312
|
+
}
|
|
313
|
+
if (isManaged<V>()) {
|
|
314
|
+
let val = changetype<usize>(slot.value);
|
|
315
|
+
if (isNullable<V>()) {
|
|
316
|
+
if (val) __visit(val, cookie);
|
|
317
|
+
} else __visit(val, cookie);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
__visit(data, cookie);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|