release: Storybook v0.2.0 - Major syntax and features update
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
This commit is contained in:
@@ -39,8 +39,6 @@ impl RelationshipKey {
|
||||
#[derive(Debug, Clone)]
|
||||
struct RelationshipDecl {
|
||||
relationship: Relationship,
|
||||
/// Which participant is "self" (index into participants)
|
||||
self_index: Option<usize>,
|
||||
}
|
||||
|
||||
/// Resolved bidirectional relationship
|
||||
@@ -57,10 +55,8 @@ pub struct ResolvedRelationship {
|
||||
pub struct ParticipantFields {
|
||||
pub participant_name: Vec<String>,
|
||||
pub role: Option<String>,
|
||||
/// Fields from this participant's "self" block
|
||||
pub self_fields: Vec<Field>,
|
||||
/// Fields from this participant's "other" block (about other participants)
|
||||
pub other_fields: Vec<Field>,
|
||||
/// Fields from this participant's block
|
||||
pub fields: Vec<Field>,
|
||||
}
|
||||
|
||||
/// Resolve bidirectional relationships in a file
|
||||
@@ -76,18 +72,11 @@ pub fn resolve_relationships(file: &File) -> Result<Vec<ResolvedRelationship>> {
|
||||
|
||||
let key = RelationshipKey::new(participant_names, rel.name.clone());
|
||||
|
||||
// Determine which participant is "self" based on self/other blocks
|
||||
let self_index = rel
|
||||
.participants
|
||||
.iter()
|
||||
.position(|p| p.self_block.is_some() || p.other_block.is_some());
|
||||
|
||||
relationship_groups
|
||||
.entry(key)
|
||||
.or_default()
|
||||
.push(RelationshipDecl {
|
||||
relationship: rel.clone(),
|
||||
self_index,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -122,43 +111,31 @@ fn merge_relationship_declarations(
|
||||
.map(|p| ParticipantFields {
|
||||
participant_name: p.name.clone(),
|
||||
role: p.role.clone(),
|
||||
self_fields: p.self_block.clone().unwrap_or_default(),
|
||||
other_fields: p.other_block.clone().unwrap_or_default(),
|
||||
fields: p.fields.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Merge shared fields (fields outside participant blocks)
|
||||
let mut merged_fields = base.fields.clone();
|
||||
|
||||
// Merge additional declarations
|
||||
for decl in decls.iter().skip(1) {
|
||||
// If this declaration specifies a different participant as "self",
|
||||
// merge their self/other blocks appropriately
|
||||
if let Some(self_idx) = decl.self_index {
|
||||
let participant_name = &decl.relationship.participants[self_idx].name;
|
||||
|
||||
// Merge participant fields
|
||||
for participant in &decl.relationship.participants {
|
||||
// Find this participant in our merged list
|
||||
if let Some(idx) = participant_fields
|
||||
if let Some(pf_idx) = participant_fields
|
||||
.iter()
|
||||
.position(|pf| &pf.participant_name == participant_name)
|
||||
.position(|pf| pf.participant_name == participant.name)
|
||||
{
|
||||
// Merge self blocks
|
||||
let self_block = decl.relationship.participants[self_idx]
|
||||
.self_block
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
merge_fields(&mut participant_fields[idx].self_fields, self_block)?;
|
||||
|
||||
// Merge other blocks
|
||||
let other_block = decl.relationship.participants[self_idx]
|
||||
.other_block
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
merge_fields(&mut participant_fields[idx].other_fields, other_block)?;
|
||||
// Merge fields for this participant
|
||||
merge_fields(
|
||||
&mut participant_fields[pf_idx].fields,
|
||||
participant.fields.clone(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge shared fields (fields outside self/other blocks)
|
||||
let mut merged_fields = base.fields.clone();
|
||||
for decl in decls.iter().skip(1) {
|
||||
// Merge shared relationship fields
|
||||
merge_fields(&mut merged_fields, decl.relationship.fields.clone())?;
|
||||
}
|
||||
|
||||
@@ -209,8 +186,7 @@ mod tests {
|
||||
Participant {
|
||||
name: vec![name.to_string()],
|
||||
role: role.map(|s| s.to_string()),
|
||||
self_block: None,
|
||||
other_block: None,
|
||||
fields: vec![],
|
||||
span: Span::new(0, 10),
|
||||
}
|
||||
}
|
||||
@@ -257,14 +233,12 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bidirectional_relationship_merge() {
|
||||
fn test_relationship_merge() {
|
||||
let mut martha_participant = make_participant("Martha", Some("spouse"));
|
||||
martha_participant.self_block = Some(vec![make_field("bond", 90)]);
|
||||
martha_participant.other_block = Some(vec![make_field("trust", 85)]);
|
||||
martha_participant.fields = vec![make_field("commitment", 90)];
|
||||
|
||||
let mut david_participant = make_participant("David", Some("spouse"));
|
||||
david_participant.self_block = Some(vec![make_field("bond", 90)]);
|
||||
david_participant.other_block = Some(vec![make_field("trust", 85)]);
|
||||
david_participant.fields = vec![make_field("trust", 85)];
|
||||
|
||||
let file = File {
|
||||
declarations: vec![
|
||||
@@ -297,10 +271,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_conflicting_field_values() {
|
||||
let mut p1 = make_participant("Alice", None);
|
||||
p1.self_block = Some(vec![make_field("bond", 80)]);
|
||||
p1.fields = vec![make_field("bond", 80)];
|
||||
|
||||
let mut p2 = make_participant("Alice", None);
|
||||
p2.self_block = Some(vec![make_field("bond", 90)]); // Different value
|
||||
p2.fields = vec![make_field("bond", 90)]; // Different value
|
||||
|
||||
let file = File {
|
||||
declarations: vec![
|
||||
|
||||
Reference in New Issue
Block a user