mirror of
https://github.com/flynx/diff.js.git
synced 2025-10-28 18:40:09 +00:00
preliminary format pattern complete...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
c2949d3d35
commit
27a9ec0e47
35
diff.js
35
diff.js
@ -251,6 +251,14 @@ var proxy = function(path, func){
|
||||
// XXX need to avoid recursion...
|
||||
// XXX should we avoid backtracking when pattern matching???
|
||||
// ...specifically when working with IN and OF...
|
||||
// XXX diffing a mismatching pattern should yield the exact position
|
||||
// (sub-pattern/rule) that failed and not just the whole pattern...
|
||||
// ...usually a pattern chain fails, i.e. the nested failing pattern
|
||||
// also fails its parent and so on, so it is not a trivial task
|
||||
// getting the source and probably the whole failed chain...
|
||||
// ...might be a good idea to build a trace failure pattern and
|
||||
// store it in .trace in the diff...
|
||||
//
|
||||
//
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
var LogicTypeClassPrototype = {
|
||||
@ -280,9 +288,9 @@ var LogicTypePrototype = {
|
||||
|| (obj != null
|
||||
&& obj.__cmp__
|
||||
&& obj.__cmp__(this, cmp, cache))
|
||||
c.set(obj, res)
|
||||
c.set(obj, !!res)
|
||||
|
||||
return res
|
||||
return !!res
|
||||
},
|
||||
}
|
||||
|
||||
@ -456,8 +464,8 @@ module.ARRAY =
|
||||
var NOT =
|
||||
module.NOT =
|
||||
object.makeConstructor('NOT', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp){
|
||||
return !cmp(this.value, obj) },
|
||||
__cmp__: function(obj, cmp, cache){
|
||||
return !cmp(this.value, obj, cache) },
|
||||
__init__: function(value){
|
||||
this.value = value
|
||||
},
|
||||
@ -468,9 +476,9 @@ object.makeConstructor('NOT', Object.assign(new LogicType(), {
|
||||
var OR =
|
||||
module.OR =
|
||||
object.makeConstructor('OR', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp){
|
||||
__cmp__: function(obj, cmp, cache){
|
||||
for(var m of this.members){
|
||||
if(cmp(m, obj)){
|
||||
if(cmp(m, obj, cache)){
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -486,9 +494,9 @@ object.makeConstructor('OR', Object.assign(new LogicType(), {
|
||||
var AND =
|
||||
module.AND =
|
||||
object.makeConstructor('AND', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp){
|
||||
__cmp__: function(obj, cmp, cache){
|
||||
for(var m of this.members){
|
||||
if(!cmp(m, obj)){
|
||||
if(!cmp(m, obj, cache)){
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -510,14 +518,14 @@ var IN =
|
||||
module.IN =
|
||||
object.makeConstructor('IN', Object.assign(new LogicType(), {
|
||||
// XXX add support for other stuff like sets and maps...
|
||||
__cmp__: function(obj, cmp){
|
||||
__cmp__: function(obj, cmp, cache){
|
||||
var p = this.value
|
||||
// XXX make this a break-on-match and not a go-through-the-whole-thing
|
||||
return typeof(obj) == typeof({})
|
||||
&& (p in obj
|
||||
|| obj.reduce(function(res, e){
|
||||
return res === false ?
|
||||
cmp(p, e)
|
||||
cmp(p, e, cache)
|
||||
: res }), false) },
|
||||
__init__: function(value){
|
||||
this.value = value
|
||||
@ -538,8 +546,8 @@ object.makeConstructor('IN', Object.assign(new LogicType(), {
|
||||
var AT =
|
||||
module.AT =
|
||||
object.makeConstructor('AT', Object.assign(new LogicType(), {
|
||||
__cmp__: function(obj, cmp){
|
||||
if(cmp(obj != null ? obj[this.key] : null, this.value)){
|
||||
__cmp__: function(obj, cmp, cache){
|
||||
if(cmp(obj != null ? obj[this.key] : null, this.value, cache)){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -1033,6 +1041,7 @@ module.Types = {
|
||||
// the above.
|
||||
//
|
||||
// NOTE: array path also supports patterns...
|
||||
// XXX should this use cmp(..) or this.cmp(..)
|
||||
filter: function(diff, filter){
|
||||
// string filter...
|
||||
filter = typeof(filter) == typeof('str') ?
|
||||
@ -1169,10 +1178,10 @@ module.Types = {
|
||||
// pass options and cache down.
|
||||
// see cache setup below...
|
||||
|| (diff(a, b) == null) }
|
||||
|
||||
// cache...
|
||||
//cache = this.__cache = cache || this.__cache || new Map()
|
||||
cache = cache || new Map()
|
||||
// cached diff...
|
||||
var diff = cache.diff = cache.diff || function(a, b){
|
||||
var l2 = cache.get(a) || new Map()
|
||||
var d = l2.get(b) || that.diff(a, b, options, cache)
|
||||
|
||||
114
format.js
114
format.js
@ -20,9 +20,14 @@ var {
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
// XXX need better mismatch checking -- ideally stating the exact spot
|
||||
// where we did not match...
|
||||
//
|
||||
// XXX need better mismatch checking -- ideally stating the exact spot
|
||||
// where we did not match and the path of fails it created...
|
||||
// XXX idea: would be nice to be able to use patterns to extract values
|
||||
// from structures (parsing)...
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
// Flat diff...
|
||||
|
||||
var VALUE =
|
||||
module.VALUE = OR(
|
||||
@ -31,39 +36,108 @@ module.VALUE = OR(
|
||||
ANY)
|
||||
|
||||
|
||||
var SIDE_VALUES =
|
||||
module.SIDE_VALUES = OR(
|
||||
// A and B...
|
||||
AND(
|
||||
AT('A', VALUE),
|
||||
AT('B', VALUE)),
|
||||
// only A...
|
||||
AT('A', VALUE),
|
||||
// only B...
|
||||
AT('B', VALUE))
|
||||
|
||||
var CHANGE =
|
||||
module.CHANGE = AND(
|
||||
AT('path', ARRAY),
|
||||
// XXX optional...
|
||||
// ...see DIFF_OBJECT's options for description...
|
||||
AT('type', OR(STRING, undefined)),
|
||||
OR(
|
||||
// A ans B...
|
||||
AND(
|
||||
AT('A', VALUE),
|
||||
AT('B', VALUE)),
|
||||
// only A...
|
||||
AT('A', VALUE),
|
||||
// only B...
|
||||
AT('B', VALUE)))
|
||||
SIDE_VALUES)
|
||||
|
||||
|
||||
var DIFF_FORMAT_FLAT =
|
||||
module.DIFF_FORMAT_FLAT = ARRAY(CHANGE)
|
||||
var DIFF_FLAT =
|
||||
module.DIFF_FLAT = OR(
|
||||
ARRAY(CHANGE),
|
||||
null)
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Tree diff...
|
||||
|
||||
var BASIC_CHANGE =
|
||||
module.BASIC_CHANGE = AND(
|
||||
AT('type', 'Basic'),
|
||||
SIDE_VALUES)
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
var OBJECT_ITEM =
|
||||
module.OBJECT_ITEM = OR(
|
||||
[STRING, DIFF_TREE],
|
||||
[STRING, STRING, DIFF_TREE])
|
||||
|
||||
var OBJECT_CHANGE =
|
||||
module.OBJECT_CHANGE = AND(
|
||||
AT('type', 'Object'),
|
||||
AT('items', ARRAY(OBJECT_ITEM)),
|
||||
// XXX
|
||||
AT('item_order', undefined))
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
var ARRAY_ITEM =
|
||||
module.ARRAY_ITEM = OR(
|
||||
[ANY, ANY, DIFF_TREE],
|
||||
[[ANY, NUMBER], [ANY, NUMBER], DIFF_TREE])
|
||||
|
||||
var ARRAY_ITEMS =
|
||||
module.ARRAY_ITEMS = AND(
|
||||
AT('length', OR(
|
||||
[NUMBER, NUMBER],
|
||||
undefined)),
|
||||
AT('items', ARRAY(
|
||||
OR(
|
||||
ARRAY_ITEM,
|
||||
OBJECT_ITEM))),
|
||||
// XXX
|
||||
AT('item_order', undefined))
|
||||
|
||||
var ARRAY_CHANGE =
|
||||
module.ARRAY_CHANGE = AND(
|
||||
AT('type', 'Array'),
|
||||
ARRAY_ITEMS)
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
var TEXT_CHANGE =
|
||||
module.TEXT_CHANGE = AND(
|
||||
AT('type', 'Text'),
|
||||
ARRAY_ITEMS)
|
||||
|
||||
// XXX it makes sense to make this a recursive pattern...
|
||||
// ...need to check if we stop on a recursive pattern...
|
||||
var DIFF_FORMAT_TREE =
|
||||
module.DIFF_FORMAT_TREE = ANY
|
||||
// XXX TEST!!!
|
||||
var DIFF_TREE =
|
||||
module.DIFF_TREE = OR(
|
||||
BASIC_CHANGE,
|
||||
OBJECT_CHANGE,
|
||||
ARRAY_CHANGE,
|
||||
TEXT_CHANGE,
|
||||
null)
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Diff...
|
||||
|
||||
var DIFF_OBJECT =
|
||||
module.DIFF_OBJECT = AND(
|
||||
// format metadata...
|
||||
AT('format', diff.FORMAT_NAME),
|
||||
//AT('version', STRING(/\d+\.\d+\.\d+/)),
|
||||
AT('version', diff.FORMAT_VERSION),
|
||||
|
||||
// instance metadata...
|
||||
AT('options', AND(
|
||||
AT('tree_diff', OR(BOOL, null)),
|
||||
AT('keep_none', OR(BOOL, null)),
|
||||
@ -74,18 +148,20 @@ module.DIFF_OBJECT = AND(
|
||||
AT('no_length', OR(BOOL, null)),
|
||||
AT('cmp', OR(FUNCTION, null)) )),
|
||||
AT('placeholders', AND(
|
||||
// XXX would be nice to store these and to use them to test later...
|
||||
// XXX would be nice to store these and to use them to test
|
||||
// deeper stuff (i.e. VALUE)...
|
||||
AT('NONE', ANY),
|
||||
AT('EMPTY', ANY))),
|
||||
|
||||
AT('timestamp', NUMBER),
|
||||
|
||||
// diff...
|
||||
OR(
|
||||
AND(
|
||||
AT('structure', 'flat'),
|
||||
AT('diff', DIFF_FORMAT_FLAT)),
|
||||
AT('diff', DIFF_FLAT)),
|
||||
AND(
|
||||
AT('structure', 'tree'),
|
||||
AT('diff', DIFF_FORMAT_TREE))) )
|
||||
AT('diff', DIFF_TREE))) )
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user