2026-02-14 13:29:33 +00:00
# Storybook Type System
**Version**: 0.3.0
**Status**: Draft
## Overview
The Storybook type system is a **declarative, pure functional DSL ** for defining narrative simulations. It separates type definitions and logic (language layer) from state management and mutation (runtime layer).
### Core Principles
1. **Language is pure ** - no mutation, no state changes, only declarations
2. **Templates are record types ** - universal structural type definitions
3. **Entities are typed values ** - characters, institutions, locations are instances
4. **Behaviors are functional ** - control flow and pattern matching
5. **Actions are the boundary ** - where language meets runtime
### Core Declarations
- **`template` **: Record type definitions (structural types)
- **`character` /`institution` /`location` **: Typed value instances
- **`concept` **: Base type declarations for pattern matching
- **`sub_concept` **: Enumerated and typed subtypes (tagged union members)
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
- **`definition` **: Compile-time pattern matching over subtype combinations
2026-02-14 13:29:33 +00:00
- **`action` **: Signature declarations for runtime-implemented operations
This system enables static validation of entity relationships, behavior conditions, and data structures while maintaining readability for narrative design.
---
## Architecture: Language vs Runtime
### Language Layer (Storybook DSL)
**Pure, declarative, no mutation:**
- Defines types (templates, concepts)
- Defines values (characters, institutions, locations)
- Defines logic (behaviors, pattern matching)
- Declares action signatures (interface to runtime)
**Example:**
```storybook
template Person {
age: Number,
profession: Profession
}
character Martha: Person {
age: 34,
profession: Baker
}
action bake(baker: Baker, item: BakingItem)
behavior BakingWork {
then {
check_orders
bake
}
}
```
### Runtime Layer (Implementation)
**Stateful, manages mutation:**
- Holds character state
- Executes actions (implements mutations)
- Runs behavior trees
- Updates world state over time
**Example (Rust):**
```rust
enum Action {
Bake { baker: EntityId, item: ItemId },
CheckOrders { baker: EntityId },
PrepareIngredients { baker: EntityId, recipe: RecipeId },
}
impl Runtime {
fn execute_action(&mut self, action: Action) {
match action {
Action::Bake { baker, item } => {
let character = self.get_character_mut(baker);
let baked_item = self.get_item(item).bake();
character.inventory.add(baked_item);
character.energy -= 10;
}
Action::CheckOrders { baker } => {
let character = self.get_character_mut(baker);
let orders = self.query_orders();
character.task_queue.extend(orders);
}
Action::PrepareIngredients { baker, recipe } => {
// Implementation
}
}
}
}
```
### Actions: The Boundary
Actions are **declared in Storybook ** (signatures) but **implemented in runtime ** (behavior).
**Language sees:**
```storybook
/// Bakes an item in the oven
///
/// The baker must have sufficient energy and the item must be prepared.
/// Updates baker's inventory and reduces energy.
action bake(baker: Baker, item: BakingItem)
```
**Runtime implements:**
```rust
impl Runtime {
fn bake(&mut self, baker: EntityId, item: ItemId) {
let character = self.get_character_mut(baker);
let baked = self.get_item(item).bake();
character.inventory.add(baked);
character.energy -= 10;
}
}
```
**Benefits:**
- ✅ Language stays pure and type-safe
- ✅ Runtime has implementation flexibility
- ✅ Clear contract between layers
- ✅ Can add standard library later without changing language
---
## Core Declarations
### `template` - Record Type Definition
A `template` defines a structural record type. Templates are the universal mechanism for defining structured data in Storybook.
**Syntax:**
```storybook
template TypeName {
field1: Type,
field2: Type,
...
}
```
**Examples:**
```storybook
template Person {
age: Number,
species_type: Species,
profession: Profession
}
template Building {
owner: Person, // Reference to Person template
capacity: Number,
place: Settlement // Reference to Settlement template
}
template Settlement {
terrain: Terrain,
population: Number
}
template FamilialBond {
parent: Person, // Reference to Person template
child: Person, // Reference to Person template
strength: Number
}
```
**Purpose:**
- Define reusable record structures
- Provide types for characters, institutions, locations, relationships
- Enable type checking for fields and references
**Field Types:**
Templates support both value types and reference types:
**Value Types:**
- `Number` - integer values (e.g., `age: 34` )
- `Decimal` - floating-point values (e.g., `price: 19.99` )
- `Text` - text values (e.g., `name: "Martha"` )
- `Boolean` - boolean values (e.g., `active: true` )
**Range Declarations:**
For procedural generation, templates can specify ranges instead of concrete values:
```storybook
template Person {
age: 18..80, // Random age between 18 and 80
height: 150..200, // Random height in cm
wealth: 100..10000 // Random wealth amount
}
```
When a character instantiates a template with ranges, it must provide concrete values within those ranges:
```storybook
character Martha: Person {
age: 34, // Must be between 18 and 80
height: 165, // Must be between 150 and 200
wealth: 5000 // Must be between 100 and 10000
}
```
**Reference Types:**
Templates can reference concepts and other templates:
```storybook
template Baker {
profession: Profession, // Reference to concept
place: Settlement, // Reference to Settlement template
tools: BakingTools // Reference to BakingTools template
}
```
Note: Template fields reference **template types ** (Person, Settlement, Building), not declaration keywords (character, location, institution).
**Reserved Keywords:**
Field names cannot use reserved keywords. Use suffixes or alternatives instead:
```storybook
// ✗ Invalid - 'species' is a keyword
template Person {
age: Number,
species: Species, // Error!
profession: Profession
}
// ✓ Valid - use alternative names
template Person {
age: Number,
species_type: Species, // OK
profession: Profession
}
```
Common alternatives:
- `species` → `species_type` , `creature_type`
- `location` → `location_ref` , `place`
- `character` → `character_ref` , `person`
- `template` → `template_name` , `template_ref`
- `behavior` → `behavior_ref` , `action_tree`
**Template Composition:**
Templates can reference other templates and concepts in their fields.
---
### Entities: Typed Value Instances
Characters, institutions, locations, and relationships are **typed values ** - instances of template types.
**Syntax:**
```storybook
character Name: TemplateName {
field1: value,
field2: value,
...
}
institution Name: TemplateName {
field1: value,
field2: value,
...
}
location Name: TemplateName {
field1: value,
field2: value,
...
}
relationship Name: TemplateName {
field1: value,
field2: value,
...
}
```
**Examples:**
```storybook
character Martha: Person {
age: 34,
species_type: Human,
profession: Baker
}
institution Bakery: Building {
owner: Martha,
capacity: 20,
place: TownSquare
}
location TownSquare: Settlement {
terrain: Plains,
population: 500
}
relationship ParentChild: FamilialBond {
parent: Martha,
child: Jane,
strength: 10
}
```
**Type Checking:**
- Values must match their template's field types
- Values must fall within range constraints (if specified in template)
- All required fields must be provided
- References must resolve to declared entities
**Example:**
```storybook
template Person {
age: 18..80,
profession: Profession
}
// ✓ Valid - within constraints
character Martha: Person {
age: 34, // 18 <= 34 <= 80
profession: Baker
}
// ✗ Error - age out of range
character TooYoung: Person {
age: 12, // 12 < 18 (violates constraint)
profession: Child
}
```
**State Management:**
- Entities are values **at declaration time **
- State changes are managed by the runtime (outside the language)
- Language defines initial state, runtime manages ongoing state
---
### `action` - Runtime Operation Signature
An `action` declares the signature of a runtime-implemented operation. Actions are the interface between the pure language layer and the stateful runtime layer.
**Syntax:**
```storybook
/// Documentation comment (required)
///
/// Multi-line docstrings explain what the action does,
/// its preconditions, and its effects.
action name(param1: Type, param2: Type, ...)
```
**Examples:**
```storybook
/// Bakes an item in the oven
///
/// The baker must have sufficient energy and the item must be prepared.
/// Updates baker's inventory and reduces energy.
action bake(baker: Baker, item: BakingItem)
/// Checks pending orders and updates the baker's task list
///
/// Queries the order queue and populates the baker's work queue.
action check_orders(baker: Baker)
/// Moves a character to a new location
///
/// Updates the character's location and triggers any location-based events.
action move_to(character: Person, destination: Settlement)
```
**Documentation Requirement:**
- Actions must have a docstring explaining their behavior
- This helps runtime implementers understand intent
- Serves as contract between language and runtime
**Type Checking:**
- Action calls in behaviors are validated against signatures
- Parameter types must match
- Unknown actions are compile errors
**Implementation:**
- Signatures are declared in `.sb` files (typically `actions.sb` )
- Implementations are provided by the runtime
- Standard library of common actions may come in future versions
**Current Limitations:**
- Actions have no return values (this version)
- Actions are statements, not expressions
- No support for action composition
---
### `concept` - Base Type Declaration
A `concept` declares a base type with no inherent structure. It serves as a parent for related `sub_concept` declarations.
**Syntax:**
```storybook
concept TypeName
```
**Example:**
```storybook
concept Cup
concept Customer
concept Vendor
```
**Purpose:**
- Establish type namespaces for related subtypes
- Provide type identity for values in the system
- Enable type checking in behaviors and conditions
**When to use:**
- When you need a type that will have multiple variants or aspects
- To create type-safe enumerations through `sub_concept`
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
- As a base for compile-time pattern matching via `definition`
2026-02-14 13:29:33 +00:00
---
### `sub_concept` - Subtype Definition
A `sub_concept` defines members of a tagged union for a parent concept. Sub_concepts are associated with their parent through **dot notation ** (explicit parent reference).
**Syntax:**
**Enumerated Form** (fixed set of values):
```storybook
sub_concept Parent.Name {
Variant1,
Variant2,
Variant3
}
```
**Typed Form** (structured with fields):
```storybook
sub_concept Parent.RecordName {
field1: TypeOrAny,
field2: TypeOrAny
}
```
**Parent Declaration:**
The parent is explicitly declared using dot notation:
- `Cup.Type` → parent: `Cup` , name: `Type`
- `Cup.Size` → parent: `Cup` , name: `Size`
- `Cupcake.Flavor` → parent: `Cupcake` , name: `Flavor`
**Why dot notation?**
- ✅ Prevents accidental naming collisions (`Cupcake` won't match `Cup` )
- ✅ Makes parent-child relationships explicit and clear
- ✅ Reads naturally: "Cup's Type", "Cup's Size"
- ✅ No ambiguity - parser knows exact parent
- ✅ Allows arbitrary sub_concept names without prefix requirements
**Examples:**
```storybook
// Parent concepts
concept Cup;
concept Cupcake;
// Cup sub_concepts (tagged union members)
sub_concept Cup.Size {
Small,
Medium,
Large
}
sub_concept Cup.Type {
Ceramic,
Glass,
Plastic
}
sub_concept Cup.Color {
Red,
Blue,
Green
}
// Cupcake sub_concepts (no confusion with Cup)
sub_concept Cupcake.Flavor {
Strawberry,
Chocolate,
Raspberry
}
// Typed sub_concept (record-like)
sub_concept Vendor.Inventory {
Bread: any,
Pastries: any,
Cakes: any,
Cup: any
}
```
**Type Checking Rules:**
- ✅ Field values must be **identifiers ** (references to other concepts/sub_concepts or `any` )
- ❌ Field values cannot be value types (Text, Number, Decimal, Boolean)
```storybook
// ✅ VALID - identifier references
sub_concept Inventory {
item: Product,
container: Cup,
quantity: any
}
// ❌ INVALID - value types not allowed
sub_concept BadInventory {
name: "string", // ✗ string literal
count: 42, // ✗ integer literal
active: true // ✗ boolean literal
}
```
**Purpose:**
- **Enumerated**: Define a fixed set of mutually exclusive values
- **Typed**: Define structured data with type-safe fields
- Both forms create tagged union members of the parent concept
**Relationship to Parent:**
Sub_concepts are **tagged union members ** , not inheritance:
- `CupSize.Small` is a distinct variant of the `Cup` union
- `CupType.Glass` is another distinct variant of the `Cup` union
- They coexist as different aspects/facets of the same base type
---
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
### `definition` - Compile-time Pattern Matching
2026-02-14 13:29:33 +00:00
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
A `definition` performs compile-time pattern matching over combinations of sub_concept values, mapping them to derived variant names.
2026-02-14 13:29:33 +00:00
**Syntax:**
```storybook
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
definition ComparisonName {
2026-02-14 13:29:33 +00:00
VariantName1: {
SubConceptName1: condition1,
SubConceptName2: condition2,
...
},
VariantName2: {
SubConceptName1: condition1,
SubConceptName2: condition2,
...
}
}
```
**Condition Syntax:**
- **`any` **: Matches any value of the specified sub_concept type
- **`Type is Value1 or Type is Value2` **: Matches specific enumerated values
**Example:**
```storybook
concept Cup;
sub_concept Cup.Size {
Small, Medium, Large
}
sub_concept Cup.Type {
Ceramic, Glass, Plastic
}
sub_concept Cup.Color {
Red, Blue, Green
}
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
definition CustomerNumbererestInCups {
2026-02-14 13:29:33 +00:00
Numbererested: {
Cup.Size: any, // Any size
Cup.Type: Cup.Type is Glass or Cup.Type is Plastic, // Only Glass or Plastic
Cup.Color: Cup.Color is Red or Cup.Color is Blue // Only Red or Blue
},
NotNumbererested: {
Cup.Size: any,
Cup.Type: any,
Cup.Color: any
},
Maybe: {
Cup.Size: any,
Cup.Type: any,
Cup.Color: any
}
}
```
**Pattern Matching Semantics:**
- The comparison evaluates **at compile-time **
- Given concrete sub_concept values, determines which variant they match
- Used in behavior conditions to enable type-safe decision making
**Usage in Behaviors:**
```storybook
behavior SellAtMarket {
repeat {
then {
greet_customer
show_products
if(CustomerNumbererestInCups.Numbererested.Cup.Size is Medium or Cup.Size is Large) {
make_sale(Cup)
}
thank_customer
}
}
}
```
**Purpose:**
- Create derived types from combinations of existing sub_concepts
- Enable compile-time validation of complex conditions
- Provide type-safe pattern matching for behaviors
**Mixing Enumerated and Typed Sub_concepts:**
Concept_comparisons can reference both enumerated and typed sub_concepts in the same pattern (support for this is being implemented).
---
## Type Compatibility
### Subtyping Rules
Sub_concepts are tagged union members of their parent concept:
```
CupSize.Small <: Cup
CupType.Glass <: Cup
CupColor.Red <: Cup
```
### Substitution
**Where sub_concept values can be used:**
- As arguments to actions that expect the parent concept
- In field assignments expecting the parent type
- In conditions and comparisons
**Example:**
```storybook
action serve(item: Cup) {
// Implementation
}
// Valid calls - sub_concepts substitute for parent
serve(CupSize.Small)
serve(CupType.Glass)
serve(CupColor.Red)
```
### Type Checking
**Compile-time:**
- Sub_concept field types must be identifiers (not value types)
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
- Pattern matching in `definition` is validated
2026-02-14 13:29:33 +00:00
- Type references must resolve to declared concepts
**Runtime:**
- Values are tagged with their specific sub_concept variant
- Pattern matching evaluates to variant names
- Type information preserved for behavior execution
---
## `any` Keyword
The `any` keyword represents **any value of a specific type ** , not a universal type.
**Semantics:**
```storybook
sub_concept VendorInventory {
Bread: any, // any value of type Bread
Pastries: any, // any value of type Pastries
Cup: any // any value of type Cup (includes all CupSize, CupType, CupColor)
}
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
definition Example {
2026-02-14 13:29:33 +00:00
AllCups: {
CupSize: any, // matches Small, Medium, Large
CupType: any, // matches Ceramic, Glass, Plastic
CupColor: any // matches Red, Blue, Green
}
}
```
**Not a universal type:**
- `any` is scoped to the field's declared type
- Does not mean "any type in the system"
- Provides flexibility while maintaining type safety
---
## Design Guidelines
### When to use `concept`
- You need a base type for multiple related variants
- You want type-safe enumerations
- You need to group related aspects of an entity
### When to use enumerated `sub_concept`
- You have a fixed set of mutually exclusive values
- Values are symbolic/categorical (not data-bearing)
- You need type-safe pattern matching over the values
### When to use typed `sub_concept`
- You need structured data with multiple fields
- Fields reference other concepts or need flexibility (`any` )
- You want record-like types within the concept system
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
### When to use `definition`
2026-02-14 13:29:33 +00:00
- You need to map combinations of sub_concepts to outcomes
- Complex conditional logic benefits from compile-time validation
- Behavior trees need type-safe decision points
---
## Examples
### Simple Enumeration
```storybook
concept Season;
sub_concept Season.Name {
Spring,
Summer,
Fall,
Winter
}
```
### Multi-faceted Type
```storybook
concept Food;
sub_concept Food.Type {
Bread,
Pastry,
Cake
}
sub_concept Food.Freshness {
Fresh,
Stale,
Spoiled
}
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
definition FoodQuality {
2026-02-14 13:29:33 +00:00
Excellent: {
Food.Type: any,
Food.Freshness: Food.Freshness is Fresh
},
Poor: {
Food.Type: any,
Food.Freshness: Food.Freshness is Stale or Food.Freshness is Spoiled
}
}
```
### Record Type
```storybook
concept Inventory;
sub_concept Inventory.Record {
item_type: Product,
quantity: any,
location: StorageArea
}
```
---
## Implementation Notes
### Parser
- Sub_concept parent inference uses prefix matching on the concept name
- Enumerated vs typed sub_concepts are disambiguated by presence of `:` after first identifier
- `any` keyword is parsed as `Value::Any` in the AST
### AST Representation
```rust
pub struct ConceptDecl {
pub name: Text,
pub span: Span,
}
pub struct SubConceptDecl {
pub name: Text,
pub parent_concept: Text, // Inferred from naming convention
pub kind: SubConceptKind,
pub span: Span,
}
pub enum SubConceptKind {
Enum { variants: Vec<Text> },
Record { fields: Vec<Field> },
}
pub struct ConceptComparisonDecl {
pub name: Text,
pub variants: Vec<VariantPattern>,
pub span: Span,
}
pub struct VariantPattern {
pub name: Text,
pub conditions: Vec<FieldCondition>,
pub span: Span,
}
pub enum Condition {
Any,
Is(Vec<Text>), // "is Value1 or Value2"
}
```
---
---
## Species and Template Inheritance
### Species as Base Types with Defaults
Species define base record types with default values that templates can extend and characters can override.
**Syntax:**
```storybook
species SpeciesName {
field: Type = default_value,
...
}
```
**Example:**
```storybook
species Human {
bipedal: Boolean = true,
has_hair: Boolean = true,
base_lifespan: Number = 80,
can_use_magic: Boolean = false
}
species Elf {
bipedal: Boolean = true,
pointed_ears: Boolean = true,
base_lifespan: Number = 1000,
can_use_magic: Boolean = true
}
```
### Template Extension
Templates extend species using `:` syntax and can override species defaults or add new fields.
**Syntax:**
```storybook
template TemplateName: SpeciesName {
field: Type = default, // Override species field
new_field: Type, // Add new required field
new_field2: Type = default // Add new field with default
}
```
**Example:**
```storybook
template Person: Human {
// Inherits: bipedal, has_hair, base_lifespan, can_use_magic (with defaults)
age: Number, // New required field
name: Text // New required field
}
template Cyborg: Human {
// Override species defaults
base_lifespan: Number = 200, // Cyborgs live longer
organic: Boolean = false, // New field
// Add new fields
model: Text, // Required
battery_level: Number = 100 // With default
}
```
### Override Priority Chain
**Character > Template > Species**
When a field is defined at multiple levels, the most specific definition wins:
```storybook
species Human {
strength: Number = 10,
intelligence: Number = 10,
speed: Number = 10
}
template Warrior: Human {
strength: Number = 15, // Override species default
weapon: Text // New required field
}
character Conan: Warrior {
strength: 20, // Override template (which overrode species)
weapon: "Greatsword", // Required by template
intelligence: 5 // Override species default
// speed: 10 (from species, no overrides)
}
```
**Resolution order:**
1. Check character fields - use if present
2. Check template fields - use if present and not in character
3. Check species fields - use if not overridden
4. Error if no value found and field is required
### Character Instantiation with Inheritance
```storybook
character Martha: Person {
// Required template fields (no defaults)
age: 34,
name: "Martha",
// Optional overrides of species defaults
bipedal: false, // She has one leg
can_use_magic: true, // Exceptional human
// Inherited from species (use defaults)
// has_hair: true (from Human)
// base_lifespan: 80 (from Human)
}
```
### Benefits
✅ **Layered defaults ** - species → template → character
✅ **No redundancy ** - don't repeat common defaults
✅ **Composable ** - templates customize species for specific roles
✅ **Exceptional cases ** - characters override when needed
✅ **Clear precedence ** - explicit override chain
---
## Life Arcs as Entity State
### Core Concept
**Life arcs represent the current state of an entity in various state machines.**
An entity (character/location/institution) is not just data - it has **state ** that changes over time. Life arcs define:
- What states exist (Baby, Child, Adult, Elder)
- How to transition between states (when age >= 18)
- What behaviors are available in each state
**The entity's life arc assignments ARE its current state in those state machines.**
### Entity State Model
```storybook
character Martha: Baker {
// Data fields
age: 34,
skill_level: 8,
reputation: 85,
// STATE - current position in life arc state machines
life_arcs: {
Human: Adult, // In "Adult" state of Human state machine
Baker: Master, // In "Master" state of Baker state machine
Reputation: Famous // In "Famous" state of Reputation state machine
}
}
```
**Martha's state is:**
- Age progression: Adult (can Work, Train, Manage)
- Career progression: Master (can BakingWork, TrainApprentice, InnovateTechniques)
- Social progression: Famous (can Influence, NetworkGlobally)
### Life Arcs Define State Machines
```storybook
life_arc Human requires { age: Number } {
Baby {
when age < 2
can use behaviors: [Cry, Sleep, Eat]
-> Child when age >= 2
}
Child {
when age >= 2 and age < 12
2026-02-14 16:29:22 +00:00
can use behaviors: [Cry, Play, Learn, Eat, Sleep]
2026-02-14 13:29:33 +00:00
-> Adolescent when age >= 12
}
Adolescent {
when age >= 12 and age < 18
2026-02-14 16:29:22 +00:00
can use behaviors: [Cry, Sleep, Play, Learn, Socialize, Work]
2026-02-14 13:29:33 +00:00
-> Adult when age >= 18
}
Adult {
when age >= 18 and age < 65
2026-02-14 16:29:22 +00:00
can use behaviors: [Cry, Sleep, Work, Socialize, Train, Manage]
2026-02-14 13:29:33 +00:00
-> Elder when age >= 65
}
Elder {
when age >= 65
2026-02-14 16:29:22 +00:00
can use behaviors: [Cry, Sleep, Rest, Socialize, Mentor]
2026-02-14 13:29:33 +00:00
}
}
```
**This defines:**
- **States**: Baby, Child, Adolescent, Adult, Elder
- **Transitions**: age thresholds trigger state changes
- **Capabilities**: each state grants different behaviors
### State Determines Capabilities
**Behavior availability = Life Arc States + Location + Template**
```storybook
Can Martha use TrainApprentice at Bakery?
Check life arc states:
✓ Human.Adult grants ability to Train
✓ Baker.Master grants TrainApprentice
Check location:
✓ Bakery enables TrainApprentice
→ YES - all conditions met
```
**If Martha were Baker.Journeyman instead:**
```storybook
character Martha: Baker {
skill_level: 5,
life_arcs: {
Human: Adult,
Baker: Journeyman // Different state!
}
}
Can Martha use TrainApprentice at Bakery?
Check life arc states:
✓ Human.Adult grants ability to Train
✗ Baker.Journeyman does NOT grant TrainApprentice
→ NO - lacks capability from life arc state
```
### Multiple Concurrent State Machines
Entities can be in multiple state machines simultaneously:
```storybook
life_arc Human requires { age: Number } {
// Age-based progression
}
life_arc Baker requires { skill_level: Number } {
// Skill-based progression
}
life_arc Reputation requires { fame: Number } {
// Fame-based progression
}
character Martha: Baker {
age: 34,
skill_level: 8,
fame: 85,
life_arcs: {
Human: Adult, // State in age dimension
Baker: Master, // State in career dimension
Reputation: Famous // State in social dimension
}
}
```
**Each life arc is an independent state machine:**
- Human state machine: transitions based on age
- Baker state machine: transitions based on skill_level
- Reputation state machine: transitions based on fame
**Available behaviors = union of all state capabilities:**
- From Human.Adult: Work, Train, Manage
- From Baker.Master: BakingWork, TrainApprentice
- From Reputation.Famous: Influence, NetworkGlobally
### Locations Have State Too
```storybook
life_arc Settlement requires { population: Number, development: Number } {
Village {
when population < 500
enables behaviors: [Farming, Fishing]
-> Town when population >= 500 and development >= 3
}
Town {
when population >= 500 and population < 5000
enables behaviors: [Trading, Crafting, Farming]
-> City when population >= 5000 and development >= 7
}
City {
when population >= 5000
enables behaviors: [Trading, Manufacturing, Politics, Education]
}
}
location TownSquare: SettlementTemplate {
population: 500,
development: 4,
life_arcs: {
Settlement: Town // Current state
}
}
```
**TownSquare's state:**
- It's in the "Town" state (not Village, not City)
- It enables behaviors: Trading, Crafting, Farming
- When population reaches 5000 AND development reaches 7, it transitions to City state
### Institutions Have State Too
```storybook
life_arc Business requires { revenue: Number, reputation: Number } {
Startup {
when revenue < 10000
enables behaviors: [Hustle, Experiment]
-> Established when revenue >= 10000
}
Established {
when revenue >= 10000 and revenue < 100000
enables behaviors: [Operate, Expand]
-> Corporate when revenue >= 100000
}
Corporate {
when revenue >= 100000
enables behaviors: [Operate, Expand, Franchise, Lobby]
}
}
institution Bakery: Building {
revenue: 15000,
reputation: 75,
life_arcs: {
Business: Established // Current state
}
}
```
### Bidirectional State Transitions
**State machines are NOT necessarily forward-only.**
Characters can progress forward, regress backward, or transition laterally based on field changes:
```storybook
life_arc Baker requires { skill_level: Number, experience: Number } {
Apprentice {
when skill_level < 3
can use behaviors: [Learn, AssistBaking]
-> Journeyman when skill_level >= 3
}
Journeyman {
when skill_level >= 3 and skill_level < 7
can use behaviors: [BakingWork, ManageInventory]
-> Master when skill_level >= 7 // Progress forward
-> Apprentice when skill_level < 3 // Regress backward!
}
Master {
when skill_level >= 7
can use behaviors: [BakingWork, ManageInventory, TrainApprentice, InnovateTechniques]
-> Journeyman when skill_level < 7 // Can lose mastery!
}
}
```
**The `when` clause defines:**
- **State validity condition**: What must be true to be in this state
- **NOT a one-time check**: Re-evaluated whenever fields change
**Examples of regression:**
```storybook
character Martha: Baker {
skill_level: 8,
life_arcs: { Baker: Master }
}
// Martha is Master Baker, then loses practice
action lose_practice(baker: Person) {
baker.skill_level -= 5 // Now skill_level = 3
}
lose_practice(Martha)
// Runtime re-evaluates:
// 1. Is Martha still valid for Master? (requires skill_level >= 7)
// 3 >= 7? NO - state is invalid!
// 2. Check Master's transitions:
// -> Journeyman when skill_level < 7
// 3 < 7? YES - transition!
// 3. Martha is now Journeyman
// Martha's available behaviors change:
// Lost: TrainApprentice, InnovateTechniques
// Kept: BakingWork, ManageInventory
```
**Examples of recovery:**
```storybook
// Later, Martha practices and improves
action practice_baking(baker: Person) {
baker.skill_level += 1
}
// Practice multiple times
practice_baking(Martha) // skill_level = 4
practice_baking(Martha) // skill_level = 5
practice_baking(Martha) // skill_level = 6
practice_baking(Martha) // skill_level = 7
// After skill_level reaches 7:
// Runtime re-evaluates:
// 1. Check Journeyman's transitions:
// -> Master when skill_level >= 7
// 7 >= 7? YES - transition!
// 2. Martha is Master again!
```
### State Changes = Mutations
**Life arcs ARE the mutability mechanism:**
1. **Actions modify field values: **
```storybook
action practice_baking(baker: Person) {
// Runtime implementation
baker.skill_level += 1
}
action lose_practice(baker: Person) {
// Runtime implementation
baker.skill_level -= 1
}
```
2. **Modified values trigger state transitions (in ANY direction): **
```storybook
// Progression
// Before: Martha.skill_level = 6, Baker state = Journeyman
practice_baking(Martha)
// After: Martha.skill_level = 7
// Transition: Journeyman -> Master (forward)
// Regression
// Before: Martha.skill_level = 7, Baker state = Master
lose_practice(Martha)
lose_practice(Martha)
lose_practice(Martha)
// After: Martha.skill_level = 4
// Transition: Master -> Journeyman (backward)
```
3. **New state grants/removes capabilities: **
```storybook
// After progression to Master:
// Gained: TrainApprentice, InnovateTechniques
// After regression to Journeyman:
// Lost: TrainApprentice, InnovateTechniques
// Kept: BakingWork, ManageInventory
```
### Runtime State Re-evaluation
**After ANY action that modifies fields:**
```rust
impl Runtime {
fn execute_action(&mut self, action: Action) {
// 1. Execute action (mutates entity fields)
let entity_id = match &action {
Action::PracticeBaking { baker } => {
let character = self.get_character_mut(*baker);
character.skill_level += 1;
*baker
}
Action::LosePractice { baker } => {
let character = self.get_character_mut(*baker);
character.skill_level -= 1;
*baker
}
_ => {
// Handle other actions
return;
}
};
// 2. Re-evaluate ALL life arc states for this entity
self.update_life_arc_states(entity_id);
}
fn update_life_arc_states(&mut self, entity_id: EntityId) {
let entity = self.get_character(entity_id);
let life_arcs = entity.life_arcs.clone();
for (arc_name, current_state) in &life_arcs {
let arc = self.get_life_arc(arc_name);
let state_def = arc.get_state(current_state);
// Check if current state condition is still valid
if !self.evaluate_condition(entity_id, &state_def.condition) {
// State is invalid - find valid transition
for transition in &state_def.transitions {
if self.evaluate_condition(entity_id, &transition.condition) {
// Transition to new state
let entity = self.get_character_mut(entity_id);
entity.life_arcs.insert(arc_name.clone(), transition.to.clone());
// Log transition
println!(
"Entity {} transitioned: {}.{} -> {}.{}",
entity.name, arc_name, current_state, arc_name, transition.to
);
break;
}
}
}
}
}
}
```
**Re-evaluation algorithm:**
1. After action execution, check ALL life arcs for the affected entity
2. For each life arc, evaluate current state's `when` condition
3. If condition is FALSE, current state is invalid
4. Check state's transitions in order
5. Take first transition whose condition is TRUE
6. Update entity's life_arcs to new state
7. New state's capabilities are now available
**Design principle:** State follows data. When field values change, states automatically transition to match the new reality.
### Mental Model
**Think of entities as:**
- **Data**: Fields with values (age, skill_level, reputation)
- **State**: Current position in life arc state machines
- **Capability**: Behaviors available based on state + location + template
**Life arcs are NOT metadata - they ARE the state.**
When you ask "What can Martha do?", you're asking:
1. What state is she in? (Human.Adult, Baker.Master)
2. Where is she? (Bakery)
3. What does her template grant? (Baker template)
The answer is the intersection of capabilities from all three layers.
---
---
## Type System Soundness
### Type Theory Foundations
Storybook uses a **hybrid type system ** combining:
- **Nominal typing**: Templates and entities have explicit names and identity
- **Structural typing**: Life arc requirements use duck typing (any template with required fields)
- **Subtype polymorphism**: Template extension creates subtype relationships
- **Algebraic types**: Concepts and sub_concepts form sum types with pattern matching
### Subtyping Relationship
**Template extension creates subtyping:**
```storybook
species Human { strength: Number = 10 }
template Person: Human { age: Number }
template Baker: Person { skill_level: Number }
Type hierarchy:
Baker <: Person <: Human
```
**Liskov Substitution Principle:**
- Baker can be used wherever Person is expected (has all Person fields)
- Person can be used wherever Human is expected (has all Human fields)
- Subtyping flows from child to parent (upcast is implicit and safe)
**Action parameter compatibility:**
```storybook
action greet(person: Person)
character Martha: Baker
greet(Martha) // ✓ Valid - Baker <: Person (implicit upcast)
action train_baker(baker: Baker)
character Bob: Person
train_baker(Bob) // ✗ ERROR - Person </: Baker (not a subtype)
```
**No downcasting needed:**
All types are resolved at compile-time. The compiler knows the exact template type of each entity and validates action calls accordingly.
### Field Resolution Through Inheritance
**Override chain priority: Character > Template > Species**
```storybook
species Human { strength: Number = 10, speed: Number = 10 }
template Warrior: Human { strength: Number = 15 }
character Conan: Warrior { strength: 20 }
Field lookup algorithm:
Conan.strength:
1. Check character instance → 20 ✓ FOUND
2. (not reached)
Conan.speed:
1. Check character instance → not found
2. Check Warrior template → not found
3. Check Human species → 10 ✓ FOUND
```
**Type invariance through chain:**
- Field types cannot change through inheritance
- If species defines `strength: Number` , template cannot override to `strength: Text`
- Only values/defaults can be overridden, not types
### Life Arc Type Constraints
**Life arcs use structural requirements (duck typing):**
```storybook
life_arc Aging requires { age: Number, species: Species }
// Works with ANY template that has these fields
```
**Compile-time validation:**
```storybook
template Person: Human {
age: Number, // ✓ has required field
name: Text,
// species inherited from Human ✓ has required field
}
character Martha: Person {
life_arcs: {
Aging: Adult // ✓ Person has all required fields
}
}
// Compiler checks:
// 1. Does Person have field 'age' of type Number? YES
// 2. Does Person have field 'species' of type Species? YES (inherited)
// 3. Are types exact match (not subtypes)? YES
// → VALID
```
**Unsoundness prevention:**
```storybook
template Robot {
age?: Number // Optional field
}
life_arc Aging requires { age: Number } {
// Requires NON-optional age
}
character R2D2: Robot {
life_arcs: { Aging: Adult }
}
// ✗ TYPE ERROR: Aging requires age: Number (required)
// but Robot has age?: Number (optional)
// Required field cannot be optional in template
```
**Rule:** Life arc required fields MUST be non-optional in template.
### Behavior Type Checking
**Implicit self with template typing:**
```storybook
behavior BakingWork {
then {
check_orders // Desugars to: check_orders(self)
bake(Bread) // Desugars to: bake(self, Bread)
}
}
action check_orders(baker: Baker)
action bake(baker: Baker, item: Item)
```
**Type of implicit self:**
- `self` has the type of the entity's template
- Known at compile-time
**Compatibility checking:**
```storybook
character Martha: Baker {
uses behaviors: [BakingWork]
}
// Compiler validates:
// When Martha runs BakingWork:
// self: Baker (Martha's template)
// check_orders(self) → check_orders(Baker) ✓
// bake(self, Bread) → bake(Baker, Item) ✓
// → VALID
character Bob: Person {
uses behaviors: [BakingWork]
}
// Compiler validates:
// When Bob tries to run BakingWork:
// self: Person (Bob's template)
// check_orders(self) → check_orders(Person)
// But check_orders expects Baker
// Person </: Baker (not a subtype)
// → ERROR: Bob cannot use BakingWork
```
**Rule:** Entity can only use behaviors where all action calls are compatible with entity's template type (via exact match or subtyping).
### State Validation
**State conditions are contracts:**
```storybook
life_arc Baker requires { skill_level: Number } {
Master {
when skill_level >= 7 // Entry condition + runtime assertion
can use behaviors: [InnovateTechniques]
}
}
```
**The `when` clause serves two purposes:**
1. **Entry condition ** : Must be true to transition INTO this state
2. **Runtime assertion ** : Should be true while IN this state
**Potential inconsistency:**
```storybook
character Martha: Baker {
skill_level: 8,
life_arcs: { Baker: Master } // State says Master
}
action lower_skill(baker: Baker) {
baker.skill_level -= 5 // Now skill_level = 3
}
// After action: Martha is in Master state, but skill_level < 7
// State is inconsistent with data!
```
**Resolution - Hybrid approach:**
**Compile-time (Storybook):**
Emit warnings when actions could invalidate state conditions:
```
Warning: action 'lower_skill' modifies 'skill_level' which is used in
state condition for Baker.Master (requires skill_level >= 7).
Runtime should validate state before executing state-specific behaviors.
```
**Runtime (Implementation):**
Before executing behaviors that depend on state:
```rust
impl Runtime {
fn execute_behavior(&mut self, entity_id: EntityId, behavior: &Behavior) {
let character = self.get_character(entity_id);
// Validate current state conditions
for (arc_name, current_state) in &character.life_arcs {
let arc = self.get_life_arc(arc_name);
let state_def = arc.get_state(current_state);
if !self.evaluate_condition(entity_id, &state_def.condition) {
// State is inconsistent!
// Option A: Re-evaluate and transition to correct state
// Option B: Log warning and continue
// Option C: Throw error and reject behavior
// Runtime decides policy
}
}
// Execute behavior actions...
}
}
```
**Rule:** State conditions are validated at entry (transition time) and SHOULD be validated at execution time (runtime's responsibility).
### Type Checking Guarantees
**Compile-time guarantees:**
✅ Template subtyping is safe (Baker <: Person)
✅ Field access through inheritance is valid
✅ Life arc structural requirements are satisfied
✅ Action parameters match expected types
✅ Behaviors are compatible with entity templates
✅ Initial life arc states satisfy entry conditions
**Runtime responsibilities:**
⚠️ Validate state conditions before executing state-specific behaviors
⚠️ Handle state transitions when field values change
⚠️ Manage entity state consistency
**The language guarantees type safety at compile-time. The runtime guarantees state consistency at execution-time.**
### Formal Type Rules
**Subtyping (transitive):**
```
2026-02-16 22:55:04 +00:00
T modifies S
2026-02-14 13:29:33 +00:00
─────────────── (SUB-EXTEND)
T <: S
T <: S S <: R
─────────────── (SUB-TRANS)
T <: R
```
**Field access:**
```
E : T T has field f : τ (through inheritance chain)
──────────────────────────────────────────────────── (FIELD-ACCESS)
E.f : τ
```
**Life arc compatibility:**
```
T has fields {f1: τ1, ..., fn: τn} (required, non-optional)
L requires {f1: τ1, ..., fn: τn}
──────────────────────────────────────────────────── (LIFEARC-COMPAT)
T compatible with L
```
**Behavior validity:**
```
B calls actions {a1(Self, ...), ..., an(Self, ...)}
E : T
∀i. T <: ParamType(ai, 0) (template is subtype of first param)
──────────────────────────────────────────────────── (BEHAVIOR-VALID)
E can use behavior B
```
**Action call:**
```
a : (T1, T2, ..., Tn) → Unit
E : T T <: T1
args : (T2, ..., Tn)
──────────────────────────────────────────────────── (ACTION-CALL)
a(E, args) : Unit
```
### Summary
The type system is **sound ** with these properties:
- **Progress**: Well-typed programs don't get stuck at compile-time
- **Type preservation**: Types are maintained through inheritance and execution
- **Memory safety**: No invalid field access or type confusion
- **Subtype safety**: Upcasting (child → parent) is safe and implicit
The runtime must maintain **state consistency ** by validating life arc conditions at execution time.
---
## Future Considerations
feat(lang): rename concept_comparison to definition (v0.3.2)
Renames the `concept_comparison` keyword to `definition` across the
entire codebase for better readability and conciseness.
Changes:
- Tree-sitter grammar: `concept_comparison` node → `definition`
- Tree-sitter queries: highlights, outline, and indents updated
- Zed extension highlights.scm updated to match
- Lexer: `Token::ConceptComparison` → `Token::Definition`
- Parser: `ConceptComparisonDecl` rule → `DefinitionDecl`
- AST: `Declaration::ConceptComparison` → `Declaration::Definition`,
`ConceptComparisonDecl` struct → `DefinitionDecl`
- All Rust source files updated (validate, names, convert, references,
semantic_tokens, symbols, code_actions, hover, completion)
- `validate_concept_comparison_patterns` → `validate_definition_patterns`
- Example file and test corpus updated
- Spec docs: created SBIR-v0.3.2-SPEC.md, updated TYPE-SYSTEM.md,
README.md, SBIR-CHANGELOG.md, SBIR-v0.3.1-SPEC.md
2026-02-23 20:37:52 +00:00
- **Exhaustiveness checking**: Ensure all variant combinations are covered in definitions
2026-02-14 13:29:33 +00:00
- **Default variants**: Support for catch-all patterns in comparisons
- **Type inference**: Automatic parent concept detection beyond prefix matching
- **Generic concepts**: Parameterized types for reusable patterns
- **Constraint validation**: Runtime validation of type constraints