forked from aptos-labs/aptos-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[move-prover] better architecture for simplification pipeline
This creates a new trait, `SpecRewriter` that handles the transformations on specs. The `SpecRewriter` has three functions to be implemented by each individual rewriter: - `rewrite_module_spec` - `rewrite_function_spec` - `rewrite_inline_spec` Multiple rewriters that implement the `SpecRewriter` trait can be composed into a new rewriter that pipelines them. This logic is captured in `SpecRewriterPipeline`, which also implements `SpecRewriter`. A `SpecRewriter` has an option to write-back the newly generated spec into a `&mut GlobalEnv` with the `override_with_rewrite` function. But this is optional and only available in cases where a `&mut GlobalEnv` can be obtained (e.g., during model building or right after the model is built). If writing-back is not needed, the three `rewrite_*` funciton should be sufficient. Closes: aptos-labs#9821
- Loading branch information
1 parent
05bb3fc
commit f4a0b8e
Showing
5 changed files
with
314 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright (c) The Diem Core Contributors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use anyhow::Result; | ||
use std::collections::BTreeMap; | ||
|
||
use move_binary_format::file_format::CodeOffset; | ||
|
||
use crate::{ | ||
ast::Spec, | ||
model::{FunId, GlobalEnv, ModuleId, QualifiedId}, | ||
}; | ||
|
||
/// A generic trait for rewriting the specifications in the `GlobalEnv`. A rewriter is expected to | ||
/// implement at least one `rewrite_*` function, depending on which type(s) of specs the rewriter | ||
/// targets. All the `rewrite_*` function should follow the convention on return value: | ||
/// - `Ok(None)` --> nothing to rewrite on this spec | ||
/// - `Ok(Some(new_spec))` --> the spec is re-written and the `new_spec` is the output | ||
/// - `Err(..)` --> something wrong (invariant violation) happened in the rewriting | ||
pub trait SpecRewriter { | ||
/// Rewrite a module-level specification | ||
fn rewrite_module_spec( | ||
&mut self, | ||
_env: &GlobalEnv, | ||
_module_id: ModuleId, | ||
_spec: &Spec, | ||
) -> Result<Option<Spec>> { | ||
Ok(None) | ||
} | ||
|
||
/// Rewrite a function-level specification | ||
fn rewrite_function_spec( | ||
&mut self, | ||
_env: &GlobalEnv, | ||
_fun_id: QualifiedId<FunId>, | ||
_spec: &Spec, | ||
) -> Result<Option<Spec>> { | ||
Ok(None) | ||
} | ||
|
||
/// Rewrite a code-level specification | ||
fn rewrite_inline_spec( | ||
&mut self, | ||
_env: &GlobalEnv, | ||
_fun_id: QualifiedId<FunId>, | ||
_code_offset: CodeOffset, | ||
_spec: &Spec, | ||
) -> Result<Option<Spec>> { | ||
Ok(None) | ||
} | ||
|
||
/// Iterate over the specs in the `GlobalEnv`, rewrite each spec, and apply changes back to the | ||
/// `GlobalEnv`. | ||
fn override_with_rewrite(&mut self, env: &mut GlobalEnv) -> Result<()> { | ||
// convert all module specs found in the model | ||
let mut new_specs = BTreeMap::new(); | ||
for menv in env.get_modules() { | ||
let mid = menv.get_id(); | ||
if let Some(new_spec) = self.rewrite_module_spec(env, mid, menv.get_spec())? { | ||
new_specs.insert(mid, new_spec); | ||
} | ||
} | ||
for (mid, spec) in new_specs { | ||
env.override_module_spec(mid, spec); | ||
} | ||
|
||
// convert all functional specs found in the model | ||
let mut new_specs = BTreeMap::new(); | ||
for menv in env.get_modules() { | ||
for fenv in menv.get_functions() { | ||
let fid = fenv.get_qualified_id(); | ||
if let Some(new_spec) = self.rewrite_function_spec(env, fid, fenv.get_spec())? { | ||
new_specs.insert(fid, new_spec); | ||
} | ||
} | ||
} | ||
for (fid, spec) in new_specs { | ||
env.override_function_spec(fid, spec); | ||
} | ||
|
||
// convert all code-level specs found in the model | ||
let mut new_specs = BTreeMap::new(); | ||
for menv in env.get_modules() { | ||
for fenv in menv.get_functions() { | ||
let fid = fenv.get_qualified_id(); | ||
for (offset, spec) in &fenv.get_spec().on_impl { | ||
if let Some(new_spec) = self.rewrite_inline_spec(env, fid, *offset, spec)? { | ||
new_specs.insert((fid, *offset), new_spec); | ||
} | ||
} | ||
} | ||
} | ||
for ((fid, offset), spec) in new_specs { | ||
env.override_inline_spec(fid, offset, spec); | ||
} | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.