extended query language + docs..

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2018-11-30 17:56:24 +03:00
parent cad5d21697
commit 2288835f5a

View File

@ -329,6 +329,15 @@ var TagsPrototype = {
.map(function(s){ return [...s[1]] }) .map(function(s){ return [...s[1]] })
.flat())] }, .flat())] },
has: function(value){
for(var v in Object.values(this.__index)){
if(v.has(value)){
return true
}
}
return false
},
// Add/Remove/Modify tags API... // Add/Remove/Modify tags API...
// //
@ -424,32 +433,56 @@ var TagsPrototype = {
// Query API... // Query API...
// //
// XXX not sure about the format... // The language (JS):
// ...we can use diff: // <query> ::= <tag>
// tags.query( // | <call>
// AND('x', // | <list>
// OR('a', 'b'), //
// NOT('z'))) // <tag> ::= string
// the algorithm would be something like: //
// - get individual tags from query // <call> ::= [ <function-name> ]
// - match tags // | [ <function-name>, <query>, .. ]
// - build item list //
// another syntax variants might be: // <list> ::= []
// tags.query( // | [ <query>, .. ]
// {and: [ //
// 'x', //
// {or: ['a', 'b']}, // Values resolution:
// {not: 'z'} ]}) // tag -> resolves to list of matching values as returned by .values(tag)
// // lisp-like... // list -> resolved to list of resolved items
// tags.query( // call -> resolves to list of values returned by the called function
// ['and', //
// 'x', //
// ['or', 'a', 'b'], // Functions:
// ['not', 'z']]) // (and ..)
// XXX each of the arguments can be: // resolves to the list of values present in each of the arguments
// - tag -> resolves to list of values // (or ..)
// - query -> resolves to list of values // resolves to the list of all the values of all the arguments
// - list of values // (not a ..)
// resolves to list of values in a not present in any of the
// other arguments
//
//
// Special forms:
// (values ..)
// resolves to the list of values as-is.
// this makes it possible to pass in a set of values as-is
// without resolving them as tags.
//
//
// Testing queries:
// (values ..) adds the ability to test queries independently of
// the actual content of the Tags object by passing in explicit
// values...
//
// Example:
// .query(['and',
// ['values', 'a', 'b', 'c'],
// ['values', 'b', 'c', 'd']])
// -> ['b', 'c']
//
//
// XXX not sure about the .flat(1) calls...
__query_ns: { __query_ns: {
and: function(...args){ and: function(...args){
// NOTE: we are sorting the lists here to start with the // NOTE: we are sorting the lists here to start with the
@ -460,16 +493,20 @@ var TagsPrototype = {
.sort(function(a, b){ return a.length - b.length }) .sort(function(a, b){ return a.length - b.length })
return [...args return [...args
.reduce(function(res, l){ .reduce(function(res, l){
return res.intersect(l) }, return res.intersect(l.flat(1)) },
new Set(args.pop()))] }, new Set(args.pop()))] },
or: function(...args){ or: function(...args){
return [...new Set(args.flat())] }, return [...new Set(args.flat(1))] },
not: function(...args){ not: function(...args){
return [...args return [...args
.reduce(function(res, l){ .reduce(function(res, l){
return res.subtract(l) }, return res.subtract(l.flat(1)) },
new Set(args.shift()))] }, new Set(args.shift()))] },
}, },
__query_ns_special: {
values: function(...args){ return args },
flat: function(...args){ return args.flat() },
},
// XXX add support for string queries... // XXX add support for string queries...
parseQuery: function(query){ parseQuery: function(query){
// XXX // XXX
@ -477,21 +514,29 @@ var TagsPrototype = {
query: function(query){ query: function(query){
var that = this var that = this
var ns = this.__query_ns var ns = this.__query_ns
var sns = this.__query_ns_special
// Query Language Executor... // Query Language Executor...
var QL = function(args){ var QL = function(args){
return args[0] in ns ? return (
ns[args[0]].call(ns, ...QL(args.slice(1))) // function -> query args and call...
args[0] in ns ?
ns[args[0]].call(that, ...QL(args.slice(1)))
// special form -> pass args as-is...
: args[0] in sns ?
sns[args[0]].call(that, ...args.slice(1))
// list of tags -> query each arg...
: args : args
.map(function(arg){ .map(function(arg){
return arg instanceof Array ? return arg instanceof Array ?
QL(arg) QL(arg)
: that.values(arg) }) } : that.values(arg) }) ) }
return QL(query instanceof Array ? return QL(query instanceof Array ?
query query
: [query] ) : [query] )
.flat() // XXX should this be here???
//.flat(1)
}, },