Skip to content

Commit 725fa2a

Browse files
committed
feat: new class-based API
The new API exposes pioasm errors and exit code. It also enables the creation of multiple pioasm instances.
1 parent 374df09 commit 725fa2a

File tree

4 files changed

+91
-47
lines changed

4 files changed

+91
-47
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@ yarn add pioasm
2525
Usage example:
2626

2727
```javascript
28-
import { pioasm } from 'pioasm';
28+
import { PIOAssembler } from 'pioasm';
2929

3030
const source = `
3131
.program blink
3232
pull block
3333
out y, 32
3434
`;
3535

36-
pioasm(source).then(result => {
37-
console.log(result);
36+
const pioasm = new PIOAssembler();
37+
pioasm.assemble(source).then(result => {
38+
console.log(result.output);
3839
})
3940
```
4041

pioasm.js

+62-41
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
import wasm from '#pioasm-emcc';
88

9-
let instance = null;
10-
let outputBuffer = [];
11-
129
/**
1310
* PIO Output format:
1411
* - c-sdk: C header suitable for use with the Raspberry Pi Pico SDK
@@ -20,46 +17,70 @@ let outputBuffer = [];
2017
*/
2118

2219
/**
23-
* Loads the pioasm Web Assembly module. Normally, `pioasm()` will load the module for
24-
* you, but you can use the `load()` method to pre-loader the Web Assembly module, or
25-
* if you need to provide custom options to EMScripten.
26-
*
27-
* For instance, you can override the `locateFile(url: string, scriptDirectory: string)`
28-
* method to configure the URL for the compiled web assembly module.
29-
*
30-
* @param {Partial<EmscriptenModule>} [options]
31-
* @returns {Promise<EmscriptenModule>}
20+
* PIO Assembler wrapper class
3221
*/
33-
export async function load(options) {
34-
if (!instance) {
35-
instance = wasm({
36-
noInitialRun: true,
37-
print(msg) {
38-
outputBuffer.push(msg);
39-
},
40-
...options,
41-
});
22+
export class PIOAssembler {
23+
/** @private */
24+
exitCode = 0;
25+
/** @private */
26+
outputBuffer = [];
27+
/** @private */
28+
instance;
29+
30+
constructor() {}
31+
32+
/**
33+
* Loads the pioasm Web Assembly module. Normally, `pioasm()` will load the module for
34+
* you, but you can use the `load()` method to pre-loader the Web Assembly module, or
35+
* if you need to provide custom options to EMScripten.
36+
*
37+
* For instance, you can override the `locateFile(url: string, scriptDirectory: string)`
38+
* method to configure the URL for the compiled web assembly module.
39+
*
40+
* @param {Partial<EmscriptenModule>} [options]
41+
* @returns {Promise<EmscriptenModule>}
42+
*/
43+
async load(options) {
44+
if (!this.instance) {
45+
this.instance = wasm({
46+
noInitialRun: true,
47+
print: (msg) => {
48+
this.outputBuffer.push(msg);
49+
},
50+
printErr: (msg) => {
51+
this.outputBuffer.push(msg);
52+
},
53+
quit: (code) => {
54+
this.exitCode = code;
55+
},
56+
...options,
57+
});
58+
}
59+
return this.instance;
4260
}
43-
return await instance;
44-
}
4561

46-
/**
47-
* Compiles the given PIO source file.
48-
*
49-
* @param {string} source PIO source to compile
50-
* @param {PioOutputFormat} [format='c-sdk'] Output format
51-
* @param {string} [outputParam] Add a parameter to be passed to the output format generator
52-
* @returns Promise<String>
53-
*/
54-
export async function pioasm(source, format = 'c-sdk', outputParam) {
55-
const runtime = await load();
56-
runtime.FS_writeFile('/input.pio', source);
57-
outputBuffer = [];
58-
const argv = ['-o', format];
59-
if (outputParam) {
60-
argv.push('-p', outputParam);
62+
/**
63+
* Compiles the given PIO source file.
64+
*
65+
* @param {string} source PIO source to compile
66+
* @param {PioOutputFormat} [format='c-sdk'] Output format
67+
* @param {string} [outputParam] Add a parameter to be passed to the output format generator
68+
* @returns Promise<{output: string, exitCode: number}>
69+
*/
70+
async assemble(source, format = 'c-sdk', outputParam) {
71+
const runtime = await this.load();
72+
runtime.FS_writeFile('/input.pio', source);
73+
this.outputBuffer = [];
74+
this.exitCode = 0;
75+
const argv = ['-o', format];
76+
if (outputParam) {
77+
argv.push('-p', outputParam);
78+
}
79+
argv.push('input.pio');
80+
runtime.callMain(argv);
81+
return {
82+
output: this.outputBuffer.join('\n'),
83+
exitCode: this.exitCode,
84+
};
6185
}
62-
argv.push('input.pio');
63-
runtime.callMain(argv);
64-
return outputBuffer.join('\n');
6586
}
File renamed without changes.

test.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import assert from 'assert';
6-
import { pioasm } from './pioasm.js';
6+
import { PIOAssembler } from './pioasm.js';
77

88
const testInput = `
99
.program blink
@@ -30,9 +30,31 @@ def blink():
3030
3131
`;
3232

33+
const badProgram = `
34+
.program bad
35+
jmp unknown
36+
`;
37+
3338
async function main() {
34-
assert.strictEqual(await pioasm(testInput, 'python'), expectedOutput);
35-
assert.strictEqual(await pioasm(testInput, 'hex'), '80a0\n6040');
39+
const pioasm = new PIOAssembler();
40+
41+
assert.deepStrictEqual(await pioasm.assemble(testInput, 'python'), {
42+
output: expectedOutput,
43+
exitCode: 0,
44+
});
45+
46+
assert.deepStrictEqual(await pioasm.assemble(testInput, 'hex'), {
47+
output: '80a0\n6040',
48+
exitCode: 0,
49+
});
50+
51+
assert.deepStrictEqual(await pioasm.assemble(badProgram, 'c-sdk'), {
52+
output: `input.pio:3.7-13: undefined symbol 'unknown'
53+
3 | jmp unknown
54+
| ^~~~~~~`,
55+
exitCode: 1,
56+
});
57+
3658
console.log('Test passed successfully!');
3759
}
3860

0 commit comments

Comments
 (0)