mirror of
https://github.com/remko/waforth
synced 2024-12-26 09:59:09 +01:00
Support reading long strings
This commit is contained in:
parent
ff84035919
commit
236ad04aa5
3 changed files with 57 additions and 38 deletions
|
@ -2758,29 +2758,34 @@
|
|||
(local $result i32)
|
||||
(local $tos i32)
|
||||
(local.tee $tos (global.get $tos))
|
||||
(call $REFILL)
|
||||
(drop (call $pop))
|
||||
(local.set $result (call $interpret))
|
||||
(global.set $tos)
|
||||
(block $endLoop (param i32) (result i32)
|
||||
(loop $loop (param i32) (result i32)
|
||||
(call $REFILL)
|
||||
(br_if $endLoop (i32.eqz (call $pop)))
|
||||
(local.set $result (call $interpret))
|
||||
(local.set $tos)
|
||||
|
||||
;; Check for stack underflow
|
||||
(if (i32.lt_s (global.get $tos) (i32.const 0x10000 (; = STACK_BASE ;)))
|
||||
(drop (call $fail (global.get $tos) (i32.const 0x200B2 (; stack empty ;)))))
|
||||
|
||||
(if (i32.ge_s (local.get $result) (i32.const 0))
|
||||
(then
|
||||
;; Write ok
|
||||
(call $shell_emit (i32.const 111))
|
||||
(call $shell_emit (i32.const 107)))
|
||||
(else
|
||||
;; Write error
|
||||
(call $shell_emit (i32.const 101))
|
||||
(call $shell_emit (i32.const 114))
|
||||
(call $shell_emit (i32.const 114))
|
||||
(call $shell_emit (i32.const 111))
|
||||
(call $shell_emit (i32.const 114))))
|
||||
(call $shell_emit (i32.const 10))
|
||||
(local.get $result))
|
||||
;; Check for stack underflow
|
||||
(if (i32.lt_s (local.get $tos) (i32.const 0x10000 (; = STACK_BASE ;)))
|
||||
(drop (call $fail (local.get $tos) (i32.const 0x200B2 (; stack empty ;)))))
|
||||
|
||||
(if (i32.ge_s (local.get $result) (i32.const 0))
|
||||
(then
|
||||
;; Write ok
|
||||
(call $shell_emit (i32.const 111))
|
||||
(call $shell_emit (i32.const 107)))
|
||||
(else
|
||||
;; Write error
|
||||
(call $shell_emit (i32.const 101))
|
||||
(call $shell_emit (i32.const 114))
|
||||
(call $shell_emit (i32.const 114))
|
||||
(call $shell_emit (i32.const 111))
|
||||
(call $shell_emit (i32.const 114))))
|
||||
(call $shell_emit (i32.const 10))
|
||||
(local.get $tos)
|
||||
(br $loop)))
|
||||
(global.set $tos)
|
||||
(local.get $result))
|
||||
|
||||
(func (export "push") (param $v i32)
|
||||
(global.set $tos (call $push (global.get $tos) (local.get $v))))
|
||||
|
|
|
@ -222,6 +222,15 @@ function loadTests() {
|
|||
expect(() => core.interpret()).to.throw();
|
||||
expect(output.trim()).to.eql("undefined word: 23FOO");
|
||||
});
|
||||
|
||||
it("should interpret a long string", () => {
|
||||
const p = ["1"];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
p.push(`${1} +`);
|
||||
}
|
||||
forth.interpret(p.join("\n"));
|
||||
expect(stackValues()).to.eql([1001]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("DUP", () => {
|
||||
|
|
|
@ -46,7 +46,7 @@ function saveString(s: string, memory: WebAssembly.Memory, addr: number) {
|
|||
* */
|
||||
class WAForth {
|
||||
core?: WebAssembly.Instance;
|
||||
#buffer?: number[];
|
||||
#buffer?: string;
|
||||
#fns: Record<string, (f: WAForth) => void>;
|
||||
|
||||
/**
|
||||
|
@ -96,7 +96,7 @@ class WAForth {
|
|||
async load() {
|
||||
let table: WebAssembly.Table;
|
||||
let memory: WebAssembly.Memory;
|
||||
this.#buffer = [];
|
||||
this.#buffer = "";
|
||||
|
||||
const instance = await WebAssembly.instantiate(wasmModule, {
|
||||
shell: {
|
||||
|
@ -111,17 +111,22 @@ class WAForth {
|
|||
},
|
||||
|
||||
read: (addr: number, length: number): number => {
|
||||
let data = new Uint8Array(
|
||||
(this.core!.exports.memory as WebAssembly.Memory).buffer,
|
||||
addr,
|
||||
length
|
||||
);
|
||||
let n = 0;
|
||||
while (this.#buffer!.length > 0 && n < length) {
|
||||
data[n] = this.#buffer!.shift()!;
|
||||
n += 1;
|
||||
let input: string;
|
||||
if (this.#buffer!.length <= length) {
|
||||
input = this.#buffer!;
|
||||
this.#buffer = "";
|
||||
} else {
|
||||
const i = this.#buffer!.lastIndexOf("\n", length - 1);
|
||||
input = this.#buffer!.substring(0, i + 1);
|
||||
this.#buffer = this.#buffer!.substring(i + 1);
|
||||
}
|
||||
return n;
|
||||
// console.log("read: %s (%d remaining)", input, this.#buffer!.length);
|
||||
saveString(
|
||||
input,
|
||||
this.core!.exports.memory as WebAssembly.Memory,
|
||||
addr
|
||||
);
|
||||
return input.length;
|
||||
},
|
||||
|
||||
key: () => {
|
||||
|
@ -215,16 +220,16 @@ class WAForth {
|
|||
* Read data `s` into the input buffer without interpreting it.
|
||||
*/
|
||||
read(s: string) {
|
||||
const data = new TextEncoder().encode(s);
|
||||
for (let i = 0, len = data.length; i < len; ++i) {
|
||||
this.#buffer!.push(data[i]);
|
||||
}
|
||||
this.#buffer = this.#buffer + s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data `s` into the input buffer, and interpret.
|
||||
*/
|
||||
interpret(s: string) {
|
||||
if (!s.endsWith("\n")) {
|
||||
s = s + "\n";
|
||||
}
|
||||
this.read(s);
|
||||
try {
|
||||
return (this.core!.exports.interpret as any)();
|
||||
|
|
Loading…
Reference in a new issue