Skip to content

Instantly share code, notes, and snippets.

@davidbalbert
Last active January 16, 2018 21:56
Show Gist options
  • Save davidbalbert/50272b7e88d80a9a41f6ca0ad55cbcc7 to your computer and use it in GitHub Desktop.
Save davidbalbert/50272b7e88d80a9a41f6ca0ad55cbcc7 to your computer and use it in GitHub Desktop.
Database.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Database.js</title>
</head>
<body>
<script>
'use strict';
function isVar(x) {
return typeof x === 'string' && x[0] === '$';
}
const EMPTY_BINDING = {facts: []};
class Database {
constructor(...facts) {
this.facts = new Set(facts);
}
assert(fact) {
this.facts.add(fact);
}
refute(fact) {
this.facts.delete(fact);
}
query(qs, callback, bindings = [EMPTY_BINDING]) {
if (qs.length === 0) {
bindings.forEach(b => {
const assert = (fact) => {
fact.provenance = b.facts;
this.assert(fact);
}
const refute = (fact) => this.refute(fact);
callback(b, assert, refute)
});
return;
}
const newBindings = this.match(qs[0], this.facts, bindings);
return this.query(qs.slice(1), callback, newBindings);
}
match(q, facts, bindings) {
let filtered = [];
for (let b of bindings) {
for (let f of facts) {
const newB = this.matchOne(q, f, b);
if (newB) {
filtered.push(newB);
}
}
}
return filtered;
}
matchOne(q, fact, binding) {
if (q.length !== fact.length) {
return null;
}
let newB = {...binding, facts: [...binding.facts, fact]};
for (let i in q) {
const qpart = q[i];
if (isVar(qpart) && newB.hasOwnProperty(qpart) && newB[qpart] !== fact[i]) {
return null;
} else if (isVar(qpart)) {
newB[qpart] = fact[i];
} else if (qpart !== fact[i]) {
return null;
}
}
return newB;
}
}
let db = new Database(
['C1', 'is a', 'circle', 'at', '(', 300, ',', 300, ')'],
['C1', '\'s', 'color', 'is', 'blue'],
['C1', '\'s', 'radius', 'is', 50],
['C2', 'is a', 'circle', 'at', '(', 200, ',', 500, ')'],
['C2', '\'s', 'color', 'is', 'red'],
['C2', '\'s', 'radius', 'is', 120],
)
db.query([
['$name', 'is a', 'circle', 'at', '(', '$x', ',', '$y', ')'],
['$name', '\'s', 'radius', 'is', '$r'],
['$name', '\'s', 'color', 'is', 'red'],
], m => console.log(m));
db.query([
['$name', 'is a', 'circle', 'at', '(', '$x', ',', '$y', ')'],
['$name', '\'s', 'radius', 'is', '$r'],
], ({$name, $r}, assert, refute) => {
console.log($name, $r);
if ($r > 100) {
assert([$name, 'is', 'large']);
}
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment