-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
446 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,9 @@ members = [ | |
"jaq-core", | ||
"jaq-std", | ||
"jaq", | ||
"jaq-play", | ||
] | ||
|
||
resolver = "2" | ||
|
||
[profile.release] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pkg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "jaq-play" | ||
description = "Web interface for jaq" | ||
version = "0.1.0" | ||
authors = ["Michael Färber <[email protected]>"] | ||
categories = ["wasm"] | ||
readme = "README.md" | ||
repository = "https://github.com/01mf02/jaq" | ||
license = "MIT" | ||
edition = "2021" | ||
|
||
[package.metadata.wasm-pack.profile.dev] | ||
wasm-opt = false | ||
|
||
[lib] | ||
crate-type = ["cdylib", "rlib"] | ||
|
||
[dependencies] | ||
jaq-syn = { version = "1.1.0", path = "../jaq-syn" } | ||
jaq-parse = { version = "1.0.0", path = "../jaq-parse" } | ||
jaq-interpret = { version = "1.2.0", path = "../jaq-interpret" } | ||
hifijson = "0.2" | ||
log = "0.4.17" | ||
serde_json = { version = "1.0.81", features = [ "arbitrary_precision", "preserve_order" ] } | ||
|
||
console_log = { version = "1.0", features = ["color"] } | ||
getrandom = { version = "0.2", features = ["js"] } | ||
wasm-bindgen = { version = "0.2" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
jaq playground | ||
============== | ||
|
||
First install `wasm-pack`: | ||
|
||
cargo install wasm-pack | ||
|
||
Compile the WASM binaries (use `--release` instead of `--dev` for better performance): | ||
|
||
wasm-pack build --target web --dev | ||
|
||
To serve: | ||
|
||
python3 -m http.server --bind 127.0.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<link rel="stylesheet" href="/src/main.css"> | ||
<title>jaq playground</title> | ||
</head> | ||
|
||
<body> | ||
<header class="top"> | ||
<button id="run" class="button">▶️ Run</span> | ||
<!-- | ||
<span id="flags" class="button">⚙️ Flags</span> | ||
--> | ||
</header> | ||
|
||
<section class="filter"> | ||
<header><h1>Filter</h1></header> | ||
<textarea id="filter" spellcheck="false">.</textarea> | ||
</section> | ||
|
||
<div class="IO"> | ||
<section class="input"> | ||
<header><h1>Input</h1></header> | ||
<textarea id="input" spellcheck="false">null</textarea> | ||
</section> | ||
|
||
<section class="output"> | ||
<header><h1>Output</h1></header> | ||
<div id="output" spellcheck="false"></div> | ||
</section> | ||
</div> | ||
<!-- | ||
<div id="footer"></div> | ||
--> | ||
<script type="module"> | ||
import init from "/pkg/jaq_play.js"; | ||
await init(); | ||
</script> | ||
<script type="module" src="./src/main.js" defer></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Functions that are called from the Rust code. | ||
|
||
export function output_newline() { | ||
const new_line = document.createElement("div"); | ||
document.getElementById("output").appendChild(new_line); | ||
} | ||
|
||
export function output_tag(tag, type) { | ||
let span = document.createElement("span"); | ||
if (type) { | ||
span.className = type; | ||
} | ||
span.textContent = tag; | ||
|
||
let last_line = document.getElementById("output").lastElementChild; | ||
last_line.appendChild(span); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
use wasm_bindgen::prelude::*; | ||
|
||
#[wasm_bindgen(module = "/src/lib.js")] | ||
extern "C" { | ||
#[wasm_bindgen] | ||
fn output_newline(); | ||
|
||
#[wasm_bindgen] | ||
fn output_tag(s: &str, typ: Option<&str>); | ||
} | ||
|
||
use jaq_interpret::{Ctx, Error, FilterT, ParseCtx, RcIter, Val}; | ||
use serde_json::{json, Value}; | ||
|
||
fn indent(level: usize) { | ||
if level > 0 { | ||
output_tag(&" ".repeat(level), None); | ||
} | ||
} | ||
|
||
fn print_val(v: &Val, level: usize, indent_start: bool) { | ||
if indent_start { | ||
indent(level); | ||
} | ||
match v { | ||
Val::Null => output_tag("null", Some("null")), | ||
Val::Bool(true) => output_tag("true", Some("bool")), | ||
Val::Bool(false) => output_tag("false", Some("bool")), | ||
Val::Int(i) => output_tag(&i.to_string(), Some("number")), | ||
Val::Float(x) if x.is_finite() => output_tag(&format!("{x:?}"), Some("number")), | ||
Val::Float(_) => output_tag("null", Some("null")), | ||
Val::Num(n) => output_tag(n, Some("number")), | ||
Val::Str(s) => output_tag(&format!("{s:?}"), Some("string")), | ||
Val::Arr(a) if a.is_empty() => output_tag("[]", Some("array")), | ||
Val::Arr(a) => { | ||
output_tag("[", Some("array")); | ||
output_newline(); | ||
let mut iter = a.iter().peekable(); | ||
while let Some(x) = iter.next() { | ||
print_val(x, level + 1, true); | ||
if iter.peek().is_some() { | ||
output_tag(",", None); | ||
} | ||
output_newline(); | ||
} | ||
indent(level); | ||
output_tag("]", Some("array")); | ||
} | ||
Val::Obj(o) if o.is_empty() => output_tag("{}", Some("object")), | ||
Val::Obj(o) => { | ||
output_tag("{", Some("object")); | ||
output_newline(); | ||
let mut iter = o.iter().peekable(); | ||
while let Some((k, v)) = iter.next() { | ||
indent(level + 1); | ||
output_tag(&format!("{k:?}"), Some("key")); | ||
output_tag(": ", None); | ||
print_val(v, level + 1, false); | ||
if iter.peek().is_some() { | ||
output_tag(",", None); | ||
} | ||
output_newline(); | ||
} | ||
indent(level); | ||
output_tag("}", Some("object")); | ||
} | ||
} | ||
} | ||
|
||
#[wasm_bindgen] | ||
pub fn run(filter: &str, input: &str) { | ||
let _ = console_log::init(); | ||
log::info!("Starting run in Rust ..."); | ||
|
||
let mut lexer = hifijson::SliceLexer::new(input.as_bytes()); | ||
let inputs = core::iter::from_fn(move || { | ||
use hifijson::token::Lex; | ||
Some(Val::parse(lexer.ws_token()?, &mut lexer).map_err(|e| todo!())) | ||
}); | ||
|
||
// start out only from core filters, | ||
// which do not include filters in the standard library | ||
// such as `map`, `select` etc. | ||
let mut defs = ParseCtx::new(Vec::new()); | ||
|
||
// parse the filter | ||
let (f, errs) = jaq_parse::parse(filter, jaq_parse::main()); | ||
assert_eq!(errs, Vec::new()); | ||
|
||
// compile the filter in the context of the given definitions | ||
let f = defs.compile(f.unwrap()); | ||
assert!(defs.errs.is_empty()); | ||
|
||
let inputs = RcIter::new(inputs); | ||
|
||
for x in &inputs { | ||
for y in f.run((Ctx::new([], &inputs), x.unwrap())) { | ||
output_newline(); | ||
match y { | ||
Ok(y) => print_val(&y, 0, false), | ||
Err(e) => { | ||
output_tag(&format!("⚠️ Error: {e}"), Some("error")); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.