@@ -1,8 +1,12 @@
1+#![feature(iter_collect_into)]
12mod utils;
23
34use std::rc::Rc;
45
5−use gloo::events::EventListener;
6+use dodrio::{
7+ bumpalo::{self, Bump},
8+ Attribute, Node, NodeKey, Render, RenderContext,
9+};
610use nock::{
711 cue::cue_bytes,
812 interpreter::{generate_interpreter_context, slam},
@@ -10,7 +14,7 @@ use nock::{
1014};
1115use wasm_bindgen::prelude::*;
1216use wasm_bindgen_futures::JsFuture;
13−use web_sys::{Element, HtmlInputElement};
17+use web_sys::Element;
1418
1519#[wasm_bindgen]
1620extern "C" {
@@ -20,45 +24,89 @@ extern "C" {
2024 fn log(s: &str);
2125}
2226
23−#[wasm_bindgen]
24−pub fn greet() {
25− alert("Hello, wock-web!");
27+struct WockApp {
28+ nock: Rc<Noun>,
29+}
30+
31+impl<'a> Render<'a> for WockApp {
32+ fn render(&self, cx: &mut dodrio::RenderContext<'a>) -> dodrio::Node<'a> {
33+ let mut ctx = generate_interpreter_context();
34+
35+ let sail = slam(&mut ctx, &self.nock, &Rc::new(Noun::from_u32(0))).unwrap();
36+
37+ render_sail(cx, &sail)
38+ }
39+}
40+
41+fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: &Rc<Noun>) -> Node<'a> {
42+ let (marx, marl) = manx.as_cell().unwrap();
43+ let (mane, mart) = marx.as_cell().unwrap();
44+
45+ if mane.is_sig() {
46+ let contents = mart
47+ .list_iter()
48+ .map(|attr| attr.as_cell().unwrap())
49+ .find(|(key, _)| key.is_sig())
50+ .map(|(_, value)| tape_to_bump_str(ctx.bump, value))
51+ .unwrap_or("");
52+ Node::text(contents)
53+ } else {
54+ let mut children = bumpalo::collections::Vec::new_in(&ctx.bump);
55+ marl.list_iter()
56+ .map(|child| render_sail(ctx, child))
57+ .collect_into(&mut children);
58+
59+ let mut attributes = bumpalo::collections::Vec::new_in(ctx.bump);
60+ mart.list_iter()
61+ .map(|attr| {
62+ let (name, value) = attr.as_cell().unwrap();
63+ Attribute {
64+ name: cord_to_bump_str(ctx.bump, name),
65+ value: cord_to_bump_str(ctx.bump, value),
66+ }
67+ })
68+ .collect_into(&mut attributes);
69+
70+ let listeners = bumpalo::collections::Vec::new_in(ctx.bump);
71+
72+ Node::element(
73+ &ctx.bump,
74+ NodeKey::NONE,
75+ cord_to_bump_str(ctx.bump, mane),
76+ listeners.into_bump_slice(),
77+ attributes.into_bump_slice(),
78+ children.into_bump_slice(),
79+ None,
80+ )
81+ }
2682}
2783
28−static mut LISTENER: Option<EventListener> = None;
84+fn cord_to_bump_str<'a>(bump: &'a Bump, non: &Rc<Noun>) -> &'a str {
85+ let bytes =
86+ bumpalo::collections::Vec::from_iter_in(non.as_bytes().unwrap().iter().cloned(), bump);
87+ &*bumpalo::collections::String::from_utf8(bytes)
88+ .unwrap()
89+ .into_bump_str()
90+}
91+
92+fn tape_to_bump_str<'a>(bump: &'a Bump, non: &Rc<Noun>) -> &'a str {
93+ let bytes = bumpalo::collections::Vec::from_iter_in(
94+ non.list_iter().map(|char| char.as_u32().unwrap() as u8),
95+ bump,
96+ );
97+ &*bumpalo::collections::String::from_utf8(bytes)
98+ .unwrap()
99+ .into_bump_str()
100+}
29101
30102#[wasm_bindgen]
31103pub async fn main(path: &str) {
32104 let nock = load_nock(path).await;
33105
34− let mut ctx = generate_interpreter_context();
35−
36106 let document = gloo::utils::document();
37− let input_element: web_sys::HtmlInputElement = document
38− .get_element_by_id("input")
39− .unwrap()
40− .dyn_into()
41− .unwrap();
42107 let output_el: Element = document.get_element_by_id("output").unwrap();
43− unsafe {
44− LISTENER = Some(EventListener::new(&input_element, "input", move |ev| {
45− let el: HtmlInputElement = ev.target().unwrap().dyn_into().unwrap();
46−
47− let bar = slam(
48− &mut ctx,
49− &nock,
50− &Rc::new(Noun::from_bytes(el.value().as_bytes())),
51− )
52− .unwrap();
53−
54− let foo = bar.as_bytes().unwrap();
55− let qux = String::from_utf8(foo).unwrap();
56−
57− output_el.set_inner_html(&*qux);
58− }));
59− }
60108
61− // window.get_eleme
109+ dodrio::Vdom::new(&output_el, WockApp { nock }).forget();
62110}
63111
64112pub async fn load_nock(path: &str) -> Rc<Noun> {