Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!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>
Add Comment
Please, Sign In to add comment