Skip to content

Commit 236a777

Browse files
authored
Add term simplification to Python bindings (#897)
This PR exposes the concrete term simplification routines already used by the booster to the Python bindings so that they can be called from Pyk. Specifically, it adds two free functions to the `runtime` module: ```python simplify_pattern(Pattern, Sort) -> Pattern simplify_bool_pattern(Pattern) -> bool ``` These are exposed as free functions because they depend on the runtime library and so can't be automatically bound to the `Pattern` class as methods; I suggest Pyk probably wants to monkey-patch them into its `Pattern` class along with some kind of dynamic check for whether the `runtime` module has been loaded or not. Previously, the C and Python bindings didn't share a great deal of code; the simplification routine is the first bit of non-trivial behaviour that they need to share. I have therefore started a reorganisation of the bindings code to extract as much functionality to a common library, which has the additional benefit of reducing the amount of memory-leak prone handling of C wrapper structures. To keep the diff in this PR reasonable I have not completed this migration, but this is future work that I will complete in a future PR. A summary of the changes in this PR is as follows: * Build a common bindings library that the C and Python bindings link against. * Extract the minimal set of features from the existing C bindings that the Python bindings require to perform term simplification, and port the C bindings over to calling the extracted common features. * Add a test case to the Python bindings test suite that performs a few small simplifications of sort `Int` and `Bool`; these are really just smoke tests and Pyk should test the feature more thoroughly.
1 parent c234191 commit 236a777

File tree

14 files changed

+2437
-65
lines changed

14 files changed

+2437
-65
lines changed

bin/llvm-kompile-clang

+1
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ if $link; then
236236
"$LIBDIR"/libcollections.a \
237237
"$LIBDIR"/libParser.a \
238238
"$LIBDIR"/libAST.a \
239+
"$LIBDIR"/libBindingsCore.a \
239240
"$LIBDIR"/libBinaryKore.a \
240241
"$LIBDIR"/libKOREPrinter.a \
241242
"$LIBDIR"/liballoc.a \

bindings/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
add_subdirectory(c)
2+
add_subdirectory(core)
23
add_subdirectory(python)

bindings/c/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ target_include_directories(kllvm-c-static PUBLIC
77

88
target_link_libraries(kllvm-c-static PUBLIC
99
AST
10+
BindingsCore
1011
util
1112
collect
1213
)

bindings/c/lib.cpp

+11-57
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
#include <kllvm/ast/AST.h>
44
#include <kllvm/binary/serializer.h>
5+
#include <kllvm/bindings/core/core.h>
56
#include <kllvm/parser/KOREParser.h>
67
#include <kllvm/printer/printer.h>
78

8-
#define FMT_HEADER_ONLY
99
#include <fmt/format.h>
1010

1111
#include <filesystem>
@@ -53,7 +53,6 @@ extern "C" {
5353
block *take_steps(int64_t, block *);
5454
void initStaticObjects(void);
5555
void freeAllKoreMem(void);
56-
void *constructInitialConfiguration(const kllvm::KOREPattern *);
5756
}
5857

5958
extern "C" {
@@ -186,14 +185,8 @@ kore_pattern *kore_pattern_new_token_with_len(
186185

187186
kore_pattern *kore_pattern_new_injection(
188187
kore_pattern const *term, kore_sort const *from, kore_sort const *to) {
189-
auto inj_sym = kore_symbol_new("inj");
190-
kore_symbol_add_formal_argument(inj_sym, from);
191-
kore_symbol_add_formal_argument(inj_sym, to);
192-
193-
auto inj = kore_composite_pattern_from_symbol(inj_sym);
194-
kore_composite_pattern_add_argument(inj, term);
195-
196-
kore_symbol_free(inj_sym);
188+
auto inj = new kore_pattern;
189+
inj->ptr_ = kllvm::bindings::make_injection(term->ptr_, from->ptr_, to->ptr_);
197190
return inj;
198191
}
199192

@@ -243,7 +236,7 @@ kore_pattern *kore_pattern_desugar_associative(kore_pattern const *pat) {
243236
}
244237

245238
block *kore_pattern_construct(kore_pattern const *pat) {
246-
return static_cast<block *>(constructInitialConfiguration(pat->ptr_.get()));
239+
return kllvm::bindings::construct_term(pat->ptr_);
247240
}
248241

249242
char *kore_block_dump(block *term) {
@@ -258,53 +251,24 @@ char *kore_block_dump(block *term) {
258251
}
259252

260253
kore_pattern *kore_pattern_from_block(block *term) {
261-
auto ast = termToKorePattern(term);
262-
263254
auto pat = new kore_pattern;
264-
pat->ptr_ = ast;
255+
pat->ptr_ = kllvm::bindings::term_to_pattern(term);
265256
return pat;
266257
}
267258

268259
bool kore_block_get_bool(block *term) {
269-
assert((((uintptr_t)term) & 1) == 0);
270-
return *(bool *)term->children;
260+
return kllvm::bindings::get_bool(term);
271261
}
272262

273263
bool kore_simplify_bool(kore_pattern const *pattern) {
274-
auto bool_sort = kore_composite_sort_new("SortBool");
275-
auto kitem_sort = kore_composite_sort_new("SortKItem");
276-
277-
auto inj = kore_pattern_new_injection(pattern, bool_sort, kitem_sort);
278-
auto ret = kore_block_get_bool(kore_pattern_construct(inj));
279-
280-
kore_sort_free(bool_sort);
281-
kore_sort_free(kitem_sort);
282-
kore_pattern_free(inj);
283-
284-
return ret;
264+
return kllvm::bindings::simplify_to_bool(pattern->ptr_);
285265
}
286266

287267
void kore_simplify(
288268
kore_pattern const *pattern, kore_sort const *sort, char **data_out,
289269
size_t *size_out) {
290-
auto kitem_sort = kore_composite_sort_new("SortKItem");
291-
auto kitem_sort_str = kore_sort_dump(kitem_sort);
292-
293-
auto block = [&] {
294-
if (kore_sort_is_kitem(sort) || kore_sort_is_k(sort)) {
295-
return kore_pattern_construct(pattern);
296-
} else {
297-
auto inj = kore_pattern_new_injection(pattern, sort, kitem_sort);
298-
auto ret = kore_pattern_construct(inj);
299-
kore_pattern_free(inj);
300-
return ret;
301-
}
302-
}();
303-
304-
serializeConfiguration(block, kitem_sort_str, data_out, size_out, true);
305-
306-
kore_sort_free(kitem_sort);
307-
free(kitem_sort_str);
270+
auto block = kllvm::bindings::simplify_to_term(pattern->ptr_, sort->ptr_);
271+
serializeConfiguration(block, "SortKItem{}", data_out, size_out, true);
308272
}
309273

310274
void kore_simplify_binary(
@@ -370,21 +334,11 @@ bool kore_sort_is_concrete(kore_sort const *sort) {
370334
}
371335

372336
bool kore_sort_is_kitem(kore_sort const *sort) {
373-
if (auto composite
374-
= dynamic_cast<kllvm::KORECompositeSort *>(sort->ptr_.get())) {
375-
return composite->getName() == "SortKItem";
376-
}
377-
378-
return false;
337+
return kllvm::bindings::is_sort_kitem(sort->ptr_);
379338
}
380339

381340
bool kore_sort_is_k(kore_sort const *sort) {
382-
if (auto composite
383-
= dynamic_cast<kllvm::KORECompositeSort *>(sort->ptr_.get())) {
384-
return composite->getName() == "SortK";
385-
}
386-
387-
return false;
341+
return kllvm::bindings::is_sort_k(sort->ptr_);
388342
}
389343

390344
/* KORECompositeSort */

bindings/core/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_library(BindingsCore
2+
src/core.cpp
3+
)
4+
5+
target_link_libraries(BindingsCore
6+
PUBLIC AST fmt::fmt-header-only
7+
)
8+
9+
install(
10+
TARGETS BindingsCore
11+
ARCHIVE DESTINATION lib/kllvm
12+
)

bindings/core/src/core.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include <kllvm/bindings/core/core.h>
2+
3+
using namespace kllvm;
4+
5+
/*
6+
* These declarations are internal to the backend and aren't exposed explicitly
7+
* through any header files, so we pull them in manually here.
8+
*/
9+
extern "C" {
10+
void *constructInitialConfiguration(const KOREPattern *);
11+
}
12+
13+
namespace kllvm::bindings {
14+
15+
std::shared_ptr<KOREPattern> make_injection(
16+
std::shared_ptr<KOREPattern> term, std::shared_ptr<KORESort> from,
17+
std::shared_ptr<KORESort> to) {
18+
auto inj_sym = KORESymbol::Create("inj");
19+
20+
inj_sym->addFormalArgument(from);
21+
inj_sym->addFormalArgument(to);
22+
23+
auto inj = KORECompositePattern::Create(std::move(inj_sym));
24+
inj->addArgument(term);
25+
26+
return inj;
27+
}
28+
29+
block *construct_term(std::shared_ptr<KOREPattern> const &pattern) {
30+
return static_cast<block *>(constructInitialConfiguration(pattern.get()));
31+
}
32+
33+
std::shared_ptr<KOREPattern> term_to_pattern(block *term) {
34+
return termToKorePattern(term);
35+
}
36+
37+
bool get_bool(block *term) {
38+
assert((((uintptr_t)term) & 1) == 0);
39+
return *(bool *)term->children;
40+
}
41+
42+
bool simplify_to_bool(std::shared_ptr<KOREPattern> pattern) {
43+
auto bool_sort = KORECompositeSort::Create("SortBool");
44+
auto kitem_sort = KORECompositeSort::Create("SortKItem");
45+
46+
auto inj = make_injection(pattern, bool_sort, kitem_sort);
47+
return get_bool(construct_term(inj));
48+
}
49+
50+
block *simplify_to_term(
51+
std::shared_ptr<KOREPattern> pattern, std::shared_ptr<KORESort> sort) {
52+
auto kitem_sort = KORECompositeSort::Create("SortKItem");
53+
54+
if (is_sort_kitem(sort) || is_sort_k(sort)) {
55+
return construct_term(pattern);
56+
} else {
57+
auto inj = make_injection(pattern, sort, kitem_sort);
58+
return construct_term(inj);
59+
}
60+
}
61+
62+
std::shared_ptr<KOREPattern>
63+
simplify(std::shared_ptr<KOREPattern> pattern, std::shared_ptr<KORESort> sort) {
64+
return term_to_pattern(simplify_to_term(pattern, sort));
65+
}
66+
67+
bool is_sort_kitem(std::shared_ptr<KORESort> const &sort) {
68+
if (auto composite = std::dynamic_pointer_cast<KORECompositeSort>(sort)) {
69+
return composite->getName() == "SortKItem";
70+
}
71+
72+
return false;
73+
}
74+
75+
bool is_sort_k(std::shared_ptr<KORESort> const &sort) {
76+
if (auto composite = std::dynamic_pointer_cast<KORECompositeSort>(sort)) {
77+
return composite->getName() == "SortK";
78+
}
79+
80+
return false;
81+
}
82+
83+
} // namespace kllvm::bindings

bindings/python/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ target_link_libraries(_kllvm PUBLIC
2525
target_link_libraries(kllvm-python-static PUBLIC
2626
AST
2727
util
28+
BindingsCore
2829
)
2930

3031
install(FILES $<TARGET_FILE:kllvm-python-static>

bindings/python/runtime.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <kllvm/ast/AST.h>
2+
#include <kllvm/bindings/core/core.h>
23

34
#include <pybind11/pybind11.h>
45

@@ -46,6 +47,15 @@ void *constructInitialConfiguration(const KOREPattern *initial);
4647
void bind_runtime(py::module_ &m) {
4748
auto runtime = m.def_submodule("runtime", "K LLVM backend runtime");
4849

50+
// This simplification should really be a member function on the Python
51+
// Pattern class, but it depends on the runtime library and so needs to be
52+
// bound as a free function in the kllvm.runtime module.
53+
m.def(
54+
"simplify_pattern",
55+
[](std::shared_ptr<KOREPattern> pattern, std::shared_ptr<KORESort> sort) {
56+
return bindings::simplify(pattern, sort);
57+
});
58+
4959
// This class can't be used directly from Python; the mutability semantics
5060
// that we get from the Pybind wrappers make it really easy to break things.
5161
// We therefore have to wrap it up in some external Python code; see

include/kllvm/bindings/core/core.h

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef BINDINGS_CORE_H
2+
#define BINDINGS_CORE_H
3+
4+
#include <kllvm/ast/AST.h>
5+
6+
#include <memory>
7+
8+
// These headers need to be included last because they pollute a number of macro
9+
// definitions into the global namespace.
10+
#include <runtime/arena.h>
11+
#include <runtime/header.h>
12+
13+
namespace kllvm::bindings {
14+
15+
std::shared_ptr<kllvm::KOREPattern> make_injection(
16+
std::shared_ptr<kllvm::KOREPattern> term,
17+
std::shared_ptr<kllvm::KORESort> from, std::shared_ptr<kllvm::KORESort> to);
18+
19+
block *construct_term(std::shared_ptr<kllvm::KOREPattern> const &pattern);
20+
21+
std::shared_ptr<kllvm::KOREPattern> term_to_pattern(block *term);
22+
23+
bool get_bool(block *term);
24+
25+
bool simplify_to_bool(std::shared_ptr<kllvm::KOREPattern> pattern);
26+
27+
block *simplify_to_term(
28+
std::shared_ptr<kllvm::KOREPattern> pattern,
29+
std::shared_ptr<kllvm::KORESort> sort);
30+
31+
std::shared_ptr<kllvm::KOREPattern> simplify(
32+
std::shared_ptr<kllvm::KOREPattern> pattern,
33+
std::shared_ptr<kllvm::KORESort> sort);
34+
35+
bool is_sort_kitem(std::shared_ptr<kllvm::KORESort> const &sort);
36+
bool is_sort_k(std::shared_ptr<kllvm::KORESort> const &sort);
37+
38+
} // namespace kllvm::bindings
39+
40+
#endif

runtime/util/ConfigurationPrinter.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,6 @@ void printSortedConfigurationToFile(
301301
printConfigurationInternal(&w, subject, sort, false, &state);
302302
}
303303

304-
std::shared_ptr<kllvm::KOREPattern> termToKorePattern(block *subject) {
305-
auto *kore_str = printConfigurationToString(subject);
306-
auto kore = std::string(kore_str->data, len(kore_str));
307-
308-
auto parser = kllvm::parser::KOREParser::from_string(kore);
309-
return parser->pattern();
310-
}
311-
312304
extern "C" void printMatchResult(
313305
std::ostream &os, MatchLog *matchLog, size_t logSize,
314306
const std::string &definitionPath) {

runtime/util/ConfigurationSerializer.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <kllvm/ast/AST.h>
2+
#include <kllvm/binary/deserializer.h>
23
#include <kllvm/binary/serializer.h>
34
#include <kllvm/parser/KOREParser.h>
45

@@ -450,3 +451,11 @@ void serializeRawTermToFile(
450451
fwrite(data, 1, size, file);
451452
fclose(file);
452453
}
454+
455+
std::shared_ptr<kllvm::KOREPattern> termToKorePattern(block *subject) {
456+
char *data_out;
457+
size_t size_out;
458+
459+
serializeConfiguration(subject, "SortKItem{}", &data_out, &size_out, true);
460+
return deserialize_pattern(data_out, data_out + size_out);
461+
}

0 commit comments

Comments
 (0)