This commit is contained in:
bQUARKz 2026-02-05 14:56:03 +00:00
parent adb4dad14b
commit 07f986df5b
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
23 changed files with 286 additions and 237 deletions

View File

@ -6,3 +6,20 @@ pub struct Span {
pub start: u32, // byte offset pub start: u32, // byte offset
pub end: u32, // byte offset, exclusive 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
}
}

View File

@ -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));
}

View File

@ -1,5 +1,5 @@
use crate::common::diagnostics::{Diagnostic, Severity}; use crate::common::diagnostics::{Diagnostic, Severity};
use crate::common::spans::Span; use crate::common::spans::{Span, FileId};
use crate::frontends::pbs::ast::AstArena; use crate::frontends::pbs::ast::AstArena;
use prometeu_analysis::NodeId; use prometeu_analysis::NodeId;
use prometeu_analysis::{NameId, SymbolId, ModuleId}; use prometeu_analysis::{NameId, SymbolId, ModuleId};
@ -91,7 +91,7 @@ impl DefIndex {
code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(), code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(),
message: "Duplicate symbol in the same module and namespace".to_string(), message: "Duplicate symbol in the same module and namespace".to_string(),
// Placeholder span; callers should overwrite with accurate span when known. // 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(), related: Vec::new(),
}); });
} }
@ -177,7 +177,7 @@ mod tests {
kind: SymbolKind::Function, kind: SymbolKind::Function,
exported: false, exported: false,
module, module,
decl_span: Span::new(0, 1, 2), decl_span: Span::new(FileId(0), 1, 2),
} }
} }
@ -242,16 +242,16 @@ mod tests {
#[test] #[test]
fn ref_index_records_refs_per_symbol() { fn ref_index_records_refs_per_symbol() {
let mut index = RefIndex::new(); let mut index = RefIndex::new();
let span_a1 = Span::new(0, 1, 2); let span_a1 = Span::new(FileId(0), 1, 2);
let span_a2 = Span::new(0, 3, 4); let span_a2 = Span::new(FileId(0), 3, 4);
let span_b1 = Span::new(1, 10, 12); let span_b1 = Span::new(FileId(1), 10, 12);
index.record_ref(SymbolId(2), span_a1); index.record_ref(SymbolId(2), span_a1.clone());
index.record_ref(SymbolId(2), span_a2); index.record_ref(SymbolId(2), span_a2.clone());
index.record_ref(SymbolId(5), span_b1); 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(2)), &[span_a1.clone(), span_a2.clone()]);
assert_eq!(index.refs_of(SymbolId(5)), &[span_b1]); assert_eq!(index.refs_of(SymbolId(5)), &[span_b1.clone()]);
assert!(index.refs_of(SymbolId(9)).is_empty()); assert!(index.refs_of(SymbolId(9)).is_empty());
} }

View File

@ -1,5 +1,6 @@
use crate::analysis::symbols::{SymbolArena}; use crate::analysis::symbols::{SymbolArena};
use prometeu_analysis::{NameId, NameInterner, TypeId, SymbolId, NodeId, ModuleId}; use prometeu_analysis::{NameId, NameInterner, TypeId, SymbolId, NodeId, ModuleId};
use crate::common::spans::FileId;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// Use canonical TypeId from prometeu-analysis // Use canonical TypeId from prometeu-analysis
@ -211,7 +212,7 @@ mod tests {
kind: SymbolKind::Struct, kind: SymbolKind::Struct,
exported: false, exported: false,
module: ModuleId(0), 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 }); let struct_t = arena.intern_type(TypeKind::Struct { sym: sym_id });

View File

@ -95,7 +95,7 @@ pub fn emit_fragments(module: &ir_vm::Module) -> Result<EmitFragments> {
if let Some(instr) = instr_opt { if let Some(instr) = instr_opt {
if let Some(span) = &instr.span { if let Some(span) = &instr.span {
pc_to_span.push((current_pc, SourceSpan { pc_to_span.push((current_pc, SourceSpan {
file_id: span.file_id as u32, file_id: span.file.as_u32(),
start: span.start, start: span.start,
end: span.end, end: span.end,
})); }));

View File

@ -2,7 +2,7 @@ use crate::backend::emit_fragments;
use crate::building::plan::{BuildStep, BuildTarget}; use crate::building::plan::{BuildStep, BuildTarget};
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::common::spans::Span; use crate::common::spans::{FileId, Span};
use crate::deps::resolver::ProjectId; use crate::deps::resolver::ProjectId;
use crate::frontends::pbs::ast::ParsedAst; use crate::frontends::pbs::ast::ParsedAst;
use crate::frontends::pbs::collector::SymbolCollector; 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 source_code = std::fs::read_to_string(&source_abs)?;
let file_id = file_manager.add(source_abs.clone(), source_code.clone()); 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 parsed = parser.parse_file()?;
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -155,7 +155,7 @@ pub fn compile_project(
interner.resolve(existing.name), interner.resolve(existing.name),
module_path module_path
), ),
existing.span, existing.span.clone(),
).into()); ).into());
} }
let _ = ms.type_symbols.insert(sym); let _ = ms.type_symbols.insert(sym);
@ -169,7 +169,7 @@ pub fn compile_project(
interner.resolve(existing.name), interner.resolve(existing.name),
module_path module_path
), ),
existing.span, existing.span.clone(),
).into()); ).into());
} }
let _ = ms.value_symbols.insert(sym); let _ = ms.value_symbols.insert(sym);
@ -209,7 +209,7 @@ pub fn compile_project(
visibility: Visibility::Pub, visibility: Visibility::Pub,
ty: meta.ty.clone(), ty: meta.ty.clone(),
is_host: meta.is_host, is_host: meta.is_host,
span: Span::new(0, 0, 0), span: Span::new(FileId::INVALID, 0, 0),
origin: Some(synthetic_module_path.clone()), origin: Some(synthetic_module_path.clone()),
}; };

