ludic.ui: parsing at load gives back what it does not keep - tpl_words written once into bytes of its own (a string a character before), a stylesheet's stripped text, its error list and each reader freed once read, ex_text's joining node freed when it collapses to one piece or none
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d9612ba2a6
commit
179dd60536
3 changed files with 31 additions and 9 deletions
|
|
@ -82,7 +82,14 @@ function ex_text(src: string, err: []string) -> UiExpr {
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
if at < len(src) { push(e.args, ex_lit(Value.str(src[at..len(src)]))) }
|
if at < len(src) { push(e.args, ex_lit(Value.str(src[at..len(src)]))) }
|
||||||
if len(e.args) == 0 { return ex_lit(Value.str("")) }
|
if len(e.args) > 1 { return e }
|
||||||
if len(e.args) == 1 { return e.args[0] }
|
# one piece or none: the joining node is not kept, so it is given back
|
||||||
return e
|
var one: UiExpr = null
|
||||||
|
if len(e.args) == 1 { one = e.args[0] }
|
||||||
|
unsafe {
|
||||||
|
free(e.args)
|
||||||
|
free(e)
|
||||||
|
}
|
||||||
|
if one == null { return ex_lit(Value.str("")) }
|
||||||
|
return one
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,12 @@ function lss_file(ui_st: mut UiState, src: string, path: string) -> UiFile {
|
||||||
@alloc_ok("a stylesheet being read: once per component class (uc_load)")
|
@alloc_ok("a stylesheet being read: once per component class (uc_load)")
|
||||||
function lss_text(ui_st: mut UiState, f: UiFile, src: string) -> void {
|
function lss_text(ui_st: mut UiState, f: UiFile, src: string) -> void {
|
||||||
let err = new []string
|
let err = new []string
|
||||||
lss_block(ui_st, f, lss_strip(src), null, err)
|
let body = lss_strip(src) # always a copy of its own (lss_strip joins its pieces)
|
||||||
|
lss_block(ui_st, f, body, null, err)
|
||||||
|
unsafe { free(body) } # every rule, selector and value read from it is a copy
|
||||||
@alloc_ok("only when a template is wrong: a broken screen, never a working one")
|
@alloc_ok("only when a template is wrong: a broken screen, never a working one")
|
||||||
for i in 0 .. len(err) { ui_err(ui_st, `{f.path}: <style> {err[i]}`) }
|
for i in 0 .. len(err) { ui_err(ui_st, `{f.path}: <style> {err[i]}`) }
|
||||||
|
unsafe { free(err) }
|
||||||
}
|
}
|
||||||
# rules, @imports and @media blocks; the rules in a @media block carry its condition
|
# rules, @imports and @media blocks; the rules in a @media block carry its condition
|
||||||
function lss_block(ui_st: mut UiState, f: UiFile, src: string, md: UiMedia, err: []string) -> void {
|
function lss_block(ui_st: mut UiState, f: UiFile, src: string, md: UiMedia, err: []string) -> void {
|
||||||
|
|
@ -62,6 +65,7 @@ function lss_block(ui_st: mut UiState, f: UiFile, src: string, md: UiMedia, err:
|
||||||
for i in at .. len(f.own) { f.own[i].md = md }
|
for i in at .. len(f.own) { f.own[i].md = md }
|
||||||
}
|
}
|
||||||
if r.err != "" { push(err, r.err) }
|
if r.err != "" { push(err, r.err) }
|
||||||
|
unsafe { free(r) } # the reader only: its text is the caller's
|
||||||
}
|
}
|
||||||
# @import "base.lss"; - its rules come before this file's own
|
# @import "base.lss"; - its rules come before this file's own
|
||||||
function lss_import(ui_st: mut UiState, f: UiFile, what: string) -> void {
|
function lss_import(ui_st: mut UiState, f: UiFile, what: string) -> void {
|
||||||
|
|
|
||||||
|
|
@ -72,17 +72,28 @@ function tpl_value(v: string, err: []string) -> UiExpr {
|
||||||
@alloc_ok("a memo miss (tw) or a template being read: once per text")
|
@alloc_ok("a memo miss (tw) or a template being read: once per text")
|
||||||
function tpl_words(s: string) -> string {
|
function tpl_words(s: string) -> string {
|
||||||
if tpl_clean(s) { return s }
|
if tpl_clean(s) { return s }
|
||||||
var out = ""
|
# written once into bytes of its own, as a TextRing slot is: a text built a character at a time
|
||||||
|
# left a string behind for every character
|
||||||
|
var p: pointer = null
|
||||||
|
unsafe { p = bytes(len(s) + 1) }
|
||||||
|
var n = 0
|
||||||
var gap = false
|
var gap = false
|
||||||
for i in 0 .. len(s) {
|
for i in 0 .. len(s) {
|
||||||
let c = s[i]
|
let c = s[i]
|
||||||
if c == 32 or c == 9 or c == 10 or c == 13 { gap = len(out) > 0 } else {
|
if c == 32 or c == 9 or c == 10 or c == 13 { gap = n > 0 } else {
|
||||||
if gap { out = out + " " }
|
unsafe {
|
||||||
|
if gap {
|
||||||
|
p[n] = 32
|
||||||
|
n += 1
|
||||||
|
}
|
||||||
|
p[n] = c
|
||||||
|
}
|
||||||
|
n += 1
|
||||||
gap = false
|
gap = false
|
||||||
out = out + s[i..i + 1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
unsafe { p[n] = 0 }
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
function tpl_attr(t: UiTpl, key: string) -> UiExpr {
|
function tpl_attr(t: UiTpl, key: string) -> UiExpr {
|
||||||
for i in 0 .. len(t.keys) {
|
for i in 0 .. len(t.keys) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue