@chanmeng666/archlang 0.4.0 → 0.6.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.
- package/README.md +175 -169
- package/dist/{chunk-DHNWMOP7.js → chunk-PABYLU6Z.js} +530 -53
- package/dist/chunk-PABYLU6Z.js.map +1 -0
- package/dist/cli.js +52 -15
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +164 -1
- package/dist/index.js +9 -3
- package/examples/themed.arch +40 -0
- package/package.json +9 -2
- package/dist/chunk-DHNWMOP7.js.map +0 -1
|
@@ -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/registry.ts","../src/geometry/union.ts","../src/render.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, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\");\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/** 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, RenderOp, ResolveCtx } from \"../registry.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 render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const w = resolved as RWall;\r\n const { fmt, pt, theme, sizes } = ctx;\r\n const segs = segmentsOfWall(w);\r\n const ops: RenderOp[] = [];\r\n for (const s of segs) {\r\n const poly = segmentRectangle(s.a, s.b, s.thickness);\r\n ops.push({ pass: \"wallFill\", svg: `<polygon points=\"${poly.map(pt).join(\" \")}\" 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 fa1 = add(s.a, mul(n, h));\r\n const fb1 = add(s.b, mul(n, h));\r\n const fa2 = add(s.a, mul(n, -h));\r\n const fb2 = add(s.b, mul(n, -h));\r\n ops.push({\r\n pass: \"wallFace\",\r\n svg: `<line x1=\"${fmt(fa1.x)}\" y1=\"${fmt(fa1.y)}\" x2=\"${fmt(fb1.x)}\" y2=\"${fmt(fb1.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.wallStroke)}\" stroke-linecap=\"square\"/>`,\r\n });\r\n ops.push({\r\n pass: \"wallFace\",\r\n svg: `<line x1=\"${fmt(fa2.x)}\" y1=\"${fmt(fa2.y)}\" x2=\"${fmt(fb2.x)}\" y2=\"${fmt(fb2.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.wallStroke)}\" stroke-linecap=\"square\"/>`,\r\n });\r\n }\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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): RenderOp[] {\r\n const r = resolved as RRoom;\r\n const { fmt, pt, xml, theme, sizes } = ctx;\r\n const ops: RenderOp[] = [];\r\n const c = rectCorners(r.at.x, r.at.y, r.size.w, r.size.h);\r\n ops.push({ pass: \"floor\", svg: `<polygon points=\"${c.map(pt).join(\" \")}\" 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 ops.push({\r\n pass: \"labels\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy - sizes.roomFont * 0.2)}\" font-size=\"${fmt(sizes.roomFont)}\" fill=\"${theme.roomLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\" font-weight=\"600\">${xml(r.label)}</text>`,\r\n });\r\n }\r\n ops.push({\r\n pass: \"labels\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy + (r.label ? sizes.roomFont * 0.9 : 0))}\" font-size=\"${fmt(sizes.areaFont)}\" fill=\"${theme.areaLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\">${areaM2} m²</text>`,\r\n });\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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 render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const dr = resolved as RDoor;\r\n const seg = dr.host;\r\n if (!seg) return [];\r\n const { fmt, pt, 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 ops: RenderOp[] = [];\r\n ops.push({ pass: \"doors\", svg: `<polygon points=\"${cover.map(pt).join(\" \")}\" 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 = cross < 0 ? 1 : 0;\r\n ops.push({\r\n pass: \"doors\",\r\n svg: `<line x1=\"${fmt(hinge.x)}\" y1=\"${fmt(hinge.y)}\" x2=\"${fmt(leafEnd.x)}\" y2=\"${fmt(leafEnd.y)}\" stroke=\"${theme.doorLeaf}\" stroke-width=\"${fmt(sizes.thin * 1.3)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"doors\",\r\n svg: `<path d=\"M ${pt(leafEnd)} A ${fmt(dr.width)} ${fmt(dr.width)} 0 0 ${sweep} ${pt(farJamb)}\" fill=\"none\" stroke=\"${theme.doorLeaf}\" stroke-width=\"${fmt(sizes.thin)}\" stroke-dasharray=\"${fmt(sizes.thin * 4)} ${fmt(sizes.thin * 3)}\"/>`,\r\n });\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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): RenderOp[] {\r\n const wn = resolved as RWindow;\r\n const seg = wn.host;\r\n if (!seg) return [];\r\n const { fmt, pt, 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 ops: RenderOp[] = [];\r\n ops.push({ pass: \"windows\", svg: `<polygon points=\"${cover.map(pt).join(\" \")}\" 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 const a = add(jA, mul(n, off));\r\n const bb = add(jB, mul(n, off));\r\n ops.push({\r\n pass: \"windows\",\r\n svg: `<line x1=\"${fmt(a.x)}\" y1=\"${fmt(a.y)}\" x2=\"${fmt(bb.x)}\" y2=\"${fmt(bb.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n }\r\n ops.push({\r\n pass: \"windows\",\r\n svg: `<line x1=\"${fmt(jA.x)}\" y1=\"${fmt(jA.y)}\" x2=\"${fmt(jB.x)}\" y2=\"${fmt(jB.y)}\" stroke=\"${theme.windowPane}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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): RenderOp[] {\r\n const f = resolved as RFurniture;\r\n const { fmt, pt, xml, theme, sizes } = ctx;\r\n const ops: RenderOp[] = [];\r\n const c = rectCorners(f.at.x, f.at.y, f.size.w, f.size.h);\r\n ops.push({\r\n pass: \"furniture\",\r\n svg: `<polygon points=\"${c.map(pt).join(\" \")}\" fill=\"${theme.furnitureFill}\" stroke=\"${theme.furnitureStroke}\" stroke-width=\"${fmt(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 ops.push({\r\n pass: \"furniture\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy)}\" font-size=\"${fmt(sizes.furnFont)}\" fill=\"${theme.furnitureLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\">${xml(f.label)}</text>`,\r\n });\r\n }\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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): RenderOp[] {\r\n const dm = resolved as RDim;\r\n const { fmt, xml, 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 ops: RenderOp[] = [];\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(dm.from.x)}\" y1=\"${fmt(dm.from.y)}\" x2=\"${fmt(p1.x)}\" y2=\"${fmt(p1.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin * 0.7)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(dm.to.x)}\" y1=\"${fmt(dm.to.y)}\" x2=\"${fmt(p2.x)}\" y2=\"${fmt(p2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin * 0.7)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(p1.x)}\" y1=\"${fmt(p1.y)}\" x2=\"${fmt(p2.x)}\" y2=\"${fmt(p2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\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 ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(t1.x)}\" y1=\"${fmt(t1.y)}\" x2=\"${fmt(t2.x)}\" y2=\"${fmt(t2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\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 ops.push({\r\n pass: \"dims\",\r\n svg: `<text x=\"${fmt(tp.x)}\" y=\"${fmt(tp.y)}\" font-size=\"${fmt(sizes.dimFont)}\" fill=\"${theme.dim}\" text-anchor=\"middle\" dominant-baseline=\"central\" transform=\"rotate(${fmt(angle)} ${fmt(tp.x)} ${fmt(tp.y)})\">${xml(label)}</text>`,\r\n });\r\n return ops;\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, RenderOp, ResolveCtx } from \"../registry.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): RenderOp[] {\r\n const c = resolved as RColumn;\r\n const { fmt, pt, 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 pass: \"furniture\",\r\n svg: `<polygon points=\"${pts.map(pt).join(\" \")}\" fill=\"${theme.column}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(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 * Element registry: the single extension point. Each element type is one module\r\n * exporting an {@link ElementDef}; parse/resolve/render iterate the registry\r\n * rather than a hard-coded switch. Adding an element = one new module + one\r\n * `register` line in `elements/index.ts`.\r\n */\r\n\r\nimport type { Token } from \"./lexer.js\";\r\nimport type { AstElement, ElementKind, ExprPoint, Point } from \"./ast.js\";\r\nimport type { Expr } from \"./expr.js\";\r\nimport type { Diagnostic } from \"./diagnostics.js\";\r\nimport type { ResolvedElement, RWall } from \"./ir.js\";\r\nimport type { Bounds, WallSegment } from \"./geometry.js\";\r\nimport type { Theme } from \"./theme.js\";\r\n\r\n/**\r\n * Ordered render layers. Element ops are bucketed by pass and emitted in this\r\n * order, preserving source order within a pass — this exactly reproduces the\r\n * v0.1 global draw order (all wall fills, then all wall faces, doors before\r\n * windows, labels above fills, …).\r\n */\r\nexport const RENDER_PASSES = [\r\n \"floor\",\r\n \"furniture\",\r\n \"wallFill\",\r\n \"wallFace\",\r\n \"doors\",\r\n \"windows\",\r\n \"labels\",\r\n \"dims\",\r\n \"annotations\",\r\n] as const;\r\nexport type RenderPass = (typeof RENDER_PASSES)[number];\r\n\r\nexport interface RenderOp {\r\n pass: RenderPass;\r\n svg: string;\r\n}\r\n\r\n/** Parser facade handed to `ElementDef.parse` — the existing recursive-descent helpers. */\r\nexport interface ParseCtx {\r\n peek(o?: number): Token;\r\n next(): Token;\r\n eat(type: Token[\"type\"]): Token;\r\n eatKeyword(kw: string): Token;\r\n eatIdent(): Token;\r\n eatNumber(): number;\r\n eatString(): string;\r\n isKeyword(kw: string, o?: number): boolean;\r\n isType(type: Token[\"type\"]): boolean;\r\n /** Parse a `(expr, expr)` point. */\r\n parsePoint(): ExprPoint;\r\n /** Parse an arithmetic expression. */\r\n parseExpr(): Expr;\r\n /** Parse a size: either a `WxH` dimension literal or `<expr> x <expr>`. */\r\n parseDimensions(): { w: Expr; h: Expr };\r\n parseIdOpt(): string;\r\n /** Report a fatal parse error at `t` (defaults to the current token); never returns. */\r\n fail(msg: string, t?: Token): never;\r\n}\r\n\r\n/** Semantic-analysis facade handed to `ElementDef.resolve`. */\r\nexport interface ResolveCtx {\r\n grid: number;\r\n snap(v: number): number;\r\n snapPt(p: Point): Point;\r\n /** Evaluate an expression against the current binding environment. */\r\n eval(e: Expr): number;\r\n /** Evaluate an expression-point to a concrete point. */\r\n evalPt(p: ExprPoint): Point;\r\n /** Resolved id of the element currently being resolved. */\r\n id: string;\r\n /** Resolved walls, ready before openings resolve (walls resolve first). */\r\n walls: RWall[];\r\n hostSegment(at: Point, ref?: string): WallSegment | null;\r\n isOnWall(at: Point, ref?: string): boolean;\r\n diag(d: Diagnostic): void;\r\n}\r\n\r\nexport interface RenderSizes {\r\n refDim: number;\r\n wallStroke: number;\r\n thin: number;\r\n roomFont: number;\r\n areaFont: number;\r\n dimFont: number;\r\n furnFont: number;\r\n margin: number;\r\n hatchGap: number;\r\n}\r\n\r\n/** Render facade: number formatting, theme, derived sizes, and drawing bounds. */\r\nexport interface RenderCtx {\r\n fmt(v: number): string;\r\n pt(p: Point): string;\r\n xml(s: string): string;\r\n theme: Theme;\r\n sizes: RenderSizes;\r\n bounds: Bounds;\r\n}\r\n\r\n/**\r\n * One element type. `TNode`/`TResolved` are the concrete node/IR types; the\r\n * registry stores these widened to the unions, and each module narrows via the\r\n * `kind` discriminant.\r\n */\r\nexport interface ElementDef {\r\n kind: ElementKind;\r\n keyword: string;\r\n parse(ctx: ParseCtx): AstElement;\r\n /** Auto-id prefix (e.g. \"room\", or a wall/furniture's category). */\r\n idPrefix(node: AstElement): string;\r\n resolve(node: AstElement, ctx: ResolveCtx): ResolvedElement;\r\n /** Points this element contributes to the drawing bounds. */\r\n bounds(resolved: ResolvedElement): Point[];\r\n render(resolved: ResolvedElement, ctx: RenderCtx): RenderOp[];\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","/** Renders a resolved plan (IR) to a professional SVG floor plan. Deterministic. */\r\n\r\nimport type { Point } from \"./ast.js\";\r\nimport type { CompileOptions } from \"./types.js\";\r\nimport type { ResolvedPlan, RWall } from \"./ir.js\";\r\nimport type { RenderCtx, RenderOp, RenderSizes } from \"./registry.js\";\r\nimport { RENDER_PASSES } from \"./registry.js\";\r\nimport { registry } from \"./elements/index.js\";\r\nimport type { Bounds } from \"./geometry.js\";\r\nimport { emptyBounds, extendBounds, segmentRectangle, segmentsOfWall } from \"./geometry.js\";\r\nimport type { Rect } from \"./geometry/union.js\";\r\nimport { rectUnionOutline } from \"./geometry/union.js\";\r\nimport type { Material } from \"./hatches.js\";\r\nimport { hatchPattern, patternId } from \"./hatches.js\";\r\nimport type { Theme } from \"./theme.js\";\r\nimport { DEFAULT_THEME, mergeTheme, sanitizeTheme } from \"./theme.js\";\r\n\r\n/** Round to 2 decimals and strip trailing zeros — keeps output stable & compact. */\r\nfunction fmt(v: number): string {\r\n const r = Math.round(v * 100) / 100;\r\n return Object.is(r, -0) ? \"0\" : String(r);\r\n}\r\nconst pt = (p: Point): string => `${fmt(p.x)},${fmt(p.y)}`;\r\n\r\nfunction xml(s: string): string {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/\"/g, \""\");\r\n}\r\n\r\nconst NICE_LENGTHS = [500, 1000, 2000, 5000, 10000, 20000, 50000, 100000];\r\nfunction niceBarLength(target: number): number {\r\n let best = NICE_LENGTHS[0];\r\n for (const v of NICE_LENGTHS) if (v <= target) best = v;\r\n return best;\r\n}\r\n\r\n/** Drawing bounds: each element contributes points via its registry `bounds`. */\r\nfunction planBounds(ir: ResolvedPlan): Bounds {\r\n const b = emptyBounds();\r\n for (const el of ir.elements) {\r\n const def = registry.get(el.kind);\r\n if (!def) continue;\r\n for (const p of def.bounds(el)) extendBounds(b, p.x, p.y);\r\n }\r\n if (!isFinite(b.minX)) {\r\n // Nothing to draw; provide a default frame.\r\n return { minX: 0, minY: 0, maxX: 1000, maxY: 1000 };\r\n }\r\n return b;\r\n}\r\n\r\n/** Is every segment of every wall axis-aligned (horizontal or vertical)? */\r\nfunction allOrthogonal(walls: RWall[]): boolean {\r\n return walls.every((w) => segmentsOfWall(w).every((s) => s.a.x === s.b.x || s.a.y === s.b.y));\r\n}\r\n\r\nfunction loopsToPath(loops: { x: number; y: number }[][]): string {\r\n return loops.map((loop) => \"M \" + loop.map(pt).join(\" L \") + \" Z\").join(\" \");\r\n}\r\n\r\n/** Distinct wall materials present, in a stable (sorted) order. */\r\nfunction materialsUsed(walls: RWall[]): string[] {\r\n return [...new Set(walls.map((w) => w.material))].sort();\r\n}\r\n\r\n/**\r\n * Wall fill + outline, grouped by material so each material's poché unions\r\n * independently and fills with its own hatch. For fully-orthogonal walls the\r\n * segment rectangles are unioned into clean boundary loops (no internal seams);\r\n * angled walls fall back to the per-segment renderer.\r\n */\r\nfunction renderWalls(walls: RWall[], ctx: RenderCtx): RenderOp[] {\r\n if (walls.length === 0) return [];\r\n const ops: RenderOp[] = [];\r\n for (const mat of materialsUsed(walls)) {\r\n const group = walls.filter((w) => w.material === mat);\r\n if (!allOrthogonal(group)) {\r\n const def = registry.get(\"wall\")!;\r\n ops.push(...group.flatMap((w) => def.render(w, ctx)));\r\n continue;\r\n }\r\n const rects: Rect[] = [];\r\n for (const w of group) {\r\n for (const s of segmentsOfWall(w)) {\r\n const corners = segmentRectangle(s.a, s.b, s.thickness);\r\n const xsv = corners.map((c) => c.x);\r\n const ysv = corners.map((c) => c.y);\r\n rects.push({ x0: Math.min(...xsv), y0: Math.min(...ysv), x1: Math.max(...xsv), y1: Math.max(...ysv) });\r\n }\r\n }\r\n const loops = rectUnionOutline(rects);\r\n if (loops.length === 0) continue;\r\n const d = loopsToPath(loops);\r\n ops.push({ pass: \"wallFill\", svg: `<path d=\"${d}\" fill=\"url(#${patternId(mat)})\" fill-rule=\"nonzero\"/>` });\r\n ops.push({\r\n pass: \"wallFace\",\r\n svg: `<path d=\"${d}\" fill=\"none\" stroke=\"${ctx.theme.wallStroke}\" stroke-width=\"${ctx.fmt(ctx.sizes.wallStroke)}\" stroke-linejoin=\"miter\"/>`,\r\n });\r\n }\r\n return ops;\r\n}\r\n\r\nexport function render(ir: ResolvedPlan, opts: CompileOptions = {}): string {\r\n // Resolve theme: defaults < plan `theme { … }` directive < CompileOptions.theme.\r\n // sanitizeTheme escapes all string values once — theme strings are untrusted\r\n // and flow into SVG attributes, so this prevents attribute breakout / XSS.\r\n const THEME: Theme = sanitizeTheme(mergeTheme(DEFAULT_THEME, ir.theme, opts.theme));\r\n const lw = THEME.lineWeight;\r\n\r\n const b = planBounds(ir);\r\n const drawW = b.maxX - b.minX;\r\n const drawH = b.maxY - b.minY;\r\n const refDim = Math.max(drawW, drawH, 1);\r\n\r\n const sizes: RenderSizes = {\r\n refDim,\r\n wallStroke: refDim * 0.0028 * lw,\r\n thin: refDim * 0.0016 * lw,\r\n roomFont: refDim * 0.03,\r\n areaFont: refDim * 0.022,\r\n dimFont: refDim * 0.02,\r\n furnFont: refDim * 0.017,\r\n margin: refDim * 0.17,\r\n hatchGap: refDim * 0.013,\r\n };\r\n const { thin, margin, hatchGap } = sizes;\r\n\r\n const vbX = b.minX - margin;\r\n const vbY = b.minY - margin;\r\n const vbW = drawW + margin * 2;\r\n const vbH = drawH + margin * 2;\r\n\r\n const out: string[] = [];\r\n const svgAttrs = opts.width\r\n ? `width=\"${fmt(opts.width)}\" height=\"${fmt((opts.width * vbH) / vbW)}\"`\r\n : \"\";\r\n out.push(\r\n `<svg xmlns=\"http://www.w3.org/2000/svg\" ${svgAttrs} viewBox=\"${fmt(vbX)} ${fmt(vbY)} ${fmt(vbW)} ${fmt(vbH)}\" font-family=\"${THEME.font}\">`,\r\n );\r\n\r\n // Defs: a hatch <pattern> for each wall material in use (default → \"poche\").\r\n const hatchCtx = { fmt, gap: hatchGap, thin, base: THEME.pocheBase, line: THEME.pocheHatch };\r\n const patterns = materialsUsed(ir.walls)\r\n .map((m) => hatchPattern(m as Material, hatchCtx))\r\n .join(\"\");\r\n out.push(`<defs>${patterns}</defs>`);\r\n\r\n // Background\r\n out.push(`<rect x=\"${fmt(vbX)}\" y=\"${fmt(vbY)}\" width=\"${fmt(vbW)}\" height=\"${fmt(vbH)}\" fill=\"${THEME.bg}\"/>`);\r\n\r\n // Elements: collect ops once (preserving source order), then emit pass by pass.\r\n // Walls are rendered centrally (see renderWalls) so their outlines can be\r\n // unioned across segments — everything else goes through the registry.\r\n const ctx: RenderCtx = { fmt, pt, xml, theme: THEME, sizes, bounds: b };\r\n const ops = ir.elements.flatMap((el) => {\r\n if (el.kind === \"wall\") return [];\r\n const def = registry.get(el.kind);\r\n return def ? def.render(el, ctx) : [];\r\n });\r\n ops.push(...renderWalls(ir.walls, ctx));\r\n for (const pass of RENDER_PASSES) {\r\n for (const op of ops) if (op.pass === pass) out.push(op.svg);\r\n }\r\n\r\n // Plan-level annotations (after element passes): north, scale bar, title block.\r\n out.push(northArrow(ir, b, margin, refDim, THEME));\r\n out.push(scaleBar(b, margin, refDim, thin, THEME));\r\n const tb = titleBlock(ir, b, margin, refDim, thin, THEME);\r\n if (tb) out.push(tb);\r\n\r\n out.push(\"</svg>\");\r\n return out.join(\"\\n\");\r\n}\r\n\r\nfunction northArrow(ir: ResolvedPlan, b: Bounds, margin: number, refDim: number, THEME: Theme): string {\r\n const r = refDim * 0.045;\r\n const cx = b.maxX - r;\r\n const cy = b.minY - margin * 0.55;\r\n let deg: number;\r\n switch (ir.north) {\r\n case \"up\": deg = 0; break;\r\n case \"down\": deg = 180; break;\r\n case \"left\": deg = 270; break;\r\n case \"right\": deg = 90; break;\r\n default: deg = typeof ir.north === \"object\" ? ir.north.deg : 0;\r\n }\r\n const fs = refDim * 0.026;\r\n // Triangle points \"up\" before rotation; only the arrow rotates — the \"N\"\r\n // label stays upright at the pointing end so it always reads correctly.\r\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)}`;\r\n const rad = (deg * Math.PI) / 180;\r\n // North screen vector (rotate the \"up\" vector (0,-1) clockwise by deg).\r\n const nx = Math.sin(rad);\r\n const ny = -Math.cos(rad);\r\n const lx = cx + nx * (r + fs * 0.8);\r\n const ly = cy + ny * (r + fs * 0.8);\r\n return (\r\n `<g>` +\r\n `<polygon points=\"${tri}\" fill=\"${THEME.annotation}\" transform=\"rotate(${fmt(deg)} ${fmt(cx)} ${fmt(cy)})\"/>` +\r\n `<text x=\"${fmt(lx)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"middle\" dominant-baseline=\"central\">N</text>` +\r\n `</g>`\r\n );\r\n}\r\n\r\nfunction scaleBar(b: Bounds, margin: number, refDim: number, thin: number, THEME: Theme): string {\r\n const barLen = niceBarLength(refDim * 0.3);\r\n const x0 = b.minX;\r\n const y0 = b.maxY + margin * 0.55;\r\n const hgt = refDim * 0.014;\r\n const fs = refDim * 0.02;\r\n const parts: string[] = [];\r\n const half = barLen / 2;\r\n // two-segment alternating bar\r\n parts.push(`<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"${THEME.annotation}\"/>`);\r\n parts.push(\r\n `<rect x=\"${fmt(x0 + half)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\r\n );\r\n parts.push(\r\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>`,\r\n );\r\n parts.push(\r\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>`,\r\n );\r\n return `<g>${parts.join(\"\")}</g>`;\r\n}\r\n\r\nfunction titleBlock(ir: ResolvedPlan, b: Bounds, margin: number, refDim: number, thin: number, THEME: Theme): string | null {\r\n const t = ir.title;\r\n if (!t && !ir.scale) return null;\r\n const boxW = refDim * 0.34;\r\n const boxH = margin * 0.82;\r\n const x0 = b.maxX - boxW;\r\n const y0 = b.maxY + margin * 0.15;\r\n const fs = refDim * 0.019;\r\n const pad = boxW * 0.05;\r\n const lines: { k: string; v: string }[] = [];\r\n if (t?.project) lines.push({ k: \"PROJECT\", v: t.project });\r\n if (t?.drawnBy) lines.push({ k: \"DRAWN BY\", v: t.drawnBy });\r\n if (t?.date) lines.push({ k: \"DATE\", v: t.date });\r\n if (ir.scale) lines.push({ k: \"SCALE\", v: ir.scale });\r\n\r\n const parts: string[] = [];\r\n parts.push(\r\n `<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(boxW)}\" height=\"${fmt(boxH)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\r\n );\r\n const rowH = boxH / Math.max(lines.length, 1);\r\n lines.forEach((ln, i) => {\r\n const ly = y0 + rowH * (i + 0.5);\r\n parts.push(\r\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>`,\r\n );\r\n parts.push(\r\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>`,\r\n );\r\n if (i > 0)\r\n parts.push(\r\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)}\"/>`,\r\n );\r\n });\r\n return `<g>${parts.join(\"\")}</g>`;\r\n}\r\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","/**\r\n * DXF export backend — consumes the resolved IR and emits ASCII DXF (R12 /\r\n * AC1009, the most broadly importable flavor). Pure, synchronous, zero-dep:\r\n * DXF is plain text, so this needs no external library and is safe to ship in\r\n * the core. It is NOT part of `compile()` — call it on the IR from `resolve()`.\r\n *\r\n * DXF's Y axis points up, while ArchLang's Y points down (SVG convention), so\r\n * every coordinate's Y is negated here to keep plans right-side-up in CAD.\r\n */\r\n\r\nimport type { Point } from \"../ast.js\";\r\nimport type { ResolvedPlan, ResolvedElement, RDoor, RWindow, RDim } from \"../ir.js\";\r\nimport { add, mul, normal, sub, unit, rectCorners, segmentsOfWall } from \"../geometry.js\";\r\n\r\n/** Deterministic number formatting (round to 4dp, no -0). */\r\nfunction num(v: number): string {\r\n const r = Math.round(v * 1e4) / 1e4;\r\n return Object.is(r, -0) ? \"0\" : String(r);\r\n}\r\n\r\nclass DxfBuilder {\r\n private out: string[] = [];\r\n\r\n /** group-code / value pair. */\r\n pair(code: number, value: string | number): void {\r\n this.out.push(String(code), String(value));\r\n }\r\n\r\n line(layer: string, a: Point, b: Point): void {\r\n this.pair(0, \"LINE\");\r\n this.pair(8, layer);\r\n this.pair(10, num(a.x));\r\n this.pair(20, num(-a.y));\r\n this.pair(11, num(b.x));\r\n this.pair(21, num(-b.y));\r\n }\r\n\r\n arc(layer: string, center: Point, radius: number, startDeg: number, endDeg: number): void {\r\n this.pair(0, \"ARC\");\r\n this.pair(8, layer);\r\n this.pair(10, num(center.x));\r\n this.pair(20, num(-center.y));\r\n this.pair(40, num(radius));\r\n this.pair(50, num(startDeg));\r\n this.pair(51, num(endDeg));\r\n }\r\n\r\n text(layer: string, at: Point, height: number, value: string): void {\r\n this.pair(0, \"TEXT\");\r\n this.pair(8, layer);\r\n this.pair(10, num(at.x));\r\n this.pair(20, num(-at.y));\r\n this.pair(40, num(height));\r\n this.pair(1, value.replace(/\\n/g, \" \"));\r\n }\r\n\r\n rect(layer: string, corners: Point[]): void {\r\n for (let i = 0; i < corners.length; i++) {\r\n this.line(layer, corners[i], corners[(i + 1) % corners.length]);\r\n }\r\n }\r\n\r\n toString(): string {\r\n return this.out.join(\"\\n\") + \"\\n\";\r\n }\r\n}\r\n\r\nconst LAYERS = [\"WALLS\", \"ROOMS\", \"DOORS\", \"WINDOWS\", \"FURNITURE\", \"COLUMNS\", \"DIMS\", \"LABELS\"];\r\n\r\nfunction header(): string {\r\n const h: string[] = [];\r\n const p = (c: number, v: string | number) => h.push(String(c), String(v));\r\n // Minimal HEADER declaring R12.\r\n p(0, \"SECTION\"); p(2, \"HEADER\"); p(9, \"$ACADVER\"); p(1, \"AC1009\"); p(0, \"ENDSEC\");\r\n // TABLES → LAYER table so entities reference real layers.\r\n p(0, \"SECTION\"); p(2, \"TABLES\"); p(0, \"TABLE\"); p(2, \"LAYER\"); p(70, LAYERS.length);\r\n for (const name of LAYERS) {\r\n p(0, \"LAYER\"); p(2, name); p(70, 0); p(62, 7); p(6, \"CONTINUOUS\");\r\n }\r\n p(0, \"ENDTAB\"); p(0, \"ENDSEC\");\r\n return h.join(\"\\n\") + \"\\n\";\r\n}\r\n\r\n/** Door leaf line + swing arc (minor arc), replicating the render geometry. */\r\nfunction emitDoor(b: DxfBuilder, dr: RDoor): void {\r\n const seg = dr.host;\r\n if (!seg) return;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const hw = dr.width / 2;\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 b.line(\"DOORS\", hinge, leafEnd);\r\n\r\n // Arc center=hinge, radius=width, in Y-flipped space; pick the minor arc.\r\n const deg = (p: Point) => (Math.atan2(-(p.y - hinge.y), p.x - hinge.x) * 180) / Math.PI;\r\n const a1 = deg(leafEnd);\r\n const a2 = deg(farJamb);\r\n const ccw = ((a2 - a1) % 360 + 360) % 360;\r\n if (ccw <= 180) b.arc(\"DOORS\", hinge, dr.width, a1, a2);\r\n else b.arc(\"DOORS\", hinge, dr.width, a2, a1);\r\n}\r\n\r\nfunction emitWindow(b: DxfBuilder, wn: RWindow): void {\r\n const seg = wn.host;\r\n if (!seg) return;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const hw = wn.width / 2;\r\n const h = seg.thickness / 2;\r\n const jA = add(wn.at, mul(d, -hw));\r\n const jB = add(wn.at, mul(d, hw));\r\n b.line(\"WINDOWS\", add(jA, mul(n, h)), add(jB, mul(n, h)));\r\n b.line(\"WINDOWS\", add(jA, mul(n, -h)), add(jB, mul(n, -h)));\r\n b.line(\"WINDOWS\", jA, jB); // glazing line\r\n}\r\n\r\nfunction emitDim(b: DxfBuilder, dm: RDim): void {\r\n const dd = unit(sub(dm.to, dm.from));\r\n const dn = normal(dd);\r\n const p1 = add(dm.from, mul(dn, dm.offset));\r\n const p2 = add(dm.to, mul(dn, dm.offset));\r\n b.line(\"DIMS\", p1, p2);\r\n if (dm.text) {\r\n const mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };\r\n b.text(\"DIMS\", mid, 150, dm.text);\r\n }\r\n}\r\n\r\n/** Render a resolved plan as an ASCII DXF document string. */\r\nexport function toDxf(ir: ResolvedPlan): string {\r\n const b = new DxfBuilder();\r\n b.pair(0, \"SECTION\");\r\n b.pair(2, \"ENTITIES\");\r\n\r\n const labelAt = (at: Point, w: number, h: number): Point => ({ x: at.x + w / 2, y: at.y + h / 2 });\r\n\r\n for (const el of ir.elements as ResolvedElement[]) {\r\n switch (el.kind) {\r\n case \"wall\":\r\n for (const s of segmentsOfWall(el)) {\r\n const d = unit(sub(s.b, s.a));\r\n const n = normal(d);\r\n const off = s.thickness / 2;\r\n // Two parallel wall faces convey thickness.\r\n b.line(\"WALLS\", add(s.a, mul(n, off)), add(s.b, mul(n, off)));\r\n b.line(\"WALLS\", add(s.a, mul(n, -off)), add(s.b, mul(n, -off)));\r\n }\r\n break;\r\n case \"room\":\r\n b.rect(\"ROOMS\", rectCorners(el.at.x, el.at.y, el.size.w, el.size.h));\r\n if (el.label) b.text(\"LABELS\", labelAt(el.at, el.size.w, el.size.h), 200, el.label);\r\n break;\r\n case \"furniture\":\r\n b.rect(\"FURNITURE\", rectCorners(el.at.x, el.at.y, el.size.w, el.size.h));\r\n if (el.label) b.text(\"LABELS\", labelAt(el.at, el.size.w, el.size.h), 150, el.label);\r\n break;\r\n case \"column\":\r\n b.rect(\"COLUMNS\", rectCorners(el.at.x, el.at.y, el.size.w, el.size.h));\r\n break;\r\n case \"door\":\r\n emitDoor(b, el);\r\n break;\r\n case \"window\":\r\n emitWindow(b, el);\r\n break;\r\n case \"dim\":\r\n emitDim(b, el);\r\n break;\r\n }\r\n }\r\n\r\n b.pair(0, \"ENDSEC\");\r\n const entities = b.toString();\r\n return header() + entities + \"0\\nEOF\\n\";\r\n}\r\n","/**\r\n * PDF export backend — consumes the produced SVG and renders it into a PDF via\r\n * pdfkit + svg-to-pdfkit. These are OPTIONAL dependencies, lazy-`import()`ed so\r\n * the zero-dep core never hard-requires them; a clear error is thrown if they\r\n * are absent. This is async and Node-oriented — NOT part of `compile()`.\r\n */\r\n\r\n/** Pull width/height (px) out of the SVG's root tag, falling back to viewBox. */\r\nfunction svgSize(svg: string): { width: number; height: number } {\r\n const w = /<svg[^>]*\\bwidth=\"([\\d.]+)/.exec(svg);\r\n const h = /<svg[^>]*\\bheight=\"([\\d.]+)/.exec(svg);\r\n if (w && h) return { width: parseFloat(w[1]), height: parseFloat(h[1]) };\r\n const vb = /<svg[^>]*\\bviewBox=\"[\\d.\\-]+ [\\d.\\-]+ ([\\d.]+) ([\\d.]+)\"/.exec(svg);\r\n if (vb) return { width: parseFloat(vb[1]), height: parseFloat(vb[2]) };\r\n return { width: 800, height: 600 };\r\n}\r\n\r\n/**\r\n * Convert an ArchLang SVG string to a PDF (returned as a Uint8Array).\r\n * Requires the optional `pdfkit` and `svg-to-pdfkit` packages.\r\n */\r\nexport async function toPdf(svg: string): Promise<Uint8Array> {\r\n // Loosely typed: the optional deps may ship without bundled types, and we\r\n // must not statically depend on them. `any` keeps the core build self-contained.\r\n /* eslint-disable @typescript-eslint/no-explicit-any */\r\n let PDFDocument: any;\r\n let SVGtoPDF: any;\r\n try {\r\n PDFDocument = (await import(\"pdfkit\" as string)).default;\r\n SVGtoPDF = (await import(\"svg-to-pdfkit\" as string)).default;\r\n } catch {\r\n throw new Error(\r\n \"PDF export needs the optional dependencies 'pdfkit' and 'svg-to-pdfkit'. \" +\r\n \"Install them: npm install pdfkit svg-to-pdfkit\",\r\n );\r\n }\r\n\r\n const { width, height } = svgSize(svg);\r\n const doc = new PDFDocument({ size: [width, height], margin: 0 });\r\n\r\n const chunks: Uint8Array[] = [];\r\n const done = new Promise<void>((resolve, reject) => {\r\n doc.on(\"data\", (c: Uint8Array) => chunks.push(c));\r\n doc.on(\"end\", () => resolve());\r\n doc.on(\"error\", (e: Error) => reject(e));\r\n });\r\n\r\n SVGtoPDF(doc, svg, 0, 0, { width, height, assumePt: true });\r\n doc.end();\r\n await done;\r\n /* eslint-enable @typescript-eslint/no-explicit-any */\r\n\r\n return concat(chunks);\r\n}\r\n\r\nfunction concat(chunks: Uint8Array[]): Uint8Array {\r\n let total = 0;\r\n for (const c of chunks) total += c.length;\r\n const out = new Uint8Array(total);\r\n let offset = 0;\r\n for (const c of chunks) {\r\n out.set(c, offset);\r\n offset += c.length;\r\n }\r\n return out;\r\n}\r\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 { render } from \"./render.js\";\r\nimport { offsetToLineCol } from \"./diagnostics.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\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 const svg = resolved && errs.length === 0 ? render(resolved.ir, opts) : \"\";\r\n\r\n return { svg, errors, warnings, diagnostics, ast: plan };\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":"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","names":["describe","fmt","pt","fmt","pt","xml","fmt","pt","fmt","pt","fmt","pt","xml","fmt","xml","fmt","pt","describe","def","header","resolve"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
compile,
|
|
4
|
-
formatDiagnostic
|
|
5
|
-
|
|
4
|
+
formatDiagnostic,
|
|
5
|
+
resolve,
|
|
6
|
+
toDxf,
|
|
7
|
+
toPdf
|
|
8
|
+
} from "./chunk-PABYLU6Z.js";
|
|
6
9
|
|
|
7
10
|
// src/cli.ts
|
|
8
11
|
import { readFileSync, writeFileSync, watchFile } from "fs";
|
|
9
|
-
import { resolve } from "path";
|
|
10
|
-
function compileFile(input, output, width) {
|
|
12
|
+
import { resolve as resolvePath } from "path";
|
|
13
|
+
async function compileFile(input, output, format, width) {
|
|
11
14
|
let source;
|
|
12
15
|
try {
|
|
13
16
|
source = readFileSync(input, "utf8");
|
|
@@ -16,7 +19,7 @@ function compileFile(input, output, width) {
|
|
|
16
19
|
`);
|
|
17
20
|
return false;
|
|
18
21
|
}
|
|
19
|
-
const { svg, diagnostics } = compile(source, { width, noCache: true });
|
|
22
|
+
const { svg, diagnostics, ast } = compile(source, { width, noCache: true });
|
|
20
23
|
for (const d of diagnostics) {
|
|
21
24
|
process.stderr.write(`${formatDiagnostic(source, d)}
|
|
22
25
|
|
|
@@ -28,6 +31,27 @@ function compileFile(input, output, width) {
|
|
|
28
31
|
`);
|
|
29
32
|
return false;
|
|
30
33
|
}
|
|
34
|
+
if (format === "dxf") {
|
|
35
|
+
const { ir } = resolve(ast);
|
|
36
|
+
const dxf = toDxf(ir);
|
|
37
|
+
writeFileSync(output, dxf, "utf8");
|
|
38
|
+
process.stdout.write(`\u2713 ${input} \u2192 ${output} (${dxf.length} bytes, DXF)
|
|
39
|
+
`);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (format === "pdf") {
|
|
43
|
+
try {
|
|
44
|
+
const pdf = await toPdf(svg);
|
|
45
|
+
writeFileSync(output, pdf);
|
|
46
|
+
process.stdout.write(`\u2713 ${input} \u2192 ${output} (${pdf.length} bytes, PDF)
|
|
47
|
+
`);
|
|
48
|
+
return true;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
process.stderr.write(`error: ${e.message}
|
|
51
|
+
`);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
31
55
|
writeFileSync(output, svg, "utf8");
|
|
32
56
|
process.stdout.write(`\u2713 ${input} \u2192 ${output} (${svg.length} bytes)
|
|
33
57
|
`);
|
|
@@ -39,14 +63,15 @@ function parseArgs(argv) {
|
|
|
39
63
|
const a = argv[i];
|
|
40
64
|
if (a === "-o" || a === "--out") res.o = argv[++i];
|
|
41
65
|
else if (a === "-w" || a === "--width") res.width = Number(argv[++i]);
|
|
66
|
+
else if (a === "-f" || a === "--format") res.format = argv[++i];
|
|
42
67
|
else res._.push(a);
|
|
43
68
|
}
|
|
44
69
|
return res;
|
|
45
70
|
}
|
|
46
|
-
function defaultOut(input) {
|
|
47
|
-
return input.replace(/\.arch$/i, "") + ".
|
|
71
|
+
function defaultOut(input, format) {
|
|
72
|
+
return input.replace(/\.arch$/i, "") + "." + format;
|
|
48
73
|
}
|
|
49
|
-
function main() {
|
|
74
|
+
async function main() {
|
|
50
75
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
51
76
|
const args = parseArgs(rest);
|
|
52
77
|
if (!cmd || cmd === "help" || cmd === "--help" || cmd === "-h") {
|
|
@@ -54,30 +79,42 @@ function main() {
|
|
|
54
79
|
`arch \u2014 ArchLang compiler
|
|
55
80
|
|
|
56
81
|
Usage:
|
|
57
|
-
arch compile <in.arch> [-o out
|
|
58
|
-
arch watch <in.arch> [-o out
|
|
82
|
+
arch compile <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]
|
|
83
|
+
arch watch <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]
|
|
84
|
+
|
|
85
|
+
Formats: svg (default) \xB7 dxf (zero-dep) \xB7 pdf (needs optional pdfkit + svg-to-pdfkit)
|
|
59
86
|
`
|
|
60
87
|
);
|
|
61
88
|
process.exit(cmd ? 0 : 1);
|
|
62
89
|
}
|
|
90
|
+
const fmt = (args.format ?? "svg").toLowerCase();
|
|
91
|
+
if (fmt !== "svg" && fmt !== "dxf" && fmt !== "pdf") {
|
|
92
|
+
process.stderr.write(`error: unknown format "${args.format}" (use svg, dxf, or pdf)
|
|
93
|
+
`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const format = fmt;
|
|
63
97
|
const input = args._[0];
|
|
64
98
|
if (!input) {
|
|
65
99
|
process.stderr.write("error: missing input file\n");
|
|
66
100
|
process.exit(1);
|
|
67
101
|
}
|
|
68
|
-
const
|
|
102
|
+
const inPath = resolvePath(input);
|
|
103
|
+
const output = args.o ? resolvePath(args.o) : defaultOut(inPath, format);
|
|
69
104
|
if (cmd === "compile") {
|
|
70
|
-
process.exit(compileFile(
|
|
105
|
+
process.exit(await compileFile(inPath, output, format, args.width) ? 0 : 1);
|
|
71
106
|
} else if (cmd === "watch") {
|
|
72
|
-
compileFile(
|
|
107
|
+
await compileFile(inPath, output, format, args.width);
|
|
73
108
|
process.stdout.write(`watching ${input} \u2026 (Ctrl+C to stop)
|
|
74
109
|
`);
|
|
75
|
-
watchFile(
|
|
110
|
+
watchFile(inPath, { interval: 300 }, () => {
|
|
111
|
+
void compileFile(inPath, output, format, args.width);
|
|
112
|
+
});
|
|
76
113
|
} else {
|
|
77
114
|
process.stderr.write(`error: unknown command "${cmd}"
|
|
78
115
|
`);
|
|
79
116
|
process.exit(1);
|
|
80
117
|
}
|
|
81
118
|
}
|
|
82
|
-
main();
|
|
119
|
+
void main();
|
|
83
120
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\r\n/** ArchLang CLI: `arch compile <in.arch> [-o out.svg]`, `arch watch <in.arch>`. */\r\n\r\nimport { readFileSync, writeFileSync, watchFile } from \"node:fs\";\r\nimport { resolve } from \"node:path\";\r\nimport { compile, formatDiagnostic } from \"./index.js\";\r\n\r\
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\r\n/** ArchLang CLI: `arch compile <in.arch> [-o out.svg]`, `arch watch <in.arch>`. */\r\n\r\nimport { readFileSync, writeFileSync, watchFile } from \"node:fs\";\r\nimport { resolve as resolvePath } from \"node:path\";\r\nimport { compile, formatDiagnostic, resolve, toDxf, toPdf } from \"./index.js\";\r\n\r\ntype Format = \"svg\" | \"dxf\" | \"pdf\";\r\n\r\nasync function compileFile(input: string, output: string, format: Format, width?: number): Promise<boolean> {\r\n let source: string;\r\n try {\r\n source = readFileSync(input, \"utf8\");\r\n } catch {\r\n process.stderr.write(`error: cannot read ${input}\\n`);\r\n return false;\r\n }\r\n const { svg, diagnostics, ast } = compile(source, { width, noCache: true });\r\n for (const d of diagnostics) {\r\n process.stderr.write(`${formatDiagnostic(source, d)}\\n\\n`);\r\n }\r\n const errorCount = diagnostics.filter((d) => d.severity === \"error\").length;\r\n if (errorCount > 0) {\r\n process.stderr.write(`✗ compilation failed (${errorCount} error${errorCount > 1 ? \"s\" : \"\"})\\n`);\r\n return false;\r\n }\r\n\r\n if (format === \"dxf\") {\r\n const { ir } = resolve(ast!);\r\n const dxf = toDxf(ir);\r\n writeFileSync(output, dxf, \"utf8\");\r\n process.stdout.write(`✓ ${input} → ${output} (${dxf.length} bytes, DXF)\\n`);\r\n return true;\r\n }\r\n if (format === \"pdf\") {\r\n try {\r\n const pdf = await toPdf(svg);\r\n writeFileSync(output, pdf);\r\n process.stdout.write(`✓ ${input} → ${output} (${pdf.length} bytes, PDF)\\n`);\r\n return true;\r\n } catch (e) {\r\n process.stderr.write(`error: ${(e as Error).message}\\n`);\r\n return false;\r\n }\r\n }\r\n writeFileSync(output, svg, \"utf8\");\r\n process.stdout.write(`✓ ${input} → ${output} (${svg.length} bytes)\\n`);\r\n return true;\r\n}\r\n\r\nfunction parseArgs(argv: string[]): { _: string[]; o?: string; width?: number; format?: string } {\r\n const res: { _: string[]; o?: string; width?: number; format?: string } = { _: [] };\r\n for (let i = 0; i < argv.length; i++) {\r\n const a = argv[i];\r\n if (a === \"-o\" || a === \"--out\") res.o = argv[++i];\r\n else if (a === \"-w\" || a === \"--width\") res.width = Number(argv[++i]);\r\n else if (a === \"-f\" || a === \"--format\") res.format = argv[++i];\r\n else res._.push(a);\r\n }\r\n return res;\r\n}\r\n\r\nfunction defaultOut(input: string, format: Format): string {\r\n return input.replace(/\\.arch$/i, \"\") + \".\" + format;\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const [cmd, ...rest] = process.argv.slice(2);\r\n const args = parseArgs(rest);\r\n\r\n if (!cmd || cmd === \"help\" || cmd === \"--help\" || cmd === \"-h\") {\r\n process.stdout.write(\r\n `arch — ArchLang compiler\\n\\n` +\r\n `Usage:\\n` +\r\n ` arch compile <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]\\n` +\r\n ` arch watch <in.arch> [-o out] [-w width] [-f svg|dxf|pdf]\\n\\n` +\r\n `Formats: svg (default) · dxf (zero-dep) · pdf (needs optional pdfkit + svg-to-pdfkit)\\n`,\r\n );\r\n process.exit(cmd ? 0 : 1);\r\n }\r\n\r\n const fmt = (args.format ?? \"svg\").toLowerCase();\r\n if (fmt !== \"svg\" && fmt !== \"dxf\" && fmt !== \"pdf\") {\r\n process.stderr.write(`error: unknown format \"${args.format}\" (use svg, dxf, or pdf)\\n`);\r\n process.exit(1);\r\n }\r\n const format = fmt as Format;\r\n\r\n const input = args._[0];\r\n if (!input) {\r\n process.stderr.write(\"error: missing input file\\n\");\r\n process.exit(1);\r\n }\r\n const inPath = resolvePath(input);\r\n const output = args.o ? resolvePath(args.o) : defaultOut(inPath, format);\r\n\r\n if (cmd === \"compile\") {\r\n process.exit((await compileFile(inPath, output, format, args.width)) ? 0 : 1);\r\n } else if (cmd === \"watch\") {\r\n await compileFile(inPath, output, format, args.width);\r\n process.stdout.write(`watching ${input} … (Ctrl+C to stop)\\n`);\r\n watchFile(inPath, { interval: 300 }, () => {\r\n void compileFile(inPath, output, format, args.width);\r\n });\r\n } else {\r\n process.stderr.write(`error: unknown command \"${cmd}\"\\n`);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nvoid main();\r\n"],"mappings":"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","names":[]}
|