@chanmeng666/archlang 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lexer.ts","../src/expr.ts","../src/theme.ts","../src/geometry.ts","../src/hatches.ts","../src/elements/wall.ts","../src/elements/room.ts","../src/elements/door.ts","../src/elements/window.ts","../src/elements/furniture.ts","../src/elements/dim.ts","../src/elements/column.ts","../src/elements/index.ts","../src/parser.ts","../src/ir.ts","../src/geometry/union.ts","../src/scene-build.ts","../src/scene.ts","../src/backends/svg.ts","../src/diagnostics.ts","../src/export/dxf.ts","../src/export/pdf.ts","../src/index.ts"],"sourcesContent":["/** Hand-written lexer for ArchLang. Zero dependencies; tracks line/col. */\r\n\r\nexport type TokenType =\r\n | \"ident\"\r\n | \"number\"\r\n | \"string\"\r\n | \"dimension\" // e.g. 4000x3000\r\n | \"lparen\"\r\n | \"rparen\"\r\n | \"lcurly\"\r\n | \"rcurly\"\r\n | \"comma\"\r\n | \"equals\"\r\n | \"colon\"\r\n | \"arrow\" // ->\r\n | \"plus\" // +\r\n | \"minus\" // - (binary or unary; arrow -> is separate)\r\n | \"star\" // *\r\n | \"slash\" // /\r\n | \"percent\" // %\r\n | \"eof\";\r\n\r\nexport interface Token {\r\n type: TokenType;\r\n value: string;\r\n /** For \"number\": the parsed value. For \"dimension\": w. */\r\n num?: number;\r\n /** For \"dimension\": h. */\r\n num2?: number;\r\n line: number;\r\n col: number;\r\n /** Byte offset of the token's first character into the source. */\r\n start: number;\r\n /** Byte offset just past the token's last character. */\r\n end: number;\r\n}\r\n\r\nexport interface LexResult {\r\n tokens: Token[];\r\n errors: { message: string; span: { start: number; end: number } }[];\r\n}\r\n\r\nconst isDigit = (c: string) => c >= \"0\" && c <= \"9\";\r\nconst isIdentStart = (c: string) =>\r\n (c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\") || c === \"_\";\r\nconst isIdentPart = (c: string) => isIdentStart(c) || isDigit(c);\r\n\r\nexport function lex(src: string): LexResult {\r\n const tokens: Token[] = [];\r\n const errors: { message: string; span: { start: number; end: number } }[] = [];\r\n let i = 0;\r\n let line = 1;\r\n let col = 1;\r\n\r\n const peek = (o = 0) => src[i + o] ?? \"\";\r\n const advance = () => {\r\n const c = src[i++];\r\n if (c === \"\\n\") {\r\n line++;\r\n col = 1;\r\n } else {\r\n col++;\r\n }\r\n return c;\r\n };\r\n const push = (\r\n type: TokenType,\r\n value: string,\r\n startLine: number,\r\n startCol: number,\r\n startIdx: number,\r\n extra?: Partial<Token>,\r\n ) => tokens.push({ type, value, line: startLine, col: startCol, ...extra, start: startIdx, end: i });\r\n\r\n while (i < src.length) {\r\n const c = peek();\r\n const startLine = line;\r\n const startCol = col;\r\n const startIdx = i;\r\n\r\n // Whitespace\r\n if (c === \" \" || c === \"\\t\" || c === \"\\r\" || c === \"\\n\") {\r\n advance();\r\n continue;\r\n }\r\n\r\n // Comment to end of line\r\n if (c === \"#\") {\r\n while (i < src.length && peek() !== \"\\n\") advance();\r\n continue;\r\n }\r\n\r\n // String literal with \\\" and \\\\ escapes\r\n if (c === '\"') {\r\n advance();\r\n let value = \"\";\r\n let terminated = false;\r\n while (i < src.length) {\r\n const ch = peek();\r\n if (ch === \"\\\\\") {\r\n advance();\r\n const esc = advance();\r\n value += esc === \"n\" ? \"\\n\" : esc;\r\n continue;\r\n }\r\n if (ch === '\"') {\r\n advance();\r\n terminated = true;\r\n break;\r\n }\r\n if (ch === \"\\n\") break; // strings don't span lines\r\n value += advance();\r\n }\r\n if (!terminated) {\r\n errors.push({ message: \"Unterminated string literal\", span: { start: startIdx, end: i } });\r\n }\r\n push(\"string\", value, startLine, startCol, startIdx);\r\n continue;\r\n }\r\n\r\n // Punctuation & operators\r\n if (c === \"(\") { advance(); push(\"lparen\", \"(\", startLine, startCol, startIdx); continue; }\r\n if (c === \")\") { advance(); push(\"rparen\", \")\", startLine, startCol, startIdx); continue; }\r\n if (c === \"{\") { advance(); push(\"lcurly\", \"{\", startLine, startCol, startIdx); continue; }\r\n if (c === \"}\") { advance(); push(\"rcurly\", \"}\", startLine, startCol, startIdx); continue; }\r\n if (c === \",\") { advance(); push(\"comma\", \",\", startLine, startCol, startIdx); continue; }\r\n if (c === \"=\") { advance(); push(\"equals\", \"=\", startLine, startCol, startIdx); continue; }\r\n if (c === \":\") { advance(); push(\"colon\", \":\", startLine, startCol, startIdx); continue; }\r\n if (c === \"-\" && peek(1) === \">\") { advance(); advance(); push(\"arrow\", \"->\", startLine, startCol, startIdx); continue; }\r\n\r\n // Arithmetic operators (unary minus is handled by the expression parser).\r\n if (c === \"+\") { advance(); push(\"plus\", \"+\", startLine, startCol, startIdx); continue; }\r\n if (c === \"-\") { advance(); push(\"minus\", \"-\", startLine, startCol, startIdx); continue; }\r\n if (c === \"*\") { advance(); push(\"star\", \"*\", startLine, startCol, startIdx); continue; }\r\n if (c === \"/\") { advance(); push(\"slash\", \"/\", startLine, startCol, startIdx); continue; }\r\n if (c === \"%\") { advance(); push(\"percent\", \"%\", startLine, startCol, startIdx); continue; }\r\n\r\n // Number (optionally part of a literal dimension WxH). Numbers are\r\n // non-negative; negation is a unary operator in expressions.\r\n if (isDigit(c) || (c === \".\" && isDigit(peek(1)))) {\r\n let raw = \"\";\r\n while (isDigit(peek())) raw += advance();\r\n if (peek() === \".\") {\r\n raw += advance();\r\n while (isDigit(peek())) raw += advance();\r\n }\r\n const first = parseFloat(raw);\r\n // Dimension: <num>x<num>\r\n if (peek() === \"x\" && (isDigit(peek(1)) || (peek(1) === \".\" && isDigit(peek(2))))) {\r\n advance(); // consume 'x'\r\n let raw2 = \"\";\r\n while (isDigit(peek())) raw2 += advance();\r\n if (peek() === \".\") {\r\n raw2 += advance();\r\n while (isDigit(peek())) raw2 += advance();\r\n }\r\n const second = parseFloat(raw2);\r\n push(\"dimension\", `${raw}x${raw2}`, startLine, startCol, startIdx, { num: first, num2: second });\r\n continue;\r\n }\r\n push(\"number\", raw, startLine, startCol, startIdx, { num: first });\r\n continue;\r\n }\r\n\r\n // Identifier / keyword\r\n if (isIdentStart(c)) {\r\n let value = \"\";\r\n while (i < src.length && isIdentPart(peek())) value += advance();\r\n push(\"ident\", value, startLine, startCol, startIdx);\r\n continue;\r\n }\r\n\r\n // Unknown character\r\n errors.push({ message: `Unexpected character ${JSON.stringify(c)}`, span: { start: startIdx, end: startIdx + 1 } });\r\n advance();\r\n }\r\n\r\n push(\"eof\", \"\", line, col, i);\r\n return { tokens, errors };\r\n}\r\n","/**\r\n * Arithmetic expressions: a small Pratt parser + a pure evaluator.\r\n *\r\n * Expressions appear anywhere a number does (coordinates, sizes, widths,\r\n * thickness, offsets). They are parsed into an {@link Expr} AST and evaluated\r\n * during `resolve` against an {@link Env} of `let`/parameter bindings.\r\n */\r\n\r\nimport type { Token, TokenType } from \"./lexer.js\";\r\nimport type { Diagnostic, Span } from \"./diagnostics.js\";\r\n\r\nexport type Expr =\r\n | { t: \"num\"; value: number }\r\n | { t: \"ref\"; name: string; span?: Span }\r\n | { t: \"unary\"; op: \"-\" | \"+\"; e: Expr }\r\n | { t: \"bin\"; op: \"+\" | \"-\" | \"*\" | \"/\" | \"%\"; l: Expr; r: Expr };\r\n\r\nexport type Env = Map<string, number>;\r\n\r\n/** Minimal token-stream the expression parser needs (satisfied by ParseCtx). */\r\nexport interface ExprTokens {\r\n peek(o?: number): Token;\r\n next(): Token;\r\n fail(msg: string, t?: Token): never;\r\n}\r\n\r\nconst BIN_PREC: Partial<Record<TokenType, number>> = {\r\n plus: 1,\r\n minus: 1,\r\n star: 2,\r\n slash: 2,\r\n percent: 2,\r\n};\r\nconst BIN_OP: Partial<Record<TokenType, \"+\" | \"-\" | \"*\" | \"/\" | \"%\">> = {\r\n plus: \"+\",\r\n minus: \"-\",\r\n star: \"*\",\r\n slash: \"/\",\r\n percent: \"%\",\r\n};\r\n\r\n/** Parse an expression (Pratt / precedence-climbing). */\r\nexport function parseExpr(ts: ExprTokens): Expr {\r\n return parseBin(ts, 1);\r\n}\r\n\r\nfunction parseBin(ts: ExprTokens, minPrec: number): Expr {\r\n let left = parseUnary(ts);\r\n for (;;) {\r\n const t = ts.peek();\r\n const prec = BIN_PREC[t.type];\r\n if (prec === undefined || prec < minPrec) break;\r\n ts.next();\r\n const right = parseBin(ts, prec + 1);\r\n left = { t: \"bin\", op: BIN_OP[t.type]!, l: left, r: right };\r\n }\r\n return left;\r\n}\r\n\r\nfunction parseUnary(ts: ExprTokens): Expr {\r\n const t = ts.peek();\r\n if (t.type === \"minus\" || t.type === \"plus\") {\r\n ts.next();\r\n return { t: \"unary\", op: t.type === \"minus\" ? \"-\" : \"+\", e: parseUnary(ts) };\r\n }\r\n return parseAtom(ts);\r\n}\r\n\r\nfunction parseAtom(ts: ExprTokens): Expr {\r\n const t = ts.peek();\r\n if (t.type === \"number\") {\r\n ts.next();\r\n return { t: \"num\", value: t.num! };\r\n }\r\n if (t.type === \"ident\") {\r\n ts.next();\r\n return { t: \"ref\", name: t.value, span: { start: t.start, end: t.end } };\r\n }\r\n if (t.type === \"lparen\") {\r\n ts.next();\r\n const e = parseExpr(ts);\r\n const close = ts.peek();\r\n if (close.type !== \"rparen\") ts.fail(`Expected \")\" but found ${describe(close)}`);\r\n ts.next();\r\n return e;\r\n }\r\n return ts.fail(`Expected a number, name, or \"(\" but found ${describe(t)}`);\r\n}\r\n\r\n/** Evaluate an expression. Errors (unknown ref, division by zero) emit a\r\n * diagnostic and yield 0 so resolution can continue and report everything. */\r\nexport function evalExpr(e: Expr, env: Env, onError: (d: Diagnostic) => void): number {\r\n switch (e.t) {\r\n case \"num\":\r\n return e.value;\r\n case \"ref\": {\r\n const v = env.get(e.name);\r\n if (v === undefined) {\r\n const hint = closest(e.name, [...env.keys()]);\r\n onError({\r\n severity: \"error\",\r\n message: `Unknown name \"${e.name}\"`,\r\n code: \"E_UNKNOWN_REF\",\r\n span: e.span,\r\n hints: hint ? [`did you mean \"${hint}\"?`] : undefined,\r\n });\r\n return 0;\r\n }\r\n return v;\r\n }\r\n case \"unary\": {\r\n const v = evalExpr(e.e, env, onError);\r\n return e.op === \"-\" ? -v : v;\r\n }\r\n case \"bin\": {\r\n const l = evalExpr(e.l, env, onError);\r\n const r = evalExpr(e.r, env, onError);\r\n switch (e.op) {\r\n case \"+\": return l + r;\r\n case \"-\": return l - r;\r\n case \"*\": return l * r;\r\n case \"/\":\r\n case \"%\":\r\n if (r === 0) {\r\n onError({ severity: \"error\", message: `${e.op === \"/\" ? \"Division\" : \"Modulo\"} by zero`, code: \"E_DIV_ZERO\" });\r\n return 0;\r\n }\r\n return e.op === \"/\" ? l / r : l % r;\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction describe(t: Token): string {\r\n if (t.type === \"eof\") return \"end of input\";\r\n if (t.type === \"string\") return `string ${JSON.stringify(t.value)}`;\r\n return `\"${t.value}\"`;\r\n}\r\n\r\n/** Nearest candidate within a small edit distance, for \"did you mean\" hints. */\r\nexport function closest(name: string, candidates: string[]): string | null {\r\n let best: string | null = null;\r\n let bestDist = Infinity;\r\n for (const c of candidates) {\r\n const d = levenshtein(name, c);\r\n if (d < bestDist) {\r\n bestDist = d;\r\n best = c;\r\n }\r\n }\r\n // Only suggest when reasonably close (≤ 2 edits, or ≤ a third of the length).\r\n const limit = Math.max(2, Math.floor(name.length / 3));\r\n return best !== null && bestDist <= limit ? best : null;\r\n}\r\n\r\nfunction levenshtein(a: string, b: string): number {\r\n const m = a.length;\r\n const n = b.length;\r\n const dp = Array.from({ length: m + 1 }, (_, i) => i);\r\n for (let j = 1; j <= n; j++) {\r\n let prev = dp[0];\r\n dp[0] = j;\r\n for (let i = 1; i <= m; i++) {\r\n const tmp = dp[i];\r\n dp[i] = Math.min(\r\n dp[i] + 1,\r\n dp[i - 1] + 1,\r\n prev + (a[i - 1] === b[j - 1] ? 0 : 1),\r\n );\r\n prev = tmp;\r\n }\r\n }\r\n return dp[m];\r\n}\r\n","/**\r\n * Theme: colours, line-weight, and font for the rendered drawing.\r\n *\r\n * Resolution order (later wins): {@link DEFAULT_THEME} → the plan's `theme { … }`\r\n * directive → `CompileOptions.theme`. Merging is a shallow override, so any\r\n * subset of keys may be supplied at either layer.\r\n */\r\n\r\nexport interface Theme {\r\n bg: string;\r\n pocheBase: string;\r\n pocheHatch: string;\r\n wallStroke: string;\r\n roomFill: string;\r\n roomLabel: string;\r\n areaLabel: string;\r\n furnitureStroke: string;\r\n furnitureFill: string;\r\n furnitureLabel: string;\r\n opening: string;\r\n doorLeaf: string;\r\n windowPane: string;\r\n dim: string;\r\n annotation: string;\r\n annotationMuted: string;\r\n column: string;\r\n /** Multiplier on all stroke widths (1 = default). */\r\n lineWeight: number;\r\n /** SVG `font-family`. */\r\n font: string;\r\n}\r\n\r\nexport const DEFAULT_THEME: Theme = {\r\n bg: \"#ffffff\",\r\n pocheBase: \"#e9e4db\",\r\n pocheHatch: \"#b9b1a4\",\r\n wallStroke: \"#1b1b1b\",\r\n roomFill: \"#fbfaf7\",\r\n roomLabel: \"#222222\",\r\n areaLabel: \"#7a7a7a\",\r\n furnitureStroke: \"#a8a29a\",\r\n furnitureFill: \"#f4f2ee\",\r\n furnitureLabel: \"#9a948c\",\r\n opening: \"#ffffff\",\r\n doorLeaf: \"#555555\",\r\n windowPane: \"#3a6ea5\",\r\n dim: \"#0E5484\",\r\n annotation: \"#333333\",\r\n annotationMuted: \"#888888\",\r\n column: \"#4a4a4a\",\r\n lineWeight: 1,\r\n font: \"Helvetica, Arial, sans-serif\",\r\n};\r\n\r\n/** Friendly directive aliases → canonical {@link Theme} keys. */\r\nconst ALIASES: Record<string, keyof Theme> = {\r\n background: \"bg\",\r\n wall: \"wallStroke\",\r\n wallFill: \"pocheBase\",\r\n wallHatch: \"pocheHatch\",\r\n room: \"roomFill\",\r\n furniture: \"furnitureFill\",\r\n door: \"doorLeaf\",\r\n window: \"windowPane\",\r\n};\r\n\r\n/** Resolve a directive key (canonical or alias) to a Theme key, or null. */\r\nexport function resolveThemeKey(key: string): keyof Theme | null {\r\n if (key in DEFAULT_THEME) return key as keyof Theme;\r\n if (key in ALIASES) return ALIASES[key];\r\n return null;\r\n}\r\n\r\n/** Keys whose values are numbers (everything else is a string). */\r\nexport function isNumericThemeKey(key: keyof Theme): boolean {\r\n return key === \"lineWeight\";\r\n}\r\n\r\n/** Shallow-merge theme layers (later overrides earlier); ignores undefined. */\r\nexport function mergeTheme(...layers: (Partial<Theme> | undefined)[]): Theme {\r\n const out: Theme = { ...DEFAULT_THEME };\r\n for (const layer of layers) {\r\n if (!layer) continue;\r\n for (const k of Object.keys(layer) as (keyof Theme)[]) {\r\n const v = layer[k];\r\n if (v !== undefined) (out as unknown as Record<string, unknown>)[k] = v;\r\n }\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * XML-escape every string theme value (colours, font). Theme strings come from\r\n * untrusted `.arch` source (the `theme { … }` directive / `CompileOptions.theme`)\r\n * and are interpolated into SVG *attributes*; escaping `& < > \"` here, once,\r\n * makes attribute breakout impossible regardless of how each render site emits\r\n * them. Numeric values (lineWeight) pass through. Valid colours/fonts contain no\r\n * escapable characters, so output is unchanged for well-formed themes.\r\n */\r\nexport function sanitizeTheme(theme: Theme): Theme {\r\n const esc = (s: string): string =>\r\n s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\r\n const out: Theme = { ...theme };\r\n for (const k of Object.keys(out) as (keyof Theme)[]) {\r\n const v = out[k];\r\n if (typeof v === \"string\") (out as unknown as Record<string, unknown>)[k] = esc(v);\r\n }\r\n return out;\r\n}\r\n","/** Pure geometry helpers. All coordinates in millimetres. Deterministic. */\r\n\r\nimport type { Point } from \"./ast.js\";\r\n\r\nexport interface Vec {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport const sub = (a: Point, b: Point): Vec => ({ x: a.x - b.x, y: a.y - b.y });\r\nexport const add = (a: Point, b: Vec): Point => ({ x: a.x + b.x, y: a.y + b.y });\r\nexport const mul = (v: Vec, s: number): Vec => ({ x: v.x * s, y: v.y * s });\r\nexport const length = (v: Vec): number => Math.hypot(v.x, v.y);\r\nexport function unit(v: Vec): Vec {\r\n const l = length(v);\r\n return l === 0 ? { x: 0, y: 0 } : { x: v.x / l, y: v.y / l };\r\n}\r\n/** Left normal (rotate +90°). */\r\nexport const normal = (v: Vec): Vec => ({ x: -v.y, y: v.x });\r\n\r\nexport interface Bounds {\r\n minX: number;\r\n minY: number;\r\n maxX: number;\r\n maxY: number;\r\n}\r\n\r\nexport const emptyBounds = (): Bounds => ({\r\n minX: Infinity,\r\n minY: Infinity,\r\n maxX: -Infinity,\r\n maxY: -Infinity,\r\n});\r\n\r\nexport function extendBounds(b: Bounds, x: number, y: number): void {\r\n if (x < b.minX) b.minX = x;\r\n if (y < b.minY) b.minY = y;\r\n if (x > b.maxX) b.maxX = x;\r\n if (y > b.maxY) b.maxY = y;\r\n}\r\n\r\n/** Distance from point p to segment ab. */\r\nexport function distPointToSegment(p: Point, a: Point, b: Point): number {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const apx = p.x - a.x;\r\n const apy = p.y - a.y;\r\n const len2 = abx * abx + aby * aby;\r\n let t = len2 === 0 ? 0 : (apx * abx + apy * aby) / len2;\r\n t = Math.max(0, Math.min(1, t));\r\n const cx = a.x + t * abx;\r\n const cy = a.y + t * aby;\r\n return Math.hypot(p.x - cx, p.y - cy);\r\n}\r\n\r\n/**\r\n * Start/end angles (in degrees) of the **minor** arc from `start` to `end` about\r\n * `center`, in CAD orientation (Y up, counter-clockwise positive — the opposite\r\n * of the screen's Y-down space these points live in). Returned ordered so the\r\n * swept arc is the shorter one. Backends that emit native arcs (e.g. DXF `ARC`)\r\n * use this so the trig lives here, not in the serializer.\r\n */\r\nexport function minorArcDegrees(center: Point, start: Point, end: Point): [number, number] {\r\n const deg = (p: Point): number => (Math.atan2(-(p.y - center.y), p.x - center.x) * 180) / Math.PI;\r\n const a1 = deg(start);\r\n const a2 = deg(end);\r\n const ccw = (((a2 - a1) % 360) + 360) % 360;\r\n return ccw <= 180 ? [a1, a2] : [a2, a1];\r\n}\r\n\r\n/** Axis-aligned rectangle corners (clockwise) from origin + size. */\r\nexport function rectCorners(x: number, y: number, w: number, h: number): Point[] {\r\n return [\r\n { x, y },\r\n { x: x + w, y },\r\n { x: x + w, y: y + h },\r\n { x, y: y + h },\r\n ];\r\n}\r\n\r\n/**\r\n * Square-capped offset rectangle for a wall segment: the segment is widened by\r\n * `thickness` and extended by `thickness/2` at each end so orthogonal corners\r\n * fill cleanly when adjacent segments are drawn.\r\n */\r\nexport function segmentRectangle(a: Point, b: Point, thickness: number): Point[] {\r\n const d = unit(sub(b, a));\r\n const n = normal(d);\r\n const half = thickness / 2;\r\n const a2 = add(a, mul(d, -half));\r\n const b2 = add(b, mul(d, half));\r\n return [\r\n add(a2, mul(n, half)),\r\n add(b2, mul(n, half)),\r\n add(b2, mul(n, -half)),\r\n add(a2, mul(n, -half)),\r\n ];\r\n}\r\n\r\nexport interface WallSegment {\r\n a: Point;\r\n b: Point;\r\n thickness: number;\r\n category: string;\r\n}\r\n\r\n/** Minimal wall shape needed by the segment/hosting helpers (a resolved wall). */\r\nexport interface WallLike {\r\n id: string;\r\n category: string;\r\n thickness: number;\r\n points: Point[];\r\n closed: boolean;\r\n}\r\n\r\n/** Flatten a single wall into its individual segments. */\r\nexport function segmentsOfWall(w: WallLike): WallSegment[] {\r\n const segs: WallSegment[] = [];\r\n for (let k = 0; k < w.points.length - 1; k++) {\r\n segs.push({ a: w.points[k], b: w.points[k + 1], thickness: w.thickness, category: w.category });\r\n }\r\n if (w.closed && w.points.length > 2) {\r\n segs.push({ a: w.points[w.points.length - 1], b: w.points[0], thickness: w.thickness, category: w.category });\r\n }\r\n return segs;\r\n}\r\n\r\n/** The wall segment hosting an opening point (nearest), filtered by ref if given. */\r\nexport function hostSegmentForWalls(walls: WallLike[], at: Point, ref?: string): WallSegment | null {\r\n const candidates = ref ? walls.filter((w) => w.id === ref || w.category === ref) : walls;\r\n let best: WallSegment | null = null;\r\n let bestDist = Infinity;\r\n for (const w of candidates) {\r\n for (const s of segmentsOfWall(w)) {\r\n const dist = distPointToSegment(at, s.a, s.b);\r\n if (dist < bestDist) {\r\n bestDist = dist;\r\n best = s;\r\n }\r\n }\r\n }\r\n return best;\r\n}\r\n\r\n/**\r\n * Single-pass host lookup: the nearest wall segment AND whether the point lies\r\n * on some wall, computed in one scan (distPointToSegment evaluated once per\r\n * segment). Byte-identical to calling {@link hostSegmentForWalls} and\r\n * {@link isOnSomeWall} separately — the nearest uses the same first-wins\r\n * `dist < best` rule; `onWall` is an order-independent OR of the per-wall\r\n * tolerance test. This halves the per-opening scan cost (the benchmark's\r\n * dominant stage) without changing output.\r\n */\r\nexport function hostInfoForWalls(\r\n walls: WallLike[],\r\n at: Point,\r\n ref?: string,\r\n): { host: WallSegment | null; onWall: boolean } {\r\n const candidates = ref ? walls.filter((w) => w.id === ref || w.category === ref) : walls;\r\n let host: WallSegment | null = null;\r\n let bestDist = Infinity;\r\n let onWall = false;\r\n for (const w of candidates) {\r\n const tol = w.thickness / 2 + Math.max(w.thickness, 1);\r\n for (const s of segmentsOfWall(w)) {\r\n const dist = distPointToSegment(at, s.a, s.b);\r\n if (dist < bestDist) {\r\n bestDist = dist;\r\n host = s;\r\n }\r\n if (!onWall && dist <= tol) onWall = true;\r\n }\r\n }\r\n return { host, onWall };\r\n}\r\n\r\n/** Whether a point lies within tolerance of some wall (filtered by ref if given). */\r\nexport function isOnSomeWall(walls: WallLike[], at: Point, ref?: string): boolean {\r\n const candidates = ref ? walls.filter((w) => w.id === ref || w.category === ref) : walls;\r\n for (const w of candidates) {\r\n const tol = w.thickness / 2 + Math.max(w.thickness, 1);\r\n for (const s of segmentsOfWall(w)) {\r\n if (distPointToSegment(at, s.a, s.b) <= tol) return true;\r\n }\r\n }\r\n return false;\r\n}\r\n","/**\r\n * Material hatch patterns — each emits an SVG `<pattern>` for wall poché.\r\n *\r\n * Zero-dependency and deterministic. `poche` is the default (the v0.1 45° hatch);\r\n * the rest are selectable via `wall <kind> thickness N material <name> { … }`.\r\n * Patterns are monochrome (base + line colours) so they stay theme-driven.\r\n */\r\n\r\nexport interface HatchCtx {\r\n fmt: (n: number) => string;\r\n /** Hatch module size in user units (derives from refDim). */\r\n gap: number;\r\n /** A thin stroke width. */\r\n thin: number;\r\n base: string;\r\n line: string;\r\n}\r\n\r\n/** Builds the inner markup of a `<pattern>` (id + attributes are added by caller). */\r\nexport type HatchDef = (id: string, c: HatchCtx) => string;\r\n\r\nexport const KNOWN_MATERIALS = [\"poche\", \"concrete\", \"brick\", \"insulation\", \"tile\", \"none\"] as const;\r\nexport type Material = (typeof KNOWN_MATERIALS)[number];\r\nexport const DEFAULT_MATERIAL: Material = \"poche\";\r\n\r\n/** The SVG element id for a material's pattern (default keeps the bare \"poche\"). */\r\nexport function patternId(material: string): string {\r\n return material === \"poche\" ? \"poche\" : `hatch-${material}`;\r\n}\r\n\r\nconst HATCHES: Record<Material, HatchDef> = {\r\n poche: (id, c) =>\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(c.gap)}\" height=\"${c.fmt(c.gap)}\" patternTransform=\"rotate(45)\">` +\r\n `<rect width=\"${c.fmt(c.gap)}\" height=\"${c.fmt(c.gap)}\" fill=\"${c.base}\"/>` +\r\n `<line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"${c.fmt(c.gap)}\" stroke=\"${c.line}\" stroke-width=\"${c.fmt(c.thin * 0.7)}\"/>` +\r\n `</pattern>`,\r\n\r\n // Aggregate speckle.\r\n concrete: (id, c) => {\r\n const w = c.gap * 1.6;\r\n return (\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\">` +\r\n `<rect width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\" fill=\"${c.base}\"/>` +\r\n `<circle cx=\"${c.fmt(w * 0.25)}\" cy=\"${c.fmt(w * 0.3)}\" r=\"${c.fmt(c.thin * 0.9)}\" fill=\"${c.line}\"/>` +\r\n `<circle cx=\"${c.fmt(w * 0.7)}\" cy=\"${c.fmt(w * 0.62)}\" r=\"${c.fmt(c.thin * 0.6)}\" fill=\"${c.line}\"/>` +\r\n `<circle cx=\"${c.fmt(w * 0.45)}\" cy=\"${c.fmt(w * 0.85)}\" r=\"${c.fmt(c.thin * 0.75)}\" fill=\"${c.line}\"/>` +\r\n `</pattern>`\r\n );\r\n },\r\n\r\n // Running-bond brick courses.\r\n brick: (id, c) => {\r\n const w = c.gap * 3;\r\n const h = c.gap * 1.4;\r\n const sw = c.fmt(c.thin * 0.6);\r\n return (\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(w)}\" height=\"${c.fmt(h)}\">` +\r\n `<rect width=\"${c.fmt(w)}\" height=\"${c.fmt(h)}\" fill=\"${c.base}\"/>` +\r\n `<line x1=\"0\" y1=\"${c.fmt(h)}\" x2=\"${c.fmt(w)}\" y2=\"${c.fmt(h)}\" stroke=\"${c.line}\" stroke-width=\"${sw}\"/>` +\r\n `<line x1=\"0\" y1=\"${c.fmt(h / 2)}\" x2=\"${c.fmt(w)}\" y2=\"${c.fmt(h / 2)}\" stroke=\"${c.line}\" stroke-width=\"${sw}\"/>` +\r\n `<line x1=\"${c.fmt(w / 2)}\" y1=\"0\" x2=\"${c.fmt(w / 2)}\" y2=\"${c.fmt(h / 2)}\" stroke=\"${c.line}\" stroke-width=\"${sw}\"/>` +\r\n `<line x1=\"0\" y1=\"${c.fmt(h / 2)}\" x2=\"0\" y2=\"${c.fmt(h)}\" stroke=\"${c.line}\" stroke-width=\"${sw}\"/>` +\r\n `<line x1=\"${c.fmt(w)}\" y1=\"${c.fmt(h / 2)}\" x2=\"${c.fmt(w)}\" y2=\"${c.fmt(h)}\" stroke=\"${c.line}\" stroke-width=\"${sw}\"/>` +\r\n `</pattern>`\r\n );\r\n },\r\n\r\n // Cross-hatch batting.\r\n insulation: (id, c) => {\r\n const w = c.gap * 1.2;\r\n return (\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\">` +\r\n `<rect width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\" fill=\"${c.base}\"/>` +\r\n `<path d=\"M0,0 L${c.fmt(w)},${c.fmt(w)} M${c.fmt(w)},0 L0,${c.fmt(w)}\" stroke=\"${c.line}\" stroke-width=\"${c.fmt(c.thin * 0.5)}\" fill=\"none\"/>` +\r\n `</pattern>`\r\n );\r\n },\r\n\r\n // Square tile grid.\r\n tile: (id, c) => {\r\n const w = c.gap * 1.8;\r\n return (\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\">` +\r\n `<rect width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\" fill=\"${c.base}\"/>` +\r\n `<rect x=\"0\" y=\"0\" width=\"${c.fmt(w)}\" height=\"${c.fmt(w)}\" fill=\"none\" stroke=\"${c.line}\" stroke-width=\"${c.fmt(c.thin * 0.6)}\"/>` +\r\n `</pattern>`\r\n );\r\n },\r\n\r\n // Solid fill, no hatch.\r\n none: (id, c) =>\r\n `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${c.fmt(c.gap)}\" height=\"${c.fmt(c.gap)}\">` +\r\n `<rect width=\"${c.fmt(c.gap)}\" height=\"${c.fmt(c.gap)}\" fill=\"${c.base}\"/>` +\r\n `</pattern>`,\r\n};\r\n\r\nexport function isKnownMaterial(name: string): name is Material {\r\n return (KNOWN_MATERIALS as readonly string[]).includes(name);\r\n}\r\n\r\n/** Render the `<pattern>` markup for a material (assumed known). */\r\nexport function hatchPattern(material: Material, c: HatchCtx): string {\r\n return HATCHES[material](patternId(material), c);\r\n}\r\n","/** `wall <category> thickness N { (x,y)… [close] }` — poché fill + crisp faces. */\r\n\r\nimport type { ExprPoint, Point, WallNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RWall } from \"../ir.js\";\r\nimport { add, mul, normal, segmentRectangle, segmentsOfWall, sub, unit } from \"../geometry.js\";\r\nimport { DEFAULT_MATERIAL, isKnownMaterial, KNOWN_MATERIALS } from \"../hatches.js\";\r\n\r\nexport const wall: ElementDef = {\r\n kind: \"wall\",\r\n keyword: \"wall\",\r\n\r\n parse(ctx: ParseCtx): WallNode {\r\n const kw = ctx.eatKeyword(\"wall\");\r\n const id = ctx.parseIdOpt();\r\n const category = ctx.eatIdent().value;\r\n ctx.eatKeyword(\"thickness\");\r\n const thickness = ctx.parseExpr();\r\n let material: string | undefined;\r\n if (ctx.isKeyword(\"material\")) {\r\n ctx.next();\r\n material = ctx.eatIdent().value;\r\n }\r\n ctx.eat(\"lcurly\");\r\n const points: ExprPoint[] = [];\r\n let closed = false;\r\n while (!ctx.isType(\"rcurly\") && !ctx.isType(\"eof\")) {\r\n if (ctx.isKeyword(\"close\")) {\r\n ctx.next();\r\n closed = true;\r\n break;\r\n }\r\n if (ctx.isType(\"lparen\")) {\r\n points.push(ctx.parsePoint());\r\n continue;\r\n }\r\n ctx.fail(`Expected a point \"(x,y)\" or \"close\" in wall body but found ${describe(ctx)}`);\r\n }\r\n ctx.eat(\"rcurly\");\r\n if (points.length < 2) ctx.fail(\"A wall needs at least two points\", kw);\r\n return { kind: \"wall\", id, category, thickness, material, points, closed, line: kw.line };\r\n },\r\n\r\n idPrefix: (node) => (node as WallNode).category || \"wall\",\r\n\r\n resolve(node, ctx: ResolveCtx): RWall {\r\n const n = node as WallNode;\r\n const id = ctx.id;\r\n const points = n.points.map((p) => ctx.snapPt(ctx.evalPt(p)));\r\n const tv = ctx.eval(n.thickness);\r\n const thickness = ctx.snap(tv) || tv;\r\n if (thickness <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Wall \"${id}\" must have a positive thickness`, code: \"E_WALL_THICKNESS\", span: n.span });\r\n }\r\n let material = DEFAULT_MATERIAL as string;\r\n if (n.material !== undefined) {\r\n if (isKnownMaterial(n.material)) material = n.material;\r\n else\r\n ctx.diag({\r\n severity: \"warning\",\r\n message: `Unknown wall material \"${n.material}\" (known: ${KNOWN_MATERIALS.join(\", \")}); using the default hatch`,\r\n code: \"W_UNKNOWN_MATERIAL\",\r\n span: n.span,\r\n });\r\n }\r\n return { kind: \"wall\", id, category: n.category, thickness, material, points, closed: n.closed, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const w = resolved as RWall;\r\n return segmentsOfWall(w).flatMap((s) => segmentRectangle(s.a, s.b, s.thickness));\r\n },\r\n\r\n /**\r\n * Per-segment wall fill (poché) + two crisp face lines. This is the angled-wall\r\n * path; orthogonal walls are unioned into clean loops in `scene-build.ts`. The\r\n * fill always references the default poché pattern, matching v0.1.\r\n */\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const w = resolved as RWall;\r\n const { theme, sizes } = ctx;\r\n const segs = segmentsOfWall(w);\r\n const nodes: SceneNode[] = [];\r\n for (const s of segs) {\r\n const poly = segmentRectangle(s.a, s.b, s.thickness);\r\n nodes.push({ layer: \"wallFill\", prim: { t: \"polygon\", pts: poly }, paint: { fill: \"url(#poche)\" } });\r\n }\r\n for (const s of segs) {\r\n const d = unit(sub(s.b, s.a));\r\n const n = normal(d);\r\n const h = s.thickness / 2;\r\n const face = { stroke: theme.wallStroke, width: sizes.wallStroke, linecap: \"square\" as const };\r\n nodes.push({ layer: \"wallFace\", prim: { t: \"line\", a: add(s.a, mul(n, h)), b: add(s.b, mul(n, h)) }, paint: face });\r\n nodes.push({ layer: \"wallFace\", prim: { t: \"line\", a: add(s.a, mul(n, -h)), b: add(s.b, mul(n, -h)) }, paint: face });\r\n }\r\n return nodes;\r\n },\r\n};\r\n\r\nfunction describe(ctx: ParseCtx): string {\r\n const t = ctx.peek();\r\n if (t.type === \"eof\") return \"end of input\";\r\n if (t.type === \"string\") return `string ${JSON.stringify(t.value)}`;\r\n return `\"${t.value}\"`;\r\n}\r\n","/** `room [id=] at (x,y) size WxH [label \"…\"]` — floor fill + label + computed area. */\r\n\r\nimport type { Point, RoomNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RRoom } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const room: ElementDef = {\r\n kind: \"room\",\r\n keyword: \"room\",\r\n\r\n parse(ctx: ParseCtx): RoomNode {\r\n const kw = ctx.eatKeyword(\"room\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const size = ctx.parseDimensions();\r\n const node: RoomNode = { kind: \"room\", id, at, size, line: kw.line };\r\n if (ctx.isKeyword(\"label\")) {\r\n ctx.next();\r\n node.label = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"room\",\r\n\r\n resolve(node, ctx: ResolveCtx): RRoom {\r\n const n = node as RoomNode;\r\n const id = ctx.id;\r\n const at = ctx.snapPt(ctx.evalPt(n.at));\r\n const size = { w: ctx.snap(ctx.eval(n.size.w)), h: ctx.snap(ctx.eval(n.size.h)) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Room \"${id}\" must have a positive size`, code: \"E_ROOM_SIZE\", span: n.span });\r\n }\r\n return { kind: \"room\", id, at, size, label: n.label, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const r = resolved as RRoom;\r\n return rectCorners(r.at.x, r.at.y, r.size.w, r.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const r = resolved as RRoom;\r\n const { theme, sizes } = ctx;\r\n const nodes: SceneNode[] = [];\r\n const c = rectCorners(r.at.x, r.at.y, r.size.w, r.size.h);\r\n nodes.push({ layer: \"floor\", prim: { t: \"polygon\", pts: c }, paint: { fill: theme.roomFill } });\r\n\r\n const cx = r.at.x + r.size.w / 2;\r\n const cy = r.at.y + r.size.h / 2;\r\n const areaM2 = ((r.size.w / 1000) * (r.size.h / 1000)).toFixed(1);\r\n if (r.label) {\r\n nodes.push({\r\n layer: \"labels\",\r\n prim: { t: \"text\", at: { x: cx, y: cy - sizes.roomFont * 0.2 }, value: r.label, size: sizes.roomFont, anchor: \"middle\", baseline: \"central\", weight: 600 },\r\n paint: { fill: theme.roomLabel },\r\n });\r\n }\r\n nodes.push({\r\n layer: \"labels\",\r\n prim: { t: \"text\", at: { x: cx, y: cy + (r.label ? sizes.roomFont * 0.9 : 0) }, value: `${areaM2} m²`, size: sizes.areaFont, anchor: \"middle\", baseline: \"central\" },\r\n paint: { fill: theme.areaLabel },\r\n });\r\n return nodes;\r\n },\r\n};\r\n","/** `door [id=] at (x,y) width N [wall ref] [hinge l|r] [swing in|out]` — opening + leaf + swing arc. */\r\n\r\nimport type { DoorNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RDoor } from \"../ir.js\";\r\nimport { add, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const door: ElementDef = {\r\n kind: \"door\",\r\n keyword: \"door\",\r\n\r\n parse(ctx: ParseCtx): DoorNode {\r\n const kw = ctx.eatKeyword(\"door\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"width\");\r\n const width = ctx.parseExpr();\r\n const node: DoorNode = { kind: \"door\", id, at, width, hinge: \"left\", swing: \"in\", line: kw.line };\r\n if (ctx.isKeyword(\"wall\")) {\r\n ctx.next();\r\n node.wall = ctx.eatIdent().value;\r\n }\r\n if (ctx.isKeyword(\"hinge\")) {\r\n ctx.next();\r\n const h = ctx.eatIdent().value;\r\n if (h !== \"left\" && h !== \"right\") ctx.fail(`Expected hinge \"left\" or \"right\" but found \"${h}\"`);\r\n node.hinge = h;\r\n }\r\n if (ctx.isKeyword(\"swing\")) {\r\n ctx.next();\r\n const s = ctx.eatIdent().value;\r\n if (s !== \"in\" && s !== \"out\") ctx.fail(`Expected swing \"in\" or \"out\" but found \"${s}\"`);\r\n node.swing = s;\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"door\",\r\n\r\n resolve(node, ctx: ResolveCtx): RDoor {\r\n const n = node as DoorNode;\r\n const id = ctx.id;\r\n const at = ctx.snapPt(ctx.evalPt(n.at));\r\n const wv = ctx.eval(n.width);\r\n const width = ctx.snap(wv) || wv;\r\n if (width <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Door \"${id}\" must have a positive width`, code: \"E_DOOR_WIDTH\", span: n.span });\r\n }\r\n if (ctx.walls.length > 0 && !ctx.isOnWall(at, n.wall)) {\r\n ctx.diag({ severity: \"warning\", message: `Door \"${id}\" does not lie on any wall`, code: \"W_DOOR_OFF_WALL\", span: n.span });\r\n }\r\n return { kind: \"door\", id, at, width, hinge: n.hinge, swing: n.swing, host: ctx.hostSegment(at, n.wall), span: n.span };\r\n },\r\n\r\n bounds: () => [],\r\n\r\n /**\r\n * Opening cover + leaf line + swing arc. The swing geometry (hinge, leaf,\r\n * far jamb, minor-arc orientation) is computed **here, once** — every backend\r\n * (SVG, DXF, PDF) now serializes the same `arc` primitive rather than\r\n * re-deriving it.\r\n */\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const dr = resolved as RDoor;\r\n const seg = dr.host;\r\n if (!seg) return [];\r\n const { theme, sizes } = ctx;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const h = seg.thickness / 2 + sizes.wallStroke;\r\n const hw = dr.width / 2;\r\n const cover: Point[] = [\r\n add(add(dr.at, mul(d, -hw)), mul(n, h)),\r\n add(add(dr.at, mul(d, hw)), mul(n, h)),\r\n add(add(dr.at, mul(d, hw)), mul(n, -h)),\r\n add(add(dr.at, mul(d, -hw)), mul(n, -h)),\r\n ];\r\n const nodes: SceneNode[] = [];\r\n nodes.push({ layer: \"doors\", prim: { t: \"polygon\", pts: cover }, paint: { fill: theme.opening } });\r\n const hinge = dr.hinge === \"left\" ? add(dr.at, mul(d, -hw)) : add(dr.at, mul(d, hw));\r\n const farJamb = dr.hinge === \"left\" ? add(dr.at, mul(d, hw)) : add(dr.at, mul(d, -hw));\r\n const leafDir = dr.swing === \"in\" ? n : mul(n, -1);\r\n const leafEnd = add(hinge, mul(leafDir, dr.width));\r\n const cross = (leafEnd.x - hinge.x) * (farJamb.y - hinge.y) - (leafEnd.y - hinge.y) * (farJamb.x - hinge.x);\r\n const sweep: 0 | 1 = cross < 0 ? 1 : 0;\r\n nodes.push({\r\n layer: \"doors\",\r\n prim: { t: \"line\", a: hinge, b: leafEnd },\r\n paint: { stroke: theme.doorLeaf, width: sizes.thin * 1.3 },\r\n });\r\n nodes.push({\r\n layer: \"doors\",\r\n prim: { t: \"arc\", center: hinge, r: dr.width, start: leafEnd, end: farJamb, sweep },\r\n paint: { fill: \"none\", stroke: theme.doorLeaf, width: sizes.thin, dash: [sizes.thin * 4, sizes.thin * 3] },\r\n });\r\n return nodes;\r\n },\r\n};\r\n","/** `window [id=] at (x,y) width N [wall ref]` — opening + glazing panes. */\r\n\r\nimport type { Point, WindowNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RWindow } from \"../ir.js\";\r\nimport { add, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const windowEl: ElementDef = {\r\n kind: \"window\",\r\n keyword: \"window\",\r\n\r\n parse(ctx: ParseCtx): WindowNode {\r\n const kw = ctx.eatKeyword(\"window\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"width\");\r\n const width = ctx.parseExpr();\r\n const node: WindowNode = { kind: \"window\", id, at, width, line: kw.line };\r\n if (ctx.isKeyword(\"wall\")) {\r\n ctx.next();\r\n node.wall = ctx.eatIdent().value;\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"window\",\r\n\r\n resolve(node, ctx: ResolveCtx): RWindow {\r\n const n = node as WindowNode;\r\n const id = ctx.id;\r\n const at = ctx.snapPt(ctx.evalPt(n.at));\r\n const wv = ctx.eval(n.width);\r\n const width = ctx.snap(wv) || wv;\r\n if (width <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Window \"${id}\" must have a positive width`, code: \"E_WINDOW_WIDTH\", span: n.span });\r\n }\r\n if (ctx.walls.length > 0 && !ctx.isOnWall(at, n.wall)) {\r\n ctx.diag({ severity: \"warning\", message: `Window \"${id}\" does not lie on any wall`, code: \"W_WINDOW_OFF_WALL\", span: n.span });\r\n }\r\n return { kind: \"window\", id, at, width, host: ctx.hostSegment(at, n.wall), span: n.span };\r\n },\r\n\r\n bounds: () => [],\r\n\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const wn = resolved as RWindow;\r\n const seg = wn.host;\r\n if (!seg) return [];\r\n const { theme, sizes } = ctx;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const h = seg.thickness / 2;\r\n const he = h + sizes.wallStroke;\r\n const hw = wn.width / 2;\r\n const cover: Point[] = [\r\n add(add(wn.at, mul(d, -hw)), mul(n, he)),\r\n add(add(wn.at, mul(d, hw)), mul(n, he)),\r\n add(add(wn.at, mul(d, hw)), mul(n, -he)),\r\n add(add(wn.at, mul(d, -hw)), mul(n, -he)),\r\n ];\r\n const nodes: SceneNode[] = [];\r\n nodes.push({ layer: \"windows\", prim: { t: \"polygon\", pts: cover }, paint: { fill: theme.opening } });\r\n const jA = add(wn.at, mul(d, -hw));\r\n const jB = add(wn.at, mul(d, hw));\r\n for (const off of [h, -h]) {\r\n nodes.push({\r\n layer: \"windows\",\r\n prim: { t: \"line\", a: add(jA, mul(n, off)), b: add(jB, mul(n, off)) },\r\n paint: { stroke: theme.wallStroke, width: sizes.thin },\r\n });\r\n }\r\n nodes.push({\r\n layer: \"windows\",\r\n prim: { t: \"line\", a: jA, b: jB },\r\n paint: { stroke: theme.windowPane, width: sizes.thin },\r\n });\r\n return nodes;\r\n },\r\n};\r\n","/** `furniture <category> [id=] at (x,y) size WxH [label \"…\"]` — outlined fill + label. */\r\n\r\nimport type { FurnitureNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RFurniture } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const furniture: ElementDef = {\r\n kind: \"furniture\",\r\n keyword: \"furniture\",\r\n\r\n parse(ctx: ParseCtx): FurnitureNode {\r\n const kw = ctx.eatKeyword(\"furniture\");\r\n const id = ctx.parseIdOpt();\r\n const category = ctx.eatIdent().value;\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const size = ctx.parseDimensions();\r\n const node: FurnitureNode = { kind: \"furniture\", id, category, at, size, line: kw.line };\r\n if (ctx.isKeyword(\"label\")) {\r\n ctx.next();\r\n node.label = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: (node) => (node as FurnitureNode).category || \"furniture\",\r\n\r\n resolve(node, ctx: ResolveCtx): RFurniture {\r\n const n = node as FurnitureNode;\r\n const id = ctx.id;\r\n const at = ctx.snapPt(ctx.evalPt(n.at));\r\n const size = { w: ctx.snap(ctx.eval(n.size.w)), h: ctx.snap(ctx.eval(n.size.h)) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Furniture \"${id}\" must have a positive size`, code: \"E_FURN_SIZE\", span: n.span });\r\n }\r\n return { kind: \"furniture\", id, category: n.category, at, size, label: n.label, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const f = resolved as RFurniture;\r\n return rectCorners(f.at.x, f.at.y, f.size.w, f.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const f = resolved as RFurniture;\r\n const { theme, sizes } = ctx;\r\n const nodes: SceneNode[] = [];\r\n const c = rectCorners(f.at.x, f.at.y, f.size.w, f.size.h);\r\n nodes.push({\r\n layer: \"furniture\",\r\n prim: { t: \"polygon\", pts: c },\r\n paint: { fill: theme.furnitureFill, stroke: theme.furnitureStroke, width: sizes.thin },\r\n });\r\n if (f.label) {\r\n const cx = f.at.x + f.size.w / 2;\r\n const cy = f.at.y + f.size.h / 2;\r\n nodes.push({\r\n layer: \"furniture\",\r\n prim: { t: \"text\", at: { x: cx, y: cy }, value: f.label, size: sizes.furnFont, anchor: \"middle\", baseline: \"central\" },\r\n paint: { fill: theme.furnitureLabel },\r\n });\r\n }\r\n return nodes;\r\n },\r\n};\r\n","/** `dim (x,y)->(x,y) [offset N] [text \"…\"]` — dimension line with ticks + length. */\r\n\r\nimport type { DimNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RDim } from \"../ir.js\";\r\nimport { add, length, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const dim: ElementDef = {\r\n kind: \"dim\",\r\n keyword: \"dim\",\r\n\r\n parse(ctx: ParseCtx): DimNode {\r\n const kw = ctx.eatKeyword(\"dim\");\r\n const from = ctx.parsePoint();\r\n ctx.eat(\"arrow\");\r\n const to = ctx.parsePoint();\r\n const node: DimNode = { kind: \"dim\", id: \"\", from, to, offset: { t: \"num\", value: 300 }, line: kw.line };\r\n if (ctx.isKeyword(\"offset\")) {\r\n ctx.next();\r\n node.offset = ctx.parseExpr();\r\n }\r\n if (ctx.isKeyword(\"text\")) {\r\n ctx.next();\r\n node.text = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"dim\",\r\n\r\n resolve(node, ctx: ResolveCtx): RDim {\r\n const n = node as DimNode;\r\n return {\r\n kind: \"dim\",\r\n id: ctx.id,\r\n from: ctx.snapPt(ctx.evalPt(n.from)),\r\n to: ctx.snapPt(ctx.evalPt(n.to)),\r\n offset: ctx.eval(n.offset),\r\n text: n.text,\r\n span: n.span,\r\n };\r\n },\r\n\r\n bounds(resolved) {\r\n const dm = resolved as RDim;\r\n return [dm.from, dm.to];\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const dm = resolved as RDim;\r\n const { theme, sizes } = ctx;\r\n const dir = unit(sub(dm.to, dm.from));\r\n const n = normal(dir);\r\n const off = mul(n, dm.offset);\r\n const p1 = add(dm.from, off);\r\n const p2 = add(dm.to, off);\r\n const tick = sizes.refDim * 0.012;\r\n const thinPaint = { stroke: theme.dim, width: sizes.thin };\r\n const nodes: SceneNode[] = [];\r\n // Extension lines (lighter), then the dimension line.\r\n nodes.push({ layer: \"dims\", prim: { t: \"line\", a: dm.from, b: p1 }, paint: { stroke: theme.dim, width: sizes.thin * 0.7 } });\r\n nodes.push({ layer: \"dims\", prim: { t: \"line\", a: dm.to, b: p2 }, paint: { stroke: theme.dim, width: sizes.thin * 0.7 } });\r\n nodes.push({ layer: \"dims\", prim: { t: \"line\", a: p1, b: p2 }, paint: thinPaint });\r\n for (const p of [p1, p2]) {\r\n const t1 = add(p, mul(unit({ x: dir.x + n.x, y: dir.y + n.y }), tick));\r\n const t2 = add(p, mul(unit({ x: dir.x + n.x, y: dir.y + n.y }), -tick));\r\n nodes.push({ layer: \"dims\", prim: { t: \"line\", a: t1, b: t2 }, paint: thinPaint });\r\n }\r\n const mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };\r\n const tp = add(mid, mul(n, sizes.dimFont * 0.7));\r\n let angle = (Math.atan2(dir.y, dir.x) * 180) / Math.PI;\r\n if (angle > 90) angle -= 180;\r\n if (angle < -90) angle += 180;\r\n const label = dm.text ?? String(Math.round(length(sub(dm.to, dm.from))));\r\n nodes.push({\r\n layer: \"dims\",\r\n prim: { t: \"text\", at: tp, value: label, size: sizes.dimFont, anchor: \"middle\", baseline: \"central\", rotate: angle },\r\n paint: { fill: theme.dim },\r\n });\r\n return nodes;\r\n },\r\n};\r\n","/**\r\n * `column [id=] at (x,y) size WxH` — a solid structural column.\r\n *\r\n * This module is the extensibility proof for the v0.3 registry: a brand-new\r\n * element type added as ONE file + one `register` line in `index.ts`, with no\r\n * edits to the parser, resolver, or renderer cores.\r\n */\r\n\r\nimport type { ColumnNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, ResolveCtx } from \"../registry.js\";\r\nimport type { SceneNode } from \"../scene.js\";\r\nimport type { RColumn } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const column: ElementDef = {\r\n kind: \"column\",\r\n keyword: \"column\",\r\n\r\n parse(ctx: ParseCtx): ColumnNode {\r\n const kw = ctx.eatKeyword(\"column\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const size = ctx.parseDimensions();\r\n return { kind: \"column\", id, at, size, line: kw.line };\r\n },\r\n\r\n idPrefix: () => \"column\",\r\n\r\n resolve(node, ctx: ResolveCtx): RColumn {\r\n const n = node as ColumnNode;\r\n const id = ctx.id;\r\n const at = ctx.snapPt(ctx.evalPt(n.at));\r\n const size = { w: ctx.snap(ctx.eval(n.size.w)), h: ctx.snap(ctx.eval(n.size.h)) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Column \"${id}\" must have a positive size`, code: \"E_COLUMN_SIZE\", span: n.span });\r\n }\r\n return { kind: \"column\", id, at, size, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const c = resolved as RColumn;\r\n return rectCorners(c.at.x, c.at.y, c.size.w, c.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): SceneNode[] {\r\n const c = resolved as RColumn;\r\n const { theme, sizes } = ctx;\r\n const pts = rectCorners(c.at.x, c.at.y, c.size.w, c.size.h);\r\n return [\r\n {\r\n layer: \"furniture\",\r\n prim: { t: \"polygon\", pts },\r\n paint: { fill: theme.column, stroke: theme.wallStroke, width: sizes.thin },\r\n },\r\n ];\r\n },\r\n};\r\n","/**\r\n * Element registry assembly. Registration order is canonical: it drives id\r\n * assignment and resolve ordering (walls first, so openings can host against\r\n * them). To add an element: write one module and add one `register()` line.\r\n */\r\n\r\nimport type { ElementDef } from \"../registry.js\";\r\nimport { wall } from \"./wall.js\";\r\nimport { room } from \"./room.js\";\r\nimport { door } from \"./door.js\";\r\nimport { windowEl } from \"./window.js\";\r\nimport { furniture } from \"./furniture.js\";\r\nimport { dim } from \"./dim.js\";\r\nimport { column } from \"./column.js\";\r\n\r\n/** Defs in canonical (registration) order. */\r\nexport const registryOrder: ElementDef[] = [];\r\n/** Lookup by keyword. */\r\nexport const registry = new Map<string, ElementDef>();\r\n\r\nfunction register(def: ElementDef): void {\r\n registry.set(def.keyword, def);\r\n registryOrder.push(def);\r\n}\r\n\r\nregister(wall);\r\nregister(room);\r\nregister(door);\r\nregister(windowEl);\r\nregister(furniture);\r\nregister(dim);\r\nregister(column);\r\n","/** Recursive-descent parser: tokens -> PlanNode. Registry-driven element dispatch. */\r\n\r\nimport type { Token } from \"./lexer.js\";\r\nimport { lex } from \"./lexer.js\";\r\nimport type { Diagnostic, Span } from \"./diagnostics.js\";\r\nimport type {\r\n ComponentDef,\r\n ExprPoint,\r\n InstanceNode,\r\n LetNode,\r\n NorthDir,\r\n PlanNode,\r\n Statement,\r\n TitleNode,\r\n} from \"./ast.js\";\r\nimport type { Expr } from \"./expr.js\";\r\nimport { parseExpr as parseExprPratt } from \"./expr.js\";\r\nimport type { Theme } from \"./theme.js\";\r\nimport { isNumericThemeKey, resolveThemeKey } from \"./theme.js\";\r\nimport type { ParseCtx } from \"./registry.js\";\r\nimport { registry } from \"./elements/index.js\";\r\n\r\nexport interface ParseOutcome {\r\n plan?: PlanNode;\r\n diagnostics: Diagnostic[];\r\n}\r\n\r\n/** Plan-level settings + binding/definition keywords (not registry elements). */\r\nconst SETTINGS = [\"units\", \"grid\", \"scale\", \"north\", \"title\", \"theme\", \"let\", \"component\"];\r\n/** Keywords that begin a plan-body statement; recovery resynchronizes to one. */\r\nconst STATEMENT_STARTS = new Set<string>([...SETTINGS, ...registry.keys()]);\r\n\r\n/** Thrown internally by `eat*` helpers; always caught within the parser. */\r\nclass ParseError extends Error {\r\n constructor(public override message: string, public span: Span) {\r\n super(message);\r\n }\r\n}\r\n\r\nexport function parse(src: string): ParseOutcome {\r\n const { tokens, errors: lexErrors } = lex(src);\r\n const lexDiags: Diagnostic[] = lexErrors.map((e) => ({\r\n severity: \"error\" as const,\r\n message: e.message,\r\n span: e.span,\r\n }));\r\n\r\n const p = new Parser(tokens);\r\n let plan: PlanNode | undefined;\r\n try {\r\n plan = p.parsePlan();\r\n } catch (e) {\r\n // Only a malformed plan *header* escapes parsePlan's per-statement recovery.\r\n if (e instanceof ParseError) {\r\n p.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n } else {\r\n throw e;\r\n }\r\n }\r\n return { plan, diagnostics: [...lexDiags, ...p.diagnostics] };\r\n}\r\n\r\nclass Parser {\r\n private pos = 0;\r\n public diagnostics: Diagnostic[] = [];\r\n /** Facade passed to element parse functions (see registry.ts). */\r\n private readonly ctx: ParseCtx;\r\n\r\n constructor(private toks: Token[]) {\r\n this.ctx = {\r\n peek: (o) => this.peek(o),\r\n next: () => this.next(),\r\n eat: (type) => this.eat(type),\r\n eatKeyword: (kw) => this.eatKeyword(kw),\r\n eatIdent: () => this.eatIdent(),\r\n eatNumber: () => this.eatNumber(),\r\n eatString: () => this.eatString(),\r\n isKeyword: (kw, o) => this.isKeyword(kw, o),\r\n isType: (type) => this.isType(type),\r\n parsePoint: () => this.parsePoint(),\r\n parseExpr: () => parseExprPratt(this.ctx),\r\n parseDimensions: () => this.parseDimensions(),\r\n parseIdOpt: () => this.parseIdOpt(),\r\n fail: (msg, t) => this.fail(msg, t),\r\n };\r\n }\r\n\r\n private peek(o = 0): Token {\r\n return this.toks[Math.min(this.pos + o, this.toks.length - 1)];\r\n }\r\n private next(): Token {\r\n return this.toks[Math.min(this.pos++, this.toks.length - 1)];\r\n }\r\n private fail(msg: string, t = this.peek()): never {\r\n throw new ParseError(msg, { start: t.start, end: t.end });\r\n }\r\n\r\n /** Span from a start offset to the end of the last consumed token. */\r\n private spanFrom(start: number): Span {\r\n const last = this.toks[Math.max(0, Math.min(this.pos - 1, this.toks.length - 1))];\r\n return { start, end: last.end };\r\n }\r\n\r\n /** Recover after a statement error: skip to the next statement start or block end. */\r\n private synchronize(): void {\r\n // Always make progress so a hard-stuck token can't loop forever.\r\n if (!this.isType(\"rcurly\") && !this.isType(\"eof\")) this.next();\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n if (t.type === \"ident\" && STATEMENT_STARTS.has(t.value)) return;\r\n this.next();\r\n }\r\n }\r\n\r\n private isKeyword(kw: string, o = 0): boolean {\r\n const t = this.peek(o);\r\n return t.type === \"ident\" && t.value === kw;\r\n }\r\n private eatKeyword(kw: string): Token {\r\n const t = this.peek();\r\n if (t.type !== \"ident\" || t.value !== kw) this.fail(`Expected \"${kw}\" but found ${describe(t)}`);\r\n return this.next();\r\n }\r\n private eat(type: Token[\"type\"]): Token {\r\n const t = this.peek();\r\n if (t.type !== type) this.fail(`Expected ${type} but found ${describe(t)}`);\r\n return this.next();\r\n }\r\n private eatIdent(): Token {\r\n return this.eat(\"ident\");\r\n }\r\n private eatNumber(): number {\r\n const t = this.eat(\"number\");\r\n return t.num!;\r\n }\r\n private eatString(): string {\r\n return this.eat(\"string\").value;\r\n }\r\n\r\n parsePlan(): PlanNode {\r\n this.eatKeyword(\"plan\");\r\n const name = this.eatString();\r\n this.eat(\"lcurly\");\r\n\r\n const plan: PlanNode = {\r\n name,\r\n units: \"mm\",\r\n grid: 0,\r\n north: \"up\",\r\n components: new Map(),\r\n body: [],\r\n };\r\n\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n const start = t.start;\r\n try {\r\n if (t.type !== \"ident\") this.fail(`Expected a statement but found ${describe(t)}`);\r\n const def = registry.get(t.value);\r\n if (def) {\r\n const node = def.parse(this.ctx);\r\n node.span = this.spanFrom(start);\r\n plan.body.push(node);\r\n continue;\r\n }\r\n // A defined component name followed by `(` is an instantiation.\r\n if (plan.components.has(t.value) && this.peek(1).type === \"lparen\") {\r\n const node = this.parseInstance();\r\n node.span = this.spanFrom(start);\r\n plan.body.push(node);\r\n continue;\r\n }\r\n switch (t.value) {\r\n case \"units\": {\r\n this.next();\r\n const u = this.eatIdent().value;\r\n if (u !== \"mm\") this.fail(`Unsupported units \"${u}\" (only \"mm\" is supported)`, t);\r\n plan.units = \"mm\";\r\n break;\r\n }\r\n case \"grid\":\r\n this.next();\r\n plan.grid = this.eatNumber();\r\n break;\r\n case \"scale\": {\r\n this.next();\r\n const a = this.eatNumber();\r\n this.eat(\"colon\");\r\n const b = this.eatNumber();\r\n plan.scale = `${a}:${b}`;\r\n break;\r\n }\r\n case \"north\":\r\n this.next();\r\n plan.north = this.parseNorth();\r\n break;\r\n case \"title\": {\r\n const n = this.parseTitle();\r\n n.span = this.spanFrom(start);\r\n plan.title = n;\r\n break;\r\n }\r\n case \"theme\": {\r\n plan.theme = { ...plan.theme, ...this.parseTheme() };\r\n break;\r\n }\r\n case \"let\": {\r\n const n = this.parseLet();\r\n n.span = this.spanFrom(start);\r\n plan.body.push(n);\r\n break;\r\n }\r\n case \"component\": {\r\n const def = this.parseComponent(plan.components);\r\n def.span = this.spanFrom(start);\r\n if (plan.components.has(def.name)) {\r\n this.fail(`Component \"${def.name}\" is already defined`, t);\r\n }\r\n plan.components.set(def.name, def);\r\n break;\r\n }\r\n default:\r\n this.fail(`Unknown statement \"${t.value}\"`, t);\r\n }\r\n } catch (e) {\r\n if (e instanceof ParseError) {\r\n this.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n this.synchronize();\r\n } else {\r\n throw e;\r\n }\r\n }\r\n }\r\n // A missing closing brace is reported but the partial plan is still returned.\r\n try {\r\n this.eat(\"rcurly\");\r\n } catch (e) {\r\n if (e instanceof ParseError) {\r\n this.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n } else {\r\n throw e;\r\n }\r\n }\r\n return plan;\r\n }\r\n\r\n private isType(type: Token[\"type\"]): boolean {\r\n return this.peek().type === type;\r\n }\r\n\r\n /** Optional `id=<ident>` prefix; returns \"\" when absent. */\r\n private parseIdOpt(): string {\r\n if (this.isKeyword(\"id\")) {\r\n this.next();\r\n this.eat(\"equals\");\r\n return this.eatIdent().value;\r\n }\r\n return \"\";\r\n }\r\n\r\n private parseNorth(): NorthDir {\r\n const t = this.peek();\r\n if (t.type === \"number\") {\r\n this.next();\r\n return { deg: t.num! };\r\n }\r\n if (t.type === \"ident\" && [\"up\", \"down\", \"left\", \"right\"].includes(t.value)) {\r\n this.next();\r\n return t.value as NorthDir;\r\n }\r\n this.fail(`Expected a north direction (up|down|left|right|<degrees>) but found ${describe(t)}`);\r\n }\r\n\r\n private parsePoint(): ExprPoint {\r\n this.eat(\"lparen\");\r\n const x = parseExprPratt(this.ctx);\r\n this.eat(\"comma\");\r\n const y = parseExprPratt(this.ctx);\r\n this.eat(\"rparen\");\r\n return { x, y };\r\n }\r\n\r\n /** A size: either a `WxH` literal dimension token or `<expr> x <expr>`. */\r\n private parseDimensions(): { w: Expr; h: Expr } {\r\n if (this.isType(\"dimension\")) {\r\n const d = this.eat(\"dimension\");\r\n return { w: { t: \"num\", value: d.num! }, h: { t: \"num\", value: d.num2! } };\r\n }\r\n const w = parseExprPratt(this.ctx);\r\n if (this.isKeyword(\"x\")) this.next();\r\n else this.fail(`Expected \"x\" between width and height but found ${describe(this.peek())}`);\r\n const h = parseExprPratt(this.ctx);\r\n return { w, h };\r\n }\r\n\r\n private parseTitle(): TitleNode {\r\n const kw = this.eatKeyword(\"title\");\r\n this.eat(\"lcurly\");\r\n const node: TitleNode = { line: kw.line };\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n if (t.type !== \"ident\") this.fail(`Expected a title field but found ${describe(t)}`);\r\n switch (t.value) {\r\n case \"project\":\r\n this.next();\r\n node.project = this.eatString();\r\n break;\r\n case \"drawn_by\":\r\n this.next();\r\n node.drawnBy = this.eatString();\r\n break;\r\n case \"date\":\r\n this.next();\r\n node.date = this.eatString();\r\n break;\r\n default:\r\n this.fail(`Unknown title field \"${t.value}\"`, t);\r\n }\r\n }\r\n this.eat(\"rcurly\");\r\n return node;\r\n }\r\n\r\n /** `theme { key: <value> … }` — colours (strings), `lineWeight` (number), `font` (string). */\r\n private parseTheme(): Partial<Theme> {\r\n this.eatKeyword(\"theme\");\r\n this.eat(\"lcurly\");\r\n const t: Partial<Theme> = {};\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const keyTok = this.eatIdent();\r\n if (this.isType(\"colon\")) this.next();\r\n const resolved = resolveThemeKey(keyTok.value);\r\n if (!resolved) {\r\n this.diagnostics.push({\r\n severity: \"warning\",\r\n message: `Unknown theme key \"${keyTok.value}\"`,\r\n code: \"W_UNKNOWN_THEME_KEY\",\r\n span: { start: keyTok.start, end: keyTok.end },\r\n });\r\n if (this.isType(\"string\") || this.isType(\"number\")) this.next();\r\n else this.fail(`Expected a value for theme key \"${keyTok.value}\"`);\r\n continue;\r\n }\r\n if (isNumericThemeKey(resolved)) {\r\n (t as Record<string, unknown>)[resolved] = this.eatNumber();\r\n } else {\r\n (t as Record<string, unknown>)[resolved] = this.eatString();\r\n }\r\n }\r\n this.eat(\"rcurly\");\r\n return t;\r\n }\r\n\r\n private parseLet(): LetNode {\r\n const kw = this.eatKeyword(\"let\");\r\n const name = this.eatIdent().value;\r\n this.eat(\"equals\");\r\n const value = parseExprPratt(this.ctx);\r\n return { kind: \"let\", id: \"\", name, value, line: kw.line };\r\n }\r\n\r\n private parseInstance(): InstanceNode {\r\n const nameTok = this.eatIdent();\r\n this.eat(\"lparen\");\r\n const args: Expr[] = [];\r\n while (!this.isType(\"rparen\") && !this.isType(\"eof\")) {\r\n args.push(parseExprPratt(this.ctx));\r\n if (this.isType(\"comma\")) this.next();\r\n else break;\r\n }\r\n this.eat(\"rparen\");\r\n return { kind: \"instance\", id: \"\", name: nameTok.value, args, line: nameTok.line };\r\n }\r\n\r\n /** `component NAME(p1, p2, …) { <statements> }`. */\r\n private parseComponent(components: Map<string, ComponentDef>): ComponentDef {\r\n const kw = this.eatKeyword(\"component\");\r\n const name = this.eatIdent().value;\r\n this.eat(\"lparen\");\r\n const params: string[] = [];\r\n while (!this.isType(\"rparen\") && !this.isType(\"eof\")) {\r\n params.push(this.eatIdent().value);\r\n if (this.isType(\"comma\")) this.next();\r\n else break;\r\n }\r\n this.eat(\"rparen\");\r\n this.eat(\"lcurly\");\r\n const body: Statement[] = [];\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n const start = t.start;\r\n const def = registry.get(t.value);\r\n if (def) {\r\n const node = def.parse(this.ctx);\r\n node.span = this.spanFrom(start);\r\n body.push(node);\r\n continue;\r\n }\r\n if (t.value === \"let\") {\r\n const n = this.parseLet();\r\n n.span = this.spanFrom(start);\r\n body.push(n);\r\n continue;\r\n }\r\n // A previously-defined component (or this one, recursively) may be called.\r\n if ((components.has(t.value) || t.value === name) && this.peek(1).type === \"lparen\") {\r\n const n = this.parseInstance();\r\n n.span = this.spanFrom(start);\r\n body.push(n);\r\n continue;\r\n }\r\n this.fail(`Expected an element, \"let\", or component call in component body but found ${describe(t)}`, t);\r\n }\r\n this.eat(\"rcurly\");\r\n return { name, params, body, line: kw.line };\r\n }\r\n}\r\n\r\nfunction describe(t: Token): string {\r\n if (t.type === \"eof\") return \"end of input\";\r\n if (t.type === \"string\") return `string ${JSON.stringify(t.value)}`;\r\n return `\"${t.value}\"`;\r\n}\r\n","/**\r\n * Intermediate representation + `resolve(ast)`.\r\n *\r\n * `resolve` is the single place semantics live: it grid-snaps coordinates,\r\n * assigns ids, hosts openings, and runs semantic checks — producing a NEW\r\n * immutable IR (the input AST is never mutated). `render` consumes IR only.\r\n */\r\n\r\nimport type {\r\n AstElement,\r\n ComponentDef,\r\n ElementKind,\r\n ExprPoint,\r\n NorthDir,\r\n PlanNode,\r\n Point,\r\n Statement,\r\n TitleNode,\r\n} from \"./ast.js\";\r\nimport type { Diagnostic, Span } from \"./diagnostics.js\";\r\nimport type { Env, Expr } from \"./expr.js\";\r\nimport { closest, evalExpr } from \"./expr.js\";\r\nimport type { Theme } from \"./theme.js\";\r\nimport type { ResolveCtx } from \"./registry.js\";\r\nimport type { WallSegment } from \"./geometry.js\";\r\nimport { hostInfoForWalls } from \"./geometry.js\";\r\nimport { registryOrder } from \"./elements/index.js\";\r\n\r\nexport interface RBase {\r\n kind: ElementKind;\r\n id: string;\r\n span?: Span;\r\n}\r\n\r\nexport interface RWall extends RBase {\r\n kind: \"wall\";\r\n category: string;\r\n thickness: number;\r\n /** Resolved hatch material (always a known material; defaults to \"poche\"). */\r\n material: string;\r\n points: Point[];\r\n closed: boolean;\r\n}\r\nexport interface RRoom extends RBase {\r\n kind: \"room\";\r\n at: Point;\r\n size: { w: number; h: number };\r\n label?: string;\r\n}\r\nexport interface RDoor extends RBase {\r\n kind: \"door\";\r\n at: Point;\r\n width: number;\r\n hinge: \"left\" | \"right\";\r\n swing: \"in\" | \"out\";\r\n host: WallSegment | null;\r\n}\r\nexport interface RWindow extends RBase {\r\n kind: \"window\";\r\n at: Point;\r\n width: number;\r\n host: WallSegment | null;\r\n}\r\nexport interface RFurniture extends RBase {\r\n kind: \"furniture\";\r\n category: string;\r\n at: Point;\r\n size: { w: number; h: number };\r\n label?: string;\r\n}\r\nexport interface RDim extends RBase {\r\n kind: \"dim\";\r\n from: Point;\r\n to: Point;\r\n offset: number;\r\n text?: string;\r\n}\r\nexport interface RColumn extends RBase {\r\n kind: \"column\";\r\n at: Point;\r\n size: { w: number; h: number };\r\n}\r\n\r\nexport type ResolvedElement = RWall | RRoom | RDoor | RWindow | RFurniture | RDim | RColumn;\r\n\r\nexport interface ResolvedPlan {\r\n name: string;\r\n units: \"mm\";\r\n grid: number;\r\n scale?: string;\r\n north: NorthDir;\r\n title?: TitleNode;\r\n theme?: Partial<Theme>;\r\n /** Resolved elements, in source order (for rendering). */\r\n elements: ResolvedElement[];\r\n /** Resolved walls (for bounds/hosting), in source order. */\r\n walls: RWall[];\r\n}\r\n\r\n/** Max component-instantiation nesting depth before bailing out. */\r\nconst MAX_DEPTH = 64;\r\n\r\n/** An element flattened out of the body, paired with the env its exprs use. */\r\ninterface Entry {\r\n node: AstElement;\r\n env: Env;\r\n id: string;\r\n resolved?: ResolvedElement;\r\n}\r\n\r\n/**\r\n * Expand a statement list into a flat element stream: evaluate `let`s into the\r\n * scope env (source order, no forward refs), and inline component instances.\r\n *\r\n * Scoping is lexical with the plan as the global scope: a component body sees\r\n * the plan-level `let`s (`global`) plus its own params and local `let`s, but\r\n * NOT the caller's locals. `env` is this scope's env; at the top level it *is*\r\n * `global`, so top-level `let`s populate the global scope.\r\n */\r\nfunction expandScope(\r\n body: Statement[],\r\n env: Env,\r\n defined: Set<string>,\r\n global: Env,\r\n components: Map<string, ComponentDef>,\r\n diagnostics: Diagnostic[],\r\n depth: number,\r\n): Entry[] {\r\n const diag = (d: Diagnostic) => diagnostics.push(d);\r\n const out: Entry[] = [];\r\n\r\n for (const stmt of body) {\r\n if (stmt.kind === \"let\") {\r\n if (defined.has(stmt.name)) {\r\n diag({ severity: \"error\", message: `\"${stmt.name}\" is already defined in this scope`, code: \"E_REDEF\", span: stmt.span });\r\n continue;\r\n }\r\n env.set(stmt.name, evalExpr(stmt.value, env, diag));\r\n defined.add(stmt.name);\r\n } else if (stmt.kind === \"instance\") {\r\n const comp = components.get(stmt.name);\r\n if (!comp) {\r\n const hint = closest(stmt.name, [...components.keys()]);\r\n diag({ severity: \"error\", message: `Unknown component \"${stmt.name}\"`, code: \"E_UNKNOWN_COMPONENT\", span: stmt.span, hints: hint ? [`did you mean \"${hint}\"?`] : undefined });\r\n continue;\r\n }\r\n if (depth >= MAX_DEPTH) {\r\n diag({ severity: \"error\", message: `Component recursion too deep (limit ${MAX_DEPTH}) instantiating \"${stmt.name}\"`, code: \"E_RECURSION\", span: stmt.span });\r\n continue;\r\n }\r\n if (stmt.args.length !== comp.params.length) {\r\n diag({ severity: \"error\", message: `Component \"${stmt.name}\" expects ${comp.params.length} argument(s) but got ${stmt.args.length}`, code: \"E_ARGCOUNT\", span: stmt.span });\r\n }\r\n const argVals = comp.params.map((_, i) => (stmt.args[i] !== undefined ? evalExpr(stmt.args[i], env, diag) : 0));\r\n // Component scope = plan global + params; its lets are local.\r\n const childEnv: Env = new Map(global);\r\n const childDefined = new Set<string>();\r\n comp.params.forEach((p, i) => {\r\n childEnv.set(p, argVals[i]);\r\n childDefined.add(p);\r\n });\r\n out.push(...expandScope(comp.body, childEnv, childDefined, global, components, diagnostics, depth + 1));\r\n } else {\r\n out.push({ node: stmt, env: new Map(env), id: \"\" });\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nexport function resolve(ast: PlanNode): { ir: ResolvedPlan; diagnostics: Diagnostic[] } {\r\n const diagnostics: Diagnostic[] = [];\r\n const g = ast.grid;\r\n const snap = (v: number) => (g > 0 ? Math.round(v / g) * g : v);\r\n const snapPt = (p: Point): Point => ({ x: snap(p.x), y: snap(p.y) });\r\n\r\n // 0. Expand body (lets + component instantiation) into a flat element stream.\r\n // At the top level the scope env IS the global env (plan-level `let`s).\r\n const globalEnv: Env = new Map();\r\n const entries = expandScope(ast.body, globalEnv, new Set(), globalEnv, ast.components, diagnostics, 0);\r\n\r\n // 1. Assign ids in registry (canonical) order. The flat stream is numbered\r\n // globally per kind, so auto-ids stay unique across component instances.\r\n const seen = new Set<string>();\r\n const assignId = (provided: string, prefix: string, idx: number, span?: Span): string => {\r\n if (provided) {\r\n if (seen.has(provided)) {\r\n diagnostics.push({ severity: \"error\", message: `Duplicate id \"${provided}\"`, code: \"E_DUP_ID\", span });\r\n }\r\n seen.add(provided);\r\n return provided;\r\n }\r\n let auto = `${prefix}_${idx}`;\r\n while (seen.has(auto)) auto = `${auto}_`;\r\n seen.add(auto);\r\n return auto;\r\n };\r\n for (const def of registryOrder) {\r\n let idx = 0;\r\n for (const e of entries) {\r\n if (e.node.kind !== def.kind) continue;\r\n idx++;\r\n e.id = assignId(e.node.id, def.idPrefix(e.node), idx, e.node.span);\r\n }\r\n }\r\n\r\n // 2. Resolve in registry order (walls first → openings can host against them).\r\n // `activeEnv`/`activeId` are swapped per entry so each element evaluates\r\n // its expressions against the env captured during expansion.\r\n const walls: RWall[] = [];\r\n let activeEnv: Env = new Map();\r\n const evalNum = (e: Expr): number => evalExpr(e, activeEnv, (d) => diagnostics.push(d));\r\n const evalPt = (p: ExprPoint): Point => ({ x: evalNum(p.x), y: evalNum(p.y) });\r\n // Openings call isOnWall(at, ref) then hostSegment(at, ref) with identical\r\n // args back-to-back; a one-entry memo fuses those into a single wall scan.\r\n // walls is fully populated before any opening resolves (registry order:\r\n // walls first), so the cached info stays valid for the whole opening phase.\r\n let hiKey = \"\";\r\n let hiVal: { host: WallSegment | null; onWall: boolean } | null = null;\r\n const hostInfo = (at: Point, ref?: string) => {\r\n const key = `${at.x},${at.y},${ref ?? \"\"}`;\r\n if (key === hiKey && hiVal) return hiVal;\r\n hiKey = key;\r\n hiVal = hostInfoForWalls(walls, at, ref);\r\n return hiVal;\r\n };\r\n const ctx: ResolveCtx = {\r\n grid: g,\r\n snap,\r\n snapPt,\r\n eval: evalNum,\r\n evalPt,\r\n id: \"\",\r\n walls,\r\n hostSegment: (at, ref) => hostInfo(at, ref).host,\r\n isOnWall: (at, ref) => hostInfo(at, ref).onWall,\r\n diag: (d) => diagnostics.push(d),\r\n };\r\n for (const def of registryOrder) {\r\n for (const e of entries) {\r\n if (e.node.kind !== def.kind) continue;\r\n activeEnv = e.env;\r\n ctx.id = e.id;\r\n const r = def.resolve(e.node, ctx);\r\n e.resolved = r;\r\n if (r.kind === \"wall\") walls.push(r);\r\n }\r\n }\r\n\r\n // 3. IR element list in source order (for rendering).\r\n const elements = entries.map((e) => e.resolved!);\r\n\r\n // 4. Cross-element checks.\r\n const drawable = elements.some(\r\n (e) => e.kind === \"wall\" || e.kind === \"room\" || e.kind === \"furniture\" || e.kind === \"column\",\r\n );\r\n if (!drawable) {\r\n diagnostics.push({\r\n severity: \"warning\",\r\n message: \"Plan has no walls, rooms, or furniture — nothing to draw\",\r\n code: \"W_EMPTY_PLAN\",\r\n });\r\n }\r\n const rooms = elements.filter((e): e is RRoom => e.kind === \"room\");\r\n for (let a = 0; a < rooms.length; a++) {\r\n for (let b = a + 1; b < rooms.length; b++) {\r\n const r1 = rooms[a];\r\n const r2 = rooms[b];\r\n const ox = Math.max(0, Math.min(r1.at.x + r1.size.w, r2.at.x + r2.size.w) - Math.max(r1.at.x, r2.at.x));\r\n const oy = Math.max(0, Math.min(r1.at.y + r1.size.h, r2.at.y + r2.size.h) - Math.max(r1.at.y, r2.at.y));\r\n if (ox > 1 && oy > 1) {\r\n diagnostics.push({\r\n severity: \"warning\",\r\n message: `Rooms \"${r1.id}\" and \"${r2.id}\" overlap`,\r\n code: \"W_ROOM_OVERLAP\",\r\n span: r2.span,\r\n });\r\n }\r\n }\r\n }\r\n\r\n const ir: ResolvedPlan = {\r\n name: ast.name,\r\n units: ast.units,\r\n grid: ast.grid,\r\n scale: ast.scale,\r\n north: ast.north,\r\n title: ast.title,\r\n theme: ast.theme,\r\n elements,\r\n walls,\r\n };\r\n return { ir, diagnostics };\r\n}\r\n","/**\r\n * Boolean union of axis-aligned rectangles → boundary loops.\r\n *\r\n * Zero-dependency, synchronous, deterministic. Used to merge wall segment\r\n * rectangles into clean outlines so orthogonal corners and T-junctions render\r\n * with no internal seams. Angled walls (non-axis-aligned rectangles) are not\r\n * handled here — the renderer falls back to per-segment outlines for those.\r\n */\r\n\r\nimport type { Point } from \"../ast.js\";\r\n\r\nexport interface Rect {\r\n x0: number;\r\n y0: number;\r\n x1: number;\r\n y1: number;\r\n}\r\n\r\nfunction uniqSorted(values: number[]): number[] {\r\n const out = [...new Set(values)].sort((a, b) => a - b);\r\n return out;\r\n}\r\n\r\n/**\r\n * Outline loops of the union of axis-aligned rectangles. Each loop is a closed\r\n * rectilinear polygon (the closing point is implied, not repeated). Outer\r\n * boundaries and holes are both returned; render with `fill-rule: nonzero`.\r\n */\r\nexport function rectUnionOutline(rects: Rect[]): Point[][] {\r\n if (rects.length === 0) return [];\r\n const xs = uniqSorted(rects.flatMap((r) => [r.x0, r.x1]));\r\n const ys = uniqSorted(rects.flatMap((r) => [r.y0, r.y1]));\r\n const nx = xs.length - 1;\r\n const ny = ys.length - 1;\r\n\r\n const filled = (i: number, j: number): boolean => {\r\n if (i < 0 || j < 0 || i >= nx || j >= ny) return false;\r\n const cx = (xs[i] + xs[i + 1]) / 2;\r\n const cy = (ys[j] + ys[j + 1]) / 2;\r\n return rects.some((r) => cx > r.x0 && cx < r.x1 && cy > r.y0 && cy < r.y1);\r\n };\r\n\r\n // Directed boundary edges, emitted per filled cell so the filled region is\r\n // consistently on one side (CCW per cell). Key by start point.\r\n const key = (x: number, y: number) => `${x},${y}`;\r\n const starts = new Map<string, Point[]>();\r\n const pushEdge = (ax: number, ay: number, bx: number, by: number) => {\r\n const k = key(ax, ay);\r\n const list = starts.get(k);\r\n if (list) list.push({ x: bx, y: by });\r\n else starts.set(k, [{ x: bx, y: by }]);\r\n };\r\n\r\n for (let i = 0; i < nx; i++) {\r\n for (let j = 0; j < ny; j++) {\r\n if (!filled(i, j)) continue;\r\n const x0 = xs[i];\r\n const x1 = xs[i + 1];\r\n const y0 = ys[j];\r\n const y1 = ys[j + 1];\r\n if (!filled(i, j - 1)) pushEdge(x1, y0, x0, y0); // top: right → left\r\n if (!filled(i - 1, j)) pushEdge(x0, y0, x0, y1); // left: top → bottom\r\n if (!filled(i, j + 1)) pushEdge(x0, y1, x1, y1); // bottom: left → right\r\n if (!filled(i + 1, j)) pushEdge(x1, y1, x1, y0); // right: bottom → top\r\n }\r\n }\r\n\r\n // Walk the directed edges into closed loops. At a vertex with two outgoing\r\n // edges (a pinch point), prefer the one that turns left, keeping loops simple.\r\n const used = new Set<string>();\r\n const edgeKey = (a: Point, b: Point) => `${a.x},${a.y}->${b.x},${b.y}`;\r\n const loops: Point[][] = [];\r\n\r\n const takeNext = (from: Point, prevDir: { x: number; y: number } | null): Point | null => {\r\n const list = starts.get(key(from.x, from.y));\r\n if (!list) return null;\r\n const candidates = list.filter((to) => !used.has(edgeKey(from, to)));\r\n if (candidates.length === 0) return null;\r\n if (candidates.length === 1 || !prevDir) return candidates[0];\r\n // Prefer the left-most turn (cross product > 0 in y-down screen space).\r\n let best = candidates[0];\r\n let bestScore = -Infinity;\r\n for (const c of candidates) {\r\n const dir = { x: c.x - from.x, y: c.y - from.y };\r\n const cross = prevDir.x * dir.y - prevDir.y * dir.x;\r\n if (cross > bestScore) {\r\n bestScore = cross;\r\n best = c;\r\n }\r\n }\r\n return best;\r\n };\r\n\r\n for (const [startKey, ends] of starts) {\r\n for (const firstEnd of ends) {\r\n const [sx, sy] = startKey.split(\",\").map(Number);\r\n const start: Point = { x: sx, y: sy };\r\n if (used.has(edgeKey(start, firstEnd))) continue;\r\n const loop: Point[] = [start];\r\n let cur = start;\r\n let next: Point | null = firstEnd;\r\n let dir: { x: number; y: number } | null = null;\r\n while (next) {\r\n used.add(edgeKey(cur, next));\r\n if (next.x === start.x && next.y === start.y) break;\r\n loop.push(next);\r\n dir = { x: next.x - cur.x, y: next.y - cur.y };\r\n cur = next;\r\n next = takeNext(cur, dir);\r\n }\r\n if (loop.length >= 4) loops.push(mergeCollinear(loop));\r\n }\r\n }\r\n return loops;\r\n}\r\n\r\n/** Drop interior vertices that lie on a straight run. */\r\nfunction mergeCollinear(loop: Point[]): Point[] {\r\n const n = loop.length;\r\n const out: Point[] = [];\r\n for (let i = 0; i < n; i++) {\r\n const prev = loop[(i - 1 + n) % n];\r\n const cur = loop[i];\r\n const next = loop[(i + 1) % n];\r\n const d1x = cur.x - prev.x;\r\n const d1y = cur.y - prev.y;\r\n const d2x = next.x - cur.x;\r\n const d2y = next.y - cur.y;\r\n // Keep the vertex only if direction changes (cross product non-zero).\r\n if (d1x * d2y - d1y * d2x !== 0) out.push(cur);\r\n }\r\n return out.length >= 3 ? out : loop;\r\n}\r\n","/**\n * Lowers a resolved plan (IR) to the backend-neutral {@link Scene}.\n *\n * This is the single place geometry is assembled: each element contributes\n * positioned primitives via its registry `render`, walls are unioned/offset here\n * (the only element needing cross-segment treatment), and the page-level sizing\n * (reference dimension, derived font/stroke sizes, bounds) is computed once and\n * carried on the Scene for the backends. Pure & deterministic — no I/O, no time.\n */\n\nimport type { CompileOptions } from \"./types.js\";\nimport type { ResolvedPlan, RWall } from \"./ir.js\";\nimport type { RenderCtx } from \"./registry.js\";\nimport type { RenderSizes, Scene, SceneNode } from \"./scene.js\";\nimport { registry } from \"./elements/index.js\";\nimport type { Bounds } from \"./geometry.js\";\nimport { emptyBounds, extendBounds, segmentRectangle, segmentsOfWall } from \"./geometry.js\";\nimport type { Rect } from \"./geometry/union.js\";\nimport { rectUnionOutline } from \"./geometry/union.js\";\nimport { patternId } from \"./hatches.js\";\nimport { DEFAULT_THEME, mergeTheme, sanitizeTheme } from \"./theme.js\";\n\n/** Drawing bounds: each element contributes points via its registry `bounds`. */\nfunction planBounds(ir: ResolvedPlan): Bounds {\n const b = emptyBounds();\n for (const el of ir.elements) {\n const def = registry.get(el.kind);\n if (!def) continue;\n for (const p of def.bounds(el)) extendBounds(b, p.x, p.y);\n }\n if (!isFinite(b.minX)) {\n // Nothing to draw; provide a default frame.\n return { minX: 0, minY: 0, maxX: 1000, maxY: 1000 };\n }\n return b;\n}\n\n/** Is every segment of every wall axis-aligned (horizontal or vertical)? */\nfunction allOrthogonal(walls: RWall[]): boolean {\n return walls.every((w) => segmentsOfWall(w).every((s) => s.a.x === s.b.x || s.a.y === s.b.y));\n}\n\n/** Distinct wall materials present, in a stable (sorted) order. */\nfunction materialsUsed(walls: RWall[]): string[] {\n return [...new Set(walls.map((w) => w.material))].sort();\n}\n\n/**\n * Wall fill + outline, grouped by material so each material's poché unions\n * independently. Orthogonal groups become a single multi-loop `region` (clean\n * boundaries, no internal seams); angled groups fall back to the wall element's\n * per-segment primitives.\n */\nfunction lowerWalls(walls: RWall[], ctx: RenderCtx): SceneNode[] {\n if (walls.length === 0) return [];\n const nodes: SceneNode[] = [];\n for (const mat of materialsUsed(walls)) {\n const group = walls.filter((w) => w.material === mat);\n if (!allOrthogonal(group)) {\n const def = registry.get(\"wall\")!;\n nodes.push(...group.flatMap((w) => def.render(w, ctx)));\n continue;\n }\n const rects: Rect[] = [];\n for (const w of group) {\n for (const s of segmentsOfWall(w)) {\n const corners = segmentRectangle(s.a, s.b, s.thickness);\n const xsv = corners.map((c) => c.x);\n const ysv = corners.map((c) => c.y);\n rects.push({ x0: Math.min(...xsv), y0: Math.min(...ysv), x1: Math.max(...xsv), y1: Math.max(...ysv) });\n }\n }\n const loops = rectUnionOutline(rects);\n if (loops.length === 0) continue;\n nodes.push({ layer: \"wallFill\", prim: { t: \"region\", loops }, paint: { fill: `url(#${patternId(mat)})`, fillRule: \"nonzero\" } });\n nodes.push({\n layer: \"wallFace\",\n prim: { t: \"region\", loops },\n paint: { fill: \"none\", stroke: ctx.theme.wallStroke, width: ctx.sizes.wallStroke, linejoin: \"miter\" },\n });\n }\n return nodes;\n}\n\n/**\n * Build the {@link Scene} for a resolved plan. The theme is merged + sanitized\n * once here and baked into node paint; it is also carried on the Scene for the\n * page chrome (north/scale/title). `opts.width` does not affect the Scene (it is\n * an SVG-only attribute) — only `opts.theme` participates.\n */\nexport function toScene(ir: ResolvedPlan, opts: CompileOptions = {}): Scene {\n const theme = sanitizeTheme(mergeTheme(DEFAULT_THEME, ir.theme, opts.theme));\n const lw = theme.lineWeight;\n\n const b = planBounds(ir);\n const drawW = b.maxX - b.minX;\n const drawH = b.maxY - b.minY;\n const refDim = Math.max(drawW, drawH, 1);\n\n const sizes: RenderSizes = {\n refDim,\n wallStroke: refDim * 0.0028 * lw,\n thin: refDim * 0.0016 * lw,\n roomFont: refDim * 0.03,\n areaFont: refDim * 0.022,\n dimFont: refDim * 0.02,\n furnFont: refDim * 0.017,\n margin: refDim * 0.17,\n hatchGap: refDim * 0.013,\n };\n\n // Collect non-wall elements (source order), then lower walls — exactly the v0.1\n // op order, so layer-bucketing in a backend reproduces the original draw order.\n const ctx: RenderCtx = { theme, sizes, bounds: b };\n const nodes: SceneNode[] = [];\n for (const el of ir.elements) {\n if (el.kind === \"wall\") continue;\n const def = registry.get(el.kind);\n if (def) nodes.push(...def.render(el, ctx));\n }\n nodes.push(...lowerWalls(ir.walls, ctx));\n\n return {\n width: drawW + sizes.margin * 2,\n height: drawH + sizes.margin * 2,\n bounds: b,\n nodes,\n theme,\n sizes,\n north: ir.north,\n scale: ir.scale,\n title: ir.title,\n name: ir.name,\n materials: materialsUsed(ir.walls),\n };\n}\n","/**\n * Backend-neutral **Scene IR** — the keystone drawing intermediate.\n *\n * `resolve()` produces semantic geometry (rooms, walls, openings); this module\n * defines a flat list of *positioned drawing primitives* tagged with a layer and\n * paint. Geometry is computed exactly **once** here (by the elements, lowered via\n * `scene-build.ts`); every backend (SVG, DXF, PDF, …) is then a thin, pure\n * serializer of the same `Scene`. This kills the geometry duplication the\n * string-based `RenderOp` forced (DXF re-deriving door arcs, PDF rasterizing SVG).\n *\n * Prior art: Typst's `Frame`/`FrameItem` (crates/typst-library/src/layout/frame.rs)\n * — a positioned list of drawable items — and D2's `d2target` (a flat, pointer-free\n * render target consumed by independent backends). ArchLang has no nested\n * transforms, so unlike Typst's `Frame` the node list is flat (no sub-frames).\n *\n * Phase v0.7 keeps this deliberately small: line-weight/line-type/named-layer\n * metadata, hatch primitives, and circles are intentionally deferred to Phase v0.9\n * (roadmap §6). Poché stays an SVG `<pattern>` fill string; page chrome (north\n * arrow, scale bar, title block) stays in the backends for now.\n */\n\nimport type { NorthDir, Point, TitleNode } from \"./ast.js\";\nimport type { Span } from \"./diagnostics.js\";\nimport type { Bounds } from \"./geometry.js\";\nimport type { Theme } from \"./theme.js\";\n\n/**\n * Ordered draw layers. Nodes are bucketed by `layer` and emitted in this order,\n * preserving collection order within a layer — this exactly reproduces the v0.1\n * global draw order (all wall fills, then all wall faces, doors before windows,\n * labels above fills, …). Doubles as the discriminant of {@link SceneNode.layer}.\n */\nexport const RENDER_PASSES = [\n \"floor\",\n \"furniture\",\n \"wallFill\",\n \"wallFace\",\n \"doors\",\n \"windows\",\n \"labels\",\n \"dims\",\n \"annotations\",\n] as const;\nexport type RenderPass = (typeof RENDER_PASSES)[number];\n\n/** Render-derived sizes (in mm), scaled from the drawing's reference dimension. */\nexport interface RenderSizes {\n refDim: number;\n wallStroke: number;\n thin: number;\n roomFont: number;\n areaFont: number;\n dimFont: number;\n furnFont: number;\n margin: number;\n hatchGap: number;\n}\n\n/**\n * How a primitive is painted. Strokes/fills carry colours (already theme-resolved\n * and escaped at the serialization boundary); `width`/`dash` carry *raw* numbers\n * that each backend formats. The optional `linecap`/`linejoin`/`fillRule` cover\n * the exact SVG attributes the original element emitters used, so the SVG\n * serializer reproduces today's output byte-for-byte.\n */\nexport interface Paint {\n /** A colour, `\"none\"`, or an SVG pattern ref like `\"url(#poche)\"`. */\n fill?: string;\n stroke?: string;\n /** Raw stroke width in mm (backend applies its own number formatting). */\n width?: number;\n /** `stroke-dasharray` pair in mm (e.g. door swing arc). */\n dash?: [number, number];\n linecap?: \"square\";\n linejoin?: \"miter\";\n fillRule?: \"nonzero\";\n}\n\n/**\n * A positioned drawing primitive. Coordinates are absolute millimetres in the\n * plan's space (origin top-left, +x right, +y down — SVG convention); backends\n * apply their own transforms (e.g. DXF's Y-flip).\n */\nexport type ScenePrim =\n /** A filled/stroked closed polygon (room, furniture, column, opening cover, per-segment wall fill). */\n | { t: \"polygon\"; pts: Point[] }\n /** A single straight segment (wall face, door leaf, window pane, dimension lines/ticks). */\n | { t: \"line\"; a: Point; b: Point }\n /**\n * A multi-loop closed region drawn as one path (`fill-rule` nonzero), used for\n * unioned orthogonal walls so the poché fills with proper holes and the outline\n * has no internal seams.\n */\n | { t: \"region\"; loops: Point[][] }\n /**\n * A circular arc (door swing). Carries the `center`/`r` a CAD backend needs to\n * emit a native arc, plus the explicit `start`/`end` points + `sweep` flag an\n * SVG `A` command needs — so neither backend re-derives endpoints from trig.\n */\n | { t: \"arc\"; center: Point; r: number; start: Point; end: Point; sweep: 0 | 1 }\n /** A text label. `value` is the raw (unescaped) string; backends escape on emit. */\n | {\n t: \"text\";\n at: Point;\n value: string;\n size: number;\n anchor: \"start\" | \"middle\" | \"end\";\n baseline: \"central\";\n /** SVG `font-weight` (e.g. 600 for a room name). */\n weight?: number;\n /** Rotation in degrees about `at` (e.g. dimension text along its line). */\n rotate?: number;\n };\n\n/** One drawable: a primitive on a layer, with paint and an optional source span. */\nexport interface SceneNode {\n layer: RenderPass;\n prim: ScenePrim;\n paint: Paint;\n span?: Span;\n}\n\n/**\n * A complete, backend-neutral drawing. `nodes` is the geometry; the remaining\n * fields are the page-level context backends need (viewBox sizing, theme colours\n * for chrome, north/scale/title block, hatch materials in use). Theme is baked\n * into node paint already — it is carried here only for the page chrome.\n */\nexport interface Scene {\n /** Padded page width/height in mm (drawing extent + annotation margin). */\n width: number;\n height: number;\n /** Tight drawing bounds (before margin), for chrome placement. */\n bounds: Bounds;\n nodes: SceneNode[];\n theme: Theme;\n sizes: RenderSizes;\n north: NorthDir;\n scale?: string;\n title?: TitleNode;\n name: string;\n /** Distinct wall materials in use (stable order), so the SVG backend can emit hatch `<pattern>`s. */\n materials: string[];\n}\n","/**\n * SVG backend — a pure serializer of the {@link Scene}.\n *\n * Each `ScenePrim` maps to one SVG element; attributes are emitted in a fixed\n * canonical order so the output is byte-identical to the original string-based\n * renderer (the golden-snapshot regression guard). Page chrome (background,\n * hatch `<pattern>` defs, north arrow, scale bar, title block) lives here — it is\n * SVG-specific framing, not element geometry. Deterministic: all numbers route\n * through {@link fmt}; all interpolated text is escaped via {@link xml}.\n */\n\nimport type { NorthDir, Point, TitleNode } from \"../ast.js\";\nimport type { CompileOptions } from \"../types.js\";\nimport type { Paint, Scene, SceneNode } from \"../scene.js\";\nimport { RENDER_PASSES } from \"../scene.js\";\nimport type { Bounds } from \"../geometry.js\";\nimport type { Material } from \"../hatches.js\";\nimport { hatchPattern } from \"../hatches.js\";\nimport type { Theme } from \"../theme.js\";\n\n/** Round to 2 decimals and strip trailing zeros — keeps output stable & compact. */\nfunction fmt(v: number): string {\n const r = Math.round(v * 100) / 100;\n return Object.is(r, -0) ? \"0\" : String(r);\n}\nconst pt = (p: Point): string => `${fmt(p.x)},${fmt(p.y)}`;\n\nfunction xml(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nconst NICE_LENGTHS = [500, 1000, 2000, 5000, 10000, 20000, 50000, 100000];\nfunction niceBarLength(target: number): number {\n let best = NICE_LENGTHS[0];\n for (const v of NICE_LENGTHS) if (v <= target) best = v;\n return best;\n}\n\n/** Stroke attributes shared by `polygon`/`line` (omitted entirely when no stroke). */\nfunction strokeAttrs(paint: Paint): string {\n if (!paint.stroke) return \"\";\n let s = ` stroke=\"${paint.stroke}\" stroke-width=\"${fmt(paint.width ?? 0)}\"`;\n if (paint.linecap) s += ` stroke-linecap=\"${paint.linecap}\"`;\n return s;\n}\n\n/** Paint attributes for a `<path>` (region/arc), in the canonical attribute order. */\nfunction pathPaint(paint: Paint): string {\n let s = ` fill=\"${paint.fill ?? \"none\"}\"`;\n if (paint.fillRule) s += ` fill-rule=\"${paint.fillRule}\"`;\n if (paint.stroke) s += ` stroke=\"${paint.stroke}\" stroke-width=\"${fmt(paint.width ?? 0)}\"`;\n if (paint.linejoin) s += ` stroke-linejoin=\"${paint.linejoin}\"`;\n if (paint.dash) s += ` stroke-dasharray=\"${fmt(paint.dash[0])} ${fmt(paint.dash[1])}\"`;\n return s;\n}\n\nfunction regionPath(loops: Point[][]): string {\n return loops.map((loop) => \"M \" + loop.map(pt).join(\" L \") + \" Z\").join(\" \");\n}\n\n/** Serialize one scene node to a single SVG element string. */\nfunction serialize(node: SceneNode): string {\n const { prim, paint } = node;\n switch (prim.t) {\n case \"polygon\":\n return `<polygon points=\"${prim.pts.map(pt).join(\" \")}\" fill=\"${paint.fill ?? \"none\"}\"${strokeAttrs(paint)}/>`;\n case \"line\":\n return `<line x1=\"${fmt(prim.a.x)}\" y1=\"${fmt(prim.a.y)}\" x2=\"${fmt(prim.b.x)}\" y2=\"${fmt(prim.b.y)}\" stroke=\"${paint.stroke ?? \"none\"}\" stroke-width=\"${fmt(paint.width ?? 0)}\"${paint.linecap ? ` stroke-linecap=\"${paint.linecap}\"` : \"\"}/>`;\n case \"region\":\n return `<path d=\"${regionPath(prim.loops)}\"${pathPaint(paint)}/>`;\n case \"arc\":\n return `<path d=\"M ${pt(prim.start)} A ${fmt(prim.r)} ${fmt(prim.r)} 0 0 ${prim.sweep} ${pt(prim.end)}\"${pathPaint(paint)}/>`;\n case \"text\": {\n const weight = prim.weight !== undefined ? ` font-weight=\"${prim.weight}\"` : \"\";\n const transform = prim.rotate !== undefined ? ` transform=\"rotate(${fmt(prim.rotate)} ${fmt(prim.at.x)} ${fmt(prim.at.y)})\"` : \"\";\n return `<text x=\"${fmt(prim.at.x)}\" y=\"${fmt(prim.at.y)}\" font-size=\"${fmt(prim.size)}\" fill=\"${paint.fill ?? \"none\"}\" text-anchor=\"${prim.anchor}\" dominant-baseline=\"${prim.baseline}\"${weight}${transform}>${xml(prim.value)}</text>`;\n }\n }\n}\n\n/** Serialize a {@link Scene} to a complete SVG document. */\nexport function renderSvg(scene: Scene, opts: CompileOptions = {}): string {\n const THEME = scene.theme;\n const sizes = scene.sizes;\n const b = scene.bounds;\n const refDim = sizes.refDim;\n const { thin, margin, hatchGap } = sizes;\n\n const drawW = b.maxX - b.minX;\n const drawH = b.maxY - b.minY;\n const vbX = b.minX - margin;\n const vbY = b.minY - margin;\n const vbW = drawW + margin * 2;\n const vbH = drawH + margin * 2;\n\n const out: string[] = [];\n const svgAttrs = opts.width\n ? `width=\"${fmt(opts.width)}\" height=\"${fmt((opts.width * vbH) / vbW)}\"`\n : \"\";\n out.push(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" ${svgAttrs} viewBox=\"${fmt(vbX)} ${fmt(vbY)} ${fmt(vbW)} ${fmt(vbH)}\" font-family=\"${THEME.font}\">`,\n );\n\n // Defs: a hatch <pattern> for each wall material in use (default → \"poche\").\n const hatchCtx = { fmt, gap: hatchGap, thin, base: THEME.pocheBase, line: THEME.pocheHatch };\n const patterns = scene.materials.map((m) => hatchPattern(m as Material, hatchCtx)).join(\"\");\n out.push(`<defs>${patterns}</defs>`);\n\n // Background\n out.push(`<rect x=\"${fmt(vbX)}\" y=\"${fmt(vbY)}\" width=\"${fmt(vbW)}\" height=\"${fmt(vbH)}\" fill=\"${THEME.bg}\"/>`);\n\n // Element/wall primitives, bucketed by layer (deterministic draw order).\n for (const pass of RENDER_PASSES) {\n for (const node of scene.nodes) if (node.layer === pass) out.push(serialize(node));\n }\n\n // Plan-level annotations (after element passes): north, scale bar, title block.\n out.push(northArrow(scene.north, b, margin, refDim, THEME));\n out.push(scaleBar(b, margin, refDim, thin, THEME));\n const tb = titleBlock(scene.title, scene.scale, b, margin, refDim, thin, THEME);\n if (tb) out.push(tb);\n\n out.push(\"</svg>\");\n return out.join(\"\\n\");\n}\n\nfunction northArrow(north: NorthDir, b: Bounds, margin: number, refDim: number, THEME: Theme): string {\n const r = refDim * 0.045;\n const cx = b.maxX - r;\n const cy = b.minY - margin * 0.55;\n let deg: number;\n switch (north) {\n case \"up\": deg = 0; break;\n case \"down\": deg = 180; break;\n case \"left\": deg = 270; break;\n case \"right\": deg = 90; break;\n default: deg = typeof north === \"object\" ? north.deg : 0;\n }\n const fs = refDim * 0.026;\n // Triangle points \"up\" before rotation; only the arrow rotates — the \"N\"\n // label stays upright at the pointing end so it always reads correctly.\n const tri = `${fmt(cx)},${fmt(cy - r)} ${fmt(cx - r * 0.5)},${fmt(cy + r * 0.6)} ${fmt(cx)},${fmt(cy + r * 0.25)} ${fmt(cx + r * 0.5)},${fmt(cy + r * 0.6)}`;\n const rad = (deg * Math.PI) / 180;\n // North screen vector (rotate the \"up\" vector (0,-1) clockwise by deg).\n const nx = Math.sin(rad);\n const ny = -Math.cos(rad);\n const lx = cx + nx * (r + fs * 0.8);\n const ly = cy + ny * (r + fs * 0.8);\n return (\n `<g>` +\n `<polygon points=\"${tri}\" fill=\"${THEME.annotation}\" transform=\"rotate(${fmt(deg)} ${fmt(cx)} ${fmt(cy)})\"/>` +\n `<text x=\"${fmt(lx)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"middle\" dominant-baseline=\"central\">N</text>` +\n `</g>`\n );\n}\n\nfunction scaleBar(b: Bounds, margin: number, refDim: number, thin: number, THEME: Theme): string {\n const barLen = niceBarLength(refDim * 0.3);\n const x0 = b.minX;\n const y0 = b.maxY + margin * 0.55;\n const hgt = refDim * 0.014;\n const fs = refDim * 0.02;\n const parts: string[] = [];\n const half = barLen / 2;\n // two-segment alternating bar\n parts.push(`<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"${THEME.annotation}\"/>`);\n parts.push(\n `<rect x=\"${fmt(x0 + half)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\n );\n parts.push(\n `<text x=\"${fmt(x0)}\" y=\"${fmt(y0 + hgt + fs)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"start\" dominant-baseline=\"central\">0</text>`,\n );\n parts.push(\n `<text x=\"${fmt(x0 + barLen)}\" y=\"${fmt(y0 + hgt + fs)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"middle\" dominant-baseline=\"central\">${barLen / 1000} m</text>`,\n );\n return `<g>${parts.join(\"\")}</g>`;\n}\n\nfunction titleBlock(t: TitleNode | undefined, scale: string | undefined, b: Bounds, margin: number, refDim: number, thin: number, THEME: Theme): string | null {\n if (!t && !scale) return null;\n const boxW = refDim * 0.34;\n const boxH = margin * 0.82;\n const x0 = b.maxX - boxW;\n const y0 = b.maxY + margin * 0.15;\n const fs = refDim * 0.019;\n const pad = boxW * 0.05;\n const lines: { k: string; v: string }[] = [];\n if (t?.project) lines.push({ k: \"PROJECT\", v: t.project });\n if (t?.drawnBy) lines.push({ k: \"DRAWN BY\", v: t.drawnBy });\n if (t?.date) lines.push({ k: \"DATE\", v: t.date });\n if (scale) lines.push({ k: \"SCALE\", v: scale });\n\n const parts: string[] = [];\n parts.push(\n `<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(boxW)}\" height=\"${fmt(boxH)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\n );\n const rowH = boxH / Math.max(lines.length, 1);\n lines.forEach((ln, i) => {\n const ly = y0 + rowH * (i + 0.5);\n parts.push(\n `<text x=\"${fmt(x0 + pad)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs * 0.8)}\" fill=\"${THEME.annotationMuted}\" dominant-baseline=\"central\">${xml(ln.k)}</text>`,\n );\n parts.push(\n `<text x=\"${fmt(x0 + boxW - pad)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"end\" dominant-baseline=\"central\">${xml(ln.v)}</text>`,\n );\n if (i > 0)\n parts.push(\n `<line x1=\"${fmt(x0)}\" y1=\"${fmt(y0 + rowH * i)}\" x2=\"${fmt(x0 + boxW)}\" y2=\"${fmt(y0 + rowH * i)}\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin * 0.5)}\"/>`,\n );\n });\n return `<g>${parts.join(\"\")}</g>`;\n}\n","/**\r\n * Diagnostics for the ArchLang compiler.\r\n *\r\n * A {@link Diagnostic} is the single, span-carrying problem record produced by\r\n * every compiler stage (lex/parse/validate). The legacy `{message, line, col}`\r\n * `errors`/`warnings` arrays on {@link import(\"./types.js\").CompileResult} are\r\n * *derived* from these. {@link formatDiagnostic} renders a codespan-style,\r\n * caret-framed snippet — zero dependencies, pure, isomorphic.\r\n */\r\n\r\n/** A half-open byte range `[start, end)` into the source string. */\r\nexport interface Span {\r\n start: number;\r\n end: number;\r\n}\r\n\r\nexport type Severity = \"error\" | \"warning\";\r\n\r\nexport interface Diagnostic {\r\n severity: Severity;\r\n message: string;\r\n /** Source location; absent for whole-program problems (e.g. an empty plan). */\r\n span?: Span;\r\n /** Stable machine code, e.g. `\"E_ROOM_SIZE\"`. */\r\n code?: string;\r\n /** Optional follow-up suggestions, each rendered as a `= help:` line. */\r\n hints?: string[];\r\n}\r\n\r\n/** Convert a byte offset into a 1-based `{line, col}`. Offsets are clamped. */\r\nexport function offsetToLineCol(source: string, offset: number): { line: number; col: number } {\r\n const o = Math.max(0, Math.min(offset, source.length));\r\n let line = 1;\r\n let col = 1;\r\n for (let k = 0; k < o; k++) {\r\n if (source[k] === \"\\n\") {\r\n line++;\r\n col = 1;\r\n } else {\r\n col++;\r\n }\r\n }\r\n return { line, col };\r\n}\r\n\r\n/** Byte offset of the start of the line containing `offset`. */\r\nfunction lineStart(source: string, offset: number): number {\r\n let k = Math.max(0, Math.min(offset, source.length));\r\n while (k > 0 && source[k - 1] !== \"\\n\") k--;\r\n return k;\r\n}\r\n\r\n/** Byte offset just past the end of the line containing `offset` (excludes `\\n`). */\r\nfunction lineEnd(source: string, offset: number): number {\r\n let k = Math.max(0, Math.min(offset, source.length));\r\n while (k < source.length && source[k] !== \"\\n\") k++;\r\n return k;\r\n}\r\n\r\n/**\r\n * Render a diagnostic as a framed source snippet:\r\n *\r\n * ```text\r\n * error[E_ROOM_SIZE]: room \"bed\" must have a positive size\r\n * --> 4:30\r\n * |\r\n * 4 | room id=bed at (0,0) size 0x4000\r\n * | ^^^^^^ width is 0\r\n * = help: did you mean 3000x4000?\r\n * ```\r\n *\r\n * With no `span`, only the header line is produced.\r\n */\r\nexport function formatDiagnostic(source: string, d: Diagnostic): string {\r\n const codeTag = d.code ? `[${d.code}]` : \"\";\r\n const header = `${d.severity}${codeTag}: ${d.message}`;\r\n const lines: string[] = [header];\r\n\r\n if (d.span) {\r\n const { line, col } = offsetToLineCol(source, d.span.start);\r\n const ls = lineStart(source, d.span.start);\r\n const le = lineEnd(source, d.span.start);\r\n const srcLine = source.slice(ls, le);\r\n // Underline within this one line; multi-line spans underline to line end.\r\n const caretStart = d.span.start - ls;\r\n const caretEnd = Math.min(d.span.end, le) - ls;\r\n const caretLen = Math.max(1, caretEnd - caretStart);\r\n\r\n const gutter = String(line);\r\n const pad = \" \".repeat(gutter.length);\r\n lines.push(`${pad} --> ${line}:${col}`);\r\n lines.push(`${pad} |`);\r\n lines.push(`${gutter} | ${srcLine}`);\r\n lines.push(`${pad} | ${\" \".repeat(caretStart)}${\"^\".repeat(caretLen)}`);\r\n for (const hint of d.hints ?? []) {\r\n lines.push(`${pad} = help: ${hint}`);\r\n }\r\n } else {\r\n for (const hint of d.hints ?? []) {\r\n lines.push(` = help: ${hint}`);\r\n }\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","/**\n * DXF export backend — a pure serializer of the {@link Scene}. Emits ASCII DXF\n * (R12 / AC1009, the most broadly importable flavor). Pure, synchronous,\n * zero-dep: DXF is plain text, so this needs no external library and ships in the\n * core. Build a Scene with `toScene(resolve(ast).ir)` (or `compile().scene`).\n *\n * As of v0.7 the geometry is NOT re-derived here: door arcs, window panes, and\n * dimension ticks are the very `ScenePrim`s the elements produced. Each primitive\n * maps generically to a DXF entity; the only element-aware step is mapping a draw\n * layer to a DXF layer name. DXF's Y axis points up while ArchLang's points down,\n * so every Y is negated to keep plans right-side-up in CAD.\n */\n\nimport type { Point } from \"../ast.js\";\nimport type { RenderPass, Scene, SceneNode } from \"../scene.js\";\nimport { minorArcDegrees } from \"../geometry.js\";\n\n/** Deterministic number formatting (round to 4dp, no -0). */\nfunction num(v: number): string {\n const r = Math.round(v * 1e4) / 1e4;\n return Object.is(r, -0) ? \"0\" : String(r);\n}\n\nclass DxfBuilder {\n private out: string[] = [];\n\n /** group-code / value pair. */\n pair(code: number, value: string | number): void {\n this.out.push(String(code), String(value));\n }\n\n line(layer: string, a: Point, b: Point): void {\n this.pair(0, \"LINE\");\n this.pair(8, layer);\n this.pair(10, num(a.x));\n this.pair(20, num(-a.y));\n this.pair(11, num(b.x));\n this.pair(21, num(-b.y));\n }\n\n arc(layer: string, center: Point, radius: number, startDeg: number, endDeg: number): void {\n this.pair(0, \"ARC\");\n this.pair(8, layer);\n this.pair(10, num(center.x));\n this.pair(20, num(-center.y));\n this.pair(40, num(radius));\n this.pair(50, num(startDeg));\n this.pair(51, num(endDeg));\n }\n\n text(layer: string, at: Point, height: number, value: string): void {\n this.pair(0, \"TEXT\");\n this.pair(8, layer);\n this.pair(10, num(at.x));\n this.pair(20, num(-at.y));\n this.pair(40, num(height));\n this.pair(1, value.replace(/\\n/g, \" \"));\n }\n\n /** Closed loop of points as a chain of LINEs (R12-safe; no LWPOLYLINE). */\n loop(layer: string, pts: Point[]): void {\n for (let i = 0; i < pts.length; i++) {\n this.line(layer, pts[i], pts[(i + 1) % pts.length]);\n }\n }\n\n toString(): string {\n return this.out.join(\"\\n\") + \"\\n\";\n }\n}\n\nconst LAYERS = [\"WALLS\", \"ROOMS\", \"DOORS\", \"WINDOWS\", \"FURNITURE\", \"COLUMNS\", \"DIMS\", \"LABELS\"];\n\n/** Map a Scene draw layer to a DXF layer name. */\nfunction dxfLayer(layer: RenderPass): string {\n switch (layer) {\n case \"wallFill\":\n case \"wallFace\":\n return \"WALLS\";\n case \"floor\":\n return \"ROOMS\";\n case \"doors\":\n return \"DOORS\";\n case \"windows\":\n return \"WINDOWS\";\n case \"furniture\":\n return \"FURNITURE\";\n case \"labels\":\n return \"LABELS\";\n case \"dims\":\n return \"DIMS\";\n default:\n return \"0\";\n }\n}\n\nfunction header(): string {\n const h: string[] = [];\n const p = (c: number, v: string | number) => h.push(String(c), String(v));\n // Minimal HEADER declaring R12.\n p(0, \"SECTION\"); p(2, \"HEADER\"); p(9, \"$ACADVER\"); p(1, \"AC1009\"); p(0, \"ENDSEC\");\n // TABLES → LAYER table so entities reference real layers.\n p(0, \"SECTION\"); p(2, \"TABLES\"); p(0, \"TABLE\"); p(2, \"LAYER\"); p(70, LAYERS.length);\n for (const name of LAYERS) {\n p(0, \"LAYER\"); p(2, name); p(70, 0); p(62, 7); p(6, \"CONTINUOUS\");\n }\n p(0, \"ENDTAB\"); p(0, \"ENDSEC\");\n return h.join(\"\\n\") + \"\\n\";\n}\n\n/** Serialize one scene node to DXF entities on the given layer. */\nfunction emit(b: DxfBuilder, node: SceneNode): void {\n const layer = dxfLayer(node.layer);\n const prim = node.prim;\n switch (prim.t) {\n case \"polygon\":\n b.loop(layer, prim.pts);\n break;\n case \"line\":\n b.line(layer, prim.a, prim.b);\n break;\n case \"region\":\n for (const lp of prim.loops) b.loop(layer, lp);\n break;\n case \"arc\": {\n const [a0, a1] = minorArcDegrees(prim.center, prim.start, prim.end);\n b.arc(layer, prim.center, prim.r, a0, a1);\n break;\n }\n case \"text\":\n b.text(layer, prim.at, prim.size, prim.value);\n break;\n }\n}\n\n/** Render a {@link Scene} as an ASCII DXF document string. */\nexport function toDxf(scene: Scene): string {\n const b = new DxfBuilder();\n b.pair(0, \"SECTION\");\n b.pair(2, \"ENTITIES\");\n for (const node of scene.nodes) emit(b, node);\n b.pair(0, \"ENDSEC\");\n return header() + b.toString() + \"0\\nEOF\\n\";\n}\n","/**\n * PDF export backend — a **true vector** serializer of the {@link Scene}.\n *\n * Walks the Scene's positioned primitives into pdfkit drawing ops, so strokes\n * are real vector paths and text is selectable (no SVG rasterization round-trip).\n * `pdfkit` is an OPTIONAL dependency, lazy-`import()`ed so the zero-dep core never\n * hard-requires it; a clear error is thrown if it is absent. Async + Node-oriented\n * — NOT part of `compile()`. Build a Scene with `toScene(ir)` or `compile().scene`.\n *\n * Coordinates: ArchLang is mm, top-left origin, +y down — pdfkit's user space is\n * the same orientation, so we map the viewBox by translating by its top-left and\n * treat 1mm as 1pt (as the previous SVG-based exporter did with `assumePt`).\n *\n * Page chrome (north arrow, scale bar, title block) is drawn with PDF-native\n * helpers to keep parity with the SVG output. This duplicates the chrome geometry\n * (also in `backends/svg.ts`) — a deliberate, bounded cost until chrome itself\n * moves into the Scene in a later phase. Hatch patterns are SVG-specific, so\n * poché regions fill with the solid poché base colour in PDF.\n */\n\nimport type { NorthDir, Point } from \"../ast.js\";\nimport type { Paint, Scene, SceneNode } from \"../scene.js\";\nimport { RENDER_PASSES } from \"../scene.js\";\nimport type { Theme } from \"../theme.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/** Resolve a Paint fill to a concrete PDF colour, or null for no fill. */\nfunction fillColor(paint: Paint, theme: Theme): string | null {\n const f = paint.fill;\n if (!f || f === \"none\") return null;\n // SVG hatch pattern refs have no PDF equivalent → fill with the poché base.\n if (f.startsWith(\"url(\")) return theme.pocheBase;\n return f;\n}\n\nfunction regionPath(loops: Point[][]): string {\n return loops.map((loop) => \"M \" + loop.map((p) => `${p.x} ${p.y}`).join(\" L \") + \" Z\").join(\" \");\n}\n\n/** Apply fill/stroke/width/dash to the path currently built on `doc`. */\nfunction applyPaint(doc: any, paint: Paint, theme: Theme): void {\n const fill = fillColor(paint, theme);\n const stroke = paint.stroke && paint.stroke !== \"none\" ? paint.stroke : null;\n if (paint.width !== undefined) doc.lineWidth(paint.width);\n doc.lineJoin(paint.linejoin ?? \"miter\");\n doc.lineCap(paint.linecap === \"square\" ? \"square\" : \"butt\");\n if (paint.dash) doc.dash(paint.dash[0], { space: paint.dash[1] });\n else doc.undash();\n if (fill && stroke) doc.fillAndStroke(fill, stroke);\n else if (fill) doc.fill(fill);\n else if (stroke) doc.stroke(stroke);\n else doc.stroke();\n}\n\n/** Draw text honouring the primitive's anchor/baseline/rotation (selectable). */\nfunction drawText(doc: any, at: Point, value: string, size: number, anchor: string, rotate: number | undefined, color: string): void {\n doc.undash();\n doc.fontSize(size).fillColor(color);\n const w = doc.widthOfString(value);\n let x = at.x;\n if (anchor === \"middle\") x -= w / 2;\n else if (anchor === \"end\") x -= w;\n // pdfkit places the text box top at y; nudge up to centre on the baseline point.\n const y = at.y - size * 0.5;\n if (rotate !== undefined) {\n doc.save();\n doc.rotate(rotate, { origin: [at.x, at.y] });\n doc.text(value, x, y, { lineBreak: false });\n doc.restore();\n } else {\n doc.text(value, x, y, { lineBreak: false });\n }\n}\n\nfunction drawNode(doc: any, node: SceneNode, theme: Theme): void {\n const { prim, paint } = node;\n switch (prim.t) {\n case \"polygon\":\n doc.polygon(...prim.pts.map((p) => [p.x, p.y]));\n applyPaint(doc, paint, theme);\n break;\n case \"line\":\n doc.moveTo(prim.a.x, prim.a.y).lineTo(prim.b.x, prim.b.y);\n applyPaint(doc, paint, theme);\n break;\n case \"region\":\n doc.path(regionPath(prim.loops));\n applyPaint(doc, paint, theme);\n break;\n case \"arc\":\n doc.path(`M ${prim.start.x} ${prim.start.y} A ${prim.r} ${prim.r} 0 0 ${prim.sweep} ${prim.end.x} ${prim.end.y}`);\n applyPaint(doc, paint, theme);\n break;\n case \"text\":\n drawText(doc, prim.at, prim.value, prim.size, prim.anchor, prim.rotate, fillColor(paint, theme) ?? \"#000000\");\n break;\n }\n}\n\n/** Convert a {@link Scene} to a vector PDF (Uint8Array). Requires optional `pdfkit`. */\nexport async function toPdf(scene: Scene): Promise<Uint8Array> {\n let PDFDocument: any;\n try {\n PDFDocument = (await import(\"pdfkit\" as string)).default;\n } catch {\n throw new Error(\n \"PDF export needs the optional dependency 'pdfkit'. Install it: npm install pdfkit\",\n );\n }\n\n const { theme, sizes, bounds: b } = scene;\n const margin = sizes.margin;\n const vbX = b.minX - margin;\n const vbY = b.minY - margin;\n const W = scene.width;\n const H = scene.height;\n\n const doc = new PDFDocument({ size: [W, H], margin: 0 });\n const chunks: Uint8Array[] = [];\n const done = new Promise<void>((resolve, reject) => {\n doc.on(\"data\", (c: Uint8Array) => chunks.push(c));\n doc.on(\"end\", () => resolve());\n doc.on(\"error\", (e: Error) => reject(e));\n });\n\n // Map scene space → page space (top-left of the viewBox to the page origin).\n doc.save();\n doc.translate(-vbX, -vbY);\n\n // Background fills the whole padded page.\n doc.rect(vbX, vbY, W, H).fill(theme.bg);\n\n // Element/wall primitives, bucketed by layer (deterministic draw order).\n for (const pass of RENDER_PASSES) {\n for (const node of scene.nodes) if (node.layer === pass) drawNode(doc, node, theme);\n }\n\n drawChrome(doc, scene);\n\n doc.restore();\n doc.end();\n await done;\n return concat(chunks);\n}\n\n/** North arrow + scale bar + title block — PDF parity with the SVG chrome. */\nfunction drawChrome(doc: any, scene: Scene): void {\n const { theme, sizes, bounds: b } = scene;\n const refDim = sizes.refDim;\n const margin = sizes.margin;\n const thin = sizes.thin;\n\n // North arrow (triangle rotated by bearing; \"N\" stays upright).\n {\n const r = refDim * 0.045;\n const cx = b.maxX - r;\n const cy = b.minY - margin * 0.55;\n const deg = northDegrees(scene.north);\n const fs = refDim * 0.026;\n doc.save();\n doc.rotate(deg, { origin: [cx, cy] });\n doc\n .polygon([cx, cy - r], [cx - r * 0.5, cy + r * 0.6], [cx, cy + r * 0.25], [cx + r * 0.5, cy + r * 0.6])\n .fill(theme.annotation);\n doc.restore();\n const rad = (deg * Math.PI) / 180;\n const lx = cx + Math.sin(rad) * (r + fs * 0.8);\n const ly = cy - Math.cos(rad) * (r + fs * 0.8);\n drawText(doc, { x: lx, y: ly }, \"N\", fs, \"middle\", undefined, theme.annotation);\n }\n\n // Scale bar (two-segment alternating bar + end labels).\n {\n const barLen = niceBarLength(refDim * 0.3);\n const x0 = b.minX;\n const y0 = b.maxY + margin * 0.55;\n const hgt = refDim * 0.014;\n const fs = refDim * 0.02;\n const half = barLen / 2;\n doc.rect(x0, y0, half, hgt).fill(theme.annotation);\n doc.lineWidth(thin).undash();\n doc.rect(x0 + half, y0, half, hgt).stroke(theme.annotation);\n drawText(doc, { x: x0, y: y0 + hgt + fs }, \"0\", fs, \"start\", undefined, theme.annotation);\n drawText(doc, { x: x0 + barLen, y: y0 + hgt + fs }, `${barLen / 1000} m`, fs, \"middle\", undefined, theme.annotation);\n }\n\n // Title block (framed metadata rows).\n const t = scene.title;\n if (t || scene.scale) {\n const boxW = refDim * 0.34;\n const boxH = margin * 0.82;\n const x0 = b.maxX - boxW;\n const y0 = b.maxY + margin * 0.15;\n const fs = refDim * 0.019;\n const pad = boxW * 0.05;\n const lines: { k: string; v: string }[] = [];\n if (t?.project) lines.push({ k: \"PROJECT\", v: t.project });\n if (t?.drawnBy) lines.push({ k: \"DRAWN BY\", v: t.drawnBy });\n if (t?.date) lines.push({ k: \"DATE\", v: t.date });\n if (scene.scale) lines.push({ k: \"SCALE\", v: scene.scale });\n doc.lineWidth(thin).undash();\n doc.rect(x0, y0, boxW, boxH).stroke(theme.annotation);\n const rowH = boxH / Math.max(lines.length, 1);\n lines.forEach((ln, i) => {\n const ly = y0 + rowH * (i + 0.5);\n drawText(doc, { x: x0 + pad, y: ly }, ln.k, fs * 0.8, \"start\", undefined, theme.annotationMuted);\n drawText(doc, { x: x0 + boxW - pad, y: ly }, ln.v, fs, \"end\", undefined, theme.annotation);\n if (i > 0) {\n doc.lineWidth(thin * 0.5).moveTo(x0, y0 + rowH * i).lineTo(x0 + boxW, y0 + rowH * i).stroke(theme.annotation);\n }\n });\n }\n}\n\nfunction northDegrees(north: NorthDir): number {\n switch (north) {\n case \"up\": return 0;\n case \"down\": return 180;\n case \"left\": return 270;\n case \"right\": return 90;\n default: return typeof north === \"object\" ? north.deg : 0;\n }\n}\n\nconst NICE_LENGTHS = [500, 1000, 2000, 5000, 10000, 20000, 50000, 100000];\nfunction niceBarLength(target: number): number {\n let best = NICE_LENGTHS[0];\n for (const v of NICE_LENGTHS) if (v <= target) best = v;\n return best;\n}\n\nfunction concat(chunks: Uint8Array[]): Uint8Array {\n let total = 0;\n for (const c of chunks) total += c.length;\n const out = new Uint8Array(total);\n let offset = 0;\n for (const c of chunks) {\n out.set(c, offset);\n offset += c.length;\n }\n return out;\n}\n","/**\r\n * ArchLang — compile declarative floor-plan source to a professional SVG.\r\n *\r\n * @example\r\n * import { compile } from \"@chanmeng666/archlang\";\r\n * const { svg, errors } = compile(`plan \"Demo\" { room at (0,0) size 4000x3000 label \"Room\" }`);\r\n */\r\n\r\nimport { parse } from \"./parser.js\";\r\nimport { resolve } from \"./ir.js\";\r\nimport { toScene } from \"./scene-build.js\";\r\nimport { renderSvg } from \"./backends/svg.js\";\r\nimport { offsetToLineCol } from \"./diagnostics.js\";\r\nimport type { Scene } from \"./scene.js\";\r\nimport type { Diagnostic } from \"./diagnostics.js\";\r\nimport type { CompileError, CompileOptions, CompileResult } from \"./types.js\";\r\n\r\nexport type {\r\n CompileError,\r\n CompileOptions,\r\n CompileResult,\r\n CompileWarning,\r\n Diagnostic,\r\n Span,\r\n Severity,\r\n} from \"./types.js\";\r\nexport { formatDiagnostic, offsetToLineCol } from \"./diagnostics.js\";\r\nexport type * from \"./ast.js\";\r\n\r\n// IR + export backends (for consumers that want resolved geometry or other\r\n// output formats). `resolve`/`toDxf` are pure & zero-dep; `toPdf` lazily loads\r\n// optional deps. None of these are part of `compile()`.\r\nexport { resolve } from \"./ir.js\";\r\nexport type {\r\n ResolvedPlan,\r\n ResolvedElement,\r\n RWall,\r\n RRoom,\r\n RDoor,\r\n RWindow,\r\n RFurniture,\r\n RDim,\r\n RColumn,\r\n} from \"./ir.js\";\r\n// Scene IR (the backend-neutral drawing target) + its builder. Backends consume\r\n// a Scene: `toDxf(scene)` / `toPdf(scene)`; build one with `toScene(ir)` or read\r\n// `compile().scene`.\r\nexport { toScene } from \"./scene-build.js\";\r\nexport type { Scene, SceneNode, ScenePrim, Paint, RenderPass, RenderSizes } from \"./scene.js\";\r\nexport { toDxf } from \"./export/dxf.js\";\r\nexport { toPdf } from \"./export/pdf.js\";\r\n\r\n/** Small LRU-ish memo cache keyed by source+options. Bounded to 64 entries. */\r\nconst cache = new Map<string, CompileResult>();\r\nconst CACHE_MAX = 64;\r\n\r\nexport function compile(source: string, opts: CompileOptions = {}): CompileResult {\r\n const key = JSON.stringify([source, opts.width ?? null, opts.theme ?? null]);\r\n if (!opts.noCache) {\r\n const hit = cache.get(key);\r\n if (hit) return hit;\r\n }\r\n\r\n const result = compileUncached(source, opts);\r\n\r\n if (!opts.noCache) {\r\n if (cache.size >= CACHE_MAX) {\r\n const oldest = cache.keys().next().value;\r\n if (oldest !== undefined) cache.delete(oldest);\r\n }\r\n cache.set(key, result);\r\n }\r\n return result;\r\n}\r\n\r\n/** Project a span-carrying diagnostic onto the legacy `{message, line, col}` shape. */\r\nfunction toLegacy(source: string, d: Diagnostic): CompileError {\r\n if (!d.span) return { message: d.message };\r\n const { line, col } = offsetToLineCol(source, d.span.start);\r\n return { message: d.message, line, col };\r\n}\r\n\r\nfunction compileUncached(source: string, opts: CompileOptions): CompileResult {\r\n const { plan, diagnostics: parseDiags } = parse(source);\r\n\r\n // parse → resolve (AST→IR, the single place semantics live) → render.\r\n const resolved = plan ? resolve(plan) : null;\r\n const diagnostics: Diagnostic[] = resolved\r\n ? [...parseDiags, ...resolved.diagnostics]\r\n : [...parseDiags];\r\n\r\n const errs = diagnostics.filter((d) => d.severity === \"error\");\r\n const errors = errs.map((d) => toLegacy(source, d));\r\n const warnings = diagnostics\r\n .filter((d) => d.severity === \"warning\")\r\n .map((d) => toLegacy(source, d));\r\n\r\n // Warnings never block rendering; any error (or no plan) aborts with svg = \"\".\r\n // The Scene is built once and serialized to SVG; it is also exposed on the\r\n // result so consumers can target other backends (toDxf/toPdf) without re-resolving.\r\n let svg = \"\";\r\n let scene: Scene | undefined;\r\n if (resolved && errs.length === 0) {\r\n scene = toScene(resolved.ir, opts);\r\n svg = renderSvg(scene, opts);\r\n }\r\n\r\n return { svg, errors, warnings, diagnostics, ast: plan, scene };\r\n}\r\n\r\n/** Clear the internal compile cache (useful in long-lived processes/tests). */\r\nexport function clearCache(): void {\r\n cache.clear();\r\n}\r\n"],"mappings":";AA0CA,IAAM,UAAU,CAAC,MAAc,KAAK,OAAO,KAAK;AAChD,IAAM,eAAe,CAAC,MACnB,KAAK,OAAO,KAAK,OAAS,KAAK,OAAO,KAAK,OAAQ,MAAM;AAC5D,IAAM,cAAc,CAAC,MAAc,aAAa,CAAC,KAAK,QAAQ,CAAC;AAExD,SAAS,IAAI,KAAwB;AAC1C,QAAM,SAAkB,CAAC;AACzB,QAAM,SAAsE,CAAC;AAC7E,MAAI,IAAI;AACR,MAAI,OAAO;AACX,MAAI,MAAM;AAEV,QAAM,OAAO,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC,KAAK;AACtC,QAAM,UAAU,MAAM;AACpB,UAAM,IAAI,IAAI,GAAG;AACjB,QAAI,MAAM,MAAM;AACd;AACA,YAAM;AAAA,IACR,OAAO;AACL;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,CACX,MACA,OACA,WACA,UACA,UACA,UACG,OAAO,KAAK,EAAE,MAAM,OAAO,MAAM,WAAW,KAAK,UAAU,GAAG,OAAO,OAAO,UAAU,KAAK,EAAE,CAAC;AAEnG,SAAO,IAAI,IAAI,QAAQ;AACrB,UAAM,IAAI,KAAK;AACf,UAAM,YAAY;AAClB,UAAM,WAAW;AACjB,UAAM,WAAW;AAGjB,QAAI,MAAM,OAAO,MAAM,OAAQ,MAAM,QAAQ,MAAM,MAAM;AACvD,cAAQ;AACR;AAAA,IACF;AAGA,QAAI,MAAM,KAAK;AACb,aAAO,IAAI,IAAI,UAAU,KAAK,MAAM,KAAM,SAAQ;AAClD;AAAA,IACF;AAGA,QAAI,MAAM,KAAK;AACb,cAAQ;AACR,UAAI,QAAQ;AACZ,UAAI,aAAa;AACjB,aAAO,IAAI,IAAI,QAAQ;AACrB,cAAM,KAAK,KAAK;AAChB,YAAI,OAAO,MAAM;AACf,kBAAQ;AACR,gBAAM,MAAM,QAAQ;AACpB,mBAAS,QAAQ,MAAM,OAAO;AAC9B;AAAA,QACF;AACA,YAAI,OAAO,KAAK;AACd,kBAAQ;AACR,uBAAa;AACb;AAAA,QACF;AACA,YAAI,OAAO,KAAM;AACjB,iBAAS,QAAQ;AAAA,MACnB;AACA,UAAI,CAAC,YAAY;AACf,eAAO,KAAK,EAAE,SAAS,+BAA+B,MAAM,EAAE,OAAO,UAAU,KAAK,EAAE,EAAE,CAAC;AAAA,MAC3F;AACA,WAAK,UAAU,OAAO,WAAW,UAAU,QAAQ;AACnD;AAAA,IACF;AAGA,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,UAAU,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAC1F,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,UAAU,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAC1F,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,UAAU,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAC1F,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,UAAU,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAC1F,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,SAAS,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACzF,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,UAAU,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAC1F,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,SAAS,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACzF,QAAI,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK;AAAE,cAAQ;AAAG,cAAQ;AAAG,WAAK,SAAS,MAAM,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAGxH,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,QAAQ,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACxF,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,SAAS,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACzF,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,QAAQ,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACxF,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,SAAS,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AACzF,QAAI,MAAM,KAAK;AAAE,cAAQ;AAAG,WAAK,WAAW,KAAK,WAAW,UAAU,QAAQ;AAAG;AAAA,IAAU;AAI3F,QAAI,QAAQ,CAAC,KAAM,MAAM,OAAO,QAAQ,KAAK,CAAC,CAAC,GAAI;AACjD,UAAI,MAAM;AACV,aAAO,QAAQ,KAAK,CAAC,EAAG,QAAO,QAAQ;AACvC,UAAI,KAAK,MAAM,KAAK;AAClB,eAAO,QAAQ;AACf,eAAO,QAAQ,KAAK,CAAC,EAAG,QAAO,QAAQ;AAAA,MACzC;AACA,YAAM,QAAQ,WAAW,GAAG;AAE5B,UAAI,KAAK,MAAM,QAAQ,QAAQ,KAAK,CAAC,CAAC,KAAM,KAAK,CAAC,MAAM,OAAO,QAAQ,KAAK,CAAC,CAAC,IAAK;AACjF,gBAAQ;AACR,YAAI,OAAO;AACX,eAAO,QAAQ,KAAK,CAAC,EAAG,SAAQ,QAAQ;AACxC,YAAI,KAAK,MAAM,KAAK;AAClB,kBAAQ,QAAQ;AAChB,iBAAO,QAAQ,KAAK,CAAC,EAAG,SAAQ,QAAQ;AAAA,QAC1C;AACA,cAAM,SAAS,WAAW,IAAI;AAC9B,aAAK,aAAa,GAAG,GAAG,IAAI,IAAI,IAAI,WAAW,UAAU,UAAU,EAAE,KAAK,OAAO,MAAM,OAAO,CAAC;AAC/F;AAAA,MACF;AACA,WAAK,UAAU,KAAK,WAAW,UAAU,UAAU,EAAE,KAAK,MAAM,CAAC;AACjE;AAAA,IACF;AAGA,QAAI,aAAa,CAAC,GAAG;AACnB,UAAI,QAAQ;AACZ,aAAO,IAAI,IAAI,UAAU,YAAY,KAAK,CAAC,EAAG,UAAS,QAAQ;AAC/D,WAAK,SAAS,OAAO,WAAW,UAAU,QAAQ;AAClD;AAAA,IACF;AAGA,WAAO,KAAK,EAAE,SAAS,wBAAwB,KAAK,UAAU,CAAC,CAAC,IAAI,MAAM,EAAE,OAAO,UAAU,KAAK,WAAW,EAAE,EAAE,CAAC;AAClH,YAAQ;AAAA,EACV;AAEA,OAAK,OAAO,IAAI,MAAM,KAAK,CAAC;AAC5B,SAAO,EAAE,QAAQ,OAAO;AAC1B;;;ACzJA,IAAM,WAA+C;AAAA,EACnD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AACX;AACA,IAAM,SAAkE;AAAA,EACtE,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AACX;AAGO,SAAS,UAAU,IAAsB;AAC9C,SAAO,SAAS,IAAI,CAAC;AACvB;AAEA,SAAS,SAAS,IAAgB,SAAuB;AACvD,MAAI,OAAO,WAAW,EAAE;AACxB,aAAS;AACP,UAAM,IAAI,GAAG,KAAK;AAClB,UAAM,OAAO,SAAS,EAAE,IAAI;AAC5B,QAAI,SAAS,UAAa,OAAO,QAAS;AAC1C,OAAG,KAAK;AACR,UAAM,QAAQ,SAAS,IAAI,OAAO,CAAC;AACnC,WAAO,EAAE,GAAG,OAAO,IAAI,OAAO,EAAE,IAAI,GAAI,GAAG,MAAM,GAAG,MAAM;AAAA,EAC5D;AACA,SAAO;AACT;AAEA,SAAS,WAAW,IAAsB;AACxC,QAAM,IAAI,GAAG,KAAK;AAClB,MAAI,EAAE,SAAS,WAAW,EAAE,SAAS,QAAQ;AAC3C,OAAG,KAAK;AACR,WAAO,EAAE,GAAG,SAAS,IAAI,EAAE,SAAS,UAAU,MAAM,KAAK,GAAG,WAAW,EAAE,EAAE;AAAA,EAC7E;AACA,SAAO,UAAU,EAAE;AACrB;AAEA,SAAS,UAAU,IAAsB;AACvC,QAAM,IAAI,GAAG,KAAK;AAClB,MAAI,EAAE,SAAS,UAAU;AACvB,OAAG,KAAK;AACR,WAAO,EAAE,GAAG,OAAO,OAAO,EAAE,IAAK;AAAA,EACnC;AACA,MAAI,EAAE,SAAS,SAAS;AACtB,OAAG,KAAK;AACR,WAAO,EAAE,GAAG,OAAO,MAAM,EAAE,OAAO,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,IAAI,EAAE;AAAA,EACzE;AACA,MAAI,EAAE,SAAS,UAAU;AACvB,OAAG,KAAK;AACR,UAAM,IAAI,UAAU,EAAE;AACtB,UAAM,QAAQ,GAAG,KAAK;AACtB,QAAI,MAAM,SAAS,SAAU,IAAG,KAAK,0BAA0B,SAAS,KAAK,CAAC,EAAE;AAChF,OAAG,KAAK;AACR,WAAO;AAAA,EACT;AACA,SAAO,GAAG,KAAK,6CAA6C,SAAS,CAAC,CAAC,EAAE;AAC3E;AAIO,SAAS,SAAS,GAAS,KAAU,SAA0C;AACpF,UAAQ,EAAE,GAAG;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK,OAAO;AACV,YAAM,IAAI,IAAI,IAAI,EAAE,IAAI;AACxB,UAAI,MAAM,QAAW;AACnB,cAAM,OAAO,QAAQ,EAAE,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC;AAC5C,gBAAQ;AAAA,UACN,UAAU;AAAA,UACV,SAAS,iBAAiB,EAAE,IAAI;AAAA,UAChC,MAAM;AAAA,UACN,MAAM,EAAE;AAAA,UACR,OAAO,OAAO,CAAC,iBAAiB,IAAI,IAAI,IAAI;AAAA,QAC9C,CAAC;AACD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,IAAI,SAAS,EAAE,GAAG,KAAK,OAAO;AACpC,aAAO,EAAE,OAAO,MAAM,CAAC,IAAI;AAAA,IAC7B;AAAA,IACA,KAAK,OAAO;AACV,YAAM,IAAI,SAAS,EAAE,GAAG,KAAK,OAAO;AACpC,YAAM,IAAI,SAAS,EAAE,GAAG,KAAK,OAAO;AACpC,cAAQ,EAAE,IAAI;AAAA,QACZ,KAAK;AAAK,iBAAO,IAAI;AAAA,QACrB,KAAK;AAAK,iBAAO,IAAI;AAAA,QACrB,KAAK;AAAK,iBAAO,IAAI;AAAA,QACrB,KAAK;AAAA,QACL,KAAK;AACH,cAAI,MAAM,GAAG;AACX,oBAAQ,EAAE,UAAU,SAAS,SAAS,GAAG,EAAE,OAAO,MAAM,aAAa,QAAQ,YAAY,MAAM,aAAa,CAAC;AAC7G,mBAAO;AAAA,UACT;AACA,iBAAO,EAAE,OAAO,MAAM,IAAI,IAAI,IAAI;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,SAAS,GAAkB;AAClC,MAAI,EAAE,SAAS,MAAO,QAAO;AAC7B,MAAI,EAAE,SAAS,SAAU,QAAO,UAAU,KAAK,UAAU,EAAE,KAAK,CAAC;AACjE,SAAO,IAAI,EAAE,KAAK;AACpB;AAGO,SAAS,QAAQ,MAAc,YAAqC;AACzE,MAAI,OAAsB;AAC1B,MAAI,WAAW;AACf,aAAW,KAAK,YAAY;AAC1B,UAAM,IAAI,YAAY,MAAM,CAAC;AAC7B,QAAI,IAAI,UAAU;AAChB,iBAAW;AACX,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAAS,CAAC,CAAC;AACrD,SAAO,SAAS,QAAQ,YAAY,QAAQ,OAAO;AACrD;AAEA,SAAS,YAAY,GAAW,GAAmB;AACjD,QAAM,IAAI,EAAE;AACZ,QAAM,IAAI,EAAE;AACZ,QAAM,KAAK,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC;AACpD,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,QAAI,OAAO,GAAG,CAAC;AACf,OAAG,CAAC,IAAI;AACR,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,MAAM,GAAG,CAAC;AAChB,SAAG,CAAC,IAAI,KAAK;AAAA,QACX,GAAG,CAAC,IAAI;AAAA,QACR,GAAG,IAAI,CAAC,IAAI;AAAA,QACZ,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,MACtC;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,GAAG,CAAC;AACb;;;AC7IO,IAAM,gBAAuB;AAAA,EAClC,IAAI;AAAA,EACJ,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM;AACR;AAGA,IAAM,UAAuC;AAAA,EAC3C,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,QAAQ;AACV;AAGO,SAAS,gBAAgB,KAAiC;AAC/D,MAAI,OAAO,cAAe,QAAO;AACjC,MAAI,OAAO,QAAS,QAAO,QAAQ,GAAG;AACtC,SAAO;AACT;AAGO,SAAS,kBAAkB,KAA2B;AAC3D,SAAO,QAAQ;AACjB;AAGO,SAAS,cAAc,QAA+C;AAC3E,QAAM,MAAa,EAAE,GAAG,cAAc;AACtC,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAO;AACZ,eAAW,KAAK,OAAO,KAAK,KAAK,GAAsB;AACrD,YAAM,IAAI,MAAM,CAAC;AACjB,UAAI,MAAM,OAAW,CAAC,IAA2C,CAAC,IAAI;AAAA,IACxE;AAAA,EACF;AACA,SAAO;AACT;AAUO,SAAS,cAAc,OAAqB;AACjD,QAAM,MAAM,CAAC,MACX,EAAE,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,QAAQ;AAC7F,QAAM,MAAa,EAAE,GAAG,MAAM;AAC9B,aAAW,KAAK,OAAO,KAAK,GAAG,GAAsB;AACnD,UAAM,IAAI,IAAI,CAAC;AACf,QAAI,OAAO,MAAM,SAAU,CAAC,IAA2C,CAAC,IAAI,IAAI,CAAC;AAAA,EACnF;AACA,SAAO;AACT;;;ACnGO,IAAM,MAAM,CAAC,GAAU,OAAmB,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE;AACvE,IAAM,MAAM,CAAC,GAAU,OAAmB,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE;AACvE,IAAM,MAAM,CAAC,GAAQ,OAAoB,EAAE,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE;AAClE,IAAM,SAAS,CAAC,MAAmB,KAAK,MAAM,EAAE,GAAG,EAAE,CAAC;AACtD,SAAS,KAAK,GAAa;AAChC,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,MAAM,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE;AAC7D;AAEO,IAAM,SAAS,CAAC,OAAiB,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE;AASnD,IAAM,cAAc,OAAe;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEO,SAAS,aAAa,GAAW,GAAW,GAAiB;AAClE,MAAI,IAAI,EAAE,KAAM,GAAE,OAAO;AACzB,MAAI,IAAI,EAAE,KAAM,GAAE,OAAO;AACzB,MAAI,IAAI,EAAE,KAAM,GAAE,OAAO;AACzB,MAAI,IAAI,EAAE,KAAM,GAAE,OAAO;AAC3B;AAGO,SAAS,mBAAmB,GAAU,GAAU,GAAkB;AACvE,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,MAAI,IAAI,SAAS,IAAI,KAAK,MAAM,MAAM,MAAM,OAAO;AACnD,MAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAC9B,QAAM,KAAK,EAAE,IAAI,IAAI;AACrB,QAAM,KAAK,EAAE,IAAI,IAAI;AACrB,SAAO,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE;AACtC;AASO,SAAS,gBAAgB,QAAe,OAAc,KAA8B;AACzF,QAAM,MAAM,CAAC,MAAsB,KAAK,MAAM,EAAE,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,OAAO,CAAC,IAAI,MAAO,KAAK;AAC/F,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,KAAK,IAAI,GAAG;AAClB,QAAM,QAAS,KAAK,MAAM,MAAO,OAAO;AACxC,SAAO,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxC;AAGO,SAAS,YAAY,GAAW,GAAW,GAAW,GAAoB;AAC/E,SAAO;AAAA,IACL,EAAE,GAAG,EAAE;AAAA,IACP,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACd,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AAAA,IACrB,EAAE,GAAG,GAAG,IAAI,EAAE;AAAA,EAChB;AACF;AAOO,SAAS,iBAAiB,GAAU,GAAU,WAA4B;AAC/E,QAAM,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC;AACxB,QAAM,IAAI,OAAO,CAAC;AAClB,QAAM,OAAO,YAAY;AACzB,QAAM,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;AAC/B,QAAM,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9B,SAAO;AAAA,IACL,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;AAAA,IACpB,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;AAAA,IACpB,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;AAAA,IACrB,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;AAAA,EACvB;AACF;AAmBO,SAAS,eAAe,GAA4B;AACzD,QAAM,OAAsB,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,EAAE,OAAO,SAAS,GAAG,KAAK;AAC5C,SAAK,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,WAAW,EAAE,WAAW,UAAU,EAAE,SAAS,CAAC;AAAA,EAChG;AACA,MAAI,EAAE,UAAU,EAAE,OAAO,SAAS,GAAG;AACnC,SAAK,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,SAAS,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,GAAG,WAAW,EAAE,WAAW,UAAU,EAAE,SAAS,CAAC;AAAA,EAC9G;AACA,SAAO;AACT;AA4BO,SAAS,iBACd,OACA,IACA,KAC+C;AAC/C,QAAM,aAAa,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,aAAa,GAAG,IAAI;AACnF,MAAI,OAA2B;AAC/B,MAAI,WAAW;AACf,MAAI,SAAS;AACb,aAAW,KAAK,YAAY;AAC1B,UAAM,MAAM,EAAE,YAAY,IAAI,KAAK,IAAI,EAAE,WAAW,CAAC;AACrD,eAAW,KAAK,eAAe,CAAC,GAAG;AACjC,YAAM,OAAO,mBAAmB,IAAI,EAAE,GAAG,EAAE,CAAC;AAC5C,UAAI,OAAO,UAAU;AACnB,mBAAW;AACX,eAAO;AAAA,MACT;AACA,UAAI,CAAC,UAAU,QAAQ,IAAK,UAAS;AAAA,IACvC;AAAA,EACF;AACA,SAAO,EAAE,MAAM,OAAO;AACxB;;;ACzJO,IAAM,kBAAkB,CAAC,SAAS,YAAY,SAAS,cAAc,QAAQ,MAAM;AAEnF,IAAM,mBAA6B;AAGnC,SAAS,UAAU,UAA0B;AAClD,SAAO,aAAa,UAAU,UAAU,SAAS,QAAQ;AAC3D;AAEA,IAAM,UAAsC;AAAA,EAC1C,OAAO,CAAC,IAAI,MACV,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,gDACjF,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,qCACpC,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA;AAAA,EAIzG,UAAU,CAAC,IAAI,MAAM;AACnB,UAAM,IAAI,EAAE,MAAM;AAClB,WACE,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,kBACzE,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,kBAC/C,EAAE,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,WAAW,EAAE,IAAI,kBAClF,EAAE,IAAI,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,WAAW,EAAE,IAAI,kBAClF,EAAE,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,IAAI,CAAC,WAAW,EAAE,IAAI;AAAA,EAGvG;AAAA;AAAA,EAGA,OAAO,CAAC,IAAI,MAAM;AAChB,UAAM,IAAI,EAAE,MAAM;AAClB,UAAM,IAAI,EAAE,MAAM;AAClB,UAAM,KAAK,EAAE,IAAI,EAAE,OAAO,GAAG;AAC7B,WACE,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,kBACzE,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,uBAC1C,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,uBAClF,EAAE,IAAI,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,gBACjG,EAAE,IAAI,IAAI,CAAC,CAAC,gBAAgB,EAAE,IAAI,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,uBAC9F,EAAE,IAAI,IAAI,CAAC,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,gBACnF,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE;AAAA,EAGxH;AAAA;AAAA,EAGA,YAAY,CAAC,IAAI,MAAM;AACrB,UAAM,IAAI,EAAE,MAAM;AAClB,WACE,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,kBACzE,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,qBAC5C,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,mBAAmB,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,EAGjI;AAAA;AAAA,EAGA,MAAM,CAAC,IAAI,MAAM;AACf,UAAM,IAAI,EAAE,MAAM;AAClB,WACE,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,kBACzE,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,+BAClC,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,yBAAyB,EAAE,IAAI,mBAAmB,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC;AAAA,EAGlI;AAAA;AAAA,EAGA,MAAM,CAAC,IAAI,MACT,gBAAgB,EAAE,0CAA0C,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,kBACjF,EAAE,IAAI,EAAE,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI;AAE1E;AAEO,SAAS,gBAAgB,MAAgC;AAC9D,SAAQ,gBAAsC,SAAS,IAAI;AAC7D;AAGO,SAAS,aAAa,UAAoB,GAAqB;AACpE,SAAO,QAAQ,QAAQ,EAAE,UAAU,QAAQ,GAAG,CAAC;AACjD;;;AC9FO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAAyB;AAC7B,UAAM,KAAK,IAAI,WAAW,MAAM;AAChC,UAAM,KAAK,IAAI,WAAW;AAC1B,UAAM,WAAW,IAAI,SAAS,EAAE;AAChC,QAAI,WAAW,WAAW;AAC1B,UAAM,YAAY,IAAI,UAAU;AAChC,QAAI;AACJ,QAAI,IAAI,UAAU,UAAU,GAAG;AAC7B,UAAI,KAAK;AACT,iBAAW,IAAI,SAAS,EAAE;AAAA,IAC5B;AACA,QAAI,IAAI,QAAQ;AAChB,UAAM,SAAsB,CAAC;AAC7B,QAAI,SAAS;AACb,WAAO,CAAC,IAAI,OAAO,QAAQ,KAAK,CAAC,IAAI,OAAO,KAAK,GAAG;AAClD,UAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,YAAI,KAAK;AACT,iBAAS;AACT;AAAA,MACF;AACA,UAAI,IAAI,OAAO,QAAQ,GAAG;AACxB,eAAO,KAAK,IAAI,WAAW,CAAC;AAC5B;AAAA,MACF;AACA,UAAI,KAAK,8DAA8DA,UAAS,GAAG,CAAC,EAAE;AAAA,IACxF;AACA,QAAI,IAAI,QAAQ;AAChB,QAAI,OAAO,SAAS,EAAG,KAAI,KAAK,oCAAoC,EAAE;AACtE,WAAO,EAAE,MAAM,QAAQ,IAAI,UAAU,WAAW,UAAU,QAAQ,QAAQ,MAAM,GAAG,KAAK;AAAA,EAC1F;AAAA,EAEA,UAAU,CAAC,SAAU,KAAkB,YAAY;AAAA,EAEnD,QAAQ,MAAM,KAAwB;AACpC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,SAAS,EAAE,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC;AAC5D,UAAM,KAAK,IAAI,KAAK,EAAE,SAAS;AAC/B,UAAM,YAAY,IAAI,KAAK,EAAE,KAAK;AAClC,QAAI,aAAa,GAAG;AAClB,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,SAAS,EAAE,oCAAoC,MAAM,oBAAoB,MAAM,EAAE,KAAK,CAAC;AAAA,IAChI;AACA,QAAI,WAAW;AACf,QAAI,EAAE,aAAa,QAAW;AAC5B,UAAI,gBAAgB,EAAE,QAAQ,EAAG,YAAW,EAAE;AAAA;AAE5C,YAAI,KAAK;AAAA,UACP,UAAU;AAAA,UACV,SAAS,0BAA0B,EAAE,QAAQ,aAAa,gBAAgB,KAAK,IAAI,CAAC;AAAA,UACpF,MAAM;AAAA,UACN,MAAM,EAAE;AAAA,QACV,CAAC;AAAA,IACL;AACA,WAAO,EAAE,MAAM,QAAQ,IAAI,UAAU,EAAE,UAAU,WAAW,UAAU,QAAQ,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK;AAAA,EAC/G;AAAA,EAEA,OAAO,UAAmB;AACxB,UAAM,IAAI;AACV,WAAO,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,KAA6B;AAC5C,UAAM,IAAI;AACV,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,OAAO,eAAe,CAAC;AAC7B,UAAM,QAAqB,CAAC;AAC5B,eAAW,KAAK,MAAM;AACpB,YAAM,OAAO,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS;AACnD,YAAM,KAAK,EAAE,OAAO,YAAY,MAAM,EAAE,GAAG,WAAW,KAAK,KAAK,GAAG,OAAO,EAAE,MAAM,cAAc,EAAE,CAAC;AAAA,IACrG;AACA,eAAW,KAAK,MAAM;AACpB,YAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5B,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,IAAI,EAAE,YAAY;AACxB,YAAM,OAAO,EAAE,QAAQ,MAAM,YAAY,OAAO,MAAM,YAAY,SAAS,SAAkB;AAC7F,YAAM,KAAK,EAAE,OAAO,YAAY,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,GAAG,OAAO,KAAK,CAAC;AAClH,YAAM,KAAK,EAAE,OAAO,YAAY,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,KAAK,CAAC;AAAA,IACtH;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAASA,UAAS,KAAuB;AACvC,QAAM,IAAI,IAAI,KAAK;AACnB,MAAI,EAAE,SAAS,MAAO,QAAO;AAC7B,MAAI,EAAE,SAAS,SAAU,QAAO,UAAU,KAAK,UAAU,EAAE,KAAK,CAAC;AACjE,SAAO,IAAI,EAAE,KAAK;AACpB;;;ACjGO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAAyB;AAC7B,UAAM,KAAK,IAAI,WAAW,MAAM;AAChC,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,IAAI;AACnB,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,MAAM;AACrB,UAAM,OAAO,IAAI,gBAAgB;AACjC,UAAM,OAAiB,EAAE,MAAM,QAAQ,IAAI,IAAI,MAAM,MAAM,GAAG,KAAK;AACnE,QAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,UAAI,KAAK;AACT,WAAK,QAAQ,IAAI,UAAU;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,MAAM;AAAA,EAEhB,QAAQ,MAAM,KAAwB;AACpC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AACtC,UAAM,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE;AAChF,QAAI,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAC9B,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,SAAS,EAAE,+BAA+B,MAAM,eAAe,MAAM,EAAE,KAAK,CAAC;AAAA,IACtH;AACA,WAAO,EAAE,MAAM,QAAQ,IAAI,IAAI,MAAM,OAAO,EAAE,OAAO,MAAM,EAAE,KAAK;AAAA,EACpE;AAAA,EAEA,OAAO,UAAmB;AACxB,UAAM,IAAI;AACV,WAAO,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,EACvD;AAAA,EAEA,OAAO,UAAU,KAA6B;AAC5C,UAAM,IAAI;AACV,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,QAAqB,CAAC;AAC5B,UAAM,IAAI,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AACxD,UAAM,KAAK,EAAE,OAAO,SAAS,MAAM,EAAE,GAAG,WAAW,KAAK,EAAE,GAAG,OAAO,EAAE,MAAM,MAAM,SAAS,EAAE,CAAC;AAE9F,UAAM,KAAK,EAAE,GAAG,IAAI,EAAE,KAAK,IAAI;AAC/B,UAAM,KAAK,EAAE,GAAG,IAAI,EAAE,KAAK,IAAI;AAC/B,UAAM,UAAW,EAAE,KAAK,IAAI,OAAS,EAAE,KAAK,IAAI,MAAO,QAAQ,CAAC;AAChE,QAAI,EAAE,OAAO;AACX,YAAM,KAAK;AAAA,QACT,OAAO;AAAA,QACP,MAAM,EAAE,GAAG,QAAQ,IAAI,EAAE,GAAG,IAAI,GAAG,KAAK,MAAM,WAAW,IAAI,GAAG,OAAO,EAAE,OAAO,MAAM,MAAM,UAAU,QAAQ,UAAU,UAAU,WAAW,QAAQ,IAAI;AAAA,QACzJ,OAAO,EAAE,MAAM,MAAM,UAAU;AAAA,MACjC,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,QAAQ,IAAI,EAAE,GAAG,IAAI,GAAG,MAAM,EAAE,QAAQ,MAAM,WAAW,MAAM,GAAG,GAAG,OAAO,GAAG,MAAM,UAAO,MAAM,MAAM,UAAU,QAAQ,UAAU,UAAU,UAAU;AAAA,MACnK,OAAO,EAAE,MAAM,MAAM,UAAU;AAAA,IACjC,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;AC7DO,IAAM,OAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAAyB;AAC7B,UAAM,KAAK,IAAI,WAAW,MAAM;AAChC,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,IAAI;AACnB,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,OAAO;AACtB,UAAM,QAAQ,IAAI,UAAU;AAC5B,UAAM,OAAiB,EAAE,MAAM,QAAQ,IAAI,IAAI,OAAO,OAAO,QAAQ,OAAO,MAAM,MAAM,GAAG,KAAK;AAChG,QAAI,IAAI,UAAU,MAAM,GAAG;AACzB,UAAI,KAAK;AACT,WAAK,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B;AACA,QAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,UAAI,KAAK;AACT,YAAM,IAAI,IAAI,SAAS,EAAE;AACzB,UAAI,MAAM,UAAU,MAAM,QAAS,KAAI,KAAK,+CAA+C,CAAC,GAAG;AAC/F,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,UAAI,KAAK;AACT,YAAM,IAAI,IAAI,SAAS,EAAE;AACzB,UAAI,MAAM,QAAQ,MAAM,MAAO,KAAI,KAAK,2CAA2C,CAAC,GAAG;AACvF,WAAK,QAAQ;AAAA,IACf;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,MAAM;AAAA,EAEhB,QAAQ,MAAM,KAAwB;AACpC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AACtC,UAAM,KAAK,IAAI,KAAK,EAAE,KAAK;AAC3B,UAAM,QAAQ,IAAI,KAAK,EAAE,KAAK;AAC9B,QAAI,SAAS,GAAG;AACd,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,SAAS,EAAE,gCAAgC,MAAM,gBAAgB,MAAM,EAAE,KAAK,CAAC;AAAA,IACxH;AACA,QAAI,IAAI,MAAM,SAAS,KAAK,CAAC,IAAI,SAAS,IAAI,EAAE,IAAI,GAAG;AACrD,UAAI,KAAK,EAAE,UAAU,WAAW,SAAS,SAAS,EAAE,8BAA8B,MAAM,mBAAmB,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3H;AACA,WAAO,EAAE,MAAM,QAAQ,IAAI,IAAI,OAAO,OAAO,EAAE,OAAO,OAAO,EAAE,OAAO,MAAM,IAAI,YAAY,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK;AAAA,EACxH;AAAA,EAEA,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQf,OAAO,UAAU,KAA6B;AAC5C,UAAM,KAAK;AACX,UAAM,MAAM,GAAG;AACf,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC;AAChC,UAAM,IAAI,OAAO,CAAC;AAClB,UAAM,IAAI,IAAI,YAAY,IAAI,MAAM;AACpC,UAAM,KAAK,GAAG,QAAQ;AACtB,UAAM,QAAiB;AAAA,MACrB,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AAAA,MACtC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AAAA,MACrC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,MACtC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,IACzC;AACA,UAAM,QAAqB,CAAC;AAC5B,UAAM,KAAK,EAAE,OAAO,SAAS,MAAM,EAAE,GAAG,WAAW,KAAK,MAAM,GAAG,OAAO,EAAE,MAAM,MAAM,QAAQ,EAAE,CAAC;AACjG,UAAM,QAAQ,GAAG,UAAU,SAAS,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;AACnF,UAAM,UAAU,GAAG,UAAU,SAAS,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;AACrF,UAAM,UAAU,GAAG,UAAU,OAAO,IAAI,IAAI,GAAG,EAAE;AACjD,UAAM,UAAU,IAAI,OAAO,IAAI,SAAS,GAAG,KAAK,CAAC;AACjD,UAAM,SAAS,QAAQ,IAAI,MAAM,MAAM,QAAQ,IAAI,MAAM,MAAM,QAAQ,IAAI,MAAM,MAAM,QAAQ,IAAI,MAAM;AACzG,UAAM,QAAe,QAAQ,IAAI,IAAI;AACrC,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ;AAAA,MACxC,OAAO,EAAE,QAAQ,MAAM,UAAU,OAAO,MAAM,OAAO,IAAI;AAAA,IAC3D,CAAC;AACD,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,OAAO,QAAQ,OAAO,GAAG,GAAG,OAAO,OAAO,SAAS,KAAK,SAAS,MAAM;AAAA,MAClF,OAAO,EAAE,MAAM,QAAQ,QAAQ,MAAM,UAAU,OAAO,MAAM,MAAM,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,EAAE;AAAA,IAC3G,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;AC3FO,IAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAA2B;AAC/B,UAAM,KAAK,IAAI,WAAW,QAAQ;AAClC,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,IAAI;AACnB,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,OAAO;AACtB,UAAM,QAAQ,IAAI,UAAU;AAC5B,UAAM,OAAmB,EAAE,MAAM,UAAU,IAAI,IAAI,OAAO,MAAM,GAAG,KAAK;AACxE,QAAI,IAAI,UAAU,MAAM,GAAG;AACzB,UAAI,KAAK;AACT,WAAK,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,MAAM;AAAA,EAEhB,QAAQ,MAAM,KAA0B;AACtC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AACtC,UAAM,KAAK,IAAI,KAAK,EAAE,KAAK;AAC3B,UAAM,QAAQ,IAAI,KAAK,EAAE,KAAK;AAC9B,QAAI,SAAS,GAAG;AACd,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,WAAW,EAAE,gCAAgC,MAAM,kBAAkB,MAAM,EAAE,KAAK,CAAC;AAAA,IAC5H;AACA,QAAI,IAAI,MAAM,SAAS,KAAK,CAAC,IAAI,SAAS,IAAI,EAAE,IAAI,GAAG;AACrD,UAAI,KAAK,EAAE,UAAU,WAAW,SAAS,WAAW,EAAE,8BAA8B,MAAM,qBAAqB,MAAM,EAAE,KAAK,CAAC;AAAA,IAC/H;AACA,WAAO,EAAE,MAAM,UAAU,IAAI,IAAI,OAAO,MAAM,IAAI,YAAY,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK;AAAA,EAC1F;AAAA,EAEA,QAAQ,MAAM,CAAC;AAAA,EAEf,OAAO,UAAU,KAA6B;AAC5C,UAAM,KAAK;AACX,UAAM,MAAM,GAAG;AACf,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC;AAChC,UAAM,IAAI,OAAO,CAAC;AAClB,UAAM,IAAI,IAAI,YAAY;AAC1B,UAAM,KAAK,IAAI,MAAM;AACrB,UAAM,KAAK,GAAG,QAAQ;AACtB,UAAM,QAAiB;AAAA,MACrB,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AAAA,MACvC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AAAA,MACtC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;AAAA,MACvC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;AAAA,IAC1C;AACA,UAAM,QAAqB,CAAC;AAC5B,UAAM,KAAK,EAAE,OAAO,WAAW,MAAM,EAAE,GAAG,WAAW,KAAK,MAAM,GAAG,OAAO,EAAE,MAAM,MAAM,QAAQ,EAAE,CAAC;AACnG,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;AACjC,UAAM,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;AAChC,eAAW,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG;AACzB,YAAM,KAAK;AAAA,QACT,OAAO;AAAA,QACP,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,EAAE;AAAA,QACpE,OAAO,EAAE,QAAQ,MAAM,YAAY,OAAO,MAAM,KAAK;AAAA,MACvD,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,GAAG,GAAG;AAAA,MAChC,OAAO,EAAE,QAAQ,MAAM,YAAY,OAAO,MAAM,KAAK;AAAA,IACvD,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;ACxEO,IAAM,YAAwB;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAA8B;AAClC,UAAM,KAAK,IAAI,WAAW,WAAW;AACrC,UAAM,KAAK,IAAI,WAAW;AAC1B,UAAM,WAAW,IAAI,SAAS,EAAE;AAChC,QAAI,WAAW,IAAI;AACnB,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,MAAM;AACrB,UAAM,OAAO,IAAI,gBAAgB;AACjC,UAAM,OAAsB,EAAE,MAAM,aAAa,IAAI,UAAU,IAAI,MAAM,MAAM,GAAG,KAAK;AACvF,QAAI,IAAI,UAAU,OAAO,GAAG;AAC1B,UAAI,KAAK;AACT,WAAK,QAAQ,IAAI,UAAU;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,CAAC,SAAU,KAAuB,YAAY;AAAA,EAExD,QAAQ,MAAM,KAA6B;AACzC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AACtC,UAAM,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE;AAChF,QAAI,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAC9B,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,cAAc,EAAE,+BAA+B,MAAM,eAAe,MAAM,EAAE,KAAK,CAAC;AAAA,IAC3H;AACA,WAAO,EAAE,MAAM,aAAa,IAAI,UAAU,EAAE,UAAU,IAAI,MAAM,OAAO,EAAE,OAAO,MAAM,EAAE,KAAK;AAAA,EAC/F;AAAA,EAEA,OAAO,UAAmB;AACxB,UAAM,IAAI;AACV,WAAO,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,EACvD;AAAA,EAEA,OAAO,UAAU,KAA6B;AAC5C,UAAM,IAAI;AACV,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,QAAqB,CAAC;AAC5B,UAAM,IAAI,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AACxD,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,WAAW,KAAK,EAAE;AAAA,MAC7B,OAAO,EAAE,MAAM,MAAM,eAAe,QAAQ,MAAM,iBAAiB,OAAO,MAAM,KAAK;AAAA,IACvF,CAAC;AACD,QAAI,EAAE,OAAO;AACX,YAAM,KAAK,EAAE,GAAG,IAAI,EAAE,KAAK,IAAI;AAC/B,YAAM,KAAK,EAAE,GAAG,IAAI,EAAE,KAAK,IAAI;AAC/B,YAAM,KAAK;AAAA,QACT,OAAO;AAAA,QACP,MAAM,EAAE,GAAG,QAAQ,IAAI,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,OAAO,EAAE,OAAO,MAAM,MAAM,UAAU,QAAQ,UAAU,UAAU,UAAU;AAAA,QACrH,OAAO,EAAE,MAAM,MAAM,eAAe;AAAA,MACtC,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AACF;;;AC3DO,IAAM,MAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAAwB;AAC5B,UAAM,KAAK,IAAI,WAAW,KAAK;AAC/B,UAAM,OAAO,IAAI,WAAW;AAC5B,QAAI,IAAI,OAAO;AACf,UAAM,KAAK,IAAI,WAAW;AAC1B,UAAM,OAAgB,EAAE,MAAM,OAAO,IAAI,IAAI,MAAM,IAAI,QAAQ,EAAE,GAAG,OAAO,OAAO,IAAI,GAAG,MAAM,GAAG,KAAK;AACvG,QAAI,IAAI,UAAU,QAAQ,GAAG;AAC3B,UAAI,KAAK;AACT,WAAK,SAAS,IAAI,UAAU;AAAA,IAC9B;AACA,QAAI,IAAI,UAAU,MAAM,GAAG;AACzB,UAAI,KAAK;AACT,WAAK,OAAO,IAAI,UAAU;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,MAAM;AAAA,EAEhB,QAAQ,MAAM,KAAuB;AACnC,UAAM,IAAI;AACV,WAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAI,IAAI;AAAA,MACR,MAAM,IAAI,OAAO,IAAI,OAAO,EAAE,IAAI,CAAC;AAAA,MACnC,IAAI,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AAAA,MAC/B,QAAQ,IAAI,KAAK,EAAE,MAAM;AAAA,MACzB,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAO,UAAU;AACf,UAAM,KAAK;AACX,WAAO,CAAC,GAAG,MAAM,GAAG,EAAE;AAAA,EACxB;AAAA,EAEA,OAAO,UAAU,KAA6B;AAC5C,UAAM,KAAK;AACX,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,MAAM,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACpC,UAAM,IAAI,OAAO,GAAG;AACpB,UAAM,MAAM,IAAI,GAAG,GAAG,MAAM;AAC5B,UAAM,KAAK,IAAI,GAAG,MAAM,GAAG;AAC3B,UAAM,KAAK,IAAI,GAAG,IAAI,GAAG;AACzB,UAAM,OAAO,MAAM,SAAS;AAC5B,UAAM,YAAY,EAAE,QAAQ,MAAM,KAAK,OAAO,MAAM,KAAK;AACzD,UAAM,QAAqB,CAAC;AAE5B,UAAM,KAAK,EAAE,OAAO,QAAQ,MAAM,EAAE,GAAG,QAAQ,GAAG,GAAG,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,QAAQ,MAAM,KAAK,OAAO,MAAM,OAAO,IAAI,EAAE,CAAC;AAC3H,UAAM,KAAK,EAAE,OAAO,QAAQ,MAAM,EAAE,GAAG,QAAQ,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,OAAO,EAAE,QAAQ,MAAM,KAAK,OAAO,MAAM,OAAO,IAAI,EAAE,CAAC;AACzH,UAAM,KAAK,EAAE,OAAO,QAAQ,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,GAAG,GAAG,GAAG,OAAO,UAAU,CAAC;AACjF,eAAW,KAAK,CAAC,IAAI,EAAE,GAAG;AACxB,YAAM,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;AACrE,YAAM,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AACtE,YAAM,KAAK,EAAE,OAAO,QAAQ,MAAM,EAAE,GAAG,QAAQ,GAAG,IAAI,GAAG,GAAG,GAAG,OAAO,UAAU,CAAC;AAAA,IACnF;AACA,UAAM,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE;AACzD,UAAM,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,UAAU,GAAG,CAAC;AAC/C,QAAI,QAAS,KAAK,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,MAAO,KAAK;AACpD,QAAI,QAAQ,GAAI,UAAS;AACzB,QAAI,QAAQ,IAAK,UAAS;AAC1B,UAAM,QAAQ,GAAG,QAAQ,OAAO,KAAK,MAAM,OAAO,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;AACvE,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,QAAQ,IAAI,IAAI,OAAO,OAAO,MAAM,MAAM,SAAS,QAAQ,UAAU,UAAU,WAAW,QAAQ,MAAM;AAAA,MACnH,OAAO,EAAE,MAAM,MAAM,IAAI;AAAA,IAC3B,CAAC;AACD,WAAO;AAAA,EACT;AACF;;;ACpEO,IAAM,SAAqB;AAAA,EAChC,MAAM;AAAA,EACN,SAAS;AAAA,EAET,MAAM,KAA2B;AAC/B,UAAM,KAAK,IAAI,WAAW,QAAQ;AAClC,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,IAAI;AACnB,UAAM,KAAK,IAAI,WAAW;AAC1B,QAAI,WAAW,MAAM;AACrB,UAAM,OAAO,IAAI,gBAAgB;AACjC,WAAO,EAAE,MAAM,UAAU,IAAI,IAAI,MAAM,MAAM,GAAG,KAAK;AAAA,EACvD;AAAA,EAEA,UAAU,MAAM;AAAA,EAEhB,QAAQ,MAAM,KAA0B;AACtC,UAAM,IAAI;AACV,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,IAAI,OAAO,IAAI,OAAO,EAAE,EAAE,CAAC;AACtC,UAAM,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE;AAChF,QAAI,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAC9B,UAAI,KAAK,EAAE,UAAU,SAAS,SAAS,WAAW,EAAE,+BAA+B,MAAM,iBAAiB,MAAM,EAAE,KAAK,CAAC;AAAA,IAC1H;AACA,WAAO,EAAE,MAAM,UAAU,IAAI,IAAI,MAAM,MAAM,EAAE,KAAK;AAAA,EACtD;AAAA,EAEA,OAAO,UAAmB;AACxB,UAAM,IAAI;AACV,WAAO,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,EACvD;AAAA,EAEA,OAAO,UAAU,KAA6B;AAC5C,UAAM,IAAI;AACV,UAAM,EAAE,OAAO,MAAM,IAAI;AACzB,UAAM,MAAM,YAAY,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAC1D,WAAO;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,MAAM,EAAE,GAAG,WAAW,IAAI;AAAA,QAC1B,OAAO,EAAE,MAAM,MAAM,QAAQ,QAAQ,MAAM,YAAY,OAAO,MAAM,KAAK;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;;;AC1CO,IAAM,gBAA8B,CAAC;AAErC,IAAM,WAAW,oBAAI,IAAwB;AAEpD,SAAS,SAAS,KAAuB;AACvC,WAAS,IAAI,IAAI,SAAS,GAAG;AAC7B,gBAAc,KAAK,GAAG;AACxB;AAEA,SAAS,IAAI;AACb,SAAS,IAAI;AACb,SAAS,IAAI;AACb,SAAS,QAAQ;AACjB,SAAS,SAAS;AAClB,SAAS,GAAG;AACZ,SAAS,MAAM;;;ACHf,IAAM,WAAW,CAAC,SAAS,QAAQ,SAAS,SAAS,SAAS,SAAS,OAAO,WAAW;AAEzF,IAAM,mBAAmB,oBAAI,IAAY,CAAC,GAAG,UAAU,GAAG,SAAS,KAAK,CAAC,CAAC;AAG1E,IAAM,aAAN,cAAyB,MAAM;AAAA,EAC7B,YAA4B,SAAwB,MAAY;AAC9D,UAAM,OAAO;AADa;AAAwB;AAAA,EAEpD;AAAA,EAF4B;AAAA,EAAwB;AAGtD;AAEO,SAAS,MAAM,KAA2B;AAC/C,QAAM,EAAE,QAAQ,QAAQ,UAAU,IAAI,IAAI,GAAG;AAC7C,QAAM,WAAyB,UAAU,IAAI,CAAC,OAAO;AAAA,IACnD,UAAU;AAAA,IACV,SAAS,EAAE;AAAA,IACX,MAAM,EAAE;AAAA,EACV,EAAE;AAEF,QAAM,IAAI,IAAI,OAAO,MAAM;AAC3B,MAAI;AACJ,MAAI;AACF,WAAO,EAAE,UAAU;AAAA,EACrB,SAAS,GAAG;AAEV,QAAI,aAAa,YAAY;AAC3B,QAAE,YAAY,KAAK,EAAE,UAAU,SAAS,SAAS,EAAE,SAAS,MAAM,EAAE,KAAK,CAAC;AAAA,IAC5E,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO,EAAE,MAAM,aAAa,CAAC,GAAG,UAAU,GAAG,EAAE,WAAW,EAAE;AAC9D;AAEA,IAAM,SAAN,MAAa;AAAA,EAMX,YAAoB,MAAe;AAAf;AAClB,SAAK,MAAM;AAAA,MACT,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC;AAAA,MACxB,MAAM,MAAM,KAAK,KAAK;AAAA,MACtB,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI;AAAA,MAC5B,YAAY,CAAC,OAAO,KAAK,WAAW,EAAE;AAAA,MACtC,UAAU,MAAM,KAAK,SAAS;AAAA,MAC9B,WAAW,MAAM,KAAK,UAAU;AAAA,MAChC,WAAW,MAAM,KAAK,UAAU;AAAA,MAChC,WAAW,CAAC,IAAI,MAAM,KAAK,UAAU,IAAI,CAAC;AAAA,MAC1C,QAAQ,CAAC,SAAS,KAAK,OAAO,IAAI;AAAA,MAClC,YAAY,MAAM,KAAK,WAAW;AAAA,MAClC,WAAW,MAAM,UAAe,KAAK,GAAG;AAAA,MACxC,iBAAiB,MAAM,KAAK,gBAAgB;AAAA,MAC5C,YAAY,MAAM,KAAK,WAAW;AAAA,MAClC,MAAM,CAAC,KAAK,MAAM,KAAK,KAAK,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AAAA,EAjBoB;AAAA,EALZ,MAAM;AAAA,EACP,cAA4B,CAAC;AAAA;AAAA,EAEnB;AAAA,EAqBT,KAAK,IAAI,GAAU;AACzB,WAAO,KAAK,KAAK,KAAK,IAAI,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC;AAAA,EAC/D;AAAA,EACQ,OAAc;AACpB,WAAO,KAAK,KAAK,KAAK,IAAI,KAAK,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC;AAAA,EAC7D;AAAA,EACQ,KAAK,KAAa,IAAI,KAAK,KAAK,GAAU;AAChD,UAAM,IAAI,WAAW,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,EAC1D;AAAA;AAAA,EAGQ,SAAS,OAAqB;AACpC,UAAM,OAAO,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC;AAChF,WAAO,EAAE,OAAO,KAAK,KAAK,IAAI;AAAA,EAChC;AAAA;AAAA,EAGQ,cAAoB;AAE1B,QAAI,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,EAAG,MAAK,KAAK;AAC7D,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,YAAM,IAAI,KAAK,KAAK;AACpB,UAAI,EAAE,SAAS,WAAW,iBAAiB,IAAI,EAAE,KAAK,EAAG;AACzD,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEQ,UAAU,IAAY,IAAI,GAAY;AAC5C,UAAM,IAAI,KAAK,KAAK,CAAC;AACrB,WAAO,EAAE,SAAS,WAAW,EAAE,UAAU;AAAA,EAC3C;AAAA,EACQ,WAAW,IAAmB;AACpC,UAAM,IAAI,KAAK,KAAK;AACpB,QAAI,EAAE,SAAS,WAAW,EAAE,UAAU,GAAI,MAAK,KAAK,aAAa,EAAE,eAAeC,UAAS,CAAC,CAAC,EAAE;AAC/F,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACQ,IAAI,MAA4B;AACtC,UAAM,IAAI,KAAK,KAAK;AACpB,QAAI,EAAE,SAAS,KAAM,MAAK,KAAK,YAAY,IAAI,cAAcA,UAAS,CAAC,CAAC,EAAE;AAC1E,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EACQ,WAAkB;AACxB,WAAO,KAAK,IAAI,OAAO;AAAA,EACzB;AAAA,EACQ,YAAoB;AAC1B,UAAM,IAAI,KAAK,IAAI,QAAQ;AAC3B,WAAO,EAAE;AAAA,EACX;AAAA,EACQ,YAAoB;AAC1B,WAAO,KAAK,IAAI,QAAQ,EAAE;AAAA,EAC5B;AAAA,EAEA,YAAsB;AACpB,SAAK,WAAW,MAAM;AACtB,UAAM,OAAO,KAAK,UAAU;AAC5B,SAAK,IAAI,QAAQ;AAEjB,UAAM,OAAiB;AAAA,MACrB;AAAA,MACA,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY,oBAAI,IAAI;AAAA,MACpB,MAAM,CAAC;AAAA,IACT;AAEA,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,YAAM,IAAI,KAAK,KAAK;AACpB,YAAM,QAAQ,EAAE;AAChB,UAAI;AACF,YAAI,EAAE,SAAS,QAAS,MAAK,KAAK,kCAAkCA,UAAS,CAAC,CAAC,EAAE;AACjF,cAAM,MAAM,SAAS,IAAI,EAAE,KAAK;AAChC,YAAI,KAAK;AACP,gBAAM,OAAO,IAAI,MAAM,KAAK,GAAG;AAC/B,eAAK,OAAO,KAAK,SAAS,KAAK;AAC/B,eAAK,KAAK,KAAK,IAAI;AACnB;AAAA,QACF;AAEA,YAAI,KAAK,WAAW,IAAI,EAAE,KAAK,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,UAAU;AAClE,gBAAM,OAAO,KAAK,cAAc;AAChC,eAAK,OAAO,KAAK,SAAS,KAAK;AAC/B,eAAK,KAAK,KAAK,IAAI;AACnB;AAAA,QACF;AACA,gBAAQ,EAAE,OAAO;AAAA,UACf,KAAK,SAAS;AACZ,iBAAK,KAAK;AACV,kBAAM,IAAI,KAAK,SAAS,EAAE;AAC1B,gBAAI,MAAM,KAAM,MAAK,KAAK,sBAAsB,CAAC,8BAA8B,CAAC;AAChF,iBAAK,QAAQ;AACb;AAAA,UACF;AAAA,UACA,KAAK;AACH,iBAAK,KAAK;AACV,iBAAK,OAAO,KAAK,UAAU;AAC3B;AAAA,UACF,KAAK,SAAS;AACZ,iBAAK,KAAK;AACV,kBAAM,IAAI,KAAK,UAAU;AACzB,iBAAK,IAAI,OAAO;AAChB,kBAAM,IAAI,KAAK,UAAU;AACzB,iBAAK,QAAQ,GAAG,CAAC,IAAI,CAAC;AACtB;AAAA,UACF;AAAA,UACA,KAAK;AACH,iBAAK,KAAK;AACV,iBAAK,QAAQ,KAAK,WAAW;AAC7B;AAAA,UACF,KAAK,SAAS;AACZ,kBAAM,IAAI,KAAK,WAAW;AAC1B,cAAE,OAAO,KAAK,SAAS,KAAK;AAC5B,iBAAK,QAAQ;AACb;AAAA,UACF;AAAA,UACA,KAAK,SAAS;AACZ,iBAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,GAAG,KAAK,WAAW,EAAE;AACnD;AAAA,UACF;AAAA,UACA,KAAK,OAAO;AACV,kBAAM,IAAI,KAAK,SAAS;AACxB,cAAE,OAAO,KAAK,SAAS,KAAK;AAC5B,iBAAK,KAAK,KAAK,CAAC;AAChB;AAAA,UACF;AAAA,UACA,KAAK,aAAa;AAChB,kBAAMC,OAAM,KAAK,eAAe,KAAK,UAAU;AAC/C,YAAAA,KAAI,OAAO,KAAK,SAAS,KAAK;AAC9B,gBAAI,KAAK,WAAW,IAAIA,KAAI,IAAI,GAAG;AACjC,mBAAK,KAAK,cAAcA,KAAI,IAAI,wBAAwB,CAAC;AAAA,YAC3D;AACA,iBAAK,WAAW,IAAIA,KAAI,MAAMA,IAAG;AACjC;AAAA,UACF;AAAA,UACA;AACE,iBAAK,KAAK,sBAAsB,EAAE,KAAK,KAAK,CAAC;AAAA,QACjD;AAAA,MACF,SAAS,GAAG;AACV,YAAI,aAAa,YAAY;AAC3B,eAAK,YAAY,KAAK,EAAE,UAAU,SAAS,SAAS,EAAE,SAAS,MAAM,EAAE,KAAK,CAAC;AAC7E,eAAK,YAAY;AAAA,QACnB,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,WAAK,IAAI,QAAQ;AAAA,IACnB,SAAS,GAAG;AACV,UAAI,aAAa,YAAY;AAC3B,aAAK,YAAY,KAAK,EAAE,UAAU,SAAS,SAAS,EAAE,SAAS,MAAM,EAAE,KAAK,CAAC;AAAA,MAC/E,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,OAAO,MAA8B;AAC3C,WAAO,KAAK,KAAK,EAAE,SAAS;AAAA,EAC9B;AAAA;AAAA,EAGQ,aAAqB;AAC3B,QAAI,KAAK,UAAU,IAAI,GAAG;AACxB,WAAK,KAAK;AACV,WAAK,IAAI,QAAQ;AACjB,aAAO,KAAK,SAAS,EAAE;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAuB;AAC7B,UAAM,IAAI,KAAK,KAAK;AACpB,QAAI,EAAE,SAAS,UAAU;AACvB,WAAK,KAAK;AACV,aAAO,EAAE,KAAK,EAAE,IAAK;AAAA,IACvB;AACA,QAAI,EAAE,SAAS,WAAW,CAAC,MAAM,QAAQ,QAAQ,OAAO,EAAE,SAAS,EAAE,KAAK,GAAG;AAC3E,WAAK,KAAK;AACV,aAAO,EAAE;AAAA,IACX;AACA,SAAK,KAAK,uEAAuED,UAAS,CAAC,CAAC,EAAE;AAAA,EAChG;AAAA,EAEQ,aAAwB;AAC9B,SAAK,IAAI,QAAQ;AACjB,UAAM,IAAI,UAAe,KAAK,GAAG;AACjC,SAAK,IAAI,OAAO;AAChB,UAAM,IAAI,UAAe,KAAK,GAAG;AACjC,SAAK,IAAI,QAAQ;AACjB,WAAO,EAAE,GAAG,EAAE;AAAA,EAChB;AAAA;AAAA,EAGQ,kBAAwC;AAC9C,QAAI,KAAK,OAAO,WAAW,GAAG;AAC5B,YAAM,IAAI,KAAK,IAAI,WAAW;AAC9B,aAAO,EAAE,GAAG,EAAE,GAAG,OAAO,OAAO,EAAE,IAAK,GAAG,GAAG,EAAE,GAAG,OAAO,OAAO,EAAE,KAAM,EAAE;AAAA,IAC3E;AACA,UAAM,IAAI,UAAe,KAAK,GAAG;AACjC,QAAI,KAAK,UAAU,GAAG,EAAG,MAAK,KAAK;AAAA,QAC9B,MAAK,KAAK,mDAAmDA,UAAS,KAAK,KAAK,CAAC,CAAC,EAAE;AACzF,UAAM,IAAI,UAAe,KAAK,GAAG;AACjC,WAAO,EAAE,GAAG,EAAE;AAAA,EAChB;AAAA,EAEQ,aAAwB;AAC9B,UAAM,KAAK,KAAK,WAAW,OAAO;AAClC,SAAK,IAAI,QAAQ;AACjB,UAAM,OAAkB,EAAE,MAAM,GAAG,KAAK;AACxC,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,YAAM,IAAI,KAAK,KAAK;AACpB,UAAI,EAAE,SAAS,QAAS,MAAK,KAAK,oCAAoCA,UAAS,CAAC,CAAC,EAAE;AACnF,cAAQ,EAAE,OAAO;AAAA,QACf,KAAK;AACH,eAAK,KAAK;AACV,eAAK,UAAU,KAAK,UAAU;AAC9B;AAAA,QACF,KAAK;AACH,eAAK,KAAK;AACV,eAAK,UAAU,KAAK,UAAU;AAC9B;AAAA,QACF,KAAK;AACH,eAAK,KAAK;AACV,eAAK,OAAO,KAAK,UAAU;AAC3B;AAAA,QACF;AACE,eAAK,KAAK,wBAAwB,EAAE,KAAK,KAAK,CAAC;AAAA,MACnD;AAAA,IACF;AACA,SAAK,IAAI,QAAQ;AACjB,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,aAA6B;AACnC,SAAK,WAAW,OAAO;AACvB,SAAK,IAAI,QAAQ;AACjB,UAAM,IAAoB,CAAC;AAC3B,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,YAAM,SAAS,KAAK,SAAS;AAC7B,UAAI,KAAK,OAAO,OAAO,EAAG,MAAK,KAAK;AACpC,YAAM,WAAW,gBAAgB,OAAO,KAAK;AAC7C,UAAI,CAAC,UAAU;AACb,aAAK,YAAY,KAAK;AAAA,UACpB,UAAU;AAAA,UACV,SAAS,sBAAsB,OAAO,KAAK;AAAA,UAC3C,MAAM;AAAA,UACN,MAAM,EAAE,OAAO,OAAO,OAAO,KAAK,OAAO,IAAI;AAAA,QAC/C,CAAC;AACD,YAAI,KAAK,OAAO,QAAQ,KAAK,KAAK,OAAO,QAAQ,EAAG,MAAK,KAAK;AAAA,YACzD,MAAK,KAAK,mCAAmC,OAAO,KAAK,GAAG;AACjE;AAAA,MACF;AACA,UAAI,kBAAkB,QAAQ,GAAG;AAC/B,QAAC,EAA8B,QAAQ,IAAI,KAAK,UAAU;AAAA,MAC5D,OAAO;AACL,QAAC,EAA8B,QAAQ,IAAI,KAAK,UAAU;AAAA,MAC5D;AAAA,IACF;AACA,SAAK,IAAI,QAAQ;AACjB,WAAO;AAAA,EACT;AAAA,EAEQ,WAAoB;AAC1B,UAAM,KAAK,KAAK,WAAW,KAAK;AAChC,UAAM,OAAO,KAAK,SAAS,EAAE;AAC7B,SAAK,IAAI,QAAQ;AACjB,UAAM,QAAQ,UAAe,KAAK,GAAG;AACrC,WAAO,EAAE,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK;AAAA,EAC3D;AAAA,EAEQ,gBAA8B;AACpC,UAAM,UAAU,KAAK,SAAS;AAC9B,SAAK,IAAI,QAAQ;AACjB,UAAM,OAAe,CAAC;AACtB,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,WAAK,KAAK,UAAe,KAAK,GAAG,CAAC;AAClC,UAAI,KAAK,OAAO,OAAO,EAAG,MAAK,KAAK;AAAA,UAC/B;AAAA,IACP;AACA,SAAK,IAAI,QAAQ;AACjB,WAAO,EAAE,MAAM,YAAY,IAAI,IAAI,MAAM,QAAQ,OAAO,MAAM,MAAM,QAAQ,KAAK;AAAA,EACnF;AAAA;AAAA,EAGQ,eAAe,YAAqD;AAC1E,UAAM,KAAK,KAAK,WAAW,WAAW;AACtC,UAAM,OAAO,KAAK,SAAS,EAAE;AAC7B,SAAK,IAAI,QAAQ;AACjB,UAAM,SAAmB,CAAC;AAC1B,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,aAAO,KAAK,KAAK,SAAS,EAAE,KAAK;AACjC,UAAI,KAAK,OAAO,OAAO,EAAG,MAAK,KAAK;AAAA,UAC/B;AAAA,IACP;AACA,SAAK,IAAI,QAAQ;AACjB,SAAK,IAAI,QAAQ;AACjB,UAAM,OAAoB,CAAC;AAC3B,WAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,CAAC,KAAK,OAAO,KAAK,GAAG;AACpD,YAAM,IAAI,KAAK,KAAK;AACpB,YAAM,QAAQ,EAAE;AAChB,YAAM,MAAM,SAAS,IAAI,EAAE,KAAK;AAChC,UAAI,KAAK;AACP,cAAM,OAAO,IAAI,MAAM,KAAK,GAAG;AAC/B,aAAK,OAAO,KAAK,SAAS,KAAK;AAC/B,aAAK,KAAK,IAAI;AACd;AAAA,MACF;AACA,UAAI,EAAE,UAAU,OAAO;AACrB,cAAM,IAAI,KAAK,SAAS;AACxB,UAAE,OAAO,KAAK,SAAS,KAAK;AAC5B,aAAK,KAAK,CAAC;AACX;AAAA,MACF;AAEA,WAAK,WAAW,IAAI,EAAE,KAAK,KAAK,EAAE,UAAU,SAAS,KAAK,KAAK,CAAC,EAAE,SAAS,UAAU;AACnF,cAAM,IAAI,KAAK,cAAc;AAC7B,UAAE,OAAO,KAAK,SAAS,KAAK;AAC5B,aAAK,KAAK,CAAC;AACX;AAAA,MACF;AACA,WAAK,KAAK,6EAA6EA,UAAS,CAAC,CAAC,IAAI,CAAC;AAAA,IACzG;AACA,SAAK,IAAI,QAAQ;AACjB,WAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,GAAG,KAAK;AAAA,EAC7C;AACF;AAEA,SAASA,UAAS,GAAkB;AAClC,MAAI,EAAE,SAAS,MAAO,QAAO;AAC7B,MAAI,EAAE,SAAS,SAAU,QAAO,UAAU,KAAK,UAAU,EAAE,KAAK,CAAC;AACjE,SAAO,IAAI,EAAE,KAAK;AACpB;;;AClUA,IAAM,YAAY;AAmBlB,SAAS,YACP,MACA,KACA,SACA,QACA,YACA,aACA,OACS;AACT,QAAM,OAAO,CAAC,MAAkB,YAAY,KAAK,CAAC;AAClD,QAAM,MAAe,CAAC;AAEtB,aAAW,QAAQ,MAAM;AACvB,QAAI,KAAK,SAAS,OAAO;AACvB,UAAI,QAAQ,IAAI,KAAK,IAAI,GAAG;AAC1B,aAAK,EAAE,UAAU,SAAS,SAAS,IAAI,KAAK,IAAI,sCAAsC,MAAM,WAAW,MAAM,KAAK,KAAK,CAAC;AACxH;AAAA,MACF;AACA,UAAI,IAAI,KAAK,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC;AAClD,cAAQ,IAAI,KAAK,IAAI;AAAA,IACvB,WAAW,KAAK,SAAS,YAAY;AACnC,YAAM,OAAO,WAAW,IAAI,KAAK,IAAI;AACrC,UAAI,CAAC,MAAM;AACT,cAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,GAAG,WAAW,KAAK,CAAC,CAAC;AACtD,aAAK,EAAE,UAAU,SAAS,SAAS,sBAAsB,KAAK,IAAI,KAAK,MAAM,uBAAuB,MAAM,KAAK,MAAM,OAAO,OAAO,CAAC,iBAAiB,IAAI,IAAI,IAAI,OAAU,CAAC;AAC5K;AAAA,MACF;AACA,UAAI,SAAS,WAAW;AACtB,aAAK,EAAE,UAAU,SAAS,SAAS,uCAAuC,SAAS,oBAAoB,KAAK,IAAI,KAAK,MAAM,eAAe,MAAM,KAAK,KAAK,CAAC;AAC3J;AAAA,MACF;AACA,UAAI,KAAK,KAAK,WAAW,KAAK,OAAO,QAAQ;AAC3C,aAAK,EAAE,UAAU,SAAS,SAAS,cAAc,KAAK,IAAI,aAAa,KAAK,OAAO,MAAM,wBAAwB,KAAK,KAAK,MAAM,IAAI,MAAM,cAAc,MAAM,KAAK,KAAK,CAAC;AAAA,MAC5K;AACA,YAAM,UAAU,KAAK,OAAO,IAAI,CAAC,GAAG,MAAO,KAAK,KAAK,CAAC,MAAM,SAAY,SAAS,KAAK,KAAK,CAAC,GAAG,KAAK,IAAI,IAAI,CAAE;AAE9G,YAAM,WAAgB,IAAI,IAAI,MAAM;AACpC,YAAM,eAAe,oBAAI,IAAY;AACrC,WAAK,OAAO,QAAQ,CAAC,GAAG,MAAM;AAC5B,iBAAS,IAAI,GAAG,QAAQ,CAAC,CAAC;AAC1B,qBAAa,IAAI,CAAC;AAAA,MACpB,CAAC;AACD,UAAI,KAAK,GAAG,YAAY,KAAK,MAAM,UAAU,cAAc,QAAQ,YAAY,aAAa,QAAQ,CAAC,CAAC;AAAA,IACxG,OAAO;AACL,UAAI,KAAK,EAAE,MAAM,MAAM,KAAK,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,QAAQ,KAAgE;AACtF,QAAM,cAA4B,CAAC;AACnC,QAAM,IAAI,IAAI;AACd,QAAM,OAAO,CAAC,MAAe,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,IAAI;AAC7D,QAAM,SAAS,CAAC,OAAqB,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,EAAE;AAIlE,QAAM,YAAiB,oBAAI,IAAI;AAC/B,QAAM,UAAU,YAAY,IAAI,MAAM,WAAW,oBAAI,IAAI,GAAG,WAAW,IAAI,YAAY,aAAa,CAAC;AAIrG,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,WAAW,CAAC,UAAkB,QAAgB,KAAa,SAAwB;AACvF,QAAI,UAAU;AACZ,UAAI,KAAK,IAAI,QAAQ,GAAG;AACtB,oBAAY,KAAK,EAAE,UAAU,SAAS,SAAS,iBAAiB,QAAQ,KAAK,MAAM,YAAY,KAAK,CAAC;AAAA,MACvG;AACA,WAAK,IAAI,QAAQ;AACjB,aAAO;AAAA,IACT;AACA,QAAI,OAAO,GAAG,MAAM,IAAI,GAAG;AAC3B,WAAO,KAAK,IAAI,IAAI,EAAG,QAAO,GAAG,IAAI;AACrC,SAAK,IAAI,IAAI;AACb,WAAO;AAAA,EACT;AACA,aAAW,OAAO,eAAe;AAC/B,QAAI,MAAM;AACV,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,KAAK,SAAS,IAAI,KAAM;AAC9B;AACA,QAAE,KAAK,SAAS,EAAE,KAAK,IAAI,IAAI,SAAS,EAAE,IAAI,GAAG,KAAK,EAAE,KAAK,IAAI;AAAA,IACnE;AAAA,EACF;AAKA,QAAM,QAAiB,CAAC;AACxB,MAAI,YAAiB,oBAAI,IAAI;AAC7B,QAAM,UAAU,CAAC,MAAoB,SAAS,GAAG,WAAW,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC;AACtF,QAAM,SAAS,CAAC,OAAyB,EAAE,GAAG,QAAQ,EAAE,CAAC,GAAG,GAAG,QAAQ,EAAE,CAAC,EAAE;AAK5E,MAAI,QAAQ;AACZ,MAAI,QAA8D;AAClE,QAAM,WAAW,CAAC,IAAW,QAAiB;AAC5C,UAAM,MAAM,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,EAAE;AACxC,QAAI,QAAQ,SAAS,MAAO,QAAO;AACnC,YAAQ;AACR,YAAQ,iBAAiB,OAAO,IAAI,GAAG;AACvC,WAAO;AAAA,EACT;AACA,QAAM,MAAkB;AAAA,IACtB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA,aAAa,CAAC,IAAI,QAAQ,SAAS,IAAI,GAAG,EAAE;AAAA,IAC5C,UAAU,CAAC,IAAI,QAAQ,SAAS,IAAI,GAAG,EAAE;AAAA,IACzC,MAAM,CAAC,MAAM,YAAY,KAAK,CAAC;AAAA,EACjC;AACA,aAAW,OAAO,eAAe;AAC/B,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,KAAK,SAAS,IAAI,KAAM;AAC9B,kBAAY,EAAE;AACd,UAAI,KAAK,EAAE;AACX,YAAM,IAAI,IAAI,QAAQ,EAAE,MAAM,GAAG;AACjC,QAAE,WAAW;AACb,UAAI,EAAE,SAAS,OAAQ,OAAM,KAAK,CAAC;AAAA,IACrC;AAAA,EACF;AAGA,QAAM,WAAW,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAS;AAG/C,QAAM,WAAW,SAAS;AAAA,IACxB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,UAAU,EAAE,SAAS,eAAe,EAAE,SAAS;AAAA,EACxF;AACA,MAAI,CAAC,UAAU;AACb,gBAAY,KAAK;AAAA,MACf,UAAU;AAAA,MACV,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,SAAS,OAAO,CAAC,MAAkB,EAAE,SAAS,MAAM;AAClE,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,aAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,YAAM,KAAK,MAAM,CAAC;AAClB,YAAM,KAAK,MAAM,CAAC;AAClB,YAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AACtG,YAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AACtG,UAAI,KAAK,KAAK,KAAK,GAAG;AACpB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,SAAS,UAAU,GAAG,EAAE,UAAU,GAAG,EAAE;AAAA,UACvC,MAAM;AAAA,UACN,MAAM,GAAG;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,KAAmB;AAAA,IACvB,MAAM,IAAI;AAAA,IACV,OAAO,IAAI;AAAA,IACX,MAAM,IAAI;AAAA,IACV,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,IAAI,YAAY;AAC3B;;;AClRA,SAAS,WAAW,QAA4B;AAC9C,QAAM,MAAM,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACrD,SAAO;AACT;AAOO,SAAS,iBAAiB,OAA0B;AACzD,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,QAAM,KAAK,WAAW,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AACxD,QAAM,KAAK,WAAW,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AACxD,QAAM,KAAK,GAAG,SAAS;AACvB,QAAM,KAAK,GAAG,SAAS;AAEvB,QAAM,SAAS,CAAC,GAAW,MAAuB;AAChD,QAAI,IAAI,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,GAAI,QAAO;AACjD,UAAM,MAAM,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;AACjC,UAAM,MAAM,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;AACjC,WAAO,MAAM,KAAK,CAAC,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,EAAE;AAAA,EAC3E;AAIA,QAAM,MAAM,CAAC,GAAW,MAAc,GAAG,CAAC,IAAI,CAAC;AAC/C,QAAM,SAAS,oBAAI,IAAqB;AACxC,QAAM,WAAW,CAAC,IAAY,IAAY,IAAY,OAAe;AACnE,UAAM,IAAI,IAAI,IAAI,EAAE;AACpB,UAAM,OAAO,OAAO,IAAI,CAAC;AACzB,QAAI,KAAM,MAAK,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC;AAAA,QAC/B,QAAO,IAAI,GAAG,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,EACvC;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAI,CAAC,OAAO,GAAG,CAAC,EAAG;AACnB,YAAM,KAAK,GAAG,CAAC;AACf,YAAM,KAAK,GAAG,IAAI,CAAC;AACnB,YAAM,KAAK,GAAG,CAAC;AACf,YAAM,KAAK,GAAG,IAAI,CAAC;AACnB,UAAI,CAAC,OAAO,GAAG,IAAI,CAAC,EAAG,UAAS,IAAI,IAAI,IAAI,EAAE;AAC9C,UAAI,CAAC,OAAO,IAAI,GAAG,CAAC,EAAG,UAAS,IAAI,IAAI,IAAI,EAAE;AAC9C,UAAI,CAAC,OAAO,GAAG,IAAI,CAAC,EAAG,UAAS,IAAI,IAAI,IAAI,EAAE;AAC9C,UAAI,CAAC,OAAO,IAAI,GAAG,CAAC,EAAG,UAAS,IAAI,IAAI,IAAI,EAAE;AAAA,IAChD;AAAA,EACF;AAIA,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,UAAU,CAAC,GAAU,MAAa,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;AACpE,QAAM,QAAmB,CAAC;AAE1B,QAAM,WAAW,CAAC,MAAa,YAA2D;AACxF,UAAM,OAAO,OAAO,IAAI,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC;AAC3C,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,QAAQ,MAAM,EAAE,CAAC,CAAC;AACnE,QAAI,WAAW,WAAW,EAAG,QAAO;AACpC,QAAI,WAAW,WAAW,KAAK,CAAC,QAAS,QAAO,WAAW,CAAC;AAE5D,QAAI,OAAO,WAAW,CAAC;AACvB,QAAI,YAAY;AAChB,eAAW,KAAK,YAAY;AAC1B,YAAM,MAAM,EAAE,GAAG,EAAE,IAAI,KAAK,GAAG,GAAG,EAAE,IAAI,KAAK,EAAE;AAC/C,YAAM,QAAQ,QAAQ,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI;AAClD,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,aAAW,CAAC,UAAU,IAAI,KAAK,QAAQ;AACrC,eAAW,YAAY,MAAM;AAC3B,YAAM,CAAC,IAAI,EAAE,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI,MAAM;AAC/C,YAAM,QAAe,EAAE,GAAG,IAAI,GAAG,GAAG;AACpC,UAAI,KAAK,IAAI,QAAQ,OAAO,QAAQ,CAAC,EAAG;AACxC,YAAM,OAAgB,CAAC,KAAK;AAC5B,UAAI,MAAM;AACV,UAAI,OAAqB;AACzB,UAAI,MAAuC;AAC3C,aAAO,MAAM;AACX,aAAK,IAAI,QAAQ,KAAK,IAAI,CAAC;AAC3B,YAAI,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,EAAG;AAC9C,aAAK,KAAK,IAAI;AACd,cAAM,EAAE,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,EAAE;AAC7C,cAAM;AACN,eAAO,SAAS,KAAK,GAAG;AAAA,MAC1B;AACA,UAAI,KAAK,UAAU,EAAG,OAAM,KAAK,eAAe,IAAI,CAAC;AAAA,IACvD;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,eAAe,MAAwB;AAC9C,QAAM,IAAI,KAAK;AACf,QAAM,MAAe,CAAC;AACtB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,OAAO,MAAM,IAAI,IAAI,KAAK,CAAC;AACjC,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,MAAM,IAAI,KAAK,CAAC;AAC7B,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,MAAM,KAAK,IAAI,IAAI;AACzB,UAAM,MAAM,KAAK,IAAI,IAAI;AAEzB,QAAI,MAAM,MAAM,MAAM,QAAQ,EAAG,KAAI,KAAK,GAAG;AAAA,EAC/C;AACA,SAAO,IAAI,UAAU,IAAI,MAAM;AACjC;;;AC7GA,SAAS,WAAW,IAA0B;AAC5C,QAAM,IAAI,YAAY;AACtB,aAAW,MAAM,GAAG,UAAU;AAC5B,UAAM,MAAM,SAAS,IAAI,GAAG,IAAI;AAChC,QAAI,CAAC,IAAK;AACV,eAAW,KAAK,IAAI,OAAO,EAAE,EAAG,cAAa,GAAG,EAAE,GAAG,EAAE,CAAC;AAAA,EAC1D;AACA,MAAI,CAAC,SAAS,EAAE,IAAI,GAAG;AAErB,WAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,KAAM,MAAM,IAAK;AAAA,EACpD;AACA,SAAO;AACT;AAGA,SAAS,cAAc,OAAyB;AAC9C,SAAO,MAAM,MAAM,CAAC,MAAM,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;AAC9F;AAGA,SAAS,cAAc,OAA0B;AAC/C,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK;AACzD;AAQA,SAAS,WAAW,OAAgB,KAA6B;AAC/D,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,QAAM,QAAqB,CAAC;AAC5B,aAAW,OAAO,cAAc,KAAK,GAAG;AACtC,UAAM,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG;AACpD,QAAI,CAAC,cAAc,KAAK,GAAG;AACzB,YAAM,MAAM,SAAS,IAAI,MAAM;AAC/B,YAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,IAAI,OAAO,GAAG,GAAG,CAAC,CAAC;AACtD;AAAA,IACF;AACA,UAAM,QAAgB,CAAC;AACvB,eAAW,KAAK,OAAO;AACrB,iBAAW,KAAK,eAAe,CAAC,GAAG;AACjC,cAAM,UAAU,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS;AACtD,cAAM,MAAM,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;AAClC,cAAM,MAAM,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;AAClC,cAAM,KAAK,EAAE,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,EAAE,CAAC;AAAA,MACvG;AAAA,IACF;AACA,UAAM,QAAQ,iBAAiB,KAAK;AACpC,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,KAAK,EAAE,OAAO,YAAY,MAAM,EAAE,GAAG,UAAU,MAAM,GAAG,OAAO,EAAE,MAAM,QAAQ,UAAU,GAAG,CAAC,KAAK,UAAU,UAAU,EAAE,CAAC;AAC/H,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM,EAAE,GAAG,UAAU,MAAM;AAAA,MAC3B,OAAO,EAAE,MAAM,QAAQ,QAAQ,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,YAAY,UAAU,QAAQ;AAAA,IACtG,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAQO,SAAS,QAAQ,IAAkB,OAAuB,CAAC,GAAU;AAC1E,QAAM,QAAQ,cAAc,WAAW,eAAe,GAAG,OAAO,KAAK,KAAK,CAAC;AAC3E,QAAM,KAAK,MAAM;AAEjB,QAAM,IAAI,WAAW,EAAE;AACvB,QAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,QAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,QAAM,SAAS,KAAK,IAAI,OAAO,OAAO,CAAC;AAEvC,QAAM,QAAqB;AAAA,IACzB;AAAA,IACA,YAAY,SAAS,QAAS;AAAA,IAC9B,MAAM,SAAS,QAAS;AAAA,IACxB,UAAU,SAAS;AAAA,IACnB,UAAU,SAAS;AAAA,IACnB,SAAS,SAAS;AAAA,IAClB,UAAU,SAAS;AAAA,IACnB,QAAQ,SAAS;AAAA,IACjB,UAAU,SAAS;AAAA,EACrB;AAIA,QAAM,MAAiB,EAAE,OAAO,OAAO,QAAQ,EAAE;AACjD,QAAM,QAAqB,CAAC;AAC5B,aAAW,MAAM,GAAG,UAAU;AAC5B,QAAI,GAAG,SAAS,OAAQ;AACxB,UAAM,MAAM,SAAS,IAAI,GAAG,IAAI;AAChC,QAAI,IAAK,OAAM,KAAK,GAAG,IAAI,OAAO,IAAI,GAAG,CAAC;AAAA,EAC5C;AACA,QAAM,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,CAAC;AAEvC,SAAO;AAAA,IACL,OAAO,QAAQ,MAAM,SAAS;AAAA,IAC9B,QAAQ,QAAQ,MAAM,SAAS;AAAA,IAC/B,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,GAAG;AAAA,IACV,OAAO,GAAG;AAAA,IACV,OAAO,GAAG;AAAA,IACV,MAAM,GAAG;AAAA,IACT,WAAW,cAAc,GAAG,KAAK;AAAA,EACnC;AACF;;;ACvGO,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACrBA,SAAS,IAAI,GAAmB;AAC9B,QAAM,IAAI,KAAK,MAAM,IAAI,GAAG,IAAI;AAChC,SAAO,OAAO,GAAG,GAAG,EAAE,IAAI,MAAM,OAAO,CAAC;AAC1C;AACA,IAAM,KAAK,CAAC,MAAqB,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AAExD,SAAS,IAAI,GAAmB;AAC9B,SAAO,EACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,IAAM,eAAe,CAAC,KAAK,KAAM,KAAM,KAAM,KAAO,KAAO,KAAO,GAAM;AACxE,SAAS,cAAc,QAAwB;AAC7C,MAAI,OAAO,aAAa,CAAC;AACzB,aAAW,KAAK,aAAc,KAAI,KAAK,OAAQ,QAAO;AACtD,SAAO;AACT;AAGA,SAAS,YAAY,OAAsB;AACzC,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,MAAI,IAAI,YAAY,MAAM,MAAM,mBAAmB,IAAI,MAAM,SAAS,CAAC,CAAC;AACxE,MAAI,MAAM,QAAS,MAAK,oBAAoB,MAAM,OAAO;AACzD,SAAO;AACT;AAGA,SAAS,UAAU,OAAsB;AACvC,MAAI,IAAI,UAAU,MAAM,QAAQ,MAAM;AACtC,MAAI,MAAM,SAAU,MAAK,eAAe,MAAM,QAAQ;AACtD,MAAI,MAAM,OAAQ,MAAK,YAAY,MAAM,MAAM,mBAAmB,IAAI,MAAM,SAAS,CAAC,CAAC;AACvF,MAAI,MAAM,SAAU,MAAK,qBAAqB,MAAM,QAAQ;AAC5D,MAAI,MAAM,KAAM,MAAK,sBAAsB,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC;AACnF,SAAO;AACT;AAEA,SAAS,WAAW,OAA0B;AAC5C,SAAO,MAAM,IAAI,CAAC,SAAS,OAAO,KAAK,IAAI,EAAE,EAAE,KAAK,KAAK,IAAI,IAAI,EAAE,KAAK,GAAG;AAC7E;AAGA,SAAS,UAAU,MAAyB;AAC1C,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,UAAQ,KAAK,GAAG;AAAA,IACd,KAAK;AACH,aAAO,oBAAoB,KAAK,IAAI,IAAI,EAAE,EAAE,KAAK,GAAG,CAAC,WAAW,MAAM,QAAQ,MAAM,IAAI,YAAY,KAAK,CAAC;AAAA,IAC5G,KAAK;AACH,aAAO,aAAa,IAAI,KAAK,EAAE,CAAC,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,aAAa,MAAM,UAAU,MAAM,mBAAmB,IAAI,MAAM,SAAS,CAAC,CAAC,IAAI,MAAM,UAAU,oBAAoB,MAAM,OAAO,MAAM,EAAE;AAAA,IAC7O,KAAK;AACH,aAAO,YAAY,WAAW,KAAK,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC;AAAA,IAC/D,KAAK;AACH,aAAO,cAAc,GAAG,KAAK,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,QAAQ,KAAK,KAAK,IAAI,GAAG,KAAK,GAAG,CAAC,IAAI,UAAU,KAAK,CAAC;AAAA,IAC3H,KAAK,QAAQ;AACX,YAAM,SAAS,KAAK,WAAW,SAAY,iBAAiB,KAAK,MAAM,MAAM;AAC7E,YAAM,YAAY,KAAK,WAAW,SAAY,sBAAsB,IAAI,KAAK,MAAM,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,OAAO;AAC/H,aAAO,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,gBAAgB,IAAI,KAAK,IAAI,CAAC,WAAW,MAAM,QAAQ,MAAM,kBAAkB,KAAK,MAAM,wBAAwB,KAAK,QAAQ,IAAI,MAAM,GAAG,SAAS,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,IACjO;AAAA,EACF;AACF;AAGO,SAAS,UAAU,OAAc,OAAuB,CAAC,GAAW;AACzE,QAAM,QAAQ,MAAM;AACpB,QAAM,QAAQ,MAAM;AACpB,QAAM,IAAI,MAAM;AAChB,QAAM,SAAS,MAAM;AACrB,QAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AAEnC,QAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,QAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,QAAM,MAAM,EAAE,OAAO;AACrB,QAAM,MAAM,EAAE,OAAO;AACrB,QAAM,MAAM,QAAQ,SAAS;AAC7B,QAAM,MAAM,QAAQ,SAAS;AAE7B,QAAM,MAAgB,CAAC;AACvB,QAAM,WAAW,KAAK,QAClB,UAAU,IAAI,KAAK,KAAK,CAAC,aAAa,IAAK,KAAK,QAAQ,MAAO,GAAG,CAAC,MACnE;AACJ,MAAI;AAAA,IACF,2CAA2C,QAAQ,aAAa,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,kBAAkB,MAAM,IAAI;AAAA,EAC1I;AAGA,QAAM,WAAW,EAAE,KAAK,KAAK,UAAU,MAAM,MAAM,MAAM,WAAW,MAAM,MAAM,WAAW;AAC3F,QAAM,WAAW,MAAM,UAAU,IAAI,CAAC,MAAM,aAAa,GAAe,QAAQ,CAAC,EAAE,KAAK,EAAE;AAC1F,MAAI,KAAK,SAAS,QAAQ,SAAS;AAGnC,MAAI,KAAK,YAAY,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,WAAW,MAAM,EAAE,KAAK;AAG9G,aAAW,QAAQ,eAAe;AAChC,eAAW,QAAQ,MAAM,MAAO,KAAI,KAAK,UAAU,KAAM,KAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EACnF;AAGA,MAAI,KAAK,WAAW,MAAM,OAAO,GAAG,QAAQ,QAAQ,KAAK,CAAC;AAC1D,MAAI,KAAK,SAAS,GAAG,QAAQ,QAAQ,MAAM,KAAK,CAAC;AACjD,QAAM,KAAK,WAAW,MAAM,OAAO,MAAM,OAAO,GAAG,QAAQ,QAAQ,MAAM,KAAK;AAC9E,MAAI,GAAI,KAAI,KAAK,EAAE;AAEnB,MAAI,KAAK,QAAQ;AACjB,SAAO,IAAI,KAAK,IAAI;AACtB;AAEA,SAAS,WAAW,OAAiB,GAAW,QAAgB,QAAgB,OAAsB;AACpG,QAAM,IAAI,SAAS;AACnB,QAAM,KAAK,EAAE,OAAO;AACpB,QAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,MAAI;AACJ,UAAQ,OAAO;AAAA,IACb,KAAK;AAAM,YAAM;AAAG;AAAA,IACpB,KAAK;AAAQ,YAAM;AAAK;AAAA,IACxB,KAAK;AAAQ,YAAM;AAAK;AAAA,IACxB,KAAK;AAAS,YAAM;AAAI;AAAA,IACxB;AAAS,YAAM,OAAO,UAAU,WAAW,MAAM,MAAM;AAAA,EACzD;AACA,QAAM,KAAK,SAAS;AAGpB,QAAM,MAAM,GAAG,IAAI,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC;AAC1J,QAAM,MAAO,MAAM,KAAK,KAAM;AAE9B,QAAM,KAAK,KAAK,IAAI,GAAG;AACvB,QAAM,KAAK,CAAC,KAAK,IAAI,GAAG;AACxB,QAAM,KAAK,KAAK,MAAM,IAAI,KAAK;AAC/B,QAAM,KAAK,KAAK,MAAM,IAAI,KAAK;AAC/B,SACE,uBACoB,GAAG,WAAW,MAAM,UAAU,uBAAuB,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,gBAC3F,IAAI,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC,WAAW,MAAM,UAAU;AAGxF;AAEA,SAAS,SAAS,GAAW,QAAgB,QAAgB,MAAc,OAAsB;AAC/F,QAAM,SAAS,cAAc,SAAS,GAAG;AACzC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,QAAM,MAAM,SAAS;AACrB,QAAM,KAAK,SAAS;AACpB,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,SAAS;AAEtB,QAAM,KAAK,YAAY,IAAI,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,WAAW,MAAM,UAAU,KAAK;AACvH,QAAM;AAAA,IACJ,YAAY,IAAI,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,yBAAyB,MAAM,UAAU,mBAAmB,IAAI,IAAI,CAAC;AAAA,EAC1J;AACA,QAAM;AAAA,IACJ,YAAY,IAAI,EAAE,CAAC,QAAQ,IAAI,KAAK,MAAM,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC,WAAW,MAAM,UAAU;AAAA,EACjG;AACA,QAAM;AAAA,IACJ,YAAY,IAAI,KAAK,MAAM,CAAC,QAAQ,IAAI,KAAK,MAAM,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC,WAAW,MAAM,UAAU,sDAAsD,SAAS,GAAI;AAAA,EAC7K;AACA,SAAO,MAAM,MAAM,KAAK,EAAE,CAAC;AAC7B;AAEA,SAAS,WAAW,GAA0B,OAA2B,GAAW,QAAgB,QAAgB,MAAc,OAA6B;AAC7J,MAAI,CAAC,KAAK,CAAC,MAAO,QAAO;AACzB,QAAM,OAAO,SAAS;AACtB,QAAM,OAAO,SAAS;AACtB,QAAM,KAAK,EAAE,OAAO;AACpB,QAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,QAAM,KAAK,SAAS;AACpB,QAAM,MAAM,OAAO;AACnB,QAAM,QAAoC,CAAC;AAC3C,MAAI,GAAG,QAAS,OAAM,KAAK,EAAE,GAAG,WAAW,GAAG,EAAE,QAAQ,CAAC;AACzD,MAAI,GAAG,QAAS,OAAM,KAAK,EAAE,GAAG,YAAY,GAAG,EAAE,QAAQ,CAAC;AAC1D,MAAI,GAAG,KAAM,OAAM,KAAK,EAAE,GAAG,QAAQ,GAAG,EAAE,KAAK,CAAC;AAChD,MAAI,MAAO,OAAM,KAAK,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9C,QAAM,QAAkB,CAAC;AACzB,QAAM;AAAA,IACJ,YAAY,IAAI,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,yBAAyB,MAAM,UAAU,mBAAmB,IAAI,IAAI,CAAC;AAAA,EACpJ;AACA,QAAM,OAAO,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC5C,QAAM,QAAQ,CAAC,IAAI,MAAM;AACvB,UAAM,KAAK,KAAK,QAAQ,IAAI;AAC5B,UAAM;AAAA,MACJ,YAAY,IAAI,KAAK,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,gBAAgB,IAAI,KAAK,GAAG,CAAC,WAAW,MAAM,eAAe,iCAAiC,IAAI,GAAG,CAAC,CAAC;AAAA,IACjJ;AACA,UAAM;AAAA,MACJ,YAAY,IAAI,KAAK,OAAO,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,gBAAgB,IAAI,EAAE,CAAC,WAAW,MAAM,UAAU,mDAAmD,IAAI,GAAG,CAAC,CAAC;AAAA,IAC/J;AACA,QAAI,IAAI;AACN,YAAM;AAAA,QACJ,aAAa,IAAI,EAAE,CAAC,SAAS,IAAI,KAAK,OAAO,CAAC,CAAC,SAAS,IAAI,KAAK,IAAI,CAAC,SAAS,IAAI,KAAK,OAAO,CAAC,CAAC,aAAa,MAAM,UAAU,mBAAmB,IAAI,OAAO,GAAG,CAAC;AAAA,MAClK;AAAA,EACJ,CAAC;AACD,SAAO,MAAM,MAAM,KAAK,EAAE,CAAC;AAC7B;;;ACzLO,SAAS,gBAAgB,QAAgB,QAA+C;AAC7F,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,OAAO,MAAM,CAAC;AACrD,MAAI,OAAO;AACX,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,OAAO,CAAC,MAAM,MAAM;AACtB;AACA,YAAM;AAAA,IACR,OAAO;AACL;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,MAAM,IAAI;AACrB;AAGA,SAAS,UAAU,QAAgB,QAAwB;AACzD,MAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,OAAO,MAAM,CAAC;AACnD,SAAO,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,KAAM;AACxC,SAAO;AACT;AAGA,SAAS,QAAQ,QAAgB,QAAwB;AACvD,MAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,OAAO,MAAM,CAAC;AACnD,SAAO,IAAI,OAAO,UAAU,OAAO,CAAC,MAAM,KAAM;AAChD,SAAO;AACT;AAgBO,SAAS,iBAAiB,QAAgB,GAAuB;AACtE,QAAM,UAAU,EAAE,OAAO,IAAI,EAAE,IAAI,MAAM;AACzC,QAAME,UAAS,GAAG,EAAE,QAAQ,GAAG,OAAO,KAAK,EAAE,OAAO;AACpD,QAAM,QAAkB,CAACA,OAAM;AAE/B,MAAI,EAAE,MAAM;AACV,UAAM,EAAE,MAAM,IAAI,IAAI,gBAAgB,QAAQ,EAAE,KAAK,KAAK;AAC1D,UAAM,KAAK,UAAU,QAAQ,EAAE,KAAK,KAAK;AACzC,UAAM,KAAK,QAAQ,QAAQ,EAAE,KAAK,KAAK;AACvC,UAAM,UAAU,OAAO,MAAM,IAAI,EAAE;AAEnC,UAAM,aAAa,EAAE,KAAK,QAAQ;AAClC,UAAM,WAAW,KAAK,IAAI,EAAE,KAAK,KAAK,EAAE,IAAI;AAC5C,UAAM,WAAW,KAAK,IAAI,GAAG,WAAW,UAAU;AAElD,UAAM,SAAS,OAAO,IAAI;AAC1B,UAAM,MAAM,IAAI,OAAO,OAAO,MAAM;AACpC,UAAM,KAAK,GAAG,GAAG,QAAQ,IAAI,IAAI,GAAG,EAAE;AACtC,UAAM,KAAK,GAAG,GAAG,IAAI;AACrB,UAAM,KAAK,GAAG,MAAM,MAAM,OAAO,EAAE;AACnC,UAAM,KAAK,GAAG,GAAG,MAAM,IAAI,OAAO,UAAU,CAAC,GAAG,IAAI,OAAO,QAAQ,CAAC,EAAE;AACtE,eAAW,QAAQ,EAAE,SAAS,CAAC,GAAG;AAChC,YAAM,KAAK,GAAG,GAAG,YAAY,IAAI,EAAE;AAAA,IACrC;AAAA,EACF,OAAO;AACL,eAAW,QAAQ,EAAE,SAAS,CAAC,GAAG;AAChC,YAAM,KAAK,aAAa,IAAI,EAAE;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACtFA,SAAS,IAAI,GAAmB;AAC9B,QAAM,IAAI,KAAK,MAAM,IAAI,GAAG,IAAI;AAChC,SAAO,OAAO,GAAG,GAAG,EAAE,IAAI,MAAM,OAAO,CAAC;AAC1C;AAEA,IAAM,aAAN,MAAiB;AAAA,EACP,MAAgB,CAAC;AAAA;AAAA,EAGzB,KAAK,MAAc,OAA8B;AAC/C,SAAK,IAAI,KAAK,OAAO,IAAI,GAAG,OAAO,KAAK,CAAC;AAAA,EAC3C;AAAA,EAEA,KAAK,OAAe,GAAU,GAAgB;AAC5C,SAAK,KAAK,GAAG,MAAM;AACnB,SAAK,KAAK,GAAG,KAAK;AAClB,SAAK,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;AACtB,SAAK,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;AACvB,SAAK,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;AACtB,SAAK,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,EACzB;AAAA,EAEA,IAAI,OAAe,QAAe,QAAgB,UAAkB,QAAsB;AACxF,SAAK,KAAK,GAAG,KAAK;AAClB,SAAK,KAAK,GAAG,KAAK;AAClB,SAAK,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC;AAC3B,SAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,SAAK,KAAK,IAAI,IAAI,MAAM,CAAC;AACzB,SAAK,KAAK,IAAI,IAAI,QAAQ,CAAC;AAC3B,SAAK,KAAK,IAAI,IAAI,MAAM,CAAC;AAAA,EAC3B;AAAA,EAEA,KAAK,OAAe,IAAW,QAAgB,OAAqB;AAClE,SAAK,KAAK,GAAG,MAAM;AACnB,SAAK,KAAK,GAAG,KAAK;AAClB,SAAK,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC;AACvB,SAAK,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,SAAK,KAAK,IAAI,IAAI,MAAM,CAAC;AACzB,SAAK,KAAK,GAAG,MAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,EACxC;AAAA;AAAA,EAGA,KAAK,OAAe,KAAoB;AACtC,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,WAAK,KAAK,OAAO,IAAI,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,WAAmB;AACjB,WAAO,KAAK,IAAI,KAAK,IAAI,IAAI;AAAA,EAC/B;AACF;AAEA,IAAM,SAAS,CAAC,SAAS,SAAS,SAAS,WAAW,aAAa,WAAW,QAAQ,QAAQ;AAG9F,SAAS,SAAS,OAA2B;AAC3C,UAAQ,OAAO;AAAA,IACb,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,SAAiB;AACxB,QAAM,IAAc,CAAC;AACrB,QAAM,IAAI,CAAC,GAAW,MAAuB,EAAE,KAAK,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAExE,IAAE,GAAG,SAAS;AAAG,IAAE,GAAG,QAAQ;AAAG,IAAE,GAAG,UAAU;AAAG,IAAE,GAAG,QAAQ;AAAG,IAAE,GAAG,QAAQ;AAEhF,IAAE,GAAG,SAAS;AAAG,IAAE,GAAG,QAAQ;AAAG,IAAE,GAAG,OAAO;AAAG,IAAE,GAAG,OAAO;AAAG,IAAE,IAAI,OAAO,MAAM;AAClF,aAAW,QAAQ,QAAQ;AACzB,MAAE,GAAG,OAAO;AAAG,MAAE,GAAG,IAAI;AAAG,MAAE,IAAI,CAAC;AAAG,MAAE,IAAI,CAAC;AAAG,MAAE,GAAG,YAAY;AAAA,EAClE;AACA,IAAE,GAAG,QAAQ;AAAG,IAAE,GAAG,QAAQ;AAC7B,SAAO,EAAE,KAAK,IAAI,IAAI;AACxB;AAGA,SAAS,KAAK,GAAe,MAAuB;AAClD,QAAM,QAAQ,SAAS,KAAK,KAAK;AACjC,QAAM,OAAO,KAAK;AAClB,UAAQ,KAAK,GAAG;AAAA,IACd,KAAK;AACH,QAAE,KAAK,OAAO,KAAK,GAAG;AACtB;AAAA,IACF,KAAK;AACH,QAAE,KAAK,OAAO,KAAK,GAAG,KAAK,CAAC;AAC5B;AAAA,IACF,KAAK;AACH,iBAAW,MAAM,KAAK,MAAO,GAAE,KAAK,OAAO,EAAE;AAC7C;AAAA,IACF,KAAK,OAAO;AACV,YAAM,CAAC,IAAI,EAAE,IAAI,gBAAgB,KAAK,QAAQ,KAAK,OAAO,KAAK,GAAG;AAClE,QAAE,IAAI,OAAO,KAAK,QAAQ,KAAK,GAAG,IAAI,EAAE;AACxC;AAAA,IACF;AAAA,IACA,KAAK;AACH,QAAE,KAAK,OAAO,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK;AAC5C;AAAA,EACJ;AACF;AAGO,SAAS,MAAM,OAAsB;AAC1C,QAAM,IAAI,IAAI,WAAW;AACzB,IAAE,KAAK,GAAG,SAAS;AACnB,IAAE,KAAK,GAAG,UAAU;AACpB,aAAW,QAAQ,MAAM,MAAO,MAAK,GAAG,IAAI;AAC5C,IAAE,KAAK,GAAG,QAAQ;AAClB,SAAO,OAAO,IAAI,EAAE,SAAS,IAAI;AACnC;;;ACnHA,SAAS,UAAU,OAAc,OAA6B;AAC5D,QAAM,IAAI,MAAM;AAChB,MAAI,CAAC,KAAK,MAAM,OAAQ,QAAO;AAE/B,MAAI,EAAE,WAAW,MAAM,EAAG,QAAO,MAAM;AACvC,SAAO;AACT;AAEA,SAASC,YAAW,OAA0B;AAC5C,SAAO,MAAM,IAAI,CAAC,SAAS,OAAO,KAAK,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,KAAK,IAAI,IAAI,EAAE,KAAK,GAAG;AACjG;AAGA,SAAS,WAAW,KAAU,OAAc,OAAoB;AAC9D,QAAM,OAAO,UAAU,OAAO,KAAK;AACnC,QAAM,SAAS,MAAM,UAAU,MAAM,WAAW,SAAS,MAAM,SAAS;AACxE,MAAI,MAAM,UAAU,OAAW,KAAI,UAAU,MAAM,KAAK;AACxD,MAAI,SAAS,MAAM,YAAY,OAAO;AACtC,MAAI,QAAQ,MAAM,YAAY,WAAW,WAAW,MAAM;AAC1D,MAAI,MAAM,KAAM,KAAI,KAAK,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,MAC3D,KAAI,OAAO;AAChB,MAAI,QAAQ,OAAQ,KAAI,cAAc,MAAM,MAAM;AAAA,WACzC,KAAM,KAAI,KAAK,IAAI;AAAA,WACnB,OAAQ,KAAI,OAAO,MAAM;AAAA,MAC7B,KAAI,OAAO;AAClB;AAGA,SAAS,SAAS,KAAU,IAAW,OAAe,MAAc,QAAgB,QAA4B,OAAqB;AACnI,MAAI,OAAO;AACX,MAAI,SAAS,IAAI,EAAE,UAAU,KAAK;AAClC,QAAM,IAAI,IAAI,cAAc,KAAK;AACjC,MAAI,IAAI,GAAG;AACX,MAAI,WAAW,SAAU,MAAK,IAAI;AAAA,WACzB,WAAW,MAAO,MAAK;AAEhC,QAAM,IAAI,GAAG,IAAI,OAAO;AACxB,MAAI,WAAW,QAAW;AACxB,QAAI,KAAK;AACT,QAAI,OAAO,QAAQ,EAAE,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;AAC3C,QAAI,KAAK,OAAO,GAAG,GAAG,EAAE,WAAW,MAAM,CAAC;AAC1C,QAAI,QAAQ;AAAA,EACd,OAAO;AACL,QAAI,KAAK,OAAO,GAAG,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,EAC5C;AACF;AAEA,SAAS,SAAS,KAAU,MAAiB,OAAoB;AAC/D,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,UAAQ,KAAK,GAAG;AAAA,IACd,KAAK;AACH,UAAI,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAC9C,iBAAW,KAAK,OAAO,KAAK;AAC5B;AAAA,IACF,KAAK;AACH,UAAI,OAAO,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,OAAO,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC;AACxD,iBAAW,KAAK,OAAO,KAAK;AAC5B;AAAA,IACF,KAAK;AACH,UAAI,KAAKA,YAAW,KAAK,KAAK,CAAC;AAC/B,iBAAW,KAAK,OAAO,KAAK;AAC5B;AAAA,IACF,KAAK;AACH,UAAI,KAAK,KAAK,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE;AAChH,iBAAW,KAAK,OAAO,KAAK;AAC5B;AAAA,IACF,KAAK;AACH,eAAS,KAAK,KAAK,IAAI,KAAK,OAAO,KAAK,MAAM,KAAK,QAAQ,KAAK,QAAQ,UAAU,OAAO,KAAK,KAAK,SAAS;AAC5G;AAAA,EACJ;AACF;AAGA,eAAsB,MAAM,OAAmC;AAC7D,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,OAAO,QAAkB,GAAG;AAAA,EACnD,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,OAAO,QAAQ,EAAE,IAAI;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,MAAM,EAAE,OAAO;AACrB,QAAM,MAAM,EAAE,OAAO;AACrB,QAAM,IAAI,MAAM;AAChB,QAAM,IAAI,MAAM;AAEhB,QAAM,MAAM,IAAI,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE,CAAC;AACvD,QAAM,SAAuB,CAAC;AAC9B,QAAM,OAAO,IAAI,QAAc,CAACC,UAAS,WAAW;AAClD,QAAI,GAAG,QAAQ,CAAC,MAAkB,OAAO,KAAK,CAAC,CAAC;AAChD,QAAI,GAAG,OAAO,MAAMA,SAAQ,CAAC;AAC7B,QAAI,GAAG,SAAS,CAAC,MAAa,OAAO,CAAC,CAAC;AAAA,EACzC,CAAC;AAGD,MAAI,KAAK;AACT,MAAI,UAAU,CAAC,KAAK,CAAC,GAAG;AAGxB,MAAI,KAAK,KAAK,KAAK,GAAG,CAAC,EAAE,KAAK,MAAM,EAAE;AAGtC,aAAW,QAAQ,eAAe;AAChC,eAAW,QAAQ,MAAM,MAAO,KAAI,KAAK,UAAU,KAAM,UAAS,KAAK,MAAM,KAAK;AAAA,EACpF;AAEA,aAAW,KAAK,KAAK;AAErB,MAAI,QAAQ;AACZ,MAAI,IAAI;AACR,QAAM;AACN,SAAO,OAAO,MAAM;AACtB;AAGA,SAAS,WAAW,KAAU,OAAoB;AAChD,QAAM,EAAE,OAAO,OAAO,QAAQ,EAAE,IAAI;AACpC,QAAM,SAAS,MAAM;AACrB,QAAM,SAAS,MAAM;AACrB,QAAM,OAAO,MAAM;AAGnB;AACE,UAAM,IAAI,SAAS;AACnB,UAAM,KAAK,EAAE,OAAO;AACpB,UAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,UAAM,MAAM,aAAa,MAAM,KAAK;AACpC,UAAM,KAAK,SAAS;AACpB,QAAI,KAAK;AACT,QAAI,OAAO,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;AACpC,QACG,QAAQ,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,EACrG,KAAK,MAAM,UAAU;AACxB,QAAI,QAAQ;AACZ,UAAM,MAAO,MAAM,KAAK,KAAM;AAC9B,UAAM,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK;AAC1C,UAAM,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK;AAC1C,aAAS,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,IAAI,UAAU,QAAW,MAAM,UAAU;AAAA,EAChF;AAGA;AACE,UAAM,SAASC,eAAc,SAAS,GAAG;AACzC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,UAAM,MAAM,SAAS;AACrB,UAAM,KAAK,SAAS;AACpB,UAAM,OAAO,SAAS;AACtB,QAAI,KAAK,IAAI,IAAI,MAAM,GAAG,EAAE,KAAK,MAAM,UAAU;AACjD,QAAI,UAAU,IAAI,EAAE,OAAO;AAC3B,QAAI,KAAK,KAAK,MAAM,IAAI,MAAM,GAAG,EAAE,OAAO,MAAM,UAAU;AAC1D,aAAS,KAAK,EAAE,GAAG,IAAI,GAAG,KAAK,MAAM,GAAG,GAAG,KAAK,IAAI,SAAS,QAAW,MAAM,UAAU;AACxF,aAAS,KAAK,EAAE,GAAG,KAAK,QAAQ,GAAG,KAAK,MAAM,GAAG,GAAG,GAAG,SAAS,GAAI,MAAM,IAAI,UAAU,QAAW,MAAM,UAAU;AAAA,EACrH;AAGA,QAAM,IAAI,MAAM;AAChB,MAAI,KAAK,MAAM,OAAO;AACpB,UAAM,OAAO,SAAS;AACtB,UAAM,OAAO,SAAS;AACtB,UAAM,KAAK,EAAE,OAAO;AACpB,UAAM,KAAK,EAAE,OAAO,SAAS;AAC7B,UAAM,KAAK,SAAS;AACpB,UAAM,MAAM,OAAO;AACnB,UAAM,QAAoC,CAAC;AAC3C,QAAI,GAAG,QAAS,OAAM,KAAK,EAAE,GAAG,WAAW,GAAG,EAAE,QAAQ,CAAC;AACzD,QAAI,GAAG,QAAS,OAAM,KAAK,EAAE,GAAG,YAAY,GAAG,EAAE,QAAQ,CAAC;AAC1D,QAAI,GAAG,KAAM,OAAM,KAAK,EAAE,GAAG,QAAQ,GAAG,EAAE,KAAK,CAAC;AAChD,QAAI,MAAM,MAAO,OAAM,KAAK,EAAE,GAAG,SAAS,GAAG,MAAM,MAAM,CAAC;AAC1D,QAAI,UAAU,IAAI,EAAE,OAAO;AAC3B,QAAI,KAAK,IAAI,IAAI,MAAM,IAAI,EAAE,OAAO,MAAM,UAAU;AACpD,UAAM,OAAO,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC5C,UAAM,QAAQ,CAAC,IAAI,MAAM;AACvB,YAAM,KAAK,KAAK,QAAQ,IAAI;AAC5B,eAAS,KAAK,EAAE,GAAG,KAAK,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,KAAK,KAAK,SAAS,QAAW,MAAM,eAAe;AAC/F,eAAS,KAAK,EAAE,GAAG,KAAK,OAAO,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,OAAO,QAAW,MAAM,UAAU;AACzF,UAAI,IAAI,GAAG;AACT,YAAI,UAAU,OAAO,GAAG,EAAE,OAAO,IAAI,KAAK,OAAO,CAAC,EAAE,OAAO,KAAK,MAAM,KAAK,OAAO,CAAC,EAAE,OAAO,MAAM,UAAU;AAAA,MAC9G;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,aAAa,OAAyB;AAC7C,UAAQ,OAAO;AAAA,IACb,KAAK;AAAM,aAAO;AAAA,IAClB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAS,aAAO;AAAA,IACrB;AAAS,aAAO,OAAO,UAAU,WAAW,MAAM,MAAM;AAAA,EAC1D;AACF;AAEA,IAAMC,gBAAe,CAAC,KAAK,KAAM,KAAM,KAAM,KAAO,KAAO,KAAO,GAAM;AACxE,SAASD,eAAc,QAAwB;AAC7C,MAAI,OAAOC,cAAa,CAAC;AACzB,aAAW,KAAKA,cAAc,KAAI,KAAK,OAAQ,QAAO;AACtD,SAAO;AACT;AAEA,SAAS,OAAO,QAAkC;AAChD,MAAI,QAAQ;AACZ,aAAW,KAAK,OAAQ,UAAS,EAAE;AACnC,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,KAAK,QAAQ;AACtB,QAAI,IAAI,GAAG,MAAM;AACjB,cAAU,EAAE;AAAA,EACd;AACA,SAAO;AACT;;;AC7LA,IAAM,QAAQ,oBAAI,IAA2B;AAC7C,IAAM,YAAY;AAEX,SAAS,QAAQ,QAAgB,OAAuB,CAAC,GAAkB;AAChF,QAAM,MAAM,KAAK,UAAU,CAAC,QAAQ,KAAK,SAAS,MAAM,KAAK,SAAS,IAAI,CAAC;AAC3E,MAAI,CAAC,KAAK,SAAS;AACjB,UAAM,MAAM,MAAM,IAAI,GAAG;AACzB,QAAI,IAAK,QAAO;AAAA,EAClB;AAEA,QAAM,SAAS,gBAAgB,QAAQ,IAAI;AAE3C,MAAI,CAAC,KAAK,SAAS;AACjB,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,SAAS,MAAM,KAAK,EAAE,KAAK,EAAE;AACnC,UAAI,WAAW,OAAW,OAAM,OAAO,MAAM;AAAA,IAC/C;AACA,UAAM,IAAI,KAAK,MAAM;AAAA,EACvB;AACA,SAAO;AACT;AAGA,SAAS,SAAS,QAAgB,GAA6B;AAC7D,MAAI,CAAC,EAAE,KAAM,QAAO,EAAE,SAAS,EAAE,QAAQ;AACzC,QAAM,EAAE,MAAM,IAAI,IAAI,gBAAgB,QAAQ,EAAE,KAAK,KAAK;AAC1D,SAAO,EAAE,SAAS,EAAE,SAAS,MAAM,IAAI;AACzC;AAEA,SAAS,gBAAgB,QAAgB,MAAqC;AAC5E,QAAM,EAAE,MAAM,aAAa,WAAW,IAAI,MAAM,MAAM;AAGtD,QAAM,WAAW,OAAO,QAAQ,IAAI,IAAI;AACxC,QAAM,cAA4B,WAC9B,CAAC,GAAG,YAAY,GAAG,SAAS,WAAW,IACvC,CAAC,GAAG,UAAU;AAElB,QAAM,OAAO,YAAY,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AAC7D,QAAM,SAAS,KAAK,IAAI,CAAC,MAAM,SAAS,QAAQ,CAAC,CAAC;AAClD,QAAM,WAAW,YACd,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,EACtC,IAAI,CAAC,MAAM,SAAS,QAAQ,CAAC,CAAC;AAKjC,MAAI,MAAM;AACV,MAAI;AACJ,MAAI,YAAY,KAAK,WAAW,GAAG;AACjC,YAAQ,QAAQ,SAAS,IAAI,IAAI;AACjC,UAAM,UAAU,OAAO,IAAI;AAAA,EAC7B;AAEA,SAAO,EAAE,KAAK,QAAQ,UAAU,aAAa,KAAK,MAAM,MAAM;AAChE;AAGO,SAAS,aAAmB;AACjC,QAAM,MAAM;AACd;","names":["describe","describe","def","header","regionPath","resolve","niceBarLength","NICE_LENGTHS"]}
package/dist/cli.js CHANGED
@@ -1,13 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  compile,
4
- formatDiagnostic
5
- } from "./chunk-GUNWYUR2.js";
4
+ formatDiagnostic,
5
+ toDxf,
6
+ toPdf
7
+ } from "./chunk-CPK5CI5Y.js";
6
8
 
