@@ -721,22 +721,34 @@ def _compose_ifs(if_stmts: List[Dict[str, ast.AST]], orelse: List[ast.AST] = Non
721
721
orelse = Maybe (orelse ).or_else_get ([]))
722
722
723
723
724
- def _single_arity_fn_ast (ctx : CompilerContext , name : str , fndef : llist .List ) -> ASTStream :
724
+ def _fn_name (s : Optional [sym .Symbol ]) -> str :
725
+ """Generate a safe Python function name from a function name symbol.
726
+ If no symbol is provided, generate a name with a default prefix."""
727
+ return genname ("__" + munge (Maybe (s ).map (lambda s : s .name ).or_else_get (_FN_PREFIX )))
728
+
729
+
730
+ def _single_arity_fn_ast (ctx : CompilerContext , name : Optional [sym .Symbol ], fndef : llist .List ) -> ASTStream :
725
731
"""Generate Python AST nodes for a single-arity function."""
726
- with ctx .new_symbol_table (name ), ctx .new_recur_point (name , fndef .first ):
732
+ py_fn_name = _fn_name (name )
733
+ with ctx .new_symbol_table (py_fn_name ), ctx .new_recur_point (py_fn_name , fndef .first ):
734
+ # Allow named anonymous functions to recursively call themselves
735
+ if name is not None :
736
+ ctx .symbol_table .new_symbol (name , py_fn_name , _SYM_CTX_LOCAL )
737
+
727
738
args , body , vargs = _fn_args_body (ctx , fndef .first , fndef .rest )
728
739
729
- yield _dependency (_expressionize (body , name , args = args , vargs = vargs ))
740
+ yield _dependency (_expressionize (body , py_fn_name , args = args , vargs = vargs ))
730
741
if ctx .recur_point .has_recur :
731
742
yield _node (ast .Call (func = _TRAMPOLINE_FN_NAME ,
732
743
args = [ast .Name (id = ctx .recur_point .name , ctx = ast .Load ())],
733
744
keywords = []))
734
745
else :
735
- yield _node (ast .Name (id = name , ctx = ast .Load ()))
746
+ yield _node (ast .Name (id = py_fn_name , ctx = ast .Load ()))
736
747
return
737
748
738
749
739
- def _multi_arity_fn_ast (ctx : CompilerContext , name : str , arities : List [FunctionArityDetails ]) -> ASTStream :
750
+ def _multi_arity_fn_ast (ctx : CompilerContext , name : Optional [sym .Symbol ],
751
+ arities : List [FunctionArityDetails ]) -> ASTStream :
740
752
"""Generate Python AST nodes for multi-arity Basilisp function definitions.
741
753
742
754
For example, a multi-arity function like this:
@@ -774,14 +786,19 @@ def __f_68(*multi_arity_args):
774
786
775
787
776
788
f = __f_68"""
789
+ py_fn_name = _fn_name (name )
777
790
if_stmts : List [Dict [str , ast .AST ]] = []
778
791
multi_arity_args_arg = _load_attr (_MULTI_ARITY_ARG_NAME )
779
792
has_rest = False
780
793
781
794
for arg_count , is_rest , arity in arities :
782
- with ctx .new_recur_point (name , arity .first ):
795
+ with ctx .new_recur_point (py_fn_name , arity .first ):
796
+ # Allow named anonymous functions to recursively call themselves
797
+ if name is not None :
798
+ ctx .symbol_table .new_symbol (name , py_fn_name , _SYM_CTX_LOCAL )
799
+
783
800
has_rest = any ([has_rest , is_rest ])
784
- arity_name = f"{ name } __arity{ '_rest' if is_rest else arg_count } "
801
+ arity_name = f"{ py_fn_name } __arity{ '_rest' if is_rest else arg_count } "
785
802
786
803
with ctx .new_symbol_table (arity_name ):
787
804
# Generate the arity function
@@ -813,7 +830,7 @@ def __f_68(*multi_arity_args):
813
830
assert len (if_stmts ) == len (arities )
814
831
815
832
yield _dependency (ast .FunctionDef (
816
- name = name ,
833
+ name = py_fn_name ,
817
834
args = ast .arguments (
818
835
args = [],
819
836
kwarg = None ,
@@ -832,14 +849,14 @@ def __f_68(*multi_arity_args):
832
849
decorator_list = [],
833
850
returns = None ))
834
851
835
- yield _node (ast .Name (id = name , ctx = ast .Load ()))
852
+ yield _node (ast .Name (id = py_fn_name , ctx = ast .Load ()))
836
853
837
854
838
855
def _fn_ast (ctx : CompilerContext , form : llist .List ) -> ASTStream :
839
856
"""Generate a Python AST Nodes for function definitions."""
840
857
assert form .first == _FN
841
858
has_name = isinstance (form [1 ], sym .Symbol )
842
- name = genname ( "__" + ( munge ( form [1 ]. name ) if has_name else _FN_PREFIX ))
859
+ name = form [1 ] if has_name else None
843
860
844
861
rest_idx = 1 + int (has_name )
845
862
arities = list (_fn_arities (ctx , form [rest_idx :]))
0 commit comments