mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-29 02:50:10 +00:00
added TEST(..) pattern + fixes and docs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
257322badc
commit
8e900bf5e5
13
README.md
13
README.md
@ -101,7 +101,7 @@ This tells us that we have four *changes*:
|
|||||||
- different `"name"`
|
- different `"name"`
|
||||||
- different `"hair"`
|
- different `"hair"`
|
||||||
- in `"skills"` missing `"guitar"`
|
- in `"skills"` missing `"guitar"`
|
||||||
- in `"skills"` different `"length"`
|
- in `"skills"` different `"length"` or *different number of skills*.
|
||||||
|
|
||||||
Some words on the format:
|
Some words on the format:
|
||||||
- `A` and `B` indicate the states of the *change* in the input objects,
|
- `A` and `B` indicate the states of the *change* in the input objects,
|
||||||
@ -386,7 +386,10 @@ XXX General description...
|
|||||||
### Logic patterns
|
### Logic patterns
|
||||||
|
|
||||||
`ANY`
|
`ANY`
|
||||||
Matches anything
|
Matches anything.
|
||||||
|
|
||||||
|
Note that this will also match `undefined`, to match anything but `undefined` use `NOT(undefined)`.
|
||||||
|
XXX this may still change.
|
||||||
|
|
||||||
|
|
||||||
`NOT(A)`
|
`NOT(A)`
|
||||||
@ -464,8 +467,8 @@ This is a shorthand for: `AND(ARRAY(x), ARRAY(y), ..)`
|
|||||||
|
|
||||||
Patterns support variables, the namespae/context is persistent per diff / compare call.
|
Patterns support variables, the namespae/context is persistent per diff / compare call.
|
||||||
|
|
||||||
`VAR(name, pattern)`
|
|
||||||
`VAR(name)`
|
`VAR(name)`
|
||||||
|
`VAR(name, pattern)`
|
||||||
A `VAR` is uniquely identified by name.
|
A `VAR` is uniquely identified by name.
|
||||||
This works in stages:
|
This works in stages:
|
||||||
1. Matches `pattern` until *first successful match*,
|
1. Matches `pattern` until *first successful match*,
|
||||||
@ -476,8 +479,8 @@ If no `pattern` is given `ANY` is assumed.
|
|||||||
|
|
||||||
Note that if the *cached* object is not a pattern it will not be matched structurally, i.e. first `===` and then `==` are used instead of `cmp(..)`.
|
Note that if the *cached* object is not a pattern it will not be matched structurally, i.e. first `===` and then `==` are used instead of `cmp(..)`.
|
||||||
|
|
||||||
`LIKE(name, pattern)`
|
|
||||||
`LIKE(name)`
|
`LIKE(name)`
|
||||||
|
`LIKE(name, pattern)`
|
||||||
This is the same as `VAR(..)` bud does a structural match (i.e. via `cmp(..)`).
|
This is the same as `VAR(..)` bud does a structural match (i.e. via `cmp(..)`).
|
||||||
|
|
||||||
Note that `VAR(..)` and `LIKE(..)` use the same namespace and can be used interchangeably depending on the type of matching desired.
|
Note that `VAR(..)` and `LIKE(..)` use the same namespace and can be used interchangeably depending on the type of matching desired.
|
||||||
@ -490,7 +493,7 @@ var P = [VAR('x', ANY), VAR('x'), LIKE('x')]
|
|||||||
cmp(P, [{}, {}, {}]) // -> false
|
cmp(P, [{}, {}, {}]) // -> false
|
||||||
|
|
||||||
var o = {}
|
var o = {}
|
||||||
// this cuccessds because o === o and cmp(o, {}) is true...
|
// this succeeds because o === o and cmp(o, {}) is true...
|
||||||
cmp(P, [o, o, {}]) // -> true
|
cmp(P, [o, o, {}]) // -> true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
116
diff.js
116
diff.js
@ -296,7 +296,7 @@ var LogicTypePrototype = {
|
|||||||
cmp: function(obj, cmp, context){
|
cmp: function(obj, cmp, context){
|
||||||
cmp = cmp || function(a, b){
|
cmp = cmp || function(a, b){
|
||||||
return a === b
|
return a === b
|
||||||
|| a == b
|
//|| a == b
|
||||||
|| (a.__cmp__ && a.__cmp__(b, cmp, context))
|
|| (a.__cmp__ && a.__cmp__(b, cmp, context))
|
||||||
|| (b.__cmp__ && b.__cmp__(a, cmp, context)) }
|
|| (b.__cmp__ && b.__cmp__(a, cmp, context)) }
|
||||||
|
|
||||||
@ -316,6 +316,8 @@ var LogicTypePrototype = {
|
|||||||
|| (obj != null
|
|| (obj != null
|
||||||
&& obj.__cmp__
|
&& obj.__cmp__
|
||||||
&& obj.__cmp__(this, cmp, context))
|
&& obj.__cmp__(this, cmp, context))
|
||||||
|
|
||||||
|
// cache...
|
||||||
c.set(obj, !!res)
|
c.set(obj, !!res)
|
||||||
|
|
||||||
return !!res
|
return !!res
|
||||||
@ -501,6 +503,11 @@ object.makeConstructor('NOT', Object.assign(new LogicType(), {
|
|||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Will compare as true if one of the .members compares as true...
|
// Will compare as true if one of the .members compares as true...
|
||||||
|
//
|
||||||
|
// XXX BUG:
|
||||||
|
// cmp(OR(1,[2],3), 2)
|
||||||
|
// -> true
|
||||||
|
// ...this is likely due to [2] == 2 -> true
|
||||||
var OR =
|
var OR =
|
||||||
module.OR =
|
module.OR =
|
||||||
object.makeConstructor('OR', Object.assign(new LogicType(), {
|
object.makeConstructor('OR', Object.assign(new LogicType(), {
|
||||||
@ -535,13 +542,64 @@ object.makeConstructor('AND', Object.assign(new LogicType(), {
|
|||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
var VAR =
|
||||||
|
module.VAR =
|
||||||
|
object.makeConstructor('VAR', Object.assign(new LogicType(), {
|
||||||
|
__cmp__: function(obj, cmp, context){
|
||||||
|
var context = context || this.context()
|
||||||
|
var ns = context.ns = context.ns || {}
|
||||||
|
var pattern = ns[this.name] =
|
||||||
|
this.name in ns ?
|
||||||
|
ns[this.name]
|
||||||
|
: this.pattern
|
||||||
|
|
||||||
|
if(cmp(pattern, obj)){
|
||||||
|
ns[this.name] = obj
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
__init__: function(name, pattern){
|
||||||
|
this.name = name
|
||||||
|
this.pattern = arguments.length < 2 ? ANY : pattern
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// this is like VAR(..) but will do a structural compare...
|
||||||
|
var LIKE =
|
||||||
|
module.LIKE =
|
||||||
|
object.makeConstructor('LIKE', Object.assign(new VAR(), {
|
||||||
|
__cmp__: function(obj, cmp, context){
|
||||||
|
var context = context || this.context()
|
||||||
|
|
||||||
|
return VAR.prototype.__cmp__.call(this, obj, cmp, context)
|
||||||
|
|| Diff.cmp(
|
||||||
|
this.name in context.ns ?
|
||||||
|
context.ns[this.name]
|
||||||
|
: this.pattern,
|
||||||
|
obj) },
|
||||||
|
}))
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// TEST(func) == L iff func(L) is true.
|
||||||
|
var TEST =
|
||||||
|
module.TEST =
|
||||||
|
object.makeConstructor('TEST', Object.assign(new VAR(), {
|
||||||
|
__cmp__: function(obj, cmp, context){
|
||||||
|
return this.func(obj, cmp, context) },
|
||||||
|
__init__: function(func){
|
||||||
|
this.func = func
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// IN(A) == L iff A in L
|
// IN(A) == L iff A in L
|
||||||
//
|
//
|
||||||
// NOTE: since this can do a search using cmp(..) thid will be slow on
|
// NOTE: since this can do a search using cmp(..) thid will be slow on
|
||||||
// large containers...
|
// large containers...
|
||||||
//
|
|
||||||
// XXX add support for other containers...
|
|
||||||
var IN =
|
var IN =
|
||||||
module.IN =
|
module.IN =
|
||||||
object.makeConstructor('IN', Object.assign(new LogicType(), {
|
object.makeConstructor('IN', Object.assign(new LogicType(), {
|
||||||
@ -549,13 +607,13 @@ object.makeConstructor('IN', Object.assign(new LogicType(), {
|
|||||||
// XXX should we check inherited stuff???
|
// XXX should we check inherited stuff???
|
||||||
__cmp__: function(obj, cmp, context){
|
__cmp__: function(obj, cmp, context){
|
||||||
var p = this.value
|
var p = this.value
|
||||||
return (obj instanceof Array ? obj
|
return (obj instanceof Map || obj instanceof Set ?
|
||||||
: obj instanceof Map || obj instanceof Set ? [...obj.values()]
|
[...obj.values()]
|
||||||
: [])
|
: [])
|
||||||
.concat(Object.values(obj))
|
.concat(Object.values(obj))
|
||||||
.reduce(function(res, e){
|
.reduce(function(res, e){
|
||||||
return res === false ?
|
return res === false ?
|
||||||
cmp(p, e, context)
|
!!cmp(p, e, context)
|
||||||
: res
|
: res
|
||||||
}, false) },
|
}, false) },
|
||||||
__init__: function(value){
|
__init__: function(value){
|
||||||
@ -606,50 +664,6 @@ object.makeConstructor('OF', Object.assign(new LogicType(), {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
var VAR =
|
|
||||||
module.VAR =
|
|
||||||
object.makeConstructor('VAR', Object.assign(new LogicType(), {
|
|
||||||
__cmp__: function(obj, cmp, context){
|
|
||||||
var context = context || this.context()
|
|
||||||
var ns = context.ns = context.ns || {}
|
|
||||||
var pattern = ns[this.name] =
|
|
||||||
this.name in ns ?
|
|
||||||
ns[this.name]
|
|
||||||
: this.pattern
|
|
||||||
|
|
||||||
if(cmp(pattern, obj)){
|
|
||||||
ns[this.name] = obj
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
__init__: function(name, pattern){
|
|
||||||
this.name = name
|
|
||||||
this.pattern = arguments.length < 2 ? ANY : pattern
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
// this is like VAR(..) but will do a structural compare...
|
|
||||||
var LIKE =
|
|
||||||
module.LIKE =
|
|
||||||
object.makeConstructor('LIKE', Object.assign(new VAR(), {
|
|
||||||
// XXX reuse...
|
|
||||||
__cmp__: function(obj, cmp, context){
|
|
||||||
var context = context || this.context()
|
|
||||||
|
|
||||||
return VAR.prototype.__cmp__.call(this, obj, cmp, context)
|
|
||||||
|| Diff.cmp(
|
|
||||||
this.name in context.ns ?
|
|
||||||
context.ns[this.name]
|
|
||||||
: this.pattern,
|
|
||||||
obj) },
|
|
||||||
}))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Placeholders...
|
// Placeholders...
|
||||||
//
|
//
|
||||||
@ -1234,7 +1248,7 @@ module.Types = {
|
|||||||
// XXX do we need to differentiate things like: new Number(123) vs. 123???
|
// XXX do we need to differentiate things like: new Number(123) vs. 123???
|
||||||
var bcmp = function(a, b, cmp){
|
var bcmp = function(a, b, cmp){
|
||||||
return a === b
|
return a === b
|
||||||
|| a == b
|
//|| a == b
|
||||||
// basic patters...
|
// basic patters...
|
||||||
|| a === that.ANY
|
|| a === that.ANY
|
||||||
|| b === that.ANY
|
|| b === that.ANY
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user