pr 02
This commit is contained in:
parent
adb4dad14b
commit
07f986df5b
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
14
crates/prometeu-analysis/tests/span_tests.rs
Normal file
14
crates/prometeu-analysis/tests/span_tests.rs
Normal 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));
|
||||||
|
}
|
||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 });
|
||||||
|
|||||||
@ -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,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -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()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(_)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
26
crates/prometeu-compiler/tests/diagnostics_span.rs
Normal file
26
crates/prometeu-compiler/tests/diagnostics_span.rs
Normal 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");
|
||||||
|
}
|
||||||
@ -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();
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user