diff --git a/src/ast.ts b/src/ast.ts index b42906b..0b8bf41 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -147,6 +147,7 @@ export type Definition = { column?: number start?: number annotation?: Annotation + module?: string } export type Rebind = { @@ -175,6 +176,7 @@ export type TypeDefinition = { line?: number column?: number start?: number + module?: string } export type Annotation = { @@ -195,6 +197,7 @@ export type ClassDefinition = { line?: number column?: number start?: number + module?: string } export type InstanceDeclaration = { @@ -204,6 +207,7 @@ export type InstanceDeclaration = { line?: number column?: number start?: number + module?: string } export type AST = diff --git a/src/cg/03-ui-components.cg b/src/cg/03-ui-components.cg index ac64bef..9e46167 100644 --- a/src/cg/03-ui-components.cg +++ b/src/cg/03-ui-components.cg @@ -390,60 +390,62 @@ LayoutChild = Fixed Int (Int \ Int \ UI) | Flex Int (Int \ Int \ UI); Alignment = Start | Center | End; Direction = Col | Row; -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; +@layout - # 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; +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; - 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 - result = fold (acc child \ - allocated = (child - | Fixed s view \ { s = s, view = view } - | Flex n view \ { s = remaining * n / info.totalFlex, view = view }); + remaining = mainSize - info.fixedMain; - childW = dir | Col \ crossSize | Row \ allocated.s; - childH = dir | Col \ allocated.s | Row \ crossSize; - posX = dir | Col \ 0 | Row \ acc.pos; - posY = dir | Col \ acc.pos | Row \ 0; + # Pass 2 + result = fold (acc child \ + allocated = (child + | Fixed s view \ { s = s, view = view } + | Flex n view \ { s = remaining * n / info.totalFlex, view = view }); - rendered = ui.positioned { - x = posX, y = posY, - child = allocated.view childW childH - }; + childW = dir | Col \ crossSize | Row \ allocated.s; + childH = dir | Col \ allocated.s | Row \ crossSize; + posX = dir | Col \ 0 | Row \ acc.pos; + posY = dir | Col \ acc.pos | Row \ 0; - acc.{ pos = acc.pos + allocated.s, children = [...acc.children, rendered] } - ) { pos = 0, children = [] } children; + rendered = ui.positioned { + 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, - row = layoutDir Row, + { ui = ui.stack { children = result.children }, w = constraints.w, h = constraints.h }; - align = hAlign vAlign w h child \ - x = hAlign - | Start \ 0 - | Center \ (w - child.w) / 2 - | End \ w - child.w; - y = vAlign - | 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 }, -}; +col = layoutDir Col; +row = layoutDir Row; + +align = hAlign vAlign w h child \ + x = hAlign + | Start \ 0 + | Center \ (w - child.w) / 2 + | End \ w - child.w; + y = vAlign + | 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 \ { 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" }), 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" }), @@ -453,13 +455,13 @@ testApp = name \ testApp2 = _ \ { view = ctx \ - layout.col { w = ctx.w, h = ctx.h } [ - Fixed 40 (w h \ (layout.align Center Center w h (sizedText "Header")).ui), - Flex 1 (w h \ (layout.row { w = w, h = h } [ + col { w = ctx.w, h = ctx.h } [ + Fixed 40 (w h \ (align Center Center w h (sizedText "Header")).ui), + Flex 1 (w h \ (row { w = w, h = h } [ 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" }), ]).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) }; diff --git a/src/parser.ts b/src/parser.ts index 5b258b8..b804b3f 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -150,6 +150,8 @@ export class Parser { } } + private currentModule: string | undefined; + parse(): { definitions: Definition[], typeDefinitions: TypeDefinition[], classDefinitions: ClassDefinition[], instanceDeclarations: InstanceDeclaration[] } { const definitions: Definition[] = []; const typeDefinitions: TypeDefinition[] = []; @@ -157,22 +159,41 @@ export class Parser { const instanceDeclarations: InstanceDeclaration[] = []; 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') { let offset = 1; while (this.peek(offset).kind === 'ident') offset++; const after = this.peek(offset); 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') { - instanceDeclarations.push(this.parseInstanceDeclaration()); + const id = this.parseInstanceDeclaration(); + if (this.currentModule) id.module = this.currentModule; + instanceDeclarations.push(id); } else { - typeDefinitions.push(this.parseTypeDefinition()); + const td = this.parseTypeDefinition(); + if (this.currentModule) td.module = this.currentModule; + typeDefinitions.push(td); } continue; } - definitions.push(this.parseDefinition()); + const def = this.parseDefinition(); + if (this.currentModule) def.module = this.currentModule; + definitions.push(def); } return { definitions, typeDefinitions, classDefinitions, instanceDeclarations };