# act.ludic - what a press does: `buy(i)` asks the view, `set pick = i` changes a state, and # `emit picked` runs what the component's user said with on-picked. Several are `;` apart. A call # of a function named set or emit (`set(4)`, a component's `on set(v)`) is a call. const A_CALL: int = 0 const A_SET: int = 1 const A_EMIT: int = 2 property UiAct { kinds: []int = null names: []string = null exprs: []UiExpr = null } function act_parse(src: string, err: []string) -> UiAct { let a = new UiAct a.kinds = new []int a.names = new []string a.exprs = new []UiExpr let r = new UiRd r.s = src while r.err == "" { rd_ws(r) if r.i >= len(r.s) { break } if act_keyword(r, "set") { push(a.kinds, A_SET) push(a.names, rd_name(r)) if not rd_op(r, "=") { rd_fail(r, "'='") } push(a.exprs, px_cond(r)) } else if act_keyword(r, "emit") { push(a.kinds, A_EMIT) push(a.names, tpl_event(rd_name(r))) # `emit click` reaches on-click, which is kept as press push(a.exprs, null) } else { push(a.kinds, A_CALL) push(a.names, "") push(a.exprs, px_cond(r)) } if not rd_op(r, ";") { break } } rd_ws(r) if r.err == "" and r.i < len(r.s) { rd_fail(r, "';' or the end") } if r.err != "" { push(err, r.err) } unsafe { free(r) } # the reader only: names and expressions are copied out return a } # `set` or `emit` as the action's first word - not a function of that name, as in `set(4)` function act_keyword(r: UiRd, word: string) -> bool { let at = r.i if not rd_word(r, word) { return false } rd_ws(r) if r.i < len(r.s) and r.s[r.i] == 40 { r.i = at return false } return true } function act_run(ui_st: mut UiState, a: UiAct, e: UiEnv) -> void { for i in 0 .. len(a.kinds) { if a.kinds[i] == A_SET { env_set(ui_st, e, a.names[i], ui_eval(ui_st, a.exprs[i], e)) } if a.kinds[i] == A_CALL { ui_eval(ui_st, a.exprs[i], e) } if a.kinds[i] == A_EMIT { act_emit(ui_st, a.names[i], e) } } } function act_emit(ui_st: mut UiState, name: string, e: UiEnv) -> void { if ui_st.ui_be != null and ui_st.ui_be.emitted != null { ui_st.ui_be.emitted(name) } var at = e while at != null { if at.on_names != null { for i in 0 .. len(at.on_names) { if at.on_names[i] == name { act_run(ui_st, at.on_acts[i], at.on_envs[i]) return } } } at = at.parent } }