diff --git a/Cargo.lock b/Cargo.lock index e43a1b4f..b29dac40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,56 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -77,6 +127,52 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "clap" +version = "4.5.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.107", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -221,7 +317,7 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "egglog" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "csv", "dyn-clone", @@ -230,6 +326,7 @@ dependencies = [ "egglog-bridge", "egglog-core-relations", "egglog-numeric-id", + "egglog-reports", "egraph-serialize", "hashbrown 0.16.0", "im-rc", @@ -239,6 +336,7 @@ dependencies = [ "ordered-float", "rayon", "rustc-hash", + "serde_json", "thiserror", "web-time", ] @@ -246,7 +344,7 @@ dependencies = [ [[package]] name = "egglog-add-primitive" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "quote", "syn 2.0.107", @@ -255,7 +353,7 @@ dependencies = [ [[package]] name = "egglog-ast" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "ordered-float", ] @@ -263,12 +361,13 @@ dependencies = [ [[package]] name = "egglog-bridge" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "anyhow", "dyn-clone", "egglog-core-relations", "egglog-numeric-id", + "egglog-reports", "egglog-union-find", "hashbrown 0.16.0", "indexmap", @@ -286,7 +385,7 @@ dependencies = [ [[package]] name = "egglog-concurrency" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "arc-swap", "rayon", @@ -295,15 +394,17 @@ dependencies = [ [[package]] name = "egglog-core-relations" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "anyhow", "bumpalo", + "crossbeam", "crossbeam-queue", "dashmap", "dyn-clone", "egglog-concurrency", "egglog-numeric-id", + "egglog-reports", "egglog-union-find", "fixedbitset", "hashbrown 0.16.0", @@ -323,10 +424,11 @@ dependencies = [ [[package]] name = "egglog-experimental" version = "0.1.0" -source = "git+https://github.com/egraphs-good/egglog-experimental?branch=update-egglog#ebb3a581732cc00aa41c8356f2c12e800a768e0f" +source = "git+https://github.com/egraphs-good/egglog-experimental?branch=main#908c47d7046c840c8ff07caa0f7ff29a2e7adc82" dependencies = [ "egglog", "egglog-ast", + "egglog-reports", "lazy_static", "log", "num", @@ -335,15 +437,29 @@ dependencies = [ [[package]] name = "egglog-numeric-id" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "rayon", ] +[[package]] +name = "egglog-reports" +version = "1.0.0" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" +dependencies = [ + "clap", + "hashbrown 0.16.0", + "indexmap", + "rustc-hash", + "serde", + "serde_json", + "web-time", +] + [[package]] name = "egglog-union-find" version = "1.0.0" -source = "git+https://github.com/saulshanabrook/egg-smol.git?branch=let-bindings-again#7b1b7fcb47c0e6766f04dd1aa10577cb29307273" +source = "git+https://github.com/egraphs-good/egglog.git?branch=main#ef90b97de1f5e7778186439b8fb0549179f82a45" dependencies = [ "crossbeam", "egglog-concurrency", @@ -360,6 +476,7 @@ dependencies = [ "egglog-bridge", "egglog-core-relations", "egglog-experimental", + "egglog-reports", "egraph-serialize", "lalrpop-util", "log", @@ -406,7 +523,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -495,6 +612,7 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.2.0", + "serde", ] [[package]] @@ -557,6 +675,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itoa" version = "1.0.15" @@ -710,6 +834,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "ordered-float" version = "5.1.0" @@ -854,8 +984,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.13.1" -source = "git+https://github.com/a1phyr/pyo3-log.git?branch=pyo3_0.27#4ccd4c7c96e8e3bda4a47bc85d92749b4927fcb9" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8bae9ad5ba08b0b0ed2bb9c2bdbaeccc69cafca96d78cf0fbcea0d45d122bb" dependencies = [ "arc-swap", "log", @@ -1021,7 +1152,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1113,6 +1244,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -1151,7 +1288,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1198,6 +1335,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.18.1" @@ -1299,6 +1442,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1308,6 +1460,71 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/Cargo.toml b/Cargo.toml index 6c1a622d..263c73ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,17 +13,15 @@ crate-type = ["cdylib"] pyo3 = { version = "0.27", features = ["extension-module", "num-bigint", "num-rational"] } num-bigint = "*" num-rational = "*" -# egglog = { git = "https://github.com/egraphs-good/egglog.git", branch = "main", default-features = false } -# egglog-bridge = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } -# egglog-core-relations = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } -egglog = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again", default-features = false } -egglog-bridge = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -egglog-core-relations = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -egglog-experimental = { git = "https://github.com/egraphs-good/egglog-experimental", branch = "update-egglog", default-features = false } -egglog-ast = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } +egglog = { git = "https://github.com/egraphs-good/egglog.git", branch = "main", default-features = false } +egglog-bridge = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +egglog-core-relations = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +egglog-experimental = { git = "https://github.com/egraphs-good/egglog-experimental", branch = "main", default-features = false } +egglog-ast = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +egglog-reports = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } egraph-serialize = { version = "0.3", features = ["serde", "graphviz"] } serde_json = "1" -pyo3-log = { git = "https://github.com/a1phyr/pyo3-log.git", branch = "pyo3_0.27" } +pyo3-log = "*" log = "0.4" lalrpop-util = { version = "0.22", features = ["lexer"] } ordered-float = "5" @@ -33,13 +31,10 @@ base64 = "0.22.1" # Use patched version of egglog in experimental [patch.'https://github.com/egraphs-good/egglog'] -# egglog = { git = "https://github.com/egraphs-good//egglog.git", branch = "main" } -egglog = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -egglog-bridge = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -egglog-core-relations = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -egglog-ast = { git = "https://github.com/saulshanabrook/egg-smol.git", branch = "let-bindings-again" } -# egglog = { path = "../egg-smol" } -# egglog = { git = "https://github.com/egraphs-good//egglog.git", rev = "5542549" } +# egglog = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +# egglog-bridge = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +# egglog-core-relations = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } +# egglog-ast = { git = "https://github.com/egraphs-good/egglog.git", branch = "main" } # enable debug symbols for easier profiling [profile.release] diff --git a/docs/changelog.md b/docs/changelog.md index cf43ce81..68d7eb9e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,7 @@ _This project uses semantic versioning_ ## UNRELEASED +- Add support for setting report level with `egraph.set_report_level` [#375](https://github.com/egraphs-good/egglog-python/pull/375) - Make docs builds fail on notebook execution errors and fix all doc issues [#369](https://github.com/egraphs-good/egglog-python/pull/369) - Add WIP `egglog.exp.any_expr` code for tracing arbitrary expressions with Python fallback [#366](https://github.com/egraphs-good/egglog-python/pull/366) - BREAKING: Remove support for Python 3.11 now that pyo3 has dropped support. diff --git a/python/egglog/__init__.py b/python/egglog/__init__.py index 6a6e2213..7d20dfdb 100644 --- a/python/egglog/__init__.py +++ b/python/egglog/__init__.py @@ -3,7 +3,7 @@ """ from . import config, ipython_magic # noqa: F401 -from .bindings import EggSmolError # noqa: F401 +from .bindings import EggSmolError, StageInfo, TimeOnly, WithPlan # noqa: F401 from .builtins import * # noqa: UP029 from .conversion import * from .deconstruct import * diff --git a/python/egglog/bindings.pyi b/python/egglog/bindings.pyi index 4aa63b37..7e585dab 100644 --- a/python/egglog/bindings.pyi +++ b/python/egglog/bindings.pyi @@ -33,10 +33,13 @@ __all__ = [ "Float", "Function", "FunctionCommand", + "FusedIntersect", "IdentSort", "Include", "Input", "Int", + "Intersect", + "IterationReport", "Let", "Lit", "NewSort", @@ -44,6 +47,7 @@ __all__ = [ "OverallStatistics", "Panic", "PanicSpan", + "Plan", "Pop", "PrintAllFunctionsSize", "PrintFunction", @@ -58,6 +62,8 @@ __all__ = [ "RewriteCommand", "Rule", "RuleCommand", + "RuleReport", + "RuleSetReport", "Run", "RunConfig", "RunReport", @@ -65,12 +71,16 @@ __all__ = [ "RunScheduleOutput", "RustSpan", "Saturate", + "Scan", "Schema", "Sequence", "SerializedEGraph", "Set", + "SingleScan", "Sort", "SrcFile", + "StageInfo", + "StageStats", "String", "SubVariants", "Subsume", @@ -78,6 +88,7 @@ __all__ = [ "TermDag", "TermLit", "TermVar", + "TimeOnly", "Union", "Unit", "UnstableCombinedRuleset", @@ -87,6 +98,7 @@ __all__ = [ "Value", "Var", "Variant", + "WithPlan", ] @final @@ -118,6 +130,7 @@ class EGraph: max_calls_per_function: int | None = None, include_temporary_functions: bool = False, ) -> SerializedEGraph: ... + def set_report_level(self, level: _ReportLevel) -> None: ... def lookup_function(self, name: str, key: list[Value]) -> Value | None: ... def eval_expr(self, expr: _Expr) -> tuple[str, Value]: ... def value_to_i64(self, v: Value) -> int: ... @@ -389,12 +402,99 @@ class IdentSort: @final class UserDefinedCommandOutput: ... +@final +class SingleScan: + atom: str + column: tuple[str, int] + + def __new__(cls, atom: str, column: tuple[str, int]) -> SingleScan: ... + +@final +class Scan: + atom: str + columns: list[tuple[str, int]] + + def __new__(cls, atom: str, columns: list[tuple[str, int]]) -> Scan: ... + +@final +class StageStats: + num_candidates: int + num_succeeded: int + + def __new__(cls, num_candidates: int, num_succeeded: int) -> StageStats: ... + +@final +class TimeOnly: + def __new__(cls) -> TimeOnly: ... + +@final +class WithPlan: + def __new__(cls) -> WithPlan: ... + +@final +class StageInfo: + def __new__(cls) -> StageInfo: ... + +_ReportLevel: TypeAlias = TimeOnly | WithPlan | StageInfo + +@final +class Intersect: + scans: list[SingleScan] + + def __new__(cls, scans: list[SingleScan]) -> Intersect: ... + +@final +class FusedIntersect: + cover: Scan + to_intersect: list[Scan] + + def __new__(cls, cover: Scan, to_intersect: list[Scan]) -> FusedIntersect: ... + +_Stage: TypeAlias = Intersect | FusedIntersect + +@final +class Plan: + stages: list[tuple[_Stage, StageStats | None, list[int]]] + + def __new__(cls, stages: list[tuple[_Stage, StageStats | None, list[int]]]) -> Plan: ... + +@final +class RuleReport: + plan: Plan | None + search_and_apply_time: timedelta + num_matches: int + + def __new__(cls, plan: Plan | None, search_and_apply_time: timedelta, num_matches: int) -> RuleReport: ... + +@final +class RuleSetReport: + changed: bool + rule_reports: dict[str, list[RuleReport]] + search_and_apply_time: timedelta + merge_time: timedelta + + def __new__( + cls, + changed: bool, + rule_reports: dict[str, list[RuleReport]], + search_and_apply_time: timedelta, + merge_time: timedelta, + ) -> RuleSetReport: ... + +@final +class IterationReport: + rule_set_report: RuleSetReport + rebuild_time: timedelta + + def __new__(cls, rule_set_report: RuleSetReport, rebuild_time: timedelta) -> IterationReport: ... + @final class Function: name: str @final class RunReport: + iterations: list[IterationReport] updated: bool search_and_apply_time_per_rule: dict[str, timedelta] num_matches_per_rule: dict[str, int] @@ -404,6 +504,7 @@ class RunReport: def __new__( cls, + iterations: list[IterationReport], updated: bool, search_and_apply_time_per_rule: dict[str, timedelta], num_matches_per_rule: dict[str, int], @@ -688,7 +789,11 @@ class Constructor: def __new__(cls, span: _Span, name: str, schema: Schema, cost: int | None, unextractable: bool) -> Constructor: ... @final -class PrintOverallStatistics: ... +class PrintOverallStatistics: + span: _Span + file: str | None + + def __new__(cls, span: _Span, file: str | None) -> PrintOverallStatistics: ... @final class UserDefined: diff --git a/python/egglog/egraph.py b/python/egglog/egraph.py index 2a98207c..aeb43457 100644 --- a/python/egglog/egraph.py +++ b/python/egglog/egraph.py @@ -105,6 +105,7 @@ "vars_", ] + T = TypeVar("T") P = ParamSpec("P") EXPR_TYPE = TypeVar("EXPR_TYPE", bound="type[Expr]") @@ -869,6 +870,12 @@ def _add_decls(self, *decls: DeclerationsLike) -> None: for d in decls: self._state.__egg_decls__ |= d + def set_report_level(self, level: bindings._ReportLevel) -> None: + """ + Set the level of detail recorded in subsequent run reports. + """ + self._egraph.set_report_level(level) + @property def as_egglog_string(self) -> str: """ @@ -948,7 +955,7 @@ def stats(self) -> bindings.RunReport: """ Returns the overall run report for the egraph. """ - (output,) = self._egraph.run_program(bindings.PrintOverallStatistics()) + (output,) = self._egraph.run_program(bindings.PrintOverallStatistics(span(1), None)) assert isinstance(output, bindings.OverallStatistics) return output.report diff --git a/src/conversions.rs b/src/conversions.rs index f32b9d13..bf799506 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -282,9 +282,15 @@ convert_enums!( name: name.to_string(), inputs: inputs.iter().map(|i| i.to_string()).collect() }; - PrintOverallStatistics() - _c -> egglog::ast::Command::PrintOverallStatistics, - egglog::ast::Command::PrintOverallStatistics => PrintOverallStatistics {}; + PrintOverallStatistics(span: Span, file: Option) + c -> egglog::ast::Command::PrintOverallStatistics( + c.span.clone().into(), + c.file.as_ref().map(|f| f.clone().into()) + ), + egglog::ast::Command::PrintOverallStatistics(span, file) => PrintOverallStatistics { + span: span.into(), + file: file.clone() + }; Datatypes(span: Span, datatypes: Vec<(Span, String, Subdatatypes)>) d -> egglog::ast::Command::Datatypes { span: d.span.clone().into(), @@ -322,6 +328,35 @@ convert_enums!( n -> egglog::ast::Subdatatypes::NewSort((&n.name).into(), n.args.iter().map(|e| e.into()).collect()), egglog::ast::Subdatatypes::NewSort(name, args) => NewSort { name: name.to_string(), args: args.iter().map(|e| e.into()).collect() } }; + egglog_reports::Stage: "{:?}" => Stage { + Intersect(scans: Vec) + s -> egglog_reports::Stage::Intersect { + scans: s.scans.iter().map(|scan| scan.into()).collect() + }, + egglog_reports::Stage::Intersect { scans } => Intersect { + scans: scans.iter().map(|scan| scan.into()).collect() + }; + FusedIntersect(cover: Scan, to_intersect: Vec) + f -> egglog_reports::Stage::FusedIntersect { + cover: (&f.cover).into(), + to_intersect: f.to_intersect.iter().map(|scan| scan.into()).collect() + }, + egglog_reports::Stage::FusedIntersect { cover, to_intersect } => FusedIntersect { + cover: cover.clone().into(), + to_intersect: to_intersect.iter().map(|scan| scan.into()).collect() + } + }; + egglog_reports::ReportLevel: "{:?}" => ReportLevel { + TimeOnly() + _r -> egglog_reports::ReportLevel::TimeOnly, + egglog_reports::ReportLevel::TimeOnly => TimeOnly {}; + WithPlan() + _r -> egglog_reports::ReportLevel::WithPlan, + egglog_reports::ReportLevel::WithPlan => WithPlan {}; + StageInfo() + _r -> egglog_reports::ReportLevel::StageInfo, + egglog_reports::ReportLevel::StageInfo => StageInfo {} + }; egglog::CommandOutput: "{}" => CommandOutput { PrintFunctionSize(size: usize) b -> egglog::CommandOutput::PrintFunctionSize(b.size), @@ -450,7 +485,136 @@ convert_struct!( ) i -> egglog::ast::IdentSort {ident: (&i.ident).into(), sort: (&i.sort).into()}, i -> IdentSort {ident: i.ident.to_string(), sort: i.sort.to_string()}; - egglog::RunReport: "{:?}" => RunReport( + egglog_reports::SingleScan: "{:?}" => SingleScan( + atom: String, + column: (String, i64) + ) + s -> egglog_reports::SingleScan( + s.atom.clone(), + (s.column.0.clone(), s.column.1) + ), + s -> SingleScan { + atom: s.0.to_string(), + column: (s.1 .0.to_string(), s.1 .1) + }; + egglog_reports::Scan: "{:?}" => Scan( + atom: String, + columns: Vec<(String, i64)> + ) + s -> egglog_reports::Scan( + s.atom.clone(), + s.columns.iter().map(|(n, i)| (n.clone(), *i)).collect() + ), + s -> Scan { + atom: s.0.to_string(), + columns: s.1.iter().map(|(n, i)| (n.to_string(), *i)).collect() + }; + egglog_reports::StageStats: "{:?}" => StageStats( + num_candidates: usize, + num_succeeded: usize + ) + s -> egglog_reports::StageStats { + num_candidates: s.num_candidates, + num_succeeded: s.num_succeeded + }, + s -> StageStats { + num_candidates: s.num_candidates, + num_succeeded: s.num_succeeded + }; + egglog_reports::Plan: "{:?}" => Plan( + stages: Vec<(Stage, Option, Vec)> + ) + p -> egglog_reports::Plan { + stages: p + .stages + .iter() + .map(|(s, ss, ts)| { + ( + s.clone().into(), + ss.as_ref().map(|st| st.clone().into()), + ts.clone(), + ) + }) + .collect() + }, + p -> Plan { + stages: p + .stages + .iter() + .map(|(s, ss, ts)| { + ( + s.clone().into(), + ss.as_ref().map(|st| st.clone().into()), + ts.clone(), + ) + }) + .collect() + }; + egglog_reports::RuleReport: "{:?}" => RuleReport( + plan: Option, + search_and_apply_time: WrappedDuration, + num_matches: usize + ) + r -> egglog_reports::RuleReport { + plan: r.plan.as_ref().map(|p| p.clone().into()), + search_and_apply_time: r.search_and_apply_time.clone().0, + num_matches: r.num_matches + }, + r -> RuleReport { + plan: r.plan.as_ref().map(|p| p.clone().into()), + search_and_apply_time: r.search_and_apply_time.clone().into(), + num_matches: r.num_matches + }; + egglog_reports::RuleSetReport: "{:?}" => RuleSetReport( + changed: bool, + rule_reports: HashMap>, + search_and_apply_time: WrappedDuration, + merge_time: WrappedDuration + ) + r -> egglog_reports::RuleSetReport { + changed: r.changed, + rule_reports: r + .rule_reports + .iter() + .map(|(k, v)| { + ( + Arc::::from(k.clone()), + v.iter().map(|rr| rr.clone().into()).collect(), + ) + }) + .collect(), + search_and_apply_time: r.search_and_apply_time.clone().0, + merge_time: r.merge_time.clone().0, + }, + r -> RuleSetReport { + changed: r.changed, + rule_reports: r + .rule_reports + .iter() + .map(|(k, v)| { + ( + k.to_string(), + v.iter().map(|rr| rr.clone().into()).collect(), + ) + }) + .collect(), + search_and_apply_time: r.search_and_apply_time.clone().into(), + merge_time: r.merge_time.clone().into(), + }; + egglog_reports::IterationReport: "{:?}" => IterationReport( + rule_set_report: RuleSetReport, + rebuild_time: WrappedDuration + ) + r -> egglog_reports::IterationReport { + rule_set_report: (&r.rule_set_report).into(), + rebuild_time: r.rebuild_time.clone().0 + }, + r -> IterationReport { + rule_set_report: (&r.rule_set_report).into(), + rebuild_time: r.rebuild_time.clone().into() + }; + egglog_reports::RunReport: "{:?}" => RunReport( + iterations: Vec, updated: bool, search_and_apply_time_per_rule: HashMap, num_matches_per_rule: HashMap, @@ -458,21 +622,67 @@ convert_struct!( merge_time_per_ruleset: HashMap, rebuild_time_per_ruleset: HashMap ) - r -> egglog::RunReport { + r -> egglog_reports::RunReport { + iterations: r + .iterations + .iter() + .map(|i| Arc::new(i.clone().into())) + .collect(), updated: r.updated, - search_and_apply_time_per_rule: r.search_and_apply_time_per_rule.iter().map(|(k, v)| (k.clone(), v.clone().0)).collect(), - num_matches_per_rule: r.num_matches_per_rule.iter().map(|(k, v)| (k.clone(), *v)).collect(), - search_and_apply_time_per_ruleset: r.search_and_apply_time_per_ruleset.iter().map(|(k, v)| (k.clone(), v.clone().0)).collect(), - merge_time_per_ruleset: r.merge_time_per_ruleset.iter().map(|(k, v)| (k.clone(), v.clone().0)).collect(), - rebuild_time_per_ruleset: r.rebuild_time_per_ruleset.iter().map(|(k, v)| (k.clone(), v.clone().0)).collect(), + search_and_apply_time_per_rule: r + .search_and_apply_time_per_rule + .iter() + .map(|(k, v)| (Arc::::from(k.clone()), v.clone().0)) + .collect(), + num_matches_per_rule: r + .num_matches_per_rule + .iter() + .map(|(k, v)| (Arc::::from(k.clone()), *v)) + .collect(), + search_and_apply_time_per_ruleset: r + .search_and_apply_time_per_ruleset + .iter() + .map(|(k, v)| (Arc::::from(k.clone()), v.clone().0)) + .collect(), + merge_time_per_ruleset: r + .merge_time_per_ruleset + .iter() + .map(|(k, v)| (Arc::::from(k.clone()), v.clone().0)) + .collect(), + rebuild_time_per_ruleset: r + .rebuild_time_per_ruleset + .iter() + .map(|(k, v)| (Arc::::from(k.clone()), v.clone().0)) + .collect(), }, r -> RunReport { + iterations: r.iterations.iter().map(|i| i.as_ref().into()).collect(), updated: r.updated, - search_and_apply_time_per_rule: r.search_and_apply_time_per_rule.iter().map(|(k, v)| (k.clone().to_string(), (*v).into())).collect(), - num_matches_per_rule: r.num_matches_per_rule.iter().map(|(k, v)| (k.clone().to_string(), *v)).collect(), - search_and_apply_time_per_ruleset: r.search_and_apply_time_per_ruleset.iter().map(|(k, v)| (k.clone().to_string(), (*v).into())).collect(), - merge_time_per_ruleset: r.merge_time_per_ruleset.iter().map(|(k, v)| (k.clone().to_string(), (*v).into())).collect(), - rebuild_time_per_ruleset: r.rebuild_time_per_ruleset.iter().map(|(k, v)| (k.clone().to_string(), (*v).into())).collect(), + search_and_apply_time_per_rule: r + .search_and_apply_time_per_rule + .iter() + .map(|(k, v)| (k.to_string(), (*v).into())) + .collect(), + num_matches_per_rule: r + .num_matches_per_rule + .iter() + .map(|(k, v)| (k.to_string(), *v)) + .collect(), + search_and_apply_time_per_ruleset: r + .search_and_apply_time_per_ruleset + .iter() + .map(|(k, v)| (k.to_string(), (*v).into())) + .collect(), + merge_time_per_ruleset: r + .merge_time_per_ruleset + .iter() + .map(|(k, v)| (k.to_string(), (*v).into())) + .collect(), + rebuild_time_per_ruleset: r + .rebuild_time_per_ruleset + .iter() + .map(|(k, v)| (k.to_string(), (*v).into())) + .collect(), } ); diff --git a/src/egraph.rs b/src/egraph.rs index a8b253e2..19e9f172 100644 --- a/src/egraph.rs +++ b/src/egraph.rs @@ -117,6 +117,10 @@ impl EGraph { }) } + fn set_report_level(&mut self, level: ReportLevel) { + self.egraph.set_report_level(level.into()); + } + fn lookup_function(&self, name: &str, key: Vec) -> Option { self.egraph .lookup_function(