7
9
  // src/cli.ts
8
10
  import { readFileSync, writeFileSync, watchFile } from "fs";
9
- import { resolve } from "path";
10
- function compileFile(input, output, width) {
11
+ import { resolve as resolvePath } from "path";
12
+ async function compileFile(input, output, format, width) {
11
13
  let source;
12
14
  try {
13
15
  source = readFileSync(input, "utf8");
@@ -16,18 +18,38 @@ function compileFile(input, output, width) {
16
18
  `);
17
19
  return false;
18
20
  }
19
- const { svg, diagnostics } = compile(source, { width, noCache: true });
21
+ const { svg, diagnostics, scene } = compile(source, { width, noCache: true });
20
22
  for (const d of diagnostics) {
21
23
  process.stderr.write(`${formatDiagnostic(source, d)}
22
24
 
23
25
  `);
24
26
  }
25
27
  const errorCount = diagnostics.filter((d) => d.severity === "error").length;
26
- if (errorCount > 0) {
28
+ if (errorCount > 0 || !scene) {
27
29
  process.stderr.write(`\u2717 compilation failed (${errorCount} error${errorCount > 1 ? "s" : ""})
28
30
  `);
29
31
  return false;
30
32
  }
33
+ if (format === "dxf") {
34
+ const dxf = toDxf(scene);
35
+ writeFileSync(output, dxf, "utf8");
36
+ process.stdout.write(`\u2713 ${input} \u2192 ${output} (${dxf.length} bytes, DXF)
37
+ `);
38
+ return true;
39
+ }
40
+ if (format === "pdf") {
41
+ try {
42
+ const pdf = await toPdf(scene);
43
+ writeFileSync(output, pdf);
44
+ process.stdout.write(`\u2713 ${input} \u2192 ${output} (${pdf.length} bytes, PDF)
45
+ `);
46
+ return true;
47
+ } catch (e) {
48
+ process.stderr.write(`error: ${e.message}
49
+ `);
50
+ return false;
51
+ }
52
+ }
31
53
  writeFileSync(output, svg, "utf8");
32
54
  process.stdout.write(`\u2713 ${input} \u2192 ${output} (${svg.length} bytes)
33
55
  `);
@@ -39,14 +61,15 @@ function parseArgs(argv) {
39
61
  const a = argv[i];
40
62
  if (a === "-o" || a === "--out") res.o = argv[++i];
41
63
  else if (a === "-w" || a === "--width") res.width = Number(argv[++i]);
64
+ else if (a === "-f" || a === "--format") res.format = argv[++i];
42
65
  else res._.push(a);
43
66
  }
44
67
  return res;
45
68
  }
46
- function defaultOut(input) {
47
- return input.replace(/\.arch$/i, "") + ".svg";
69
+ function defaultOut(input, format) {
70
+ return input.replace(/\.arch$/i, "") + "." + format;
48
71
  }
49
- function main() {
72
+ async function main() {
50
73
  const [cmd, ...rest] = process.argv.slice(2);
51
74
  const args = parseArgs(rest);
52
75
  if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
@@ -54,30 +77,42 @@ function main() {
54
77
  `arch \u2014 ArchLang compiler
55
78
 
56
79
  Usage:
57
- arch compile <in.arch> [-o out.svg] [-w width]
58
- arch watch <in.arch> [-o out.svg] [-w width]
80
+ arch compile <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]
81
+ arch watch <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]
82
+
83
+ Formats: svg (default) \xB7 dxf (zero-dep) \xB7 pdf (needs optional pdfkit + svg-to-pdfkit)
59
84
  `
60
85
  );
61
86
  process.exit(cmd ? 0 : 1);
62
87
  }
88
+ const fmt = (args.format ?? "svg").toLowerCase();
89
+ if (fmt !== "svg" && fmt !== "dxf" && fmt !== "pdf") {
90
+ process.stderr.write(`error: unknown format "${args.format}" (use svg, dxf, or pdf)
91
+ `);
92
+ process.exit(1);
93
+ }
94
+ const format = fmt;
63
95
  const input = args._[0];
64
96
  if (!input) {
65
97
  process.stderr.write("error: missing input file\n");
66
98
  process.exit(1);
67
99
  }
68
- const output = args.o ? resolve(args.o) : defaultOut(resolve(input));
100
+ const inPath = resolvePath(input);
101
+ const output = args.o ? resolvePath(args.o) : defaultOut(inPath, format);
69
102
  if (cmd === "compile") {
70
- process.exit(compileFile(resolve(input), output, args.width) ? 0 : 1);
103
+ process.exit(await compileFile(inPath, output, format, args.width) ? 0 : 1);
71
104
  } else if (cmd === "watch") {
72
- compileFile(resolve(input), output, args.width);
105
+ await compileFile(inPath, output, format, args.width);
73
106
  process.stdout.write(`watching ${input} \u2026 (Ctrl+C to stop)
74
107
  `);
75
- watchFile(resolve(input), { interval: 300 }, () => compileFile(resolve(input), output, args.width));
108
+ watchFile(inPath, { interval: 300 }, () => {
109
+ void compileFile(inPath, output, format, args.width);
110
+ });
76
111
  } else {
77
112
  process.stderr.write(`error: unknown command "${cmd}"
78
113
  `);
79
114
  process.exit(1);
80
115
  }
81
116
  }
82
- main();
117
+ void main();
83
118
  //# sourceMappingURL=cli.js.map