8000 first pass ability to add external functions to datalog rules · Z80coder/datalog-cpp@efa8767 · GitHub
[go: up one dir, main page]

Skip to content

Commit efa8767

Browse files
author
wright
committed
first pass ability to add external functions to datalog rules
1 parent 01d8615 commit efa8767

File tree

2 files changed

+97
-28
lines changed

2 files changed

+97
-28
lines changed

src/Datalog.h

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <numeric>
77
#include <optional>
88
#include <limits>
9+
#include <functional>
910
#include <cassert>
1011
#include <iostream>
1112
#include <memory>
@@ -98,7 +99,11 @@ static bool bind(const GROUND_TYPE &fact, tuple<Ts...> &atom)
9899
template <typename T>
99100
static void ground(const Variable<T>* s, T &v)
100101
{
101-
assert(s->isBound());
102+
// TODO: restrict to debug builds only
103+
if (!s->isBound()) {
104+
cerr << "ERROR: unbound variable (" << s << ")" << endl;
105+
exit(EXIT_FAILURE);
106+
}
102107
v = s->value();
103108
}
104109

@@ -136,13 +141,13 @@ struct AtomTypeSpecifier {
136141
};
137142

138143
template <typename ... Ts>
139-
static tuple<Ts...> atom(Ts&&... args) {
144+
static tuple<Ts...> atomImpl(Ts&&... args) {
140145
return tuple<Ts...>{args...};
141146
}
142147

143148
template <typename RELATION_TYPE, typename ... Us>
144149
static AtomTypeSpecifier<RELATION_TYPE, Us...> atom(Us&&... args) {
145-
return AtomTypeSpecifier<RELATION_TYPE, Us...>{atom(args...)};
150+
return AtomTypeSpecifier<RELATION_TYPE, Us...>{atomImpl(args...)};
146151
}
147152

148153
template <typename... Ts>
@@ -173,17 +178,42 @@ struct Rule
173178
typedef tuple<const typename BODY_RELATIONs::TrackedGround *...> SliceType;
174179
};
175180

181+
template <typename HEAD_ATOM_SPECIFIER, typename... BODY_ATOM_SPECIFIERs>
182+
struct RuleInstance;
183+
184+
template <typename EXTERNALS_TYPE, typename HEAD_ATOM_SPECIFIER, typename... BODY_ATOM_SPECIFIERs>
185+
struct ExternalRuleInstance;
186+
187+
template<typename ... EXTERNAL_TYPEs>
188+
struct Externals {
189+
tuple<const EXTERNAL_TYPEs&...> externals;
190+
};
191+
176192
template <typename HEAD_ATOM_SPECIFIER, typename... BODY_ATOM_SPECIFIERs>
177193
struct RuleInstance {
178194
typedef Rule<typename HEAD_ATOM_SPECIFIER::RelationType, typename BODY_ATOM_SPECIFIERs::RelationType...> RuleType;
179195
typedef typename HEAD_ATOM_SPECIFIER::AtomType HeadType;
180196
HeadType head;
181197
typedef tuple<typename BODY_ATOM_SPECIFIERs::AtomType...> BodyType;
182198
BodyType body;
199+
200+
template <typename ... EXTERNAL_TYPEs>
201+
ExternalRuleInstance<Externals<EXTERNAL_TYPEs...>, HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> externals(
202+
const EXTERNAL_TYPEs&... externals
203+
) {
204+
typedef ExternalRuleInstance<Externals<EXTERNAL_TYPEs...>, HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> RuleInstanceType;
205+
return RuleInstanceType{head, body, Externals<EXTERNAL_TYPEs...>{externals...}};
206+
}
207+
208+
};
209+
210+
template <typename EXTERNALS_TYPE, typename HEAD_ATOM_SPECIFIER, typename... BODY_ATOM_SPECIFIERs>
211+
struct ExternalRuleInstance : RuleInstance<HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> {
212+
const EXTERNALS_TYPE& externals;
183213
};
184214

