Skip to content

feat(lsp,cli,effects): variable hover (type+docs), builtin docs generator, handler-owned effect state + resume front-end#149

Merged
MelbourneDeveloper merged 10 commits into
mainfrom
feature/higher-order-calls
Jun 25, 2026
Merged

feat(lsp,cli,effects): variable hover (type+docs), builtin docs generator, handler-owned effect state + resume front-end#149
MelbourneDeveloper merged 10 commits into
mainfrom
feature/higher-order-calls

Conversation

@MelbourneDeveloper

Copy link
Copy Markdown
Collaborator

TLDR

Adds editor variable hover (declared/inferred type + /// docs), a single-source-of-truth built-in function docs generator, handler-owned mutable state for algebraic effects, and the parse/type front-end for explicit resume — all behind a green make ci.

Details

LSP / editor — variable hover ([LSP-HOVER])

  • collect_all_symbols now deep-walks every expression body (blocks, match arms, lambdas, call args, string interpolations, handler in {…} blocks), so a let/mut nested anywhere is discoverable — fixing "no hover bubble on a variable inside an HTTP server block".
  • Hover shows the declared type, or the inferred type for unannotated bindings, via position-keyed ProgramTypes.lets / let_type (new crates/osprey-types/src/info.rs + check.rs).
  • Variables are documentable with /// like functions: grammar doc_comment on let, captured through syntax lowering into the AST doc field, rendered as hover prose. The binding position anchors on the name/keyword field, so a leading /// never shifts it.
  • lspkit is reused, not reimplemented; the one missing text primitive is a documented shim in text.rs filed upstream as Nimblesite/lspkit#2. Spec 0020 gains [LSP-HOVER], [LSP-HOVER-VARIABLES], [LSP-HOVER-DOCS], [LSP-REUSE-LSPKIT].

Built-in docs generator — osprey --docs --docs-dir <dir>

  • New crates/osprey-cli/src/docs.rs + crates/osprey-types/src/builtin_docs{,_lang,_sys}.rs: the compiler's type schemes are the single source of truth — one page per built-in plus an index, with stale pages pruned. Regenerates 90 website/src/docs/functions/* pages so the website and editor hover show identical signatures/types.

Algebraic effects

  • Handler-owned state ([EFFECTS-HANDLER-STATE]): handler arms read/write a mut captured from the enclosing scope (promoted to a shared heap cell; per-region env carried on the handler stack). Makes the State effect fully usable. Runtime in effects_runtime.c; codegen in effects.rs / lower.rs / expr.rs. Reference example compiler/examples/tested/effects/http_state_levels.osp.
  • Explicit resume front-end: grammar / AST / syntax-lowering + Hindley-Milner typing (resume typed against the operation result; rejected outside a handler arm). The continuation runtime/codegen is not yet wiredresume parses and type-checks but is currently rejected at code generation; spec 0017 and plan 0008 mark it specified-but-not-yet-executable.

Examples / runtime

  • compiler/examples/statefulhttp/{server,tui}.osp + README: a stateful HTTP server and a terminal UI. Terminal/raw-mode additions in system_runtime.c; HTTP handler return-type alignment in http_server_runtime.c.

VS Code extension

  • Debug-config synthesis extracted and unit-tested; server-command resolution hardening; test harness/runner updates; FEATURES/README/TESTING docs refreshed.

Scope note: this branch is named feature/higher-order-calls, but that feature already shipped in the merged PR #148. The changes here are the post-#148 work that accumulated on the branch (the four areas above); they are unrelated to higher-order calls.

How Do The Automated Tests Prove It Works?

  • Variable hover (Rust, crates/osprey-lsp): hover_on_a_let_binding_uses_the_name_and_type_form (asserts limit: int), hover_on_a_local_let_shows_inferred_type_and_docs (asserts inferred greeting: string and the /// doc prose), hover_on_a_documented_function_renders_its_docs, and collect_all_symbols_descends_into_every_expression_form (walks every expression container).
  • Variable hover (VS Code e2e / vsix): vscode-extension/test/suite/extension.test.ts — "CHUNKY: full language-intelligence sweep…" asserts radius: int / count: int on unannotated lets, and "CHUNKY: a ///-documented variable hovers with its type AND its docs" asserts a top-level and a block-nested documented let hover with type + doc prose through a live executeHoverProvider against the launched LSP.
  • Docs generator (Rust, crates/osprey-cli/src/docs.rs): generate_writes_a_page_per_builtin_plus_an_index, prune_deletes_stale_pages_but_keeps_live_ones_and_the_index, slugs_disambiguate_case_collisions_and_stay_unique, slug_map_falls_back_to_a_numeric_suffix_when_the_type_slug_also_collides, page_uses_scheme_types_and_omits_empty_sections.
  • Handler-owned state: the differential harness runs http_state_levels.osp through osprey --run and matches .expectedoutput byte-for-byte (part of PASS=48 FAIL=0).
  • Resume typing: osprey-types select_and_handler_expressions type-checks a handle … resume(v + 1000) … program (auto-unwrap of the arithmetic Result into the operation-result slot).
  • Gates: make ci green — clippy -D warnings, cargo fmt --check, all 7 crate coverage thresholds (osprey-lsp 99.1%, osprey-types 98.7%, osprey-cli 96.4%, osprey-codegen 95.6%, …), vscode-extension 90.37% ≥ 89%, differential PASS=48 FAIL=0 NOEXP=0 + FC_OK.

Calls and iterator callbacks whose callee is an arbitrary expression — a
chained application (`add3(1)(2)(3)`), a function held in a record field
(`cfg.processor`), or any computed call result — previously failed loudly.
They now recover the callee's signature from the type table and dispatch
through the existing closure cell:

- builder.rs: `callee_fn_type` resolves the function `Type` of a callee
  expression (identifier / chained call / record-field access).
- expr.rs: the non-identifier callee in `gen_call` dispatches via the
  recovered `FnSig` instead of bailing; still fails loudly for non-functions.
- iter.rs: `callback_of` evaluates a computed/field callback once to a closure
  handle (`Callback::Value`) and calls it per element through its cell.

Closes plan 0001. Extends function_composition_test with a chained 3-deep
call, a computed iterator callback, and a record-field filter callback; adds
a codegen unit test for the three paths.
@MelbourneDeveloper MelbourneDeveloper merged commit edfa67d into main Jun 25, 2026
5 checks passed
@MelbourneDeveloper MelbourneDeveloper deleted the feature/higher-order-calls branch June 25, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant