77
88from abc import ABC , abstractmethod
99from dataclasses import dataclass
10- from typing import TYPE_CHECKING , Any , Callable , Dict , List , Optional , Set , Tuple , Union
10+ from typing import Any , Callable , Dict , List , Optional , Set , Tuple , Union
1111
1212from .target import (
1313 TargetExpr , Var , Lit , Symbol , Builtin , NamedFun , NewMessage , EnumValue , OneOf , ListExpr , Call , Lambda , Let ,
@@ -64,6 +64,7 @@ class CodeGenerator(ABC):
6464 def __init__ (self , proto_messages : Optional [Dict [Tuple [str , str ], Any ]] = None ) -> None :
6565 self .builtin_registry : Dict [str , BuiltinSpec ] = {}
6666 self .proto_messages = proto_messages or {}
67+ self ._generate_cache : Dict [type , Callable ] = {}
6768
6869 @abstractmethod
6970 def escape_keyword (self , name : str ) -> str :
@@ -401,81 +402,42 @@ def generate_lines(self, expr: TargetExpr, lines: List[str], indent: str = "") -
401402 Returns the value expression as a string, or None if the expression
402403 returns (i.e., contains a Return node that was executed).
403404 """
404- if isinstance (expr , Var ):
405- return self .escape_identifier (expr .name )
405+ t = type (expr )
406+ method = self ._generate_cache .get (t )
407+ if method is None :
408+ method = getattr (self , f'_generate_{ t .__name__ } ' , None )
409+ if method is None :
410+ raise ValueError (f"Unknown expression type: { t .__name__ } " )
411+ self ._generate_cache [t ] = method
412+ return method (expr , lines , indent )
406413
407- elif isinstance ( expr , Lit ) :
408- return self .gen_literal (expr .value )
414+ def _generate_Var ( self , expr : Var , lines : List [ str ], indent : str ) -> str :
415+ return self .escape_identifier (expr .name )
409416
410- elif isinstance ( expr , Symbol ) :
411- return self .gen_symbol (expr .name )
417+ def _generate_Lit ( self , expr : Lit , lines : List [ str ], indent : str ) -> str :
418+ return self .gen_literal (expr .value )
412419
413- elif isinstance ( expr , NewMessage ) :
414- return self ._generate_newmessage (expr , lines , indent )
420+ def _generate_Symbol ( self , expr : Symbol , lines : List [ str ], indent : str ) -> str :
421+ return self .gen_symbol (expr . name )
415422
416- elif isinstance ( expr , EnumValue ) :
417- return self ._generate_enum_value (expr , lines , indent )
423+ def _generate_Builtin ( self , expr : Builtin , lines : List [ str ], indent : str ) -> str :
424+ return self .gen_builtin_ref (expr . name )
418425
419- elif isinstance ( expr , Builtin ) :
420- return self .gen_builtin_ref (expr .name )
426+ def _generate_NamedFun ( self , expr : NamedFun , lines : List [ str ], indent : str ) -> str :
427+ return self .gen_named_fun_ref (expr .name )
421428
422- elif isinstance ( expr , NamedFun ) :
423- return self .gen_named_fun_ref (expr .name )
429+ def _generate_PrintNonterminal ( self , expr : PrintNonterminal , lines : List [ str ], indent : str ) -> str :
430+ return self .gen_pretty_nonterminal_ref (expr . nonterminal .name )
424431
425- elif isinstance ( expr , PrintNonterminal ) :
426- return self .gen_pretty_nonterminal_ref (expr .nonterminal .name )
432+ def _generate_ParseNonterminal ( self , expr : ParseNonterminal , lines : List [ str ], indent : str ) -> str :
433+ return self .gen_parse_nonterminal_ref (expr .nonterminal .name )
427434
428- elif isinstance (expr , ParseNonterminal ):
429- return self .gen_parse_nonterminal_ref (expr .nonterminal .name )
435+ def _generate_GetField (self , expr : GetField , lines : List [str ], indent : str ) -> str :
436+ obj_code = self .generate_lines (expr .object , lines , indent )
437+ assert obj_code is not None , "GetField object should not contain a return"
438+ return self .gen_field_access (obj_code , expr .field_name )
430439
431- elif isinstance (expr , OneOf ):
432- return self ._generate_oneof (expr , lines , indent )
433-
434- elif isinstance (expr , ListExpr ):
435- return self ._generate_list_expr (expr , lines , indent )
436-
437- elif isinstance (expr , GetField ):
438- obj_code = self .generate_lines (expr .object , lines , indent )
439- assert obj_code is not None , "GetField object should not contain a return"
440- return self .gen_field_access (obj_code , expr .field_name )
441-
442- elif isinstance (expr , GetElement ):
443- return self ._generate_get_element (expr , lines , indent )
444-
445- elif isinstance (expr , Call ):
446- return self ._generate_call (expr , lines , indent )
447-
448- elif isinstance (expr , Lambda ):
449- return self ._generate_lambda (expr , lines , indent )
450-
451- elif isinstance (expr , Let ):
452- return self ._generate_let (expr , lines , indent )
453-
454- elif isinstance (expr , IfElse ):
455- return self ._generate_if_else (expr , lines , indent )
456-
457- elif isinstance (expr , Seq ):
458- return self ._generate_seq (expr , lines , indent )
459-
460- elif isinstance (expr , While ):
461- return self ._generate_while (expr , lines , indent )
462-
463- elif isinstance (expr , Foreach ):
464- return self ._generate_foreach (expr , lines , indent )
465-
466- elif isinstance (expr , ForeachEnumerated ):
467- return self ._generate_foreach_enumerated (expr , lines , indent )
468-
469- elif isinstance (expr , Assign ):
470- return self ._generate_assign (expr , lines , indent )
471-
472- elif isinstance (expr , Return ):
473- return self ._generate_return (expr , lines , indent )
474-
475- else :
476- raise ValueError (f"Unknown expression type: { type (expr )} " )
477-
478- def _generate_call (self , expr : Call , lines : List [str ], indent : str ) -> Optional [str ]:
440+ def _generate_Call (self , expr : Call , lines : List [str ], indent : str ) -> Optional [str ]:
479441 """Generate code for a function call."""
480442 # NewMessage should be handled directly, not wrapped in Call
481443 assert not isinstance (expr .func , NewMessage ), \
@@ -567,7 +529,7 @@ def _generate_short_circuit_call(self, op: str, left: TargetExpr, right: TargetE
567529 lines .append (f"{ indent } { end } " )
568530 return tmp
569531
570- def _generate_newmessage (self , expr : NewMessage , lines : List [str ], indent : str ) -> str :
532+ def _generate_NewMessage (self , expr : NewMessage , lines : List [str ], indent : str ) -> str :
571533 """Generate code for a NewMessage expression.
572534
573535 Default implementation uses positional constructor args.
@@ -597,7 +559,7 @@ def _generate_newmessage(self, expr: NewMessage, lines: List[str], indent: str)
597559 lines .append (f"{ indent } { self .gen_assignment (tmp , call , is_declaration = True )} " )
598560 return tmp
599561
600- def _generate_get_element (self , expr : GetElement , lines : List [str ], indent : str ) -> str :
562+ def _generate_GetElement (self , expr : GetElement , lines : List [str ], indent : str ) -> str :
601563 """Generate code for a GetElement expression.
602564
603565 Default implementation uses 0-based indexing.
@@ -606,11 +568,11 @@ def _generate_get_element(self, expr: GetElement, lines: List[str], indent: str)
606568 tuple_code = self .generate_lines (expr .tuple_expr , lines , indent )
607569 return f"{ tuple_code } [{ expr .index } ]"
608570
609- def _generate_enum_value (self , expr : EnumValue , lines : List [str ], indent : str ) -> str :
571+ def _generate_EnumValue (self , expr : EnumValue , lines : List [str ], indent : str ) -> str :
610572 """Generate code for an enum value reference."""
611573 return self .gen_enum_value (expr .module , expr .enum_name , expr .value_name )
612574
613- def _generate_oneof (self , expr : OneOf , lines : List [str ], indent : str ) -> str :
575+ def _generate_OneOf (self , expr : OneOf , lines : List [str ], indent : str ) -> str :
614576 """Generate code for a OneOf expression.
615577
616578 Default implementation treats it as an error since OneOf should only
@@ -619,7 +581,7 @@ def _generate_oneof(self, expr: OneOf, lines: List[str], indent: str) -> str:
619581 """
620582 raise ValueError (f"OneOf should only appear as arguments to Message constructors: { expr } " )
621583
622- def _generate_list_expr (self , expr : ListExpr , lines : List [str ], indent : str ) -> str :
584+ def _generate_ListExpr (self , expr : ListExpr , lines : List [str ], indent : str ) -> str :
623585 """Generate code for a list expression."""
624586 elements : List [str ] = []
625587 for elem in expr .elements :
@@ -628,7 +590,7 @@ def _generate_list_expr(self, expr: ListExpr, lines: List[str], indent: str) ->
628590 elements .append (elem_code )
629591 return self .gen_list_literal (elements , expr .element_type )
630592
631- def _generate_lambda (self , expr : Lambda , lines : List [str ], indent : str ) -> str :
593+ def _generate_Lambda (self , expr : Lambda , lines : List [str ], indent : str ) -> str :
632594 """Generate code for a lambda expression."""
633595 params = [self .escape_identifier (p .name ) for p in expr .params ]
634596 f = gensym ()
@@ -648,15 +610,15 @@ def _generate_lambda(self, expr: Lambda, lines: List[str], indent: str) -> str:
648610 lines .append (f"{ indent } { after } " )
649611 return f
650612
651- def _generate_let (self , expr : Let , lines : List [str ], indent : str ) -> Optional [str ]:
613+ def _generate_Let (self , expr : Let , lines : List [str ], indent : str ) -> Optional [str ]:
652614 """Generate code for a let binding."""
653615 var_name = self .escape_identifier (expr .var .name )
654616 init_val = self .generate_lines (expr .init , lines , indent )
655617 assert init_val is not None , "Let initializer should not contain a return"
656618 lines .append (f"{ indent } { self .gen_assignment (var_name , init_val , is_declaration = True )} " )
657619 return self .generate_lines (expr .body , lines , indent )
658620
659- def _generate_if_else (self , expr : IfElse , lines : List [str ], indent : str ) -> Optional [str ]:
621+ def _generate_IfElse (self , expr : IfElse , lines : List [str ], indent : str ) -> Optional [str ]:
660622 """Generate code for an if-else expression."""
661623 cond_code = self .generate_lines (expr .condition , lines , indent )
662624 assert cond_code is not None , "If condition should not contain a return"
@@ -754,7 +716,7 @@ def _generate_nil_else_branch(
754716 lines .append (f"{ body_indent } { self .gen_assignment (tmp , else_code )} " )
755717 return else_code
756718
757- def _generate_seq (self , expr : Seq , lines : List [str ], indent : str ) -> Optional [str ]:
719+ def _generate_Seq (self , expr : Seq , lines : List [str ], indent : str ) -> Optional [str ]:
758720 """Generate code for a sequence of expressions.
759721
760722 If any expression returns None (indicating a return statement was executed),
@@ -767,7 +729,7 @@ def _generate_seq(self, expr: Seq, lines: List[str], indent: str) -> Optional[st
767729 break
768730 return result
769731
770- def _generate_while (self , expr : While , lines : List [str ], indent : str ) -> str :
732+ def _generate_While (self , expr : While , lines : List [str ], indent : str ) -> str :
771733 """Generate code for a while loop."""
772734 m = len (lines )
773735 cond_code = self .generate_lines (expr .condition , lines , indent )
@@ -796,7 +758,7 @@ def _generate_while(self, expr: While, lines: List[str], indent: str) -> str:
796758
797759 return self .gen_none ()
798760
799- def _generate_foreach (self , expr : Foreach , lines : List [str ], indent : str ) -> str :
761+ def _generate_Foreach (self , expr : Foreach , lines : List [str ], indent : str ) -> str :
800762 """Generate code for a foreach loop."""
801763 collection_code = self .generate_lines (expr .collection , lines , indent )
802764 assert collection_code is not None , "Foreach collection should not contain a return"
@@ -812,7 +774,7 @@ def _generate_foreach(self, expr: Foreach, lines: List[str], indent: str) -> str
812774
813775 return self .gen_none ()
814776
815- def _generate_foreach_enumerated (self , expr : ForeachEnumerated , lines : List [str ], indent : str ) -> str :
777+ def _generate_ForeachEnumerated (self , expr : ForeachEnumerated , lines : List [str ], indent : str ) -> str :
816778 """Generate code for a foreach enumerated loop."""
817779 collection_code = self .generate_lines (expr .collection , lines , indent )
818780 assert collection_code is not None , "ForeachEnumerated collection should not contain a return"
@@ -829,15 +791,15 @@ def _generate_foreach_enumerated(self, expr: ForeachEnumerated, lines: List[str]
829791
830792 return self .gen_none ()
831793
832- def _generate_assign (self , expr : Assign , lines : List [str ], indent : str ) -> str :
794+ def _generate_Assign (self , expr : Assign , lines : List [str ], indent : str ) -> str :
833795 """Generate code for an assignment."""
834796 var_name = self .escape_identifier (expr .var .name )
835797 expr_code = self .generate_lines (expr .expr , lines , indent )
836798 assert expr_code is not None , "Assignment expression should not contain a return"
837799 lines .append (f"{ indent } { self .gen_assignment (var_name , expr_code )} " )
838800 return self .gen_none ()
839801
840- def _generate_return (self , expr : Return , lines : List [str ], indent : str ) -> None :
802+ def _generate_Return (self , expr : Return , lines : List [str ], indent : str ) -> None :
841803 """Generate code for a return statement.
842804
843805 Returns None to indicate that the caller should not add another return
0 commit comments