fpy2 0.2.4__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fpy2-0.3.0/LICENSE +202 -0
- fpy2-0.3.0/NOTICE +2 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/PKG-INFO +3 -2
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/alias.py +157 -50
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/digit_bound/__init__.py +1 -1
- fpy2-0.3.0/fpy2/analysis/digit_bound/infer.py +2713 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/digit_bound/solver.py +19 -11
- fpy2-0.3.0/fpy2/analysis/digit_bound/spaces.py +120 -0
- fpy2-0.3.0/fpy2/analysis/digit_bound/store.py +376 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/escape.py +27 -28
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/format_infer/analysis.py +398 -165
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/value_class.py +6 -11
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/compiler.py +0 -2
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/emitter.py +33 -15
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/emitter.py +39 -2
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/launcher.py +19 -1
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/target.py +55 -14
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/unfold_round.py +20 -5
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/unfold_round.py +64 -18
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ops.py +43 -4
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/specialize.py +48 -39
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2.egg-info/PKG-INFO +3 -2
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2.egg-info/SOURCES.txt +2 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/pyproject.toml +2 -2
- fpy2-0.2.4/LICENSE +0 -21
- fpy2-0.2.4/fpy2/analysis/digit_bound/infer.py +0 -1778
- fpy2-0.2.4/fpy2/analysis/digit_bound/store.py +0 -265
- {fpy2-0.2.4 → fpy2-0.3.0}/README.md +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/array_size.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/call_graph.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/context_use.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/define_use.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/defs.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/format_infer/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/format_infer/double_round.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/format_infer/format.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/hoistability.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/live_vars.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/partial_eval.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/purity.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/reachability.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/reaching_defs.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/storage_infer.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/syntax_check.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/analysis/type_infer.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ast/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ast/accessors.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ast/formatter.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ast/fpyast.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/ast/visitor.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/backend.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/ops.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/storage.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/target.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/types.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/unbox.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/unfold_round.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/utils.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/cpp/variables.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/fpc.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/compiler.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/normalize.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/split_names.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/storage.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/types.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/backend/triton/vectorize.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/decorator.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/env.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/fpc_context.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/frontend/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/frontend/fpc.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/frontend/parser.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/function.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/interpret/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/interpret/byte.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/interpret/interpreter.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/interpret/value.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/base.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/core.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/eft.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/matrix.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/metrics.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/libraries/vector.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/module.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/context.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/efloat.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/exponential.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/format.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/ieee754.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/mp_fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/mp_float.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/mpb_fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/mpb_float.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/mps_float.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/real.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/context/sm_fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/engine/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/engine/engine.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/engine/gmp.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/engine/real.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/format.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/globals.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/gmputils.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/native.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/number/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/number/flags.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/number/floats.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/number/reals.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/number/round.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/primitive.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/applier.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/matcher.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/pattern.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/rewrite.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/search.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/rewrite/subst.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/runner.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/anf.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/assert_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/comp_lower.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/context_lift.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/exit_single.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/fixed_rescale.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/float_lower.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/free_var.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/func_inline.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/hoistable.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/if_simplify.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/invariant_hoist.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/iter_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/iter_unfold.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/loop_split.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/loop_unroll.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/mono.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/neg_zero_unfold.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/overflow_unfold.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/reduce_fusion.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/round_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/round_insert.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/round_split.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/scale_hoist.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/simple.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/sites.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/strategies/special_unfold.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/anf.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/assert_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/comp_to_loop.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/const_fold.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/copy_propagate.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/cursor.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/dead_code.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/enumerate_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/error.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/float_to_fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/for_bundling.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/for_unpack.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/for_unroll.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/free_var_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/func_inline.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/hoist_invariant.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/hoist_scale.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/hoistable.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/if_bundling.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/iter_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/lift_context.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/monomorphize.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/path.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/reduce_fusion.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/rename_target.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/rescale_fixed.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/round_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/round_insert.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/simplify.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/simplify_if.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/single_exit.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/split_loop.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/split_round.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/statement_form.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/subst_var.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/unfold_iter.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/unfold_neg_zero.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/unfold_overflow.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/unfold_special.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/unnest_context.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/utils.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/while_bundling.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/while_unroll.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/transform/zip_elim.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/types.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/__init__.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/bits.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/compare.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/decorator.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/default.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/float_params.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/fractions.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/gensym.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/identifier.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/inspect.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/iterator.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/loader.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/location.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/ordering.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/string.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/uninit.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2/utils/unionfind.py +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2.egg-info/dependency_links.txt +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2.egg-info/requires.txt +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/fpy2.egg-info/top_level.txt +0 -0
- {fpy2-0.2.4 → fpy2-0.3.0}/setup.cfg +0 -0
fpy2-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
fpy2-0.3.0/NOTICE
ADDED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fpy2
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: An embedded DSL for numerical computing
|
|
5
5
|
Author-email: Brett Saiki <bsaiki@cs.washington.edu>
|
|
6
|
-
License-Expression:
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/bksaiki/fpy
|
|
8
8
|
Project-URL: Issues, https://github.com/bksaiki/fpy/issues
|
|
9
9
|
Project-URL: Documentation, https://fpy.readthedocs.io/
|
|
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Requires-Python: >=3.11
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
+
License-File: NOTICE
|
|
15
16
|
Requires-Dist: titanfp==0.1.2
|
|
16
17
|
Requires-Dist: gmpy2==2.3.1
|
|
17
18
|
Requires-Dist: numpy
|
|
@@ -47,6 +47,9 @@ elements part, ``fld(c, i)`` field *i*):
|
|
|
47
47
|
``for row in xss`` ``reg(row) ≡ elts(xss)``
|
|
48
48
|
``xs if c else ys`` ``reg(result) ≡ reg(xs) ≡ reg(ys)``
|
|
49
49
|
``enumerate``/``zip`` ``elts(result) ≡ elts(arg)``
|
|
50
|
+
``f(xs, ys)`` if ``f`` may keep ``xs``: each list in ``xs`` ≡
|
|
51
|
+
each same-shaped one in ``result``, or in ``ys``
|
|
52
|
+
if ``f`` may write it
|
|
50
53
|
========================= ==========================================
|
|
51
54
|
|
|
52
55
|
Equality rather than inclusion is deliberate. Each place denotes exactly one
|
|
@@ -64,13 +67,12 @@ The ownership queries stay sound because shared-outward poisons them;
|
|
|
64
67
|
:meth:`AliasAnalysis.may_alias` is sound only for the routes above.
|
|
65
68
|
|
|
66
69
|
Two routes leave the function, and they mean opposite things for ownership.
|
|
67
|
-
*Shared outward* —
|
|
68
|
-
something else may hold the list while this function still does
|
|
69
|
-
|
|
70
|
-
**E-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
returned and nothing else.
|
|
70
|
+
*Shared outward* — kept by a call, or handed to an unmodelled operation — means
|
|
71
|
+
something else may hold the list while this function still does. A call that
|
|
72
|
+
only writes it is flagged apart (:meth:`AliasAnalysis.callee_writes_at`):
|
|
73
|
+
**E-App** keeps no store of its own, so a callee writes the caller's cells.
|
|
74
|
+
*Returned* is **E-Ret** handing a location out, which is a transfer; see
|
|
75
|
+
:meth:`AliasAnalysis.transfers_ownership`.
|
|
74
76
|
|
|
75
77
|
Limitations
|
|
76
78
|
-----------
|
|
@@ -79,12 +81,13 @@ One *summary* store for the whole function, not one per program point, so it is
|
|
|
79
81
|
flow-insensitive: ``ys = xs`` marks ``xs`` shared even if ``ys`` is dead
|
|
80
82
|
immediately afterwards, and a container part counts as a referrer even if the
|
|
81
83
|
container itself is never read — except :attr:`AliasAnalysis.consumed_defs`,
|
|
82
|
-
which buys back one flow-sensitive fact under narrow guards.
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
which buys back one flow-sensitive fact under narrow guards. Context-insensitive:
|
|
85
|
+
one summary of a callee (:mod:`fpy2.analysis.escape`) answers for every call to
|
|
86
|
+
it. Index-insensitive: ``xs[0]`` and ``xs[1]`` are one part. All three
|
|
85
87
|
cost precision, not soundness.
|
|
86
88
|
"""
|
|
87
89
|
|
|
90
|
+
from collections.abc import Iterator
|
|
88
91
|
from dataclasses import dataclass, field
|
|
89
92
|
from typing import TYPE_CHECKING, Literal, overload
|
|
90
93
|
|
|
@@ -121,7 +124,7 @@ from ..ast import (
|
|
|
121
124
|
Zip,
|
|
122
125
|
)
|
|
123
126
|
from ..function import Function
|
|
124
|
-
from ..types import ListType, TupleType, Type
|
|
127
|
+
from ..types import ListType, TupleType, Type, VarType
|
|
125
128
|
from ..utils import Unionfind
|
|
126
129
|
from .array_size import (
|
|
127
130
|
ArraySizeAnalysis,
|
|
@@ -132,7 +135,7 @@ from .array_size import (
|
|
|
132
135
|
)
|
|
133
136
|
from .define_use import DefineUse, DefineUseAnalysis
|
|
134
137
|
from .reaching_defs import AssignDef, Definition, same_object_defs
|
|
135
|
-
from .type_infer import TypeAnalysis, TypeInfer
|
|
138
|
+
from .type_infer import TypeAnalysis, TypeInfer, TypeInferError
|
|
136
139
|
|
|
137
140
|
if TYPE_CHECKING:
|
|
138
141
|
# `escape` builds on this module; the dependency only goes the other way
|
|
@@ -156,10 +159,10 @@ def _carries_list(ty: Type | None) -> bool:
|
|
|
156
159
|
"""Whether a value of type *ty* can hold a list reference anywhere inside it.
|
|
157
160
|
|
|
158
161
|
Values that cannot are not given regions at all — nothing about them is
|
|
159
|
-
observable through aliasing.
|
|
162
|
+
observable through aliasing. A type variable may be a list.
|
|
160
163
|
"""
|
|
161
164
|
match ty:
|
|
162
|
-
case ListType():
|
|
165
|
+
case ListType() | VarType():
|
|
163
166
|
return True
|
|
164
167
|
case TupleType():
|
|
165
168
|
return any(_carries_list(elt) for elt in ty.elts)
|
|
@@ -167,6 +170,17 @@ def _carries_list(ty: Type | None) -> bool:
|
|
|
167
170
|
return False
|
|
168
171
|
|
|
169
172
|
|
|
173
|
+
def _shape(ty: Type | None) -> object:
|
|
174
|
+
"""*ty*'s list and tuple nesting, without sizes or scalar types."""
|
|
175
|
+
match ty:
|
|
176
|
+
case ListType():
|
|
177
|
+
return ('list', _shape(ty.elt))
|
|
178
|
+
case TupleType():
|
|
179
|
+
return tuple(_shape(elt) for elt in ty.elts)
|
|
180
|
+
case _:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
170
184
|
class AllocSite:
|
|
171
185
|
"""A place a list value comes into existence.
|
|
172
186
|
|
|
@@ -233,12 +247,14 @@ class _Regions:
|
|
|
233
247
|
# things for ownership -- see `AliasAnalysis.transfers_ownership`.
|
|
234
248
|
self._shared_out: set[Region] = set()
|
|
235
249
|
self._returned: set[Region] = set()
|
|
250
|
+
# handed to a callee that may store into it, which need not keep it
|
|
251
|
+
self._callee_written: set[Region] = set()
|
|
236
252
|
self._parts: dict[Region, dict[_PartKey, Region]] = {}
|
|
237
253
|
|
|
238
254
|
@property
|
|
239
255
|
def _flags(self) -> tuple[set[Region], ...]:
|
|
240
256
|
"""Every downward-propagating class flag, so each is handled alike."""
|
|
241
|
-
return (self._shared_out, self._returned)
|
|
257
|
+
return (self._shared_out, self._returned, self._callee_written)
|
|
242
258
|
|
|
243
259
|
def new(
|
|
244
260
|
self, kind: str, *, name: NamedId | None = None, slot: bool = False,
|
|
@@ -363,14 +379,20 @@ class _Regions:
|
|
|
363
379
|
inherit the flag in :meth:`part`, so the two directions together are
|
|
364
380
|
order-independent.
|
|
365
381
|
"""
|
|
382
|
+
flag.update(self.within(c))
|
|
383
|
+
|
|
384
|
+
def parts(self, c: Region) -> dict[_PartKey, Region]:
|
|
385
|
+
return {k: self.find(r) for k, r in self._parts.get(self.find(c), {}).items()}
|
|
386
|
+
|
|
387
|
+
def within(self, c: Region) -> set[Region]:
|
|
388
|
+
"""*c* and every class reachable inside it, through elements and fields."""
|
|
366
389
|
pending, seen = [self.find(c)], set()
|
|
367
390
|
while pending:
|
|
368
391
|
root = self.find(pending.pop())
|
|
369
|
-
if root in seen:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
pending.extend(self._parts.get(root, {}).values())
|
|
392
|
+
if root not in seen:
|
|
393
|
+
seen.add(root)
|
|
394
|
+
pending.extend(self._parts.get(root, {}).values())
|
|
395
|
+
return seen
|
|
374
396
|
|
|
375
397
|
def mark_shared_out(self, c: Region) -> None:
|
|
376
398
|
"""*c* may be held by something outside while this function holds it."""
|
|
@@ -380,9 +402,16 @@ class _Regions:
|
|
|
380
402
|
"""*c* is handed to the caller by a ``return``."""
|
|
381
403
|
self._spread(self._returned, c)
|
|
382
404
|
|
|
405
|
+
def mark_callee_written(self, c: Region) -> None:
|
|
406
|
+
"""*c* is handed to a callee that may store into it."""
|
|
407
|
+
self._spread(self._callee_written, c)
|
|
408
|
+
|
|
383
409
|
def is_shared_out(self, c: Region) -> bool:
|
|
384
410
|
return self.find(c) in self._shared_out
|
|
385
411
|
|
|
412
|
+
def is_callee_written(self, c: Region) -> bool:
|
|
413
|
+
return self.find(c) in self._callee_written
|
|
414
|
+
|
|
386
415
|
def is_returned(self, c: Region) -> bool:
|
|
387
416
|
return self.find(c) in self._returned
|
|
388
417
|
|
|
@@ -453,6 +482,14 @@ class AliasAnalysis:
|
|
|
453
482
|
"""The region *depth* list levels inside *region*."""
|
|
454
483
|
return self._walk(region, depth)
|
|
455
484
|
|
|
485
|
+
def parts(self, region: Region) -> dict[_PartKey, Region]:
|
|
486
|
+
"""*region*'s parts by key: its elements (:data:`ELTS`) or field *i*."""
|
|
487
|
+
return self._regions.parts(region)
|
|
488
|
+
|
|
489
|
+
def within(self, region: Region) -> frozenset[Region]:
|
|
490
|
+
"""*region* and every region it holds, through elements and fields."""
|
|
491
|
+
return frozenset(self._regions.within(region))
|
|
492
|
+
|
|
456
493
|
def region_field(self, region: Region | None, i: int) -> Region | None:
|
|
457
494
|
"""The region held by field *i* of *region*'s tuple."""
|
|
458
495
|
if region is None:
|
|
@@ -509,9 +546,13 @@ class AliasAnalysis:
|
|
|
509
546
|
|
|
510
547
|
def escapes_at(self, region: Region) -> bool:
|
|
511
548
|
"""Whether *region* is held by something outside while this function
|
|
512
|
-
still holds it —
|
|
549
|
+
still holds it — kept by a call, or handed to an unmodelled operation."""
|
|
513
550
|
return self._regions.is_shared_out(region)
|
|
514
551
|
|
|
552
|
+
def callee_writes_at(self, region: Region) -> bool:
|
|
553
|
+
"""Whether a callee *region* is handed to may store into it."""
|
|
554
|
+
return self._regions.is_callee_written(region)
|
|
555
|
+
|
|
515
556
|
def returned_at(self, region: Region) -> bool:
|
|
516
557
|
"""Whether *region* is handed to the caller by a ``return``."""
|
|
517
558
|
return self._regions.is_returned(region)
|
|
@@ -537,7 +578,7 @@ class AliasAnalysis:
|
|
|
537
578
|
|
|
538
579
|
def escapes(self, site: AllocSite) -> bool:
|
|
539
580
|
"""Whether *site*, or a container holding it, leaves the function at all
|
|
540
|
-
—
|
|
581
|
+
— kept by a call, or returned.
|
|
541
582
|
|
|
542
583
|
Says nothing about *which*; :meth:`transfers_ownership` separates them.
|
|
543
584
|
"""
|
|
@@ -591,11 +632,31 @@ class AliasAnalysis:
|
|
|
591
632
|
return False
|
|
592
633
|
return self._regions.find(ca) is self._regions.find(cb)
|
|
593
634
|
|
|
635
|
+
def may_write(self, region: Region) -> bool:
|
|
636
|
+
"""Whether this function may store into *region*, or into a list it
|
|
637
|
+
holds, itself or through a call it hands one to."""
|
|
638
|
+
return any(
|
|
639
|
+
r in self.written_regions or r in self.stored_regions
|
|
640
|
+
or self.escapes_at(r) or self.callee_writes_at(r)
|
|
641
|
+
for r in self.within(region)
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
def param_regions(self, func: FuncDef, def_use: DefineUseAnalysis) -> dict[int, Region]:
|
|
645
|
+
"""The region of each of *func*'s list parameters, by position."""
|
|
646
|
+
out: dict[int, Region] = {}
|
|
647
|
+
for i, arg in enumerate(func.args):
|
|
648
|
+
if isinstance(arg.name, NamedId):
|
|
649
|
+
r = self.region_of(def_use.find_def_from_site(arg.name, arg))
|
|
650
|
+
if r is not None:
|
|
651
|
+
out[i] = r
|
|
652
|
+
return out
|
|
653
|
+
|
|
594
654
|
def may_change(self, d: Definition) -> bool:
|
|
595
655
|
"""Whether the list *d* names may have an element replaced, through
|
|
596
656
|
any name here or by a call it is handed to."""
|
|
597
657
|
r = self.region_of(d)
|
|
598
|
-
return r is None or r in self.stored_regions
|
|
658
|
+
return (r is None or r in self.stored_regions
|
|
659
|
+
or self.escapes_at(r) or self.callee_writes_at(r))
|
|
599
660
|
|
|
600
661
|
|
|
601
662
|
class _EscapeVars(DefaultVisitor):
|
|
@@ -628,11 +689,13 @@ class _Builder(DefaultVisitor):
|
|
|
628
689
|
|
|
629
690
|
def __init__(self, func: FuncDef, def_use: DefineUseAnalysis,
|
|
630
691
|
type_info: TypeAnalysis,
|
|
631
|
-
summaries: 'dict[FuncDef, EscapeSummary]'
|
|
692
|
+
summaries: 'dict[FuncDef, EscapeSummary]',
|
|
693
|
+
linked: frozenset[tuple[int, int]]):
|
|
632
694
|
self.func = func
|
|
633
695
|
self.def_use = def_use
|
|
634
696
|
self.types = type_info
|
|
635
697
|
self.summaries = summaries
|
|
698
|
+
self.linked = linked
|
|
636
699
|
self.regions = _Regions()
|
|
637
700
|
self.sites: list[AllocSite] = []
|
|
638
701
|
self.by_def: dict[Definition, Region] = {}
|
|
@@ -721,13 +784,28 @@ class _Builder(DefaultVisitor):
|
|
|
721
784
|
self.regions.merge(self._reg(d), self._reg(self.def_use.defs[i]))
|
|
722
785
|
|
|
723
786
|
def _seed_params(self) -> None:
|
|
724
|
-
|
|
787
|
+
params: dict[int, tuple[Region, Type | None]] = {}
|
|
788
|
+
for i, arg in enumerate(self.func.args):
|
|
725
789
|
if not isinstance(arg.name, NamedId):
|
|
726
790
|
continue
|
|
727
791
|
d = self.def_use.find_def_from_site(arg.name, arg)
|
|
728
792
|
ty = self.types.by_def.get(d)
|
|
729
793
|
if _carries_list(ty):
|
|
730
794
|
self._seed(self._reg(d), ty, arg, 0)
|
|
795
|
+
params[i] = (self._reg(d), ty)
|
|
796
|
+
for i, j in self.linked:
|
|
797
|
+
if i in params and j in params:
|
|
798
|
+
self._merge_by_shape(*params[i], *params[j])
|
|
799
|
+
|
|
800
|
+
def _merge_by_shape(
|
|
801
|
+
self, a: Region, a_ty: Type | None, b: Region, b_ty: Type | None,
|
|
802
|
+
) -> None:
|
|
803
|
+
"""Merge each list in *a* with each list in *b* of the same shape."""
|
|
804
|
+
theirs = list(self._lists_in(b, b_ty))
|
|
805
|
+
for r, ty in list(self._lists_in(a, a_ty)):
|
|
806
|
+
for q, qty in theirs:
|
|
807
|
+
if _shape(ty) == _shape(qty):
|
|
808
|
+
self.regions.merge(r, q)
|
|
731
809
|
|
|
732
810
|
def _seed(self, region: Region, ty: Type | None, arg: Argument,
|
|
733
811
|
depth: int) -> None:
|
|
@@ -738,6 +816,8 @@ class _Builder(DefaultVisitor):
|
|
|
738
816
|
self._site('param', arg, region, depth)
|
|
739
817
|
if _carries_list(ty.elt):
|
|
740
818
|
self._seed(self._part(region), ty.elt, arg, depth + 1)
|
|
819
|
+
case VarType():
|
|
820
|
+
self._site('param', arg, region, depth)
|
|
741
821
|
case TupleType():
|
|
742
822
|
for i, elt in enumerate(ty.elts):
|
|
743
823
|
if _carries_list(elt):
|
|
@@ -823,9 +903,8 @@ class _Builder(DefaultVisitor):
|
|
|
823
903
|
)
|
|
824
904
|
return region
|
|
825
905
|
case Call():
|
|
826
|
-
|
|
827
|
-
self.
|
|
828
|
-
return region
|
|
906
|
+
# linked to what the callee keeps by `_visit_call`
|
|
907
|
+
return self._alloc('call', e, deep=True)
|
|
829
908
|
case Range1() | Range2() | Range3() | Empty():
|
|
830
909
|
# A fresh sequence over *integer* arguments: there is nothing
|
|
831
910
|
# list-shaped for it to retain, so unlike the catch-all below it
|
|
@@ -874,23 +953,32 @@ class _Builder(DefaultVisitor):
|
|
|
874
953
|
for i, elt in enumerate(target.elts):
|
|
875
954
|
self._bind(elt, self._part(region, i), site)
|
|
876
955
|
|
|
877
|
-
def
|
|
878
|
-
"""
|
|
956
|
+
def _summary(self, e: Call) -> 'EscapeSummary | None':
|
|
957
|
+
"""The callee's summary, computed when not given; ``None`` for a foreign
|
|
958
|
+
function or one that does not type on its own, which means the
|
|
959
|
+
conservative answer."""
|
|
960
|
+
if not isinstance(e.fn, Function):
|
|
961
|
+
return None
|
|
962
|
+
fd = e.fn.ast
|
|
963
|
+
if fd not in self.summaries:
|
|
964
|
+
from .escape import Escape
|
|
965
|
+
try:
|
|
966
|
+
self.summaries[fd] = Escape.analyze(fd, self.summaries)
|
|
967
|
+
except TypeInferError:
|
|
968
|
+
return None
|
|
969
|
+
return self.summaries[fd]
|
|
879
970
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
continue
|
|
892
|
-
if summary is None or summary.retains(i):
|
|
893
|
-
self.regions.mark_shared_out(ac)
|
|
971
|
+
def _lists_in(self, region: Region, ty: Type | None) -> Iterator[tuple[Region, Type]]:
|
|
972
|
+
"""Every list *region* holds, itself included, with its type."""
|
|
973
|
+
match ty:
|
|
974
|
+
case ListType():
|
|
975
|
+
yield region, ty
|
|
976
|
+
if _carries_list(ty.elt):
|
|
977
|
+
yield from self._lists_in(self._part(region), ty.elt)
|
|
978
|
+
case TupleType():
|
|
979
|
+
for i, elt in enumerate(ty.elts):
|
|
980
|
+
if _carries_list(elt):
|
|
981
|
+
yield from self._lists_in(self._part(region, i), elt)
|
|
894
982
|
|
|
895
983
|
# -- constraint-generating hooks ---------------------------------------
|
|
896
984
|
#
|
|
@@ -904,9 +992,23 @@ class _Builder(DefaultVisitor):
|
|
|
904
992
|
return super()._visit_expr(e, ctx)
|
|
905
993
|
|
|
906
994
|
def _visit_call(self, e: Call, ctx):
|
|
907
|
-
"""
|
|
908
|
-
|
|
909
|
-
|
|
995
|
+
"""An argument the callee may write is marked so; one it may keep is
|
|
996
|
+
shared outward and joins each same-shaped list in the result or in a
|
|
997
|
+
written argument."""
|
|
998
|
+
summary = self._summary(e)
|
|
999
|
+
written = [a for i, a in enumerate(e.args) if summary is None or summary.writes(i)]
|
|
1000
|
+
retained = [a for i, a in enumerate(e.args) if summary is None or summary.retains(i)]
|
|
1001
|
+
reach = [(x, xc) for x in (e, *written) if (xc := self._region_for(x)) is not None]
|
|
1002
|
+
for x, xc in reach:
|
|
1003
|
+
if x is not e:
|
|
1004
|
+
self.regions.mark_callee_written(xc)
|
|
1005
|
+
for a in retained:
|
|
1006
|
+
if (ac := self._region_for(a)) is None:
|
|
1007
|
+
continue
|
|
1008
|
+
self.regions.mark_shared_out(ac)
|
|
1009
|
+
for x, xc in reach:
|
|
1010
|
+
self._merge_by_shape(
|
|
1011
|
+
ac, self.types.by_expr.get(a), xc, self.types.by_expr.get(x))
|
|
910
1012
|
super()._visit_call(e, ctx)
|
|
911
1013
|
|
|
912
1014
|
def _visit_assign(self, stmt: Assign, ctx):
|
|
@@ -1170,6 +1272,7 @@ class Alias:
|
|
|
1170
1272
|
def_use: DefineUseAnalysis | None = None,
|
|
1171
1273
|
type_info: TypeAnalysis | None = None,
|
|
1172
1274
|
summaries: 'dict[FuncDef, EscapeSummary] | None' = None,
|
|
1275
|
+
linked: frozenset[tuple[int, int]] = frozenset(),
|
|
1173
1276
|
) -> AliasAnalysis:
|
|
1174
1277
|
"""Compute what may refer to each list in *func*.
|
|
1175
1278
|
|
|
@@ -1179,8 +1282,11 @@ class Alias:
|
|
|
1179
1282
|
type_info: reuse an existing type analysis (needed to tell which
|
|
1180
1283
|
expressions carry lists).
|
|
1181
1284
|
summaries: escape summaries for the callees, so an argument a callee
|
|
1182
|
-
does not retain is not treated as shared. A
|
|
1183
|
-
it is
|
|
1285
|
+
does not retain is not treated as shared. A memo: one absent
|
|
1286
|
+
from it is computed and added. A foreign callee, or one that
|
|
1287
|
+
does not type on its own, is assumed to retain everything.
|
|
1288
|
+
linked: pairs of parameters a caller may pass one list to, at any
|
|
1289
|
+
depth; their same-shaped lists share regions.
|
|
1184
1290
|
"""
|
|
1185
1291
|
if not isinstance(func, FuncDef):
|
|
1186
1292
|
raise TypeError(f"expected a 'FuncDef', got {func}")
|
|
@@ -1188,4 +1294,5 @@ class Alias:
|
|
|
1188
1294
|
def_use = DefineUse.analyze(func)
|
|
1189
1295
|
if type_info is None:
|
|
1190
1296
|
type_info = TypeInfer.check(func, def_use=def_use)
|
|
1191
|
-
|
|
1297
|
+
summaries = {} if summaries is None else summaries
|
|
1298
|
+
return _Builder(func, def_use, type_info, summaries, linked).run()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Answers one question -- how many binades separate a value from the position it
|
|
4
4
|
is rounded at -- which is the precision of the resulting fixed-point value.
|
|
5
|
-
See ``docs/todos/digit-bound
|
|
5
|
+
See ``docs/todos/digit-bound.md``.
|
|
6
6
|
|
|
7
7
|
:mod:`solver` is the constraint language and its backend, :mod:`store` the
|
|
8
8
|
domain and its queries, and :mod:`infer` the pass over a program.
|