Implement self-contained grapho architecture with four data types

Major rewrite of grapho CLI to support:
- Type 1 (Config): grapho init <repo-url> clones NixOS config
- Type 2 (Sync): Isolated Syncthing on port 8385 (separate from system)
- Type 3 (Backup): Restic integration with systemd timer
- Type 4 (Server): Mount point for central server data

New features:
- Welcome flow on first run (detects ~/.config/grapho/grapho.toml)
- grapho setup wizard creates directory structure
- grapho sync/backup/server subcommands
- grapho status shows all four data types
- grapho doctor checks system health

Added modules/grapho.nix NixOS module:
- Configures isolated Syncthing (ports 8385, 22001, 21028)
- Sets up grapho-backup systemd service and timer
- Creates directory structure via tmpfiles
- Optional NFS server mount

Updated flake.nix:
- Export grapho NixOS module
- Add grapho CLI package (nix build .#grapho)

Documented additional Lux language limitations:
- String == comparison broken in C backend
- let _ = pattern not supported
- List literals with recursion cause segfaults

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 06:12:58 -05:00
parent 63fedfb525
commit 117e6af528
5 changed files with 984 additions and 293 deletions

View File

@@ -116,15 +116,93 @@ let count = Int.parse(someString) // ERROR: Unknown effect operation
---
## C Backend Issues
### 7. String Equality Comparison Generates Incorrect C Code
**Severity:** High
**Status:** Bug
Using `==` to compare strings generates C code that compares pointers instead of string contents.
```lux
let result = execQuiet("echo yes")
if result == "yes" then ... // C code: (result == "yes") - pointer comparison!
```
**Impact:** String comparisons fail in compiled binaries.
**Workaround:** Use `String.contains` for comparison:
```lux
fn isYes(s: String): Bool = String.contains(s, "yes")
if result |> isYes then ...
```
### 8. String.startsWith Not Available in C Backend
**Severity:** Medium
**Status:** Bug
`String.startsWith` works in interpreter but generates undefined function calls in C.
```lux
String.startsWith(s, "prefix") // C error: lux_string__startsWith undefined
```
**Workaround:** Use `String.contains` instead.
### 9. `let _ = expr` Pattern Not Supported
**Severity:** Low
**Status:** Bug
The underscore wildcard pattern for discarding results doesn't work.
```lux
let _ = Process.exec("...") // ERROR: Expected identifier
```
**Workaround:** Use a named binding:
```lux
let ignore = Process.exec("...")
```
### 10. List Literals and Recursion Cause Segfaults
**Severity:** High
**Status:** Bug
Combining list literals with recursive functions can cause segmentation faults in compiled binaries while working fine in interpreter.
```lux
// This crashes when compiled:
let dirs = ["a", "b", "c"]
fn processDirs(dirs: List<String>): Unit =
match List.head(dirs) {
Some(d) => { ...; match List.tail(dirs) { Some(rest) => processDirs(rest), ... } }
None => ()
}
```
**Workaround:** Avoid list literals with recursive processing. Inline the operations:
```lux
fn processA(): Unit = ...
fn processB(): Unit = ...
fn processC(): Unit = ...
// Call each individually
```
---
## Suggestions for Lux
1. **Add escape sequence support** - At minimum `\"`, `\\`, `\n`, `\t`
2. **Fix String.fromChar** to return String, not Int
3. **Add raw string literals** - Something like `r"..."` or `'''...'''` for shell commands
4. **Fix the double execution bug** in the runtime
4. **Fix the double execution bug** in the runtime (DONE)
5. **Support record type literals** matching their declared type
6. **Add Int.parse and Float.parse** for string-to-number conversion
7. **Consider a heredoc syntax** for multi-line strings with special characters
8. **Fix string equality** - Use strcmp in C backend for string ==
9. **Support `let _ = `** - Allow underscore as discard binding
10. **Fix String.startsWith** in C backend
11. **Fix list literals with recursion** causing segfaults
---
@@ -135,3 +213,6 @@ let count = Int.parse(someString) // ERROR: Unknown effect operation
3. **Quotes in output:** Avoided entirely or generated via shell
4. **Structured types:** Using individual variables instead of records
5. **Numeric parsing:** Keeping counts as strings throughout
6. **String comparison:** Using `String.contains` with helper functions instead of `==`
7. **Discarding results:** Using `let ignore = ...` instead of `let _ = ...`
8. **Lists with recursion:** Replaced with individual function calls