# Lux Language Issues — blu-site SSG Project Issues discovered while building a static site generator in Lux. Each entry includes a reproduction case and the workaround used. --- ## Issue 1: `Html.render()` / `Html.document()` not available in interpreter **Category**: Missing feature **Severity**: High The Html module only works in the JS backend, not the interpreter. All HTML must be generated via string concatenation. **Workaround**: Build all HTML as concatenated strings. --- ## Issue 2: String interpolation `{}` has no escape mechanism **Category**: Missing feature → **Fixed** (added `\{` and `\}` escape sequences) **Severity**: High Any `{` inside a string literal triggers interpolation mode, and there was no way to include literal braces. This breaks when generating JavaScript like `function() { ... }` or JSON like `{}`. **Reproduction**: ```lux let s = "function() { return 1; }" // Parse error: treats { } as interpolation ``` **Fix**: Added `\{` and `\}` as escape sequences in the lexer (src/lexer.rs). Also fixed the formatter (src/formatter.rs) to re-escape `{` and `}` in string literals so that `lux fmt` doesn't break escaped braces. Now: ```lux let s = "function() \{ return 1; \}" // Works, produces literal braces ``` --- ## Issue 3: Module-qualified constructors not supported in pattern matching **Category**: Parser limitation **Severity**: High Cannot use `module.Constructor` in match patterns. The parser expects `=>` but finds `.`. **Reproduction**: ```lux import frontmatter let result = frontmatter.parse(content); match result { frontmatter.ParseResult(front, body) => ... // ERROR: Expected =>, found . } ``` **Workaround**: Consolidated everything into a single file. Alternatively, use `import foo.*` (wildcard imports), though this can cause name conflicts. --- ## Issue 4: Tuple field access (`.0`, `.1`) not supported **Category**: Missing feature **Severity**: High The parser's field access only works on Records (with named fields), not tuples. The `.` operator expects an identifier. **Reproduction**: ```lux let pair = ("hello", 42); let x = pair.0; // ERROR: Expected identifier ``` **Workaround**: Use ADTs (algebraic data types) with accessor functions: ```lux type Pair = | Pair(String, Int) fn first(p: Pair): String = match p { Pair(a, _) => a } ``` --- ## Issue 5: Multi-line function arguments cause parse errors **Category**: Parser limitation **Severity**: High Function call arguments cannot span multiple lines. The parser sees `\n` where it expects `,` or `)`. **Reproduction**: ```lux let result = someFunction( arg1, arg2 ); // ERROR: Expected ,, found \n ``` **Workaround**: Keep all function arguments on a single line, or use `let` bindings for intermediate values: ```lux let a = arg1; let b = arg2; let result = someFunction(a, b); ``` --- ## Issue 6: Multi-line lambdas in function call arguments fail **Category**: Parser limitation **Severity**: High Lambda bodies that span multiple lines inside function call arguments cause parse errors. **Reproduction**: ```lux List.map(items, fn(x: Int): Int => x + 1 // ERROR: Expected ,, found \n ); ``` **Workaround**: Either keep lambdas on one line or extract to named functions: ```lux fn addOne(x: Int): Int = x + 1 List.map(items, addOne) ``` --- ## Issue 7: Effectful callbacks in `List.map`/`forEach`/`fold` **Category**: Type checker limitation **Severity**: Medium The type checker requires pure callbacks for higher-order List functions, but effectful callbacks are often needed (e.g., reading files in a map operation). **Reproduction**: ```lux fn readFile(path: String): String with {File} = File.read(path) let contents = List.map(paths, fn(p: String): String => readFile(p)); // ERROR: Effect mismatch: expected {File}, got {} ``` **Workaround**: Use manual recursion instead of List.map/forEach: ```lux fn mapRead(paths: List): List with {File} = match List.head(paths) { None => [], Some(p) => { let content = readFile(p); match List.tail(paths) { Some(rest) => List.concat([content], mapRead(rest)), None => [content] } } } ``` --- ## Issue 8: `String.indexOf` and `String.lastIndexOf` missing from type checker **Category**: Type checker gap → **Fixed** **Severity**: Medium These functions exist in the interpreter but were not registered in the type checker, causing "Module 'String' has no member" errors. **Fix**: Added type registrations in src/types.rs: - `String.indexOf(String, String) -> Option` - `String.lastIndexOf(String, String) -> Option` --- ## Issue 9: No `List.sort` / `List.sortBy` **Category**: Missing feature **Severity**: Medium No built-in sorting for lists. Must implement manually. **Workaround**: Insertion sort via `List.fold`: ```lux fn sortByDateDesc(items: List): List = List.fold(items, [], sortInsert) fn insertByDate(sorted: List, item: Page): List = { match List.head(sorted) { None => [item], Some(first) => if pgDate(item) >= pgDate(first) then List.concat([item], sorted) else match List.tail(sorted) { Some(rest) => List.concat([first], insertByDate(rest, item)), None => [first, item] } } } ``` --- ## Issue 10: No HashMap/Map type **Category**: Missing feature **Severity**: Medium No associative data structure available. Tag grouping required manual list scanning. **Workaround**: Use `List<(key, value)>` with `List.filter`/`List.find` for lookups. O(n) per lookup. --- ## Issue 11: No regex support **Category**: Missing feature **Severity**: Medium Inline markdown parsing (bold, italic, links, code) required manual character-by-character scanning with index tracking. **Workaround**: Recursive `processInlineFrom(text, i, len, acc)` function scanning character by character. --- ## Issue 12: No multiline string literals **Category**: Missing feature **Severity**: Medium HTML templates require very long single-line strings with many `+` concatenations and `\"` escapes. **Workaround**: Concatenate multiple single-line strings with `+`. --- ## Issue 13: `Json.parse` returns `Result` **Category**: Documentation gap **Severity**: Low Not immediately obvious that `Json.parse` wraps the result in `Ok`/`Err`. Error message "Json.get expects Json, got Constructor" is confusing. **Workaround**: Pattern match on `Ok(j)` / `Err(_)`: ```lux let json = match Json.parse(raw) { Ok(j) => j, Err(_) => ... }; ``` --- ## Issue 14: No `File.copy` **Category**: Missing feature **Severity**: Low Must shell out to copy files/directories. **Workaround**: `Process.exec("cp -r static/* _site/")`. --- ## Issue 15: No file globbing **Category**: Missing feature **Severity**: Low Must manually scan directories and filter by extension. **Workaround**: `File.readDir(dir)` + `List.filter(entries, fn(e) => String.endsWith(e, ".md"))`. --- ## Summary | # | Issue | Severity | Status | |---|-------|----------|--------| | 1 | Html module interpreter-only | High | Open | | 2 | No `\{` `\}` string escapes | High | **Fixed** | | 3 | Module-qualified pattern matching | High | Open | | 4 | Tuple field access `.0` `.1` | High | Open | | 5 | Multi-line function arguments | High | Open | | 6 | Multi-line lambdas in calls | High | Open | | 7 | Effectful callbacks in List HOFs | Medium | Open | | 8 | String.indexOf/lastIndexOf types | Medium | **Fixed** | | 9 | No List.sort | Medium | Open | | 10 | No HashMap/Map | Medium | Open | | 11 | No regex | Medium | Open | | 12 | No multiline strings | Medium | Open | | 13 | Json.parse return type docs | Low | Open | | 14 | No File.copy | Low | Open | | 15 | No file globbing | Low | Open |