Module syntax. doesn't really do anything yet. well, it groups definitions

This commit is contained in:
Dustin Swan 2026-04-01 21:39:08 -06:00
parent d3248be4d9
commit ed103ed2cb
No known key found for this signature in database
GPG key ID: 30D46587E2100467
3 changed files with 77 additions and 50 deletions

View file

@ -147,6 +147,7 @@ export type Definition = {
column?: number column?: number
start?: number start?: number
annotation?: Annotation annotation?: Annotation
module?: string
} }
export type Rebind = { export type Rebind = {
@ -175,6 +176,7 @@ export type TypeDefinition = {
line?: number line?: number
column?: number column?: number
start?: number start?: number
module?: string
} }
export type Annotation = { export type Annotation = {
@ -195,6 +197,7 @@ export type ClassDefinition = {
line?: number line?: number
column?: number column?: number
start?: number start?: number
module?: string
} }
export type InstanceDeclaration = { export type InstanceDeclaration = {
@ -204,6 +207,7 @@ export type InstanceDeclaration = {
line?: number line?: number
column?: number column?: number
start?: number start?: number
module?: string
} }
export type AST = export type AST =

View file

@ -390,60 +390,62 @@ 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;
layout = { @layout
layoutDir
# : Direction \ { w : Int, h : Int } \ List LayoutChild \ { ui : UI, w : Int, h : Int }
= dir constraints children \
mainSize = dir | Col \ constraints.h | Row \ constraints.w;
crossSize = dir | Col \ constraints.w | Row \ constraints.h;
# Pass 1: sum fixed heights, total flex weight layoutDir
info = fold (acc child \ child : Direction \ { w : Int, h : Int } \ List LayoutChild \ { ui : UI, w : Int, h : Int }
| Fixed s _ \ acc.{ fixedMain = acc.fixedMain + s } = dir constraints children \
| Flex n _ \ acc.{ totalFlex = acc.totalFlex + n } mainSize = dir | Col \ constraints.h | Row \ constraints.w;
) { fixedMain = 0, totalFlex = 0 } children; crossSize = dir | Col \ constraints.w | Row \ constraints.h;
remaining = mainSize - info.fixedMain; # Pass 1: sum fixed heights, total flex weight
info = fold (acc child \ child
| Fixed s _ \ acc.{ fixedMain = acc.fixedMain + s }
| Flex n _ \ acc.{ totalFlex = acc.totalFlex + n }
) { fixedMain = 0, totalFlex = 0 } children;
# Pass 2 remaining = mainSize - info.fixedMain;
result = fold (acc child \
allocated = (child
| Fixed s view \ { s = s, view = view }
| Flex n view \ { s = remaining * n / info.totalFlex, view = view });
childW = dir | Col \ crossSize | Row \ allocated.s; # Pass 2
childH = dir | Col \ allocated.s | Row \ crossSize; result = fold (acc child \
posX = dir | Col \ 0 | Row \ acc.pos; allocated = (child
posY = dir | Col \ acc.pos | Row \ 0; | Fixed s view \ { s = s, view = view }
| Flex n view \ { s = remaining * n / info.totalFlex, view = view });
rendered = ui.positioned { childW = dir | Col \ crossSize | Row \ allocated.s;
x = posX, y = posY, childH = dir | Col \ allocated.s | Row \ crossSize;
child = allocated.view childW childH posX = dir | Col \ 0 | Row \ acc.pos;
}; posY = dir | Col \ acc.pos | Row \ 0;
acc.{ pos = acc.pos + allocated.s, children = [...acc.children, rendered] } rendered = ui.positioned {
) { pos = 0, children = [] } children; x = posX, y = posY,
child = allocated.view childW childH
};
{ ui = ui.stack { children = result.children }, w = constraints.w, h = constraints.h }, acc.{ pos = acc.pos + allocated.s, children = [...acc.children, rendered] }
) { pos = 0, children = [] } children;
col = layoutDir Col, { ui = ui.stack { children = result.children }, w = constraints.w, h = constraints.h };
row = layoutDir Row,
align = hAlign vAlign w h child \ col = layoutDir Col;
x = hAlign row = layoutDir Row;
| Start \ 0
| Center \ (w - child.w) / 2 align = hAlign vAlign w h child \
| End \ w - child.w; x = hAlign
y = vAlign | Start \ 0
| Start \ 0 | Center \ (w - child.w) / 2
| Center \ (h - child.h) / 2 | End \ w - child.w;
| End \ h - child.h; y = vAlign
{ ui = ui.positioned { x = x, y = y, child = child.ui }, w = w, h = h }, | Start \ 0
}; | Center \ (h - child.h) / 2
| End \ h - child.h;
{ ui = ui.positioned { x = x, y = y, child = child.ui }, w = w, h = h };
@
testApp = name \ testApp = name \
{ view = ctx \ { view = ctx \
layout.col { w = ctx.w, h = ctx.h } [ 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" }),
@ -453,13 +455,13 @@ testApp = name \
testApp2 = _ \ testApp2 = _ \
{ view = ctx \ { view = ctx \
layout.col { w = ctx.w, h = ctx.h } [ col { w = ctx.w, h = ctx.h } [
Fixed 40 (w h \ (layout.align Center Center w h (sizedText "Header")).ui), Fixed 40 (w h \ (align Center Center w h (sizedText "Header")).ui),
Flex 1 (w h \ (layout.row { w = w, h = h } [ Flex 1 (w h \ (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 \ (layout.align Center Center w h (sizedText "Footer")).ui), Fixed 30 (w h \ (align Center Center w h (sizedText "Footer")).ui),
] ]
~ (e \ e.ui) ~ (e \ e.ui)
}; };

View file

@ -150,6 +150,8 @@ export class Parser {
} }
} }
private currentModule: string | undefined;
parse(): { definitions: Definition[], typeDefinitions: TypeDefinition[], classDefinitions: ClassDefinition[], instanceDeclarations: InstanceDeclaration[] } { parse(): { definitions: Definition[], typeDefinitions: TypeDefinition[], classDefinitions: ClassDefinition[], instanceDeclarations: InstanceDeclaration[] } {
const definitions: Definition[] = []; const definitions: Definition[] = [];
const typeDefinitions: TypeDefinition[] = []; const typeDefinitions: TypeDefinition[] = [];
@ -157,22 +159,41 @@ export class Parser {
const instanceDeclarations: InstanceDeclaration[] = []; const instanceDeclarations: InstanceDeclaration[] = [];
while (this.current().kind !== 'eof') { while (this.current().kind !== 'eof') {
// Module tags
if (this.current().kind === 'at') {
this.advance();
if (this.current().kind === 'ident' && this.peek().kind !== 'equals' && this.peek().kind !== 'colon') {
this.currentModule = (this.advance() as { value: string }).value;
} else {
this.currentModule = undefined;
}
continue;
}
if (this.current().kind === 'type-ident') { if (this.current().kind === 'type-ident') {
let offset = 1; let offset = 1;
while (this.peek(offset).kind === 'ident') offset++; while (this.peek(offset).kind === 'ident') offset++;
const after = this.peek(offset); const after = this.peek(offset);
if (after.kind === 'open-brace') { if (after.kind === 'open-brace') {
classDefinitions.push(this.parseClassDefinition()); const cd = this.parseClassDefinition();
if (this.currentModule) cd.module = this.currentModule;
classDefinitions.push(cd);
} else if (after.kind === 'colon') { } else if (after.kind === 'colon') {
instanceDeclarations.push(this.parseInstanceDeclaration()); const id = this.parseInstanceDeclaration();
if (this.currentModule) id.module = this.currentModule;
instanceDeclarations.push(id);
} else { } else {
typeDefinitions.push(this.parseTypeDefinition()); const td = this.parseTypeDefinition();
if (this.currentModule) td.module = this.currentModule;
typeDefinitions.push(td);
} }
continue; continue;
} }
definitions.push(this.parseDefinition()); const def = this.parseDefinition();
if (this.currentModule) def.module = this.currentModule;
definitions.push(def);
} }
return { definitions, typeDefinitions, classDefinitions, instanceDeclarations }; return { definitions, typeDefinitions, classDefinitions, instanceDeclarations };