diff --git a/crates/prometeu-analysis/src/text_index.rs b/crates/prometeu-analysis/src/text_index.rs index 34049e5a..1c2a190a 100644 --- a/crates/prometeu-analysis/src/text_index.rs +++ b/crates/prometeu-analysis/src/text_index.rs @@ -1,10 +1,10 @@ -/// TextIndex fornece conversões entre offsets em bytes (usados no core) -/// e posições LSP (linha, coluna em unidades UTF-16). +/// TextIndex provides conversions between byte offsets (used in the core) +/// and LSP positions (line, column in UTF-16 units). /// -/// Observações: -/// - `line_starts` guarda os offsets em bytes do início de cada linha. -/// - Mantemos uma cópia do texto para permitir conversões sem dependências externas. -/// - A coluna LSP é contada em unidades UTF-16, excluindo o `\n` do fim de linha. +/// Notes: +/// - `line_starts` stores byte offsets for the start of each line. +/// - We keep a copy of the text to allow conversions without external dependencies. +/// - The LSP column is counted in UTF-16 units, excluding the end-of-line `\n`. #[derive(Clone, Debug)] pub struct TextIndex { text: String, @@ -12,13 +12,13 @@ pub struct TextIndex { } impl TextIndex { - /// Constrói o índice a partir do conteúdo textual atual do arquivo. + /// Builds the index from the file's current textual content. pub fn new(text: &str) -> Self { let mut line_starts = Vec::with_capacity(128); line_starts.push(0); for (byte, ch) in text.char_indices() { if ch == '\n' { - // início da próxima linha é o byte após o '\n' + // the start of the next line is the byte after the '\n' line_starts.push((byte + 1) as u32); } } @@ -28,15 +28,15 @@ impl TextIndex { } } - /// Número de linhas (0-based; linhas vazias contam). + /// Number of lines (0-based; empty lines count). #[inline] pub fn line_count(&self) -> u32 { self.line_starts.len() as u32 } - /// Converte um offset em bytes (dentro do arquivo) para (linha, coluna UTF-16) no padrão LSP. + /// Converts a byte offset (within the file) to (line, UTF-16 column) in LSP format. /// - /// Para offsets exatamente no fim da linha, a coluna será o comprimento UTF-16 da linha. + /// For offsets exactly at end-of-line, the column will be the line's UTF-16 length. pub fn byte_to_lsp(&self, byte: u32) -> (u32, u32) { let byte = byte.min(self.text.len() as u32); let line = match self.line_starts.binary_search(&byte) { @@ -56,10 +56,10 @@ impl TextIndex { (line, utf16_col) } - /// Converte (linha, coluna UTF-16) em offset em bytes. + /// Converts (line, UTF-16 column) to a byte offset. /// - /// - Linhas fora do intervalo são clampadas para [0, last]. - /// - Colunas maiores que o tamanho UTF-16 da linha retornam o fim da linha. + /// - Lines outside the range are clamped to [0, last]. + /// - Columns larger than the line's UTF-16 length return end-of-line. pub fn lsp_to_byte(&self, line: u32, utf16_col: u32) -> u32 { let line = line.min(self.line_count().saturating_sub(1)); let (line_start, line_end) = self.line_bounds(line); @@ -72,7 +72,7 @@ impl TextIndex { } acc += ch.len_utf16() as u32; } - // Se a coluna alvo é após o último caractere, retorne o fim da linha. + // If the target column is after the last character, return end-of-line. line_end as u32 } @@ -83,9 +83,8 @@ impl TextIndex { .get(line as usize) .unwrap_or(self.line_starts.last().unwrap()); let next = self.line_starts.get(line as usize + 1).copied(); - // Se existe próxima linha, `next` aponta para o byte após o '\n' da linha atual - // então o conteúdo termina em `next - 1`. Caso contrário (última linha), - // o conteúdo termina em `text.len()`. + // If there is a next line, `next` points to the byte after the current line's '\n', + // so the content ends at `next - 1`. Otherwise (last line), the content ends at `text.len()`. let end = match next { Some(next_start) => next_start.saturating_sub(1), None => self.text.len() as u32, @@ -103,11 +102,11 @@ mod tests_internal { let s = "ab\ncd\n"; let idx = TextIndex::new(s); assert_eq!(idx.line_count(), 3); - // linha 0: "ab" + // line 0: "ab" assert_eq!(idx.line_bounds(0), (0, 2)); - // linha 1: "cd" + // line 1: "cd" assert_eq!(idx.line_bounds(1), (3, 5)); - // linha 2: linha vazia final + // line 2: final empty line assert_eq!(idx.line_bounds(2), (6, 6)); } } diff --git a/crates/prometeu-analysis/tests/text_index_tests.rs b/crates/prometeu-analysis/tests/text_index_tests.rs index cec1b680..ada55d54 100644 --- a/crates/prometeu-analysis/tests/text_index_tests.rs +++ b/crates/prometeu-analysis/tests/text_index_tests.rs @@ -5,22 +5,22 @@ fn text_index_ascii_roundtrip() { let text = "hello\nworld\nthis is ascii"; let idx = TextIndex::new(text); - // Verifica round-trip em todas as fronteiras de char + // Verify round-trip on all character boundaries let mut boundaries: Vec = text.char_indices().map(|(i, _)| i).collect(); boundaries.push(text.len()); for &b in &boundaries { let (line, col16) = idx.byte_to_lsp(b as u32); let b2 = idx.lsp_to_byte(line, col16); - assert_eq!(b2, b as u32, "roundtrip falhou para byte {} -> (l={},c16={})", b, line, col16); + assert_eq!(b2, b as u32, "roundtrip failed for byte {} -> (l={},c16={})", b, line, col16); } - // Alguns checks diretos - // início: (0,0) + // Some direct checks + // start: (0,0) assert_eq!(idx.byte_to_lsp(0), (0, 0)); - // após "hello" (5), antes do '\n': linha 0, col=5 + // after "hello" (5), before '\n': line 0, col=5 assert_eq!(idx.byte_to_lsp(5), (0, 5)); - // após '\n' (6): linha 1, col=0 + // after '\n' (6): line 1, col=0 assert_eq!(idx.byte_to_lsp(6), (1, 0)); } @@ -30,25 +30,25 @@ fn text_index_unicode_roundtrip_utf16() { let text = "aé🙂b"; let idx = TextIndex::new(text); - // fronteiras de char + fim + // character boundaries + end let mut boundaries: Vec = text.char_indices().map(|(i, _)| i).collect(); boundaries.push(text.len()); for &b in &boundaries { let (line, col16) = idx.byte_to_lsp(b as u32); let b2 = idx.lsp_to_byte(line, col16); - assert_eq!(b2, b as u32, "roundtrip unicode falhou para byte {} -> (l={},c16={})", b, line, col16); + assert_eq!(b2, b as u32, "unicode roundtrip failed for byte {} -> (l={},c16={})", b, line, col16); } - // Checagens de colunas esperadas na linha 0 + // Expected columns on line 0 // bytes: [0:'a'][1..2:'é'][3..6:'🙂'][7:'b'][8:end] - assert_eq!(idx.byte_to_lsp(0), (0, 0)); // antes de 'a' - assert_eq!(idx.byte_to_lsp(1), (0, 1)); // após 'a' - assert_eq!(idx.byte_to_lsp(3), (0, 2)); // após 'a' + 'é' (1+1 utf16) - assert_eq!(idx.byte_to_lsp(7), (0, 4)); // após '🙂' (2 utf16) => 1+1+2=4 - assert_eq!(idx.byte_to_lsp(8), (0, 5)); // após 'b' + assert_eq!(idx.byte_to_lsp(0), (0, 0)); // before 'a' + assert_eq!(idx.byte_to_lsp(1), (0, 1)); // after 'a' + assert_eq!(idx.byte_to_lsp(3), (0, 2)); // after 'a' + 'é' (1+1 utf16) + assert_eq!(idx.byte_to_lsp(7), (0, 4)); // after '🙂' (2 utf16) => 1+1+2=4 + assert_eq!(idx.byte_to_lsp(8), (0, 5)); // after 'b' - // e inverso, colunas específicas + // and inverse, specific columns assert_eq!(idx.lsp_to_byte(0, 0), 0); assert_eq!(idx.lsp_to_byte(0, 1), 1); assert_eq!(idx.lsp_to_byte(0, 2), 3); diff --git a/crates/prometeu-compiler/src/analysis/types.rs b/crates/prometeu-compiler/src/analysis/types.rs index 5fccbcea..c84f8828 100644 --- a/crates/prometeu-compiler/src/analysis/types.rs +++ b/crates/prometeu-compiler/src/analysis/types.rs @@ -113,8 +113,8 @@ impl TypeFacts { #[cfg(test)] mod tests { use super::*; - // Mock de NameId e SymbolId para testes simplificados se necessário, - // ou usar valores reais. + // Mock NameId and SymbolId for simplified tests if necessary, + // or use real values. #[test] fn type_arena_push_is_append_only() { @@ -138,7 +138,7 @@ mod tests { assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. })); assert!(matches!(arena.kind(t2), TypeKind::Optional { .. })); - // Adicionar mais tipos não deve mudar os anteriores + // Adding more types should not change the previous ones let t3 = arena.intern_type(TypeKind::Array { inner: t1, len: None }); assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. })); assert!(matches!(arena.kind(t2), TypeKind::Optional { .. })); diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs index 126da997..176048a9 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs @@ -225,7 +225,7 @@ fn walk_node( walk_node(member, arena, module, index, imports, ref_index, node_to_symbol, diagnostics); } } - // Nós literais ou que não contém outros nós para percorrer (neste nível) + // Literal nodes or those that do not contain other nodes to walk (at this level) NodeKind::IntLit(_) | NodeKind::FloatLit(_) | NodeKind::BoundedLit(_) | NodeKind::StringLit(_) | NodeKind::TypeName(_) | NodeKind::TypeApp(_) | NodeKind::Import(_) | NodeKind::ImportSpec(_) | NodeKind::ServiceFnSig(_) | NodeKind::ConstructorDecl(_) | NodeKind::ConstantDecl(_) => {} diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs index 02f2760e..0d514e33 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs @@ -441,9 +441,9 @@ impl<'a> Resolver<'a> { let sym_id = self.define_local(param.name, param.span.clone(), SymbolKind::Local); if let (Some(tid), Some(sid)) = (ty_id, sym_id) { self.type_facts.set_symbol_type(sid, tid); - // O node do Ident do parâmetro na declaração também pode ser vinculado - // Mas o ParamNodeArena não tem um NodeId direto no AST que represente o Ident do parâmetro. - // O `param.name` é NameId. + // The Ident node of the parameter in the declaration could also be bound + // But ParamNodeArena does not have a direct NodeId in the AST that represents the parameter's Ident. + // `param.name` is a NameId. } } if let Some(ret) = n.ret { diff --git a/crates/prometeu-kernel/src/prometeu_os.rs b/crates/prometeu-kernel/src/prometeu_os.rs index 1d80b55c..bcf55937 100644 --- a/crates/prometeu-kernel/src/prometeu_os.rs +++ b/crates/prometeu-kernel/src/prometeu_os.rs @@ -335,7 +335,7 @@ impl PrometeuOS { } - // Helper para syscalls + // Helper for syscalls fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> { let level = match level_val { 0 => LogLevel::Trace, @@ -370,11 +370,11 @@ impl PrometeuOS { } pub fn get_color(&self, value: i64) -> Color { - // Agora usamos o valor diretamente como RGB565. + // We now use the value directly as RGB565. Color::from_raw(value as u16) } - // Helper para syscalls + // Helper for syscalls pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a prometeu_abi::model::Button> { let pad = hw.pad(); match id { diff --git a/crates/prometeu-lsp/src/main.rs b/crates/prometeu-lsp/src/main.rs index 49dab266..ef0a1fe4 100644 --- a/crates/prometeu-lsp/src/main.rs +++ b/crates/prometeu-lsp/src/main.rs @@ -24,7 +24,7 @@ impl tower_lsp::LanguageServer for Backend { tower_lsp::lsp_types::TextDocumentSyncKind::FULL, ), ), - // Declaramos capacidades desde já para evitar churn posterior. + // Declare capabilities up front to avoid later churn. definition_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), document_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), workspace_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), @@ -40,7 +40,7 @@ impl tower_lsp::LanguageServer for Backend { tower_lsp::lsp_types::SemanticTokensServerCapabilities::SemanticTokensOptions( tower_lsp::lsp_types::SemanticTokensOptions { legend: tower_lsp::lsp_types::SemanticTokensLegend { - // preenchido no PR-12 + // filled in PR-12 token_types: vec![], token_modifiers: vec![], }, diff --git a/crates/prometeu-lsp/src/rebuild.rs b/crates/prometeu-lsp/src/rebuild.rs index 6077d2d3..0d1bdf6f 100644 --- a/crates/prometeu-lsp/src/rebuild.rs +++ b/crates/prometeu-lsp/src/rebuild.rs @@ -2,10 +2,10 @@ use tokio_util::sync::CancellationToken; use crate::analysis_db::SharedDb; -/// Solicita rebuild do projeto (coarse). Cancela rebuild anterior se em progresso. -/// Implementação inicial: apenas cria task e retorna. +/// Requests a project rebuild (coarse). Cancels the previous rebuild if in progress. +/// Initial implementation: only spawns a task and returns. pub async fn request_rebuild(db: SharedDb) { - // 1) lock curto: cancelar token anterior e instalar token novo + // 1) short lock: cancel previous token and install a new one let new_token = CancellationToken::new(); { let mut guard = db.write().await; @@ -15,33 +15,33 @@ pub async fn request_rebuild(db: SharedDb) { guard.active_rebuild = Some(new_token.clone()); } - // 2) spawn task: roda análise fora do lock + // 2) spawn task: run analysis outside the lock tokio::spawn(async move { - // Ponto seguro: checar antes de começar + // Safe point: check before starting if new_token.is_cancelled() { return; } // TODO(PR-03/04/05): - // - Clonar snapshot de FileDB + // - Clone FileDB snapshot // - Parsing // - Binding/Resolver // - Typecheck - // - Coleta de diagnostics + // - Collect diagnostics - // Ponto seguro: após parsing + // Safe point: after parsing if new_token.is_cancelled() { return; } - // Ponto seguro: após resolver + // Safe point: after resolving if new_token.is_cancelled() { return; } - // Ponto seguro: após typecheck + // Safe point: after typecheck if new_token.is_cancelled() { return; } - // 3) lock curto: se token não cancelado, swap estado + revision++ + // 3) short lock: if token not cancelled, swap state + revision++ if !new_token.is_cancelled() { let mut guard = db.write().await; - // TODO: checar se o token ainda é o ativo quando tivermos um identificador estável + // TODO: check if the token is still the active one when we have a stable identifier if !new_token.is_cancelled() { - // TODO: aplicar resultados reais de análise quando disponíveis + // TODO: apply real analysis results when available guard.revision = guard.revision.saturating_add(1); - // Nota: não limpamos `active_rebuild` aqui para evitar interferir num rebuild mais novo + // Note: we don't clear `active_rebuild` here to avoid interfering with a newer rebuild } } });