View File

@ -1,5 +1,5 @@
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::common::spans::Span; use crate::common::spans::{FileId, Span};
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -84,21 +84,26 @@ impl DiagnosticBundle {
let mut diags = self.diagnostics.clone(); let mut diags = self.diagnostics.clone();
diags.sort_by(|a, b| { 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<CanonicalDiag> = diags let canonical_diags: Vec<CanonicalDiag> = diags
.iter() .iter()
.map(|d| { .map(|d| {
let s = d.span; let s = &d.span;
let file = if s.file_id == usize::MAX { let file = if s.file == FileId::INVALID {
"<virtual>".to_string() "<virtual>".to_string()
} else { } else {
file_manager 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())) .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 { let canonical_span = CanonicalSpan {
file, file,
@ -110,13 +115,13 @@ impl DiagnosticBundle {
.related .related
.iter() .iter()
.map(|(msg, sp)| { .map(|(msg, sp)| {
let file = if sp.file_id == usize::MAX { let file = if sp.file == FileId::INVALID {
"<virtual>".to_string() "<virtual>".to_string()
} else { } else {
file_manager 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())) .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 { let rsp = CanonicalSpan {
file, file,

View File

@ -1,18 +1,3 @@
use serde::{Deserialize, Serialize}; // Canonical Span for the whole workspace
pub use prometeu_analysis::span::Span;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub use prometeu_analysis::ids::FileId;
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,
}
}
}

View File

@ -170,14 +170,14 @@ fn convert_symbol(
// Actually, we'll just mark it exported=false if it's a function. // Actually, we'll just mark it exported=false if it's a function.
} }
let span = sym.span; let span = sym.span.clone();
let file_path = file_manager.get_path(span.file_id) let file_path = file_manager.get_path(span.file.as_usize())
.map(|p| p.to_string_lossy().to_string()) .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 // Convert 1-based to 0-based
let (s_line, s_col) = file_manager.lookup_pos(span.file_id, span.start); 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_id, span.end); let (e_line, e_col) = file_manager.lookup_pos(span.file.as_usize(), span.end);
let decl_span = SpanRange { let decl_span = SpanRange {
file_uri: file_path, file_uri: file_path,

View File

@ -6,7 +6,7 @@
use crate::backend; use crate::backend;
use crate::common::config::ProjectConfig; use crate::common::config::ProjectConfig;
use crate::common::files::FileManager; 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 crate::common::symbols::{DebugSymbol, ProjectSymbols, RawSymbol, SymbolsFile};
use anyhow::Result; use anyhow::Result;
use prometeu_bytecode::BytecodeModule; use prometeu_bytecode::BytecodeModule;
@ -44,11 +44,11 @@ impl CompilationUnit {
pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> { pub fn export(&self, out: &Path, emit_disasm: bool, emit_symbols: bool) -> Result<()> {
let mut debug_symbols = Vec::new(); let mut debug_symbols = Vec::new();
for raw in &self.raw_symbols { 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()) .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 { debug_symbols.push(DebugSymbol {
pc: raw.pc, pc: raw.pc,
@ -116,11 +116,7 @@ pub fn compile_ext(project_dir: &Path, explain_deps: bool) -> Result<Compilation
for (pc, span) in &debug.pc_to_span { for (pc, span) in &debug.pc_to_span {
raw_symbols.push(RawSymbol { raw_symbols.push(RawSymbol {
pc: *pc, pc: *pc,
span: Span { span: Span::new(FileId(span.file_id), span.start, span.end),
file_id: span.file_id as usize,
start: span.start,
end: span.end,
},
}); });
} }
} }

View File

@ -30,7 +30,7 @@ impl AstArena {
} }
pub fn span(&self, id: NodeId) -> Span { pub fn span(&self, id: NodeId) -> Span {
self.spans[id.0 as usize] self.spans[id.0 as usize].clone()
} }
} }

View File

@ -66,7 +66,7 @@ impl<'a> SymbolCollector<'a> {
}; };
let span = arena.span(id); let span = arena.span(id);
self.check_export_eligibility(SymbolKind::Function, vis, span); self.check_export_eligibility(SymbolKind::Function, vis, &span);
let symbol = Symbol { let symbol = Symbol {
name: decl.name, name: decl.name,
@ -75,7 +75,7 @@ impl<'a> SymbolCollector<'a> {
visibility: vis, visibility: vis,
ty: None, // Will be resolved later ty: None, // Will be resolved later
is_host: false, is_host: false,
span, span: span.clone(),
origin: None, origin: None,
}; };
self.insert_value_symbol(symbol); self.insert_value_symbol(symbol);
@ -89,7 +89,7 @@ impl<'a> SymbolCollector<'a> {
let span = arena.span(id); let span = arena.span(id);
self.check_export_eligibility(SymbolKind::Service, vis, span); self.check_export_eligibility(SymbolKind::Service, vis, &span);
let symbol = Symbol { let symbol = Symbol {
name: decl.name, name: decl.name,
@ -98,7 +98,7 @@ impl<'a> SymbolCollector<'a> {
visibility: vis, visibility: vis,
ty: None, ty: None,
is_host: false, is_host: false,
span, span: span.clone(),
origin: None, origin: None,
}; };
self.insert_type_symbol(symbol); self.insert_type_symbol(symbol);
@ -119,7 +119,7 @@ impl<'a> SymbolCollector<'a> {
let span = arena.span(id); let span = arena.span(id);
self.check_export_eligibility(kind.clone(), vis, span); self.check_export_eligibility(kind.clone(), vis, &span);
let symbol = Symbol { let symbol = Symbol {
name: decl.name, name: decl.name,
@ -128,7 +128,7 @@ impl<'a> SymbolCollector<'a> {
visibility: vis, visibility: vis,
ty: None, ty: None,
is_host: decl.is_host, is_host: decl.is_host,
span, span: span.clone(),
origin: None, origin: None,
}; };
self.insert_type_symbol(symbol); self.insert_type_symbol(symbol);
@ -171,9 +171,9 @@ impl<'a> SymbolCollector<'a> {
message: format!( message: format!(
"Duplicate symbol '{}' already defined at {:?}", "Duplicate symbol '{}' already defined at {:?}",
self.interner.resolve(symbol.name), self.interner.resolve(symbol.name),
existing.span &existing.span
), ),
span: symbol.span, span: symbol.span.clone(),
related: Vec::new(), related: Vec::new(),
}); });
} }
@ -186,20 +186,20 @@ impl<'a> SymbolCollector<'a> {
"DebugSymbol '{}' collides with another symbol in the {:?} namespace defined at {:?}", "DebugSymbol '{}' collides with another symbol in the {:?} namespace defined at {:?}",
self.interner.resolve(symbol.name), self.interner.resolve(symbol.name),
existing.namespace, existing.namespace,
existing.span &existing.span
), ),
span: symbol.span, span: symbol.span.clone(),
related: Vec::new(), 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) { if let Err(msg) = ExportSurfaceKind::validate_visibility(kind, vis) {
self.diagnostics.push(Diagnostic { self.diagnostics.push(Diagnostic {
severity: Severity::Error, severity: Severity::Error,
code: "E_SEMANTIC_EXPORT_RESTRICTION".to_string(), code: "E_SEMANTIC_EXPORT_RESTRICTION".to_string(),
message: msg, message: msg,
span, span: span.clone(),
related: Vec::new(), related: Vec::new(),
}); });
} }

View File

@ -1,16 +1,16 @@
use super::token::{Token, TokenKind}; use super::token::{Token, TokenKind};
use crate::common::spans::Span; use crate::common::spans::{FileId, Span};
use std::iter::Peekable; use std::iter::Peekable;
use std::str::Chars; use std::str::Chars;
pub struct Lexer<'a> { pub struct Lexer<'a> {
chars: Peekable<Chars<'a>>, chars: Peekable<Chars<'a>>,
file_id: usize, file_id: FileId,
pos: u32, pos: u32,
} }
impl<'a> Lexer<'a> { 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 { Self {
chars: source.chars().peekable(), chars: source.chars().peekable(),
file_id, file_id,
@ -289,7 +289,7 @@ mod tests {
#[test] #[test]
fn test_lex_basic_tokens() { fn test_lex_basic_tokens() {
let source = "( ) { } [ ] , . : ; -> = == + - * / % ! != < > <= >= && ||"; let source = "( ) { } [ ] , . : ; -> = == + - * / % ! != < > <= >= && ||";
let mut lexer = Lexer::new(source, 0); let mut lexer = Lexer::new(source, FileId(0));
let expected = vec![ let expected = vec![
TokenKind::OpenParen, TokenKind::CloseParen, TokenKind::OpenParen, TokenKind::CloseParen,
@ -313,7 +313,7 @@ mod tests {
#[test] #[test]
fn test_lex_keywords() { 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 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![ let expected = vec![
TokenKind::Import, TokenKind::Pub, TokenKind::Mod, TokenKind::Service, TokenKind::Import, TokenKind::Pub, TokenKind::Mod, TokenKind::Service,
@ -336,7 +336,7 @@ mod tests {
#[test] #[test]
fn test_lex_identifiers() { fn test_lex_identifiers() {
let source = "foo bar _baz qux123"; let source = "foo bar _baz qux123";
let mut lexer = Lexer::new(source, 0); let mut lexer = Lexer::new(source, FileId(0));
let expected = vec![ let expected = vec![
TokenKind::Identifier("foo".to_string()), TokenKind::Identifier("foo".to_string()),
@ -355,7 +355,7 @@ mod tests {
#[test] #[test]
fn test_lex_literals() { fn test_lex_literals() {
let source = "123 3.14 255b \"hello world\""; 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![ let expected = vec![
TokenKind::IntLit(123), TokenKind::IntLit(123),
@ -374,7 +374,7 @@ mod tests {
#[test] #[test]
fn test_lex_comments() { fn test_lex_comments() {
let source = "let x = 10; // this is a comment\nlet y = 20;"; 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![ let expected = vec![
TokenKind::Let, TokenKind::Let,
@ -399,7 +399,7 @@ mod tests {
#[test] #[test]
fn test_lex_spans() { fn test_lex_spans() {
let source = "let x = 10;"; 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 let t1 = lexer.next_token(); // let
assert_eq!(t1.span.start, 0); assert_eq!(t1.span.start, 0);
@ -425,7 +425,7 @@ mod tests {
#[test] #[test]
fn test_lex_invalid_tokens() { fn test_lex_invalid_tokens() {
let source = "@ #"; 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(_)));
assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_))); assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_)));
@ -435,7 +435,7 @@ mod tests {
#[test] #[test]
fn test_lex_unterminated_string() { fn test_lex_unterminated_string() {
let source = "\"hello"; 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(_))); assert!(matches!(lexer.next_token().kind, TokenKind::Invalid(_)));
} }

View File

@ -297,7 +297,7 @@ impl<'a> Lowerer<'a> {
} }
fn lower_node(&mut self, node: NodeId) -> Result<(), ()> { 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)); self.current_span = Some(self.arena.span(node));
let res = match self.arena.kind(node) { let res = match self.arena.kind(node) {
@ -1243,7 +1243,7 @@ impl<'a> Lowerer<'a> {
fn emit(&mut self, kind: InstrKind) { fn emit(&mut self, kind: InstrKind) {
if let Some(block) = &mut self.current_block { 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::frontends::pbs::symbols::ModuleSymbols;
use crate::ir_core; use crate::ir_core;
use prometeu_analysis::NameInterner; use prometeu_analysis::NameInterner;
use crate::common::spans::FileId;
fn lower_program(code: &str) -> ir_core::Program { fn lower_program(code: &str) -> ir_core::Program {
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1461,7 +1462,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1695,7 +1696,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1727,7 +1728,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1772,7 +1773,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1810,7 +1811,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1841,7 +1842,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1869,7 +1870,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1896,7 +1897,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1923,7 +1924,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1959,7 +1960,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -1995,7 +1996,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -2031,7 +2032,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -2058,7 +2059,7 @@ mod tests {
} }
"; ";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse");
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);

View File

@ -25,6 +25,7 @@ use crate::frontends::Frontend;
use crate::ir_vm; use crate::ir_vm;
use crate::lowering::core_to_vm; use crate::lowering::core_to_vm;
use prometeu_analysis::NameInterner; use prometeu_analysis::NameInterner;
use crate::common::spans::FileId;
use std::path::Path; use std::path::Path;
pub struct PbsFrontend; pub struct PbsFrontend;
@ -43,13 +44,13 @@ impl Frontend for PbsFrontend {
crate::common::diagnostics::DiagnosticBundle::error( crate::common::diagnostics::DiagnosticBundle::error(
"E_FRONTEND_IO", "E_FRONTEND_IO",
format!("Failed to read file: {}", e), 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 file_id = file_manager.add(entry.to_path_buf(), source.clone());
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file()?;
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);
@ -88,7 +89,7 @@ impl Frontend for PbsFrontend {
crate::common::diagnostics::DiagnosticBundle::error( crate::common::diagnostics::DiagnosticBundle::error(
"E_CORE_INVARIANT", "E_CORE_INVARIANT",
format!("Core IR Invariant Violation: {}", e), 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( crate::common::diagnostics::DiagnosticBundle::error(
"E_LOWERING", "E_LOWERING",
format!("Lowering error: {}", e), format!("Lowering error: {}", e),
crate::common::spans::Span::new(usize::MAX, 0, 0), crate::common::spans::Span::new(FileId::INVALID, 0, 0),
) )
}) })
} }

View File

@ -1,5 +1,5 @@
use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, Severity}; 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::ast::*;
use crate::frontends::pbs::lexer::Lexer; use crate::frontends::pbs::lexer::Lexer;
use crate::frontends::pbs::token::{Token, TokenKind}; use crate::frontends::pbs::token::{Token, TokenKind};
@ -8,7 +8,7 @@ use prometeu_analysis::{NameId, NameInterner, NodeId};
pub struct Parser<'a> { pub struct Parser<'a> {
tokens: Vec<Token>, tokens: Vec<Token>,
pos: usize, pos: usize,
file_id: usize, file_id: FileId,
errors: Vec<Diagnostic>, errors: Vec<Diagnostic>,
interner: &'a mut NameInterner, interner: &'a mut NameInterner,
arena: AstArena, arena: AstArena,
@ -26,7 +26,7 @@ pub struct Parser<'a> {
} }
impl<'a> 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 lexer = Lexer::new(source, file_id);
let mut tokens = Vec::new(); let mut tokens = Vec::new();
loop { loop {
@ -72,7 +72,7 @@ impl<'a> Parser<'a> {
} }
pub fn parse_file(&mut self) -> Result<ParsedAst, DiagnosticBundle> { pub fn parse_file(&mut self) -> Result<ParsedAst, DiagnosticBundle> {
let start_span = self.peek().span; let start_span = self.peek().span.clone();
let mut imports = Vec::new(); let mut imports = Vec::new();
let mut decls = 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() { if !self.errors.is_empty() {
return Err(DiagnosticBundle { return Err(DiagnosticBundle {
@ -152,7 +152,7 @@ impl<'a> Parser<'a> {
fn parse_import_spec(&mut self) -> Result<NodeId, DiagnosticBundle> { fn parse_import_spec(&mut self) -> Result<NodeId, DiagnosticBundle> {
let mut path = Vec::new(); let mut path = Vec::new();
let start_span = self.peek().span; let start_span = self.peek().span.clone();
if self.peek().kind == TokenKind::OpenBrace { if self.peek().kind == TokenKind::OpenBrace {
self.advance(); // { 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); let span = Span::new(self.file_id, start_span.start, end_span.end);
Ok(self.arena.push(NodeKind::ImportSpec(ImportSpecNodeArena { path }), span)) 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 let NodeKind::TypeApp(ta) = &mut self.arena.nodes[index] {
if ta.base == self.builtin_array { if ta.base == self.builtin_array {
ta.args.push(size_node); ta.args.push(size_node);
self.arena.spans[index] = span; self.arena.spans[index] = span.clone();
wrapped = false; wrapped = false;
} }
} }
@ -1043,7 +1043,7 @@ impl<'a> Parser<'a> {
severity: Severity::Error, severity: Severity::Error,
code: code.unwrap_or("E_PARSE_ERROR").to_string(), code: code.unwrap_or("E_PARSE_ERROR").to_string(),
message: message.to_string(), message: message.to_string(),
span: self.peek().span, span: self.peek().span.clone(),
related: Vec::new(), related: Vec::new(),
}; };
self.errors.push(diag.clone()); self.errors.push(diag.clone());
@ -1054,7 +1054,7 @@ impl<'a> Parser<'a> {
self.consume(TokenKind::OpenBracket)?; self.consume(TokenKind::OpenBracket)?;
let mut constructors = Vec::new(); let mut constructors = Vec::new();
while self.peek().kind != TokenKind::CloseBracket && self.peek().kind != TokenKind::Eof { 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()?; let params = self.parse_param_list()?;
self.consume(TokenKind::Colon)?; self.consume(TokenKind::Colon)?;
@ -1097,11 +1097,12 @@ impl<'a> Parser<'a> {
mod tests { mod tests {
use super::*; use super::*;
use serde_json; use serde_json;
use crate::common::spans::FileId;
#[test] #[test]
fn test_parse_empty_file() { fn test_parse_empty_file() {
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1118,7 +1119,7 @@ import std.io from "std";
import math from "./math.pbs"; import math from "./math.pbs";
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1147,7 +1148,7 @@ fn add(a: int, b: int): int {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1174,7 +1175,7 @@ pub declare struct Point {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1200,7 +1201,7 @@ pub service Audio {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1226,7 +1227,7 @@ fn main() {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1252,7 +1253,7 @@ fn main(x: int) {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1272,7 +1273,7 @@ fn bad() {
fn good() {} fn good() {}
"#; "#;
let mut interner = NameInterner::new(); 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(); let result = parser.parse_file();
assert!(result.is_err()); assert!(result.is_err());
} }
@ -1281,7 +1282,7 @@ fn good() {}
fn test_parse_mod_fn() { fn test_parse_mod_fn() {
let source = "mod fn test() {}"; let source = "mod fn test() {}";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("mod fn should be allowed");
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1298,7 +1299,7 @@ fn good() {}
fn test_parse_pub_fn() { fn test_parse_pub_fn() {
let source = "pub fn test() {}"; let source = "pub fn test() {}";
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("pub fn should be allowed in parser");
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,
@ -1319,7 +1320,7 @@ fn main() {
} }
"#; "#;
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().unwrap();
let file = match parsed.arena.kind(parsed.root) { let file = match parsed.arena.kind(parsed.root) {
NodeKind::File(file) => file, NodeKind::File(file) => file,

View File

@ -48,7 +48,7 @@ pub fn build_def_index(
kind, kind,
exported, exported,
module, module,
decl_span: span, decl_span: span.clone(),
}; };
let symbol_id = symbols.insert(symbol); let symbol_id = symbols.insert(symbol);
@ -125,7 +125,7 @@ fn walk_node(
}; };
if let Some(symbol_id) = index.get(key) { 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); node_to_symbol.bind_node(node_id, symbol_id);
} else if let Some((import_arena, import_index)) = imports { } 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) { 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, severity: Severity::Error,
code: "E_RESOLVE_VISIBILITY".to_string(), 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, span: span.clone(),
related: Vec::new(), 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); node_to_symbol.bind_node(node_id, symbol_id);
} else { } else {
diagnostics.push(Diagnostic { diagnostics.push(Diagnostic {
severity: Severity::Error, severity: Severity::Error,
code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(), code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(),
message: "Undefined identifier".to_string(), message: "Undefined identifier".to_string(),
span, span: span.clone(),
related: Vec::new(), related: Vec::new(),
}); });
} }
@ -155,7 +155,7 @@ fn walk_node(
severity: Severity::Error, severity: Severity::Error,
code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(), code: "E_RESOLVE_UNDEFINED_IDENTIFIER".to_string(),
message: "Undefined identifier".to_string(), message: "Undefined identifier".to_string(),
span, span: span.clone(),
related: Vec::new(), related: Vec::new(),
}); });
} }
@ -239,7 +239,7 @@ mod tests {
AstArena, BlockNodeArena, CallNodeArena, ExprStmtNodeArena, FileNodeArena, FnDeclNodeArena, AstArena, BlockNodeArena, CallNodeArena, ExprStmtNodeArena, FileNodeArena, FnDeclNodeArena,
IdentNodeArena, TypeDeclNodeArena, IdentNodeArena, TypeDeclNodeArena,
}; };
use crate::common::spans::Span; use crate::common::spans::{Span, FileId};
#[test] #[test]
fn test_build_def_index_success() { fn test_build_def_index_success() {
@ -247,7 +247,7 @@ mod tests {
let mut interner = NameInterner::new(); let mut interner = NameInterner::new();
// Create a dummy body for the function to avoid panic/invalid access // 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_name = interner.intern("my_func");
let fn_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { let fn_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
@ -257,7 +257,7 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 10, 20)); }), Span::new(FileId(0), 10, 20));
let type_name = interner.intern("MyStruct"); let type_name = interner.intern("MyStruct");
let type_id = arena.push(NodeKind::TypeDecl(TypeDeclNodeArena { let type_id = arena.push(NodeKind::TypeDecl(TypeDeclNodeArena {
@ -269,12 +269,12 @@ mod tests {
constructors: vec![], constructors: vec![],
constants: vec![], constants: vec![],
body: None, body: None,
}), Span::new(0, 30, 40)); }), Span::new(FileId(0), 30, 40));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![fn_id, type_id], decls: vec![fn_id, type_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); arena.roots.push(file_id);
@ -303,7 +303,7 @@ mod tests {
let name = interner.intern("conflict"); 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 { let fn1_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
@ -312,7 +312,7 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 10, 20)); }), Span::new(FileId(0), 10, 20));
let fn2_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena { let fn2_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
@ -321,12 +321,12 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 30, 40)); }), Span::new(FileId(0), 30, 40));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![fn1_id, fn2_id], decls: vec![fn1_id, fn2_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); arena.roots.push(file_id);
@ -334,7 +334,7 @@ mod tests {
assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics.len(), 1);
assert_eq!(diagnostics[0].code, "E_RESOLVE_DUPLICATE_SYMBOL"); 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] #[test]
@ -343,7 +343,7 @@ mod tests {
let mut interner = NameInterner::new(); let mut interner = NameInterner::new();
let name = interner.intern("bound_func"); 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 { let decl_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
name, name,
@ -351,12 +351,12 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 10, 20)); }), Span::new(FileId(0), 10, 20));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![decl_id], decls: vec![decl_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); arena.roots.push(file_id);
@ -373,9 +373,9 @@ mod tests {
let mut interner = NameInterner::new(); let mut interner = NameInterner::new();
let ident_name = interner.intern("unknown"); let ident_name = interner.intern("unknown");
let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: ident_name }), Span::new(0, 50, 60)); 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(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(0, 40, 70)); 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 { let fn_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
@ -384,12 +384,12 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 10, 80)); }), Span::new(FileId(0), 10, 80));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![fn_id], decls: vec![fn_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); arena.roots.push(file_id);
@ -397,7 +397,7 @@ mod tests {
assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics.len(), 1);
assert_eq!(diagnostics[0].code, "E_RESOLVE_UNDEFINED_IDENTIFIER"); 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] #[test]
@ -407,7 +407,7 @@ mod tests {
// fn target() {} // fn target() {}
let target_name = interner.intern("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 { let target_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
name: target_name, name: target_name,
@ -415,13 +415,13 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: target_body, body: target_body,
}), Span::new(0, 0, 10)); }), Span::new(FileId(0), 0, 10));
// fn caller() { target(); } // fn caller() { target(); }
let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 56)); 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(0, 50, 58)); 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(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(0, 40, 70)); 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 { let caller_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
@ -430,12 +430,12 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 30, 80)); }), Span::new(FileId(0), 30, 80));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![target_id, caller_id], decls: vec![target_id, caller_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); 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 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); let refs = ref_index.refs_of(target_sym_id);
assert_eq!(refs.len(), 1); 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"); let bound_id = node_to_symbol.get(ident_id).expect("ident should be bound to symbol");
assert_eq!(bound_id, target_sym_id); assert_eq!(bound_id, target_sym_id);
@ -459,7 +459,7 @@ mod tests {
// Módulo 1: define função privada // Módulo 1: define função privada
let mut arena1 = AstArena::default(); let mut arena1 = AstArena::default();
let target_name = interner.intern("private_func"); 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 { let decl1 = arena1.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, // Privado vis: None, // Privado
name: target_name, name: target_name,
@ -467,20 +467,20 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body1, body: body1,
}), Span::new(0, 0, 10)); }), Span::new(FileId(0), 0, 10));
let file1 = arena1.push(NodeKind::File(FileNodeArena { let file1 = arena1.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![decl1], decls: vec![decl1],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena1.roots.push(file1); arena1.roots.push(file1);
let (symbols1, index1, _, _, _) = build_def_index(&arena1, ModuleId(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 // Módulo 2: tenta usar função privada do Módulo 1
let mut arena2 = AstArena::default(); let mut arena2 = AstArena::default();
let ident_id = arena2.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 62)); 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(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(0, 40, 70)); 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 { let caller = arena2.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: Some("pub".to_string()), vis: Some("pub".to_string()),
name: interner.intern("caller"), name: interner.intern("caller"),
@ -488,11 +488,11 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body2, body: body2,
}), Span::new(0, 30, 80)); }), Span::new(FileId(0), 30, 80));
let file2 = arena2.push(NodeKind::File(FileNodeArena { let file2 = arena2.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![caller], decls: vec![caller],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena2.roots.push(file2); arena2.roots.push(file2);
let (_symbols2, _index2, _ref_index2, _node_to_symbol2, diagnostics) = let (_symbols2, _index2, _ref_index2, _node_to_symbol2, diagnostics) =
@ -500,7 +500,7 @@ mod tests {
assert_eq!(diagnostics.len(), 1); assert_eq!(diagnostics.len(), 1);
assert_eq!(diagnostics[0].code, "E_RESOLVE_VISIBILITY"); 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] #[test]
@ -509,7 +509,7 @@ mod tests {
let mut interner = NameInterner::new(); let mut interner = NameInterner::new();
let target_name = interner.intern("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 { let target_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: Some("pub".to_string()), vis: Some("pub".to_string()),
name: target_name, name: target_name,
@ -517,13 +517,13 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: target_body, body: target_body,
}), Span::new(0, 0, 10)); }), Span::new(FileId(0), 0, 10));
let caller_name = interner.intern("caller"); let caller_name = interner.intern("caller");
let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 56)); 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(0, 50, 58)); 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(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(0, 40, 70)); 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 { let caller_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None, vis: None,
@ -532,12 +532,12 @@ mod tests {
ret: None, ret: None,
else_fallback: None, else_fallback: None,
body: body_id, body: body_id,
}), Span::new(0, 30, 80)); }), Span::new(FileId(0), 30, 80));
let file_id = arena.push(NodeKind::File(FileNodeArena { let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![], imports: vec![],
decls: vec![target_id, caller_id], decls: vec![target_id, caller_id],
}), Span::new(0, 0, 100)); }), Span::new(FileId(0), 0, 100));
arena.roots.push(file_id); arena.roots.push(file_id);

View File

@ -81,7 +81,7 @@ impl<'a> Resolver<'a> {
}, },
exported: sym.visibility == Visibility::Pub, exported: sym.visibility == Visibility::Pub,
module: ModuleId(0), module: ModuleId(0),
decl_span: sym.span, decl_span: sym.span.clone(),
}); });
} }
for (name, sym) in &self.current_module.value_symbols.symbols { for (name, sym) in &self.current_module.value_symbols.symbols {
@ -97,7 +97,7 @@ impl<'a> Resolver<'a> {
}, },
exported: sym.visibility == Visibility::Pub, exported: sym.visibility == Visibility::Pub,
module: ModuleId(0), 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, exported: sym.visibility == Visibility::Pub,
module: ModuleId(0), // Should be target module 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 { for (name, sym) in &self.imported_symbols.value_symbols.symbols {
@ -138,7 +138,7 @@ impl<'a> Resolver<'a> {
}, },
exported: sym.visibility == Visibility::Pub, exported: sym.visibility == Visibility::Pub,
module: ModuleId(0), // Should be target module 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(); self.enter_scope();
for param in &n.params { for param in &n.params {
let ty_id = self.resolve_type_ref(arena, param.ty); 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) { if let (Some(tid), Some(sid)) = (ty_id, sym_id) {
self.type_facts.set_symbol_type(sid, tid); self.type_facts.set_symbol_type(sid, tid);
// O node do Ident do parâmetro na declaração também pode ser vinculado // 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(); self.enter_scope();
for param in &n.params { for param in &n.params {
self.resolve_type_ref(arena, param.ty); 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 { for init in &n.initializers {
self.resolve_node(arena, *init); self.resolve_node(arena, *init);
@ -804,7 +804,7 @@ impl<'a> Resolver<'a> {
self.interner.resolve(name) self.interner.resolve(name)
), ),
span, span,
related: vec![("type defined here".to_string(), existing.span)], related: vec![("type defined here".to_string(), existing.span.clone())],
}); });
return None; return None;
} }
@ -815,7 +815,7 @@ impl<'a> Resolver<'a> {
code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(), code: "E_RESOLVE_DUPLICATE_SYMBOL".to_string(),
message: format!("Duplicate local variable '{}'", self.interner.resolve(name)), message: format!("Duplicate local variable '{}'", self.interner.resolve(name)),
span, span,
related: vec![("previous definition here".to_string(), prev_sym.span)], related: vec![("previous definition here".to_string(), prev_sym.span.clone())],
}); });
None None
} else { } else {
@ -826,7 +826,7 @@ impl<'a> Resolver<'a> {
visibility: Visibility::FilePrivate, visibility: Visibility::FilePrivate,
ty: None, // Will be set by TypeChecker ty: None, // Will be set by TypeChecker
is_host: false, is_host: false,
span, span: span.clone(),
origin: None, origin: None,
}; };
@ -884,7 +884,7 @@ impl<'a> Resolver<'a> {
self.interner.resolve(sym.name) self.interner.resolve(sym.name)
), ),
span, 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) { fn setup_test(source: &str) -> (ParsedAst, usize, NameInterner) {
let mut fm = FileManager::new(); let mut fm = FileManager::new();
let file_id = fm.add(PathBuf::from("test.pbs"), source.to_string()); 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"); let parsed = parser.parse_file().expect("Parsing failed");
(parsed, file_id, fm.interner().clone()) (parsed, file_id, fm.interner().clone())
} }
@ -1018,7 +1018,7 @@ mod tests {
visibility: Visibility::FilePrivate, visibility: Visibility::FilePrivate,
ty: None, ty: None,
is_host: false, is_host: false,
span: Span::new(1, 0, 0), span: Span::new(crate::common::spans::FileId(1), 0, 0),
origin: None, origin: None,
}).unwrap(); }).unwrap();
@ -1066,7 +1066,7 @@ mod tests {
visibility: Visibility::Pub, visibility: Visibility::Pub,
ty: None, ty: None,
is_host: false, is_host: false,
span: Span::new(1, 0, 0), span: Span::new(crate::common::spans::FileId(1), 0, 0),
origin: None, origin: None,
}).unwrap(); }).unwrap();

