Move everything to javascript dir. Add jspgf API, test files for both Node and web.

This commit is contained in:
John J. Camilleri
2022-08-01 14:11:45 +02:00
parent 63828de0c2
commit 3d272ac053
10 changed files with 206 additions and 15 deletions

View File

@@ -18,12 +18,24 @@ gu_exn_is_raised(GuExn* err) {
return err && (err->state == GU_EXN_RAISED);
}
GU_API_DECL void
gu_exn_clear(GuExn* err) {
err->caught = NULL;
err->state = GU_EXN_OK;
}
GU_API bool
gu_exn_caught_(GuExn* err, const char* type)
{
return (err->caught && strcmp(err->caught, type) == 0);
}
GU_API_DECL void*
gu_exn_caught_data(GuExn* err)
{
return err->data.data;
}
GU_API void
gu_exn_block(GuExn* err)
{

View File

@@ -71,11 +71,13 @@ gu_new_exn(GuPool* pool);
GU_API_DECL bool
gu_exn_is_raised(GuExn* err);
static inline void
gu_exn_clear(GuExn* err) {
err->caught = NULL;
err->state = GU_EXN_OK;
}
// static inline void
// gu_exn_clear(GuExn* err) {
// err->caught = NULL;
// err->state = GU_EXN_OK;
// }
GU_API_DECL void
gu_exn_clear(GuExn* err);
#define gu_exn_caught(err, type) \
(err->caught && strcmp(err->caught, #type) == 0)
@@ -83,11 +85,13 @@ gu_exn_clear(GuExn* err) {
GU_API_DECL bool
gu_exn_caught_(GuExn* err, const char* type);
static inline const void*
gu_exn_caught_data(GuExn* err)
{
return err->data.data;
}
// static inline const void*
// gu_exn_caught_data(GuExn* err)
// {
// return err->data.data;
// }
GU_API_DECL void*
gu_exn_caught_data(GuExn* err);
/// Temporarily block a raised exception.
GU_API_DECL void

1
src/runtime/javascript/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.libs/

View File

@@ -16,8 +16,7 @@ COPY \
RUN autoreconf -i
RUN emconfigure ./configure
RUN emmake make
RUN emcc .libs/libgu.a .libs/libpgf.a -o pgf.html \
-sFORCE_FILESYSTEM \
RUN emcc .libs/libgu.a .libs/libpgf.a -o pgf.js \
-sALLOW_MEMORY_GROWTH \
-sEXPORTED_FUNCTIONS="\
_pgf_read,\

View File

@@ -0,0 +1,11 @@
# JavaScript runtime using Web Assembly
This folder contains very early work experimenting with a pure JavaScript runtime,
copiled to Web Assembly (WASM) using [Emscripten](https://emscripten.org/).
1. Compile the WASM files (inside Docker) using `build-wasm.js`, placing them in `.libs/`
2. Test in Node.js by running `node test-node.js [path to PGF]`
3. Test in a web browser
a. Start a server with `npx serve -l 41296`
b. Browse to `http://localhost:41296/test-web.html`
c. Check JavaScript console

View File

@@ -1,10 +1,10 @@
#! /usr/bin/env bash
set -e
cd ../c
# Build inside Docker image
IMAGE="gf/build-c-runtime-wasm"
docker build . --file Dockerfile-wasm --tag $IMAGE
docker build ../c --file Dockerfile --tag $IMAGE
# Copy bulit files from container to host
docker run --rm --volume "$PWD":/tmp/host $IMAGE bash -c "cp pgf.js pgf.wasm /tmp/host/"
mkdir -p .libs
docker run --rm --volume "$PWD":/tmp/host $IMAGE bash -c "cp pgf.js pgf.wasm /tmp/host/.libs/"

View File

@@ -0,0 +1,104 @@
/**
* This module is the high-level JavaScript wrapper around the WASM-compiled version.
*/
function mkAPI(Module) {
function checkError(err) {
if (Module._gu_exn_is_raised(err)) {
console.error('raised');
const isCaught = Module.ccall(
'gu_exn_caught_',
'boolean',
['number', 'string'],
[err, 'GuErrno']
);
if (isCaught) {
console.error('caught');
errDataPtr = Module._gu_exn_caught_data(err);
errno = Module.getValue(errDataPtr, '*');
console.error('errno', errno);
}
Module._gu_exn_clear(err);
return true;
}
return false;
}
function readPGF(pgfPath) {
const pool = Module._gu_new_pool();
const tmp_pool = Module._gu_new_pool();
const err = Module._gu_new_exn(tmp_pool);
// const pgf = Module.ccall(
// 'pgf_read',
// 'number',
// ['string', 'number', 'number'],
// [pgfPath, pool, err]
// );
const strPtr = Module.allocateUTF8(pgfPath);
const pgf = Module._pgf_read(strPtr, pool, err);
if (checkError(err)) {
Module._free(tmp_pool);
throw new Error('Cannot read PGF');
}
Module._free(tmp_pool);
return pgf;
}
function abstractName(pgf) {
const namePtr = Module._pgf_abstract_name(pgf);
return Module.UTF8ToString(namePtr);
}
function readExpr(exprStr) {
const tmp_pool = Module._gu_new_pool();
const strPtr = Module.allocateUTF8(exprStr);
const in_ = Module._gu_data_in(strPtr, exprStr.length, tmp_pool);
const err = Module._gu_new_exn(tmp_pool);
const pool = Module._gu_new_pool();
const expr = Module._pgf_read_expr(in_, pool, tmp_pool, err);
Module._free(strPtr);
if (checkError(err)) {
throw new Error();
}
if (expr == 0) {
throw new Error('Expression cannot be parsed');
}
Module._free(tmp_pool);
return expr;
}
function arity(expr) {
return Module._pgf_expr_arity(expr);
}
function showExpr(expr) {
const tmp_pool = Module._gu_new_pool();
const sb = Module._gu_new_string_buf(tmp_pool);
const out = Module._gu_string_buf_out(sb);
const err = Module._gu_new_exn(tmp_pool);
Module._pgf_print_expr(expr, 0, 0, out, err);
if (checkError(err)) {
Module._free(tmp_pool);
throw new Error('Cannot print expression');
}
const str = Module._gu_string_buf_data(sb);
return Module.UTF8ToString(str);
}
return { readPGF, abstractName, readExpr, arity, showExpr };
}
// This allows us to use both from Node and in browser
if (typeof module != 'undefined') {
module.exports = mkAPI;
}

View File

@@ -0,0 +1,33 @@
const Module = require('./.libs/pgf.js');
const JSPGF = require('./jspgf.js')(Module);
const fs = require('fs');
const path = require('path');
Module.onRuntimeInitialized = () => {
// Read PGF path from args
if (process.argv.length > 2) {
const pgfPathHost = process.argv[2];
// Copy file into filesystem
const pgfPathFS = '/tmp/' + path.basename(pgfPathHost);
const rawPgf = fs.readFileSync(pgfPathHost);
Module.FS.writeFile(pgfPathFS, rawPgf);
// Read PGF
const pgf = JSPGF.readPGF(pgfPathFS);
// Print its name
console.log(JSPGF.abstractName(pgf));
}
// Parse expression
const expr = JSPGF.readExpr("Pred (Another (x f))");
// Show it
console.log(JSPGF.showExpr(expr));
// Print its arity
console.log('arity', JSPGF.arity(expr));
}

View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script type="text/javascript" src=".libs/pgf.js"></script>
<script type="text/javascript" src="./jspgf.js"></script>
<script type="text/javascript" src="./test-web.js"></script>
</body>
</html>

View File

@@ -0,0 +1,13 @@
Module.onRuntimeInitialized = () => {
const JSPGF = mkAPI(Module);
// Parse expression
const expr = JSPGF.readExpr("Pred (Another (x f))");
// Show it
console.log(JSPGF.showExpr(expr));
// Print its arity
console.log('arity', JSPGF.arity(expr));
}