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

13 KiB
Raw Blame History

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

// 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

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

#[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

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

#[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

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

#[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

#[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

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.