diff --git a/packages/ludic.ui/backend.ludic b/packages/ludic.ui/backend.ludic index 1fc7bc7f..309256c3 100644 --- a/packages/ludic.ui/backend.ludic +++ b/packages/ludic.ui/backend.ludic @@ -36,6 +36,9 @@ export state UiState { pl_cur: UiPool = null mm: UiMemo = null # memo.ludic: splits, gradients and keys by their text mm_ints: []string = null + mm_ivals: []Val = null + ev_depth: int = 0 # eval.ludic: a call's arguments, in lists kept one a depth + ev_args: []Val = new []Val ly_depth: int = 0 # layout_run.ludic: the lists a line lays out with, one a depth ly_sizes: [][]float = new [][]float ly_frozen: [][]bool = new [][]bool diff --git a/packages/ludic.ui/build.ludic b/packages/ludic.ui/build.ludic index 7ff8d45c..d2e24b37 100644 --- a/packages/ludic.ui/build.ludic +++ b/packages/ludic.ui/build.ludic @@ -49,7 +49,7 @@ function bd_each(ui_st: mut UiState, k: UiTpl, e: UiEnv, key: string, out: []UiN for j in 0 .. Value.count(list) { let le = env_new(ui_st, e) env_bind(le, as_name, Value.at(list, j)) - env_bind(le, at_name, Value.int(j)) + env_bind(le, at_name, mm_ival(ui_st, j)) var id = mm_int(ui_st, j) if by != null { id = ui_eval_text(ui_st, by, le) } bd_kids(ui_st, k.kids, le, mm_join(ui_st, key, "#", id), out) diff --git a/packages/ludic.ui/build_class.ludic b/packages/ludic.ui/build_class.ludic index 641720a5..b4603e57 100644 --- a/packages/ludic.ui/build_class.ludic +++ b/packages/ludic.ui/build_class.ludic @@ -5,7 +5,9 @@ function bd_class(ui_st: mut UiState, k: UiTpl, e: UiEnv, key: string, out: []Ui let cls = k.cls uc_load(ui_st, cls) let it = in_get(ui_st, key, cls) - let props = Value.object() + if it.props == null { it.props = Value.object() } + let props = it.props + Value.clear(props) for i in 0 .. len(k.keys) { let a = k.keys[i] if a != "class" and a != "style" and a != "id" { Value.put(props, a, ui_eval(ui_st, k.vals[i], e)) } diff --git a/packages/ludic.ui/elem.ludic b/packages/ludic.ui/elem.ludic index fb1b32c0..cbaf014c 100644 --- a/packages/ludic.ui/elem.ludic +++ b/packages/ludic.ui/elem.ludic @@ -55,7 +55,7 @@ function el_text(ui_st: mut UiState, n: UiNode, s: string) -> void { function el_keep(ui_st: mut UiState, n: UiNode, key: string, v: Val) -> void { let s = vl_text_u(ui_st, v) if key == "id" { n.id = s } else if key == "class" { - let parts = lss_split(s, 32) + let parts = mm_split(ui_st, s, 32) for i in 0 .. len(parts) { if len(parts[i]) > 0 { push(n.classes, parts[i]) } } diff --git a/packages/ludic.ui/eval.ludic b/packages/ludic.ui/eval.ludic index 9b88cf47..c488dc69 100644 --- a/packages/ludic.ui/eval.ludic +++ b/packages/ludic.ui/eval.ludic @@ -34,8 +34,18 @@ function ui_eval(ui_st: mut UiState, x: UiExpr, e: UiEnv) -> Val { } # a call: len() and range() are the template's own, anything else is the view's function ev_call(ui_st: mut UiState, x: UiExpr, e: UiEnv) -> Val { - let args = Value.list() + let depth = ui_st.ev_depth + while len(ui_st.ev_args) <= depth { push(ui_st.ev_args, Value.list()) } + let args = ui_st.ev_args[depth] + Value.clear(args) + ui_st.ev_depth = depth + 1 for i in 0 .. len(x.args) { Value.add(args, ui_eval(ui_st, x.args[i], e)) } + let r = ev_call_with(ui_st, x, e, args) + ui_st.ev_depth = depth + return r +} +# the call itself, its arguments evaluated; a callee reads them and keeps none +function ev_call_with(ui_st: mut UiState, x: UiExpr, e: UiEnv, args: Val) -> Val { if x.s == "len" and len(x.args) == 1 { return Value.int(Value.count(Value.at(args, 0))) } if x.s == "range" and len(x.args) == 1 { let out = Value.list() diff --git a/packages/ludic.ui/instance.ludic b/packages/ludic.ui/instance.ludic index 57bbec41..30bec83e 100644 --- a/packages/ludic.ui/instance.ludic +++ b/packages/ludic.ui/instance.ludic @@ -5,6 +5,7 @@ property UiInst { cls: UiClass = null ptr: pointer = null seen: int = 0 + props: Val = null # its props, filled again each frame into the same object } function in_get(ui_st: mut UiState, key: string, k: UiClass) -> UiInst { for i in 0 .. len(ui_st.in_list) { diff --git a/packages/ludic.ui/memo_join.ludic b/packages/ludic.ui/memo_join.ludic index c429cff4..6031be13 100644 --- a/packages/ludic.ui/memo_join.ludic +++ b/packages/ludic.ui/memo_join.ludic @@ -40,3 +40,12 @@ function mm_int(ui_st: mut UiState, i: int) -> string { } return ui_st.mm_ints[i] } +# a small whole number as a Value, made once and shared: read it, never change it (a loop's index) +function mm_ival(ui_st: mut UiState, i: int) -> Val { + if i < 0 or i >= 1024 { return Value.int(i) } + if ui_st.mm_ivals == null { + ui_st.mm_ivals = new []Val + for k in 0 .. 1024 { push(ui_st.mm_ivals, Value.int(k)) } + } + return ui_st.mm_ivals[i] +} diff --git a/packages/ludic.ui/native.ludic b/packages/ludic.ui/native.ludic index 6c22b246..374878ab 100644 --- a/packages/ludic.ui/native.ludic +++ b/packages/ludic.ui/native.ludic @@ -78,7 +78,13 @@ export function ui_attr(n: UiNode, key: string) -> Val { } return Value.null() } -export function ui_attr_text(n: UiNode, key: string) -> string { return vl_text(ui_attr(n, key)) } +export function ui_attr_text(n: UiNode, key: string) -> string { + if n.akeys == null { return "" } + for i in 0 .. len(n.akeys) { + if n.akeys[i] == key { return vl_text(n.vals[i]) } + } + return "" +} # a boolean attribute: present with no value is true, as HTML's are (