prometeu-runtime/files/PRs para Junie.md
2026-03-24 13:40:25 +00:00

572 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Prometeu — PR Plan (Arena-Driven) para um LSP Completo
---
# **PR-00.X — Reorganização estrutural do workspace (préArena / préLSP)**
> **Objetivo macro:** separar *modelo/ABI*, *execução*, *kernel* e *tooling* antes de qualquer refator arena-driven.
>
> **Regra de ouro:** nenhuma mudança de comportamento. Apenas **movimentação de código + ajuste de dependências**.
>
> **Modelo final alvo:**
>
> * `prometeu-bytecode` ✅ (fica)
> * `prometeu-abi` ✅ (novo — ex-`prometeu-core` sem execução)
> * `prometeu-vm` ✅ (novo)
> * `prometeu-kernel` ✅ (novo)
> * `prometeu-runtime-desktop` ✅ (fica)
> * `prometeu-compiler` ✅ (fica)
> * `prometeu` (CLI) ✅ (fica agregando)
---
> **Meta do Nilton / Junie workflow**: PRs extremamente prescritivos. A Junie só implementa; você revisa o design **antes** do código.
>
> **Regra de ouro:** cada PR abaixo vem com:
>
> 1. Arquivos/alvos exatos
> 2. Estruturas e assinaturas obrigatórias
> 3. Esquemas JSON (quando aplicável)
> 4. Testes (golden + unit)
> 5. Critérios de aceite “binário” (passou/não passou)
---
## Estado atual (confirmado pelo repo)
Workspace (Archive.zip) tem crates:
* `prometeu/`
* `prometeu-bytecode/`
* `prometeu-core/`
* `prometeu-compiler/` (bin `src/main.rs`, deps: `serde`, `serde_json`, `anyhow`, `clap`, e família `oxc_*`).
**Saída atual existente:** `symbols.json` (schema_version 0), exportando símbolos por projeto, com `decl_span` em `line/col` e paths absolutos. (Vamos evoluir isso no PR-07.)
---
## Visão de arquitetura alvo
### Camadas
1. **FileDB**: texto, URI/path, line-index, snapshots.
2. **Lexer/Parser**: produz **AstArena** (NodeId + spans por nó).
3. **Binder/Resolver**: produz **SymbolArena** + índices (def/ref).
4. **Typecheck**: produz **TypeArena** + facts (node→type, symbol→type).
5. **Analysis Export**: `analysis.json` (full) + `symbols.json` (leve e estável).
6. **LSP Server**: consome `AnalysisDb` e responde requests.
### IDs padronizados (newtypes)
* `FileId(u32)`
* `NodeId(u32)`
* `NameId(u32)` (interner)
* `SymbolId(u32)`
* `TypeId(u32)`
* `ProjectId(u32)`
* `ModuleId(u32)`
### Invariantes
* AST é **imutável** após construção (normativo na spec PBS).
* Nenhuma fase expõe referências diretas entre nós; apenas **IDs**.
* IDs externos são aceitos, mas sempre passam por **validate/resolve** (API checked).
---
# Templates prescritivos para PR (usar em TODAS)
## Template de descrição (copiar/colar)
* **Motivação:**
* **Mudança de modelo de dados:**
* **APIs novas / alteradas:**
* **Arquivos tocados:**
* **Testes adicionados/atualizados:**
* **Riscos & rollback:**
* **Checklist de aceite (binário):**
## Regras para Junie (para reduzir vai-e-volta)
1. Não “inventar design”. Se algo não estiver especificado, **criar TODO** e parar.
2. Não mudar formatação/estilo fora do escopo.
3. Todo novo tipo público precisa de doc-comment curta e exemplo.
4. Toda mudança de JSON precisa:
* `schema_version` bump (se não for backward)
* teste de snapshot
5. Cada PR deve deixar `cargo test` verde.
---
# PRs (detalhados)
## PR-01 — FileDB + LineIndex (base do LSP e spans)
**Branch:** `pr-01-filedb`
### Objetivo
Criar uma base de arquivos com IDs estáveis na sessão e conversão offset<->(line,col).
### Arquivos / módulos
* `prometeu-analysis/src/file_db.rs`
* `prometeu-analysis/src/span.rs`
* `prometeu-analysis/src/ids.rs`
* `prometeu-analysis/src/lib.rs` (re-exports)
### Estruturas obrigatórias
```rust
// prometeu-analysis/src/ids.rs
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct FileId(pub u32);
// prometeu-analysis/src/span.rs
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Span {
pub file: FileId,
pub start: u32, // byte offset
pub end: u32, // byte offset, exclusive
}
// prometeu-analysis/src/file_db.rs
pub struct FileDB {
// map uri->id, id->uri/text/line_index
}
pub struct LineIndex {
// stores line start offsets
}
```
### Regras
* Spans são **byte offsets UTF-8** (`start` inclusive, `end` exclusive) — alinhado ao Canonical Addenda.
* `LineIndex` deve lidar com `
` (LF). (CRLF pode ser normalizado na entrada.)
### APIs obrigatórias
```rust
impl FileDB {
pub fn upsert(&mut self, uri: &str, text: String) -> FileId;
pub fn file_id(&self, uri: &str) -> Option<FileId>;
pub fn uri(&self, id: FileId) -> &str;
pub fn text(&self, id: FileId) -> &str;
pub fn line_index(&self, id: FileId) -> &LineIndex;
}
impl LineIndex {
pub fn offset_to_line_col(&self, offset: u32) -> (u32, u32);
pub fn line_col_to_offset(&self, line: u32, col: u32) -> Option<u32>;
}
```
### Testes obrigatórios
* `tests/file_db_line_index.rs` (unit)
* roundtrip offset->(l,c)->offset
* bordas (start/end, EOF)
### Critérios de aceite
* Testes passam.
* Nenhuma mudança no output do `prometeu-compiler` ainda.
---
## PR-02 — NameInterner (NameId) e eliminação de String no hot path
**Branch:** `pr-02-name-interner`
### Objetivo
Trocar identificadores em AST/resolver de `String` para `NameId`.
### Arquivos
* `prometeu-analysis/src/interner.rs`
* Ajustar frontend PBS no `prometeu-compiler` (ver lista de toques abaixo).
### Estruturas obrigatórias
```rust
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct NameId(pub u32);
pub struct NameInterner {
// bidirectional: string->id, id->string
}
```
### APIs obrigatórias
```rust
impl NameInterner {
pub fn new() -> Self;
pub fn intern(&mut self, s: &str) -> NameId;
pub fn resolve(&self, id: NameId) -> &str;
}
```
### Regras
* Interner é **session-local**.
* `resolve` deve retornar `&str` estável (armazenar `String` internamente).
### Touch points no `prometeu-compiler`
* Onde hoje existe `String` como nome de símbolo, token de identifier, etc:
* AST nodes de `Ident`
* Resolver scopes: `HashMap<NameId, _>`
### Testes
* Unit: intern/resolve, dedup
* Golden: manter comportamento de resolver/diags
### Critérios de aceite
* Redução de `String` em estruturas hot (resolver)
* Build e testes ok.
---
## PR-03 — AST Arena (NodeId) para PBS
**Branch:** `pr-03-ast-arena`
### Objetivo
Refatorar o AST PBS (atualmente recursivo) para uma arena `Vec` com `NodeId`.
### Alvos no repo
* `prometeu-compiler/src/frontends/pbs/*` (localizar AST/parser atuais)
### Estruturas obrigatórias
```rust
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct NodeId(pub u32);
pub struct AstArena {
pub nodes: Vec<NodeKind>,
pub spans: Vec<prometeu_analysis::Span>,
pub roots: Vec<NodeId>,
}
pub enum NodeKind {
File { imports: Vec<NodeId>, decls: Vec<NodeId> },
Import { /* ... */ },
FnDecl { name: NameId, /* ... */, body: NodeId },
// ... (conforme canonical AST do PBS)
}
```
### Regras
* `AstArena::push(kind, span) -> NodeId` sempre faz append.
* `spans.len() == nodes.len()` sempre.
### APIs obrigatórias
```rust
impl AstArena {
pub fn push(&mut self, kind: NodeKind, span: Span) -> NodeId;
pub fn kind(&self, id: NodeId) -> &NodeKind;
pub fn span(&self, id: NodeId) -> Span;
}
```
### Testes obrigatórios
* Parser golden tests: comparar JSON canonical (se você já tem) ou snapshots equivalentes.
* Unit: invariantes (push mantém alinhamento).
### Critérios de aceite
* Nenhum `Box<Node>` em AST PBS.
* Resolver e typechecker passam a consumir NodeId.
---
## PR-04 — SymbolArena + índices (defs/refs) + node→symbol
**Branch:** `pr-04-symbol-arena-index`
### Objetivo
Criar `SymbolArena` e índices para features de LSP sem traversal pesado.
### Estruturas obrigatórias
```rust
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct SymbolId(pub u32);
pub enum SymbolKind { Type, Value, Service, Function /* etc */ }
pub struct Symbol {
pub name: NameId,
pub kind: SymbolKind,
pub exported: bool,
pub module: ModuleId,
pub decl_span: Span,
}
pub struct SymbolArena { pub symbols: Vec<Symbol> }
pub struct DefIndex { /* HashMap<(ModuleId, NameId, Namespace), SymbolId> */ }
pub struct RefIndex { /* Vec<Vec<Span>> by SymbolId */ }
pub struct NodeToSymbol { /* Vec<Option<SymbolId>> by NodeId */ }
```
### APIs obrigatórias
* `insert_symbol(...) -> SymbolId` (falha se duplicate, com diag E_RESOLVE_DUPLICATE_SYMBOL)
* `record_ref(symbol_id, span)`
* `bind_node(node_id, symbol_id)`
### Testes
* Duplicate symbol
* Undefined identifier
* Visibility violations
* Determinismo (mesma input → mesma ordem IDs, quando possível)
---
## PR-05 — TypeArena + TypeFacts (node→type, symbol→type)
**Branch:** `pr-05-type-arena-facts`
### Objetivo
Dar base para hover, completion e erros de tipo.
### Estruturas obrigatórias
```rust
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
pub struct TypeId(pub u32);
pub enum TypeKind {
Primitive { name: NameId },
Struct { sym: SymbolId },
Optional { inner: TypeId },
Result { ok: TypeId, err: TypeId },
Array { inner: TypeId, len: Option<u32> },
// ... conforme v0
}
pub struct TypeArena { pub types: Vec<TypeKind> }
pub struct TypeFacts {
pub node_type: Vec<Option<TypeId>>, // index by NodeId
pub symbol_type: Vec<Option<TypeId>>, // index by SymbolId
}
```
### APIs obrigatórias
* `intern_type(TypeKind) -> TypeId` (dedup opcional; documentar)
* `set_node_type(NodeId, TypeId)`
* `set_symbol_type(SymbolId, TypeId)`
### Testes
* Hover type display snapshots.
---
## PR-06 — Diagnostics canonizados (E_* / W_*)
**Branch:** `pr-06-diagnostics`
### Objetivo
Diagnósticos estáveis e serializáveis, alinhados ao Canonical Addenda (codes).
### Estruturas obrigatórias
```rust
pub enum Severity { Error, Warning }
pub struct Diagnostic {
pub severity: Severity,
pub code: String,
pub message: String,
pub span: Span,
pub related: Vec<(String, Span)>,
}
```
### Regras
* Codes conforme Canonical Addenda (E_PARSE_*, E_RESOLVE_*, E_TYPE_*).
### Testes
* Golden diag JSON determinístico.
---
## PR-07 — Export: `symbols.json` v1 + `analysis.json` v0
**Branch:** `pr-07-analysis-export`
### Objetivo
Separar índice leve (`symbols.json`) e export completo (`analysis.json`).
### Símbolos (novo formato recomendado)
* **IMPORTANTE:** parar de gravar paths absolutos (usar URI relativo ao projeto quando possível).
`symbols.json` v1 (schema_version=1):
* `projects[]`:
* `project` (string)
* `project_dir` (string) (pode ficar absoluto por enquanto)
* `symbols[]`:
* `symbol_id` (u32) **OU** string estável atual (mantém compat)
* `name` (string)
* `kind` (string)
* `exported` (bool)
* `module_path` (string)
* `decl_span`: `{ file_uri, start:{line,col}, end:{line,col} }`
`analysis.json` (schema_version=0):
* `file_table`: [{file_id:u32, uri:string}]
* `symbols`: [{symbol_id:u32, name_id:u32, kind, exported, module_id, decl_span}]
* `refs`: [{symbol_id:u32, spans:[Span]}]
* `types`: [{type_id:u32, kind:...}]
* `facts`: { node_type: [...], symbol_type: [...] }
* `diagnostics`: [Diagnostic]
### Testes
* Snapshot de ambos JSONs.
---
## PR-08 — LSP MVP (diagnostics + symbols + goto definition)
**Branch:** `pr-08-lsp-mvp`
### Objetivo
LSP funcional mínimo usando `AnalysisDb` (em memória), recompilando quando arquivo muda.
### Features
* `initialize`
* `didOpen`/`didChange`/`didClose`
* `publishDiagnostics`
* `documentSymbol` / `workspaceSymbol`
* `definition`
### Regras
* `didChange`: por enquanto full-text (simplifica)
* Rebuild: coarse (projeto inteiro) inicialmente
### Testes
* Test harness: abrir doc e pedir definition.
---
## PR-09 — LSP: references + rename
**Branch:** `pr-09-lsp-refs-rename`
### Objetivo
Baseado em RefIndex e NodeToSymbol.
### Features
* `references`
* `prepareRename`
* `rename`
### Regras de segurança
* Não renomear se símbolo não-resolvido.
* Não renomear se span em comentário/string.
---
## PR-10 — LSP: hover + signatureHelp
**Branch:** `pr-10-lsp-hover-sighelp`
### Features
* `hover`: type + docstring (docstring opcional por enquanto)
* `signatureHelp`: para call nodes (se parser já marca)
---
## PR-11 — LSP: completion
**Branch:** `pr-11-lsp-completion`
### Buckets
* locals em scope (se você tiver scope facts)
* symbols do módulo
* exports importados
* members via type facts
---
## PR-12 — LSP: semantic tokens + highlights
**Branch:** `pr-12-lsp-semantic`
---
## PR-13 — LSP: formatting + code actions (opcional)
**Branch:** `pr-13-lsp-actions`
---
## PR-14 — Incremental analysis + cancelation
**Branch:** `pr-14-incremental`
---
## PR-15 — Debug map (pc→span) + integração com traps
**Branch:** `pr-15-debug-map`
---
---
# Sequência recomendada (travada)
1. PR-00.1 (`prometeu-abi` + compat)
2. PR-00.2 (`prometeu-vm`)
3. PR-00.3 (`prometeu-kernel`)
4. PR-00.4 (depurar `prometeu-core`)
5. PR-00.5 (opcional firmware)
6. PR-00.6 (remover core)
> Após PR-00.X, iniciar a trilha Arena-Driven (PR-01..PR-07) no compiler/analysis.