BREAKING CHANGES: - Relationship syntax now requires blocks for all participants - Removed self/other perspective blocks from relationships - Replaced 'guard' keyword with 'if' for behavior tree decorators Language Features: - Add tree-sitter grammar with improved if/condition disambiguation - Add comprehensive tutorial and reference documentation - Add SBIR v0.2.0 binary format specification - Add resource linking system for behaviors and schedules - Add year-long schedule patterns (day, season, recurrence) - Add behavior tree enhancements (named nodes, decorators) Documentation: - Complete tutorial series (9 chapters) with baker family examples - Complete reference documentation for all language features - SBIR v0.2.0 specification with binary format details - Added locations and institutions documentation Examples: - Convert all examples to baker family scenario - Add comprehensive working examples Tooling: - Zed extension with LSP integration - Tree-sitter grammar for syntax highlighting - Build scripts and development tools Version Updates: - Main package: 0.1.0 → 0.2.0 - Tree-sitter grammar: 0.1.0 → 0.2.0 - Zed extension: 0.1.0 → 0.2.0 - Storybook editor: 0.1.0 → 0.2.0
165 lines
4.2 KiB
Rust
165 lines
4.2 KiB
Rust
//! Integration tests for the resolution engine
|
|
|
|
use crate::{
|
|
resolve::names::{
|
|
DeclKind,
|
|
NameTable,
|
|
},
|
|
syntax::{
|
|
lexer::Lexer,
|
|
FileParser,
|
|
},
|
|
};
|
|
|
|
fn parse(source: &str) -> crate::syntax::ast::File {
|
|
let lexer = Lexer::new(source);
|
|
let parser = FileParser::new();
|
|
parser.parse(lexer).expect("Should parse successfully")
|
|
}
|
|
|
|
#[test]
|
|
fn test_name_resolution_example_file() {
|
|
let source = r#"
|
|
character Alice {
|
|
age: 30
|
|
}
|
|
|
|
character Bob {
|
|
age: 35
|
|
}
|
|
|
|
template PersonTemplate {
|
|
age: 18..80
|
|
}
|
|
|
|
enum Status {
|
|
active,
|
|
inactive
|
|
}
|
|
"#;
|
|
|
|
let file = parse(source);
|
|
let table = NameTable::from_file(&file).expect("Should build name table");
|
|
|
|
// Verify all names are registered
|
|
assert!(table.lookup(&["Alice".to_string()]).is_some());
|
|
assert!(table.lookup(&["Bob".to_string()]).is_some());
|
|
assert!(table.lookup(&["PersonTemplate".to_string()]).is_some());
|
|
assert!(table.lookup(&["Status".to_string()]).is_some());
|
|
|
|
// Verify kind filtering
|
|
assert_eq!(table.entries_of_kind(DeclKind::Character).count(), 2);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Template).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Enum).count(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_use_statements_are_parsed() {
|
|
let source = r#"
|
|
use characters::Martha;
|
|
use templates::{Person, NPC};
|
|
use locations::*;
|
|
|
|
character LocalChar {
|
|
age: 25
|
|
}
|
|
"#;
|
|
|
|
let file = parse(source);
|
|
let table = NameTable::from_file(&file).expect("Should build name table");
|
|
|
|
// Verify imports were collected
|
|
assert_eq!(table.imports().len(), 3);
|
|
|
|
// Verify local declaration is registered
|
|
assert!(table.lookup(&["LocalChar".to_string()]).is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn test_duplicate_name_error() {
|
|
let source = r#"
|
|
character Martha {
|
|
age: 30
|
|
}
|
|
|
|
character Martha {
|
|
age: 35
|
|
}
|
|
"#;
|
|
|
|
let file = parse(source);
|
|
let result = NameTable::from_file(&file);
|
|
|
|
// Should fail with duplicate error
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_fuzzy_matching_suggestion() {
|
|
let source = r#"
|
|
character Elizabeth {
|
|
age: 30
|
|
}
|
|
"#;
|
|
|
|
let file = parse(source);
|
|
let table = NameTable::from_file(&file).expect("Should build name table");
|
|
|
|
// Typo "Elizabet" should suggest "Elizabeth"
|
|
let suggestion = table.find_suggestion("Elizabet");
|
|
assert_eq!(suggestion, Some("Elizabeth".to_string()));
|
|
|
|
// Typo "Elizabth" should also suggest "Elizabeth"
|
|
let suggestion = table.find_suggestion("Elizabth");
|
|
assert_eq!(suggestion, Some("Elizabeth".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn test_all_declaration_kinds() {
|
|
let source = r#"
|
|
character C { age: 1 }
|
|
template T { age: 1..2 }
|
|
life_arc L {
|
|
state s {}
|
|
}
|
|
schedule S {
|
|
10:00 -> 11:00: activity { }
|
|
}
|
|
behavior B {
|
|
action
|
|
}
|
|
institution I {
|
|
name: "Test"
|
|
}
|
|
relationship R {
|
|
C { }
|
|
C { }
|
|
}
|
|
location Loc {
|
|
name: "Place"
|
|
}
|
|
species Sp {
|
|
lifespan: 100
|
|
}
|
|
enum E {
|
|
a,
|
|
b
|
|
}
|
|
"#;
|
|
|
|
let file = parse(source);
|
|
let table = NameTable::from_file(&file).expect("Should build name table");
|
|
|
|
// All 10 declaration kinds should be represented
|
|
assert_eq!(table.entries_of_kind(DeclKind::Character).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Template).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::LifeArc).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Schedule).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Behavior).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Institution).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Relationship).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Location).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Species).count(), 1);
|
|
assert_eq!(table.entries_of_kind(DeclKind::Enum).count(), 1);
|
|
}
|