feat(type-system): implement concept_comparison with pattern matching

Added complete support for the new type system syntax including:

- concept: Base type declarations
- sub_concept: Enum and record sub-type definitions
- concept_comparison: Compile-time pattern matching with conditional guards

Parser changes:
- Added VariantPattern, FieldCondition, and Condition AST nodes
- Implemented "is" keyword for pattern matching (e.g., "CupType is Glass or CupType is Plastic")
- Added Value::Any variant to support universal type matching
- Disambiguated enum-like vs record-like sub_concept syntax

LSP updates:
- Added Value::Any match arms across code_actions, completion, hover, inlay_hints, and semantic_tokens
- Type inference and formatting support for Any values

Example fixes:
- Fixed syntax error in baker-family behaviors (missing closing brace in nested if)
- Removed deprecated core_enums.sb file
This commit is contained in:
2026-02-14 09:28:20 +00:00
parent 6e3b35e68f
commit 25d59d6107
30 changed files with 8639 additions and 6536 deletions

View File

@@ -5,7 +5,6 @@ use proptest::prelude::*;
use crate::{
resolve::convert::{
convert_character,
convert_enum,
convert_file,
},
syntax::ast::*,
@@ -98,16 +97,6 @@ fn valid_character() -> impl Strategy<Value = Character> {
})
}
fn valid_enum() -> impl Strategy<Value = EnumDecl> {
(valid_ident(), prop::collection::vec(valid_ident(), 1..10)).prop_map(|(name, variants)| {
EnumDecl {
name,
variants,
span: Span::new(0, 100),
}
})
}
// ===== Property Tests =====
proptest! {
@@ -142,26 +131,10 @@ proptest! {
}
}
#[test]
fn test_enum_name_preserved(enum_decl in valid_enum()) {
let original_name = enum_decl.name.clone();
let resolved = convert_enum(&enum_decl).unwrap();
assert_eq!(resolved.name, original_name);
}
#[test]
fn test_enum_variants_preserved(enum_decl in valid_enum()) {
let resolved = convert_enum(&enum_decl).unwrap();
assert_eq!(resolved.variants.len(), enum_decl.variants.len());
for (i, variant) in enum_decl.variants.iter().enumerate() {
assert_eq!(&resolved.variants[i], variant);
}
}
#[test]
fn test_convert_file_preserves_declaration_count(
characters in prop::collection::vec(valid_character(), 0..5),
enums in prop::collection::vec(valid_enum(), 0..5)
characters in prop::collection::vec(valid_character(), 0..5)
) {
// Ensure unique names across all declarations to avoid duplicate definition errors
let mut seen_names = std::collections::HashSet::new();
@@ -173,12 +146,6 @@ proptest! {
}
}
for enum_decl in enums {
if seen_names.insert(enum_decl.name.clone()) {
declarations.push(Declaration::Enum(enum_decl));
}
}
let file = File { declarations: declarations.clone() };
let resolved = convert_file(&file).unwrap();