diff --git a/crates/prometeu-analysis/src/span.rs b/crates/prometeu-analysis/src/span.rs index e9d91378..5d8042b9 100644 --- a/crates/prometeu-analysis/src/span.rs +++ b/crates/prometeu-analysis/src/span.rs @@ -6,3 +6,20 @@ pub struct Span { pub start: u32, // byte offset pub end: u32, // byte offset, exclusive } + +impl Span { + #[inline] + pub fn new(file: FileId, start: u32, end: u32) -> Self { + Self { file, start, end } + } + + #[inline] + pub fn len(&self) -> u32 { + self.end.saturating_sub(self.start) + } + + #[inline] + pub fn contains(&self, byte: u32) -> bool { + self.start <= byte && byte < self.end + } +} diff --git a/crates/prometeu-analysis/tests/span_tests.rs b/crates/prometeu-analysis/tests/span_tests.rs new file mode 100644 index 00000000..b58ee7c9 --- /dev/null +++ b/crates/prometeu-analysis/tests/span_tests.rs @@ -0,0 +1,14 @@ +use prometeu_analysis::{ids::FileId, span::Span}; + +#[test] +fn span_end_is_exclusive() { + let file = FileId(1); + let s = Span::new(file, 2, 5); + // len = end - start + assert_eq!(s.len(), 3); + // contains is [start, end) + assert!(s.contains(2)); + assert!(s.contains(3)); + assert!(s.contains(4)); + assert!(!s.contains(5)); +} diff --git a/crates/prometeu-compiler/src/analysis/symbols/mod.rs b/crates/prometeu-compiler/src/analysis/symbols/mod.rs index 34701303..9120eb83 100644 --- a/crates/prometeu-compiler/src/analysis/symbols/mod.rs +++ b/crates/prometeu-compiler/src/analysis/symbols/mod.rs @@ -1,5 +1,5 @@ use crate::common::diagnostics::{Diagnostic, Severity}; -use crate::common::spans::Span; +use crate::common::spans::{Span, FileId}; use crate::frontends::pbs::ast::AstArena; use prometeu_analysis::NodeId; use prometeu_analysis::{NameId, SymbolId, ModuleId}; @@ -91,7 +91,7 @@ impl DefIndex { code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(), message: "Duplicate symbol in the same module and namespace".to_string(), // Placeholder span; callers should overwrite with accurate span when known. - span: Span::new(0, 0, 0), + span: Span::new(FileId(0), 0, 0), related: Vec::new(), }); } @@ -177,7 +177,7 @@ mod tests { kind: SymbolKind::Function, exported: false, module, - decl_span: Span::new(0, 1, 2), + decl_span: Span::new(FileId(0), 1, 2), } } @@ -242,16 +242,16 @@ mod tests { #[test] fn ref_index_records_refs_per_symbol() { let mut index = RefIndex::new(); - let span_a1 = Span::new(0, 1, 2); - let span_a2 = Span::new(0, 3, 4); - let span_b1 = Span::new(1, 10, 12); + let span_a1 = Span::new(FileId(0), 1, 2); + let span_a2 = Span::new(FileId(0), 3, 4); + let span_b1 = Span::new(FileId(1), 10, 12); - index.record_ref(SymbolId(2), span_a1); - index.record_ref(SymbolId(2), span_a2); - index.record_ref(SymbolId(5), span_b1); + index.record_ref(SymbolId(2), span_a1.clone()); + index.record_ref(SymbolId(2), span_a2.clone()); + index.record_ref(SymbolId(5), span_b1.clone()); - assert_eq!(index.refs_of(SymbolId(2)), &[span_a1, span_a2]); - assert_eq!(index.refs_of(SymbolId(5)), &[span_b1]); + assert_eq!(index.refs_of(SymbolId(2)), &[span_a1.clone(), span_a2.clone()]); + assert_eq!(index.refs_of(SymbolId(5)), &[span_b1.clone()]); assert!(index.refs_of(SymbolId(9)).is_empty()); } diff --git a/crates/prometeu-compiler/src/analysis/types.rs b/crates/prometeu-compiler/src/analysis/types.rs index 9d840e75..5fccbcea 100644 --- a/crates/prometeu-compiler/src/analysis/types.rs +++ b/crates/prometeu-compiler/src/analysis/types.rs @@ -1,5 +1,6 @@ use crate::analysis::symbols::{SymbolArena}; use prometeu_analysis::{NameId, NameInterner, TypeId, SymbolId, NodeId, ModuleId}; +use crate::common::spans::FileId; use serde::{Deserialize, Serialize}; // Use canonical TypeId from prometeu-analysis @@ -211,7 +212,7 @@ mod tests { kind: SymbolKind::Struct, exported: false, module: ModuleId(0), - decl_span: Span::new(0, 0, 0), + decl_span: Span::new(FileId(0), 0, 0), }); let struct_t = arena.intern_type(TypeKind::Struct { sym: sym_id }); diff --git a/crates/prometeu-compiler/src/backend/emit_bytecode.rs b/crates/prometeu-compiler/src/backend/emit_bytecode.rs index 4d240ffb..62c4cc0a 100644 --- a/crates/prometeu-compiler/src/backend/emit_bytecode.rs +++ b/crates/prometeu-compiler/src/backend/emit_bytecode.rs @@ -95,7 +95,7 @@ pub fn emit_fragments(module: &ir_vm::Module) -> Result { if let Some(instr) = instr_opt { if let Some(span) = &instr.span { pc_to_span.push((current_pc, SourceSpan { - file_id: span.file_id as u32, + file_id: span.file.as_u32(), start: span.start, end: span.end, })); diff --git a/crates/prometeu-compiler/src/building/output.rs b/crates/prometeu-compiler/src/building/output.rs index ed71dac6..530d94ce 100644 --- a/crates/prometeu-compiler/src/building/output.rs +++ b/crates/prometeu-compiler/src/building/output.rs @@ -2,7 +2,7 @@ use crate::backend::emit_fragments; use crate::building::plan::{BuildStep, BuildTarget}; use crate::common::diagnostics::DiagnosticBundle; use crate::common::files::FileManager; -use crate::common::spans::Span; +use crate::common::spans::{FileId, Span}; use crate::deps::resolver::ProjectId; use crate::frontends::pbs::ast::ParsedAst; use crate::frontends::pbs::collector::SymbolCollector; @@ -123,7 +123,7 @@ pub fn compile_project( let source_code = std::fs::read_to_string(&source_abs)?; let file_id = file_manager.add(source_abs.clone(), source_code.clone()); - let mut parser = Parser::new(&source_code, file_id, &mut interner); + let mut parser = Parser::new(&source_code, FileId(file_id as u32), &mut interner); let parsed = parser.parse_file()?; let mut collector = SymbolCollector::new(&interner); @@ -155,7 +155,7 @@ pub fn compile_project( interner.resolve(existing.name), module_path ), - existing.span, + existing.span.clone(), ).into()); } let _ = ms.type_symbols.insert(sym); @@ -169,7 +169,7 @@ pub fn compile_project( interner.resolve(existing.name), module_path ), - existing.span, + existing.span.clone(), ).into()); } let _ = ms.value_symbols.insert(sym); @@ -209,7 +209,7 @@ pub fn compile_project( visibility: Visibility::Pub, ty: meta.ty.clone(), is_host: meta.is_host, - span: Span::new(0, 0, 0), + span: Span::new(FileId::INVALID, 0, 0), origin: Some(synthetic_module_path.clone()), }; diff --git a/crates/prometeu-compiler/src/common/diagnostics.rs b/crates/prometeu-compiler/src/common/diagnostics.rs index f209a389..1e954baf 100644 --- a/crates/prometeu-compiler/src/common/diagnostics.rs +++ b/crates/prometeu-compiler/src/common/diagnostics.rs @@ -1,5 +1,5 @@ use crate::common::files::FileManager; -use crate::common::spans::Span; +use crate::common::spans::{FileId, Span}; use serde::{Serialize, Serializer}; #[derive(Debug, Clone, PartialEq)] @@ -84,21 +84,26 @@ impl DiagnosticBundle { let mut diags = self.diagnostics.clone(); diags.sort_by(|a, b| { - (a.span.file_id, a.span.start, a.span.end, &a.code) - .cmp(&(b.span.file_id, b.span.start, b.span.end, &b.code)) + ( + a.span.file.as_usize(), + a.span.start, + a.span.end, + &a.code, + ) + .cmp(&(b.span.file.as_usize(), b.span.start, b.span.end, &b.code)) }); let canonical_diags: Vec = diags .iter() .map(|d| { - let s = d.span; - let file = if s.file_id == usize::MAX { + let s = &d.span; + let file = if s.file == FileId::INVALID { "".to_string() } else { file_manager - .get_path(s.file_id) + .get_path(s.file.as_usize()) .and_then(|p| p.file_name().map(|n| n.to_string_lossy().to_string())) - .unwrap_or_else(|| format!("file_{}", s.file_id)) + .unwrap_or_else(|| format!("file_{}", s.file.as_usize())) }; let canonical_span = CanonicalSpan { file, @@ -110,13 +115,13 @@ impl DiagnosticBundle { .related .iter() .map(|(msg, sp)| { - let file = if sp.file_id == usize::MAX { + let file = if sp.file == FileId::INVALID { "".to_string() } else { file_manager - .get_path(sp.file_id) + .get_path(sp.file.as_usize()) .and_then(|p| p.file_name().map(|n| n.to_string_lossy().to_string())) - .unwrap_or_else(|| format!("file_{}", sp.file_id)) + .unwrap_or_else(|| format!("file_{}", sp.file.as_usize())) }; let rsp = CanonicalSpan { file, diff --git a/crates/prometeu-compiler/src/common/spans.rs b/crates/prometeu-compiler/src/common/spans.rs index 591d80a1..10e9e17e 100644 --- a/crates/prometeu-compiler/src/common/spans.rs +++ b/crates/prometeu-compiler/src/common/spans.rs @@ -1,18 +1,3 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Span { - pub file_id: usize, - pub start: u32, - pub end: u32, -} - -impl Span { - pub fn new(file_id: usize, start: u32, end: u32) -> Self { - Self { - file_id, - start, - end, - } - } -} +// Canonical Span for the whole workspace +pub use prometeu_analysis::span::Span; +pub use prometeu_analysis::ids::FileId; diff --git a/crates/prometeu-compiler/src/common/symbols.rs b/crates/prometeu-compiler/src/common/symbols.rs index 127d38b2..0739c07f 100644 --- a/crates/prometeu-compiler/src/common/symbols.rs +++ b/crates/prometeu-compiler/src/common/symbols.rs @@ -170,14 +170,14 @@ fn convert_symbol( // Actually, we'll just mark it exported=false if it's a function. } - let span = sym.span; - let file_path = file_manager.get_path(span.file_id) + let span = sym.span.clone(); + let file_path = file_manager.get_path(span.file.as_usize()) .map(|p| p.to_string_lossy().to_string()) - .unwrap_or_else(|| format!("unknown_file_{}", span.file_id)); + .unwrap_or_else(|| format!("unknown_file_{}", span.file.as_usize())); // Convert 1-based to 0-based - let (s_line, s_col) = file_manager.lookup_pos(span.file_id, span.start); - let (e_line, e_col) = file_manager.lookup_pos(span.file_id, span.end); + let (s_line, s_col) = file_manager.lookup_pos(span.file.as_usize(), span.start); + let (e_line, e_col) = file_manager.lookup_pos(span.file.as_usize(), span.end); let decl_span = SpanRange { file_uri: file_path, diff --git a/crates/prometeu-compiler/src/compiler.rs b/crates/prometeu-compiler/src/compiler.rs index 6c404931..03ec2ad9 100644 --- a/crates/prometeu-compiler/src/compiler.rs +++ b/crates/prometeu-compiler/src/compiler.rs @@ -6,7 +6,7 @@ use crate::backend; use crate::common::config::ProjectConfig; use crate::common::files::FileManager; -use crate::common::spans::Span; +use crate::common::spans::{FileId, Span}; use crate::common::symbols::{DebugSymbol, ProjectSymbols, RawSymbol, SymbolsFile}; use anyhow::Result; use prometeu_bytecode::BytecodeModule; @@ -44,11 +44,11 @@ impl CompilationUnit { pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> { let mut debug_symbols = Vec::new(); for raw in &self.raw_symbols { - let path = self.file_manager.get_path(raw.span.file_id) + let path = self.file_manager.get_path(raw.span.file.as_usize()) .map(|p| p.to_string_lossy().to_string()) - .unwrap_or_else(|| format!("file_{}", raw.span.file_id)); + .unwrap_or_else(|| format!("file_{}", raw.span.file.as_usize())); - let (line, col) = self.file_manager.lookup_pos(raw.span.file_id, raw.span.start); + let (line, col) = self.file_manager.lookup_pos(raw.span.file.as_usize(), raw.span.start); debug_symbols.push(DebugSymbol { pc: raw.pc, @@ -116,11 +116,7 @@ pub fn compile_ext(project_dir: &Path, explain_deps: bool) -> Result Span { - self.spans[id.0 as usize] + self.spans[id.0 as usize].clone() } } diff --git a/crates/prometeu-compiler/src/frontends/pbs/collector.rs b/crates/prometeu-compiler/src/frontends/pbs/collector.rs index f85ba16a..f1e7ba84 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/collector.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/collector.rs @@ -66,7 +66,7 @@ impl<'a> SymbolCollector<'a> { }; let span = arena.span(id); - self.check_export_eligibility(SymbolKind::Function, vis, span); + self.check_export_eligibility(SymbolKind::Function, vis, &span); let symbol = Symbol { name: decl.name, @@ -75,7 +75,7 @@ impl<'a> SymbolCollector<'a> { visibility: vis, ty: None, // Will be resolved later is_host: false, - span, + span: span.clone(), origin: None, }; self.insert_value_symbol(symbol); @@ -89,7 +89,7 @@ impl<'a> SymbolCollector<'a> { let span = arena.span(id); - self.check_export_eligibility(SymbolKind::Service, vis, span); + self.check_export_eligibility(SymbolKind::Service, vis, &span); let symbol = Symbol { name: decl.name, @@ -98,7 +98,7 @@ impl<'a> SymbolCollector<'a> { visibility: vis, ty: None, is_host: false, - span, + span: span.clone(), origin: None, }; self.insert_type_symbol(symbol); @@ -119,7 +119,7 @@ impl<'a> SymbolCollector<'a> { let span = arena.span(id); - self.check_export_eligibility(kind.clone(), vis, span); + self.check_export_eligibility(kind.clone(), vis, &span); let symbol = Symbol { name: decl.name, @@ -128,7 +128,7 @@ impl<'a> SymbolCollector<'a> { visibility: vis, ty: None, is_host: decl.is_host, - span, + span: span.clone(), origin: None, }; self.insert_type_symbol(symbol); @@ -171,9 +171,9 @@ impl<'a> SymbolCollector<'a> { message: format!( "Duplicate symbol '{}' already defined at {:?}", self.interner.resolve(symbol.name), - existing.span + &existing.span ), - span: symbol.span, + span: symbol.span.clone(), related: Vec::new(), }); } @@ -186,20 +186,20 @@ impl<'a> SymbolCollector<'a> { "DebugSymbol '{}' collides with another symbol in the {:?} namespace defined at {:?}", self.interner.resolve(symbol.name), existing.namespace, - existing.span + &existing.span ), - span: symbol.span, + span: symbol.span.clone(), related: Vec::new(), }); } - fn check_export_eligibility(&mut self, kind: SymbolKind, vis: Visibility, span: crate::common::spans::Span) { + fn check_export_eligibility(&mut self, kind: SymbolKind, vis: Visibility, span: &crate::common::spans::Span) { if let Err(msg) = ExportSurfaceKind::validate_visibility(kind, vis) { self.diagnostics.push(Diagnostic { severity: Severity::Error, code: "E_SEMANTIC_EXPORT_RESTRICTION".to_string(), message: msg, - span, + span: span.clone(), related: Vec::new(), }); } diff --git a/crates/prometeu-compiler/src/frontends/pbs/lexer.rs b/crates/prometeu-compiler/src/frontends/pbs/lexer.rs index 6a7e7894..bd577d1b 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/lexer.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/lexer.rs @@ -1,16 +1,16 @@ use super::token::{Token, TokenKind}; -use crate::common::spans::Span; +use crate::common::spans::{FileId, Span}; use std::iter::Peekable; use std::str::Chars; pub struct Lexer<'a> { chars: Peekable>, - file_id: usize, + file_id: FileId, pos: u32, } impl<'a> Lexer<'a> { - pub fn new(source: &'a str, file_id: usize) -> Self { + pub fn new(source: &'a str, file_id: FileId) -> Self { Self { chars: source.chars().peekable(), file_id, @@ -289,7 +289,7 @@ mod tests { #[test] fn test_lex_basic_tokens() { let source = "( ) { } [ ] , . : ; -> = == + - * / % ! != < > <= >= && ||"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let expected = vec![ TokenKind::OpenParen, TokenKind::CloseParen, @@ -313,7 +313,7 @@ mod tests { #[test] fn test_lex_keywords() { let source = "import pub mod service fn let mut declare struct contract host error optional result some none ok err if else when for in return handle borrow mutate peek take alloc weak as"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let expected = vec![ TokenKind::Import, TokenKind::Pub, TokenKind::Mod, TokenKind::Service, @@ -336,7 +336,7 @@ mod tests { #[test] fn test_lex_identifiers() { let source = "foo bar _baz qux123"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let expected = vec![ TokenKind::Identifier("foo".to_string()), @@ -355,7 +355,7 @@ mod tests { #[test] fn test_lex_literals() { let source = "123 3.14 255b \"hello world\""; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let expected = vec![ TokenKind::IntLit(123), @@ -374,7 +374,7 @@ mod tests { #[test] fn test_lex_comments() { let source = "let x = 10; // this is a comment\nlet y = 20;"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let expected = vec![ TokenKind::Let, @@ -399,7 +399,7 @@ mod tests { #[test] fn test_lex_spans() { let source = "let x = 10;"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); let t1 = lexer.next_token(); // let assert_eq!(t1.span.start, 0); @@ -425,7 +425,7 @@ mod tests { #[test] fn test_lex_invalid_tokens() { let source = "@ #"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_))); assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_))); @@ -435,7 +435,7 @@ mod tests { #[test] fn test_lex_unterminated_string() { let source = "\"hello"; - let mut lexer = Lexer::new(source, 0); + let mut lexer = Lexer::new(source, FileId(0)); assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_))); } diff --git a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs index b1786a56..837805a5 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/lowering.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/lowering.rs @@ -297,7 +297,7 @@ impl<'a> Lowerer<'a> { } fn lower_node(&mut self, node: NodeId) -> Result<(), ()> { - let old_span = self.current_span; + let old_span = self.current_span.clone(); self.current_span = Some(self.arena.span(node)); let res = match self.arena.kind(node) { @@ -1243,7 +1243,7 @@ impl<'a> Lowerer<'a> { fn emit(&mut self, kind: InstrKind) { if let Some(block) = &mut self.current_block { - block.instrs.push(Instr::new(kind, self.current_span)); + block.instrs.push(Instr::new(kind, self.current_span.clone())); } } @@ -1346,10 +1346,11 @@ mod tests { use crate::frontends::pbs::symbols::ModuleSymbols; use crate::ir_core; use prometeu_analysis::NameInterner; + use crate::common::spans::FileId; fn lower_program(code: &str) -> ir_core::Program { let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1461,7 +1462,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1695,7 +1696,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1727,7 +1728,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1772,7 +1773,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1810,7 +1811,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1841,7 +1842,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1869,7 +1870,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1896,7 +1897,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1923,7 +1924,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1959,7 +1960,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -1995,7 +1996,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -2031,7 +2032,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); @@ -2058,7 +2059,7 @@ mod tests { } "; let mut interner = NameInterner::new(); - let mut parser = Parser::new(code, 0, &mut interner); + let mut parser = Parser::new(code, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse"); let mut collector = SymbolCollector::new(&interner); diff --git a/crates/prometeu-compiler/src/frontends/pbs/mod.rs b/crates/prometeu-compiler/src/frontends/pbs/mod.rs index a043a3e0..b0433629 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/mod.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/mod.rs @@ -25,6 +25,7 @@ use crate::frontends::Frontend; use crate::ir_vm; use crate::lowering::core_to_vm; use prometeu_analysis::NameInterner; +use crate::common::spans::FileId; use std::path::Path; pub struct PbsFrontend; @@ -43,13 +44,13 @@ impl Frontend for PbsFrontend { crate::common::diagnostics::DiagnosticBundle::error( "E_FRONTEND_IO", format!("Failed to read file: {}", e), - crate::common::spans::Span::new(usize::MAX, 0, 0), + crate::common::spans::Span::new(FileId::INVALID, 0, 0), ) })?; let file_id = file_manager.add(entry.to_path_buf(), source.clone()); let mut interner = NameInterner::new(); - let mut parser = parser::Parser::new(&source, file_id, &mut interner); + let mut parser = parser::Parser::new(&source, FileId(file_id as u32), &mut interner); let parsed = parser.parse_file()?; let mut collector = SymbolCollector::new(&interner); @@ -88,7 +89,7 @@ impl Frontend for PbsFrontend { crate::common::diagnostics::DiagnosticBundle::error( "E_CORE_INVARIANT", format!("Core IR Invariant Violation: {}", e), - crate::common::spans::Span::new(usize::MAX, 0, 0), + crate::common::spans::Span::new(FileId::INVALID, 0, 0), ) })?; @@ -97,7 +98,7 @@ impl Frontend for PbsFrontend { crate::common::diagnostics::DiagnosticBundle::error( "E_LOWERING", format!("Lowering error: {}", e), - crate::common::spans::Span::new(usize::MAX, 0, 0), + crate::common::spans::Span::new(FileId::INVALID, 0, 0), ) }) } diff --git a/crates/prometeu-compiler/src/frontends/pbs/parser.rs b/crates/prometeu-compiler/src/frontends/pbs/parser.rs index d5407428..ed977412 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/parser.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/parser.rs @@ -1,5 +1,5 @@ use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, Severity}; -use crate::common::spans::Span; +use crate::common::spans::{FileId, Span}; use crate::frontends::pbs::ast::*; use crate::frontends::pbs::lexer::Lexer; use crate::frontends::pbs::token::{Token, TokenKind}; @@ -8,7 +8,7 @@ use prometeu_analysis::{NameId, NameInterner, NodeId}; pub struct Parser<'a> { tokens: Vec, pos: usize, - file_id: usize, + file_id: FileId, errors: Vec, interner: &'a mut NameInterner, arena: AstArena, @@ -26,7 +26,7 @@ pub struct Parser<'a> { } impl<'a> Parser<'a> { - pub fn new(source: &str, file_id: usize, interner: &'a mut NameInterner) -> Self { + pub fn new(source: &str, file_id: FileId, interner: &'a mut NameInterner) -> Self { let mut lexer = Lexer::new(source, file_id); let mut tokens = Vec::new(); loop { @@ -72,7 +72,7 @@ impl<'a> Parser<'a> { } pub fn parse_file(&mut self) -> Result { - let start_span = self.peek().span; + let start_span = self.peek().span.clone(); let mut imports = Vec::new(); let mut decls = Vec::new(); @@ -90,7 +90,7 @@ impl<'a> Parser<'a> { } } - let end_span = self.peek().span; + let end_span = self.peek().span.clone(); if !self.errors.is_empty() { return Err(DiagnosticBundle { @@ -152,7 +152,7 @@ impl<'a> Parser<'a> { fn parse_import_spec(&mut self) -> Result { let mut path = Vec::new(); - let start_span = self.peek().span; + let start_span = self.peek().span.clone(); if self.peek().kind == TokenKind::OpenBrace { self.advance(); // { @@ -190,7 +190,7 @@ impl<'a> Parser<'a> { } } - let end_span = self.tokens[self.pos - 1].span; + let end_span = self.tokens[self.pos - 1].span.clone(); let span = Span::new(self.file_id, start_span.start, end_span.end); Ok(self.arena.push(NodeKind::ImportSpec(ImportSpecNodeArena { path }), span)) } @@ -554,7 +554,7 @@ impl<'a> Parser<'a> { if let NodeKind::TypeApp(ta) = &mut self.arena.nodes[index] { if ta.base == self.builtin_array { ta.args.push(size_node); - self.arena.spans[index] = span; + self.arena.spans[index] = span.clone(); wrapped = false; } } @@ -1043,7 +1043,7 @@ impl<'a> Parser<'a> { severity: Severity::Error, code: code.unwrap_or("E_PARSE_ERROR").to_string(), message: message.to_string(), - span: self.peek().span, + span: self.peek().span.clone(), related: Vec::new(), }; self.errors.push(diag.clone()); @@ -1054,7 +1054,7 @@ impl<'a> Parser<'a> { self.consume(TokenKind::OpenBracket)?; let mut constructors = Vec::new(); while self.peek().kind != TokenKind::CloseBracket && self.peek().kind != TokenKind::Eof { - let start_span = self.peek().span; + let start_span = self.peek().span.clone(); let params = self.parse_param_list()?; self.consume(TokenKind::Colon)?; @@ -1097,11 +1097,12 @@ impl<'a> Parser<'a> { mod tests { use super::*; use serde_json; + use crate::common::spans::FileId; #[test] fn test_parse_empty_file() { let mut interner = NameInterner::new(); - let mut parser = Parser::new("", 0, &mut interner); + let mut parser = Parser::new("", FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1118,7 +1119,7 @@ import std.io from "std"; import math from "./math.pbs"; "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1147,7 +1148,7 @@ fn add(a: int, b: int): int { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1174,7 +1175,7 @@ pub declare struct Point { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1200,7 +1201,7 @@ pub service Audio { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1226,7 +1227,7 @@ fn main() { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1252,7 +1253,7 @@ fn main(x: int) { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1272,7 +1273,7 @@ fn bad() { fn good() {} "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let result = parser.parse_file(); assert!(result.is_err()); } @@ -1281,7 +1282,7 @@ fn good() {} fn test_parse_mod_fn() { let source = "mod fn test() {}"; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().expect("mod fn should be allowed"); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1298,7 +1299,7 @@ fn good() {} fn test_parse_pub_fn() { let source = "pub fn test() {}"; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().expect("pub fn should be allowed in parser"); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, @@ -1319,7 +1320,7 @@ fn main() { } "#; let mut interner = NameInterner::new(); - let mut parser = Parser::new(source, 0, &mut interner); + let mut parser = Parser::new(source, FileId(0), &mut interner); let parsed = parser.parse_file().unwrap(); let file = match parsed.arena.kind(parsed.root) { NodeKind::File(file) => file, diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs index 2cc20e14..126da997 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolve.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolve.rs @@ -48,7 +48,7 @@ pub fn build_def_index( kind, exported, module, - decl_span: span, + decl_span: span.clone(), }; let symbol_id = symbols.insert(symbol); @@ -125,7 +125,7 @@ fn walk_node( }; if let Some(symbol_id) = index.get(key) { - ref_index.record_ref(symbol_id, span); + ref_index.record_ref(symbol_id, span.clone()); node_to_symbol.bind_node(node_id, symbol_id); } else if let Some((import_arena, import_index)) = imports { if let Some((_, symbol_id)) = import_index.get_by_name_any_module(ident.name, Namespace::Value) { @@ -135,18 +135,18 @@ fn walk_node( severity: Severity::Error, code: "E_RESOLVE_VISIBILITY".to_string(), message: format!("Symbol is not exported from module {:?}", symbol.module), - span, + span: span.clone(), related: Vec::new(), }); } - ref_index.record_ref(symbol_id, span); + ref_index.record_ref(symbol_id, span.clone()); node_to_symbol.bind_node(node_id, symbol_id); } else { diagnostics.push(Diagnostic { severity: Severity::Error, code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(), message: "Undefined identifier".to_string(), - span, + span: span.clone(), related: Vec::new(), }); } @@ -155,7 +155,7 @@ fn walk_node( severity: Severity::Error, code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(), message: "Undefined identifier".to_string(), - span, + span: span.clone(), related: Vec::new(), }); } @@ -239,7 +239,7 @@ mod tests { AstArena, BlockNodeArena, CallNodeArena, ExprStmtNodeArena, FileNodeArena, FnDeclNodeArena, IdentNodeArena, TypeDeclNodeArena, }; - use crate::common::spans::Span; + use crate::common::spans::{Span, FileId}; #[test] fn test_build_def_index_success() { @@ -247,7 +247,7 @@ mod tests { let mut interner = NameInterner::new(); // Create a dummy body for the function to avoid panic/invalid access - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 0, 0)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 0, 0)); let fn_name = interner.intern("my_func"); let fn_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { @@ -257,7 +257,7 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 10, 20)); + }), Span::new(FileId(0), 10, 20)); let type_name = interner.intern("MyStruct"); let type_id = arena.push(NodeKind::TypeDecl(TypeDeclNodeArena { @@ -269,12 +269,12 @@ mod tests { constructors: vec![], constants: vec![], body: None, - }), Span::new(0, 30, 40)); + }), Span::new(FileId(0), 30, 40)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![fn_id, type_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); @@ -303,7 +303,7 @@ mod tests { let name = interner.intern("conflict"); - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 0, 0)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 0, 0)); let fn1_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, @@ -312,7 +312,7 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 10, 20)); + }), Span::new(FileId(0), 10, 20)); let fn2_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, @@ -321,12 +321,12 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 30, 40)); + }), Span::new(FileId(0), 30, 40)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![fn1_id, fn2_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); @@ -334,7 +334,7 @@ mod tests { assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_DUPLICATE_SYMBOL"); - assert_eq!(diagnostics[0].span, Span::new(0, 30, 40)); + assert_eq!(diagnostics[0].span, Span::new(FileId(0), 30, 40)); } #[test] @@ -343,7 +343,7 @@ mod tests { let mut interner = NameInterner::new(); let name = interner.intern("bound_func"); - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 0, 0)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 0, 0)); let decl_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, name, @@ -351,12 +351,12 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 10, 20)); + }), Span::new(FileId(0), 10, 20)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![decl_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); @@ -373,9 +373,9 @@ mod tests { let mut interner = NameInterner::new(); let ident_name = interner.intern("unknown"); - let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: ident_name }), Span::new(0, 50, 60)); - let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: ident_id }), Span::new(0, 50, 60)); - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(0, 40, 70)); + let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: ident_name }), Span::new(FileId(0), 50, 60)); + let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: ident_id }), Span::new(FileId(0), 50, 60)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(FileId(0), 40, 70)); let fn_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, @@ -384,12 +384,12 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 10, 80)); + }), Span::new(FileId(0), 10, 80)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![fn_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); @@ -397,7 +397,7 @@ mod tests { assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_UNDEFINED_IDENTIFIER"); - assert_eq!(diagnostics[0].span, Span::new(0, 50, 60)); + assert_eq!(diagnostics[0].span, Span::new(FileId(0), 50, 60)); } #[test] @@ -407,7 +407,7 @@ mod tests { // fn target() {} let target_name = interner.intern("target"); - let target_body = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 5, 5)); + let target_body = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 5, 5)); let target_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, name: target_name, @@ -415,13 +415,13 @@ mod tests { ret: None, else_fallback: None, body: target_body, - }), Span::new(0, 0, 10)); + }), Span::new(FileId(0), 0, 10)); // fn caller() { target(); } - let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 56)); - let call_id = arena.push(NodeKind::Call(CallNodeArena { callee: ident_id, args: vec![] }), Span::new(0, 50, 58)); - let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: call_id }), Span::new(0, 50, 58)); - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(0, 40, 70)); + let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(FileId(0), 50, 56)); + let call_id = arena.push(NodeKind::Call(CallNodeArena { callee: ident_id, args: vec![] }), Span::new(FileId(0), 50, 58)); + let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: call_id }), Span::new(FileId(0), 50, 58)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(FileId(0), 40, 70)); let caller_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, @@ -430,12 +430,12 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 30, 80)); + }), Span::new(FileId(0), 30, 80)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![target_id, caller_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); @@ -446,7 +446,7 @@ mod tests { 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)); + assert_eq!(refs[0], Span::new(FileId(0), 50, 56)); let bound_id = node_to_symbol.get(ident_id).expect("ident should be bound to symbol"); assert_eq!(bound_id, target_sym_id); @@ -459,7 +459,7 @@ mod tests { // Módulo 1: define função privada let mut arena1 = AstArena::default(); let target_name = interner.intern("private_func"); - let body1 = arena1.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 0, 0)); + let body1 = arena1.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 0, 0)); let decl1 = arena1.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, // Privado name: target_name, @@ -467,20 +467,20 @@ mod tests { ret: None, else_fallback: None, body: body1, - }), Span::new(0, 0, 10)); + }), Span::new(FileId(0), 0, 10)); let file1 = arena1.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![decl1], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena1.roots.push(file1); 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(); - let ident_id = arena2.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 62)); - let expr_stmt = arena2.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: ident_id }), Span::new(0, 50, 62)); - let body2 = arena2.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(0, 40, 70)); + let ident_id = arena2.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(FileId(0), 50, 62)); + let expr_stmt = arena2.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: ident_id }), Span::new(FileId(0), 50, 62)); + let body2 = arena2.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(FileId(0), 40, 70)); let caller = arena2.push(NodeKind::FnDecl(FnDeclNodeArena { vis: Some("pub".to_string()), name: interner.intern("caller"), @@ -488,11 +488,11 @@ mod tests { ret: None, else_fallback: None, body: body2, - }), Span::new(0, 30, 80)); + }), Span::new(FileId(0), 30, 80)); let file2 = arena2.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![caller], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena2.roots.push(file2); let (_symbols2, _index2, _ref_index2, _node_to_symbol2, diagnostics) = @@ -500,7 +500,7 @@ mod tests { assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics[0].code, "E_RESOLVE_VISIBILITY"); - assert_eq!(diagnostics[0].span, Span::new(0, 50, 62)); + assert_eq!(diagnostics[0].span, Span::new(FileId(0), 50, 62)); } #[test] @@ -509,7 +509,7 @@ mod tests { let mut interner = NameInterner::new(); let target_name = interner.intern("target"); - let target_body = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 5, 5)); + let target_body = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(FileId(0), 5, 5)); let target_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: Some("pub".to_string()), name: target_name, @@ -517,13 +517,13 @@ mod tests { ret: None, else_fallback: None, body: target_body, - }), Span::new(0, 0, 10)); + }), Span::new(FileId(0), 0, 10)); let caller_name = interner.intern("caller"); - let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 56)); - let call_id = arena.push(NodeKind::Call(CallNodeArena { callee: ident_id, args: vec![] }), Span::new(0, 50, 58)); - let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: call_id }), Span::new(0, 50, 58)); - let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(0, 40, 70)); + let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(FileId(0), 50, 56)); + let call_id = arena.push(NodeKind::Call(CallNodeArena { callee: ident_id, args: vec![] }), Span::new(FileId(0), 50, 58)); + let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: call_id }), Span::new(FileId(0), 50, 58)); + let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(FileId(0), 40, 70)); let caller_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { vis: None, @@ -532,12 +532,12 @@ mod tests { ret: None, else_fallback: None, body: body_id, - }), Span::new(0, 30, 80)); + }), Span::new(FileId(0), 30, 80)); let file_id = arena.push(NodeKind::File(FileNodeArena { imports: vec![], decls: vec![target_id, caller_id], - }), Span::new(0, 0, 100)); + }), Span::new(FileId(0), 0, 100)); arena.roots.push(file_id); diff --git a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs index 98b65ab7..02f2760e 100644 --- a/crates/prometeu-compiler/src/frontends/pbs/resolver.rs +++ b/crates/prometeu-compiler/src/frontends/pbs/resolver.rs @@ -81,7 +81,7 @@ impl<'a> Resolver<'a> { }, exported: sym.visibility == Visibility::Pub, module: ModuleId(0), - decl_span: sym.span, + decl_span: sym.span.clone(), }); } for (name, sym) in &self.current_module.value_symbols.symbols { @@ -97,7 +97,7 @@ impl<'a> Resolver<'a> { }, exported: sym.visibility == Visibility::Pub, module: ModuleId(0), - decl_span: sym.span, + decl_span: sym.span.clone(), }); } @@ -122,7 +122,7 @@ impl<'a> Resolver<'a> { }, exported: sym.visibility == Visibility::Pub, module: ModuleId(0), // Should be target module - decl_span: sym.span, + decl_span: sym.span.clone(), }); } for (name, sym) in &self.imported_symbols.value_symbols.symbols { @@ -138,7 +138,7 @@ impl<'a> Resolver<'a> { }, exported: sym.visibility == Visibility::Pub, module: ModuleId(0), // Should be target module - decl_span: sym.span, + decl_span: sym.span.clone(), }); } @@ -438,7 +438,7 @@ impl<'a> Resolver<'a> { self.enter_scope(); for param in &n.params { let ty_id = self.resolve_type_ref(arena, param.ty); - let sym_id = self.define_local(param.name, param.span, SymbolKind::Local); + 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 @@ -512,7 +512,7 @@ impl<'a> Resolver<'a> { self.enter_scope(); for param in &n.params { self.resolve_type_ref(arena, param.ty); - self.define_local(param.name, param.span, SymbolKind::Local); + self.define_local(param.name, param.span.clone(), SymbolKind::Local); } for init in &n.initializers { self.resolve_node(arena, *init); @@ -804,7 +804,7 @@ impl<'a> Resolver<'a> { self.interner.resolve(name) ), span, - related: vec![("type defined here".to_string(), existing.span)], + related: vec![("type defined here".to_string(), existing.span.clone())], }); return None; } @@ -815,7 +815,7 @@ impl<'a> Resolver<'a> { code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(), message: format!("Duplicate local variable '{}'", self.interner.resolve(name)), span, - related: vec![("previous definition here".to_string(), prev_sym.span)], + related: vec![("previous definition here".to_string(), prev_sym.span.clone())], }); None } else { @@ -826,7 +826,7 @@ impl<'a> Resolver<'a> { visibility: Visibility::FilePrivate, ty: None, // Will be set by TypeChecker is_host: false, - span, + span: span.clone(), origin: None, }; @@ -884,7 +884,7 @@ impl<'a> Resolver<'a> { self.interner.resolve(sym.name) ), span, - related: vec![("symbol defined here".to_string(), sym.span)], + related: vec![("symbol defined here".to_string(), sym.span.clone())], }); } } @@ -900,7 +900,7 @@ mod tests { fn setup_test(source: &str) -> (ParsedAst, usize, NameInterner) { let mut fm = FileManager::new(); let file_id = fm.add(PathBuf::from("test.pbs"), source.to_string()); - let mut parser = parser::Parser::new(source, file_id, fm.interner_mut()); + let mut parser = parser::Parser::new(source, crate::common::spans::FileId(file_id as u32), fm.interner_mut()); let parsed = parser.parse_file().expect("Parsing failed"); (parsed, file_id, fm.interner().clone()) } @@ -1018,7 +1018,7 @@ mod tests { visibility: Visibility::FilePrivate, ty: None, is_host: false, - span: Span::new(1, 0, 0), + span: Span::new(crate::common::spans::FileId(1), 0, 0), origin: None, }).unwrap(); @@ -1066,7 +1066,7 @@ mod tests { visibility: Visibility::Pub, ty: None, is_host: false, - span: Span::new(1, 0, 0), + span: Span::new(crate::common::spans::FileId(1), 0, 0), origin: None, }).unwrap(); diff --git a/crates/prometeu-compiler/src/lowering/core_to_vm.rs b/crates/prometeu-compiler/src/lowering/core_to_vm.rs index 450de4d3..a5b7e720 100644 --- a/crates/prometeu-compiler/src/lowering/core_to_vm.rs +++ b/crates/prometeu-compiler/src/lowering/core_to_vm.rs @@ -81,7 +81,7 @@ pub fn lower_function( let mut stack_types = Vec::new(); for instr in &block.instrs { - let span = instr.span; + let span = instr.span.clone(); match &instr.kind { ir_core::InstrKind::PushConst(id) => { let ty = if let Some(val) = program.const_pool.get(ir_core::ConstId(id.0)) { @@ -94,11 +94,11 @@ pub fn lower_function( ir_core::Type::Void }; stack_types.push(ty); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushConst(ir_vm::ConstId(id.0)), span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushConst(ir_vm::ConstId(id.0)), span.clone())); } ir_core::InstrKind::PushBounded(val) => { stack_types.push(ir_core::Type::Bounded); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushBounded(*val), span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::PushBounded(*val), span.clone())); } ir_core::InstrKind::Call(func_id, arg_count) => { // Pop arguments from type stack @@ -135,13 +135,13 @@ pub fn lower_function( for _ in 0..*slots { stack_types.push(ir_core::Type::Int); } - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Syscall(*id), span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Syscall(*id), span.clone())); } ir_core::InstrKind::GetLocal(slot) => { let ty = local_types.get(slot).cloned().unwrap_or(ir_core::Type::Void); stack_types.push(ty.clone()); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span.clone())); // If it's a gate, we should retain it if we just pushed it onto stack? // "on assigning a gate to a local/global" @@ -150,7 +150,7 @@ pub fn lower_function( // Wait, if I Load it, I have a new handle on the stack. I should Retain it. if is_gate_type(&ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); } } ir_core::InstrKind::SetLocal(slot) => { @@ -160,8 +160,8 @@ pub fn lower_function( // 1. Release old value if it was a gate if let Some(old_ty) = old_ty { if is_gate_type(&old_ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: *slot }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } } @@ -174,22 +174,22 @@ pub fn lower_function( // Actually, if we Pop it later, we Release it. local_types.insert(*slot, new_ty); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalStore { slot: *slot }, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalStore { slot: *slot }, span.clone())); } ir_core::InstrKind::Pop => { let ty = stack_types.pop().unwrap_or(ir_core::Type::Void); if is_gate_type(&ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } else { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Pop, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Pop, span.clone())); } } ir_core::InstrKind::Dup => { let ty = stack_types.last().cloned().unwrap_or(ir_core::Type::Void); stack_types.push(ty.clone()); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Dup, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Dup, span.clone())); if is_gate_type(&ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); } } ir_core::InstrKind::Add | ir_core::InstrKind::Sub | ir_core::InstrKind::Mul | ir_core::InstrKind::Div => { @@ -203,10 +203,10 @@ pub fn lower_function( ir_core::InstrKind::Div => ir_vm::InstrKind::Div, _ => unreachable!(), }; - vm_func.body.push(ir_vm::Instruction::new(kind, span)); + vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); } ir_core::InstrKind::Neg => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Neg, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Neg, span.clone())); } ir_core::InstrKind::Eq | ir_core::InstrKind::Neq | ir_core::InstrKind::Lt | ir_core::InstrKind::Lte | ir_core::InstrKind::Gt | ir_core::InstrKind::Gte => { stack_types.pop(); @@ -221,7 +221,7 @@ pub fn lower_function( ir_core::InstrKind::Gte => ir_vm::InstrKind::Gte, _ => unreachable!(), }; - vm_func.body.push(ir_vm::Instruction::new(kind, span)); + vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); } ir_core::InstrKind::And | ir_core::InstrKind::Or => { stack_types.pop(); @@ -232,12 +232,12 @@ pub fn lower_function( ir_core::InstrKind::Or => ir_vm::InstrKind::Or, _ => unreachable!(), }; - vm_func.body.push(ir_vm::Instruction::new(kind, span)); + vm_func.body.push(ir_vm::Instruction::new(kind, span.clone())); } ir_core::InstrKind::Not => { stack_types.pop(); stack_types.push(ir_core::Type::Bool); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Not, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::Not, span.clone())); } ir_core::InstrKind::Alloc { ty, slots } => { stack_types.push(ir_core::Type::Struct("".to_string())); // It's a gate @@ -247,31 +247,31 @@ pub fn lower_function( }, None)); } ir_core::InstrKind::BeginPeek { gate } => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginPeek, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginPeek, span.clone())); } ir_core::InstrKind::BeginBorrow { gate } => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginBorrow, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginBorrow, span.clone())); } ir_core::InstrKind::BeginMutate { gate } => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginMutate, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginMutate, span.clone())); } ir_core::InstrKind::EndPeek => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndPeek, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndPeek, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } ir_core::InstrKind::EndBorrow => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndBorrow, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndBorrow, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } ir_core::InstrKind::EndMutate => { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndMutate, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateEndMutate, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } ir_core::InstrKind::GateLoadField { gate, field } => { let offset = program.field_offsets.get(field) @@ -280,12 +280,12 @@ pub fn lower_function( let field_ty = program.field_types.get(field).cloned().unwrap_or(ir_core::Type::Int); stack_types.push(field_ty.clone()); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span.clone())); if is_gate_type(&field_ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); } } ir_core::InstrKind::GateStoreField { gate, field, value } => { @@ -296,24 +296,24 @@ pub fn lower_function( // 1. Release old value in HIP if it was a gate if is_gate_type(&field_ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRelease, span.clone())); } - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: value.0 }, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: gate.0 }, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::LocalLoad { slot: value.0 }, span.clone())); // 2. Retain new value if it's a gate if let Some(val_ty) = local_types.get(&value.0) { if is_gate_type(val_ty) { - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateRetain, span.clone())); } } - vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateStore { offset: *offset }, span)); + vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateStore { offset: *offset }, span.clone())); } ir_core::InstrKind::GateLoadIndex { .. } => { anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering"); diff --git a/crates/prometeu-compiler/src/sources.rs b/crates/prometeu-compiler/src/sources.rs index 8ad915e4..dc4f93c5 100644 --- a/crates/prometeu-compiler/src/sources.rs +++ b/crates/prometeu-compiler/src/sources.rs @@ -1,6 +1,7 @@ use crate::common::diagnostics::DiagnosticBundle; use crate::common::files::FileManager; use crate::frontends::pbs::{collector::SymbolCollector, parser::Parser, Symbol, Visibility}; +use crate::common::spans::FileId; use crate::manifest::{load_manifest, ManifestKind}; use prometeu_analysis::NameInterner; use serde::{Deserialize, Serialize}; @@ -131,7 +132,7 @@ pub fn build_exports(module_dir: &Path, file_manager: &mut FileManager) -> Resul let source = fs::read_to_string(&file_path)?; let file_id = file_manager.add(file_path.clone(), source.clone()); - let mut parser = Parser::new(&source, file_id, &mut interner); + let mut parser = Parser::new(&source, FileId(file_id as u32), &mut interner); let parsed = parser.parse_file()?; let mut collector = SymbolCollector::new(&interner); diff --git a/crates/prometeu-compiler/tests/diagnostics_span.rs b/crates/prometeu-compiler/tests/diagnostics_span.rs new file mode 100644 index 00000000..b6f5c14c --- /dev/null +++ b/crates/prometeu-compiler/tests/diagnostics_span.rs @@ -0,0 +1,26 @@ +use prometeu_analysis::{ids::FileId, span::Span}; +use prometeu_compiler::common::diagnostics::{Diagnostic, DiagnosticBundle, Severity}; + +#[test] +fn diagnostic_span_is_valid_for_file() { + // Fixture simples + let text = "let x = 10;"; // len = 11 + let file = FileId(1); + + // Cria um diagnóstico com span válido: end exclusivo e <= len + let span = Span::new(file, 0, text.len() as u32); + assert!(span.end >= span.start); + assert!(span.end <= text.len() as u32); + + let diag = Diagnostic { + severity: Severity::Error, + code: "E_TEST".to_string(), + message: "testing".to_string(), + span, + related: vec![], + }; + let bundle = DiagnosticBundle { diagnostics: vec![diag] }; + + // Serialize para garantir que o span passa pelo pipeline sem panics + let _json = serde_json::to_string(&bundle).expect("must serialize diagnostics"); +} diff --git a/crates/prometeu-compiler/tests/generate_canonical_goldens.rs b/crates/prometeu-compiler/tests/generate_canonical_goldens.rs index dd748617..9cf8caba 100644 --- a/crates/prometeu-compiler/tests/generate_canonical_goldens.rs +++ b/crates/prometeu-compiler/tests/generate_canonical_goldens.rs @@ -2,6 +2,7 @@ use prometeu_bytecode::disasm::disasm; use prometeu_bytecode::BytecodeLoader; use prometeu_compiler::compiler::compile; use prometeu_compiler::frontends::pbs::parser::Parser; +use prometeu_compiler::common::spans::FileId; use prometeu_analysis::NameInterner; use std::fs; use std::path::Path; @@ -57,7 +58,7 @@ fn generate_canonical_goldens() { // 3. AST JSON let source = fs::read_to_string(project_dir.join("src/main/modules/main.pbs")).unwrap(); let mut interner = NameInterner::new(); - let mut parser = Parser::new(&source, 0, &mut interner); + let mut parser = Parser::new(&source, FileId(0), &mut interner); let parsed = parser.parse_file().expect("Failed to parse AST"); let ast_json = serde_json::to_string_pretty(parsed.arena.kind(parsed.root)).unwrap(); fs::write(golden_dir.join("ast.json"), ast_json).unwrap(); diff --git a/test-cartridges/canonical/golden/program.pbc b/test-cartridges/canonical/golden/program.pbc index 666448e9..b06b91ca 100644 Binary files a/test-cartridges/canonical/golden/program.pbc and b/test-cartridges/canonical/golden/program.pbc differ