#!/usr/bin/env bx use b use rope def io_block_size 1024 Main() sched_init() new(r, html_reader) new(w, rope_sayer) sh(rope, r, w) start(r) start(w) run() process html_reader() rope rope_null rope_set_null(rope_null) state circbuf b port rope out init(&b, circbuf, io_block_size) repeat Read(STDIN_FILENO, circbuf_get_end(b), wr(out, r("hello")) wr(out, r("world")) wr(out, r("this")) wr(out, r("is")) wr(out, r("nice")) wr(out, rope_null) process rope_sayer() port rope in rope r repeat rd(in, r) if rope_is_null(r) break say_rope(r) fprint_rope(FILE *stream, rope r) for_str_in_rope(s, r) fprint_str(stream, s) # TODO use writev? fprint_str(FILE *stream, str s) Fwrite(str_get_start(s), 1, str_get_size(s), stream) # this defines print and say functions for type foo in terms of fprint_foo Def prints_and_says(type) print_^^type(type o) fprint_^^type(stdout, o) fsay_^^type(FILE *stream, type o) fprint_^^type(stream, o) nl(stream) say_^^type(type o) fsay_^^type(stdout, o) prints_and_says(rope) prints_and_says(str) # brace_shuffle is borked #typedef void (*str_f)(str s) #rope_each_str(rope r, void (*f)(str s)) # if rope_is_empty(r) # . # eif rope_is_a_str(r) # (*f)(r.s) # else # ropev_each_str(r.v, f) # #ropev_each_str(ropev v, void (*f)(str s)) # for(i, ropev_range(v)) # rope_each_str(*i, f) def for_str_in_rope(S, R) new(my(q), deque, rope) deque_push(my(q), R) rope my(r) while deque_get_size(my(q)) deque_shift(my(q), my(r)) if rope_is_empty(my(r)) continue eif rope_is_a_ropev(my(r)) for(i, ropev_range(my(r).v)) deque_push(my(q), my(r)) continue let(S, my(r).s) # idea - functions that have access to env of caller "automatically" without # having to pass in params, create automatically for each macro YYY! shuttle(rope)