Skip to content

Commit 5675e9c

Browse files
authored
Dev (#3)
* added some more debug tools for vec classes, and fixed typos/broken links in readme * added the ability to create references * removed unneccessary try-catch blocks * updated readme to include info on references * fixed typos
1 parent 68bd5b3 commit 5675e9c

32 files changed

Lines changed: 1239 additions & 621 deletions

README.md

Lines changed: 237 additions & 170 deletions
Large diffs are not rendered by default.

benchmarks/public/dist/compiler.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function restrictedFieldName(name) {
2121
case "e":
2222
case "_viewingIndex":
2323
case "ref":
24-
case "isNull":
24+
case "index":
2525
return true;
2626
default:
2727
return false;
@@ -184,6 +184,11 @@ function reservedJsKeyword(word) {
184184
return false;
185185
}
186186
}
187+
export function invalidClassName(name) {
188+
return (!validVariableName(name)
189+
|| reservedJsKeyword(name)
190+
|| name.length < 1);
191+
}
187192
export function validateCompileOptions(input) {
188193
if (typeof input !== "object"
189194
|| input === null
@@ -195,9 +200,7 @@ export function validateCompileOptions(input) {
195200
throw TypeError("option 'pathToLib' missing");
196201
}
197202
if (typeof input.className !== "string"
198-
|| !validVariableName(input.className)
199-
|| reservedJsKeyword(input.className)
200-
|| input.className.length < 1) {
203+
|| invalidClassName(input.className)) {
201204
throw SyntaxError(`inputted class name is not a valid javascript class name, got "${input.className}"`);
202205
}
203206
switch (input.exportSyntax) {
@@ -218,7 +221,7 @@ export function createVecDef(tokens, structDef, { lang, pathToLib, className, ex
218221
const ts = lang === "ts";
219222
const generic = `<${def}>`;
220223
const libPath = `"${pathToLib}"`;
221-
const importStatement = `import {Vec${ts ? ", StructDef, Struct, CursorConstructor" : ""}} from ${libPath}`;
224+
const importStatement = `import {Vec${ts ? ", StructDef, Struct, CursorConstructor, VecCursor, DetachedVecCursor" : ""}} from ${libPath}`;
222225
const CursorConstructor = "CursorConstructor" + generic;
223226
const memory = ts ?
224227
"(this.self as unknown as {_f32Memory: Float32Array})._f32Memory"
@@ -236,9 +239,11 @@ ${ts || runtimeCompile
236239
* @extends {Vec${generic}}
237240
*/`}
238241
${exportSyntax === "named" ? "export " : ""}class ${className} extends Vec${ts ? generic : ""} {
239-
${ts ? "protected " : ""}static Cursor = class Cursor {
240-
_viewingIndex = 0${ts ? "\n\t\tself: Vec" + generic : ""}
241-
constructor(self${ts ? ": Vec" + generic : ""}) { this.self = self }
242+
static ${ts ? "readonly " : ""}def${ts ? ": StructDef" : ""} = ${def}
243+
static ${ts ? "readonly " : ""}elementSize${ts ? ": number" : ""} = ${elementSize}
244+
${ts ? "protected " : ""}static Cursor = class ${className}Cursor {
245+
${ts ? `_viewingIndex: number\n\t\tself: Vec${generic}` : ""}
246+
constructor(self${ts ? ": Vec" + generic : ""}, index${ts ? ": number" : ""}) { this.self = self;this._viewingIndex = index}
242247
${float32Fields.map(({ field, offset }) => {
243248
const fieldOffset = offset < 1 ? "" : (" + " + offset.toString());
244249
const base = `${memory}[this._viewingIndex${fieldOffset}]`;
@@ -279,7 +284,9 @@ ${exportSyntax === "named" ? "export " : ""}class ${className} extends Vec${ts ?
279284
}).join(";")}; }
280285
get e()${ts ? ": Struct" + generic : ""} { return {${fieldNames.map((field) => {
281286
return field + ": this." + field;
282-
}).join(", ")}} }
287+
}).join(", ")}} }
288+
get ref()${ts ? `: VecCursor${generic}` : ""} { return new ${className}.Cursor(this.self, this._viewingIndex) }
289+
index(index${ts ? ": number" : ""})${ts ? `: DetachedVecCursor${generic}` : ""} { this._viewingIndex = index * this.self.elementSize; return this }
283290
}${ts ? " as " + CursorConstructor : ""}
284291
get elementSize()${ts ? ": number" : ""} { return ${elementSize} }
285292
get def()${ts ? ": StructDef" : ""} { return ${def} }

benchmarks/public/dist/core.js

Lines changed: 62 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,23 @@ export const VALID_DATA_TYPES_INTERNAL = [
88
];
99
export class Vec {
1010
constructor(initialCapacity = 15, memory) {
11-
try {
12-
let vecCapacity = 0;
13-
let vecLength = 0;
14-
let buffer;
15-
if (!memory) {
16-
vecCapacity = Math.abs(initialCapacity);
17-
buffer = this.createMemory(vecCapacity);
18-
}
19-
else {
20-
vecLength = memory[memory.length - 1];
21-
vecCapacity = memory[memory.length - 2];
22-
buffer = memory.buffer;
23-
}
24-
this._f32Memory = new Float32Array(buffer);
25-
this._i32Memory = new Int32Array(buffer);
26-
this._length = vecLength;
27-
this._capacity = vecCapacity;
28-
this._cursor = new this.cursorDef(this);
11+
let vecCapacity = 0;
12+
let vecLength = 0;
13+
let buffer;
14+
if (!memory) {
15+
vecCapacity = Math.abs(initialCapacity);
16+
buffer = this.createMemory(vecCapacity);
2917
}
30-
catch (err) {
31-
throw new Error(`[Vec::allocator] buffer memory failed to initialize. ${err}`);
18+
else {
19+
vecLength = memory[memory.length - 1];
20+
vecCapacity = memory[memory.length - 2];
21+
buffer = memory.buffer;
3222
}
23+
this._f32Memory = new Float32Array(buffer);
24+
this._i32Memory = new Int32Array(buffer);
25+
this._length = vecLength;
26+
this._capacity = vecCapacity;
27+
this._cursor = new this.cursorDef(this, 0);
3328
}
3429
static isVec(candidate) {
3530
return candidate instanceof this;
@@ -346,30 +341,24 @@ export class Vec {
346341
return this;
347342
}
348343
reserve(additional) {
349-
try {
350-
const elementSize = this.elementSize;
351-
const length = this._length;
352-
const capacity = this._capacity;
353-
if (length + additional <= capacity) {
354-
return;
355-
}
356-
const newCapacity = length + additional;
357-
const elementsMemory = (MEMORY_LAYOUT.BYTES_PER_ELEMENT
358-
* elementSize
359-
* newCapacity);
360-
const bufferSize = (8
361-
+ elementsMemory);
362-
const buffer = new BUFFER_TYPE(bufferSize);
363-
const memory = new MEMORY_LAYOUT(buffer);
364-
memory.set(this._f32Memory);
365-
this.replaceMemory(memory);
366-
this._capacity = newCapacity;
367-
return this;
368-
}
369-
catch (err) {
370-
console.error(`Vec ::allocator: runtime failed to allocate more memory for vec. Aborting operation`, err);
371-
throw err;
344+
const elementSize = this.elementSize;
345+
const length = this._length;
346+
const capacity = this._capacity;
347+
if (length + additional <= capacity) {
348+
return;
372349
}
350+
const newCapacity = length + additional;
351+
const elementsMemory = (MEMORY_LAYOUT.BYTES_PER_ELEMENT
352+
* elementSize
353+
* newCapacity);
354+
const bufferSize = (8
355+
+ elementsMemory);
356+
const buffer = new BUFFER_TYPE(bufferSize);
357+
const memory = new MEMORY_LAYOUT(buffer);
358+
memory.set(this._f32Memory);
359+
this.replaceMemory(memory);
360+
this._capacity = newCapacity;
361+
return this;
373362
}
374363
reverse() {
375364
const elementSize = this.elementSize;
@@ -481,25 +470,20 @@ export class Vec {
481470
const capacity = this._capacity;
482471
const minimumCapcity = length + structs.length;
483472
if (minimumCapcity > capacity) {
484-
try {
485-
const targetCapacity = capacity * 2;
486-
const newCapacity = minimumCapcity > targetCapacity
487-
? minimumCapcity + 15
488-
: targetCapacity;
489-
const elementsMemory = (MEMORY_LAYOUT.BYTES_PER_ELEMENT
490-
* elementSize
491-
* newCapacity);
492-
const bufferSize = (8
493-
+ elementsMemory);
494-
const buffer = new BUFFER_TYPE(bufferSize);
495-
const memory = new MEMORY_LAYOUT(buffer);
496-
memory.set(this._f32Memory);
497-
this.replaceMemory(memory);
498-
this._capacity = newCapacity;
499-
}
500-
catch (err) {
501-
throw new Error(`[Vec::allocator] runtime failed to allocate more memory for vec. ${err}`);
502-
}
473+
const targetCapacity = capacity * 2;
474+
const newCapacity = minimumCapcity > targetCapacity
475+
? minimumCapcity + 15
476+
: targetCapacity;
477+
const elementsMemory = (MEMORY_LAYOUT.BYTES_PER_ELEMENT
478+
* elementSize
479+
* newCapacity);
480+
const bufferSize = (8
481+
+ elementsMemory);
482+
const buffer = new BUFFER_TYPE(bufferSize);
483+
const memory = new MEMORY_LAYOUT(buffer);
484+
memory.set(this._f32Memory);
485+
this.replaceMemory(memory);
486+
this._capacity = newCapacity;
503487
}
504488
const previousIndex = this._cursor._viewingIndex;
505489
for (let i = 0; i < structs.length; i += 1) {
@@ -621,30 +605,24 @@ export class Vec {
621605
return newLength;
622606
}
623607
shrinkTo(minCapacity = 15) {
624-
try {
625-
const elementSize = this.elementSize;
626-
const length = this._length;
627-
const capacity = this._capacity;
628-
const minCapacityNormalize = minCapacity < 0
629-
? 0
630-
: minCapacity;
631-
const newCapacity = length + minCapacityNormalize;
632-
if (newCapacity >= capacity) {
633-
return this;
634-
}
635-
this._f32Memory = this.shrinkCapacity(newCapacity);
636-
this._capacity = newCapacity;
608+
const length = this._length;
609+
const capacity = this._capacity;
610+
const minCapacityNormalize = minCapacity < 0
611+
? 0
612+
: minCapacity;
613+
const newCapacity = length + minCapacityNormalize;
614+
if (newCapacity >= capacity) {
637615
return this;
638616
}
639-
catch (err) {
640-
throw new Error(`[Vec::allocator] runtime failed to deallocate memory for vec. ${err}`);
641-
}
617+
this._f32Memory = this.shrinkCapacity(newCapacity);
618+
this._capacity = newCapacity;
619+
return this;
642620
}
643621
sort(compareFn) {
644622
if (this._length < 2) {
645623
return this;
646624
}
647-
const helperCursor = new this.cursorDef(this);
625+
const helperCursor = new this.cursorDef(this, 0);
648626
this.reserve(1);
649627
const elementSize = this.elementSize;
650628
const temporaryIndex = this._length * elementSize;
@@ -701,6 +679,9 @@ export class Vec {
701679
memoryStr += `${this.elementSize},${this._capacity},${this._length}]`;
702680
return memoryStr;
703681
}
682+
detachedCursor(index) {
683+
return new this.cursorDef(this, index);
684+
}
704685
createMemory(capacity) {
705686
const elementsMemory = (MEMORY_LAYOUT.BYTES_PER_ELEMENT
706687
* this.elementSize
@@ -738,3 +719,5 @@ export class Vec {
738719
this._i32Memory = new Int32Array(memory.buffer);
739720
}
740721
}
722+
Vec.def = {};
723+
Vec.elementSize = 0;

benchmarks/public/dist/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Vec as BaseVec } from "./core.js";
2-
import { tokenizeStructDef, ERR_PREFIX, createVecDef, validateCompileOptions } from "./compiler.js";
2+
import { tokenizeStructDef, ERR_PREFIX, createVecDef, validateCompileOptions, invalidClassName } from "./compiler.js";
33
export { Vec } from "./core.js";
44
export function validateStructDef(def) {
55
try {
@@ -10,21 +10,25 @@ export function validateStructDef(def) {
1010
return false;
1111
}
1212
}
13-
export function vec(structDef) {
13+
export function vec(structDef, options = {}) {
1414
if (typeof SharedArrayBuffer === "undefined") {
1515
throw new Error(`${ERR_PREFIX} sharedArrayBuffers are not supported in this environment and are required for vecs`);
1616
}
1717
const tokens = tokenizeStructDef(structDef);
18-
const { def, className } = createVecDef(tokens, structDef, {
18+
const { className = "AnonymousVec" } = options;
19+
if (invalidClassName(className)) {
20+
throw SyntaxError(`inputted class name (className option) is not a valid javascript class name, got "${className}"`);
21+
}
22+
const { def, className: clsName } = createVecDef(tokens, structDef, {
1923
lang: "js",
2024
exportSyntax: "none",
2125
pathToLib: "none",
22-
className: "AnonymousVec",
26+
className,
2327
runtimeCompile: true
2428
});
2529
const genericVec = Function(`"use strict";return (Vec) => {
2630
${def}
27-
return ${className}
31+
return ${clsName}
2832
}`)()(BaseVec);
2933
return genericVec;
3034
}

benchmarks/public/index.mjs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
import {vec} from "../../dist/index.js"
22
import {Benchmark} from "./lib.mjs"
33

4-
const Position = vec({
5-
x: "f32",
6-
y: "f32",
7-
z: "f32"
8-
})
4+
const Position = vec({x: "f32", y: "f32", z: "f32"})
95

106
const elementCount = 10_000_000
117

128
const benchmark = new Benchmark()
139
benchmark
14-
/*
1510
.add("vec push", () => {
1611
const container = new Position()
1712
for (let i = 0; i < elementCount; i += 1) {
@@ -24,7 +19,7 @@ benchmark
2419
container.push({x: 1, y: 1, z: 1})
2520
}
2621
})
27-
*/
22+
/*
2823
.add("vec push with pre-alloc", () => {
2924
const container = new Position()
3025
container.reserve(elementCount)
@@ -38,4 +33,5 @@ benchmark
3833
container.push({x: 1, y: 1, z: 1})
3934
}
4035
})
36+
*/
4137
.run()

buildInfo/index.js.br

54 Bytes
Binary file not shown.

codegenTests/codegen.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ describe("generated vec classes have all the standard methods and properties", (
1313
expect(typeof NamedTs.fromMemory).toBe("function")
1414
expect(typeof NamedTs.fromString).toBe("function")
1515
expect(typeof NamedTs.isVec).toBe("function")
16+
expect(NamedTs.def).toEqual(structdef)
17+
expect(NamedTs.elementSize).toBe(3)
1618
const v = new NamedTs(15).fill({
1719
x: true, y: 10, z: "a"
1820
})
@@ -69,6 +71,8 @@ describe("generated vec classes have all the standard methods and properties", (
6971
expect(typeof NamedJs.fromMemory).toBe("function")
7072
expect(typeof NamedJs.fromString).toBe("function")
7173
expect(typeof NamedJs.isVec).toBe("function")
74+
expect(NamedJs.def).toEqual(structdef)
75+
expect(NamedJs.elementSize).toBe(3)
7276
const v = new NamedJs(15).fill({
7377
x: true, y: 10, z: "a"
7478
})
@@ -125,6 +129,8 @@ describe("generated vec classes have all the standard methods and properties", (
125129
expect(typeof defaultTs.DefaultTs.fromMemory).toBe("function")
126130
expect(typeof defaultTs.DefaultTs.fromString).toBe("function")
127131
expect(typeof defaultTs.DefaultTs.isVec).toBe("function")
132+
expect(defaultTs.DefaultTs.def).toEqual(structdef)
133+
expect(defaultTs.DefaultTs.elementSize).toBe(3)
128134
const v = new defaultTs.DefaultTs(15).fill({
129135
x: true, y: 10, z: "a"
130136
})
@@ -181,6 +187,8 @@ describe("generated vec classes have all the standard methods and properties", (
181187
expect(typeof defaultJs.DefaultJs.fromMemory).toBe("function")
182188
expect(typeof defaultJs.DefaultJs.fromString).toBe("function")
183189
expect(typeof defaultJs.DefaultJs.isVec).toBe("function")
190+
expect(defaultJs.DefaultJs.def).toEqual(structdef)
191+
expect(defaultJs.DefaultJs.elementSize).toBe(3)
184192
const v = new defaultJs.DefaultJs(15).fill({
185193
x: true, y: 10, z: "a"
186194
})

codegenTests/default-js.mjs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ import {Vec} from "../dist"
33
* @extends {Vec<{"x":"bool","y":"f32","z":"char"}>}
44
*/
55
class DefaultJs extends Vec {
6-
static Cursor = class Cursor {
7-
_viewingIndex = 0
8-
constructor(self) { this.self = self }
6+
static def = {"x":"bool","y":"f32","z":"char"}
7+
static elementSize = 3
8+
static Cursor = class DefaultJsCursor {
9+
10+
constructor(self, index) { this.self = self;this._viewingIndex = index}
911
get y() { return this.self._f32Memory[this._viewingIndex] }; set y(newValue) { this.self._f32Memory[this._viewingIndex] = newValue };
1012

1113
get z() { return String.fromCodePoint(this.self._i32Memory[this._viewingIndex + 1] || 32) }; set z(newValue) { this.self._i32Memory[this._viewingIndex + 1] = newValue.codePointAt(0) || 32 };
1214
get x() { return Boolean(this.self._i32Memory[this._viewingIndex + 2] & 1) }; set x(newValue) { this.self._i32Memory[this._viewingIndex + 2] &= -2;this.self._i32Memory[this._viewingIndex + 2] |= Boolean(newValue)};
1315
set e({y, z, x}) { this.y = y;this.z = z;this.x = x; }
14-
get e() { return {y: this.y, z: this.z, x: this.x} }
16+
get e() { return {y: this.y, z: this.z, x: this.x} }
17+
get ref() { return new DefaultJs.Cursor(this.self, this._viewingIndex) }
18+
index(index) { this._viewingIndex = index * this.self.elementSize; return this }
1519
}
1620
get elementSize() { return 3 }
1721
get def() { return {"x":"bool","y":"f32","z":"char"} }

0 commit comments

Comments
 (0)