Skip to content

Commit a681775

Browse files
committed
feat: Add Christmas tree demo and enable incremental output from WASM to the UI.
1 parent f6904e6 commit a681775

File tree

8 files changed

+142
-25
lines changed

8 files changed

+142
-25
lines changed

demo_codes/christmas_tree.ch

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
let println = import "stdlib/io".println
2+
3+
# 简单的字符串重复函数
4+
def repeat(str, count) {
5+
let res = ""
6+
let i = 0
7+
for i < count {
8+
res = res + str
9+
i = i + 1
10+
}
11+
return res
12+
}
13+
14+
def print_tree(height) {
15+
println("🎄 Merry Christmas! 🎄")
16+
println("")
17+
18+
# 打印树冠
19+
let i = 1
20+
for i <= height {
21+
let spaces = repeat(" ", height - i)
22+
# 装饰一点彩灯(简单随机模拟:用不同字符?)
23+
# 这里仅用星星
24+
let stars = repeat("*", 2 * i - 1)
25+
println(spaces + stars)
26+
i = i + 1
27+
}
28+
29+
# 打印树干
30+
let trunk_padding = repeat(" ", height - 2)
31+
32+
let j = 0
33+
for j < 2 {
34+
println(trunk_padding + "###")
35+
j = j + 1
36+
}
37+
38+
println("")
39+
println(repeat(" ", height - 4) + "Happy New Year!")
40+
}
41+
42+
print_tree(10)

docs/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ <h1>Chen Lang <span>Playground</span></h1>
3838
<option value="async_task">Coroutines</option>
3939
<option value="async_http">Async HTTP Request</option>
4040
<option value="concurrent_http">Concurrent HTTP</option>
41+
<option value="christmas_tree">Christmas Tree</option>
4142
</select>
4243
</div>
4344
<button id="run">

