feat!: map reads are Result(V, Error); emit comma-ok via Go IIFE#94
Conversation
Rvalue `m[k]` on `map[K]V` now infers as `Result(V, Error)` (missing key is
failure). Forst rejects `v, ok := m[k]`; use `ensure x is Ok()` (or otherwise
handle the `Result`) before using `V`. Indexed assignment `m[k] = x` still
types the LHS as `V`. The Go backend lowers map reads with an IIFE that uses
`v, ok :=` and `errors.New("missing map key")` internally.
Adds `examples/in/map_catalog.ft`, compiler/pipeline/typechecker coverage, and
README catalog/CLI notes.
BREAKING CHANGE: Map subscript expressions are no longer plain `V`; callers must
account for `Result(V, Error)` or narrow with `ensure`.
Example:
```forst
avail := catalog[sku]
ensure avail is Ok()
println(string(avail))
```
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (24)
WalkthroughThis PR introduces comprehensive support for map index reads returning Changes
Sequence Diagram(s)sequenceDiagram
participant Parser
participant TypeChecker
participant Transformer
participant CodeGen
Parser->>Parser: Parse map[key] as IndexExpressionNode
Parser->>TypeChecker: Pass AST node
TypeChecker->>TypeChecker: Infer target type (TypeMap)
TypeChecker->>TypeChecker: Validate key compatibility
TypeChecker->>TypeChecker: Return Result(V, Error) type
TypeChecker->>Transformer: Provide inferred type
Transformer->>Transformer: Detect Result type via type inference
Transformer->>Transformer: Check cache for duplicate reads
alt Cache Hit
Transformer->>CodeGen: Return cached function literal
else Cache Miss
Transformer->>Transformer: Generate IIFE function literal
Transformer->>Transformer: v, ok := m[k]<br/>if !ok: return (zero, errMissingMapKey)
Transformer->>Transformer: Store in per-function cache
Transformer->>CodeGen: Return new function literal
end
CodeGen->>CodeGen: Emit call expression to IIFE
sequenceDiagram
participant LSP Client
participant Hover Handler
participant TypeChecker
participant TokenStream
LSP Client->>Hover Handler: Request hover at bracket position
Hover Handler->>TokenStream: Locate '[' token
Hover Handler->>Hover Handler: Check prior token is identifier
Hover Handler->>TypeChecker: Infer variable type
TypeChecker->>TypeChecker: Resolve to TypeMap
alt Is Map Type
Hover Handler->>Hover Handler: Generate Result(V, Error) hover text
Hover Handler->>LSP Client: Return map lookup hover markdown
else Not Map Type
Hover Handler->>LSP Client: Return empty or fallback hover
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
GetTypeScriptType now handles builtin `Result` with two params, emitting
`({ ok: true; value: S } | { ok: false; error: F })` and wrapping S/F in
parentheses when they already contain `|` or ` & `.
test(examples): add map_catalog.go compiler golden
Locks in emitted Go for `examples/in/map_catalog.ft` (map-read IIFE, missing-key
error, ensure split).
Example (TS mapping for `Result(Int, Error)`):
```ts
({ ok: true; value: number } | { ok: false; error: unknown })
```
Emit `var errMissingMapKey = errors.New("missing map key")` once via
`TransformerOutput.EnsureErrMissingMapKeyDecl`, reuse in map-read IIFEs, and
cache identical `*ast.FuncLit` per function (`mapIndexExprCacheKey`, hit counter
for tests). `goZeroValueGoAST` returns `nil` for pointers; add table tests and
golden/pipeline/compiler marker updates.
feat(lsp): hover on `[` after a map variable
When the cursor is on `LBracket` following a map-typed identifier, show that
lookup is `Result(V, Error)` and to use `ensure … is Ok()` before using `V`.
fix(typechecker): targeted `string()` error for raw map index Result
If the operand is a map subscript typed as `Result`, diagnose map lookup
explicitly instead of only "unsupported operand type Result". Add
`inferExpressionTypeWithExpected` hook for `IndexExpressionNode` and nested /
chained map tests.
docs(ts): clarify Result lowering vs generated TS union
Comment on `TypeResult` in `GeeScriptType`: TS discriminated union is a
static signature hint; Go remains `(T, error)` unless a codec maps wire data.
Example (diagnostic):
```forst
println(string(m["a"])) // map lookup has type Result(V, Error); use ensure first
```
Rvalue
m[k]onmap[K]Vnow infers asResult(V, Error)(missing key is failure). Forst rejectsv, ok := m[k]; useensure x is Ok()(or otherwise handle theResult) before usingV. Indexed assignmentm[k] = xstill types the LHS asV. The Go backend lowers map reads with an IIFE that usesv, ok :=anderrors.New("missing map key")internally.Adds
examples/in/map_catalog.ft, compiler/pipeline/typechecker coverage, and README catalog/CLI notes.BREAKING CHANGE: Map subscript expressions are no longer plain
V; callers must account forResult(V, Error)or narrow withensure.Example:
Summary by CodeRabbit
Release Notes
New Features
Resulttypes requiringensure ... is Ok()error handling before use.Documentation
.ftfiles for CLI usage and.gofor Go builds.Tests