This commit is contained in:
bQUARKz 2026-02-04 19:41:05 +00:00
parent 89163807b4
commit a7669c9a8f
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 63 additions and 3 deletions

View File

@ -36,7 +36,7 @@ pub struct Symbol {
pub decl_span: Span, pub decl_span: Span,
} }
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SymbolArena { pub struct SymbolArena {
pub symbols: Vec<Symbol>, pub symbols: Vec<Symbol>,
} }

View File

@ -234,7 +234,7 @@ mod tests {
use super::*; use super::*;
use crate::frontends::pbs::ast::{ use crate::frontends::pbs::ast::{
AstArena, BlockNodeArena, CallNodeArena, ExprStmtNodeArena, FileNodeArena, FnDeclNodeArena, AstArena, BlockNodeArena, CallNodeArena, ExprStmtNodeArena, FileNodeArena, FnDeclNodeArena,
IdentNodeArena, NodeId, TypeDeclNodeArena, IdentNodeArena, TypeDeclNodeArena,
}; };
use crate::common::spans::Span; use crate::common::spans::Span;
@ -436,7 +436,7 @@ mod tests {
arena.roots.push(file_id); arena.roots.push(file_id);
let (symbols, index, ref_index, node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None); let (_symbols, index, ref_index, node_to_symbol, diagnostics) = build_def_index(&arena, 1, &interner, None);
assert!(diagnostics.is_empty(), "Diagnostics should be empty: {:?}", diagnostics); assert!(diagnostics.is_empty(), "Diagnostics should be empty: {:?}", diagnostics);
@ -499,4 +499,64 @@ mod tests {
assert_eq!(diagnostics[0].code, Some("E_RESOLVE_VISIBILITY".to_string())); assert_eq!(diagnostics[0].code, Some("E_RESOLVE_VISIBILITY".to_string()));
assert_eq!(diagnostics[0].span, Some(Span::new(0, 50, 62))); assert_eq!(diagnostics[0].span, Some(Span::new(0, 50, 62)));
} }
#[test]
fn test_determinism() {
let mut arena = AstArena::default();
let mut interner = NameInterner::new();
let target_name = interner.intern("target");
let target_body = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![], tail: None }), Span::new(0, 5, 5));
let target_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: Some("pub".to_string()),
name: target_name,
params: vec![],
ret: None,
else_fallback: None,
body: target_body,
}), Span::new(0, 0, 10));
let caller_name = interner.intern("caller");
let ident_id = arena.push(NodeKind::Ident(IdentNodeArena { name: target_name }), Span::new(0, 50, 56));
let call_id = arena.push(NodeKind::Call(CallNodeArena { callee: ident_id, args: vec![] }), Span::new(0, 50, 58));
let expr_stmt = arena.push(NodeKind::ExprStmt(ExprStmtNodeArena { expr: call_id }), Span::new(0, 50, 58));
let body_id = arena.push(NodeKind::Block(BlockNodeArena { stmts: vec![expr_stmt], tail: None }), Span::new(0, 40, 70));
let caller_id = arena.push(NodeKind::FnDecl(FnDeclNodeArena {
vis: None,
name: caller_name,
params: vec![],
ret: None,
else_fallback: None,
body: body_id,
}), Span::new(0, 30, 80));
let file_id = arena.push(NodeKind::File(FileNodeArena {
imports: vec![],
decls: vec![target_id, caller_id],
}), Span::new(0, 0, 100));
arena.roots.push(file_id);
let run1 = build_def_index(&arena, 1, &interner, None);
let run2 = build_def_index(&arena, 1, &interner, None);
// runX is (SymbolArena, DefIndex, RefIndex, NodeToSymbol, Vec<Diagnostic>)
let json1_symbols = serde_json::to_string(&run1.0).unwrap();
let json2_symbols = serde_json::to_string(&run2.0).unwrap();
assert_eq!(json1_symbols, json2_symbols, "SymbolArena should be deterministic");
let json1_refs = serde_json::to_string(&run1.2).unwrap();
let json2_refs = serde_json::to_string(&run2.2).unwrap();
assert_eq!(json1_refs, json2_refs, "RefIndex should be deterministic");
let json1_node_to_symbol = serde_json::to_string(&run1.3).unwrap();
let json2_node_to_symbol = serde_json::to_string(&run2.3).unwrap();
assert_eq!(json1_node_to_symbol, json2_node_to_symbol, "NodeToSymbol should be deterministic");
let json1_diags = serde_json::to_string(&run1.4).unwrap();
let json2_diags = serde_json::to_string(&run2.4).unwrap();
assert_eq!(json1_diags, json2_diags, "Diagnostics should be deterministic");
}
} }