View File

@ -81,7 +81,7 @@ pub fn lower_function(
let mut stack_types = Vec::new(); let mut stack_types = Vec::new();
for instr in &block.instrs { for instr in &block.instrs {
let span = instr.span; let span = instr.span.clone();
match &instr.kind { match &instr.kind {
ir_core::InstrKind::PushConst(id) => { ir_core::InstrKind::PushConst(id) => {
let ty = if let Some(val) = program.const_pool.get(ir_core::ConstId(id.0)) { 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 ir_core::Type::Void
}; };
stack_types.push(ty); 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) => { ir_core::InstrKind::PushBounded(val) => {
stack_types.push(ir_core::Type::Bounded); 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) => { ir_core::InstrKind::Call(func_id, arg_count) => {
// Pop arguments from type stack // Pop arguments from type stack
@ -135,13 +135,13 @@ pub fn lower_function(
for _ in 0..*slots { for _ in 0..*slots {
stack_types.push(ir_core::Type::Int); 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) => { ir_core::InstrKind::GetLocal(slot) => {
let ty = local_types.get(slot).cloned().unwrap_or(ir_core::Type::Void); let ty = local_types.get(slot).cloned().unwrap_or(ir_core::Type::Void);
stack_types.push(ty.clone()); 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? // If it's a gate, we should retain it if we just pushed it onto stack?
// "on assigning a gate to a local/global" // "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. // Wait, if I Load it, I have a new handle on the stack. I should Retain it.
if is_gate_type(&ty) { 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) => { ir_core::InstrKind::SetLocal(slot) => {
@ -160,8 +160,8 @@ pub fn lower_function(
// 1. Release old value if it was a gate // 1. Release old value if it was a gate
if let Some(old_ty) = old_ty { if let Some(old_ty) = old_ty {
if is_gate_type(&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::LocalLoad { slot: *slot }, span.clone()));
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()));
} }
} }
@ -174,22 +174,22 @@ pub fn lower_function(
// Actually, if we Pop it later, we Release it. // Actually, if we Pop it later, we Release it.
local_types.insert(*slot, new_ty); 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 => { ir_core::InstrKind::Pop => {
let ty = stack_types.pop().unwrap_or(ir_core::Type::Void); let ty = stack_types.pop().unwrap_or(ir_core::Type::Void);
if is_gate_type(&ty) { 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 { } 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 => { ir_core::InstrKind::Dup => {
let ty = stack_types.last().cloned().unwrap_or(ir_core::Type::Void); let ty = stack_types.last().cloned().unwrap_or(ir_core::Type::Void);
stack_types.push(ty.clone()); 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) { 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 => { 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, ir_core::InstrKind::Div => ir_vm::InstrKind::Div,
_ => unreachable!(), _ => 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 => { 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 => { 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(); stack_types.pop();
@ -221,7 +221,7 @@ pub fn lower_function(
ir_core::InstrKind::Gte => ir_vm::InstrKind::Gte, ir_core::InstrKind::Gte => ir_vm::InstrKind::Gte,
_ => unreachable!(), _ => 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 => { ir_core::InstrKind::And | ir_core::InstrKind::Or => {
stack_types.pop(); stack_types.pop();
@ -232,12 +232,12 @@ pub fn lower_function(
ir_core::InstrKind::Or => ir_vm::InstrKind::Or, ir_core::InstrKind::Or => ir_vm::InstrKind::Or,
_ => unreachable!(), _ => 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 => { ir_core::InstrKind::Not => {
stack_types.pop(); stack_types.pop();
stack_types.push(ir_core::Type::Bool); 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 } => { ir_core::InstrKind::Alloc { ty, slots } => {
stack_types.push(ir_core::Type::Struct("".to_string())); // It's a gate stack_types.push(ir_core::Type::Struct("".to_string())); // It's a gate
@ -247,31 +247,31 @@ pub fn lower_function(
}, None)); }, None));
} }
ir_core::InstrKind::BeginPeek { gate } => { 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::LocalLoad { slot: gate.0 }, span.clone()));
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::GateBeginPeek, span)); vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginPeek, span.clone()));
} }
ir_core::InstrKind::BeginBorrow { gate } => { 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::LocalLoad { slot: gate.0 }, span.clone()));
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::GateBeginBorrow, span)); vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginBorrow, span.clone()));
} }
ir_core::InstrKind::BeginMutate { gate } => { 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::LocalLoad { slot: gate.0 }, span.clone()));
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::GateBeginMutate, span)); vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateBeginMutate, span.clone()));
} }
ir_core::InstrKind::EndPeek => { 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::GateEndPeek, span.clone()));
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()));
} }
ir_core::InstrKind::EndBorrow => { 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::GateEndBorrow, span.clone()));
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()));
} }
ir_core::InstrKind::EndMutate => { 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::GateEndMutate, span.clone()));
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()));
} }
ir_core::InstrKind::GateLoadField { gate, field } => { ir_core::InstrKind::GateLoadField { gate, field } => {
let offset = program.field_offsets.get(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); let field_ty = program.field_types.get(field).cloned().unwrap_or(ir_core::Type::Int);
stack_types.push(field_ty.clone()); 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::LocalLoad { slot: gate.0 }, span.clone()));
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::GateLoad { offset: *offset }, span)); vm_func.body.push(ir_vm::Instruction::new(ir_vm::InstrKind::GateLoad { offset: *offset }, span.clone()));
if is_gate_type(&field_ty) { 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 } => { 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 // 1. Release old value in HIP if it was a gate
if is_gate_type(&field_ty) { 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::LocalLoad { slot: gate.0 }, span.clone()));
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::GateLoad { offset: *offset }, span)); 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)); 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::LocalLoad { slot: gate.0 }, span.clone()));
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::LocalLoad { slot: value.0 }, span)); 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 // 2. Retain new value if it's a gate
if let Some(val_ty) = local_types.get(&value.0) { if let Some(val_ty) = local_types.get(&value.0) {
if is_gate_type(val_ty) { 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 { .. } => { ir_core::InstrKind::GateLoadIndex { .. } => {
anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering"); anyhow::bail!("E_LOWER_UNSUPPORTED: Dynamic HIP index access not supported in v0 lowering");

View File

@ -1,6 +1,7 @@
use crate::common::diagnostics::DiagnosticBundle; use crate::common::diagnostics::DiagnosticBundle;
use crate::common::files::FileManager; use crate::common::files::FileManager;
use crate::frontends::pbs::{collector::SymbolCollector, parser::Parser, Symbol, Visibility}; use crate::frontends::pbs::{collector::SymbolCollector, parser::Parser, Symbol, Visibility};
use crate::common::spans::FileId;
use crate::manifest::{load_manifest, ManifestKind}; use crate::manifest::{load_manifest, ManifestKind};
use prometeu_analysis::NameInterner; use prometeu_analysis::NameInterner;
use serde::{Deserialize, Serialize}; 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 source = fs::read_to_string(&file_path)?;
let file_id = file_manager.add(file_path.clone(), source.clone()); 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 parsed = parser.parse_file()?;
let mut collector = SymbolCollector::new(&interner); let mut collector = SymbolCollector::new(&interner);

View File

@ -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");
}

View File

@ -2,6 +2,7 @@ use prometeu_bytecode::disasm::disasm;
use prometeu_bytecode::BytecodeLoader; use prometeu_bytecode::BytecodeLoader;
use prometeu_compiler::compiler::compile; use prometeu_compiler::compiler::compile;
use prometeu_compiler::frontends::pbs::parser::Parser; use prometeu_compiler::frontends::pbs::parser::Parser;
use prometeu_compiler::common::spans::FileId;
use prometeu_analysis::NameInterner; use prometeu_analysis::NameInterner;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
@ -57,7 +58,7 @@ fn generate_canonical_goldens() {
// 3. AST JSON // 3. AST JSON
let source = fs::read_to_string(project_dir.join("src/main/modules/main.pbs")).unwrap(); let source = fs::read_to_string(project_dir.join("src/main/modules/main.pbs")).unwrap();
let mut interner = NameInterner::new(); 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 parsed = parser.parse_file().expect("Failed to parse AST");
let ast_json = serde_json::to_string_pretty(parsed.arena.kind(parsed.root)).unwrap(); let ast_json = serde_json::to_string_pretty(parsed.arena.kind(parsed.root)).unwrap();
fs::write(golden_dir.join("ast.json"), ast_json).unwrap(); fs::write(golden_dir.join("ast.json"), ast_json).unwrap();