From adb4dad14baee5ec53f67798ba28d754d5858e8a Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Thu, 5 Feb 2026 11:06:28 +0000 Subject: [PATCH] pr 01 --- crates/prometeu-analysis/src/ids.rs | 64 +- crates/prometeu-analysis/src/interner.rs | 4 +- crates/prometeu-analysis/src/lib.rs | 4 +- .../src/analysis/symbols/mod.rs | 28 +- .../prometeu-compiler/src/analysis/types.rs | 10 +- .../src/frontends/pbs/ast.rs | 5 +- .../src/frontends/pbs/collector.rs | 2 +- .../src/frontends/pbs/lowering.rs | 2 +- .../src/frontends/pbs/parser.rs | 2 +- .../src/frontends/pbs/resolve.rs | 34 +- .../src/frontends/pbs/resolver.rs | 16 +- .../src/frontends/pbs/typecheck.rs | 2 +- files/LPS - prep.md | 301 +++++++++ files/PRs para Junie Global.md | 39 -- files/PRs para Junie.md | 571 ------------------ test-cartridges/canonical/golden/program.pbc | Bin 3727 -> 3727 bytes 16 files changed, 414 insertions(+), 670 deletions(-) create mode 100644 files/LPS - prep.md delete mode 100644 files/PRs para Junie Global.md delete mode 100644 files/PRs para Junie.md diff --git a/crates/prometeu-analysis/src/ids.rs b/crates/prometeu-analysis/src/ids.rs index 9d6b6c42..35aef095 100644 --- a/crates/prometeu-analysis/src/ids.rs +++ b/crates/prometeu-analysis/src/ids.rs @@ -1,2 +1,62 @@ -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)] -pub struct FileId(pub u32); +//! Canonical ID newtypes used across the Prometeu workspace. +//! Keep this crate low-level and independent from higher layers. + +macro_rules! define_id { + ($name:ident) => { + #[repr(transparent)] + #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, serde::Serialize, serde::Deserialize)] + pub struct $name(pub u32); + + impl $name { + pub const INVALID: $name = $name(u32::MAX); + + #[inline] + pub const fn as_u32(self) -> u32 { self.0 } + + // Temporary helper for places that still index Vec/slots by usize + #[inline] + pub const fn as_usize(self) -> usize { self.0 as usize } + } + + impl From for $name { + #[inline] + fn from(value: u32) -> Self { Self(value) } + } + + impl From<$name> for u32 { + #[inline] + fn from(value: $name) -> Self { value.0 } + } + }; +} + +define_id!(FileId); +define_id!(NodeId); +define_id!(NameId); +define_id!(SymbolId); +define_id!(TypeId); +define_id!(ModuleId); +define_id!(ProjectId); + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use std::mem::size_of; + + #[test] + fn ids_are_repr_transparent_and_hashable() { + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + + // Hash/Eq usage + let mut m: HashMap = HashMap::new(); + m.insert(SymbolId(1), "one"); + assert_eq!(m.get(&SymbolId(1)).copied(), Some("one")); + } +} diff --git a/crates/prometeu-analysis/src/interner.rs b/crates/prometeu-analysis/src/interner.rs index e1c76f16..2122124a 100644 --- a/crates/prometeu-analysis/src/interner.rs +++ b/crates/prometeu-analysis/src/interner.rs @@ -1,7 +1,5 @@ use std::collections::HashMap; - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)] -pub struct NameId(pub u32); +use crate::ids::NameId; #[derive(Debug, Default, Clone)] pub struct NameInterner { diff --git a/crates/prometeu-analysis/src/lib.rs b/crates/prometeu-analysis/src/lib.rs index 6fbd2fdc..ce958134 100644 --- a/crates/prometeu-analysis/src/lib.rs +++ b/crates/prometeu-analysis/src/lib.rs @@ -3,7 +3,7 @@ pub mod span; pub mod file_db; pub mod interner; -pub use ids::FileId; +pub use ids::*; pub use span::Span; pub use file_db::{FileDB, LineIndex}; -pub use interner::{NameId, NameInterner}; +pub use interner::NameInterner; diff --git a/crates/prometeu-compiler/src/analysis/symbols/mod.rs b/crates/prometeu-compiler/src/analysis/symbols/mod.rs index 93f39ae2..34701303 100644 --- a/crates/prometeu-compiler/src/analysis/symbols/mod.rs +++ b/crates/prometeu-compiler/src/analysis/symbols/mod.rs @@ -1,13 +1,11 @@ use crate::common::diagnostics::{Diagnostic, Severity}; use crate::common::spans::Span; -use crate::frontends::pbs::ast::{AstArena, NodeId}; -use prometeu_analysis::NameId; +use crate::frontends::pbs::ast::AstArena; +use prometeu_analysis::NodeId; +use prometeu_analysis::{NameId, SymbolId, ModuleId}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub struct SymbolId(pub u32); - #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum SymbolKind { Type, @@ -32,7 +30,7 @@ pub struct Symbol { pub name: NameId, pub kind: SymbolKind, pub exported: bool, - pub module: u32, + pub module: ModuleId, pub decl_span: Span, } @@ -43,7 +41,7 @@ pub struct SymbolArena { #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct DefKey { - pub module: u32, + pub module: ModuleId, pub name: NameId, pub namespace: Namespace, } @@ -107,7 +105,7 @@ impl DefIndex { } /// Lookup by name/namespace ignoring module. Returns the first match with its module id. - pub fn get_by_name_any_module(&self, name: NameId, namespace: Namespace) -> Option<(u32, SymbolId)> { + pub fn get_by_name_any_module(&self, name: NameId, namespace: Namespace) -> Option<(ModuleId, SymbolId)> { for (k, v) in &self.symbols { if k.name == name && k.namespace == namespace { return Some((k.module, *v)); @@ -173,7 +171,7 @@ impl NodeToSymbol { mod tests { use super::*; - fn sample_symbol(name: NameId, module: u32) -> Symbol { + fn sample_symbol(name: NameId, module: ModuleId) -> Symbol { Symbol { name, kind: SymbolKind::Function, @@ -186,8 +184,8 @@ mod tests { #[test] fn insert_returns_incremental_ids() { let mut arena = SymbolArena::new(); - let id0 = arena.insert(sample_symbol(NameId(0), 0)); - let id1 = arena.insert(sample_symbol(NameId(1), 0)); + let id0 = arena.insert(sample_symbol(NameId(0), ModuleId(0))); + let id1 = arena.insert(sample_symbol(NameId(1), ModuleId(0))); assert_eq!(id0, SymbolId(0)); assert_eq!(id1, SymbolId(1)); @@ -196,7 +194,7 @@ mod tests { #[test] fn get_returns_correct_symbol() { let mut arena = SymbolArena::new(); - let symbol = sample_symbol(NameId(7), 3); + let symbol = sample_symbol(NameId(7), ModuleId(3)); let id = arena.insert(symbol.clone()); assert_eq!(arena.get(id).name, symbol.name); @@ -209,7 +207,7 @@ mod tests { fn def_index_duplicate_in_same_namespace_errors() { let mut index = DefIndex::new(); let key = DefKey { - module: 1, + module: ModuleId(1), name: NameId(10), namespace: Namespace::Type, }; @@ -225,12 +223,12 @@ mod tests { let mut index = DefIndex::new(); let name = NameId(11); let type_key = DefKey { - module: 2, + module: ModuleId(2), name, namespace: Namespace::Type, }; let value_key = DefKey { - module: 2, + module: ModuleId(2), name, namespace: Namespace::Value, }; diff --git a/crates/prometeu-compiler/src/analysis/types.rs b/crates/prometeu-compiler/src/analysis/types.rs index 50118bb9..9d840e75 100644 --- a/crates/prometeu-compiler/src/analysis/types.rs +++ b/crates/prometeu-compiler/src/analysis/types.rs @@ -1,10 +1,8 @@ -use crate::analysis::symbols::{SymbolArena, SymbolId}; -use crate::frontends::pbs::ast::NodeId; -use prometeu_analysis::interner::{NameId, NameInterner}; +use crate::analysis::symbols::{SymbolArena}; +use prometeu_analysis::{NameId, NameInterner, TypeId, SymbolId, NodeId, ModuleId}; use serde::{Deserialize, Serialize}; -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub struct TypeId(pub u32); +// Use canonical TypeId from prometeu-analysis #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum TypeKind { @@ -212,7 +210,7 @@ mod tests { name: my_struct_name, kind: SymbolKind::Struct, exported: false, - module: 0, + module: ModuleId(0), decl_span: Span::new(0, 0, 0), }); diff --git a/crates/prometeu-compiler/src/frontends/pbs/ast.rs b/crates/prometeu-compiler/src/frontends/pbs/ast.rs index c186121b..3d00111a 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/ast.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/ast.rs @@ -1,9 +1,8 @@ use crate::common::spans::Span; -use prometeu_analysis::NameId; +use prometeu_analysis::{NameId, NodeId}; use serde::{Deserialize, Serialize}; -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub struct NodeId(pub u32); +// Use canonical NodeId from prometeu-analysis #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)] pub struct AstArena { diff --git a/crates/prometeu-compiler/src/frontends/pbs/collector.rs b/crates/prometeu-compiler/src/frontends/pbs/collector.rs index 9dc34b2b..f85ba16a 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/collector.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/collector.rs @@ -2,7 +2,7 @@ use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, Severity}; use crate::frontends::pbs::ast::*; use crate::frontends::pbs::symbols::*; use crate::semantics::export_surface::ExportSurfaceKind; -use prometeu_analysis::NameInterner; +use prometeu_analysis::{NameInterner, NodeId}; pub struct SymbolCollector<'a> { interner: &'a NameInterner, diff --git a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs index 5294d155..b1786a56 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs @@ -7,7 +7,7 @@ use crate::frontends::pbs::types::PbsType; use crate::ir_core; use crate::ir_core::ids::{FieldId, FunctionId, TypeId, ValueId}; use crate::ir_core::{Block, Function, Instr, InstrKind, Module, Param, Program, Terminator, Type}; -use prometeu_analysis::NameInterner; +use prometeu_analysis::{NameInterner, NodeId}; use std::collections::HashMap; #[derive(Clone)] diff --git a/crates/prometeu-compiler/src/frontends/pbs/parser.rs b/crates/prometeu-compiler/src/frontends/pbs/parser.rs index 00f689df..d5407428 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/parser.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/parser.rs @@ -3,7 +3,7 @@ use crate::common::spans::Span; use crate::frontends::pbs::ast::*; use crate::frontends::pbs::lexer::Lexer; use crate::frontends::pbs::token::{Token, TokenKind}; -use prometeu_analysis::{NameId, NameInterner}; +use prometeu_analysis::{NameId, NameInterner, NodeId}; pub struct Parser<'a> { tokens: Vec, diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs index 11ba069d..2cc20e14 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs @@ -1,11 +1,11 @@ use crate::common::diagnostics::{Diagnostic, Severity}; -use crate::frontends::pbs::ast::{AstArena, NodeKind, NodeId}; +use crate::frontends::pbs::ast::{AstArena, NodeKind}; use crate::analysis::symbols::{Symbol, SymbolArena, SymbolKind, DefIndex, DefKey, Namespace, NodeToSymbol, RefIndex}; -use prometeu_analysis::NameInterner; +use prometeu_analysis::{NameInterner, NodeId, ModuleId}; pub fn build_def_index( arena: &AstArena, - module: u32, + module: ModuleId, _interner: &NameInterner, imports: Option<(&SymbolArena, &DefIndex)>, ) -> (SymbolArena, DefIndex, RefIndex, NodeToSymbol, Vec) { @@ -79,7 +79,7 @@ pub fn build_def_index( fn walk_node( node_id: NodeId, arena: &AstArena, - module: u32, + module: ModuleId, index: &DefIndex, imports: Option<(&SymbolArena, &DefIndex)>, ref_index: &mut RefIndex, @@ -134,7 +134,7 @@ fn walk_node( diagnostics.push(Diagnostic { severity: Severity::Error, code: "E_RESOLVE_VISIBILITY".to_string(), - message: format!("Symbol is not exported from module {}", symbol.module), + message: format!("Symbol is not exported from module {:?}", symbol.module), span, related: Vec::new(), }); @@ -278,18 +278,18 @@ mod tests { arena.roots.push(file_id); - let (symbols, index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None); + let (symbols, index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, ModuleId(1), &interner, None); assert!(diagnostics.is_empty()); assert_eq!(symbols.symbols.len(), 2); - let fn_sym_id = index.get(DefKey { module: 1, name: fn_name, namespace: Namespace::Value }).unwrap(); + let fn_sym_id = index.get(DefKey { module: ModuleId(1), name: fn_name, namespace: Namespace::Value }).unwrap(); let fn_sym = symbols.get(fn_sym_id); assert_eq!(fn_sym.name, fn_name); assert_eq!(fn_sym.kind, SymbolKind::Function); assert!(fn_sym.exported); - let type_sym_id = index.get(DefKey { module: 1, name: type_name, namespace: Namespace::Type }).unwrap(); + let type_sym_id = index.get(DefKey { module: ModuleId(1), name: type_name, namespace: Namespace::Type }).unwrap(); let type_sym = symbols.get(type_sym_id); assert_eq!(type_sym.name, type_name); assert_eq!(type_sym.kind, SymbolKind::Struct); @@ -330,7 +330,7 @@ mod tests { arena.roots.push(file_id); - let (_symbols, _index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None); + let (_symbols, _index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, ModuleId(1), &interner, None); assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_DUPLICATE_SYMBOL"); @@ -360,7 +360,7 @@ mod tests { arena.roots.push(file_id); - let (symbols, _index, _ref_index, node_to_symbol, _diagnostics) = build_def_index(&arena, 1, &interner, None); + let (symbols, _index, _ref_index, node_to_symbol, _diagnostics) = build_def_index(&arena, ModuleId(1), &interner, None); let symbol_id = node_to_symbol.get(decl_id).expect("Node should be bound to a symbol"); let symbol = symbols.get(symbol_id); @@ -393,7 +393,7 @@ mod tests { arena.roots.push(file_id); - let (_symbols, _index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None); + let (_symbols, _index, _ref_index, _node_to_symbol, diagnostics) = build_def_index(&arena, ModuleId(1), &interner, None); assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_UNDEFINED_IDENTIFIER"); @@ -439,11 +439,11 @@ mod tests { arena.roots.push(file_id); - let (_symbols, index, ref_index, node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None); + let (_symbols, index, ref_index, node_to_symbol, diagnostics) = build_def_index(&arena, ModuleId(1), &interner, None); assert!(diagnostics.is_empty(), "Diagnostics should be empty: {:?}", diagnostics); - let target_sym_id = index.get(DefKey { module: 1, name: target_name, namespace: Namespace::Value }).expect("target should be in index"); + let target_sym_id = index.get(DefKey { module: ModuleId(1), name: target_name, namespace: Namespace::Value }).expect("target should be in index"); let refs = ref_index.refs_of(target_sym_id); assert_eq!(refs.len(), 1); assert_eq!(refs[0], Span::new(0, 50, 56)); @@ -474,7 +474,7 @@ mod tests { }), Span::new(0, 0, 100)); arena1.roots.push(file1); - let (symbols1, index1, _, _, _) = build_def_index(&arena1, 1, &interner, None); + let (symbols1, index1, _, _, _) = build_def_index(&arena1, ModuleId(1), &interner, None); // Módulo 2: tenta usar função privada do Módulo 1 let mut arena2 = AstArena::default(); @@ -496,7 +496,7 @@ mod tests { arena2.roots.push(file2); let (_symbols2, _index2, _ref_index2, _node_to_symbol2, diagnostics) = - build_def_index(&arena2, 2, &interner, Some((&symbols1, &index1))); + build_def_index(&arena2, ModuleId(2), &interner, Some((&symbols1, &index1))); assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_VISIBILITY"); @@ -541,8 +541,8 @@ mod tests { arena.roots.push(file_id); - let run1 = build_def_index(&arena, 1, &interner, None); - let run2 = build_def_index(&arena, 1, &interner, None); + let run1 = build_def_index(&arena, ModuleId(1), &interner, None); + let run2 = build_def_index(&arena, ModuleId(1), &interner, None); // runX is (SymbolArena, DefIndex, RefIndex, NodeToSymbol, Vec) diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs index 23015fc4..98b65ab7 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs @@ -1,10 +1,10 @@ -use crate::analysis::symbols::{SymbolArena, SymbolId, NodeToSymbol}; -use crate::analysis::types::{TypeArena, TypeFacts, TypeId, TypeKind}; +use crate::analysis::symbols::{SymbolArena, NodeToSymbol}; +use crate::analysis::types::{TypeArena, TypeFacts, TypeKind}; use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, Severity}; use crate::common::spans::Span; use crate::frontends::pbs::ast::*; use crate::frontends::pbs::symbols::*; -use prometeu_analysis::{NameId, NameInterner}; +use prometeu_analysis::{NameId, NameInterner, SymbolId, ModuleId, TypeId, NodeId}; use std::collections::HashMap; pub trait ModuleProvider { @@ -80,7 +80,7 @@ impl<'a> Resolver<'a> { SymbolKind::Local => crate::analysis::symbols::SymbolKind::Local, }, exported: sym.visibility == Visibility::Pub, - module: 0, + module: ModuleId(0), decl_span: sym.span, }); } @@ -96,7 +96,7 @@ impl<'a> Resolver<'a> { SymbolKind::Local => crate::analysis::symbols::SymbolKind::Local, }, exported: sym.visibility == Visibility::Pub, - module: 0, + module: ModuleId(0), decl_span: sym.span, }); } @@ -121,7 +121,7 @@ impl<'a> Resolver<'a> { SymbolKind::Local => crate::analysis::symbols::SymbolKind::Local, }, exported: sym.visibility == Visibility::Pub, - module: 0, // Should be target module + module: ModuleId(0), // Should be target module decl_span: sym.span, }); } @@ -137,7 +137,7 @@ impl<'a> Resolver<'a> { SymbolKind::Local => crate::analysis::symbols::SymbolKind::Local, }, exported: sym.visibility == Visibility::Pub, - module: 0, // Should be target module + module: ModuleId(0), // Should be target module decl_span: sym.span, }); } @@ -838,7 +838,7 @@ impl<'a> Resolver<'a> { _ => crate::analysis::symbols::SymbolKind::Value, }, exported: false, - module: 0, // TODO + module: ModuleId(0), // TODO: set actual module id when available decl_span: span, }); diff --git a/crates/prometeu-compiler/src/frontends/pbs/typecheck.rs b/crates/prometeu-compiler/src/frontends/pbs/typecheck.rs index bcce125b..5dcd4308 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/typecheck.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/typecheck.rs @@ -5,7 +5,7 @@ use crate::frontends::pbs::contracts::ContractRegistry; use crate::frontends::pbs::resolver::ModuleProvider; use crate::frontends::pbs::symbols::*; use crate::frontends::pbs::types::PbsType; -use prometeu_analysis::{NameId, NameInterner}; +use prometeu_analysis::{NameId, NameInterner, NodeId}; use std::collections::HashMap; pub struct TypeChecker<'a> { diff --git a/files/LPS - prep.md b/files/LPS - prep.md new file mode 100644 index 00000000..059e956a --- /dev/null +++ b/files/LPS - prep.md @@ -0,0 +1,301 @@ +## PR-R1 — IDs padronizados (newtypes) em um único lugar + +**Branch:** `pr-r1-ids-newtypes` + +### Briefing + +Hoje existem IDs espalhados entre crates (`FileId`, `NameId`, `NodeId`, `SymbolId`, `TypeId`) e alguns campos ainda usam `u32`/`usize` cru (ex.: `Symbol.module: u32`). Para LSP, precisamos de IDs consistentes para indexação, caches, spans e cross-crate APIs. + +### Alvo + +Centralizar e padronizar os seguintes IDs (newtypes): + +* `FileId(u32)` +* `NodeId(u32)` +* `NameId(u32)` +* `SymbolId(u32)` +* `TypeId(u32)` +* `ModuleId(u32)` +* `ProjectId(u32)` *(ver PR-R4 para adoção total; aqui é apenas definição + plumbing mínimo se necessário)* + +**Definição única** em `prometeu-analysis` (ou um crate novo `prometeu-ids`, se você preferir isolar): + +* Arquivo sugerido: `crates/prometeu-analysis/src/ids.rs` +* Exportar via `pub mod ids; pub use ids::*;` + +### Escopo / Mudanças + +1. **Criar o módulo de IDs** com: + +* `#[repr(transparent)] pub struct FileId(pub u32);` etc. +* `Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug`. +* Helpers: + + * `impl FileId { pub const INVALID: FileId = FileId(u32::MAX); }` (opcional) + * `impl From for FileId` e `From for u32`. + +2. **Padronizar uso cross-crate**: + +* `prometeu-compiler/frontends/pbs/ast`: trocar `NodeId` local para `prometeu_analysis::NodeId`. +* `prometeu-compiler/analysis/symbols`: trocar `SymbolId` local para `prometeu_analysis::SymbolId`. +* `prometeu-compiler/analysis/types`: trocar `TypeId` local para `prometeu_analysis::TypeId`. +* Onde houver `usize`/`u32` cru representando file/module/symbol/type/node: substituir. + +3. **Trocar `Symbol.module: u32` → `ModuleId`**. + +4. **Interner (`NameId`)**: + +* Garantir que o interner existente retorna `NameId` do módulo unificado. +* Se existirem `NameId` duplicados em crates diferentes, remover e apontar para o único. + +### Regras de compatibilidade (para não quebrar tudo de uma vez) + +* Se algum ponto ainda depende de `usize`, oferecer funções auxiliares **temporárias**: + + * `fn as_usize(self) -> usize` (somente se realmente necessário) + * Preferir converter na borda (ex.: índices de `Vec`). + +### Testes de aceite + +* `cargo test -q` no workspace. +* Teste unitário novo em `prometeu-analysis`: + + * `ids_are_repr_transparent_and_hashable()` (checa `size_of::() == 4` etc.). +* Teste de compilação indireto: build de `prometeu-compiler` sem warnings de tipos duplicados. + +### Notas de implementação + +* Evitar circular dependency: `prometeu-analysis` deve ser “baixo nível”. Se o compiler já depende dele, ok. +* Se `prometeu-analysis` não puder depender do compiler (não deve), manter IDs neutros e reutilizáveis. + +--- + +## PR-R2 — Span unificado + FileId consistente em todo pipeline + +**Branch:** `pr-r2-span-unify` + +### Briefing + +Hoje existem dois tipos de `Span`: + +* `prometeu-analysis::Span` (com `FileId`) +* `prometeu-compiler::common::spans::Span` (com `file_id: usize`) + +Para LSP, diagnostics/definition/symbols precisam de um único modelo de span para conversão consistente para `Location/Range`. + +A spec aponta spans como **byte offsets**, `end` exclusivo, e file id deve ser estável. (PBS Implementation Spec / Diagnostic specs) + +### Alvo + +* Tornar `prometeu-analysis::Span` o **span canônico** do projeto. +* Remover/aposentar `prometeu-compiler::common::spans::Span`. +* Garantir que **todo span carregue `FileId`**, e não `usize`. + +### Escopo / Mudanças + +1. **Definir `Span` canônico** (se já existe, reforçar): + +* `pub struct Span { pub file: FileId, pub start: u32, pub end: u32 }` +* `start/end` em bytes (u32), `end` exclusivo. +* Helpers: + + * `Span::new(file, start, end)` + * `Span::len()` + * `Span::contains(byte)` + +2. **Migrar compiler para usar Span canônico**: + +* Parser: todos os nós AST devem carregar spans canônicos. +* Diagnostics: `Diagnostic.span` deve ser canônico. +* Resolver/Symbols: `Symbol.decl_span` deve ser canônico. +* RefIndex: deve usar `Span` canônico. + +3. **Matar o `file_id: usize`**: + +* Onde havia `usize`, trocar por `FileId`. +* Nas arenas indexadas por `Vec`, converter no ponto de acesso: `file.0 as usize`. + +4. **Adapters temporários (se necessário)** + +* Se houver muitos pontos que esperam o Span antigo, criar `type OldSpan = Span` por 1 PR (somente dentro do compiler), e remover no fim da PR. + +### Testes de aceite + +* `cargo test -q` no workspace. +* Teste novo: + + * `span_end_is_exclusive()` + * `diagnostic_span_is_valid_for_file()` (valida `end>=start` e `end<=text.len()` em um fixture simples). + +### Critérios de “done” + +* Não existe mais `prometeu-compiler::common::spans::Span` (ou está `deprecated` e sem uso). +* Qualquer `Span` do pipeline é `prometeu-analysis::Span`. + +--- + +## PR-R3 — TextIndex/LineIndex correto para LSP (UTF-16) + conversões + +**Branch:** `pr-r3-text-index-utf16` + +### Briefing + +O LSP usa `Position.character` em **UTF-16 code units** (não bytes). Hoje o `LineIndex` calcula coluna como *byte offset* na linha. Em arquivos com Unicode (acentos), diagnostics e goto definition ficam desalinhados. + +Queremos: + +* Manter o core do compilador em **byte offsets** (spec). +* Converter **somente na borda** (LSP e ferramentas). + +### Alvo + +Criar um índice de texto (por arquivo) que suporte: + +* `byte_offset -> (line, utf16_col)` +* `(line, utf16_col) -> byte_offset` + +E manter: + +* `Span` em bytes. +* O índice baseado no **conteúdo atual** do arquivo. + +### Escopo / Mudanças + +1. Introduzir `TextIndex` em `prometeu-analysis` (ou `prometeu-lsp` se você quiser limitar ao LSP; mas recomendo em `analysis` pois será útil para debug map e tooling): + +* Arquivo sugerido: `crates/prometeu-analysis/src/text_index.rs` +* Estrutura: + + * `line_starts: Vec` (byte offsets) + * `line_utf16_lens: Vec` (opcional cache) + +2. API mínima: + +* `TextIndex::new(text: &str) -> Self` +* `fn byte_to_lsp(&self, byte: u32) -> (u32 /*line*/, u32 /*utf16_col*/)` +* `fn lsp_to_byte(&self, line: u32, utf16_col: u32) -> u32` + +3. Algoritmo + +* `line_starts` calculado por varredura de `\n`. +* Para conversão de col: + + * pegar o slice da linha (`&text[line_start..line_end]`) + * iterar `char_indices()`, acumulando: + + * `byte_pos` e `utf16_count += ch.len_utf16()` + * parar quando: + + * `byte_pos >= target_byte` (byte_to_lsp) + * `utf16_count >= target_utf16` (lsp_to_byte) + +4. Testes fortes com Unicode + +* Casos: `"aé🙂b"` (emoji e acento). +* Validar round-trip: + + * `byte == lsp_to_byte(byte_to_lsp(byte))` para bytes em fronteira de char. + +5. Integração + +* Por enquanto, **não** mexer no LSP server. +* Apenas oferecer API em `analysis` para o LSP consumir na PR-08. + +### Testes de aceite + +* `cargo test -q`. +* Testes novos em `prometeu-analysis`: + + * `text_index_ascii_roundtrip()` + * `text_index_unicode_roundtrip_utf16()` + +--- + +## PR-R4 — ProjectId padronizado + modelagem de Project/Module estável + +**Branch:** `pr-r4-project-id` + +### Briefing + +Hoje o resolver trabalha com `Project { name, version }` e o `symbols.json` contém projects e símbolos agrupados por projeto. Para LSP e para incremental analysis, queremos IDs estáveis e leves para: + +* mapear `uri -> FileId -> (ProjectId, ModuleId)` +* armazenar caches por projeto +* suportar workspace com múltiplos projetos no futuro + +Você pediu explicitamente incluir `ProjectId(u32)` nesta série. + +### Alvo + +Introduzir `ProjectId(u32)` e plugar no modelo de resolução/linking: + +* Cada projeto carregado/descoberto no workspace recebe `ProjectId`. +* Mapas centrais usam `ProjectId` como chave em vez de string. + +### Escopo / Mudanças + +1. Definir `ProjectId(u32)` (já definido na PR-R1) e agora **adotar**. + +2. Criar um registry estável (no analysis/resolver layer): + +* `ProjectRegistry`: + + * `by_name: HashMap` + * `projects: Vec` +* `ProjectKey` pode ser: + + * `{ name: SmolStr, version: Option }` ou `{ name, version }` + +3. Ajustar estruturas existentes para carregar `ProjectId` + +* `ModuleRef` / `ModulePath` / `ResolvedModule` devem apontar para `ProjectId`. +* `symbols.json` writer/reader: + + * Manter `project: "sdk"` no JSON (formato externo), mas internamente mapear para `ProjectId`. + +4. Integração mínima (sem LSP ainda) + +* `AnalysisDb` (ou equivalente) deve conseguir responder: + + * `fn project_for_file(file: FileId) -> ProjectId` + +### Estratégia para não explodir o diff + +* Não reescrever o mundo: + + * manter `ProjectMeta { id: ProjectId, name, version }` + * adicionar `id` aos lugares críticos (resolver, module index, symbols export) + +### Testes de aceite + +* `cargo test -q`. +* Teste novo: + + * `project_registry_stable_ids_for_same_key()` + * `symbols_json_roundtrip_preserves_project_grouping()` (se houver infra de roundtrip) + +### Critérios de “done” + +* Nenhum mapa central chaveado por `String` para identificar projeto no core; usar `ProjectId`. +* Persistência (symbols.json) continua legível e compatível. + +--- + +# Ordem recomendada de merge (para minimizar conflitos) + +1. PR-R1 (IDs) +2. PR-R2 (Span) +3. PR-R3 (TextIndex) +4. PR-R4 (ProjectId) + +> Depois disso, a PR-08 (LSP MVP) fica bem menor: o LSP só consome `Span` + `TextIndex` + IDs. + +--- + +# Checklist global (pré-PR-08) + +* [ ] IDs unificados e usados em todos os crates +* [ ] Span único, sempre com `FileId`, e offsets em bytes +* [ ] TextIndex com conversão UTF-16 confiável (testado) +* [ ] ProjectId adotado no resolver/modelo de projeto +* [ ] Workspace compila e `cargo test` passa diff --git a/files/PRs para Junie Global.md b/files/PRs para Junie Global.md deleted file mode 100644 index 0c037b57..00000000 --- a/files/PRs para Junie Global.md +++ /dev/null @@ -1,39 +0,0 @@ -## 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). - ---- - -## 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. \ No newline at end of file diff --git a/files/PRs para Junie.md b/files/PRs para Junie.md deleted file mode 100644 index 0cb4ce4a..00000000 --- a/files/PRs para Junie.md +++ /dev/null @@ -1,571 +0,0 @@ -# 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; - 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; -} -``` - -### 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` - -### 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, - pub spans: Vec, - pub roots: Vec, -} - -pub enum NodeKind { - File { imports: Vec, decls: Vec }, - 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` 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 } - -pub struct DefIndex { /* HashMap<(ModuleId, NameId, Namespace), SymbolId> */ } - -pub struct RefIndex { /* Vec> by SymbolId */ } - -pub struct NodeToSymbol { /* Vec> 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 }, - // ... conforme v0 -} - -pub struct TypeArena { pub types: Vec } - -pub struct TypeFacts { - pub node_type: Vec>, // index by NodeId - pub symbol_type: Vec>, // 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. diff --git a/test-cartridges/canonical/golden/program.pbc b/test-cartridges/canonical/golden/program.pbc index b06b91caaacaf4416129e782584fa51dc847ec21..666448e9c82fd9759bc1514ce6c916eaa9193fac 100644 GIT binary patch delta 25 ecmeB|?U&tadA