185215
template <typename HEAD_ATOM_SPECIFIER, typename... BODY_ATOM_SPECIFIERs>
186-
RuleInstance<HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> rule(
216+
static RuleInstance<HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> rule(
187217
const HEAD_ATOM_SPECIFIER& h,
188218
const BODY_ATOM_SPECIFIERs&... b
189219
) {
@@ -193,6 +223,28 @@ RuleInstance<HEAD_ATOM_SPECIFIER, BODY_ATOM_SPECIFIERs...> rule(
193223
return RuleInstanceType{head, body};
194224
}
195225

226+
// Rules with external functions
227+
228+
template<typename T, typename ... ATOM_TYPE_SPECIFIERs>
229+
struct ExternalFunction {
230+
Variable<T>& bindVariable;
231+
typedef tuple<const ATOM_TYPE_SPECIFIERs&...> AtomsTupleType;
232+
AtomsTupleType boundAtoms;
233+
typedef tuple<const typename ATOM_TYPE_SPECIFIERs::RelationType::Ground&...> ArgsType;
234+
function<T(const ArgsType&)> externalFunction;
235+
};
236+
237+
template<typename T, typename ... ATOM_TYPE_SPECIFIERs>
238+
static ExternalFunction<T, ATOM_TYPE_SPECIFIERs...> external(
239+
unique_ptr<Variable<T>>& bindVariable,
240+
function<T(const typename ExternalFunction<T, ATOM_TYPE_SPECIFIERs...>::ArgsType&)> externalFunction,
241+
const ATOM_TYPE_SPECIFIERs&... boundAtoms
242+
) {
243+
return ExternalFunction<T, ATOM_TYPE_SPECIFIERs...> {
244+
*bindVariable, {boundAtoms...}, externalFunction
245+
};
246+
}
247+
196248
template <typename RELATION_TYPE>
197249
static ostream& operator<<(ostream& out, const typename RELATION_TYPE::Ground& t) {
198250
out << "[";
@@ -480,7 +532,6 @@ static bool bindBodyAtomsToSlice(typename RULE_INSTANCE_TYPE::BodyType &atoms,
480532
// get the atom
481533
auto &atom = get<I>(atoms);
482534
// try to bind the atom with the fact
483-
//success = bind(fact.second, atom);
484535
success = bind(fact.second, atom);
485536
}
486537
return success;

tests/types_test.cpp

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -196,49 +196,67 @@ bool test4()
196196
struct Person : Relation<Name, Age, Gender, Country>{};
197197

198198
// Extensional data
199-
Name ian{"Ian"};
200-
Name anna{"Anna"};
201-
Name albert{"Albert"};
202-
Name henry{"Henry"};
203-
Name rhiannon{"Rhiannon"};
204-
Name jean{"Jean"};
205-
Name bas{"Bas"};
199+
Name sam{"Sam"};
200+
Name tim{"Tim"};
201+
Name rod{"Rod"};
202+
Name bob{"Bob"};
203+
Name jill{"Jill"};
204+
Name jane{"Jane"};
205+
Name sally{"Sally"};
206206

207207
Person::Set people{
208-
{ian, 48u, male, scotland},
209-
{anna, 25u, female, england},
210-
{albert, 25u, male, germany},
211-
{henry, 25u, male, england},
212-
{rhiannon, 25u, female, wales},
213-
{jean, 25u, male, france},
214-
{bas, 25u, male, netherlands}
208+
{sam, 48u, male, scotland},
209+
{tim, 25u, male, england},
210+
{rod, 38u, male, germany},
211+
{bob, 18u, male, england},
212+
{jill, 56u, female, wales},
213+
{jane, 32u, female, france},
214+
{sally, 40u, female, netherlands}
215215
};
216216

217217
auto name = var<Name>();
218218
auto age = var<Age>();
219-
auto country = var<Country>();
220219
auto gender = var<Gender>();
220+
auto country = var<Country>();
221221

222222
struct Female : Relation<Name>{};
223223
auto females = rule(
224224
atom<Female>(name),
225225
atom<Person>(name, age, female, country)
226226
);
227227

228-
#if 0
229-
typedef float Height;
230-
struct Height : Relation<Name, Height>{};
228+
#if 1
229+
typedef float Metres;
230+
struct Height : Relation<Name, Metres>{};
231231

232-
auto height = rule(
232+
auto height = var<Metres>();
233+
234+
auto heights = rule(
233235
atom<Height>(name, height),
234-
bind(height, external(f, atom<Person>(name, age, gender, country)))
236+
atom<Person>(name, age, female, country)
235237
);
238+
239+
auto anyPerson = atom<Person>(name, age, gender, country);
240+
241+
auto heightsExternal = rule(
242+
atom<Height>(name, height),
243+
anyPerson
244+
).externals(
245+
external<Metres>(
246+
height,
247+
[](const tuple<const Person::Ground&>& atoms) {
248+
return 0.0f;
249+
},
250+
anyPerson
251+
)
252+
);
253+
236254
#endif
237255

238256
// Apply rules
239-
State<Person, Female> state{people, {}};
240-
RuleSet<decltype(females)> rules{
241-
{females}
257+
State<Person, Female, Height> state{people, {}, {}};
258+
RuleSet<decltype(females), decltype(heights)> rules{
259+
{females, heights}
242260
};
243261

244262
cout << "before = " << state << endl;

0 commit comments

Comments
 (0)
0