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:
@@ -1,13 +1,52 @@
|
||||
/// Source location for error reporting
|
||||
/// Source location for error reporting with line/column information
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Span {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub start_line: usize, // 0-indexed line number
|
||||
pub start_col: usize, // 0-indexed column number
|
||||
pub end_line: usize,
|
||||
pub end_col: usize,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn new(start: usize, end: usize) -> Self {
|
||||
Self { start, end }
|
||||
Self {
|
||||
start,
|
||||
end,
|
||||
start_line: 0,
|
||||
start_col: 0,
|
||||
end_line: 0,
|
||||
end_col: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_position(
|
||||
start: usize,
|
||||
end: usize,
|
||||
start_line: usize,
|
||||
start_col: usize,
|
||||
end_line: usize,
|
||||
end_col: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
start,
|
||||
end,
|
||||
start_line,
|
||||
start_col,
|
||||
end_line,
|
||||
end_col,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to LSP Position for the start
|
||||
pub fn start_position(&self) -> (u32, u32) {
|
||||
(self.start_line as u32, self.start_col as u32)
|
||||
}
|
||||
|
||||
/// Convert to LSP Position for the end
|
||||
pub fn end_position(&self) -> (u32, u32) {
|
||||
(self.end_line as u32, self.end_col as u32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +87,36 @@ pub enum UseKind {
|
||||
Wildcard, // use foo::*
|
||||
}
|
||||
|
||||
/// Link to a behavior tree with optional conditions and priority
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct BehaviorLink {
|
||||
pub tree: Vec<String>, // Qualified path to behavior tree
|
||||
pub condition: Option<Expr>, // Optional when clause
|
||||
pub priority: Priority, // Execution priority
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Priority levels for behavior selection
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Priority {
|
||||
Low,
|
||||
Normal,
|
||||
High,
|
||||
Critical,
|
||||
}
|
||||
|
||||
impl Priority {
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
| "low" => Some(Priority::Low),
|
||||
| "normal" => Some(Priority::Normal),
|
||||
| "high" => Some(Priority::High),
|
||||
| "critical" => Some(Priority::Critical),
|
||||
| _ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Character definition
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Character {
|
||||
@@ -55,6 +124,9 @@ pub struct Character {
|
||||
pub species: Option<String>, // `: Species` - what the character fundamentally is
|
||||
pub fields: Vec<Field>,
|
||||
pub template: Option<Vec<String>>, // `from Template1, Template2`
|
||||
pub uses_behaviors: Option<Vec<BehaviorLink>>, // `uses behaviors: [...]`
|
||||
pub uses_schedule: Option<Vec<String>>, /* `uses schedule: ScheduleName` or `uses schedules:
|
||||
* [...]` */
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -65,6 +137,9 @@ pub struct Template {
|
||||
pub fields: Vec<Field>,
|
||||
pub strict: bool,
|
||||
pub includes: Vec<String>,
|
||||
pub uses_behaviors: Option<Vec<BehaviorLink>>, // `uses behaviors: [...]`
|
||||
pub uses_schedule: Option<Vec<String>>, /* `uses schedule: ScheduleName` or `uses
|
||||
* schedules: [...]` */
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -155,23 +230,66 @@ pub struct Transition {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Schedule definition
|
||||
/// Schedule definition with composition support
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Schedule {
|
||||
pub name: String,
|
||||
pub extends: Option<String>, // Base schedule to extend
|
||||
pub blocks: Vec<ScheduleBlock>,
|
||||
pub recurrences: Vec<RecurrencePattern>, // Recurring events
|
||||
pub fields: Vec<Field>, // Documentation prose blocks, metadata
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// A time block in a schedule
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ScheduleBlock {
|
||||
pub name: Option<String>, // Block name for override system
|
||||
pub is_override: bool, // Whether this block overrides a base block
|
||||
pub start: Time,
|
||||
pub end: Time,
|
||||
pub activity: String,
|
||||
pub activity: String, // DEPRECATED: kept for backward compatibility
|
||||
pub action: Option<Vec<String>>, // Behavior reference (new way)
|
||||
pub temporal_constraint: Option<TemporalConstraint>, // When this block applies
|
||||
pub fields: Vec<Field>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Temporal constraint for when a schedule block applies
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TemporalConstraint {
|
||||
Season(String), // Applies during specific season (enum value)
|
||||
DayOfWeek(String), // Applies on specific day of week (enum value)
|
||||
Month(String), // Applies during specific month (enum value)
|
||||
DateRange(String, String), // Applies between two dates (TODO: date type)
|
||||
}
|
||||
|
||||
/// Recurring event pattern
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct RecurrencePattern {
|
||||
pub name: String, // Event name (e.g., "MarketDay")
|
||||
pub constraint: TemporalConstraint, // When it recurs (e.g., "on Earthday")
|
||||
pub blocks: Vec<ScheduleBlock>, // What happens during the event
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
// ===== Parser Helper Types for Schedules =====
|
||||
|
||||
/// Helper for parsing schedule bodies with flexible ordering
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ScheduleBodyItem {
|
||||
Field(Field),
|
||||
Block(ScheduleBlock),
|
||||
Recurrence(RecurrencePattern),
|
||||
}
|
||||
|
||||
/// Helper for parsing schedule block content
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BlockContentItem {
|
||||
TimeRange(Time, Time),
|
||||
Field(Field),
|
||||
}
|
||||
|
||||
/// Behavior tree definition
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Behavior {
|
||||
@@ -182,19 +300,73 @@ pub struct Behavior {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BehaviorNode {
|
||||
Selector(Vec<BehaviorNode>), // ? operator
|
||||
Sequence(Vec<BehaviorNode>), // > operator (context-dependent)
|
||||
Selector {
|
||||
label: Option<String>,
|
||||
children: Vec<BehaviorNode>,
|
||||
},
|
||||
Sequence {
|
||||
label: Option<String>,
|
||||
children: Vec<BehaviorNode>,
|
||||
},
|
||||
Condition(Expr),
|
||||
Action(String, Vec<Field>), // Action name + parameters
|
||||
Decorator(String, Box<BehaviorNode>),
|
||||
Decorator {
|
||||
decorator_type: DecoratorType,
|
||||
child: Box<BehaviorNode>,
|
||||
},
|
||||
SubTree(Vec<String>), // Reference to another behavior
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DecoratorType {
|
||||
Repeat, // infinite loop
|
||||
RepeatN(u32), // N times
|
||||
RepeatRange(u32, u32), // min..max times
|
||||
Invert,
|
||||
Retry(u32), // max attempts
|
||||
Timeout(String), // duration string (e.g., "5s", "30m", "2h")
|
||||
Cooldown(String), // duration string (e.g., "5s", "30m", "2h")
|
||||
If(Expr),
|
||||
SucceedAlways,
|
||||
FailAlways,
|
||||
}
|
||||
|
||||
// BehaviorDuration is used for decorator timeouts/cooldowns (single unit)
|
||||
// whereas Duration (above) is for general time literals (compound: 2h30m)
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct BehaviorDuration {
|
||||
pub value: u32,
|
||||
pub unit: DurationUnit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DurationUnit {
|
||||
Days,
|
||||
Hours,
|
||||
Minutes,
|
||||
Seconds,
|
||||
}
|
||||
|
||||
impl BehaviorDuration {
|
||||
pub fn to_milliseconds(&self) -> u64 {
|
||||
let base_ms = self.value as u64;
|
||||
match self.unit {
|
||||
| DurationUnit::Days => base_ms * 24 * 60 * 60 * 1000,
|
||||
| DurationUnit::Hours => base_ms * 60 * 60 * 1000,
|
||||
| DurationUnit::Minutes => base_ms * 60 * 1000,
|
||||
| DurationUnit::Seconds => base_ms * 1000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Institution definition
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Institution {
|
||||
pub name: String,
|
||||
pub fields: Vec<Field>,
|
||||
pub uses_behaviors: Option<Vec<BehaviorLink>>, // `uses behaviors: [...]`
|
||||
pub uses_schedule: Option<Vec<String>>, /* `uses schedule: ScheduleName` or `uses
|
||||
* schedules: [...]` */
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -209,10 +381,9 @@ pub struct Relationship {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Participant {
|
||||
pub role: Option<String>, // "as parent"
|
||||
pub name: Vec<String>, // Qualified path
|
||||
pub self_block: Option<Vec<Field>>,
|
||||
pub other_block: Option<Vec<Field>>,
|
||||
pub role: Option<String>, // "as parent" (optional)
|
||||
pub fields: Vec<Field>, // Participant-specific fields (required block)
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -284,3 +455,40 @@ pub enum QuantifierKind {
|
||||
ForAll,
|
||||
Exists,
|
||||
}
|
||||
|
||||
// ===== Parser Helper Types =====
|
||||
// These enums are used internally by the LALRPOP parser to handle flexible
|
||||
// ordering
|
||||
|
||||
/// Helper for parsing character/institution bodies with flexible ordering
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CharacterBodyItem {
|
||||
Field(Field),
|
||||
UsesBehaviors(Vec<BehaviorLink>),
|
||||
UsesSchedule(Vec<String>),
|
||||
}
|
||||
|
||||
/// Helper for parsing institution bodies with flexible ordering
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InstitutionBodyItem {
|
||||
Field(Field),
|
||||
UsesBehaviors(Vec<BehaviorLink>),
|
||||
UsesSchedule(Vec<String>),
|
||||
}
|
||||
|
||||
/// Helper for parsing template body items with flexible ordering
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TemplateBodyItem {
|
||||
Field(Field),
|
||||
Include(String),
|
||||
UsesBehaviors(Vec<BehaviorLink>),
|
||||
UsesSchedule(Vec<String>),
|
||||
}
|
||||
|
||||
/// Helper for parsing behavior link fields
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BehaviorLinkField {
|
||||
Tree(Vec<String>),
|
||||
Condition(Expr),
|
||||
Priority(Priority),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user