docs/index.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,48 @@ println("All requests completed!")
364364
println("Request 1 status: " + results[0])
365365
println("Request 2 status: " + results[1])
366366
println("Request 3 UUID: " + results[2])
367+
`,
368+
christmas_tree: `# Merry Christmas!
369+
let println = import "stdlib/io".println
370+
371+
# Simple string repeat function
372+
def repeat(str, count) {
373+
let res = ""
374+
let i = 0
375+
for i < count {
376+
res = res + str
377+
i = i + 1
378+
}
379+
return res
380+
}
381+
382+
def print_tree(height) {
383+
println("🎄 Merry Christmas! 🎄")
384+
println("")
385+
386+
# Print leaves
387+
let i = 1
388+
for i <= height {
389+
let spaces = repeat(" ", height - i)
390+
let stars = repeat("*", 2 * i - 1)
391+
println(spaces + stars)
392+
i = i + 1
393+
}
394+
395+
# Print trunk
396+
let trunk_padding = repeat(" ", height - 2)
397+
398+
let j = 0
399+
for j < 2 {
400+
println(trunk_padding + "###")
401+
j = j + 1
402+
}
403+
404+
println("")
405+
println(repeat(" ", height - 4) + "Happy New Year!")
406+
}
407+
408+
print_tree(10)
367409
`
368410
};
369411

@@ -455,11 +497,20 @@ async function run() {
455497

456498
runBtn.addEventListener('click', async () => {
457499
const code = codeArea.value;
500+
outputArea.textContent = '';
501+
502+
window.print_output = (text) => {
503+
outputArea.textContent += text;
504+
outputArea.scrollTop = outputArea.scrollHeight;
505+
};
506+
458507
try {
459508
const result = await run_wasm(code);
460-
outputArea.textContent = result;
509+
if (result) outputArea.textContent += result;
461510
} catch (e) {
462-
outputArea.textContent = `Error: ${e}`;
511+
outputArea.textContent += `Error: ${e}`;
512+
} finally {
513+
window.print_output = null;
463514
}
464515
});
465516

docs/pkg/chen_lang.d.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ export interface InitOutput {
99
readonly memory: WebAssembly.Memory;
1010
readonly run: (a: number, b: number) => void;
1111
readonly run_wasm: (a: number, b: number) => any;
12-
readonly wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue_____: (a: number, b: number, c: any) => void;
13-
readonly wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut__wasm_bindgen_47816a2d43ec07ce___JsValue____Output_______: (a: number, b: number) => void;
14-
readonly wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke______: (a: number, b: number) => void;
15-
readonly wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
16-
readonly wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue__wasm_bindgen_47816a2d43ec07ce___JsValue_____: (a: number, b: number, c: any, d: any) => void;
12+
readonly wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue_____: (a: number, b: number, c: any) => void;
13+
readonly wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut__wasm_bindgen_3453c9d0e447211b___JsValue____Output_______: (a: number, b: number) => void;
14+
readonly wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke______: (a: number, b: number) => void;
15+
readonly wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
16+
readonly wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue__wasm_bindgen_3453c9d0e447211b___JsValue_____: (a: number, b: number, c: any, d: any) => void;
1717
readonly __wbindgen_malloc: (a: number, b: number) => number;
1818
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
1919
readonly __wbindgen_exn_store: (a: number) => void;

docs/pkg/chen_lang.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,16 +208,16 @@ if (!('encodeInto' in cachedTextEncoder)) {
208208

209209
let WASM_VECTOR_LEN = 0;
210210

211-
function wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue_____(arg0, arg1, arg2) {
212-
wasm.wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue_____(arg0, arg1, arg2);
211+
function wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue_____(arg0, arg1, arg2) {
212+
wasm.wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue_____(arg0, arg1, arg2);
213213
}
214214

215-
function wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke______(arg0, arg1) {
216-
wasm.wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke______(arg0, arg1);
215+
function wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke______(arg0, arg1) {
216+
wasm.wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke______(arg0, arg1);
217217
}
218218

219-
function wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue__wasm_bindgen_47816a2d43ec07ce___JsValue_____(arg0, arg1, arg2, arg3) {
220-
wasm.wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue__wasm_bindgen_47816a2d43ec07ce___JsValue_____(arg0, arg1, arg2, arg3);
219+
function wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue__wasm_bindgen_3453c9d0e447211b___JsValue_____(arg0, arg1, arg2, arg3) {
220+
wasm.wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue__wasm_bindgen_3453c9d0e447211b___JsValue_____(arg0, arg1, arg2, arg3);
221221
}
222222

223223
const __wbindgen_enum_RequestCache = ["default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached"];
@@ -403,7 +403,7 @@ function __wbg_get_imports() {
403403
const a = state0.a;
404404
state0.a = 0;
405405
try {
406-
return wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue__wasm_bindgen_47816a2d43ec07ce___JsValue_____(a, state0.b, arg0, arg1);
406+
return wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue__wasm_bindgen_3453c9d0e447211b___JsValue_____(a, state0.b, arg0, arg1);
407407
} finally {
408408
state0.a = a;
409409
}
@@ -430,6 +430,9 @@ function __wbg_get_imports() {
430430
const ret = arg0.next();
431431
return ret;
432432
}, arguments) };
433+
imports.wbg.__wbg_print_output_0fa5b8f975cf9b66 = function(arg0, arg1) {
434+
print_output(getStringFromWasm0(arg0, arg1));
435+
};
433436
imports.wbg.__wbg_queueMicrotask_9b549dfce8865860 = function(arg0) {
434437
const ret = arg0.queueMicrotask;
435438
return ret;
@@ -519,7 +522,7 @@ function __wbg_get_imports() {
519522
};
520523
imports.wbg.__wbindgen_cast_06ecd7d2bbdbbef7 = function(arg0, arg1) {
521524
// Cast intrinsic for `Closure(Closure { dtor_idx: 278, function: Function { arguments: [], shim_idx: 279, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
522-
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut_____Output_______, wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke______);
525+
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut_____Output_______, wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke______);
523526
return ret;
524527
};
525528
imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
@@ -529,7 +532,7 @@ function __wbg_get_imports() {
529532
};
530533
imports.wbg.__wbindgen_cast_b1bcbba6fa3c236c = function(arg0, arg1) {
531534
// Cast intrinsic for `Closure(Closure { dtor_idx: 357, function: Function { arguments: [Externref], shim_idx: 358, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
532-
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut__wasm_bindgen_47816a2d43ec07ce___JsValue____Output_______, wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue_____);
535+
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut__wasm_bindgen_3453c9d0e447211b___JsValue____Output_______, wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue_____);
533536
return ret;
534537
};
535538
imports.wbg.__wbindgen_init_externref_table = function() {

docs/pkg/chen_lang_bg.wasm

-2.99 KB
Binary file not shown.

docs/pkg/chen_lang_bg.wasm.d.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
export const memory: WebAssembly.Memory;
44
export const run: (a: number, b: number) => void;
55
export const run_wasm: (a: number, b: number) => any;
6-
export const wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue_____: (a: number, b: number, c: any) => void;
7-
export const wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut__wasm_bindgen_47816a2d43ec07ce___JsValue____Output_______: (a: number, b: number) => void;
8-
export const wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke______: (a: number, b: number) => void;
9-
export const wasm_bindgen_47816a2d43ec07ce___closure__destroy___dyn_core_3cd24c61823388c3___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
10-
export const wasm_bindgen_47816a2d43ec07ce___convert__closures_____invoke___wasm_bindgen_47816a2d43ec07ce___JsValue__wasm_bindgen_47816a2d43ec07ce___JsValue_____: (a: number, b: number, c: any, d: any) => void;
6+
export const wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue_____: (a: number, b: number, c: any) => void;
7+
export const wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut__wasm_bindgen_3453c9d0e447211b___JsValue____Output_______: (a: number, b: number) => void;
8+
export const wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke______: (a: number, b: number) => void;
9+
export const wasm_bindgen_3453c9d0e447211b___closure__destroy___dyn_core_1ea7ec8b69c1cd75___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
10+
export const wasm_bindgen_3453c9d0e447211b___convert__closures_____invoke___wasm_bindgen_3453c9d0e447211b___JsValue__wasm_bindgen_3453c9d0e447211b___JsValue_____: (a: number, b: number, c: any, d: any) => void;
1111
export const __wbindgen_malloc: (a: number, b: number) => number;
1212
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
1313
export const __wbindgen_exn_store: (a: number) => void;

src/lib.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,28 @@ fn get_line_range(code: &str, line: u32) -> Range<usize> {
191191
if len > 0 { len - 1..len } else { 0..0 }
192192
}
193193

194+
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
195+
#[wasm_bindgen]
196+
extern "C" {
197+
#[wasm_bindgen(js_name = print_output)]
198+
fn print_output(s: &str);
199+
}
200+
201+
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
202+
struct RealtimeWriter;
203+
204+
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
205+
impl Write for RealtimeWriter {
206+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
207+
let s = String::from_utf8_lossy(buf);
208+
print_output(&s);
209+
Ok(buf.len())
210+
}
211+
fn flush(&mut self) -> std::io::Result<()> {
212+
Ok(())
213+
}
214+
}
215+
194216
#[cfg(all(feature = "wasm", target_arch = "wasm32"))]
195217
#[wasm_bindgen]
196218
pub async fn run_wasm(code: String) -> String {
@@ -201,17 +223,15 @@ pub async fn run_wasm(code: String) -> String {
201223

202224
let program = compiler::compile(&code.chars().collect::<Vec<char>>(), ast);
203225

204-
let output = Arc::new(Mutex::new(Vec::new()));
205-
let writer = SharedWriter(output.clone());
226+
let writer = RealtimeWriter;
206227

207228
{
208229
let mut vm = vm::VM::with_writer(Box::new(writer));
209230
// Execute async to handle HTTP requests and other async operations
210231
let _result = vm.execute_async(Rc::new(program)).await?;
211232
}
212233

213-
let output_vec = output.lock().unwrap().clone();
214-
Ok::<String, ChenError>(String::from_utf8(output_vec)?)
234+
Ok::<String, ChenError>(String::new())
215235
}
216236
.await;
217237

0 commit comments

Comments
 (0)