Skip to content

Commit

Permalink
Add jsdoc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
remko committed Feb 18, 2024
1 parent 5a19a40 commit 95014d9
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 7 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ clean:
lint:
$(ESLINT) .

TSC ?= tsc
lint-tsc:
$(TSC) --project jsconfig.json --noEmit
17 changes: 17 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"noImplicitAny": true,
"target": "es2017",
"strict": true,
"checkJs": true,
"baseUrl": "src"
},
"include": [
"src"
],
"exclude": [
"src/tests",
"src/benchmarks",
"src/examples"
]
}
39 changes: 36 additions & 3 deletions src/util/asm.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const opcodes = [
"SFT",
];

/**
* @param {string} s
* @returns {number}
*/
function opcode(s) {
if (s === "BRK") {
return 0;
Expand Down Expand Up @@ -72,28 +76,50 @@ function opcode(s) {
return -1;
}

/**
* @param {string} c
* @returns {boolean}
*/
function isNumber(c) {
return /^([0-9A-Fa-f]{4}|[0-9A-Fa-f]{2})$/.test(c);
}

/**
* @param {string} c
* @returns {boolean}
*/
function isWhitespace(c) {
return /\s/.test(c);
}

/**
* @param {string} l
* @returns {string}
*/
function assertValidName(l) {
if (isNumber(l)) {
throw new Error(`label is a number: ${l}`);
}
return l;
}

/**
* @param {string} label
* @param {string} currentLabel
* @returns {string}
*/
function expandLabel(label, currentLabel) {
if (label.startsWith("&")) {
return currentLabel + "/" + assertValidName(label.slice(1));
}
return assertValidName(label);
}

/**
* @param {string} source
* @param {{include: (file: string) => string}} options
* @returns {Uint8Array}
*/
export function asm(
source,
options = {
Expand Down Expand Up @@ -143,8 +169,10 @@ export function asm(
////////////////////////////////////////////////////////////////////////////////

let cp = 0x100;
/** @type {number[]} */
const code = [];

/** @param {...number} cs */
function emit(...cs) {
if (cp < 0x100) {
throw Error("unexpected emit");
Expand All @@ -155,6 +183,7 @@ export function asm(
}
}

/** @param {...number} cs */
function emit2(...cs) {
if (cp < 0x100) {
throw Error("unexpected emit");
Expand All @@ -168,15 +197,19 @@ export function asm(

////////////////////////////////////////////////////////////////////////////////

/** @type {number[]} */
const lambdas = [];
/** @type {Record<string, string>} */
const macros = {};
/** @type {Record<string, number>} */
const labels = {};
/** @type {Array<{type: "-"|","|"."|";"|"="|"!"|"_"|"-"|"?"|""; label: string; offset: number}>} */
const refs = [];
let currentLabel = "on-reset";

for (let token = readToken(); token != null; token = readToken()) {
const c0 = token[0];
const rtoken = token.substr(1);
const rtoken = token.substring(1);
if (token === "[" || token === "]") {
continue;
} else if (token === "{") {
Expand All @@ -186,10 +219,10 @@ export function asm(
emit(JCI, 0x00, 0x00);
lambdas.push(cp - 2);
} else if (token === "}") {
if (lambdas.length <= 0) {
const l = lambdas.pop();
if (l == null) {
throw new Error("unexpected lambda end");
}
const l = lambdas.pop();
const ocp = cp;
cp = l;
emit2(ocp - cp - 2);
Expand Down
29 changes: 28 additions & 1 deletion src/util/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
export { asm } from "./asm.js";
export { decodeUlz, encodeUlz } from "./ulz.js";

/**
* @param {Uint8Array} mem
* @param {number} addr
* @returns {number}
*/
export function peek16(mem, addr) {
return (mem[addr] << 8) | mem[addr + 1];
}

/**
* @param {Uint8Array} mem
* @param {number} addr
* @param {number} val
*/
export function poke16(mem, addr, val) {
mem[addr] = val >> 8;
mem[addr + 1] = val;
}

/**
* @typedef {{
* deo?: (port: number, val: number) => void;
* dei?: (port: number) => number;
* }} Device
*/

/**
* @param {import("../uxn.js").Uxn} uxn
* @param {Record<number, Device>} devices
* @returns {Device}
*/
export function mux(uxn, devices) {
return {
deo(port, val) {
Expand All @@ -34,16 +56,20 @@ export function mux(uxn, devices) {
* the callback whenever a complete newline-delimited line is received.
*
* The resulting function also has a `flush()` function to flush any remaining output.
* @param {(line: string) => void} fn
* @returns {{(c: number): void; flush: () => void;}}
*/
function withLineBuffer(fn) {
/** @type {number[]} */
let buffer = [];
const flush = () => {
if (buffer.length > 0) {
fn(new TextDecoder().decode(Uint8Array.from(buffer)));
buffer = [];
}
};
const r = (c) => {
const r = (/** @type {number} */ c) => {
buffer.push(c);
if (c == 0xa) {
flush();
Expand All @@ -53,6 +79,7 @@ function withLineBuffer(fn) {
return r;
}

/** @returns {Device & {flush: () => void}} */
export function LogConsole() {
const out = withLineBuffer(console.log);
return {
Expand Down
17 changes: 17 additions & 0 deletions src/util/ulz.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
/**
* @param {Uint8Array} src
* @returns {Uint8Array}
*/
export function decodeUlz(src) {
/** @type {number[]} */
const dst = [];
let sp = 0;
while (sp < src.length) {
Expand Down Expand Up @@ -39,6 +44,13 @@ export function decodeUlz(src) {

const MIN_MAX_LENGTH = 4;

/**
* @param {Uint8Array} src
* @param {number} sp
* @param {number} dlen
* @param {number} slen
* @returns {[number, number]}
*/
function findBestMatch(src, sp, dlen, slen) {
let bmlen = 0;
let bmp = 0;
Expand All @@ -61,7 +73,12 @@ function findBestMatch(src, sp, dlen, slen) {
return [bmp, bmlen];
}

/**
* @param {Uint8Array} src
* @returns {Uint8Array}
*/
export function encodeUlz(src) {
/** @type {number[]} */
let dst = [];
let sp = 0;
let litp = -1;
Expand Down
31 changes: 28 additions & 3 deletions src/uxn.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
// @ts-ignore
import wasmModule from "./uxn.wat";

/**
* @constructor
*/
export function Uxn() {
let core, wst, rst;
/**
* @type {{
* eval: (addr: number) => void;
* wstp: () => number;
* rstp: () => number;
* reset: () => void;
* memory: WebAssembly.Memory;
* }}
*/
let core;

/** @type {Uint8Array} */
let wst;

/** @type {Uint8Array} */
let rst;

const reset = () => {
core.reset();
};

/** @type {(system: {dei?: (addr: number) => number; deo?: (addr: number, val: number) => void; }) => Promise<void>} */
this.init = async (system) => {
system = system != null ? system : {};
core = (
core = /** @type {*} */ (
await WebAssembly.instantiate(wasmModule, {
system: {
deo: system.deo != null ? system.deo : () => {},
dei:
system.dei != null
? system.dei
: (port) => {
: (/** @type {number} */ port) => {
return this.dev[port];
},
},
Expand All @@ -28,6 +48,7 @@ export function Uxn() {
this.dev = new Uint8Array(core.memory.buffer, 0x10200, 0x100);
};

/** @type {(rom: Uint8Array) => Uxn} */
this.load = (rom) => {
reset();
for (let i = 0, len = rom.length; i < len; ++i) {
Expand All @@ -36,10 +57,13 @@ export function Uxn() {
return this;
};

/** @type {(addr: number) => void} */
this.eval = (addr = 0x100) => {
core.eval(addr);
};

/** @typedef {{get: (i: number) => number; ptr: () => number; }} Stack */
/** @type {Stack} */
this.wst = {
get: (i) => {
return wst[0xff - i];
Expand All @@ -49,6 +73,7 @@ export function Uxn() {
},
};

/** @type {Stack} */
this.rst = {
get: (i) => {
return rst[0xff - i];
Expand Down

0 comments on commit 95014d9

Please sign in to comment.