Skip to content

Commit 8846c2c

Browse files
antonsyndclaude
andcommitted
feat: update dogfood prompts for newer language features and weighted sampling
Add properties, tuple unpacking, spread operators, walrus operator, pattern matching, with statement, named tuples, and comparison chaining to the allowed features in dogfood prompts. Remove these from the forbidden list and update prevalidation/Python-verification skip lists. Restructure feature focuses into 3 weighted tiers (basics 15%, intermediate 35%, advanced 50%) so dogfooding prioritizes less-covered features. Shift complexity bias toward medium/complex. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1a3035d commit 8846c2c

File tree

3 files changed

+329
-142
lines changed

3 files changed

+329
-142
lines changed

build_tools/sharpy_dogfood/convert.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,35 @@ def get_category_from_feature(feature_focus: Optional[str]) -> str:
183183
# Containment & Tuple Types
184184
"containment_test": "collections",
185185
"tuple_types": "type_system",
186+
# Properties
187+
"auto_property": "properties",
188+
"function_style_property": "properties",
189+
"property_inheritance": "properties",
190+
"property_with_validation": "properties",
191+
# Tuple Unpacking & Star Patterns
192+
"tuple_unpacking_assignment": "expressions",
193+
"tuple_unpacking_nested": "expressions",
194+
"star_unpacking": "expressions",
195+
# Spread Operators
196+
"spread_list": "collections",
197+
"spread_dict": "collections",
198+
"spread_set": "collections",
199+
"spread_call": "expressions",
200+
"spread_with_comprehension": "collections",
201+
# Walrus Operator
202+
"walrus_operator": "expressions",
203+
# Pattern Matching
204+
"match_literal": "pattern_matching",
205+
"match_type_binding": "pattern_matching",
206+
"match_wildcard": "pattern_matching",
207+
"match_guard": "pattern_matching",
208+
"match_with_enum": "pattern_matching",
209+
# Context Managers
210+
"with_statement": "with_statement",
211+
# Named Tuples
212+
"named_tuple": "named_tuples",
213+
# Comparison Chaining
214+
"comparison_chaining": "type_system",
186215
}
187216

188217
return category_map.get(feature_focus, "misc")

build_tools/sharpy_dogfood/orchestrator.py

Lines changed: 172 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ async def _verify_expected_with_python(
233233
"str?",
234234
"float?",
235235
"bool?",
236+
"property ", # Sharpy properties (auto or function-style)
237+
"property get ",
238+
"property set ",
239+
"property init ",
240+
"with ", # Sharpy with statement uses IDisposable, not Python __enter__/__exit__
241+
"from System", # .NET interop imports
242+
"from system",
243+
"type ", # Named tuple type aliases (type Point = tuple[x: ...])
236244
]
237245
if any(feature in code for feature in sharpy_only_features):
238246
return True, None, "Sharpy-specific features - skipping Python verification"
@@ -397,116 +405,172 @@ def _replace_expected_output_in_code(code: str, new_output: str) -> str:
397405
return result
398406

399407

