@@ -473,6 +473,18 @@ def gen_builtin_call(
473473 return spec .generator (args , lines , indent )
474474 return None
475475
476+ # --- Beta reduction hooks ---
477+
478+ def _enter_beta_body (self , lam : Lambda ) -> None :
479+ """Called before evaluating a beta-reduced lambda body.
480+
481+ Subclasses can override to set up type context (e.g., Go's
482+ lambda return type stack for IfElse type hints).
483+ """
484+
485+ def _exit_beta_body (self , lam : Lambda ) -> None :
486+ """Called after evaluating a beta-reduced lambda body."""
487+
476488 # --- Type-based expression classification ---
477489
478490 @staticmethod
@@ -585,6 +597,24 @@ def _generate_Call(self, expr: Call, lines: list[str], indent: str) -> str | Non
585597 return None
586598 return result .value
587599
600+ # Beta reduction: inline lambda calls instead of emitting closures.
601+ # Call(Lambda([p1, ...], body), [a1, ...]) => assign args to params, eval body.
602+ if isinstance (expr .func , Lambda ) and len (expr .func .params ) == len (expr .args ):
603+ for param , arg in zip (expr .func .params , expr .args ):
604+ arg_code = self .generate_lines (arg , lines , indent )
605+ assert arg_code is not None , (
606+ "Function argument should not contain a return"
607+ )
608+ param_name = self .escape_identifier (param .name )
609+ lines .append (
610+ f"{ indent } { self .gen_assignment (param_name , arg_code , is_declaration = True )} "
611+ )
612+ self ._enter_beta_body (expr .func )
613+ try :
614+ return self .generate_lines (expr .func .body , lines , indent )
615+ finally :
616+ self ._exit_beta_body (expr .func )
617+
588618 # Regular call
589619 f = self .generate_lines (expr .func , lines , indent )
590620 assert f is not None , "Function expression should not contain a return"
@@ -886,17 +916,56 @@ def _generate_nil_else_branch(
886916 lines .append (f"{ body_indent } { self .gen_assignment (tmp , else_code )} " )
887917 return else_code
888918
919+ @staticmethod
920+ def _extract_write_io_literal (expr : TargetExpr ) -> str | None :
921+ """If expr is Call(Builtin("write_io"), [Lit(s)]), return s."""
922+ if (
923+ isinstance (expr , Call )
924+ and isinstance (expr .func , Builtin )
925+ and expr .func .name == "write_io"
926+ and len (expr .args ) == 1
927+ and isinstance (expr .args [0 ], Lit )
928+ and isinstance (expr .args [0 ].value , str )
929+ ):
930+ return expr .args [0 ].value
931+ return None
932+
933+ def _flush_write_io_literals (
934+ self , strings : list [str ], lines : list [str ], indent : str
935+ ) -> None :
936+ """Emit a single write_io call for a run of string literals."""
937+ merged = "" .join (strings )
938+ merged_str = self .gen_string (merged )
939+ result = self .gen_builtin_call ("write_io" , [merged_str ], lines , indent )
940+ if result is not None :
941+ for stmt in result .statements :
942+ lines .append (f"{ indent } { stmt } " )
943+
889944 def _generate_Seq (self , expr : Seq , lines : list [str ], indent : str ) -> str | None :
890945 """Generate code for a sequence of expressions.
891946
892947 If any expression returns None (indicating a return statement was executed),
893948 stop processing and propagate None (subsequent expressions are unreachable).
949+
950+ Consecutive write_io calls with string literal arguments are merged into
951+ a single call with the concatenated string.
894952 """
895953 result : str | None = self .gen_none ()
954+ pending_writes : list [str ] = []
896955 for e in expr .exprs :
956+ write_str = self ._extract_write_io_literal (e )
957+ if write_str is not None :
958+ pending_writes .append (write_str )
959+ result = self .gen_none ()
960+ continue
961+ if pending_writes :
962+ self ._flush_write_io_literals (pending_writes , lines , indent )
963+ pending_writes .clear ()
897964 result = self .generate_lines (e , lines , indent )
898965 if result is None :
899966 break
967+ if pending_writes :
968+ self ._flush_write_io_literals (pending_writes , lines , indent )
900969 return result
901970
902971 def _generate_While (self , expr : While , lines : list [str ], indent : str ) -> str :
0 commit comments