diff --git a/pyk/pyk-tests/Makefile b/pyk/pyk-tests/Makefile
index c9790a3e5f1..bb30acdff51 100644
--- a/pyk/pyk-tests/Makefile
+++ b/pyk/pyk-tests/Makefile
@@ -10,12 +10,13 @@ CHECK = git --no-pager diff --no-index -R
.PHONY: all clean update-results \
- test test-kpyk test-kpyk-graphviz test-kpyk-minimize-term
+ test test-kpyk test-kpyk-graphviz test-kpyk-minimize-term test-post-process
all: test
clean:
rm -rf definitions
+ $(MAKE) -C post-process clean
update-results: CHECK=cp
update-results: test
@@ -27,7 +28,7 @@ test: test-kpyk
## kpyk runner tests
-test-kpyk: test-kpyk-graphviz test-kpyk-minimize-term
+test-kpyk: test-kpyk-graphviz test-kpyk-minimize-term test-post-process
test-kpyk-graphviz: d.kompiled
$(PYK) -v definitions/d graph-imports
@@ -39,6 +40,9 @@ test-kpyk-minimize-term: imp-verification.kompiled
| $(PYK) -v definitions/imp-verification print /dev/stdin > imp-unproveable-spec.k.out
$(CHECK) imp-unproveable-spec.k.out imp-unproveable-spec.k.expected
+test-post-process:
+ $(MAKE) -C post-process
+
## definitions to build ahead of time
diff --git a/pyk/pyk-tests/post-process/.gitignore b/pyk/pyk-tests/post-process/.gitignore
new file mode 100644
index 00000000000..d54362dcbb6
--- /dev/null
+++ b/pyk/pyk-tests/post-process/.gitignore
@@ -0,0 +1 @@
+kompiled/
diff --git a/pyk/pyk-tests/post-process/Makefile b/pyk/pyk-tests/post-process/Makefile
new file mode 100644
index 00000000000..44dea11c976
--- /dev/null
+++ b/pyk/pyk-tests/post-process/Makefile
@@ -0,0 +1,14 @@
+KOMPILED_DIR := kompiled
+
+.PHONY: clean
+
+
+$(KOMPILED_DIR)/timestamp: assign.k transform.py
+ kompile assign.k \
+ --backend haskell \
+ --output-definition $(KOMPILED_DIR) \
+ --emit-json \
+ --post-process 'python3 transform.py'
+
+clean:
+ rm -rf $(KOMPILED_DIR)
diff --git a/pyk/pyk-tests/post-process/assign.k b/pyk/pyk-tests/post-process/assign.k
new file mode 100644
index 00000000000..d4bab85b4ee
--- /dev/null
+++ b/pyk/pyk-tests/post-process/assign.k
@@ -0,0 +1,41 @@
+module ASSIGN-SYNTAX
+ imports INT-SYNTAX
+ imports ID-SYNTAX
+
+ syntax Expr ::= Int | Id
+
+ syntax Stmt ::= Decl | Assign
+ syntax Decl ::= "var" Ids ";"
+ syntax Ids ::= List{Id, ","}
+ syntax Assign ::= Id "=" Expr ";" [strict(2)]
+
+ syntax Pgm ::= List{Stmt, ""}
+
+ syntax KResult ::= Int
+endmodule
+
+
+module ASSIGN
+ imports ASSIGN-SYNTAX
+ imports BOOL
+
+ configuration
+
+ $PGM:Pgm
+ .Map
+
+
+ rule S:Stmt P:Pgm => S ~> P ...
+ rule .Pgm => . ...
+
+ rule [r1]: X:Id => I ...
+ ... X |-> I ...
+
+ rule [r2]: X = I:Int; => . ...
+ ... X |-> (_ => I) ...
+
+ rule var .Ids ; => . ...
+
+ rule [r3]: var (X, Xs => Xs); ...
+ Rho:Map (.Map => X |-> 0) requires notBool (X in_keys(Rho))
+endmodule
diff --git a/pyk/pyk-tests/post-process/transform.py b/pyk/pyk-tests/post-process/transform.py
new file mode 100644
index 00000000000..2471a507a81
--- /dev/null
+++ b/pyk/pyk-tests/post-process/transform.py
@@ -0,0 +1,69 @@
+import json
+from argparse import ArgumentParser
+from sys import stdin
+
+from pyk.kast import KDefinition, KInner, KRule, KSentence, KVariable, top_down
+from pyk.kastManip import if_ktype
+
+
+def main():
+ parser = create_argument_parser()
+ args = parser.parse_args()
+
+ with open(args.compiled_json, 'r') as f:
+ json_data = json.load(f)
+
+ format = json_data['format']
+ version = json_data['version']
+ term = json_data['term']
+
+ input_definition = KDefinition.from_dict(term)
+ output_definition = transform_definition(input_definition)
+
+ print(json.dumps({
+ 'format': format,
+ 'version': version,
+ 'term': output_definition.to_dict(),
+ }))
+
+
+def create_argument_parser() -> ArgumentParser:
+ parser = ArgumentParser(description='Transform rules of a compiled K definition')
+ parser.add_argument('compiled_json', type=str, help='Path to compiled.json')
+ return parser
+
+
+def transform_definition(definition: KDefinition) -> KDefinition:
+ return (
+ definition.let(modules=(
+ module.let(sentences=(
+ transform_sentence(sentence) for sentence in module.sentences
+ )) for module in definition.modules
+ ))
+ )
+
+
+def transform_sentence(sentence: KSentence) -> KSentence:
+ return transform_rule(sentence) if type(sentence) is KRule else sentence
+
+
+def transform_rule(rule: KRule) -> KRule:
+ return rule.let(
+ body=rename_anon_vars(rule.body),
+ requires=rename_anon_vars(rule.requires),
+ ensures=rename_anon_vars(rule.ensures),
+ )
+
+
+def rename_anon_vars(kinner: KInner) -> KInner:
+ return top_down(if_ktype(KVariable, rename_anon), kinner)
+
+
+def rename_anon(var: KVariable) -> KVariable:
+ if var.name.startswith('_Gen'):
+ return var.let(name='_Var' + var.name[4:])
+ return var
+
+
+if __name__ == "__main__":
+ main()