@@ -165,6 +165,8 @@ def _sharpy_to_python(sharpy_code: str) -> str:
165165
166166 For basic features (phases 0.1.0-0.1.5), Sharpy is syntactically
167167 identical to Python, so minimal transformation is needed.
168+ Note: Classes, structs, enums, interfaces (0.1.6-0.1.10) may need
169+ additional conversion or skipping for Python verification.
168170 """
169171 lines = []
170172 for line in sharpy_code .split ("\n " ):
@@ -239,32 +241,69 @@ def _has_multi_arg_print(line: str) -> bool:
239241 return False
240242
241243
242- # Feature focuses for code generation - matched to phases 0.1.0-0.1.5
244+ # Feature focuses for code generation - matched to phases 0.1.0-0.1.10
243245# Each focus tests specific compiler functionality
244246FEATURE_FOCUSES = [
247+ # Phase 0.1.3: Variables & Expressions
245248 "integer_variables" , # x: int = 42
246249 "float_variables" , # y: float = 3.14
247250 "bool_variables" , # flag: bool = True
248- "arithmetic_operators" , # +, -, *, /, //, %
251+ "arithmetic_operators" , # +, -, *, /, //, %, **
249252 "comparison_operators" , # ==, !=, <, <=, >, >=
250253 "logical_operators" , # and, or, not
251254 "augmented_assignment" , # +=, -=, *=, /=
255+ # Phase 0.1.4: Control Flow
252256 "if_else_simple" , # basic if/else
253257 "if_elif_else" , # if/elif/else chains
254258 "while_loop" , # while with counter
255259 "for_range_single" , # for i in range(n)
256260 "for_range_start_end" , # for i in range(start, end)
257261 "for_range_with_step" , # for i in range(start, end, step)
258262 "break_continue" , # break/continue in loops
263+ # Phase 0.1.5: Functions
259264 "simple_function" , # def with parameters, return
260265 "function_with_print" , # function that prints values
261266 "function_calling_function" , # one function calls another
267+ "function_default_params" , # def foo(x: int, y: int = 5)
268+ "function_keyword_args" , # foo(x=10, y=20)
269+ # Phase 0.1.6: Classes
270+ "simple_class" , # class with fields
271+ "class_with_init" , # class with __init__
272+ "class_instance_methods" , # instance methods with self
273+ "class_static_methods" , # static methods (no self)
274+ "class_field_access" , # obj.field, self.field
275+ # Phase 0.1.7: Inheritance & Interfaces
276+ "class_inheritance" , # class Child(Parent)
277+ "super_init_call" , # super().__init__()
278+ "abstract_class" , # @abstract class
279+ "virtual_override" , # @virtual and @override methods
280+ "interface_definition" , # interface with method signatures
281+ "interface_implementation" , # class implements interface
282+ "access_modifiers" , # @private, @protected
283+ # Phase 0.1.8: Structs & Enums
284+ "struct_definition" , # struct with fields
285+ "enum_definition" , # enum with values
286+ "enum_usage" , # using enum values
287+ # Phase 0.1.9: Type System
288+ "nullable_types" , # T? syntax
289+ "null_coalescing" , # ?? operator
290+ "null_conditional" , # ?. operator
291+ "type_narrowing" , # if x is not None
292+ "type_alias" , # type UserId = int
293+ "generic_class" , # class Box[T]
294+ "generic_function" , # def foo[T](x: T) -> T
295+ # Phase 0.1.10: Module System
296+ "import_statement" , # import module
297+ "from_import" , # from module import item
298+ # Combinations
262299 "nested_if_in_loop" , # if inside for/while
263300 "loop_in_function" , # for/while inside function
301+ "class_with_loop" , # class with method using loop
302+ "inheritance_with_override" , # override methods with logic
264303]
265304
266305# Bias toward simpler tests initially - complex tests often hit unimplemented features
267- COMPLEXITY_LEVELS = ["simple" , "simple" , "medium" ] # 2/3 simple, 1/3 medium
306+ COMPLEXITY_LEVELS = ["simple" , "simple" , "simple" , "medium" , " medium" , "complex" ]
268307
269308
270309class DogfoodOrchestrator :
@@ -314,46 +353,42 @@ async def initialize(self) -> bool:
314353 def _load_example_snippets (self ) -> None :
315354 """Load example Sharpy snippets from the snippets directory.
316355
317- Filters to only include snippets that use features from phases 0.1.0-0.1.5.
356+ Filters to only include snippets that use features from phases 0.1.0-0.1.10.
357+ Excludes snippets with v0.1.11+ features like collections, comprehensions, etc.
318358 """
319359 snippets_dir = self .config .snippets_dir
320360 if not snippets_dir .exists ():
321361 return
322362
323- # Features that indicate code is beyond phases 0.1.0-0.1.5
363+ # Features that indicate code is beyond phases 0.1.0-0.1.10
364+ # (collections, comprehensions, exceptions, lambdas, .NET interop)
324365 forbidden_patterns = [
325- "class " ,
326- "struct " ,
327- "interface " ,
328- "import " ,
329- "from " ,
330366 "lambda" ,
331367 "try:" ,
332368 "except:" ,
333369 "raise " ,
334- 'f"' ,
335- "f'" ,
336- "= [" ,
337- "= {" ,
338- ": list" ,
339- ": dict" ,
340- ": set" ,
341- "-> list" ,
342- "-> dict" ,
343- "Optional[" ,
344- "?" , # nullable types
345- "@" , # decorators
370+ 'f"' , # f-strings (v0.1.11)
371+ "f'" , # f-strings (v0.1.11)
372+ "= [" , # list literals (v0.1.11)
373+ "= {" , # dict/set literals (v0.1.11)
374+ ": list[" , # list type (v0.1.11)
375+ ": dict[" , # dict type (v0.1.11)
376+ ": set[" , # set type (v0.1.11)
377+ "-> list[" , # list return type (v0.1.11)
378+ "-> dict[" , # dict return type (v0.1.11)
379+ "Optional[" , # Use T? instead
380+ "from system" , # .NET interop (v0.1.12)
381+ "from System" , # .NET interop (v0.1.12)
382+ " for " , # comprehensions (approximate check)
346383 ]
347384
348385 for spy_file in snippets_dir .glob ("*.spy" ):
349386 try :
350387 content = spy_file .read_text ()
351388 # Only include smaller snippets without forbidden features
352- if len (content ) < 400 :
353- content_lower = content .lower ()
389+ if len (content ) < 500 :
354390 has_forbidden = any (
355- pattern .lower () in content_lower
356- for pattern in forbidden_patterns
391+ pattern in content for pattern in forbidden_patterns
357392 )
358393 if not has_forbidden :
359394 self .example_snippets .append (content )
@@ -423,7 +458,7 @@ async def run_iteration(
423458 if prevalidation_error :
424459 print (f" Pre-validation failed: { prevalidation_error } " , file = sys .stderr )
425460 print (
426- " Skipping (generated code uses features beyond phases 0.1.0-0.1.5 )" ,
461+ " Skipping (generated code uses features beyond phases 0.1.0-0.1.10 )" ,
427462 file = sys .stderr ,
428463 )
429464 return IterationResult (
@@ -598,45 +633,45 @@ def _quick_prevalidate(self, code: str) -> Optional[str]:
598633
599634 Returns None if code passes, or an error message if it fails.
600635 This catches obvious issues before expensive AI validation.
636+
637+ Validates against phases 0.1.0-0.1.10 (excludes v0.1.11+ features).
601638 """
602639 import re
603640
604- # Patterns that indicate features beyond phases 0.1.0-0.1.5
641+ # Patterns that indicate features beyond phases 0.1.0-0.1.10
642+ # Note: Classes, structs, interfaces, enums, imports, decorators,
643+ # nullable types, default params, keyword args ARE allowed now
605644 forbidden_checks = [
606- (r'f"[^"]*\{' , "f-string interpolation" ),
607- (r"f'[^']*\{" , "f-string interpolation" ),
608- # Note: multi-argument print is checked separately with _has_multi_arg_print()
609- (r"def\s+\w+\s*\([^)]*=\s*[^,)]+" , "default parameter value" ),
610- (
611- r"\w+\s*=\s*\w+\s*\(" ,
612- None ,
613- ), # skip - this is just a function call assignment
614- (r"\(\s*\w+\s*=\s*" , "keyword argument" ),
615- (r"\bclass\s+\w+" , "class definition" ),
616- (r"\bstruct\s+\w+" , "struct definition" ),
617- (r"\binterface\s+\w+" , "interface definition" ),
618- (r"\bimport\s+" , "import statement" ),
619- (r"\bfrom\s+\w+\s+import" , "from import statement" ),
620- (r"\blambda\s*[^:]*:" , "lambda expression" ),
621- (r"\btry\s*:" , "try block" ),
622- (r"\bexcept\s*" , "except block" ),
623- (r"\braise\s+" , "raise statement" ),
624- (r"\bwith\s+" , "with statement" ),
625- (r"\basync\s+def" , "async function" ),
626- (r"\bawait\s+" , "await expression" ),
627- (r":\s*list\[" , "list type annotation" ),
628- (r":\s*dict\[" , "dict type annotation" ),
629- (r":\s*set\[" , "set type annotation" ),
630- (r":\s*\w+\?" , "nullable type annotation" ),
631- (r"->\s*\w+\?" , "nullable return type" ),
632- (r":\s*Optional\[" , "Optional type" ),
633- (r"\[\s*\]" , "empty list literal" ),
634- (r"\{\s*\}" , "empty dict/set literal" ),
635- (r"\[\s*\w+.*for\s+\w+\s+in" , "list comprehension" ),
636- (r"\{[^}]*for\s+\w+\s+in" , "dict/set comprehension" ),
637- (r"^\s*@\w+" , "decorator" ),
638- (r"\bx\s+if\s+.+\s+else\s+" , "ternary expression" ),
639- (r"\w+\s*,\s*\w+\s*=" , "tuple unpacking" ),
645+ # String features not yet supported
646+ (r'f"[^"]*\{' , "f-string interpolation (v0.1.11)" ),
647+ (r"f'[^']*\{" , "f-string interpolation (v0.1.11)" ),
648+ # Collections (v0.1.11)
649+ (r":\s*list\[" , "list type annotation (v0.1.11)" ),
650+ (r":\s*dict\[" , "dict type annotation (v0.1.11)" ),
651+ (r":\s*set\[" , "set type annotation (v0.1.11)" ),
652+ (r":\s*Optional\[" , "Optional type - use T? instead" ),
653+ (r"\[\s*\]" , "empty list literal (v0.1.11)" ),
654+ (r"\{\s*\}" , "empty dict/set literal (v0.1.11)" ),
655+ (r"\[\s*\w+.*for\s+\w+\s+in" , "list comprehension (v0.1.11)" ),
656+ (r"\{[^}]*for\s+\w+\s+in" , "dict/set comprehension (v0.1.11)" ),
657+ # Exception handling (v0.1.13)
658+ (r"\btry\s*:" , "try block (v0.1.13)" ),
659+ (r"\bexcept\s*" , "except block (v0.1.13)" ),
660+ (r"\braise\s+" , "raise statement (v0.1.13)" ),
661+ # Lambdas (v0.1.14)
662+ (r"\blambda\s*[^:]*:" , "lambda expression (v0.1.14)" ),
663+ # Async/await (deferred)
664+ (r"\basync\s+def" , "async function (deferred)" ),
665+ (r"\bawait\s+" , "await expression (deferred)" ),
666+ # Context managers (deferred)
667+ (r"\bwith\s+" , "with statement (deferred)" ),
668+ # Tuple unpacking
669+ (r"\w+\s*,\s*\w+\s*=" , "tuple unpacking (not supported)" ),
670+ # Ternary expression
671+ (r"\bx\s+if\s+.+\s+else\s+" , "ternary expression (not supported)" ),
672+ # .NET interop imports (v0.1.12)
673+ (r"\bfrom\s+system\s+import" , ".NET interop import (v0.1.12)" ),
674+ (r"\bfrom\s+System\s+import" , ".NET interop import (v0.1.12)" ),
640675 ]
641676
642677 lines = code .split ("\n " )
@@ -654,14 +689,6 @@ def _quick_prevalidate(self, code: str) -> Optional[str]:
654689 if description is None :
655690 continue
656691 if re .search (pattern , stripped ):
657- # Special case: skip "keyword argument" false positives for comparisons
658- if description == "keyword argument" :
659- # Check if it's actually a comparison or assignment in a function call
660- if re .search (r"\w+\s*==\s*" , stripped ):
661- continue
662- # Skip if it's a regular assignment (no parenthesis before =)
663- if not re .search (r"\([^)]*\w+\s*=\s*[^=]" , stripped ):
664- continue
665692 return f"Line { i } : { description } - '{ stripped [:50 ]} ...'"
666693
667694 return None
0 commit comments