mirror of
https://github.com/remko/waforth
synced 2024-12-27 09:59:29 +01:00
vscode-extension: Import
This commit is contained in:
parent
cd6e712b75
commit
4f154243b5
20 changed files with 789 additions and 18 deletions
15
.github/workflows/build-vscode-extension.yml
vendored
Normal file
15
.github/workflows/build-vscode-extension.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
name: Build VS Code Extension
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: ./.github/actions/setup
|
||||||
|
- run: make -C src/web/vscode-extension install-deps package
|
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Run VS Code Extension",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"debugWebviews": true,
|
||||||
|
"request": "launch",
|
||||||
|
"runtimeExecutable": "${execPath}",
|
||||||
|
"args": [
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}/src/web/vscode-extension",
|
||||||
|
"${workspaceFolder}/src/web/vscode-extension/examples"
|
||||||
|
],
|
||||||
|
"outFiles": ["${workspaceFolder}/src/web/vscode-extension/dist/*.js"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.5",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^17.0.31",
|
"@types/node": "^17.0.31",
|
||||||
|
"@types/vscode": "^1.73.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||||
"@typescript-eslint/parser": "^5.30.5",
|
"@typescript-eslint/parser": "^5.30.5",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import * as jsx from "./jsx";
|
import WAForth, { ErrorCode } from "waforth";
|
||||||
import WAForth from "waforth";
|
|
||||||
import thurtleFS from "./thurtle.fs";
|
import thurtleFS from "./thurtle.fs";
|
||||||
import turtle from "./turtle.svg";
|
import turtle from "./turtle.svg";
|
||||||
|
|
||||||
const padding = 0.05;
|
const padding = 0.025;
|
||||||
|
|
||||||
enum PenState {
|
enum PenState {
|
||||||
Up = 0,
|
Up = 0,
|
||||||
|
@ -18,14 +17,16 @@ type Path = {
|
||||||
export default async function draw({
|
export default async function draw({
|
||||||
program,
|
program,
|
||||||
drawEl,
|
drawEl,
|
||||||
outputEl,
|
onEmit,
|
||||||
showTurtle = true,
|
showTurtle = true,
|
||||||
|
jsx,
|
||||||
}: {
|
}: {
|
||||||
program?: string;
|
program?: string;
|
||||||
drawEl: SVGSVGElement;
|
drawEl: SVGSVGElement;
|
||||||
outputEl?: HTMLElement;
|
onEmit?: (c: string) => void;
|
||||||
showTurtle?: boolean;
|
showTurtle?: boolean;
|
||||||
}) {
|
jsx: any;
|
||||||
|
}): Promise<ErrorCode | null> {
|
||||||
// Initialize state
|
// Initialize state
|
||||||
let rotation = 270;
|
let rotation = 270;
|
||||||
const position = { x: 0, y: 0 };
|
const position = { x: 0, y: 0 };
|
||||||
|
@ -52,6 +53,7 @@ export default async function draw({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run program
|
// Run program
|
||||||
|
let result: ErrorCode | null = null;
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
const forth = new WAForth();
|
const forth = new WAForth();
|
||||||
await forth.load();
|
await forth.load();
|
||||||
|
@ -97,15 +99,10 @@ export default async function draw({
|
||||||
});
|
});
|
||||||
|
|
||||||
forth.interpret(thurtleFS);
|
forth.interpret(thurtleFS);
|
||||||
if (outputEl != null) {
|
if (onEmit != null) {
|
||||||
forth.onEmit = (c) => {
|
forth.onEmit = onEmit;
|
||||||
outputEl.appendChild(document.createTextNode(c));
|
|
||||||
if (c === "\n") {
|
|
||||||
outputEl.scrollTop = outputEl.scrollHeight;
|
|
||||||
}
|
}
|
||||||
};
|
result = forth.interpret(program, true);
|
||||||
}
|
|
||||||
forth.interpret(program, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
@ -119,6 +116,7 @@ export default async function draw({
|
||||||
data-hook="turtle"
|
data-hook="turtle"
|
||||||
width="50"
|
width="50"
|
||||||
height="50"
|
height="50"
|
||||||
|
style={{}}
|
||||||
href={turtle}
|
href={turtle}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -143,6 +141,23 @@ export default async function draw({
|
||||||
} ${position.y - 25})`
|
} ${position.y - 25})`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If we have a turtle, expand the view so that the entire turtle is in sight
|
||||||
|
// This looks better than just adjusting the bounding box
|
||||||
|
if (showTurtle && visible) {
|
||||||
|
const extendX = Math.max(
|
||||||
|
boundingBox.minX - Math.min(boundingBox.minX, position.x - 25),
|
||||||
|
Math.max(boundingBox.maxX, position.x + 25) - boundingBox.maxX
|
||||||
|
);
|
||||||
|
const extendY = Math.max(
|
||||||
|
boundingBox.minY - Math.min(boundingBox.minY, position.y - 25),
|
||||||
|
Math.max(boundingBox.maxY, position.y + 25) - boundingBox.maxY
|
||||||
|
);
|
||||||
|
boundingBox.maxX += extendX;
|
||||||
|
boundingBox.minX -= extendX;
|
||||||
|
boundingBox.maxY += extendY;
|
||||||
|
boundingBox.minY -= extendY;
|
||||||
|
}
|
||||||
|
|
||||||
const width = boundingBox.maxX - boundingBox.minX;
|
const width = boundingBox.maxX - boundingBox.minX;
|
||||||
const height = boundingBox.maxY - boundingBox.minY;
|
const height = boundingBox.maxY - boundingBox.minY;
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
|
@ -165,4 +180,6 @@ export default async function draw({
|
||||||
if (showTurtle) {
|
if (showTurtle) {
|
||||||
drawEl.appendChild(turtleEl);
|
drawEl.appendChild(turtleEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
43
src/web/thurtle/jsjsx.ts
Normal file
43
src/web/thurtle/jsjsx.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Simple version of JSX that does not require a DOM
|
||||||
|
|
||||||
|
function elementToHTML(el: any) {
|
||||||
|
const out: string[] = [];
|
||||||
|
out.push("<", el._tag);
|
||||||
|
for (const [k, v] of Object.entries(el)) {
|
||||||
|
if (typeof v == "function" || k.startsWith("_") || k === "innerHTML") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k === "style" && typeof v !== "string") {
|
||||||
|
// TODO
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out.push(" ", k, '="', v as string, '"');
|
||||||
|
}
|
||||||
|
out.push(">");
|
||||||
|
for (const child of el._children) {
|
||||||
|
out.push(elementToHTML(child));
|
||||||
|
}
|
||||||
|
out.push("</", el._tag, ">");
|
||||||
|
return out.join("");
|
||||||
|
}
|
||||||
|
class JSJSX {
|
||||||
|
createElement(tag: any, props: any = {}, ...children: any[]) {
|
||||||
|
return {
|
||||||
|
_tag: tag,
|
||||||
|
_children: children ?? [],
|
||||||
|
...props,
|
||||||
|
appendChild(c: any) {
|
||||||
|
this._children.push(c);
|
||||||
|
},
|
||||||
|
setAttribute(k: any, v: any) {
|
||||||
|
this[k] = v;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toHTML(el: any) {
|
||||||
|
return elementToHTML(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default JSJSX;
|
|
@ -458,7 +458,12 @@ async function getSVG(): Promise<{
|
||||||
height: number;
|
height: number;
|
||||||
}> {
|
}> {
|
||||||
const svgEl = <svg xmlns="http://www.w3.org/2000/svg" />;
|
const svgEl = <svg xmlns="http://www.w3.org/2000/svg" />;
|
||||||
await draw({ program: editor.getValue(), drawEl: svgEl, showTurtle: false });
|
await draw({
|
||||||
|
program: editor.getValue(),
|
||||||
|
drawEl: svgEl,
|
||||||
|
showTurtle: false,
|
||||||
|
jsx,
|
||||||
|
});
|
||||||
const viewBox = svgEl.getAttribute("viewBox")!.split(" ");
|
const viewBox = svgEl.getAttribute("viewBox")!.split(" ");
|
||||||
svgEl.setAttribute("width", parseInt(viewBox[2]) + "");
|
svgEl.setAttribute("width", parseInt(viewBox[2]) + "");
|
||||||
svgEl.setAttribute("height", parseInt(viewBox[3]) + "");
|
svgEl.setAttribute("height", parseInt(viewBox[3]) + "");
|
||||||
|
@ -540,10 +545,22 @@ document.addEventListener("keydown", (ev) => {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function output(c: string) {
|
||||||
|
outputEl.appendChild(document.createTextNode(c));
|
||||||
|
if (c === "\n") {
|
||||||
|
outputEl.scrollTop = outputEl.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
try {
|
try {
|
||||||
runButtonEl.disabled = true;
|
runButtonEl.disabled = true;
|
||||||
await draw({ program: editor.getValue(), drawEl: worldEl, outputEl });
|
await draw({
|
||||||
|
program: editor.getValue(),
|
||||||
|
drawEl: worldEl,
|
||||||
|
onEmit: output,
|
||||||
|
jsx,
|
||||||
|
});
|
||||||
editor.focus();
|
editor.focus();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -553,7 +570,7 @@ async function run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reset() {
|
async function reset() {
|
||||||
await draw({ drawEl: worldEl, outputEl });
|
await draw({ drawEl: worldEl, onEmit: output, jsx });
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
4
src/web/vscode-extension/.gitignore
vendored
Normal file
4
src/web/vscode-extension/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/dist/
|
||||||
|
/LICENSE.txt
|
||||||
|
*.vsix
|
||||||
|
/icon.png
|
5
src/web/vscode-extension/.vscodeignore
Normal file
5
src/web/vscode-extension/.vscodeignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
doc/
|
||||||
|
src/
|
||||||
|
Makefile
|
||||||
|
build.js
|
||||||
|
.gitignore
|
28
src/web/vscode-extension/Makefile
Normal file
28
src/web/vscode-extension/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
all:
|
||||||
|
./build.js
|
||||||
|
|
||||||
|
.PHONY: install-deps
|
||||||
|
install-deps:
|
||||||
|
yarn global add vsce
|
||||||
|
|
||||||
|
.PHONY: prepackage
|
||||||
|
prepackage: all LICENSE.txt icon.png
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: package
|
||||||
|
package: prepackage
|
||||||
|
vsce package
|
||||||
|
|
||||||
|
.PHONY: publish
|
||||||
|
publish:
|
||||||
|
vsce publish
|
||||||
|
|
||||||
|
LICENSE.txt: ../../../LICENSE.txt
|
||||||
|
cp $^ $@
|
||||||
|
|
||||||
|
icon.png: ../../../doc/logo.svg
|
||||||
|
convert -background transparent $< $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
-rm -rf dist LICENSE.txt *.vsix icon.png
|
14
src/web/vscode-extension/README.md
Normal file
14
src/web/vscode-extension/README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# WAForth VS Code Extension
|
||||||
|
|
||||||
|
This extension provides support for [WAForth](https://github.com/remko/waforth) notebooks.
|
||||||
|
|
||||||
|
Choose between a standard (text-based) Forth kernel, and a
|
||||||
|
[Thurtle](https://mko.re/thurtle/) kernel for drawing
|
||||||
|
Logo-like Forth Turtle graphics.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<div>
|
||||||
|
<a href="https://mko.re/waforth/"><img src="https://raw.githubusercontent.com/remko/waforth/master/src/web/vscode-extension/doc/notebook.gif" alt="WAForth notebook"></a>
|
||||||
|
</div>
|
||||||
|
<figcaption><em><a href="https://mko.re/waforth/">WAForth notebook</a></em></figcaption>
|
||||||
|
</div>
|
36
src/web/vscode-extension/build.js
Executable file
36
src/web/vscode-extension/build.js
Executable file
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
/* eslint-env node */
|
||||||
|
/* eslint @typescript-eslint/no-var-requires:0 */
|
||||||
|
|
||||||
|
const esbuild = require("esbuild");
|
||||||
|
const path = require("path");
|
||||||
|
const { wasmTextPlugin } = require("../../../scripts/esbuild/wasm-text");
|
||||||
|
|
||||||
|
let dev = false;
|
||||||
|
for (const arg of process.argv.slice(2)) {
|
||||||
|
switch (arg) {
|
||||||
|
case "--development":
|
||||||
|
dev = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esbuild
|
||||||
|
.build({
|
||||||
|
bundle: true,
|
||||||
|
logLevel: "info",
|
||||||
|
entryPoints: [path.join(__dirname, "src/extension.ts")],
|
||||||
|
outfile: path.join(__dirname, "dist/extension.js"),
|
||||||
|
format: "cjs",
|
||||||
|
minify: !dev,
|
||||||
|
sourcemap: true,
|
||||||
|
platform: "node",
|
||||||
|
external: ["vscode"],
|
||||||
|
loader: {
|
||||||
|
".wasm": "binary",
|
||||||
|
".fs": "text",
|
||||||
|
".svg": "dataurl",
|
||||||
|
},
|
||||||
|
plugins: [wasmTextPlugin({ debug: true })],
|
||||||
|
})
|
||||||
|
.catch(() => process.exit(1));
|
BIN
src/web/vscode-extension/doc/notebook.gif
Normal file
BIN
src/web/vscode-extension/doc/notebook.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 MiB |
BIN
src/web/vscode-extension/doc/notebook.mp4
Normal file
BIN
src/web/vscode-extension/doc/notebook.mp4
Normal file
Binary file not shown.
109
src/web/vscode-extension/examples/drawing-with-forth.wafnb
Normal file
109
src/web/vscode-extension/examples/drawing-with-forth.wafnb
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "# Drawing with Forth\n\nIn this tutorial, you'll learn basic Forth by drawing graphics with a turtle.\n\n| *VS Code Note:* Make sure you select the *Thurtle* kernel in the top right above to run this notebook\n\n## The stack\n\nForth is a stack-based language. Numbers are put on the stack, and words pop them off the stack (and put new ones on the stack) again.\nFor example, to take the sum of 8 and 14, put both numbers on the stack, and call `+`. To pop the result of the stack and print it out, use `.`:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "8 14 +\n."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "## Drawing lines\n\nInstead of printing numbers to output, we can also draw lines.\n\nThe `FORWARD` word pops the number of the stack, and moves a turtle forward while drawing a line:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "200 FORWARD"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "Let's now also turn the turtle 90 degrees, and create a complete square:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "200 FORWARD\n90 RIGHT\n200 FORWARD\n90 RIGHT\n200 FORWARD\n90 RIGHT\n200 FORWARD\n90 RIGHT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "## Creating your own words\n\nWe can create our own parameterized word that draws a square of the given size:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": ": SQUARE ( n -- )\n DUP FORWARD\n 90 RIGHT\n DUP FORWARD\n 90 RIGHT\n DUP FORWARD\n 90 RIGHT\n DUP FORWARD\n 90 RIGHT\n;\n\n500 SQUARE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "## Loops\n\nForth also has loops using `DO` and `LOOP`:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": ": SQUARE ( n -- )\n 4 0 DO\n DUP FORWARD\n 90 RIGHT\n LOOP\n DROP\n;\n\n250 SQUARE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "# Combining words\n\nWe can create more complex figures by using the `SQUARE` word from above, and repeating it.\n\n| *Tip*: Play with the numbers in `FLOWER` to create variations of the flower "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": ": SQUARE ( n -- )\n 4 0 DO\n DUP FORWARD\n 90 RIGHT\n LOOP\n DROP\n;\n\n: FLOWER ( n -- )\n 24 0 DO\n DUP SQUARE\n 15 RIGHT\n LOOP\n DROP\n;\n\n250 FLOWER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": " 4 0 DO\n DUP FORWARD\n 90 RIGHT\n LOOP\n DROP\n;\n\n: FLOWER ( n -- )\n 24 0 DO\n DUP SQUARE\n 15 RIGHT\n LOOP\n DROP\n;\n\n250 FLOWER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "## Recursion\n\nWords can also call themselves:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": ": SPIRAL ( n -- )\n DUP 1 < IF DROP EXIT THEN \n DUP FORWARD\n 15 RIGHT\n 98 100 */ RECURSE\n;\n\n140 SPIRAL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "We can make a small variation of the above recursive program, where the lines become longer instead of shorter.\nTo avoid hard-coding some constants in the code, we use the word `CONSTANT` to define a new constant (`ANGLE`) to turn.\n\n| *Tip*: Change the constant `ANGLE` to 91 and see what happens."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "90 CONSTANT ANGLE\n\n: SPIRAL ( n -- )\n DUP 800 > IF DROP EXIT THEN \n DUP FORWARD\n ANGLE RIGHT\n 10 +\n RECURSE\n;\n\n1 SPIRAL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "# Fractals\n\nYou can create more complex recursive drawings, called *fractals*. \n\nA famous fractal is the *Koch snowflake*.\n\n| *Tip*: Change the `DEPTH` constant to make a coarser or finer grained snowflake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "730 CONSTANT LENGTH\n6 CONSTANT DEPTH\n\n: SIDE ( length depth -- )\n DUP 0= IF \n DROP FORWARD EXIT \n THEN\n SWAP 3 / SWAP 1-\n 2DUP RECURSE\n 60 LEFT 2DUP RECURSE\n 120 RIGHT 2DUP RECURSE\n 60 LEFT RECURSE\n;\n\n: SNOWFLAKE ( -- )\n 3 0 DO \n LENGTH DEPTH SIDE\n 120 RIGHT\n LOOP\n;\n\n1 SETPENSIZE\nSNOWFLAKE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 1,
|
||||||
|
"language": "markdown",
|
||||||
|
"value": "You can also draw plants and trees using fractals:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": 2,
|
||||||
|
"language": "waforth",
|
||||||
|
"value": "450 CONSTANT SIZE\n7 CONSTANT BRANCHES\n160 CONSTANT SPREAD\n\nVARIABLE RND\nHERE RND !\n\n: RANDOM ( -- n )\n RND @ 75 * 74 + 65537 MOD\n DUP RND !\n;\n\n: CHOOSE ( n1 -- n2 )\n RANDOM 65537 */MOD SWAP DROP \n; \n\n: PLANT ( size angle -- )\n OVER 10 < IF 2DROP EXIT THEN\n DUP RIGHT\n OVER FORWARD\n BRANCHES 0 DO\n OVER 2/\n SPREAD CHOOSE SPREAD 2/ -\n RECURSE\n LOOP\n PENUP SWAP BACKWARD PENDOWN\n LEFT\n;\n \n1 SETPENSIZE\nSIZE 0 PLANT"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"lineComment": "\\"
|
||||||
|
}
|
||||||
|
}
|
175
src/web/vscode-extension/language/waforth.tmGrammar.json
Normal file
175
src/web/vscode-extension/language/waforth.tmGrammar.json
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
{
|
||||||
|
"fileTypes": ["f", "fs"],
|
||||||
|
"scopeName": "source.waforth",
|
||||||
|
"foldingStartMarker": "/\\*\\*|\\{\\s*$",
|
||||||
|
"foldingStopMarker": "\\*\\*/|^\\s*\\}",
|
||||||
|
"name": "WAForth",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#constant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#comment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#word"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#variable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#word-def"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"comment": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(\\\\[\\s\\S]*$)",
|
||||||
|
"name": "comment.line.backslash.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(\\.?\\( [^)]*\\))",
|
||||||
|
"name": "comment.line.parentheses.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"constant": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "(?i:(?<=^|\\s)(TRUE|FALSE|BL|PI|CELL|C/L|R/O|W/O|R/W)(?=\\s))",
|
||||||
|
"name": "constant.language.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)([$#%]?[-+]?[0-9]+(\\.[0-9]*e(-?[0-9]+)|\\.?[0-9a-fA-F]*))(?=\\s)",
|
||||||
|
"name": "constant.numeric.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(([&^]\\S)|((\"|')\\S(\"|')))(?=\\s)",
|
||||||
|
"name": "constant.character.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"comment": "",
|
||||||
|
"match": "(?<=^|\\s)(?i:(2CONSTANT|2VARIABLE|ALIAS|CONSTANT|CREATE-INTERPRET/COMPILE[:]?|CREATE|DEFER|FCONSTANT|FIELD|FVARIABLE|USER|VALUE|VARIABLE|VOCABULARY))(?=\\s)",
|
||||||
|
"name": "storage.type.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"comment": "",
|
||||||
|
"match": "(?i:((?<=ABORT\" )|(?<=BREAK\" )|(?<=\\.\" )|(C\" )|(0\")|(S\\\\?\" )))[^\"]+\"",
|
||||||
|
"name": "string.quoted.double.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"comment": "",
|
||||||
|
"match": "(?i:((?<=INCLUDE)|(?<=NEEDS)|(?<=REQUIRE)|(?<=USE)))[ ]\\S+(?=\\s)",
|
||||||
|
"name": "string.unquoted.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\b(?i:I|J)\\b",
|
||||||
|
"name": "variable.language.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"word": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)\\[(?i:(NIP|TUCK|ROT|SWAP|DUP|OVER|DROP|2SWAP|2DUP|2DROP|FNIP|FTUCK|FROT|FSWAP|FDUP|FOVER|FDROP|F2SWAP|F2DUP|F2DROP))\\](?=\\s)",
|
||||||
|
"name": "keyword.other.word.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)\\[(?i:(F+|F-|F*|F**|FSQRT|F/|F.S))\\](?=\\s)",
|
||||||
|
"name": "keyword.other.word.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)\\[(?i:(EXECUTE|ABORT|CATCH|C@|F@|>R|R>|!|/MOD|MOD))\\](?=\\s)",
|
||||||
|
"name": "keyword.other.word.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)\\[(?i:(\\?DO|\\+LOOP|AGAIN|BEGIN|DEFINED|DO|ELSE|ENDIF|FOR|IF|IFDEF|IFUNDEF|LOOP|NEXT|REPEAT|THEN|UNTIL|WHILE))\\](?=\\s)",
|
||||||
|
"name": "keyword.control.immediate.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(?i:(COMPILE-ONLY|IMMEDIATE|IS|RESTRICT|TO|WHAT'S|]))(?=\\s)",
|
||||||
|
"name": "keyword.operator.immediate.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(?i:(-DO|\\-LOOP|\\?DO|\\?LEAVE|\\+DO|\\+LOOP|ABORT\\\"|AGAIN|AHEAD|BEGIN|CASE|DO|ELSE|ENDCASE|ENDIF|ENDOF|ENDTRY\\-IFERROR|ENDTRY|FOR|IF|IFERROR|LEAVE|LOOP|NEXT|RECOVER|REPEAT|RESTORE|THEN|TRY|U\\-DO|U\\+DO|UNTIL|WHILE))(?=\\s)",
|
||||||
|
"name": "keyword.control.compile-only.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(?i:(\\?DUP-0=-IF|\\?DUP-IF|\\)|\\[|\\['\\]|\\[CHAR\\]|\\[COMPILE\\]|\\[IS\\]|\\[TO\\]|<COMPILATION|<INTERPRETATION|ASSERT\\(|ASSERT0\\(|ASSERT1\\(|ASSERT2\\(|ASSERT3\\(|COMPILATION>|DEFERS|DOES>|INTERPRETATION>|OF|POSTPONE))(?=\\s)",
|
||||||
|
"name": "keyword.other.compile-only.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(?i:('|<IS>|<TO>|CHAR|END-STRUCT|INCLUDE[D]?|LOAD|NEEDS|REQUIRE[D]?|REVISION|SEE|STRUCT|THRU|USE))(?=\\s)",
|
||||||
|
"name": "keyword.other.non-immediate.waforth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "(?<=^|\\s)(?i:(~~|BREAK:|BREAK\"|DBG))(?=\\s)",
|
||||||
|
"name": "keyword.other.warning.waforth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"word-def": {
|
||||||
|
"begin": "(^:|\\s:)\\s(\\S+)\\s|(?i:(:NONAME))",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "keyword.other.compile-only.waforth"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "entity.name.function.waforth"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"name": "keyword.other.compile-only.waforth"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "keyword.other.word.waforth"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(;(?i:CODE)?)",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "keyword.other.compile-only.waforth"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "meta.block.waforth",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#constant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#comment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#word"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#variable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#storage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
src/web/vscode-extension/package.json
Normal file
78
src/web/vscode-extension/package.json
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
{
|
||||||
|
"name": "waforth-vscode-extension",
|
||||||
|
"version": "0.1.3",
|
||||||
|
"displayName": "WAForth",
|
||||||
|
"description": "WAForth interactive notebooks",
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages",
|
||||||
|
"Notebooks"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"forth"
|
||||||
|
],
|
||||||
|
"publisher": "remko",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "github:remko/waforth",
|
||||||
|
"icon": "icon.png",
|
||||||
|
"main": "dist/extension.js",
|
||||||
|
"browser": "dist/extension.js",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.61.0"
|
||||||
|
},
|
||||||
|
"capabilities": {
|
||||||
|
"untrustedWorkspaces": {
|
||||||
|
"supported": true
|
||||||
|
},
|
||||||
|
"virtualWorkspaces": true
|
||||||
|
},
|
||||||
|
"activationEvents": [
|
||||||
|
"onNotebook:waforth-notebook",
|
||||||
|
"onCommand:waforth-notebook.new"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"notebooks": [
|
||||||
|
{
|
||||||
|
"type": "waforth-notebook",
|
||||||
|
"displayName": "WAForth Notebook",
|
||||||
|
"selector": [
|
||||||
|
{
|
||||||
|
"filenamePattern": "*.wafnb"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"id": "waforth",
|
||||||
|
"aliases": [
|
||||||
|
"WAForth"
|
||||||
|
],
|
||||||
|
"configuration": "./language/language-configuration.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grammars": [
|
||||||
|
{
|
||||||
|
"language": "waforth",
|
||||||
|
"scopeName": "source.waforth",
|
||||||
|
"path": "./language/waforth.tmGrammar.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"title": "WAForth: New Notebook",
|
||||||
|
"shortTitle": "WAForth Notebook",
|
||||||
|
"command": "waforth-notebook.new"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"menus": {
|
||||||
|
"file/newFile": [
|
||||||
|
{
|
||||||
|
"command": "waforth-notebook.new"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"vscode:prepublish": "make prepackage"
|
||||||
|
}
|
||||||
|
}
|
197
src/web/vscode-extension/src/extension.ts
Normal file
197
src/web/vscode-extension/src/extension.ts
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import * as vscode from "vscode";
|
||||||
|
import WAForth, { ErrorCode, isSuccess } from "../../waforth";
|
||||||
|
import draw from "../../thurtle/draw";
|
||||||
|
import JSJSX from "thurtle/jsjsx";
|
||||||
|
|
||||||
|
export async function activate(context: vscode.ExtensionContext) {
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.workspace.registerNotebookSerializer(
|
||||||
|
"waforth-notebook",
|
||||||
|
new NotebookSerializer(),
|
||||||
|
{
|
||||||
|
transientOutputs: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await createNotebookController("WAForth", "waforth-controller", false, false);
|
||||||
|
await createNotebookController("Thurtle", "thurtle-controller", true, false);
|
||||||
|
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.commands.registerCommand("waforth-notebook.new", async function () {
|
||||||
|
const newNotebook = await vscode.workspace.openNotebookDocument(
|
||||||
|
"waforth-notebook",
|
||||||
|
new vscode.NotebookData([
|
||||||
|
new vscode.NotebookCellData(
|
||||||
|
vscode.NotebookCellKind.Code,
|
||||||
|
".( Hello world) CR",
|
||||||
|
"waforth"
|
||||||
|
),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
await vscode.commands.executeCommand("vscode.open", newNotebook.uri);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deactivate() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// Notebook Serializer
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
interface RawNotebookData {
|
||||||
|
cells: RawNotebookCell[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RawNotebookCell {
|
||||||
|
language: string;
|
||||||
|
value: string;
|
||||||
|
kind: vscode.NotebookCellKind;
|
||||||
|
editable?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotebookSerializer implements vscode.NotebookSerializer {
|
||||||
|
public readonly label: string = "WAForth Content Serializer";
|
||||||
|
|
||||||
|
public async deserializeNotebook(
|
||||||
|
data: Uint8Array
|
||||||
|
): Promise<vscode.NotebookData> {
|
||||||
|
const contents = new TextDecoder().decode(data);
|
||||||
|
if (contents.trim().length === 0) {
|
||||||
|
return new vscode.NotebookData([]);
|
||||||
|
}
|
||||||
|
let raw: RawNotebookData;
|
||||||
|
try {
|
||||||
|
raw = <RawNotebookData>JSON.parse(contents);
|
||||||
|
} catch (e) {
|
||||||
|
vscode.window.showErrorMessage("Error parsing:", (e as any).message);
|
||||||
|
raw = { cells: [] };
|
||||||
|
}
|
||||||
|
const cells = raw.cells.map(
|
||||||
|
(item) =>
|
||||||
|
new vscode.NotebookCellData(item.kind, item.value, item.language)
|
||||||
|
);
|
||||||
|
return new vscode.NotebookData(cells);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async serializeNotebook(
|
||||||
|
data: vscode.NotebookData
|
||||||
|
): Promise<Uint8Array> {
|
||||||
|
const contents: RawNotebookData = { cells: [] };
|
||||||
|
for (const cell of data.cells) {
|
||||||
|
contents.cells.push({
|
||||||
|
kind: cell.kind,
|
||||||
|
language: cell.languageId,
|
||||||
|
value: cell.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new TextEncoder().encode(JSON.stringify(contents, undefined, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// Notebook Serializer
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
async function createNotebookController(
|
||||||
|
name: string,
|
||||||
|
id: string,
|
||||||
|
turtleSupport: boolean,
|
||||||
|
stateful: boolean
|
||||||
|
) {
|
||||||
|
let executionOrder = 0;
|
||||||
|
|
||||||
|
// Global instance (for non-Thurtle kernel)
|
||||||
|
let globalForth: WAForth;
|
||||||
|
if (stateful) {
|
||||||
|
globalForth = await new WAForth().load();
|
||||||
|
}
|
||||||
|
|
||||||
|
const controller = vscode.notebooks.createNotebookController(
|
||||||
|
id,
|
||||||
|
"waforth-notebook",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
controller.supportedLanguages = ["waforth"];
|
||||||
|
controller.supportsExecutionOrder = stateful;
|
||||||
|
controller.executeHandler = async (
|
||||||
|
cells: vscode.NotebookCell[],
|
||||||
|
_notebook: vscode.NotebookDocument,
|
||||||
|
controller: vscode.NotebookController
|
||||||
|
) => {
|
||||||
|
for (const cell of cells) {
|
||||||
|
const execution = controller.createNotebookCellExecution(cell);
|
||||||
|
execution.executionOrder = ++executionOrder;
|
||||||
|
execution.start(Date.now());
|
||||||
|
execution.clearOutput();
|
||||||
|
try {
|
||||||
|
let outputBuffer: string[] = [];
|
||||||
|
const flushOutputBuffer = () => {
|
||||||
|
if (outputBuffer.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
execution.appendOutput(
|
||||||
|
new vscode.NotebookCellOutput([
|
||||||
|
vscode.NotebookCellOutputItem.text(outputBuffer.join("")),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
outputBuffer = [];
|
||||||
|
};
|
||||||
|
const emit = (c: string) => {
|
||||||
|
outputBuffer.push(c);
|
||||||
|
if (c.endsWith("\n")) {
|
||||||
|
flushOutputBuffer();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let result: ErrorCode;
|
||||||
|
const program = execution.cell.document.getText();
|
||||||
|
if (cell.document.languageId != "waforth") {
|
||||||
|
throw new Error("can't happen");
|
||||||
|
}
|
||||||
|
if (!turtleSupport) {
|
||||||
|
const forth = stateful ? globalForth : await new WAForth().load();
|
||||||
|
forth.onEmit = emit;
|
||||||
|
result = forth.interpret(program, true);
|
||||||
|
} else {
|
||||||
|
const jsx = new JSJSX();
|
||||||
|
const svgEl = jsx.createElement("svg", {
|
||||||
|
xmlns: "http://www.w3.org/2000/svg",
|
||||||
|
});
|
||||||
|
result = (await draw({
|
||||||
|
program,
|
||||||
|
drawEl: svgEl as any,
|
||||||
|
onEmit: emit,
|
||||||
|
showTurtle: true,
|
||||||
|
jsx,
|
||||||
|
}))!;
|
||||||
|
const paths = (svgEl._children as any[]).find(
|
||||||
|
(el) => el._tag === "g"
|
||||||
|
)._children;
|
||||||
|
if (paths.length > 1 || paths[0].d !== "M0 0") {
|
||||||
|
svgEl.height = "300px";
|
||||||
|
svgEl.style =
|
||||||
|
"background-color: rgb(221, 248, 221); border-radius: 10px;";
|
||||||
|
execution.appendOutput(
|
||||||
|
new vscode.NotebookCellOutput([
|
||||||
|
vscode.NotebookCellOutputItem.text(
|
||||||
|
"<div style='width: 100%; display: flex; justify-content: center;'>" +
|
||||||
|
jsx.toHTML(svgEl) +
|
||||||
|
"</div>",
|
||||||
|
"text/html"
|
||||||
|
),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flushOutputBuffer();
|
||||||
|
execution.end(isSuccess(result), Date.now());
|
||||||
|
} catch (e) {
|
||||||
|
vscode.window.showErrorMessage((e as any).message);
|
||||||
|
execution.end(false, Date.now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ function saveString(s: string, memory: WebAssembly.Memory, addr: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ErrorCode {
|
export enum ErrorCode {
|
||||||
Unknown = 0x1, // Unknown error
|
Unknown = 0x1, // Unknown error
|
||||||
Quit = 0x2, // QUIT was called
|
Quit = 0x2, // QUIT was called
|
||||||
Abort = 0x3, // ABORT or ABORT" was called
|
Abort = 0x3, // ABORT or ABORT" was called
|
||||||
|
@ -44,6 +44,10 @@ enum ErrorCode {
|
||||||
Bye = 0x5, // BYE was called
|
Bye = 0x5, // BYE was called
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSuccess(code: ErrorCode) {
|
||||||
|
return code !== ErrorCode.Abort && code !== ErrorCode.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JavaScript shell around the WAForth WebAssembly module.
|
* JavaScript shell around the WAForth WebAssembly module.
|
||||||
*
|
*
|
||||||
|
@ -191,6 +195,7 @@ class WAForth {
|
||||||
this.core = instance.instance;
|
this.core = instance.instance;
|
||||||
const table = this.core.exports.table as WebAssembly.Table;
|
const table = this.core.exports.table as WebAssembly.Table;
|
||||||
const memory = this.core.exports.memory as WebAssembly.Memory;
|
const memory = this.core.exports.memory as WebAssembly.Memory;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory(): WebAssembly.Memory {
|
memory(): WebAssembly.Memory {
|
||||||
|
|
|
@ -117,6 +117,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
|
||||||
integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==
|
integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==
|
||||||
|
|
||||||
|
"@types/vscode@^1.73.1":
|
||||||
|
version "1.73.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.73.1.tgz#f2b198dca65c693c4570475aca04a34ad773609d"
|
||||||
|
integrity sha512-eArfOrAoZVV+Ao9zQOCaFNaeXj4kTCD+bGS2gyNgIFZH9xVMuLMlRrEkhb22NyxycFWKV1UyTh03vhaVHmqVMg==
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^5.30.5":
|
"@typescript-eslint/eslint-plugin@^5.30.5":
|
||||||
version "5.30.5"
|
version "5.30.5"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz#e9a0afd6eb3b1d663db91cf1e7bc7584d394503d"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz#e9a0afd6eb3b1d663db91cf1e7bc7584d394503d"
|
||||||
|
|
Loading…
Reference in a new issue