code wiki / _hdl_build / nx_grid_gate.nx
nx_grid_gate.nx source
↩ module page · 159 lines · 9173 B
1// nx_grid_gate.nx -- VERDICT gate for the GRID rung (display:grid + grid-template-columns) of the
2// sovereign HTML renderer. Runs the REAL render pipeline prefix on controlled grid fixtures and ASSERTS
3// exact box geometry (measured via nx_grid_test, not guessed). Proves: N equal columns from an explicit
4// track list `1fr 1fr 1fr` AND from `repeat(3, 1fr)`; ROW-MAJOR WRAPPING (4 kids / 2 cols -> row 2 at
5// y=10); and a DIFFERENTIAL no-grid control (same markup STACKS without display:grid -> a no-op grid
6// can't pass both). LIAR-KILL: the checker fed a wrong expectation must reject it. GREEN iff all hold.
7// Also exercises the CSS multi-token value capture (grid-template-columns is a multi-value property).
8// 100% sovereign (no gcc/V8/Chrome). license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_css_tokenize.nx"
11import "nx_css_parse.nx"
12import "nx_css_apply.nx"
13import "nx_css_color_decode.nx"
14import "nx_css_dimension_to_px.nx"
15import "nx_css_selector_match.nx"
16import "nx_html_tokenizer.nx"
17import "nx_dom_query.nx"
18import "nx_layout_box.nx"
19import "nx_layout_default_display.nx"
20import "nx_layout_from_dom.nx"
21import "nx_layout_block.nx"
22import "nx_render_html.nx"
23
24func g_w(s: *u8) -> i64 { var k: i64=0; while s[k]!=(0 as u8){k=k+1} sys_write(1,s,k); return 0 }
25func pn(v0: i64) -> i64 { var v: i64=v0; if v<0 { let m: *u8=sys_mmap(8); m[0]=45 as u8; sys_write(1,m,1); v=0-v } let b: *u8=sys_mmap(24); var k: i64=0; if v==0 {b[0]=48;k=1} while v>0 {b[k]=(48+(v%10)) as u8; v=v/10; k=k+1} let o: *u8=sys_mmap(24); var j: i64=0; while j<k {o[j]=b[k-1-j];j=j+1} sys_write(1,o,k); return 0 }
26
27// Run the REAL render pipeline prefix on (html + css) at viewport vw; return the laid-out box tree.
28func run_layout(html: *u8, css: *u8, vw: i64) -> *LayoutTree {
29 var hlen: i64 = 0
30 while html[hlen]!=(0 as u8) { hlen=hlen+1 }
31 var clen: i64 = 0
32 while css[clen]!=(0 as u8) { clen=clen+1 }
33 let total: i64 = hlen + clen
34 let buf: *u8 = sys_mmap(total + 16)
35 var i: i64 = 0
36 while i < hlen { buf[i]=html[i]; i=i+1 }
37 var j: i64 = 0
38 while j < clen { buf[hlen+j]=css[j]; j=j+1 }
39
40 let boxes: *LayoutBox = (sys_mmap(NX_LAYOUT_BOX_BYTES*1024+16)) as *LayoutBox
41 let tree: *LayoutTree = (sys_mmap(64)) as *LayoutTree
42 nx_layout_tree_init(tree, boxes, 1024)
43 let stk: *LayoutFromDomStack = (sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES+8)) as *LayoutFromDomStack
44 let sidx: *i64 = (sys_mmap(8*64)) as *i64
45 nx_layout_from_dom_stack_init(stk, sidx, 64)
46 nx_layout_from_dom(buf, hlen, tree, stk)
47
48 let ext: *CssElement = (sys_mmap(NX_CSS_ELEMENT_BYTES*1024 as nx_size)) as *CssElement
49 let n_ext: i64 = rh_extract(buf, hlen, ext, 1024)
50 let boxel: *CssElement = (sys_mmap((NX_CSS_ELEMENT_BYTES*(tree.count+1)) as nx_size)) as *CssElement
51 var k: i64 = 0
52 i = 0
53 while i < tree.count {
54 let bb: *LayoutBox = ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox
55 let e: *CssElement = ((boxel as i64)+i*NX_CSS_ELEMENT_BYTES) as *CssElement
56 e.src = buf
57 var mapped: i64 = 0
58 if rh_is_elem(bb.kind)==1 { if bb.parent_idx != (0-1) { if k < n_ext {
59 let s: *CssElement = ((ext as i64)+k*NX_CSS_ELEMENT_BYTES) as *CssElement
60 e.tag_off=s.tag_off; e.tag_len=s.tag_len; e.id_off=s.id_off; e.id_len=s.id_len; e.class_off=s.class_off; e.class_len=s.class_len
61 k=k+1; mapped=1
62 } } }
63 if mapped==0 { e.tag_off=0; e.tag_len=0; e.id_off=0; e.id_len=0; e.class_off=0; e.class_len=0 }
64 i=i+1
65 }
66
67 let cur: *CssCursor = (sys_mmap(NX_CSS_CURSOR_BYTES) as nx_size) as *CssCursor
68 nx_css_cursor_init(cur, buf, total); cur.pos = hlen
69 let tok: *CssToken = (sys_mmap(NX_CSS_TOKEN_BYTES) as nx_size) as *CssToken
70 let rules: *CssRule = (sys_mmap(NX_CSS_RULE_BYTES*512 as nx_size)) as *CssRule
71 let decls: *CssDeclaration = (sys_mmap(NX_CSS_DECLARATION_BYTES*512 as nx_size)) as *CssDeclaration
72 let st: *CssParseState = (sys_mmap(128) as nx_size) as *CssParseState
73 nx_css_parse_state_init(st, cur, tok, rules, 512, decls, 512)
74 nx_css_parse(st)
75 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES*4096 as nx_size)) as *CssComputedDecl
76 let cb: *i64 = (sys_mmap(8)) as *i64
77 rh_cascade(buf, rules, st.rule_count, decls, st.decl_count, boxel, tree.count, tree, computed, 4096, cb)
78 let ncomp: i64 = cb[0]
79
80 let pbuf: *u8 = sys_mmap(256)
81 let ltable: *LayoutPropTable = (sys_mmap(NX_LAYOUT_PROP_TABLE_BYTES)) as *LayoutPropTable
82 nx_layout_prop_table_init(ltable, pbuf)
83 let resolve: *CssResolveCtx = (sys_mmap(NX_CSS_RESOLVE_CTX_BYTES)) as *CssResolveCtx
84 resolve.root_font_size_px = 16; resolve.parent_font_size_px = 16; resolve.parent_dimension_px = vw
85 let lctx: *LayoutCtx = (sys_mmap(NX_LAYOUT_CTX_BYTES)) as *LayoutCtx
86 nx_layout_ctx_init(lctx, tree, computed, ncomp, buf, vw, resolve)
87 nx_layout_block_layout(lctx, ltable, 0)
88 return tree
89}
90
91func geom_match(tree: *LayoutTree, i: i64, ex: i64, ey: i64, ew: i64, eh: i64) -> i64 {
92 let b: *LayoutBox = ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox
93 if b.x != ex { return 0 }
94 if b.y != ey { return 0 }
95 if b.w != ew { return 0 }
96 if b.h != eh { return 0 }
97 return 1
98}
99func chk(tree: *LayoutTree, i: i64, ex: i64, ey: i64, ew: i64, eh: i64, label: *u8, pass: *i64) -> i64 {
100 let m: i64 = geom_match(tree, i, ex, ey, ew, eh)
101 let b: *LayoutBox = ((tree.boxes as i64)+i*NX_LAYOUT_BOX_BYTES) as *LayoutBox
102 g_w(" " as *u8); g_w(label); g_w(": " as *u8)
103 if m==1 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 }
104 else {
105 g_w("FAIL got x=" as *u8); pn(b.x); g_w(" y=" as *u8); pn(b.y); g_w(" w=" as *u8); pn(b.w); g_w(" h=" as *u8); pn(b.h)
106 g_w(" expected x=" as *u8); pn(ex); g_w(" y=" as *u8); pn(ey); g_w(" w=" as *u8); pn(ew); g_w(" h=" as *u8); pn(eh); g_w("\n" as *u8)
107 }
108 return m
109}
110
111func main() -> i64 {
112 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0
113 g_w("=== GRID-RENDER GATE (display:grid asserted geometry, sovereign nx_cc->nxasm) ===\n" as *u8)
114
115 let html3: *u8 = "<div id=\"g\"><div id=\"a\">A</div><div id=\"b\">B</div><div id=\"c\">C</div></div>\x00" as *u8
116 let html4: *u8 = "<div id=\"g\"><div id=\"a\">A</div><div id=\"b\">B</div><div id=\"c\">C</div><div id=\"d\">D</div></div>\x00" as *u8
117
118 // G1 explicit 3-track list -> 3 equal columns of 300 at vw=900, all on row 0
119 let t1: *LayoutTree = run_layout(html3, "#g{display:grid;grid-template-columns:1fr 1fr 1fr}\x00" as *u8, 900)
120 g_w("G1 grid-template-columns:1fr 1fr 1fr (3 equal cols)\n" as *u8)
121 // ONE LINE BOX = NX_INLINE_LINE_H from nx_layout_block, never a literal. These heights were
122 // hardcoded 10; the renderer then correctly adopted real 9x15 font metrics (17, "was 10") and this
123 // gate went RED with x/w perfectly correct -- a STALE EXPECTATION, not a bug. Deriving it means a
124 // future metrics change cannot mass-fail gates that test GRID, not fonts.
125 let LH: i64 = NX_INLINE_LINE_H
126 chk(t1, 2, 0, 0, 300, LH, "#a col0 x=0 w=300\x00" as *u8, pass)
127 chk(t1, 4, 300, 0, 300, LH, "#b col1 x=300 w=300\x00" as *u8, pass)
128 chk(t1, 6, 600, 0, 300, LH, "#c col2 x=600 w=300\x00" as *u8, pass)
129
130 // G2 repeat(3, 1fr) -> identical (proves repeat() track-count parse + multi-token value capture)
131 let t2: *LayoutTree = run_layout(html3, "#g{display:grid;grid-template-columns:repeat(3, 1fr)}\x00" as *u8, 900)
132 g_w("G2 grid-template-columns:repeat(3, 1fr)\n" as *u8)
133 chk(t2, 2, 0, 0, 300, LH, "#a col0 x=0 w=300\x00" as *u8, pass)
134 chk(t2, 4, 300, 0, 300, LH, "#b col1 x=300 w=300\x00" as *u8, pass)
135 chk(t2, 6, 600, 0, 300, LH, "#c col2 x=600 w=300\x00" as *u8, pass)
136
137 // G3 WRAP: 4 children / 2 cols (vw=800 -> 400 each); c,d wrap to row 1 at y=10
138 let t3: *LayoutTree = run_layout(html4, "#g{display:grid;grid-template-columns:1fr 1fr}\x00" as *u8, 800)
139 g_w("G3 row-major WRAP (4 kids / 2 cols)\n" as *u8)
140 chk(t3, 2, 0, 0, 400, LH, "#a r0c0 x=0 y=0\x00" as *u8, pass)
141 chk(t3, 6, 0, LH, 400, LH, "#c WRAP r1c0 x=0 one line down\x00" as *u8, pass)
142 chk(t3, 8, 400, LH, 400, LH, "#d r1c1 x=400 one line down\x00" as *u8, pass)
143
144 // G4 CONTROL: no display:grid -> children STACK vertically full-width (differential vs G1)
145 let t4: *LayoutTree = run_layout(html3, "#g{color:#000}\x00" as *u8, 900)
146 g_w("G4 no-grid control (must STACK)\n" as *u8)
147 chk(t4, 2, 0, 0, 900, LH, "#a x=0 w=900\x00" as *u8, pass)
148 chk(t4, 4, 0, LH, 900, LH, "#b BELOW one line w=900\x00" as *u8, pass)
149
150 // LIAR-KILL: wrong x for G1 #b (real x=300, claim x=0) -> honest checker MUST return 0
151 g_w("LIAR-KILL (wrong geometry must be rejected)\n" as *u8)
152 let lk: i64 = geom_match(t1, 4, 0, 0, 300, LH)
153 g_w(" rejects bad x=0 for col1 #b: " as *u8)
154 if lk==0 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w("FAIL (checker is a rubber stamp)\n" as *u8) }
155
156 g_w("GRID-RENDER rows=12 pass=" as *u8); pn(pass[0])
157 if pass[0]==12 { g_w(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
158 g_w(" verdict=RED\n" as *u8); sys_exit(1); return 1
159}