@@ -657,37 +657,6 @@ def _def_to_py_ast( # pylint: disable=too-many-branches
657
657
assert node .op == NodeOp .DEF
658
658
659
659
defsym = node .name
660
- is_defn = False
661
- is_var_bound = node .var .is_bound
662
- is_noop_redef_of_bound_var = is_var_bound and node .init is None
663
-
664
- if node .init is not None :
665
- # Since Python function definitions always take the form `def name(...):`,
666
- # it is redundant to assign them to the their final name after they have
667
- # been defined under a private alias. This codepath generates `defn`
668
- # declarations by directly generating the Python `def` with the correct
669
- # function name and short-circuiting the default double-declaration.
670
- if node .init .op == NodeOp .FN :
671
- assert isinstance (node .init , Fn )
672
- def_ast : Optional [GeneratedPyAST ] = _fn_to_py_ast ( # type: ignore[call-arg]
673
- ctx , node .init , def_name = defsym .name
674
- )
675
- is_defn = True
676
- elif (
677
- node .init .op == NodeOp .WITH_META
678
- and isinstance (node .init , WithMeta )
679
- and node .init .expr .op == NodeOp .FN
680
- ):
681
- assert isinstance (node .init , WithMeta )
682
- def_ast = _with_meta_to_py_ast (ctx , node .init , def_name = defsym .name )
683
- is_defn = True
684
- else :
685
- def_ast = gen_py_ast (ctx , node .init )
686
- elif is_noop_redef_of_bound_var :
687
- def_ast = None
688
- else :
689
- def_ast = GeneratedPyAST (node = ast .Constant (None ))
690
-
691
660
ns_name = _load_attr (_NS_VAR_VALUE )
692
661
def_name = ast .Call (
693
662
func = _NEW_SYM_FN_NAME , args = [ast .Constant (defsym .name )], keywords = []
@@ -709,74 +678,79 @@ def _def_to_py_ast( # pylint: disable=too-many-branches
709
678
710
679
# Warn if this symbol is potentially being redefined (if the Var was
711
680
# previously bound)
712
- if is_var_bound and __should_warn_on_redef (ctx , defsym , safe_name , def_meta ):
681
+ if node . var . is_bound and __should_warn_on_redef (ctx , defsym , safe_name , def_meta ):
713
682
logger .warning (
714
683
f"redefining local Python name '{ safe_name } ' in module "
715
684
f"'{ ctx .current_ns .module .__name__ } ' ({ node .env .ns } :{ node .env .line } )"
716
685
)
717
686
718
- meta_ast = gen_py_ast (ctx , node .meta )
719
-
720
- # For defn style def generation, we specifically need to generate the
721
- # global declaration prior to emitting the Python `def` otherwise the
722
- # Python compiler will throw an exception during compilation
723
- # complaining that we assign the value prior to global declaration.
724
- if is_defn :
725
- assert def_ast is not None , "def_ast must be defined at this point"
726
- def_dependencies = list (
727
- chain (
728
- [] if node .top_level else [ast .Global (names = [safe_name ])],
729
- def_ast .dependencies ,
730
- [] if meta_ast is None else meta_ast .dependencies ,
687
+ if node .init is not None :
688
+ # Since Python function definitions always take the form `def name(...):`,
689
+ # it is redundant to assign them to the their final name after they have
690
+ # been defined under a private alias. This codepath generates `defn`
691
+ # declarations by directly generating the Python `def` with the correct
692
+ # function name and short-circuiting the default double-declaration.
693
+ assert node .init is not None # silence MyPy
694
+ if node .init .op == NodeOp .FN :
695
+ assert isinstance (node .init , Fn )
696
+ def_ast = _fn_to_py_ast ( # type: ignore[call-arg]
697
+ ctx , node .init , def_name = defsym .name
731
698
)
732
- )
733
- elif is_noop_redef_of_bound_var :
734
- # Re-def-ing previously bound Vars without providing a value is
735
- # essentially a no-op, which should not modify the Var root.
736
- assert def_ast is None , "def_ast is not defined at this point"
737
- def_dependencies = list (
738
- chain (
739
- [] if node .top_level else [ast .Global (names = [safe_name ])],
740
- [] if meta_ast is None else meta_ast .dependencies ,
699
+ is_defn = True
700
+ elif (
701
+ node .init .op == NodeOp .WITH_META
702
+ and isinstance (node .init , WithMeta )
703
+ and node .init .expr .op == NodeOp .FN
704
+ ):
705
+ assert isinstance (node .init , WithMeta )
706
+ def_ast = _with_meta_to_py_ast (ctx , node .init , def_name = defsym .name )
707
+ is_defn = True
708
+ else :
709
+ def_ast = gen_py_ast (ctx , node .init )
710
+ is_defn = False
711
+
712
+ func = _INTERN_VAR_FN_NAME
713
+ extra_args = [ast .Name (id = safe_name , ctx = ast .Load ())]
714
+ if is_defn :
715
+ # For defn style def generation, we specifically need to generate
716
+ # the global declaration prior to emitting the Python `def` otherwise
717
+ # the Python compiler will throw an exception during compilation
718
+ # complaining that we assign the value prior to global declaration.
719
+ def_dependencies = list (
720
+ chain (
721
+ [ast .Global (names = [safe_name ])] if node .in_func_ctx else [],
722
+ def_ast .dependencies ,
723
+ )
741
724
)
742
- )
743
- else :
744
- assert def_ast is not None , "def_ast must be defined at this point"
745
- def_dependencies = list (
746
- chain (
747
- def_ast .dependencies ,
748
- [] if node .top_level else [ast .Global (names = [safe_name ])],
749
- [
750
- ast .Assign (
751
- targets = [ast .Name (id = safe_name , ctx = ast .Store ())],
752
- value = def_ast .node ,
753
- )
754
- ],
755
- [] if meta_ast is None else meta_ast .dependencies ,
725
+ else :
726
+ def_dependencies = list (
727
+ chain (
728
+ def_ast .dependencies ,
729
+ [ast .Global (names = [safe_name ])] if node .in_func_ctx else [],
730
+ [
731
+ ast .Assign (
732
+ targets = [ast .Name (id = safe_name , ctx = ast .Store ())],
733
+ value = def_ast .node ,
734
+ )
735
+ ],
736
+ )
756
737
)
757
- )
738
+ else :
739
+ # Callers can either `(def v)` to declare an unbound Var or they
740
+ # can redef a bound Var with no init value to fetch a reference
741
+ # to the var. Re-def-ing previously bound Vars without providing
742
+ # a value is essentially a no-op, which should not modify the Var
743
+ # root.
744
+ func = _INTERN_UNBOUND_VAR_FN_NAME
745
+ extra_args = []
746
+ def_dependencies = [ast .Global (names = [safe_name ])] if node .in_func_ctx else []
758
747
759
- if is_noop_redef_of_bound_var :
760
- return GeneratedPyAST (
761
- node = ast .Call (
762
- func = _INTERN_UNBOUND_VAR_FN_NAME ,
763
- args = [ns_name , def_name ],
764
- keywords = list (
765
- chain (
766
- dynamic_kwarg ,
767
- []
768
- if meta_ast is None
769
- else [ast .keyword (arg = "meta" , value = meta_ast .node )],
770
- )
771
- ),
772
- ),
773
- dependencies = def_dependencies ,
774
- )
748
+ meta_ast = gen_py_ast (ctx , node .meta )
775
749
776
750
return GeneratedPyAST (
777
751
node = ast .Call (
778
- func = _INTERN_VAR_FN_NAME ,
779
- args = [ns_name , def_name , ast . Name ( id = safe_name , ctx = ast . Load ())] ,
752
+ func = func ,
753
+ args = list ( chain ( [ns_name , def_name ], extra_args )) ,
780
754
keywords = list (
781
755
chain (
782
756
dynamic_kwarg ,
@@ -786,7 +760,9 @@ def _def_to_py_ast( # pylint: disable=too-many-branches
786
760
)
787
761
),
788
762
),
789
- dependencies = def_dependencies ,
763
+ dependencies = list (
764
+ chain (def_dependencies , [] if meta_ast is None else meta_ast .dependencies ,)
765
+ ),
790
766
)
791
767
792
768
0 commit comments