relationalai 0.13.0.dev0__py3-none-any.whl → 0.13.2__py3-none-any.whl
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.
- frontend/debugger/dist/.gitignore +2 -0
- frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
- frontend/debugger/dist/assets/index-Cssla-O7.js +208 -0
- frontend/debugger/dist/assets/index-DlHsYx1V.css +9 -0
- frontend/debugger/dist/index.html +17 -0
- relationalai/__init__.py +256 -1
- relationalai/clients/__init__.py +18 -0
- relationalai/clients/client.py +947 -0
- relationalai/clients/config.py +673 -0
- relationalai/clients/direct_access_client.py +118 -0
- relationalai/clients/exec_txn_poller.py +91 -0
- relationalai/clients/hash_util.py +31 -0
- relationalai/clients/local.py +586 -0
- relationalai/clients/profile_polling.py +73 -0
- relationalai/clients/resources/__init__.py +8 -0
- relationalai/clients/resources/azure/azure.py +502 -0
- relationalai/clients/resources/snowflake/__init__.py +20 -0
- relationalai/clients/resources/snowflake/cli_resources.py +98 -0
- relationalai/clients/resources/snowflake/direct_access_resources.py +734 -0
- relationalai/clients/resources/snowflake/engine_service.py +381 -0
- relationalai/clients/resources/snowflake/engine_state_handlers.py +315 -0
- relationalai/clients/resources/snowflake/error_handlers.py +240 -0
- relationalai/clients/resources/snowflake/export_procedure.py.jinja +249 -0
- relationalai/clients/resources/snowflake/resources_factory.py +99 -0
- relationalai/clients/resources/snowflake/snowflake.py +3185 -0
- relationalai/clients/resources/snowflake/use_index_poller.py +1019 -0
- relationalai/clients/resources/snowflake/use_index_resources.py +188 -0
- relationalai/clients/resources/snowflake/util.py +387 -0
- relationalai/clients/result_helpers.py +420 -0
- relationalai/clients/types.py +118 -0
- relationalai/clients/util.py +356 -0
- relationalai/debugging.py +389 -0
- relationalai/dsl.py +1749 -0
- relationalai/early_access/builder/__init__.py +30 -0
- relationalai/early_access/builder/builder/__init__.py +35 -0
- relationalai/early_access/builder/snowflake/__init__.py +12 -0
- relationalai/early_access/builder/std/__init__.py +25 -0
- relationalai/early_access/builder/std/decimals/__init__.py +12 -0
- relationalai/early_access/builder/std/integers/__init__.py +12 -0
- relationalai/early_access/builder/std/math/__init__.py +12 -0
- relationalai/early_access/builder/std/strings/__init__.py +14 -0
- relationalai/early_access/devtools/__init__.py +12 -0
- relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
- relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
- relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
- relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
- relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
- relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
- relationalai/early_access/dsl/bindings/common.py +402 -0
- relationalai/early_access/dsl/bindings/csv.py +170 -0
- relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
- relationalai/early_access/dsl/bindings/snowflake.py +64 -0
- relationalai/early_access/dsl/codegen/binder.py +411 -0
- relationalai/early_access/dsl/codegen/common.py +79 -0
- relationalai/early_access/dsl/codegen/helpers.py +23 -0
- relationalai/early_access/dsl/codegen/relations.py +700 -0
- relationalai/early_access/dsl/codegen/weaver.py +417 -0
- relationalai/early_access/dsl/core/builders/__init__.py +47 -0
- relationalai/early_access/dsl/core/builders/logic.py +19 -0
- relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
- relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
- relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
- relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
- relationalai/early_access/dsl/core/context.py +13 -0
- relationalai/early_access/dsl/core/cset.py +132 -0
- relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
- relationalai/early_access/dsl/core/exprs/relational.py +18 -0
- relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
- relationalai/early_access/dsl/core/instances.py +44 -0
- relationalai/early_access/dsl/core/logic/__init__.py +193 -0
- relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
- relationalai/early_access/dsl/core/logic/exists.py +223 -0
- relationalai/early_access/dsl/core/logic/helper.py +163 -0
- relationalai/early_access/dsl/core/namespaces.py +32 -0
- relationalai/early_access/dsl/core/relations.py +276 -0
- relationalai/early_access/dsl/core/rules.py +112 -0
- relationalai/early_access/dsl/core/std/__init__.py +45 -0
- relationalai/early_access/dsl/core/temporal/recall.py +6 -0
- relationalai/early_access/dsl/core/types/__init__.py +270 -0
- relationalai/early_access/dsl/core/types/concepts.py +128 -0
- relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
- relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
- relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
- relationalai/early_access/dsl/core/types/standard.py +92 -0
- relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
- relationalai/early_access/dsl/core/types/variables.py +203 -0
- relationalai/early_access/dsl/ir/compiler.py +318 -0
- relationalai/early_access/dsl/ir/executor.py +260 -0
- relationalai/early_access/dsl/ontologies/constraints.py +88 -0
- relationalai/early_access/dsl/ontologies/export.py +30 -0
- relationalai/early_access/dsl/ontologies/models.py +453 -0
- relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
- relationalai/early_access/dsl/ontologies/readings.py +60 -0
- relationalai/early_access/dsl/ontologies/relationships.py +322 -0
- relationalai/early_access/dsl/ontologies/roles.py +87 -0
- relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
- relationalai/early_access/dsl/orm/constraints.py +438 -0
- relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
- relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
- relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
- relationalai/early_access/dsl/orm/measures/measures.py +299 -0
- relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
- relationalai/early_access/dsl/orm/models.py +256 -0
- relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
- relationalai/early_access/dsl/orm/printer.py +469 -0
- relationalai/early_access/dsl/orm/reasoners.py +480 -0
- relationalai/early_access/dsl/orm/relations.py +19 -0
- relationalai/early_access/dsl/orm/relationships.py +251 -0
- relationalai/early_access/dsl/orm/types.py +42 -0
- relationalai/early_access/dsl/orm/utils.py +79 -0
- relationalai/early_access/dsl/orm/verb.py +204 -0
- relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
- relationalai/early_access/dsl/relations.py +170 -0
- relationalai/early_access/dsl/rulesets.py +69 -0
- relationalai/early_access/dsl/schemas/__init__.py +450 -0
- relationalai/early_access/dsl/schemas/builder.py +48 -0
- relationalai/early_access/dsl/schemas/comp_names.py +51 -0
- relationalai/early_access/dsl/schemas/components.py +203 -0
- relationalai/early_access/dsl/schemas/contexts.py +156 -0
- relationalai/early_access/dsl/schemas/exprs.py +89 -0
- relationalai/early_access/dsl/schemas/fragments.py +464 -0
- relationalai/early_access/dsl/serialization.py +79 -0
- relationalai/early_access/dsl/serialize/exporter.py +163 -0
- relationalai/early_access/dsl/snow/api.py +105 -0
- relationalai/early_access/dsl/snow/common.py +76 -0
- relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
- relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
- relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
- relationalai/early_access/dsl/types/__init__.py +40 -0
- relationalai/early_access/dsl/types/concepts.py +12 -0
- relationalai/early_access/dsl/types/entities.py +135 -0
- relationalai/early_access/dsl/types/values.py +17 -0
- relationalai/early_access/dsl/utils.py +102 -0
- relationalai/early_access/graphs/__init__.py +13 -0
- relationalai/early_access/lqp/__init__.py +12 -0
- relationalai/early_access/lqp/compiler/__init__.py +12 -0
- relationalai/early_access/lqp/constructors/__init__.py +18 -0
- relationalai/early_access/lqp/executor/__init__.py +12 -0
- relationalai/early_access/lqp/ir/__init__.py +12 -0
- relationalai/early_access/lqp/passes/__init__.py +12 -0
- relationalai/early_access/lqp/pragmas/__init__.py +12 -0
- relationalai/early_access/lqp/primitives/__init__.py +12 -0
- relationalai/early_access/lqp/types/__init__.py +12 -0
- relationalai/early_access/lqp/utils/__init__.py +12 -0
- relationalai/early_access/lqp/validators/__init__.py +12 -0
- relationalai/early_access/metamodel/__init__.py +58 -0
- relationalai/early_access/metamodel/builtins/__init__.py +12 -0
- relationalai/early_access/metamodel/compiler/__init__.py +12 -0
- relationalai/early_access/metamodel/dependency/__init__.py +12 -0
- relationalai/early_access/metamodel/factory/__init__.py +17 -0
- relationalai/early_access/metamodel/helpers/__init__.py +12 -0
- relationalai/early_access/metamodel/ir/__init__.py +14 -0
- relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
- relationalai/early_access/metamodel/typer/__init__.py +3 -0
- relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
- relationalai/early_access/metamodel/types/__init__.py +15 -0
- relationalai/early_access/metamodel/util/__init__.py +15 -0
- relationalai/early_access/metamodel/visitor/__init__.py +12 -0
- relationalai/early_access/rel/__init__.py +12 -0
- relationalai/early_access/rel/executor/__init__.py +12 -0
- relationalai/early_access/rel/rel_utils/__init__.py +12 -0
- relationalai/early_access/rel/rewrite/__init__.py +7 -0
- relationalai/early_access/solvers/__init__.py +19 -0
- relationalai/early_access/sql/__init__.py +11 -0
- relationalai/early_access/sql/executor/__init__.py +3 -0
- relationalai/early_access/sql/rewrite/__init__.py +3 -0
- relationalai/early_access/tests/logging/__init__.py +12 -0
- relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
- relationalai/early_access/tests/utils/__init__.py +12 -0
- relationalai/environments/__init__.py +35 -0
- relationalai/environments/base.py +381 -0
- relationalai/environments/colab.py +14 -0
- relationalai/environments/generic.py +71 -0
- relationalai/environments/ipython.py +68 -0
- relationalai/environments/jupyter.py +9 -0
- relationalai/environments/snowbook.py +169 -0
- relationalai/errors.py +2496 -0
- relationalai/experimental/SF.py +38 -0
- relationalai/experimental/inspect.py +47 -0
- relationalai/experimental/pathfinder/__init__.py +158 -0
- relationalai/experimental/pathfinder/api.py +160 -0
- relationalai/experimental/pathfinder/automaton.py +584 -0
- relationalai/experimental/pathfinder/bridge.py +226 -0
- relationalai/experimental/pathfinder/compiler.py +416 -0
- relationalai/experimental/pathfinder/datalog.py +214 -0
- relationalai/experimental/pathfinder/diagnostics.py +56 -0
- relationalai/experimental/pathfinder/filter.py +236 -0
- relationalai/experimental/pathfinder/glushkov.py +439 -0
- relationalai/experimental/pathfinder/options.py +265 -0
- relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +1951 -0
- relationalai/experimental/pathfinder/rpq.py +344 -0
- relationalai/experimental/pathfinder/transition.py +200 -0
- relationalai/experimental/pathfinder/utils.py +26 -0
- relationalai/experimental/paths/README.md +107 -0
- relationalai/experimental/paths/api.py +143 -0
- relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
- relationalai/experimental/paths/code_organization.md +2 -0
- relationalai/experimental/paths/examples/Movies.ipynb +16328 -0
- relationalai/experimental/paths/examples/basic_example.py +40 -0
- relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
- relationalai/experimental/paths/examples/movie_example.py +77 -0
- relationalai/experimental/paths/examples/movies_data/actedin.csv +193 -0
- relationalai/experimental/paths/examples/movies_data/directed.csv +45 -0
- relationalai/experimental/paths/examples/movies_data/follows.csv +7 -0
- relationalai/experimental/paths/examples/movies_data/movies.csv +39 -0
- relationalai/experimental/paths/examples/movies_data/person.csv +134 -0
- relationalai/experimental/paths/examples/movies_data/produced.csv +16 -0
- relationalai/experimental/paths/examples/movies_data/ratings.csv +10 -0
- relationalai/experimental/paths/examples/movies_data/wrote.csv +11 -0
- relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
- relationalai/experimental/paths/examples/paths_example.py +116 -0
- relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
- relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
- relationalai/experimental/paths/graph.py +185 -0
- relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
- relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
- relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
- relationalai/experimental/paths/path_algorithms/single.py +59 -0
- relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
- relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
- relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
- relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
- relationalai/experimental/paths/path_algorithms/usp.py +150 -0
- relationalai/experimental/paths/product_graph.py +93 -0
- relationalai/experimental/paths/rpq/automaton.py +584 -0
- relationalai/experimental/paths/rpq/diagnostics.py +56 -0
- relationalai/experimental/paths/rpq/rpq.py +378 -0
- relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
- relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
- relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
- relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
- relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
- relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
- relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
- relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
- relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
- relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
- relationalai/experimental/paths/tree_agg.py +168 -0
- relationalai/experimental/paths/utilities/iterators.py +27 -0
- relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
- relationalai/experimental/solvers.py +1087 -0
- relationalai/loaders/csv.py +195 -0
- relationalai/loaders/loader.py +177 -0
- relationalai/loaders/types.py +23 -0
- relationalai/rel_emitter.py +373 -0
- relationalai/rel_utils.py +185 -0
- relationalai/semantics/__init__.py +22 -146
- relationalai/semantics/designs/query_builder/identify_by.md +106 -0
- relationalai/semantics/devtools/benchmark_lqp.py +535 -0
- relationalai/semantics/devtools/compilation_manager.py +294 -0
- relationalai/semantics/devtools/extract_lqp.py +110 -0
- relationalai/semantics/internal/internal.py +3785 -0
- relationalai/semantics/internal/snowflake.py +325 -0
- relationalai/semantics/lqp/README.md +34 -0
- relationalai/semantics/lqp/builtins.py +16 -0
- relationalai/semantics/lqp/compiler.py +22 -0
- relationalai/semantics/lqp/constructors.py +68 -0
- relationalai/semantics/lqp/executor.py +469 -0
- relationalai/semantics/lqp/intrinsics.py +24 -0
- relationalai/semantics/lqp/model2lqp.py +877 -0
- relationalai/semantics/lqp/passes.py +680 -0
- relationalai/semantics/lqp/primitives.py +252 -0
- relationalai/semantics/lqp/result_helpers.py +202 -0
- relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
- relationalai/semantics/lqp/rewrite/cdc.py +216 -0
- relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
- relationalai/semantics/lqp/rewrite/extract_keys.py +512 -0
- relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
- relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
- relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
- relationalai/semantics/lqp/rewrite/splinter.py +76 -0
- relationalai/semantics/lqp/types.py +101 -0
- relationalai/semantics/lqp/utils.py +160 -0
- relationalai/semantics/lqp/validators.py +57 -0
- relationalai/semantics/metamodel/__init__.py +40 -6
- relationalai/semantics/metamodel/builtins.py +771 -205
- relationalai/semantics/metamodel/compiler.py +133 -0
- relationalai/semantics/metamodel/dependency.py +862 -0
- relationalai/semantics/metamodel/executor.py +61 -0
- relationalai/semantics/metamodel/factory.py +287 -0
- relationalai/semantics/metamodel/helpers.py +361 -0
- relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
- relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
- relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
- relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
- relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
- relationalai/semantics/metamodel/typer/checker.py +353 -0
- relationalai/semantics/metamodel/typer/typer.py +1399 -0
- relationalai/semantics/metamodel/util.py +506 -0
- relationalai/semantics/reasoners/__init__.py +10 -0
- relationalai/semantics/reasoners/graph/README.md +620 -0
- relationalai/semantics/reasoners/graph/__init__.py +37 -0
- relationalai/semantics/reasoners/graph/core.py +9019 -0
- relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +797 -0
- relationalai/semantics/reasoners/graph/tests/README.md +21 -0
- relationalai/semantics/reasoners/optimization/__init__.py +68 -0
- relationalai/semantics/reasoners/optimization/common.py +88 -0
- relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
- relationalai/semantics/reasoners/optimization/solvers_pb.py +1414 -0
- relationalai/semantics/rel/builtins.py +40 -0
- relationalai/semantics/rel/compiler.py +989 -0
- relationalai/semantics/rel/executor.py +362 -0
- relationalai/semantics/rel/rel.py +482 -0
- relationalai/semantics/rel/rel_utils.py +276 -0
- relationalai/semantics/snowflake/__init__.py +3 -0
- relationalai/semantics/sql/compiler.py +2503 -0
- relationalai/semantics/sql/executor/duck_db.py +52 -0
- relationalai/semantics/sql/executor/result_helpers.py +64 -0
- relationalai/semantics/sql/executor/snowflake.py +149 -0
- relationalai/semantics/sql/rewrite/denormalize.py +222 -0
- relationalai/semantics/sql/rewrite/double_negation.py +49 -0
- relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
- relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
- relationalai/semantics/sql/sql.py +504 -0
- relationalai/semantics/std/__init__.py +40 -60
- relationalai/semantics/std/constraints.py +43 -37
- relationalai/semantics/std/datetime.py +135 -246
- relationalai/semantics/std/decimals.py +52 -45
- relationalai/semantics/std/floats.py +5 -13
- relationalai/semantics/std/integers.py +11 -26
- relationalai/semantics/std/math.py +112 -183
- relationalai/semantics/std/pragmas.py +11 -0
- relationalai/semantics/std/re.py +62 -80
- relationalai/semantics/std/std.py +14 -0
- relationalai/semantics/std/strings.py +60 -117
- relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
- relationalai/semantics/tests/test_snapshot_base.py +9 -0
- relationalai/semantics/tests/utils.py +46 -0
- relationalai/std/__init__.py +70 -0
- relationalai/tools/cli.py +2089 -0
- relationalai/tools/cli_controls.py +1826 -0
- relationalai/tools/cli_helpers.py +802 -0
- relationalai/tools/debugger.py +183 -289
- relationalai/tools/debugger_client.py +109 -0
- relationalai/tools/debugger_server.py +302 -0
- relationalai/tools/dev.py +685 -0
- relationalai/tools/notes +7 -0
- relationalai/tools/qb_debugger.py +425 -0
- relationalai/util/clean_up_databases.py +95 -0
- relationalai/util/format.py +106 -48
- relationalai/util/list_databases.py +9 -0
- relationalai/util/otel_configuration.py +26 -0
- relationalai/util/otel_handler.py +484 -0
- relationalai/util/snowflake_handler.py +88 -0
- relationalai/util/span_format_test.py +43 -0
- relationalai/util/span_tracker.py +207 -0
- relationalai/util/spans_file_handler.py +72 -0
- relationalai/util/tracing_handler.py +34 -0
- relationalai-0.13.2.dist-info/METADATA +74 -0
- relationalai-0.13.2.dist-info/RECORD +460 -0
- relationalai-0.13.2.dist-info/WHEEL +4 -0
- relationalai-0.13.2.dist-info/entry_points.txt +3 -0
- relationalai-0.13.2.dist-info/licenses/LICENSE +202 -0
- relationalai_test_util/__init__.py +4 -0
- relationalai_test_util/fixtures.py +233 -0
- relationalai_test_util/snapshot.py +252 -0
- relationalai_test_util/traceback.py +118 -0
- relationalai/config/__init__.py +0 -56
- relationalai/config/config.py +0 -289
- relationalai/config/config_fields.py +0 -86
- relationalai/config/connections/__init__.py +0 -46
- relationalai/config/connections/base.py +0 -23
- relationalai/config/connections/duckdb.py +0 -29
- relationalai/config/connections/snowflake.py +0 -243
- relationalai/config/external/__init__.py +0 -17
- relationalai/config/external/dbt_converter.py +0 -101
- relationalai/config/external/dbt_models.py +0 -93
- relationalai/config/external/snowflake_converter.py +0 -41
- relationalai/config/external/snowflake_models.py +0 -85
- relationalai/config/external/utils.py +0 -19
- relationalai/semantics/backends/lqp/annotations.py +0 -11
- relationalai/semantics/backends/sql/sql_compiler.py +0 -327
- relationalai/semantics/frontend/base.py +0 -1707
- relationalai/semantics/frontend/core.py +0 -179
- relationalai/semantics/frontend/front_compiler.py +0 -1313
- relationalai/semantics/frontend/pprint.py +0 -408
- relationalai/semantics/metamodel/metamodel.py +0 -437
- relationalai/semantics/metamodel/metamodel_analyzer.py +0 -519
- relationalai/semantics/metamodel/metamodel_compiler.py +0 -0
- relationalai/semantics/metamodel/pprint.py +0 -412
- relationalai/semantics/metamodel/rewriter.py +0 -266
- relationalai/semantics/metamodel/typer.py +0 -1378
- relationalai/semantics/std/aggregates.py +0 -149
- relationalai/semantics/std/common.py +0 -44
- relationalai/semantics/std/numbers.py +0 -86
- relationalai/shims/executor.py +0 -147
- relationalai/shims/helpers.py +0 -126
- relationalai/shims/hoister.py +0 -221
- relationalai/shims/mm2v0.py +0 -1290
- relationalai/tools/cli/__init__.py +0 -6
- relationalai/tools/cli/cli.py +0 -90
- relationalai/tools/cli/components/__init__.py +0 -5
- relationalai/tools/cli/components/progress_reader.py +0 -1524
- relationalai/tools/cli/components/utils.py +0 -58
- relationalai/tools/cli/config_template.py +0 -45
- relationalai/tools/cli/dev.py +0 -19
- relationalai/tools/typer_debugger.py +0 -93
- relationalai/util/dataclasses.py +0 -43
- relationalai/util/docutils.py +0 -40
- relationalai/util/error.py +0 -199
- relationalai/util/naming.py +0 -145
- relationalai/util/python.py +0 -35
- relationalai/util/runtime.py +0 -156
- relationalai/util/schema.py +0 -197
- relationalai/util/source.py +0 -185
- relationalai/util/structures.py +0 -163
- relationalai/util/tracing.py +0 -261
- relationalai-0.13.0.dev0.dist-info/METADATA +0 -46
- relationalai-0.13.0.dev0.dist-info/RECORD +0 -488
- relationalai-0.13.0.dev0.dist-info/WHEEL +0 -5
- relationalai-0.13.0.dev0.dist-info/entry_points.txt +0 -3
- relationalai-0.13.0.dev0.dist-info/top_level.txt +0 -2
- v0/relationalai/__init__.py +0 -216
- v0/relationalai/clients/__init__.py +0 -5
- v0/relationalai/clients/azure.py +0 -477
- v0/relationalai/clients/client.py +0 -912
- v0/relationalai/clients/config.py +0 -673
- v0/relationalai/clients/direct_access_client.py +0 -118
- v0/relationalai/clients/hash_util.py +0 -31
- v0/relationalai/clients/local.py +0 -571
- v0/relationalai/clients/profile_polling.py +0 -73
- v0/relationalai/clients/result_helpers.py +0 -420
- v0/relationalai/clients/snowflake.py +0 -3869
- v0/relationalai/clients/types.py +0 -113
- v0/relationalai/clients/use_index_poller.py +0 -980
- v0/relationalai/clients/util.py +0 -356
- v0/relationalai/debugging.py +0 -389
- v0/relationalai/dsl.py +0 -1749
- v0/relationalai/early_access/builder/__init__.py +0 -30
- v0/relationalai/early_access/builder/builder/__init__.py +0 -35
- v0/relationalai/early_access/builder/snowflake/__init__.py +0 -12
- v0/relationalai/early_access/builder/std/__init__.py +0 -25
- v0/relationalai/early_access/builder/std/decimals/__init__.py +0 -12
- v0/relationalai/early_access/builder/std/integers/__init__.py +0 -12
- v0/relationalai/early_access/builder/std/math/__init__.py +0 -12
- v0/relationalai/early_access/builder/std/strings/__init__.py +0 -14
- v0/relationalai/early_access/devtools/__init__.py +0 -12
- v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
- v0/relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
- v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
- v0/relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
- v0/relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
- v0/relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
- v0/relationalai/early_access/dsl/bindings/common.py +0 -402
- v0/relationalai/early_access/dsl/bindings/csv.py +0 -170
- v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
- v0/relationalai/early_access/dsl/bindings/snowflake.py +0 -64
- v0/relationalai/early_access/dsl/codegen/binder.py +0 -411
- v0/relationalai/early_access/dsl/codegen/common.py +0 -79
- v0/relationalai/early_access/dsl/codegen/helpers.py +0 -23
- v0/relationalai/early_access/dsl/codegen/relations.py +0 -700
- v0/relationalai/early_access/dsl/codegen/weaver.py +0 -417
- v0/relationalai/early_access/dsl/core/builders/__init__.py +0 -47
- v0/relationalai/early_access/dsl/core/builders/logic.py +0 -19
- v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
- v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
- v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
- v0/relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
- v0/relationalai/early_access/dsl/core/context.py +0 -13
- v0/relationalai/early_access/dsl/core/cset.py +0 -132
- v0/relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
- v0/relationalai/early_access/dsl/core/exprs/relational.py +0 -18
- v0/relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
- v0/relationalai/early_access/dsl/core/instances.py +0 -44
- v0/relationalai/early_access/dsl/core/logic/__init__.py +0 -193
- v0/relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
- v0/relationalai/early_access/dsl/core/logic/exists.py +0 -223
- v0/relationalai/early_access/dsl/core/logic/helper.py +0 -163
- v0/relationalai/early_access/dsl/core/namespaces.py +0 -32
- v0/relationalai/early_access/dsl/core/relations.py +0 -276
- v0/relationalai/early_access/dsl/core/rules.py +0 -112
- v0/relationalai/early_access/dsl/core/std/__init__.py +0 -45
- v0/relationalai/early_access/dsl/core/temporal/recall.py +0 -6
- v0/relationalai/early_access/dsl/core/types/__init__.py +0 -270
- v0/relationalai/early_access/dsl/core/types/concepts.py +0 -128
- v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
- v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
- v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
- v0/relationalai/early_access/dsl/core/types/standard.py +0 -92
- v0/relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
- v0/relationalai/early_access/dsl/core/types/variables.py +0 -203
- v0/relationalai/early_access/dsl/ir/compiler.py +0 -318
- v0/relationalai/early_access/dsl/ir/executor.py +0 -260
- v0/relationalai/early_access/dsl/ontologies/constraints.py +0 -88
- v0/relationalai/early_access/dsl/ontologies/export.py +0 -30
- v0/relationalai/early_access/dsl/ontologies/models.py +0 -453
- v0/relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
- v0/relationalai/early_access/dsl/ontologies/readings.py +0 -60
- v0/relationalai/early_access/dsl/ontologies/relationships.py +0 -322
- v0/relationalai/early_access/dsl/ontologies/roles.py +0 -87
- v0/relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
- v0/relationalai/early_access/dsl/orm/constraints.py +0 -438
- v0/relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
- v0/relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
- v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
- v0/relationalai/early_access/dsl/orm/measures/measures.py +0 -299
- v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
- v0/relationalai/early_access/dsl/orm/models.py +0 -256
- v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
- v0/relationalai/early_access/dsl/orm/printer.py +0 -469
- v0/relationalai/early_access/dsl/orm/reasoners.py +0 -480
- v0/relationalai/early_access/dsl/orm/relations.py +0 -19
- v0/relationalai/early_access/dsl/orm/relationships.py +0 -251
- v0/relationalai/early_access/dsl/orm/types.py +0 -42
- v0/relationalai/early_access/dsl/orm/utils.py +0 -79
- v0/relationalai/early_access/dsl/orm/verb.py +0 -204
- v0/relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
- v0/relationalai/early_access/dsl/relations.py +0 -170
- v0/relationalai/early_access/dsl/rulesets.py +0 -69
- v0/relationalai/early_access/dsl/schemas/__init__.py +0 -450
- v0/relationalai/early_access/dsl/schemas/builder.py +0 -48
- v0/relationalai/early_access/dsl/schemas/comp_names.py +0 -51
- v0/relationalai/early_access/dsl/schemas/components.py +0 -203
- v0/relationalai/early_access/dsl/schemas/contexts.py +0 -156
- v0/relationalai/early_access/dsl/schemas/exprs.py +0 -89
- v0/relationalai/early_access/dsl/schemas/fragments.py +0 -464
- v0/relationalai/early_access/dsl/serialization.py +0 -79
- v0/relationalai/early_access/dsl/serialize/exporter.py +0 -163
- v0/relationalai/early_access/dsl/snow/api.py +0 -104
- v0/relationalai/early_access/dsl/snow/common.py +0 -76
- v0/relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
- v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
- v0/relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
- v0/relationalai/early_access/dsl/types/__init__.py +0 -40
- v0/relationalai/early_access/dsl/types/concepts.py +0 -12
- v0/relationalai/early_access/dsl/types/entities.py +0 -135
- v0/relationalai/early_access/dsl/types/values.py +0 -17
- v0/relationalai/early_access/dsl/utils.py +0 -102
- v0/relationalai/early_access/graphs/__init__.py +0 -13
- v0/relationalai/early_access/lqp/__init__.py +0 -12
- v0/relationalai/early_access/lqp/compiler/__init__.py +0 -12
- v0/relationalai/early_access/lqp/constructors/__init__.py +0 -18
- v0/relationalai/early_access/lqp/executor/__init__.py +0 -12
- v0/relationalai/early_access/lqp/ir/__init__.py +0 -12
- v0/relationalai/early_access/lqp/passes/__init__.py +0 -12
- v0/relationalai/early_access/lqp/pragmas/__init__.py +0 -12
- v0/relationalai/early_access/lqp/primitives/__init__.py +0 -12
- v0/relationalai/early_access/lqp/types/__init__.py +0 -12
- v0/relationalai/early_access/lqp/utils/__init__.py +0 -12
- v0/relationalai/early_access/lqp/validators/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/__init__.py +0 -58
- v0/relationalai/early_access/metamodel/builtins/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/compiler/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/dependency/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/factory/__init__.py +0 -17
- v0/relationalai/early_access/metamodel/helpers/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/ir/__init__.py +0 -14
- v0/relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
- v0/relationalai/early_access/metamodel/typer/__init__.py +0 -3
- v0/relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
- v0/relationalai/early_access/metamodel/types/__init__.py +0 -15
- v0/relationalai/early_access/metamodel/util/__init__.py +0 -15
- v0/relationalai/early_access/metamodel/visitor/__init__.py +0 -12
- v0/relationalai/early_access/rel/__init__.py +0 -12
- v0/relationalai/early_access/rel/executor/__init__.py +0 -12
- v0/relationalai/early_access/rel/rel_utils/__init__.py +0 -12
- v0/relationalai/early_access/rel/rewrite/__init__.py +0 -7
- v0/relationalai/early_access/solvers/__init__.py +0 -19
- v0/relationalai/early_access/sql/__init__.py +0 -11
- v0/relationalai/early_access/sql/executor/__init__.py +0 -3
- v0/relationalai/early_access/sql/rewrite/__init__.py +0 -3
- v0/relationalai/early_access/tests/logging/__init__.py +0 -12
- v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
- v0/relationalai/early_access/tests/utils/__init__.py +0 -12
- v0/relationalai/environments/__init__.py +0 -35
- v0/relationalai/environments/base.py +0 -381
- v0/relationalai/environments/colab.py +0 -14
- v0/relationalai/environments/generic.py +0 -71
- v0/relationalai/environments/ipython.py +0 -68
- v0/relationalai/environments/jupyter.py +0 -9
- v0/relationalai/environments/snowbook.py +0 -169
- v0/relationalai/errors.py +0 -2455
- v0/relationalai/experimental/SF.py +0 -38
- v0/relationalai/experimental/inspect.py +0 -47
- v0/relationalai/experimental/pathfinder/__init__.py +0 -158
- v0/relationalai/experimental/pathfinder/api.py +0 -160
- v0/relationalai/experimental/pathfinder/automaton.py +0 -584
- v0/relationalai/experimental/pathfinder/bridge.py +0 -226
- v0/relationalai/experimental/pathfinder/compiler.py +0 -416
- v0/relationalai/experimental/pathfinder/datalog.py +0 -214
- v0/relationalai/experimental/pathfinder/diagnostics.py +0 -56
- v0/relationalai/experimental/pathfinder/filter.py +0 -236
- v0/relationalai/experimental/pathfinder/glushkov.py +0 -439
- v0/relationalai/experimental/pathfinder/options.py +0 -265
- v0/relationalai/experimental/pathfinder/rpq.py +0 -344
- v0/relationalai/experimental/pathfinder/transition.py +0 -200
- v0/relationalai/experimental/pathfinder/utils.py +0 -26
- v0/relationalai/experimental/paths/api.py +0 -143
- v0/relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
- v0/relationalai/experimental/paths/examples/basic_example.py +0 -40
- v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
- v0/relationalai/experimental/paths/examples/movie_example.py +0 -77
- v0/relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
- v0/relationalai/experimental/paths/examples/paths_example.py +0 -116
- v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
- v0/relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
- v0/relationalai/experimental/paths/graph.py +0 -185
- v0/relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
- v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
- v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
- v0/relationalai/experimental/paths/path_algorithms/single.py +0 -59
- v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
- v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
- v0/relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
- v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
- v0/relationalai/experimental/paths/path_algorithms/usp.py +0 -150
- v0/relationalai/experimental/paths/product_graph.py +0 -93
- v0/relationalai/experimental/paths/rpq/automaton.py +0 -584
- v0/relationalai/experimental/paths/rpq/diagnostics.py +0 -56
- v0/relationalai/experimental/paths/rpq/rpq.py +0 -378
- v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
- v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
- v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
- v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
- v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
- v0/relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
- v0/relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
- v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
- v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
- v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
- v0/relationalai/experimental/paths/tree_agg.py +0 -168
- v0/relationalai/experimental/paths/utilities/iterators.py +0 -27
- v0/relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
- v0/relationalai/experimental/solvers.py +0 -1087
- v0/relationalai/loaders/csv.py +0 -195
- v0/relationalai/loaders/loader.py +0 -177
- v0/relationalai/loaders/types.py +0 -23
- v0/relationalai/rel_emitter.py +0 -373
- v0/relationalai/rel_utils.py +0 -185
- v0/relationalai/semantics/__init__.py +0 -29
- v0/relationalai/semantics/devtools/benchmark_lqp.py +0 -536
- v0/relationalai/semantics/devtools/compilation_manager.py +0 -294
- v0/relationalai/semantics/devtools/extract_lqp.py +0 -110
- v0/relationalai/semantics/internal/internal.py +0 -3785
- v0/relationalai/semantics/internal/snowflake.py +0 -324
- v0/relationalai/semantics/lqp/builtins.py +0 -16
- v0/relationalai/semantics/lqp/compiler.py +0 -22
- v0/relationalai/semantics/lqp/constructors.py +0 -68
- v0/relationalai/semantics/lqp/executor.py +0 -469
- v0/relationalai/semantics/lqp/intrinsics.py +0 -24
- v0/relationalai/semantics/lqp/model2lqp.py +0 -839
- v0/relationalai/semantics/lqp/passes.py +0 -680
- v0/relationalai/semantics/lqp/primitives.py +0 -252
- v0/relationalai/semantics/lqp/result_helpers.py +0 -202
- v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
- v0/relationalai/semantics/lqp/rewrite/cdc.py +0 -216
- v0/relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
- v0/relationalai/semantics/lqp/rewrite/extract_keys.py +0 -449
- v0/relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
- v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
- v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
- v0/relationalai/semantics/lqp/rewrite/splinter.py +0 -76
- v0/relationalai/semantics/lqp/types.py +0 -101
- v0/relationalai/semantics/lqp/utils.py +0 -160
- v0/relationalai/semantics/lqp/validators.py +0 -57
- v0/relationalai/semantics/metamodel/__init__.py +0 -40
- v0/relationalai/semantics/metamodel/builtins.py +0 -774
- v0/relationalai/semantics/metamodel/compiler.py +0 -133
- v0/relationalai/semantics/metamodel/dependency.py +0 -862
- v0/relationalai/semantics/metamodel/executor.py +0 -61
- v0/relationalai/semantics/metamodel/factory.py +0 -287
- v0/relationalai/semantics/metamodel/helpers.py +0 -361
- v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
- v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
- v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
- v0/relationalai/semantics/metamodel/rewrite/flatten.py +0 -549
- v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
- v0/relationalai/semantics/metamodel/typer/checker.py +0 -353
- v0/relationalai/semantics/metamodel/typer/typer.py +0 -1395
- v0/relationalai/semantics/metamodel/util.py +0 -505
- v0/relationalai/semantics/reasoners/__init__.py +0 -10
- v0/relationalai/semantics/reasoners/graph/__init__.py +0 -37
- v0/relationalai/semantics/reasoners/graph/core.py +0 -9020
- v0/relationalai/semantics/reasoners/optimization/__init__.py +0 -68
- v0/relationalai/semantics/reasoners/optimization/common.py +0 -88
- v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
- v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
- v0/relationalai/semantics/rel/builtins.py +0 -40
- v0/relationalai/semantics/rel/compiler.py +0 -989
- v0/relationalai/semantics/rel/executor.py +0 -359
- v0/relationalai/semantics/rel/rel.py +0 -482
- v0/relationalai/semantics/rel/rel_utils.py +0 -276
- v0/relationalai/semantics/snowflake/__init__.py +0 -3
- v0/relationalai/semantics/sql/compiler.py +0 -2503
- v0/relationalai/semantics/sql/executor/duck_db.py +0 -52
- v0/relationalai/semantics/sql/executor/result_helpers.py +0 -64
- v0/relationalai/semantics/sql/executor/snowflake.py +0 -145
- v0/relationalai/semantics/sql/rewrite/denormalize.py +0 -222
- v0/relationalai/semantics/sql/rewrite/double_negation.py +0 -49
- v0/relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
- v0/relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
- v0/relationalai/semantics/sql/sql.py +0 -504
- v0/relationalai/semantics/std/__init__.py +0 -54
- v0/relationalai/semantics/std/constraints.py +0 -43
- v0/relationalai/semantics/std/datetime.py +0 -363
- v0/relationalai/semantics/std/decimals.py +0 -62
- v0/relationalai/semantics/std/floats.py +0 -7
- v0/relationalai/semantics/std/integers.py +0 -22
- v0/relationalai/semantics/std/math.py +0 -141
- v0/relationalai/semantics/std/pragmas.py +0 -11
- v0/relationalai/semantics/std/re.py +0 -83
- v0/relationalai/semantics/std/std.py +0 -14
- v0/relationalai/semantics/std/strings.py +0 -63
- v0/relationalai/semantics/tests/__init__.py +0 -0
- v0/relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
- v0/relationalai/semantics/tests/test_snapshot_base.py +0 -9
- v0/relationalai/semantics/tests/utils.py +0 -46
- v0/relationalai/std/__init__.py +0 -70
- v0/relationalai/tools/__init__.py +0 -0
- v0/relationalai/tools/cli.py +0 -1940
- v0/relationalai/tools/cli_controls.py +0 -1826
- v0/relationalai/tools/cli_helpers.py +0 -390
- v0/relationalai/tools/debugger.py +0 -183
- v0/relationalai/tools/debugger_client.py +0 -109
- v0/relationalai/tools/debugger_server.py +0 -302
- v0/relationalai/tools/dev.py +0 -685
- v0/relationalai/tools/qb_debugger.py +0 -425
- v0/relationalai/util/clean_up_databases.py +0 -95
- v0/relationalai/util/format.py +0 -123
- v0/relationalai/util/list_databases.py +0 -9
- v0/relationalai/util/otel_configuration.py +0 -25
- v0/relationalai/util/otel_handler.py +0 -484
- v0/relationalai/util/snowflake_handler.py +0 -88
- v0/relationalai/util/span_format_test.py +0 -43
- v0/relationalai/util/span_tracker.py +0 -207
- v0/relationalai/util/spans_file_handler.py +0 -72
- v0/relationalai/util/tracing_handler.py +0 -34
- /relationalai/{semantics/frontend → analysis}/__init__.py +0 -0
- {v0/relationalai → relationalai}/analysis/mechanistic.py +0 -0
- {v0/relationalai → relationalai}/analysis/whynot.py +0 -0
- /relationalai/{shims → auth}/__init__.py +0 -0
- {v0/relationalai → relationalai}/auth/jwt_generator.py +0 -0
- {v0/relationalai → relationalai}/auth/oauth_callback_server.py +0 -0
- {v0/relationalai → relationalai}/auth/token_handler.py +0 -0
- {v0/relationalai → relationalai}/auth/util.py +0 -0
- {v0/relationalai/clients → relationalai/clients/resources/snowflake}/cache_store.py +0 -0
- {v0/relationalai → relationalai}/compiler.py +0 -0
- {v0/relationalai → relationalai}/dependencies.py +0 -0
- {v0/relationalai → relationalai}/docutils.py +0 -0
- {v0/relationalai/analysis → relationalai/early_access}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/__init__.py +0 -0
- {v0/relationalai/auth → relationalai/early_access/dsl/adapters}/__init__.py +0 -0
- {v0/relationalai/early_access → relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
- {v0/relationalai/early_access/dsl/adapters → relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
- {v0/relationalai/early_access/dsl/adapters/orm → relationalai/early_access/dsl/bindings}/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/adapters/owl → relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/bindings → relationalai/early_access/dsl/codegen}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/constants.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/core/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/core/stack.py +0 -0
- {v0/relationalai/early_access/dsl/bindings/legacy → relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/core/utils.py +0 -0
- {v0/relationalai/early_access/dsl/codegen → relationalai/early_access/dsl/ir}/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/core/temporal → relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
- {v0/relationalai/early_access/dsl/ir → relationalai/early_access/dsl/orm}/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/ontologies → relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
- {v0/relationalai/early_access/dsl/orm → relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/orm/measures → relationalai/early_access/dsl/serialize}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
- {v0/relationalai → relationalai}/early_access/dsl/serialize/model.py +0 -0
- {v0/relationalai/early_access/dsl/physical_metadata → relationalai/early_access/dsl/snow}/__init__.py +0 -0
- {v0/relationalai → relationalai}/early_access/tests/__init__.py +0 -0
- {v0/relationalai → relationalai}/environments/ci.py +0 -0
- {v0/relationalai → relationalai}/environments/hex.py +0 -0
- {v0/relationalai → relationalai}/environments/terminal.py +0 -0
- {v0/relationalai → relationalai}/experimental/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/graphs.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/rpq/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/rpq/filter.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/rpq/glushkov.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/rpq/transition.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/utilities/__init__.py +0 -0
- {v0/relationalai → relationalai}/experimental/paths/utilities/utilities.py +0 -0
- {v0/relationalai/early_access/dsl/serialize → relationalai/loaders}/__init__.py +0 -0
- {v0/relationalai → relationalai}/metagen.py +0 -0
- {v0/relationalai → relationalai}/metamodel.py +0 -0
- {v0/relationalai → relationalai}/rel.py +0 -0
- {v0/relationalai → relationalai}/semantics/devtools/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/internal/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/internal/annotations.py +0 -0
- {v0/relationalai → relationalai}/semantics/lqp/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/lqp/ir.py +0 -0
- {v0/relationalai → relationalai}/semantics/lqp/pragmas.py +0 -0
- {v0/relationalai → relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/dataflow.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/ir.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/typer/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/types.py +0 -0
- {v0/relationalai → relationalai}/semantics/metamodel/visitor.py +0 -0
- {v0/relationalai → relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/rel/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/sql/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/sql/executor/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/sql/rewrite/__init__.py +0 -0
- {v0/relationalai/early_access/dsl/snow → relationalai/semantics/tests}/__init__.py +0 -0
- {v0/relationalai → relationalai}/semantics/tests/logging.py +0 -0
- {v0/relationalai → relationalai}/std/aggregates.py +0 -0
- {v0/relationalai → relationalai}/std/dates.py +0 -0
- {v0/relationalai → relationalai}/std/graphs.py +0 -0
- {v0/relationalai → relationalai}/std/inspect.py +0 -0
- {v0/relationalai → relationalai}/std/math.py +0 -0
- {v0/relationalai → relationalai}/std/re.py +0 -0
- {v0/relationalai → relationalai}/std/strings.py +0 -0
- {v0/relationalai/loaders → relationalai/tools}/__init__.py +0 -0
- {v0/relationalai → relationalai}/tools/cleanup_snapshots.py +0 -0
- {v0/relationalai → relationalai}/tools/constants.py +0 -0
- {v0/relationalai → relationalai}/tools/query_utils.py +0 -0
- {v0/relationalai → relationalai}/tools/snapshot_viewer.py +0 -0
- {v0/relationalai → relationalai}/util/__init__.py +0 -0
- {v0/relationalai → relationalai}/util/constants.py +0 -0
- {v0/relationalai → relationalai}/util/graph.py +0 -0
- {v0/relationalai → relationalai}/util/timeout.py +0 -0
|
@@ -0,0 +1,862 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Support for dependency analysis of metamodel IRs.
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Iterable, Optional
|
|
7
|
+
from itertools import count
|
|
8
|
+
from more_itertools import peekable
|
|
9
|
+
from relationalai.semantics.metamodel import builtins, ir, helpers, visitor
|
|
10
|
+
from relationalai.semantics.metamodel.util import OrderedSet, ordered_set
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
#--------------------------------------------------
|
|
14
|
+
# Public API
|
|
15
|
+
#--------------------------------------------------
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class DependencyInfo():
|
|
19
|
+
"""
|
|
20
|
+
Represents the result of performing binding and dependency analysis on a metamodel tree.
|
|
21
|
+
|
|
22
|
+
All dicts are keyed by task ids.
|
|
23
|
+
"""
|
|
24
|
+
# input vars for a task
|
|
25
|
+
input_bindings: dict[int, OrderedSet[ir.Var]] = field(default_factory=dict)
|
|
26
|
+
# output vars for a task
|
|
27
|
+
output_bindings: dict[int, OrderedSet[ir.Var]] = field(default_factory=dict)
|
|
28
|
+
# clusters of dependency that each task participates on
|
|
29
|
+
dependency_clusters: dict[int, Cluster] = field(default_factory=dict)
|
|
30
|
+
# keep track of the parents of each task
|
|
31
|
+
parent: dict[int, ir.Task] = field(default_factory=dict)
|
|
32
|
+
# keep track of replacements that were made during a rewrite
|
|
33
|
+
replacements: dict[int, ir.Task] = field(default_factory=dict)
|
|
34
|
+
|
|
35
|
+
def task_inputs(self, node: ir.Task) -> Optional[OrderedSet[ir.Var]]:
|
|
36
|
+
""" The input variables for this task, if any. """
|
|
37
|
+
if node.id in self.input_bindings:
|
|
38
|
+
return self.input_bindings[node.id]
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
def has_inputs(self, node: ir.Task):
|
|
42
|
+
return node.id in self.input_bindings
|
|
43
|
+
|
|
44
|
+
def task_outputs(self, node: ir.Task) -> Optional[OrderedSet[ir.Var]]:
|
|
45
|
+
""" The output variables for this task, if any. """
|
|
46
|
+
if node.id in self.output_bindings:
|
|
47
|
+
return self.output_bindings[node.id]
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
def has_outputs(self, node: ir.Task):
|
|
51
|
+
return node.id in self.output_bindings
|
|
52
|
+
|
|
53
|
+
def task_dependencies(self, task: ir.Task) -> OrderedSet[ir.Task]:
|
|
54
|
+
"""
|
|
55
|
+
All dependencies for this task, if any. This includes tasks in outer contexts,
|
|
56
|
+
not only siblings.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
deps = ordered_set()
|
|
60
|
+
cluster = self.dependency_clusters.get(task.id, None)
|
|
61
|
+
parent = self.parent.get(task.id)
|
|
62
|
+
|
|
63
|
+
if cluster:
|
|
64
|
+
self._collect_deps(cluster, deps)
|
|
65
|
+
while parent:
|
|
66
|
+
cluster = self.dependency_clusters.get(parent.id, None)
|
|
67
|
+
if cluster:
|
|
68
|
+
self._collect_deps(cluster, deps)
|
|
69
|
+
parent = self.parent[cluster.content[0].id]
|
|
70
|
+
else:
|
|
71
|
+
parent = None
|
|
72
|
+
return self._with_replacements(deps)
|
|
73
|
+
|
|
74
|
+
def local_dependencies(self, task: ir.Task) -> Optional[OrderedSet[ir.Task]]:
|
|
75
|
+
""" Similar to task_dependencies but returns only dependencies that are siblings. """
|
|
76
|
+
|
|
77
|
+
if task.id in self.dependency_clusters:
|
|
78
|
+
deps = ordered_set()
|
|
79
|
+
self._collect_deps(self.dependency_clusters[task.id], deps)
|
|
80
|
+
return self._with_replacements(deps)
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
def replaced(self, original: ir.Task, replacement: ir.Task):
|
|
84
|
+
"""
|
|
85
|
+
Inform that, during some pass, this original task was replaced with this replacement
|
|
86
|
+
task. This affects the info of .task_dependencies(...) since it will answer with
|
|
87
|
+
the replacement when the original is in the set of dependencies.
|
|
88
|
+
"""
|
|
89
|
+
self.replacements[original.id] = replacement
|
|
90
|
+
|
|
91
|
+
#
|
|
92
|
+
# Implementation details
|
|
93
|
+
#
|
|
94
|
+
def _collect_deps(self, cluster: Cluster, deps: OrderedSet[ir.Task]):
|
|
95
|
+
queue = []
|
|
96
|
+
# start with the cluster dependencies, because cluster represents the task we
|
|
97
|
+
# care about
|
|
98
|
+
queue.extend(cluster.dependencies)
|
|
99
|
+
seen = set()
|
|
100
|
+
while queue:
|
|
101
|
+
cluster = queue.pop()
|
|
102
|
+
if cluster.id in seen:
|
|
103
|
+
continue
|
|
104
|
+
seen.add(cluster.id)
|
|
105
|
+
deps.update(cluster.content)
|
|
106
|
+
queue.extend(cluster.dependencies)
|
|
107
|
+
|
|
108
|
+
def _with_replacements(self, deps):
|
|
109
|
+
# Return deps with all tasks that need replacements (because they are in the
|
|
110
|
+
# replacements dict) replaced.
|
|
111
|
+
if any([dep.id in self.replacements for dep in deps]):
|
|
112
|
+
# Only allocate and compute replacements if there's a dep that was replaced
|
|
113
|
+
info = ordered_set()
|
|
114
|
+
for dep in deps:
|
|
115
|
+
info.add(self.replacements.get(dep.id, dep))
|
|
116
|
+
return info
|
|
117
|
+
return deps
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def analyze_bindings(task: ir.Task) -> DependencyInfo:
|
|
121
|
+
"""
|
|
122
|
+
Perform just the binding analysis, skipping the dependency analysis. This is useful
|
|
123
|
+
for passes that only require knowing the input/output sets for nodes, but do not need
|
|
124
|
+
the more expensive dependency information.
|
|
125
|
+
|
|
126
|
+
The returned DependencyInfo object will only have input and output bindings filled.
|
|
127
|
+
"""
|
|
128
|
+
binding = BindingAnalysis()
|
|
129
|
+
task.accept(binding)
|
|
130
|
+
return binding.info
|
|
131
|
+
|
|
132
|
+
def analyze(task: ir.Task) -> DependencyInfo:
|
|
133
|
+
"""
|
|
134
|
+
Perform binding and dependency analysis on this task.
|
|
135
|
+
|
|
136
|
+
The returned DependencyInfo object will have all dictionaries filled.
|
|
137
|
+
"""
|
|
138
|
+
# first perform binding analysis to get inputs and outputs
|
|
139
|
+
info = analyze_bindings(task)
|
|
140
|
+
|
|
141
|
+
# TODO - if the toplevel task needs inputs, that's a groundness error
|
|
142
|
+
|
|
143
|
+
# now perform the dependency analysis
|
|
144
|
+
dependency = DependencyAnalysis(info)
|
|
145
|
+
task.accept(dependency)
|
|
146
|
+
return info
|
|
147
|
+
|
|
148
|
+
#--------------------------------------------------
|
|
149
|
+
# Dependency Analysis
|
|
150
|
+
#--------------------------------------------------
|
|
151
|
+
|
|
152
|
+
# id generator for Clusters
|
|
153
|
+
_global_id = peekable(count(0))
|
|
154
|
+
def next_id():
|
|
155
|
+
return next(_global_id)
|
|
156
|
+
|
|
157
|
+
class Cluster():
|
|
158
|
+
def __init__(self, info: DependencyInfo, task: ir.Task):
|
|
159
|
+
""" Create a cluster starting with only this task. """
|
|
160
|
+
self.id = next_id()
|
|
161
|
+
self.info = info
|
|
162
|
+
# exists and lookups for nullary relations are always required (i.e. everything
|
|
163
|
+
# should depend on them)
|
|
164
|
+
self.required = isinstance(task, ir.Exists) or (isinstance(task, ir.Lookup) and not task.args)
|
|
165
|
+
# this is a binders cluster, which is a candidate to being merged
|
|
166
|
+
self.mergeable = not self.required and isinstance(task, helpers.BINDERS)
|
|
167
|
+
# this is a cluster that will only hold an effect
|
|
168
|
+
self.effectful = isinstance(task, helpers.EFFECTS)
|
|
169
|
+
# this is a cluster that will only hold a composite
|
|
170
|
+
self.composite = isinstance(task, helpers.COMPOSITES)
|
|
171
|
+
# content is either a single task or a set of tasks
|
|
172
|
+
self.content: OrderedSet[ir.Task] = ordered_set(task)
|
|
173
|
+
# combined inputs and outputs for all tasks in the cluster
|
|
174
|
+
self.inputs: OrderedSet[ir.Var] = OrderedSet.from_iterable(info.input_bindings.get(task.id))
|
|
175
|
+
self.outputs: OrderedSet[ir.Var] = OrderedSet.from_iterable(info.output_bindings.get(task.id))
|
|
176
|
+
# eventually we will compute dependencies between clusters
|
|
177
|
+
self.dependencies: OrderedSet[Cluster] = ordered_set()
|
|
178
|
+
|
|
179
|
+
def __str__(self) -> str:
|
|
180
|
+
if isinstance(self.content, ir.Task):
|
|
181
|
+
return str(self.content.id)
|
|
182
|
+
else:
|
|
183
|
+
return ', '.join(str(node.id) for node in self.content)
|
|
184
|
+
|
|
185
|
+
def __eq__(self, other):
|
|
186
|
+
return isinstance(other, Cluster) and other.id == self.id
|
|
187
|
+
|
|
188
|
+
def __hash__(self):
|
|
189
|
+
return hash(self.id)
|
|
190
|
+
|
|
191
|
+
def depends_on(self, other: Cluster):
|
|
192
|
+
""" Assert that this cluster depends on the other cluster. """
|
|
193
|
+
if self in other.dependencies:
|
|
194
|
+
# prevent cycles caused by bugs, like the union hoisting pets in the
|
|
195
|
+
# relationship7 test
|
|
196
|
+
print("Warning: there is a cycle in the dependency graph. This is likely a bug.")
|
|
197
|
+
# k = ','.join(str(x.id) for x in self.content)
|
|
198
|
+
# v = ','.join(str(x.id) for x in other.content)
|
|
199
|
+
# print(f"{k} --> {v}")
|
|
200
|
+
else:
|
|
201
|
+
self.dependencies.add(other)
|
|
202
|
+
|
|
203
|
+
def shares_variable(self, other: Cluster):
|
|
204
|
+
""" Returns True iff this cluster and the other cluster have at least one var in common. """
|
|
205
|
+
return (
|
|
206
|
+
any(i in other.inputs or i in other.outputs for i in self.inputs) or
|
|
207
|
+
any(o in other.inputs or o in other.outputs for o in self.outputs)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
def try_merge(self, other: Cluster, hoisted_vars: OrderedSet[ir.Var]):
|
|
211
|
+
"""
|
|
212
|
+
Verify that this cluster and the other cluster can be merged. If so, merge the
|
|
213
|
+
other cluster into this cluster and return True. Otherwise, return False and the
|
|
214
|
+
clusters are left unmodified.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
# 1. only mergeable
|
|
218
|
+
if not (self.mergeable and other.mergeable):
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
# 2. share some variable
|
|
222
|
+
if not self.shares_variable(other):
|
|
223
|
+
return False
|
|
224
|
+
|
|
225
|
+
# 3. all inputs are covered by outputs within the cluster
|
|
226
|
+
if not all(v in self.outputs or v in other.outputs for v in self.inputs):
|
|
227
|
+
return False
|
|
228
|
+
if not all(v in self.outputs or v in other.outputs for v in other.inputs):
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
# 4. if there are hoisted vars in context, we can only merge clusters that bind the
|
|
232
|
+
# same hoisted vars
|
|
233
|
+
if hoisted_vars:
|
|
234
|
+
for v in hoisted_vars:
|
|
235
|
+
# if self binds v and other does not bind v, they can't be merged
|
|
236
|
+
if v in self.outputs or v in self.inputs:
|
|
237
|
+
if v not in other.outputs or v not in other.inputs:
|
|
238
|
+
return False
|
|
239
|
+
# the other way around
|
|
240
|
+
if v in other.outputs or v in other.inputs:
|
|
241
|
+
if v not in self.outputs or v not in self.inputs:
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
# ok, can merge
|
|
245
|
+
self.merge(other)
|
|
246
|
+
return True
|
|
247
|
+
|
|
248
|
+
def try_merge_group(self, others: list[Cluster]):
|
|
249
|
+
"""
|
|
250
|
+
Verify that this cluster and the other clusters can all be merged together. If so,
|
|
251
|
+
merge the other clusters into this cluster and return True. Otherwise, return False
|
|
252
|
+
and all clusters are left unmodified.
|
|
253
|
+
"""
|
|
254
|
+
assert(len(others) > 0)
|
|
255
|
+
|
|
256
|
+
# 1. only mergeable
|
|
257
|
+
if not (self.mergeable and all(o.mergeable for o in others)):
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
# 2. share some variable
|
|
261
|
+
if not self.shares_variable(others[0]):
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
# 3. all inputs are covered by outputs within the newly formed cluster
|
|
265
|
+
if len(others) == 1:
|
|
266
|
+
others_outputs = others[0].outputs
|
|
267
|
+
else:
|
|
268
|
+
others_outputs = ordered_set()
|
|
269
|
+
[others_outputs.update(o.outputs) for o in others]
|
|
270
|
+
if not all(v in self.outputs or v in others_outputs for v in self.inputs):
|
|
271
|
+
return False
|
|
272
|
+
for other in others:
|
|
273
|
+
if not all(v in self.outputs or v in others_outputs for v in other.inputs):
|
|
274
|
+
return False
|
|
275
|
+
|
|
276
|
+
# ok, can merge
|
|
277
|
+
self.merge(others)
|
|
278
|
+
return True
|
|
279
|
+
|
|
280
|
+
def merge(self, other: Cluster|Iterable[Cluster]):
|
|
281
|
+
"""
|
|
282
|
+
Merge the other cluster(s) into this one. This assumes that the merge makes sense.
|
|
283
|
+
In general, we should use try_merge or try_merge_group instead.
|
|
284
|
+
"""
|
|
285
|
+
# merge the other cluster's content, inputs and outputs
|
|
286
|
+
if isinstance(other, Cluster):
|
|
287
|
+
self.content.update(other.content)
|
|
288
|
+
self.inputs.update(other.inputs)
|
|
289
|
+
self.outputs.update(other.outputs)
|
|
290
|
+
# update dependencies, ensuring we remove the other from the self
|
|
291
|
+
self.dependencies.update(other.dependencies)
|
|
292
|
+
self.dependencies.remove(other)
|
|
293
|
+
else:
|
|
294
|
+
for o in other:
|
|
295
|
+
self.content.update(o.content)
|
|
296
|
+
self.inputs.update(o.inputs)
|
|
297
|
+
self.outputs.update(o.outputs)
|
|
298
|
+
self.dependencies.update(o.dependencies)
|
|
299
|
+
self.dependencies.remove(o)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class DependencyAnalysis(visitor.Visitor):
|
|
303
|
+
"""
|
|
304
|
+
A visitor to perform dependency analysis in logicals and store the result in a
|
|
305
|
+
DependencyInfo object.
|
|
306
|
+
|
|
307
|
+
The dependency analysis is performed for Logical nodes in 3 steps:
|
|
308
|
+
|
|
309
|
+
1. form clusters of children that are mutually dependent, because they are binders (like
|
|
310
|
+
lookups and aggregates) that have variables in common.
|
|
311
|
+
|
|
312
|
+
2. compute dependencies between the clusters based on input and outputs.
|
|
313
|
+
|
|
314
|
+
3. attempt to merge clusters that could form larger clusters.
|
|
315
|
+
|
|
316
|
+
Consider the following example, where we are computing dependencies for the numbered nodes:
|
|
317
|
+
|
|
318
|
+
Logical
|
|
319
|
+
|1| Edges(edges)
|
|
320
|
+
|2| i(edges, i)
|
|
321
|
+
|3| Logical ⇑[v]
|
|
322
|
+
Logical ⇑[j=None]
|
|
323
|
+
j(edges, j)
|
|
324
|
+
count([edges, j], [i], [v])
|
|
325
|
+
|4| i < 10
|
|
326
|
+
|5| i < v
|
|
327
|
+
|6| Logical ⇑[v_2=None]
|
|
328
|
+
max([i], [], [v, v_2])
|
|
329
|
+
|7| → output[i](v, v_2 as 'v2')
|
|
330
|
+
|
|
331
|
+
In step 1., we merge (1,2,4) because they have `edges` and `i` in common, but nothing
|
|
332
|
+
else. In particular, (5) is not merged as it also depends on v.
|
|
333
|
+
|
|
334
|
+
In step 2. we compute dependencies:
|
|
335
|
+
(1,2,4)
|
|
336
|
+
(3) -> (1,2,4)
|
|
337
|
+
(5) -> (1,2,4), (3)
|
|
338
|
+
(6) -> (1,2,4), (3), (5)
|
|
339
|
+
(7) -> (1,2,4), (3), (5), (6)
|
|
340
|
+
|
|
341
|
+
For this example, step 3. does not change anything.
|
|
342
|
+
|
|
343
|
+
This result can be interpreted as, in order to compute task 6, tasks (1,2,4), (3) and (5)
|
|
344
|
+
must hold. This means that a compiler pass that extracts the logical in task 6 into its
|
|
345
|
+
own top-level logical must bring these dependencies together.
|
|
346
|
+
|
|
347
|
+
To illustrate the need for step 3, consider this example:
|
|
348
|
+
|
|
349
|
+
Logical
|
|
350
|
+
|1| Edge(edge)
|
|
351
|
+
|2| i(edge, i)
|
|
352
|
+
|3| Edge(edge_2)
|
|
353
|
+
|4| j(edge_2, j)
|
|
354
|
+
|5| i = j
|
|
355
|
+
|6| Logical ⇑[res=None]
|
|
356
|
+
.....
|
|
357
|
+
|7| → output[edge, j, i](i, res)
|
|
358
|
+
|
|
359
|
+
The result of step 2 is the following:
|
|
360
|
+
(1,2)
|
|
361
|
+
(3,4)
|
|
362
|
+
(5) -> (1,2), (3,4)
|
|
363
|
+
(6) -> (1,2), (3,4), (5)
|
|
364
|
+
(7) -> (1,2), (3,4), (5), (6)
|
|
365
|
+
|
|
366
|
+
Step 3 observes that task (5) is a bridge between (1,2) and (3,4), so that merging those
|
|
367
|
+
3 clusters together yields a consistent cluster. So the result is:
|
|
368
|
+
|
|
369
|
+
(1,2,3,4,5)
|
|
370
|
+
(6) -> (1,2,3,4,5)
|
|
371
|
+
(7) -> (1,2,3,4,5), (6)
|
|
372
|
+
|
|
373
|
+
"""
|
|
374
|
+
def __init__(self, info: DependencyInfo):
|
|
375
|
+
self.info = info
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def enter(self, node: ir.Node, parent: Optional[ir.Node]=None):
|
|
379
|
+
# keep track of parents of all nodes
|
|
380
|
+
if parent and isinstance(parent, ir.Task):
|
|
381
|
+
self.info.parent[node.id] = parent
|
|
382
|
+
return super().enter(node, parent)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def visit_logical(self, node: ir.Logical, parent: Optional[ir.Node]):
|
|
386
|
+
# quick check to see if it's worth it computing clusters at all
|
|
387
|
+
some_child_has_bindings = False
|
|
388
|
+
for child in node.body:
|
|
389
|
+
if child.id in self.info.input_bindings or child.id in self.info.output_bindings:
|
|
390
|
+
some_child_has_bindings = True
|
|
391
|
+
break
|
|
392
|
+
|
|
393
|
+
if some_child_has_bindings:
|
|
394
|
+
# print(ir.node_to_string(node, print_ids=True))
|
|
395
|
+
# compute clusters for the nodes based on inputs/outputs and shared variables
|
|
396
|
+
clusters = self.compute_clusters(node)
|
|
397
|
+
# compute the dependencies between those clusters
|
|
398
|
+
self.compute_dependencies(clusters)
|
|
399
|
+
# attempt to further merge clusters
|
|
400
|
+
self.merge_clusters(clusters)
|
|
401
|
+
# index the clusters by tasks participating in those clusters, and record it
|
|
402
|
+
self.index(clusters)
|
|
403
|
+
# self._print_debug_info(node, clusters)
|
|
404
|
+
|
|
405
|
+
return super().visit_logical(node, parent)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def compute_clusters(self, task: ir.Logical) -> list[Cluster]:
|
|
409
|
+
"""
|
|
410
|
+
Cluster the children of the logical, storing together children that are mutually
|
|
411
|
+
dependent.
|
|
412
|
+
"""
|
|
413
|
+
# create initial clusters
|
|
414
|
+
clusters:list[Cluster] = [Cluster(self.info, child) for child in task.body]
|
|
415
|
+
|
|
416
|
+
# all hoisted vars of children, used to ensure we don't merge clusters that depend
|
|
417
|
+
# on a variable hoisted by a composite
|
|
418
|
+
hoisted_vars = ordered_set()
|
|
419
|
+
for child in task.body:
|
|
420
|
+
if isinstance(child, helpers.COMPOSITES):
|
|
421
|
+
hoisted_vars.update(helpers.hoisted_vars(child.hoisted))
|
|
422
|
+
|
|
423
|
+
# iterate clustering until nothing changes
|
|
424
|
+
merging = True
|
|
425
|
+
while merging:
|
|
426
|
+
merging = False
|
|
427
|
+
cs = list(clusters)
|
|
428
|
+
while cs:
|
|
429
|
+
# last c1 merged some c2s, so cs was modified, restart
|
|
430
|
+
if merging:
|
|
431
|
+
break
|
|
432
|
+
c1 = cs.pop()
|
|
433
|
+
for c2 in cs:
|
|
434
|
+
if c1 is c2:
|
|
435
|
+
continue
|
|
436
|
+
if c1.try_merge(c2, hoisted_vars):
|
|
437
|
+
clusters.remove(c2)
|
|
438
|
+
merging = True
|
|
439
|
+
return clusters
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def compute_dependencies(self, clusters: list[Cluster]):
|
|
443
|
+
"""
|
|
444
|
+
Traverse the clusters finding dependencies between them, based on input and output
|
|
445
|
+
variables used by tasks within the clusters.
|
|
446
|
+
"""
|
|
447
|
+
def has_dependency(c1: Cluster, c2: Cluster):
|
|
448
|
+
# c2 is a required cluster, everything depends no it
|
|
449
|
+
if c2.required:
|
|
450
|
+
return True
|
|
451
|
+
# if c1 has an effect and c2 is mergeable (basically it contains only binders)
|
|
452
|
+
# then c2 behaves like a filter, so c1 must depend on it, even if it does not
|
|
453
|
+
# have variables in common (this may bring other dependencies).
|
|
454
|
+
if c1.effectful and c2.mergeable:
|
|
455
|
+
return True
|
|
456
|
+
# if c1 has an effect and c2 is a composite without hoisted variables or with a
|
|
457
|
+
# hoisted variable that does not have a default (it is a plain var), then c2
|
|
458
|
+
# behaves like a filter and c1 depends on it.
|
|
459
|
+
if c1.effectful and c2.composite:
|
|
460
|
+
task = c2.content.some()
|
|
461
|
+
assert(isinstance(task, helpers.COMPOSITES))
|
|
462
|
+
if not task.hoisted:
|
|
463
|
+
return True
|
|
464
|
+
for h in task.hoisted:
|
|
465
|
+
if isinstance(h, ir.Var): # no default
|
|
466
|
+
return True
|
|
467
|
+
|
|
468
|
+
# if c1 is a composite and c2 binds its hoisted vars, c1 can't depend on c2
|
|
469
|
+
# (dependency is the other way around)
|
|
470
|
+
if c1.composite and c1.outputs:
|
|
471
|
+
for v in c1.outputs:
|
|
472
|
+
if c2.outputs and v in c2.outputs:
|
|
473
|
+
return False
|
|
474
|
+
if c2.inputs and v in c2.inputs:
|
|
475
|
+
return False
|
|
476
|
+
|
|
477
|
+
# c1 does not depend on c2 if one of its output vars is an input to c2
|
|
478
|
+
# (dependency is the other way around)
|
|
479
|
+
if (c1.outputs and c2.inputs):
|
|
480
|
+
# optimization for any([v in c2.inputs for v in c1_outputs])):
|
|
481
|
+
for v in c1.outputs:
|
|
482
|
+
if v in c2.inputs:
|
|
483
|
+
return False
|
|
484
|
+
|
|
485
|
+
# c1 depends on c2 if one of its input vars is an output of c2
|
|
486
|
+
if (c1.inputs and c2.outputs):
|
|
487
|
+
# optimization for any([v in c2.outputs for v in c1_inputs])):
|
|
488
|
+
for v in c1.inputs:
|
|
489
|
+
if v in c2.outputs:
|
|
490
|
+
return True
|
|
491
|
+
|
|
492
|
+
# c1 is a composite with hoisted variables; it depends on c2 if c2 is a
|
|
493
|
+
# composite that does not have hoisted vars, hence behaving like a filter.
|
|
494
|
+
if c1.composite and c2.composite:
|
|
495
|
+
c1task = c1.content.some()
|
|
496
|
+
assert(isinstance(c1task, helpers.COMPOSITES))
|
|
497
|
+
if c1task.hoisted:
|
|
498
|
+
c2task = c2.content.some()
|
|
499
|
+
assert(isinstance(c2task, helpers.COMPOSITES))
|
|
500
|
+
if not c2task.hoisted:
|
|
501
|
+
return True
|
|
502
|
+
return False
|
|
503
|
+
|
|
504
|
+
cs = list(clusters)
|
|
505
|
+
while cs:
|
|
506
|
+
c1 = cs.pop()
|
|
507
|
+
for c2 in cs:
|
|
508
|
+
if c1 is c2:
|
|
509
|
+
continue
|
|
510
|
+
|
|
511
|
+
if has_dependency(c1, c2):
|
|
512
|
+
c1.depends_on(c2)
|
|
513
|
+
if has_dependency(c2, c1):
|
|
514
|
+
c2.depends_on(c1)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def merge_clusters(self, clusters: list[Cluster]):
|
|
518
|
+
"""
|
|
519
|
+
Traverse clusters trying to merge multiple clusters if they together form a larger
|
|
520
|
+
cluster.
|
|
521
|
+
"""
|
|
522
|
+
# iterate clustering until nothing changes
|
|
523
|
+
merging = True
|
|
524
|
+
while merging:
|
|
525
|
+
merging = False
|
|
526
|
+
cs = list(clusters)
|
|
527
|
+
while cs:
|
|
528
|
+
if merging:
|
|
529
|
+
break
|
|
530
|
+
c = cs.pop()
|
|
531
|
+
if c.dependencies and c.mergeable:
|
|
532
|
+
deps = list(c.dependencies)
|
|
533
|
+
if c.try_merge_group(deps):
|
|
534
|
+
# remove the deps from clusters
|
|
535
|
+
for d in deps:
|
|
536
|
+
clusters.remove(d)
|
|
537
|
+
# rewire other clusters to the new node
|
|
538
|
+
# this is not very efficient but should not happen often
|
|
539
|
+
for c2 in clusters:
|
|
540
|
+
if c2 is not c:
|
|
541
|
+
for d in deps:
|
|
542
|
+
if d in c2.dependencies:
|
|
543
|
+
c2.dependencies.add(c)
|
|
544
|
+
c2.dependencies.remove(d)
|
|
545
|
+
merging = True
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def index(self, clusters: list[Cluster]):
|
|
549
|
+
"""
|
|
550
|
+
Index clusters by task, and record in the info
|
|
551
|
+
"""
|
|
552
|
+
for dep_node in clusters:
|
|
553
|
+
for n in dep_node.content:
|
|
554
|
+
self.info.dependency_clusters[n.id] = dep_node
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def _print_debug_info(self, node, clusters: list[Cluster]):
|
|
558
|
+
# print(ir.node_to_string(node, print_ids=True))
|
|
559
|
+
print("dependencies")
|
|
560
|
+
for dep_node in clusters:
|
|
561
|
+
k = ','.join(str(x.id) for x in dep_node.content)
|
|
562
|
+
print(f"({k}) ->")
|
|
563
|
+
for v in dep_node.dependencies:
|
|
564
|
+
v = ','.join(str(x.id) for x in v.content)
|
|
565
|
+
print(f" ({v})")
|
|
566
|
+
print()
|
|
567
|
+
print("clusters")
|
|
568
|
+
for c in clusters:
|
|
569
|
+
print(f"{c}")
|
|
570
|
+
if c.inputs:
|
|
571
|
+
print(f" inputs: {','.join(str(v.name) for v in c.inputs)}")
|
|
572
|
+
if c.outputs:
|
|
573
|
+
print(f" outputs: {','.join(str(v.name) for v in c.outputs)}")
|
|
574
|
+
print()
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
class BindingAnalysis(visitor.Visitor):
|
|
579
|
+
"""
|
|
580
|
+
Visitor to perform binding analysis, i.e. figure out for each task in the tree, which
|
|
581
|
+
variables it binds as input ad output.
|
|
582
|
+
"""
|
|
583
|
+
def __init__(self):
|
|
584
|
+
self.info = DependencyInfo()
|
|
585
|
+
# a stack of variables grounded by the last logical being visited
|
|
586
|
+
self._grounded: list[OrderedSet[ir.Var]] = []
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def input(self, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
|
|
590
|
+
""" Assert that this task binds this variable(s) as input. """
|
|
591
|
+
self._register(self.info.input_bindings, key, val)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def output(self, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
|
|
595
|
+
""" Assert that this task binds this variable(s) as output. """
|
|
596
|
+
self._register(self.info.output_bindings, key, val)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
def _register(self, map, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
|
|
600
|
+
""" Register key.id -> val in this map, assuming the map holds ordered sets of vals. """
|
|
601
|
+
if val is None or (isinstance(val, Iterable) and not val):
|
|
602
|
+
return
|
|
603
|
+
if key.id not in map:
|
|
604
|
+
map[key.id] = ordered_set()
|
|
605
|
+
if isinstance(val, Iterable):
|
|
606
|
+
for v in val:
|
|
607
|
+
map[key.id].add(v)
|
|
608
|
+
else:
|
|
609
|
+
map[key.id].add(val)
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
#
|
|
613
|
+
# Composite tasks
|
|
614
|
+
#
|
|
615
|
+
def visit_logical(self, node: ir.Logical, parent: Optional[ir.Node]):
|
|
616
|
+
# compute variables grounded by children of this logical
|
|
617
|
+
grounds = ordered_set()
|
|
618
|
+
grounded_by_ancestors = None
|
|
619
|
+
if self._grounded:
|
|
620
|
+
# grounded variables inherited from ancestors or siblings
|
|
621
|
+
grounded_by_ancestors = self._grounded[-1]
|
|
622
|
+
grounds.update(grounded_by_ancestors)
|
|
623
|
+
|
|
624
|
+
potentially_grounded = ordered_set()
|
|
625
|
+
for child in node.body:
|
|
626
|
+
# leaf constructs that ground variables
|
|
627
|
+
if isinstance(child, ir.Lookup):
|
|
628
|
+
# special case eq because it can be input or output
|
|
629
|
+
# TODO: this is similar to what's done below in visit_lookup, modularize
|
|
630
|
+
if builtins.is_eq(child.relation):
|
|
631
|
+
x, y = child.args[0], child.args[1]
|
|
632
|
+
# Compute input/output vars of the equality
|
|
633
|
+
if isinstance(x, ir.Var) and not isinstance(y, ir.Var):
|
|
634
|
+
# Variable x is potentially grounded by other expressions at
|
|
635
|
+
# level in the Logical. If it is, then we should mark it as
|
|
636
|
+
# input (which is done later).
|
|
637
|
+
potentially_grounded.add((child, x, x))
|
|
638
|
+
elif not isinstance(x, ir.Var) and isinstance(y, ir.Var):
|
|
639
|
+
potentially_grounded.add((child, y, y))
|
|
640
|
+
elif isinstance(x, ir.Var) and isinstance(y, ir.Var):
|
|
641
|
+
# mark as potentially grounded, if any is grounded in other atoms then we later ground both
|
|
642
|
+
potentially_grounded.add((child, x, y))
|
|
643
|
+
else:
|
|
644
|
+
# grounds only outputs
|
|
645
|
+
for idx, f in enumerate(child.relation.fields):
|
|
646
|
+
arg = child.args[idx]
|
|
647
|
+
if not f.input and isinstance(arg, ir.Var):
|
|
648
|
+
grounds.add(arg)
|
|
649
|
+
elif isinstance(child, ir.Data):
|
|
650
|
+
# grounds all vars
|
|
651
|
+
grounds.update(child.vars)
|
|
652
|
+
elif isinstance(child, ir.Aggregate):
|
|
653
|
+
# grounds output args
|
|
654
|
+
for idx, f in enumerate(child.aggregation.fields):
|
|
655
|
+
arg = child.args[idx]
|
|
656
|
+
if not f.input and isinstance(arg, ir.Var):
|
|
657
|
+
grounds.add(arg)
|
|
658
|
+
elif isinstance(child, ir.Rank):
|
|
659
|
+
# grounds the info
|
|
660
|
+
grounds.add(child.result)
|
|
661
|
+
elif isinstance(child, ir.Construct):
|
|
662
|
+
# grounds the output var
|
|
663
|
+
grounds.add(child.id_var)
|
|
664
|
+
|
|
665
|
+
# add child hoisted vars to grounded so that they can be picked up by the children
|
|
666
|
+
for child in node.body:
|
|
667
|
+
if isinstance(child, helpers.COMPOSITES):
|
|
668
|
+
grounds.update(helpers.hoisted_vars(child.hoisted))
|
|
669
|
+
|
|
670
|
+
# equalities where both sides are already grounded mean that both sides are input
|
|
671
|
+
for child, x, y in potentially_grounded:
|
|
672
|
+
if x in grounds and y in grounds:
|
|
673
|
+
self.input(child, x)
|
|
674
|
+
self.input(child, y)
|
|
675
|
+
|
|
676
|
+
# deal with potentially grounded vars up to a fixpoint
|
|
677
|
+
changed = True
|
|
678
|
+
while changed:
|
|
679
|
+
changed = False
|
|
680
|
+
for child, x, y in potentially_grounded:
|
|
681
|
+
if x in grounds and y not in grounds:
|
|
682
|
+
self.input(child, x)
|
|
683
|
+
self.output(child, y)
|
|
684
|
+
grounds.add(y)
|
|
685
|
+
changed = True
|
|
686
|
+
elif y in grounds and x not in grounds:
|
|
687
|
+
self.input(child, y)
|
|
688
|
+
self.output(child, x)
|
|
689
|
+
grounds.add(x)
|
|
690
|
+
changed = True
|
|
691
|
+
|
|
692
|
+
# now visit the children
|
|
693
|
+
self._grounded.append(grounds)
|
|
694
|
+
super().visit_logical(node, parent)
|
|
695
|
+
self._grounded.pop()
|
|
696
|
+
|
|
697
|
+
hoisted_vars = helpers.hoisted_vars(node.hoisted)
|
|
698
|
+
if grounded_by_ancestors:
|
|
699
|
+
# inputs to this logical: grounded by ancestor while being used by a child,
|
|
700
|
+
# excluding variables hoisted by the logical
|
|
701
|
+
vars = helpers.collect_vars(node)
|
|
702
|
+
self.input(node, (grounded_by_ancestors & vars) - hoisted_vars)
|
|
703
|
+
|
|
704
|
+
# outputs are vars declared as hoisted
|
|
705
|
+
self.output(node, hoisted_vars)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def visit_union(self, node: ir.Union, parent: Optional[ir.Node]):
|
|
709
|
+
# visit children first
|
|
710
|
+
super().visit_union(node, parent)
|
|
711
|
+
|
|
712
|
+
# inputs taken from all children
|
|
713
|
+
for child in node.tasks:
|
|
714
|
+
self.input(node, self.info.task_inputs(child))
|
|
715
|
+
# outputs are vars declared as hoisted
|
|
716
|
+
self.output(node, helpers.hoisted_vars(node.hoisted))
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
def visit_match(self, node: ir.Match, parent: Optional[ir.Node]):
|
|
720
|
+
# visit children first
|
|
721
|
+
super().visit_match(node, parent)
|
|
722
|
+
|
|
723
|
+
# inputs taken from all children
|
|
724
|
+
for child in node.tasks:
|
|
725
|
+
self.input(node, self.info.task_inputs(child))
|
|
726
|
+
# outputs are vars declared as hoisted
|
|
727
|
+
self.output(node, helpers.hoisted_vars(node.hoisted))
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def visit_require(self, node: ir.Require, parent: Optional[ir.Node]):
|
|
731
|
+
# visit children first
|
|
732
|
+
super().visit_require(node, parent)
|
|
733
|
+
|
|
734
|
+
# inputs taken from the domain and all check tasks
|
|
735
|
+
self.input(node, self.info.task_inputs(node.domain))
|
|
736
|
+
for check in node.checks:
|
|
737
|
+
self.input(node, self.info.task_inputs(check.check))
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
#
|
|
741
|
+
# Logical tasks
|
|
742
|
+
#
|
|
743
|
+
def visit_not(self, node: ir.Not, parent: Optional[ir.Node]):
|
|
744
|
+
# visit children first
|
|
745
|
+
super().visit_not(node, parent)
|
|
746
|
+
|
|
747
|
+
# not gets the inputs from its child
|
|
748
|
+
self.input(node, self.info.task_inputs(node.task))
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
def visit_exists(self, node: ir.Exists, parent: Optional[ir.Node]):
|
|
752
|
+
# visit children first
|
|
753
|
+
super().visit_exists(node, parent)
|
|
754
|
+
|
|
755
|
+
# exists variables are local, so they are ignored
|
|
756
|
+
self.input(node, self.info.task_inputs(node.task))
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
#
|
|
760
|
+
# Leaf tasks
|
|
761
|
+
#
|
|
762
|
+
def visit_data(self, node: ir.Data, parent: Optional[ir.Node]):
|
|
763
|
+
# data outputs all its variables
|
|
764
|
+
for v in helpers.vars(node.vars):
|
|
765
|
+
self.output(node, v)
|
|
766
|
+
|
|
767
|
+
return super().visit_data(node, parent)
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
def visit_update(self, node: ir.Update, parent: Optional[ir.Node]):
|
|
771
|
+
# register variables being used as arguments to the update, it's always considered an input
|
|
772
|
+
for v in helpers.vars(node.args):
|
|
773
|
+
self.input(node, v)
|
|
774
|
+
return super().visit_update(node, parent)
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
def visit_lookup(self, node: ir.Lookup, parent: Optional[ir.Node]):
|
|
778
|
+
def register(node, field, arg):
|
|
779
|
+
if isinstance(arg, ir.Var):
|
|
780
|
+
if field.input:
|
|
781
|
+
self.input(node, arg)
|
|
782
|
+
else:
|
|
783
|
+
self.output(node, arg)
|
|
784
|
+
|
|
785
|
+
if builtins.is_eq(node.relation):
|
|
786
|
+
# Most cases are covered already at the parent level if the equality is part of
|
|
787
|
+
# a Logical. The remaining cases are when the equality is a child of a
|
|
788
|
+
# non-Logical, or if its variables are not ground elsewhere in the Logical.
|
|
789
|
+
if self.info.task_inputs(node) or self.info.task_outputs(node):
|
|
790
|
+
# already covered
|
|
791
|
+
pass
|
|
792
|
+
else:
|
|
793
|
+
x, y = node.args[0], node.args[1]
|
|
794
|
+
grounds = self._grounded[-1] if self._grounded else ordered_set()
|
|
795
|
+
if isinstance(x, ir.Var):
|
|
796
|
+
if x in grounds:
|
|
797
|
+
self.input(node, x)
|
|
798
|
+
else:
|
|
799
|
+
self.output(node, x)
|
|
800
|
+
if isinstance(y, ir.Var):
|
|
801
|
+
if y in grounds:
|
|
802
|
+
self.input(node, y)
|
|
803
|
+
else:
|
|
804
|
+
self.output(node, y)
|
|
805
|
+
else:
|
|
806
|
+
# register variables depending on the input flag of the relation bound to the lookup
|
|
807
|
+
for idx, f in enumerate(node.relation.fields):
|
|
808
|
+
arg = node.args[idx]
|
|
809
|
+
if isinstance(arg, Iterable):
|
|
810
|
+
# deal with ListType fields that pack arguments in a tuple
|
|
811
|
+
for element in arg:
|
|
812
|
+
register(node, f, element)
|
|
813
|
+
else:
|
|
814
|
+
register(node, f, arg)
|
|
815
|
+
return super().visit_lookup(node, parent)
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def visit_output(self, node: ir.Output, parent: Optional[ir.Node]):
|
|
819
|
+
# register variables being output, they always considered an input to the task
|
|
820
|
+
for v in helpers.output_vars(node.aliases):
|
|
821
|
+
self.input(node, v)
|
|
822
|
+
# also register keys as inputs
|
|
823
|
+
self.input(node, node.keys)
|
|
824
|
+
return super().visit_output(node, parent)
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
def visit_construct(self, node: ir.Construct, parent: Optional[ir.Node]):
|
|
828
|
+
# values are inputs, id_var is an output
|
|
829
|
+
for v in helpers.vars(node.values):
|
|
830
|
+
self.input(node, v)
|
|
831
|
+
self.output(node, node.id_var)
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
def visit_aggregate(self, node: ir.Aggregate, parent: Optional[ir.Node]):
|
|
835
|
+
# register projection and group as inputs
|
|
836
|
+
for v in node.projection:
|
|
837
|
+
self.input(node, v)
|
|
838
|
+
for v in node.group:
|
|
839
|
+
self.input(node, v)
|
|
840
|
+
|
|
841
|
+
# register variables depending on the input flag of the aggregation relation
|
|
842
|
+
for idx, f in enumerate(node.aggregation.fields):
|
|
843
|
+
arg = node.args[idx]
|
|
844
|
+
if isinstance(arg, ir.Var):
|
|
845
|
+
if f.input:
|
|
846
|
+
self.input(node, arg)
|
|
847
|
+
else:
|
|
848
|
+
self.output(node, arg)
|
|
849
|
+
return super().visit_aggregate(node, parent)
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
def visit_rank(self, node: ir.Rank, parent: Optional[ir.Node]):
|
|
853
|
+
# register projection and group as inputs
|
|
854
|
+
for v in node.projection:
|
|
855
|
+
self.input(node, v)
|
|
856
|
+
for v in node.group:
|
|
857
|
+
self.input(node, v)
|
|
858
|
+
for v in node.args:
|
|
859
|
+
self.input(node, v)
|
|
860
|
+
|
|
861
|
+
self.output(node, node.result)
|
|
862
|
+
return super().visit_rank(node, parent)
|