on master help sign in
Basic app
7d27db8iko
nock/src/main.rs+2−2
@@ -146,7 +146,7 @@ fn main() -> Result<(), std::io::Error> {
146}
146}
147
147
148/// Reads a `vase` from a `.nock` file.
148/// Reads a `vase` from a `.nock` file.
149−fn read_nock(nock_file: &PathBuf) -> Result<Vase, std::io::Error> {
149+fn read_nock(nock_file: &PathBuf) -> Result<(Rc<Noun>, Rc<Noun>), std::io::Error> {
150 let nock = cue_bytes(&read_file(nock_file)?);
150 let nock = cue_bytes(&read_file(nock_file)?);
151 let (typ, nok) = nock.as_cell().unwrap();
151 let (typ, nok) = nock.as_cell().unwrap();
152 Ok((typ.clone(), nok.clone()))
152 Ok((typ.clone(), nok.clone()))
@@ -223,7 +223,7 @@ fn read_nock_or_compile(
223 ctx: &mut InterpreterContext,
223 ctx: &mut InterpreterContext,
224 urbit: &LazyCell<Rc<Noun>>,
224 urbit: &LazyCell<Rc<Noun>>,
225 path: &PathBuf,
225 path: &PathBuf,
226−) -> Result<Vase, std::io::Error> {
226+) -> Result<(Rc<Noun>, Rc<Noun>), std::io::Error> {
227 if path.extension().and_then(|x| x.to_str()) == Some("hoon") {
227 if path.extension().and_then(|x| x.to_str()) == Some("hoon") {
228 let nock = compile_to_nock(ctx, urbit, spinner, path.clone())?;
228 let nock = compile_to_nock(ctx, urbit, spinner, path.clone())?;
229 let (typ, nok) = nock.as_cell().unwrap();
229 let (typ, nok) = nock.as_cell().unwrap();
nock/wock.hoonnew file+51
@@ -0,0 +1,51 @@
1+=>
2+|%
3+++ wock-app
4+ |$ [model event]
5+ $_ ^?
6+ |%
7+ ++ init *model
8+ ++ view |~ model *manx
9+ ++ move |~ [model [event *]] *model
10+ --
11+++ app
12+ |* [model=mold event=mold]
13+ |= app=(wock-app model event)
14+ |= [cmd=@tas args=*]
15+ ?+ cmd !!
16+ %init
17+ init.app
18+ %view
19+ (view.app (model args))
20+ %move
21+ =/ [=model event-tape=tape payload=*] (,[model tape *] args)
22+ (move.app [model (event (crip event-tape)) payload])
23+ ==
24+--
25+=>
26+|%
27++$ event
28+ $?
29+ %inc
30+ %dec
31+ ==
32+--
33+%- (app @ud event)
34+|%
35+++ view
36+ |= count=@ud
37+ ^- manx
38+ ;div
39+ ;h1: {<count>}
40+ ;button(on-click "inc"): +
41+ ;button(on-click "dec"): -
42+ ==
43+++ init 8
44+++ move
45+ |= [model=@ud step=[event *]]
46+ ^- @ud
47+ ?- -.step
48+ %inc +(model)
49+ %dec ?: =(model 0) 0 (dec model)
50+ ==
51+--
nock/wock.nocknew file

Binary file not shown.

wock-web/Cargo.toml+1−1
@@ -37,7 +37,7 @@ wasm-bindgen-test = "0.3.34"
37
37
38[profile.release]
38[profile.release]
39# Tell `rustc` to optimize for small code size.
39# Tell `rustc` to optimize for small code size.
40−opt-level = "s"
40+opt-level = 3
41
41
42[package.metadata.wasm-pack.profile.dev]
42[package.metadata.wasm-pack.profile.dev]
43wasm-opt = ["-O", "--enable-bulk-memory"]
43wasm-opt = ["-O", "--enable-bulk-memory"]
wock-web/build.sh+1−1
@@ -1,3 +1,3 @@
1#!/bin/sh
1#!/bin/sh
2
2
3−wasm-pack build --no-typescript --no-pack --target=web --dev
3+wasm-pack build --release --no-typescript --no-pack --target=web
wock-web/event-payloads.mdnew file+5
@@ -0,0 +1,5 @@
1+# Event payloads
2+
3+| Event attribute name | Hoon payload |
4+| --- | ----------- |
5+| `on-click` | `~` |
wock-web/index.html+1−2
@@ -3,8 +3,7 @@
3 <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
3 <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
4 </head>
4 </head>
5 <body>
5 <body>
6− <input id="input"></input>
7 <div id="output"></div>
6 <div id="output"></div>
8− <script type="module" src="script.mjs?src=/sail.nock"></script>
7+ <script type="module" src="script.mjs?src=/wock.nock"></script>
9 </body>
8 </body>
10</html>
9</html>
wock-web/src/lib.rs+62−17
@@ -5,12 +5,12 @@ use std::rc::Rc;
5
5
6use dodrio::{
6use dodrio::{
7 bumpalo::{self, Bump},
7 bumpalo::{self, Bump},
8− Attribute, Node, NodeKey, Render, RenderContext,
8+ Attribute, Listener, Node, NodeKey, Render, RenderContext, RootRender, VdomWeak,
9};
9};
10use nock::{
10use nock::{
11 cue::cue_bytes,
11 cue::cue_bytes,
12 interpreter::{generate_interpreter_context, slam},
12 interpreter::{generate_interpreter_context, slam},
13− noun::Noun,
13+ noun::{cell, Noun},
14};
14};
15use wasm_bindgen::prelude::*;
15use wasm_bindgen::prelude::*;
16use wasm_bindgen_futures::JsFuture;
16use wasm_bindgen_futures::JsFuture;
@@ -26,19 +26,25 @@ extern "C" {
26
26
27struct WockApp {
27struct WockApp {
28 nock: Rc<Noun>,
28 nock: Rc<Noun>,
29+ model: Rc<Noun>,
29}
30}
30
31
31impl<'a> Render<'a> for WockApp {
32impl<'a> Render<'a> for WockApp {
32 fn render(&self, cx: &mut dodrio::RenderContext<'a>) -> dodrio::Node<'a> {
33 fn render(&self, cx: &mut dodrio::RenderContext<'a>) -> dodrio::Node<'a> {
33 let mut ctx = generate_interpreter_context();
34 let mut ctx = generate_interpreter_context();
34
35
35− let sail = slam(&mut ctx, &self.nock, &Rc::new(Noun::from_u32(0))).unwrap();
36+ let sail = slam(
37+ &mut ctx,
38+ &self.nock,
39+ &cell(&Rc::new(Noun::from_bytes(b"view")), &self.model),
40+ )
41+ .unwrap();
36
42
37− render_sail(cx, &sail)
43+ render_sail(cx, sail)
38 }
44 }
39}
45}
40
46
41−fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: &Rc<Noun>) -> Node<'a> {
47+fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: Rc<Noun>) -> Node<'a> {
42 let (marx, marl) = manx.as_cell().unwrap();
48 let (marx, marl) = manx.as_cell().unwrap();
43 let (mane, mart) = marx.as_cell().unwrap();
49 let (mane, mart) = marx.as_cell().unwrap();
44
50
@@ -53,21 +59,51 @@ fn render_sail<'a>(ctx: &mut RenderContext<'a>, manx: &Rc<Noun>) -> Node<'a> {
53 } else {
59 } else {
54 let mut children = bumpalo::collections::Vec::new_in(&ctx.bump);
60 let mut children = bumpalo::collections::Vec::new_in(&ctx.bump);
55 marl.list_iter()
61 marl.list_iter()
56− .map(|child| render_sail(ctx, child))
62+ .map(|child| render_sail(ctx, child.clone()))
57 .collect_into(&mut children);
63 .collect_into(&mut children);
58
64
59 let mut attributes = bumpalo::collections::Vec::new_in(ctx.bump);
65 let mut attributes = bumpalo::collections::Vec::new_in(ctx.bump);
66+ let mut listeners = bumpalo::collections::Vec::new_in(ctx.bump);
67+
60− mart.list_iter()
68+ mart.list_iter().for_each(|attr| {
61− .map(|attr| {
62− let (name, value) = attr.as_cell().unwrap();
69+ let (name, value) = attr.as_cell().unwrap();
70+ match &*name.as_bytes().unwrap() {
71+ b"on-click" => listeners.push(Listener {
72+ event: "click",
73+ callback: {
74+ let value = value.clone();
75+ ctx.bump.alloc(
76+ move |root: &mut dyn RootRender,
77+ vdom: VdomWeak,
78+ _event: web_sys::Event| {
79+ let mut ctx = generate_interpreter_context();
80+ let sig = ctx.nouns.sig.clone();
81+
82+ let app = root.unwrap_mut::<WockApp>();
83+
84+ let new_model = slam(
85+ &mut ctx,
86+ &app.nock,
87+ &cell(
88+ &Rc::new(Noun::from_bytes(b"move")),
89+ &cell(&app.model, &cell(&value, &sig)),
90+ ),
91+ )
92+ .unwrap();
93+
94+ app.model = new_model;
95+
96+ vdom.schedule_render();
97+ },
98+ )
99+ },
100+ }),
63− Attribute {
101+ _ => attributes.push(Attribute {
64 name: cord_to_bump_str(ctx.bump, name),
102 name: cord_to_bump_str(ctx.bump, name),
65− value: cord_to_bump_str(ctx.bump, value),
103+ value: tape_to_bump_str(ctx.bump, value),
66− }
104+ }),
67− })
105+ };
68− .collect_into(&mut attributes);
106+ });
69−
70− let listeners = bumpalo::collections::Vec::new_in(ctx.bump);
71
107
72 Node::element(
108 Node::element(
73 &ctx.bump,
109 &ctx.bump,
@@ -106,7 +142,16 @@ pub async fn main(path: &str) {
106 let document = gloo::utils::document();
142 let document = gloo::utils::document();
107 let output_el: Element = document.get_element_by_id("output").unwrap();
143 let output_el: Element = document.get_element_by_id("output").unwrap();
108
144
145+ let mut ctx = generate_interpreter_context();
146+
147+ let model = slam(
148+ &mut ctx,
149+ &nock,
150+ &cell(&Rc::new(Noun::from_bytes(b"init")), &Rc::new(Noun::SIG)),
151+ )
152+ .unwrap();
153+
109− dodrio::Vdom::new(&output_el, WockApp { nock }).forget();
154+ dodrio::Vdom::new(&output_el, WockApp { nock, model }).forget();
110}
155}
111
156
112pub async fn load_nock(path: &str) -> Rc<Noun> {
157pub async fn load_nock(path: &str) -> Rc<Noun> {
wock.nocknew file

Binary file not shown.