400-
# Feature focuses for code generation - matched to phases 0.1.0-0.1.18
401-
# Each focus tests specific compiler functionality
402-
FEATURE_FOCUSES = [
403-
# Phase 0.1.3: Variables & Expressions
404-
"integer_variables", # x: int = 42
405-
"float_variables", # y: float = 3.14
406-
"bool_variables", # flag: bool = True
407-
"arithmetic_operators", # +, -, *, /, //, %, **
408-
"comparison_operators", # ==, !=, <, <=, >, >=
409-
"logical_operators", # and, or, not
410-
"augmented_assignment", # +=, -=, *=, /=
411-
# Phase 0.1.4: Control Flow
412-
"if_else_simple", # basic if/else
413-
"if_elif_else", # if/elif/else chains
414-
"while_loop", # while with counter
415-
"for_range_single", # for i in range(n)
416-
"for_range_start_end", # for i in range(start, end)
417-
"for_range_with_step", # for i in range(start, end, step)
418-
"break_continue", # break/continue in loops
419-
# Phase 0.1.5: Functions
420-
"simple_function", # def with parameters, return
421-
"function_with_print", # function that prints values
422-
"function_calling_function", # one function calls another
423-
"function_default_params", # def foo(x: int, y: int = 5)
424-
"function_keyword_args", # foo(x=10, y=20)
425-
# Phase 0.1.6: Classes
426-
"simple_class", # class with fields
427-
"class_with_init", # class with __init__
428-
"class_instance_methods", # instance methods with self
429-
"class_static_methods", # static methods (no self)
430-
"class_field_access", # obj.field, self.field
431-
# Phase 0.1.7: Inheritance & Interfaces
432-
"class_inheritance", # class Child(Parent)
433-
"super_init_call", # super().__init__()
434-
"abstract_class", # @abstract class
435-
"virtual_override", # @virtual and @override methods
436-
"interface_definition", # interface with method signatures
437-
"interface_implementation", # class implements interface
438-
"access_modifiers", # @private, @protected
439-
# Phase 0.1.8: Structs & Enums
440-
"struct_definition", # struct with fields
441-
"enum_definition", # enum with values
442-
"enum_usage", # using enum values
443-
# Phase 0.1.9: Type System
444-
"nullable_types", # T? syntax
445-
"null_coalescing", # ?? operator
446-
"null_conditional", # ?. operator
447-
"type_narrowing", # if x is not None
448-
"type_alias", # type UserId = int
449-
"generic_class", # class Box[T]
450-
"generic_function", # def foo[T](x: T) -> T
451-
# Phase 0.1.10: Module System
452-
"import_statement", # import module
453-
"from_import", # from module import item
454-
# Phase 0.1.11: F-Strings & Collections
455-
"f_string_basic", # f"Hello {name}"
456-
"f_string_expressions", # f"Result: {x + y}"
457-
"list_literal", # [1, 2, 3]
458-
"dict_literal", # {"key": value}
459-
"set_literal", # {1, 2, 3}
460-
"list_comprehension", # [x * 2 for x in range(10)]
461-
"dict_comprehension", # {k: v for k, v in items}
462-
"set_comprehension", # {x for x in items}
463-
"collection_iteration", # for item in collection
464-
"collection_methods", # .add(), .remove(), len()
465-
# Phase 0.1.12: .NET Interop
466-
"dotnet_import", # from system import Console
467-
"dotnet_type_usage", # using .NET types
468-
# Phase 0.1.13: Exception Handling
469-
"try_except_basic", # try/except
470-
"try_except_finally", # try/except/finally
471-
"try_except_else", # try/except/else/finally
472-
"raise_exception", # raise ValueError()
473-
# Phase 0.1.14: Lambda Expressions
474-
"lambda_basic", # lambda x: x * 2
475-
"lambda_multiarg", # lambda a, b: a + b
476-
"higher_order_function", # passing lambdas
477-
# Phase 0.1.15-0.1.18: Optional & Result Types
478-
"optional_type", # T?, Some(x), None()
479-
"optional_unwrap", # .unwrap(), .unwrap_or(), .map()
480-
"result_type", # T !E, Ok(x), Err(e)
481-
"result_unwrap", # .unwrap(), .unwrap_or(), .map()
482-
"maybe_expression", # maybe expr — T | None → T?
483-
"try_expression", # try expr — wraps in Result[T, E]
484-
"lambda_type_inference", # lambda params inferred from context
408+
# Feature focuses organized into tiers by coverage maturity.
409+
# Tier 1 (basics) — well-covered by existing test fixtures, sampled less often.
410+
# Tier 2 (intermediate) — moderate coverage, standard sampling.
411+
# Tier 3 (advanced/newer) — least covered, sampled most often.
412+
413+
_TIER1_BASICS: list[str] = [
414+
# Phase 0.1.3: Variables & Expressions — extensively covered
415+
"integer_variables",
416+
"float_variables",
417+
"bool_variables",
418+
"arithmetic_operators",
419+
"comparison_operators",
420+
"logical_operators",
421+
"augmented_assignment",
422+
# Phase 0.1.4: Control Flow — extensively covered
423+
"if_else_simple",
424+
"if_elif_else",
425+
"while_loop",
426+
"for_range_single",
427+
"for_range_start_end",
428+
"for_range_with_step",
429+
"break_continue",
430+
# Phase 0.1.5: Functions — extensively covered
431+
"simple_function",
432+
"function_with_print",
433+
"function_calling_function",
434+
"function_default_params",
435+
"function_keyword_args",
436+
# Phase 0.1.6: Basic Classes — extensively covered
437+
"simple_class",
438+
"class_with_init",
439+
"class_instance_methods",
440+
"class_static_methods",
441+
"class_field_access",
442+
]
443+
444+
_TIER2_INTERMEDIATE: list[str] = [
445+
# Inheritance & Interfaces
446+
"class_inheritance",
447+
"super_init_call",
448+
"abstract_class",
449+
"virtual_override",
450+
"interface_definition",
451+
"interface_implementation",
452+
"access_modifiers",
453+
# Structs & Enums
454+
"struct_definition",
455+
"enum_definition",
456+
"enum_usage",
457+
# Type System
458+
"nullable_types",
459+
"null_coalescing",
460+
"null_conditional",
461+
"type_narrowing",
462+
"type_alias",
463+
"generic_class",
464+
"generic_function",
465+
# Module System
466+
"import_statement",
467+
"from_import",
468+
# F-Strings & Collections
469+
"f_string_basic",
470+
"f_string_expressions",
471+
"list_literal",
472+
"dict_literal",
473+
"set_literal",
474+
"list_comprehension",
475+
"dict_comprehension",
476+
"set_comprehension",
477+
"collection_iteration",
478+
"collection_methods",
479+
# .NET Interop
480+
"dotnet_import",
481+
"dotnet_type_usage",
482+
# Exception Handling
483+
"try_except_basic",
484+
"try_except_finally",
485+
"try_except_else",
486+
"raise_exception",
487+
# Lambda Expressions
488+
"lambda_basic",
489+
"lambda_multiarg",
490+
"higher_order_function",
491+
"lambda_type_inference",
485492
# Dunder Methods
486-
"dunder_str", # __str__() method
487-
"dunder_eq_hash", # __eq__() + __hash__() pair
488-
"dunder_bool", # __bool__() for truthiness
489-
"dunder_len", # __len__() + len() builtin
490-
"dunder_iter", # __iter__() + __next__() iterator protocol
491-
"dunder_operators", # __add__(), __sub__(), __mul__(), __div__(), __mod__(), plus bitwise
492-
"dunder_comparison", # __lt__(), __le__(), __gt__(), __ge__(), __ne__()
493-
"dunder_unary", # __neg__(), __pos__(), __invert__()
494-
# Additional Builtins
495-
"builtin_conversions", # int(), float(), bool(), str()
496-
"builtin_aggregation", # min(), max(), sum()
497-
"builtin_higher_order", # sorted(), filter(), map(), enumerate(), zip()
498-
# Containment & Tuple Types
499-
"containment_test", # x in collection, x not in collection
500-
"tuple_types", # tuple[int, str], tuple unpacking in for loops
501-
# Combinations
502-
"nested_if_in_loop", # if inside for/while
503-
"loop_in_function", # for/while inside function
504-
"class_with_loop", # class with method using loop
505-
"inheritance_with_override", # override methods with logic
493+
"dunder_str",
494+
"dunder_eq_hash",
495+
"dunder_bool",
496+
"dunder_len",
497+
"dunder_iter",
498+
"dunder_operators",
499+
"dunder_comparison",
500+
"dunder_unary",
501+
# Builtins
502+
"builtin_conversions",
503+
"builtin_aggregation",
504+
"builtin_higher_order",
505+
"containment_test",
506+
"tuple_types",
506507
]
507508

508-
# Bias toward simpler tests initially - complex tests often hit unimplemented features
509-
COMPLEXITY_LEVELS = ["simple", "simple", "simple", "medium", "medium", "complex"]
509+
_TIER3_ADVANCED: list[str] = [
510+
# Optional & Result Types
511+
"optional_type",
512+
"optional_unwrap",
513+
"result_type",
514+
"result_unwrap",
515+
"maybe_expression",
516+
"try_expression",
517+
# Properties
518+
"auto_property",
519+
"function_style_property",
520+
"property_inheritance",
521+
# Tuple Unpacking & Star Patterns
522+
"tuple_unpacking_assignment",
523+
"tuple_unpacking_nested",
524+
"star_unpacking",
525+
# Spread Operators
526+
"spread_list",
527+
"spread_dict",
528+
"spread_set",
529+
"spread_call",
530+
# Walrus Operator
531+
"walrus_operator",
532+
# Pattern Matching
533+
"match_literal",
534+
"match_type_binding",
535+
"match_wildcard",
536+
"match_guard",
537+
# Context Managers
538+
"with_statement",
539+
# Named Tuples
540+
"named_tuple",
541+
# Comparison Chaining
542+
"comparison_chaining",
543+
# Feature Combinations (advanced)
544+
"nested_if_in_loop",
545+
"loop_in_function",
546+
"class_with_loop",
547+
"inheritance_with_override",
548+
"property_with_validation",
549+
"match_with_enum",
550+
"spread_with_comprehension",
551+
]
552+
553+
# Flat list for backward compatibility (e.g. category mapping lookups).
554+
FEATURE_FOCUSES = _TIER1_BASICS + _TIER2_INTERMEDIATE + _TIER3_ADVANCED
555+
556+
# Tier weights: how likely each tier is to be sampled.
557+
# Tier 3 (advanced/newer) gets ~50%, Tier 2 ~35%, Tier 1 ~15%.
558+
_TIER_WEIGHTS: list[float] = [0.15, 0.35, 0.50]
559+
_TIERS: list[list[str]] = [_TIER1_BASICS, _TIER2_INTERMEDIATE, _TIER3_ADVANCED]
560+
561+
562+
def pick_feature_focus() -> str:
563+
"""Select a feature focus with weighted tier sampling.
564+
565+
Newer/less-covered features (tier 3) are chosen ~50% of the time,
566+
intermediate features ~35%, and well-covered basics ~15%.
567+
"""
568+
tier = random.choices(_TIERS, weights=_TIER_WEIGHTS, k=1)[0]
569+
return random.choice(tier)
570+
571+
572+
# Bias toward medium/complex — basics are well-covered by existing fixtures.
573+
COMPLEXITY_LEVELS = ["simple", "medium", "medium", "medium", "complex", "complex"]
510574

511575

512576
class DogfoodOrchestrator:
@@ -617,8 +681,6 @@ def _load_example_snippets(self) -> None:
617681
forbidden_patterns = [
618682
"async def", # Not implemented
619683
"await ", # Not implemented
620-
" with ", # Context managers not implemented
621-
":=", # Walrus operator not implemented
622684
]
623685

624686
for spy_file in snippets_dir.glob("*.spy"):
@@ -1744,23 +1806,6 @@ async def _quick_prevalidate(self, code: str) -> Optional[str]:
17441806
return f"Line {j + 1}: @abstract and @virtual combined (abstract methods are inherently virtual — use only @abstract)"
17451807
break # Stop at first non-empty, non-decorator line
17461808

1747-
# Regex-only checks for things the lexer doesn't cover as keyword tokens
1748-
forbidden_regex_checks = [
1749-
# Walrus operator (not implemented) - operator token, not keyword
1750-
(r":=", "walrus operator (not implemented)"),
1751-
# Tuple unpacking (may have issues)
1752-
# Anchored to line start to avoid matching keyword arguments
1753-
(r"^\w+\s*,\s*\w+\s*=[^=]", "tuple unpacking (not fully supported)"),
1754-
]
1755-
1756-
for i, line in enumerate(lines, 1):
1757-
stripped = line.split("#")[0].strip()
1758-
if not stripped:
1759-
continue
1760-
for pattern, description in forbidden_regex_checks:
1761-
if re.search(pattern, stripped):
1762-
return f"Line {i}: {description} - '{stripped[:50]}...'"
1763-
17641809
return None
17651810

17661811
async def _check_forbidden_tokens_via_lexer(self, code: str) -> Optional[str]:
@@ -1773,10 +1818,8 @@ async def _check_forbidden_tokens_via_lexer(self, code: str) -> Optional[str]:
17731818

17741819
# Forbidden token types that indicate unimplemented features
17751820
forbidden_tokens = {
1776-
"With": "with statement (not implemented)",
17771821
"Async": "async function (not implemented)",
17781822
"Await": "await expression (not implemented)",
1779-
"Match": "pattern matching (not implemented)",
17801823
}
17811824

17821825
try:
@@ -1963,7 +2006,7 @@ async def run(self, iterations: Optional[int] = None) -> int:
19632006
) # Multi-file is at least medium
19642007
else:
19652008
# Regular single-file iteration
1966-
feature_focus = random.choice(FEATURE_FOCUSES)
2009+
feature_focus = pick_feature_focus()
19672010
complexity = random.choice(COMPLEXITY_LEVELS)
19682011

19692012
start_time = datetime.now()

0 commit comments

Comments
 (0)