Records now hoist their fields if they reference other fields so we can have circular
This commit is contained in:
parent
a76f4cc332
commit
d3248be4d9
2 changed files with 75 additions and 48 deletions
|
|
@ -390,8 +390,9 @@ LayoutChild = Fixed Int (Int \ Int \ UI) | Flex Int (Int \ Int \ UI);
|
||||||
Alignment = Start | Center | End;
|
Alignment = Start | Center | End;
|
||||||
Direction = Col | Row;
|
Direction = Col | Row;
|
||||||
|
|
||||||
layoutDir
|
layout = {
|
||||||
: Direction \ { w : Int, h : Int } \ List LayoutChild \ { ui : UI, w : Int, h : Int }
|
layoutDir
|
||||||
|
# : Direction \ { w : Int, h : Int } \ List LayoutChild \ { ui : UI, w : Int, h : Int }
|
||||||
= dir constraints children \
|
= dir constraints children \
|
||||||
mainSize = dir | Col \ constraints.h | Row \ constraints.w;
|
mainSize = dir | Col \ constraints.h | Row \ constraints.w;
|
||||||
crossSize = dir | Col \ constraints.w | Row \ constraints.h;
|
crossSize = dir | Col \ constraints.w | Row \ constraints.h;
|
||||||
|
|
@ -423,12 +424,12 @@ layoutDir
|
||||||
acc.{ pos = acc.pos + allocated.s, children = [...acc.children, rendered] }
|
acc.{ pos = acc.pos + allocated.s, children = [...acc.children, rendered] }
|
||||||
) { pos = 0, children = [] } children;
|
) { pos = 0, children = [] } children;
|
||||||
|
|
||||||
{ ui = ui.stack { children = result.children }, w = constraints.w, h = constraints.h };
|
{ ui = ui.stack { children = result.children }, w = constraints.w, h = constraints.h },
|
||||||
|
|
||||||
col = layoutDir Col;
|
col = layoutDir Col,
|
||||||
row = layoutDir Row;
|
row = layoutDir Row,
|
||||||
|
|
||||||
align = hAlign vAlign w h child \
|
align = hAlign vAlign w h child \
|
||||||
x = hAlign
|
x = hAlign
|
||||||
| Start \ 0
|
| Start \ 0
|
||||||
| Center \ (w - child.w) / 2
|
| Center \ (w - child.w) / 2
|
||||||
|
|
@ -437,11 +438,12 @@ align = hAlign vAlign w h child \
|
||||||
| Start \ 0
|
| Start \ 0
|
||||||
| Center \ (h - child.h) / 2
|
| Center \ (h - child.h) / 2
|
||||||
| End \ h - child.h;
|
| End \ h - child.h;
|
||||||
{ ui = ui.positioned { x = x, y = y, child = child.ui }, w = w, h = h };
|
{ ui = ui.positioned { x = x, y = y, child = child.ui }, w = w, h = h },
|
||||||
|
};
|
||||||
|
|
||||||
testApp = name \
|
testApp = name \
|
||||||
{ view = ctx \
|
{ view = ctx \
|
||||||
col { w = ctx.w, h = ctx.h } [
|
layout.col { w = ctx.w, h = ctx.h } [
|
||||||
Fixed 40 (w h \ box { w = w, h = h, color = "red", child = text "Header" }),
|
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" }),
|
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" }),
|
Fixed 30 (w h \ box { w = w, h = h, color = "blue", child = text "Footer" }),
|
||||||
|
|
@ -451,13 +453,13 @@ testApp = name \
|
||||||
|
|
||||||
testApp2 = _ \
|
testApp2 = _ \
|
||||||
{ view = ctx \
|
{ view = ctx \
|
||||||
col { w = ctx.w, h = ctx.h } [
|
layout.col { w = ctx.w, h = ctx.h } [
|
||||||
Fixed 40 (w h \ (align Center Center w h (sizedText "Header")).ui),
|
Fixed 40 (w h \ (layout.align Center Center w h (sizedText "Header")).ui),
|
||||||
Flex 1 (w h \ (row { w = w, h = h } [
|
Flex 1 (w h \ (layout.row { w = w, h = h } [
|
||||||
Fixed 200 (w h \ box { w = w, h = h, color = "#2a2a3e", child = text "Sidebar" }),
|
Fixed 200 (w h \ box { w = w, h = h, color = "#2a2a3e", child = text "Sidebar" }),
|
||||||
Flex 1 (w h \ box { w = w, h = h, color = "#1a1a2e", child = text "Main" }),
|
Flex 1 (w h \ box { w = w, h = h, color = "#1a1a2e", child = text "Main" }),
|
||||||
]).ui),
|
]).ui),
|
||||||
Fixed 30 (w h \ (align Center Center w h (sizedText "Footer")).ui),
|
Fixed 30 (w h \ (layout.align Center Center w h (sizedText "Footer")).ui),
|
||||||
]
|
]
|
||||||
~ (e \ e.ui)
|
~ (e \ e.ui)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,31 @@ export function compile(ast: AST, ctx: CompileCtx = defaultCtx): string {
|
||||||
return `${compile(ast.func, ctx)}(${args})`;
|
return `${compile(ast.func, ctx)}(${args})`;
|
||||||
|
|
||||||
case 'record': {
|
case 'record': {
|
||||||
|
const fieldNames = new Set(
|
||||||
|
ast.entries.filter(e => e.kind === 'field').map(e => e.key)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if any field references another
|
||||||
|
const needsHoist = ast.entries.some(entry =>
|
||||||
|
entry.kind === 'field' &&
|
||||||
|
[...freeVars(entry.value)].some(v =>
|
||||||
|
fieldNames.has(v) && v !== entry.key && !ctx.bound.has(v) && !ctx.topLevel.has(v)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (needsHoist) {
|
||||||
|
const bindings: string[] = [];
|
||||||
|
const names: string[] = [];
|
||||||
|
for (const entry of ast.entries) {
|
||||||
|
if (entry.kind === 'spread') continue;
|
||||||
|
const safe = sanitizeName(entry.key);
|
||||||
|
bindings.push(`const ${safe} = ${compile(entry.value, { ...ctx, bound: new Set([...ctx.bound, ...fieldNames]) })};`);
|
||||||
|
names.push(`${JSON.stringify(entry.key)}: ${safe}`);
|
||||||
|
}
|
||||||
|
return `(() => { ${bindings.join(' ')} return {${names.join(', ')}}; })()`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple record, no hoisting
|
||||||
const parts = ast.entries.map(entry =>
|
const parts = ast.entries.map(entry =>
|
||||||
entry.kind === 'spread'
|
entry.kind === 'spread'
|
||||||
? `...${compile(entry.expr, ctx)}`
|
? `...${compile(entry.expr, ctx)}`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue