mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
Move everything to javascript dir. Add jspgf API, test files for both Node and web.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
1
src/runtime/javascript/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.libs/
|
||||
@@ -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,\
|
||||
11
src/runtime/javascript/README.md
Normal file
11
src/runtime/javascript/README.md
Normal 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
|
||||
@@ -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/"
|
||||
|
||||
104
src/runtime/javascript/jspgf.js
Normal file
104
src/runtime/javascript/jspgf.js
Normal 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;
|
||||
}
|
||||
33
src/runtime/javascript/test-node.js
Normal file
33
src/runtime/javascript/test-node.js
Normal 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));
|
||||
}
|
||||
|
||||
14
src/runtime/javascript/test-web.html
Normal file
14
src/runtime/javascript/test-web.html
Normal 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>
|
||||
|
||||
|
||||
13
src/runtime/javascript/test-web.js
Normal file
13
src/runtime/javascript/test-web.js
Normal 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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user