From 6656b90717f2a8e5249f57e8c71e5fcb1c60f20c Mon Sep 17 00:00:00 2001 From: Dustin Swan Date: Wed, 1 Apr 2026 16:00:11 -0600 Subject: [PATCH] Fixing multi argument Constructors. Adding a layout system! Flex and fixed within a column --- src/cg/03-ui-components.cg | 46 ++++++++++++++++++++++++++++++++++++++ src/compiler.ts | 25 ++++++++++++++++----- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/cg/03-ui-components.cg b/src/cg/03-ui-components.cg index d91ce72..e35af10 100644 --- a/src/cg/03-ui-components.cg +++ b/src/cg/03-ui-components.cg @@ -379,3 +379,49 @@ measureText = config \ width = strLen * charW * c.scale + max 0 (strLen - 1) * gap, height = 12 * c.scale }; + +# new CG layout +LayoutChild = Fixed Int (Int\ Int \ UI) | Flex Int (Int \ Int \ UI); + +layout = constraints children \ + # Pass 1: sum fixed heights, total flex weight + info = fold (acc child \ child + | Fixed h _ \ acc.{ fixedH = acc.fixedH + h } + | Flex n _ \ acc.{ totalFlex = acc.totalFlex + n } + ) { fixedH = 0, totalFlex = 0 } children; + + remainingH = constraints.h - info.fixedH; + + # Pass 2 + fold (acc child \ + allocated = (child + | Fixed h view \ { h = h, view = view } + | Flex n view \ { h = remainingH * n / info.totalFlex, view = view }); + + rendered = ui.positioned { + x = 0, + y = acc.y, + child = allocated.view constraints.w allocated.h + }; + + acc.{ y = acc.y + allocated.h, children = [...acc.children, rendered] } + ) { y = 0, children = [] } children + ~ (r \ r.children) + ~ (c \ ui.stack { children = c }); + +testApp = name \ + { view = ctx \ + # ui.rect { w = 10, h = 10 }, + layout { w = ctx.w, h = ctx.h } [ + Fixed 40 (w h \ box { w = w, h = h, color = "red", child = text "Header" }), + Flex 1 (w h \ box { w = w, h = h, color = "#1a1a2e", child = text "Main content" }), + Fixed 30 (w h \ box { w = w, h = h, color = "blue", child = text "Footer" }), + ] + }; + +testApp2 = ctx \ + layout { w = ctx.w, h = ctx.h } [ + Fixed 40 (w h \ box { w = w, h = h, color = "red", child = text "Header" }), + Flex 1 (w h \ box { w = w, h = h, color = "#1a1a2e", child = text "Main content" }), + Fixed 30 (w h \ box { w = w, h = h, color = "blue", child = text "Footer" }), + ]; diff --git a/src/compiler.ts b/src/compiler.ts index 2c3918f..66bbed6 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -43,13 +43,28 @@ export function compile(ast: AST, ctx: CompileCtx = defaultCtx): string { } case 'apply': - // Constructor - if (ast.func.kind === 'constructor') { - const ctorName = ast.func.name; - const arg = compile(ast.args[0], ctx); - return `({ _tag: "${ctorName}", _0: ${arg} })`; + // Collect constructor args from nested applie + let node: AST = ast; + const ctorArgs: AST[] = []; + while (node.kind === 'apply' && node.func.kind !== 'constructor') { + // Check if inner func is a constructor chain + if (node.func.kind === 'apply') { + ctorArgs.unshift(node.args[0]); + node = node.func; + } else { + break; + } } + // Constructor + if (node.kind === 'apply' && node.func.kind === 'constructor') { + ctorArgs.unshift(node.args[0]); + const ctorName = node.func.name; + const compiledArgs = ctorArgs.map((a, i) => `_${i}: ${compile(a, ctx)}`).join(', '); + return `({ _tag: "${ctorName}", ${compiledArgs} })`; + } + + // Function application const args = ast.args.map(a => compile(a, ctx)).join(')('); return `${compile(ast.func, ctx)}(${args})`;