diff --git a/diff.js b/diff.js index 9dd367b..1b9f318 100644 --- a/diff.js +++ b/diff.js @@ -694,20 +694,36 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // AT(A, K) == L iff A in L and L[K] == A +// +// NOTE: this also supports path keys -- i.e. array of path elements that +// will be traversed and the last one checked... +// NOTE: to include an array as an explicit key (Map/...) wrap it in +// an array: +// AT([[123]], ...) +// // XXX .key can't be a pattern at this point... -// XXX this is a potential problem as with a pattern key we would need to -// look ahead to pick the correct candidate... +// ...to implement this we would need to do: +// 1) a search for a matching pattern... +// 2) handle multiple matches in some manner (first, all?)... // XXX this falls into recursion on: // X = AT('moo') // X.value = OR(123, X) // cmp(X, {'moo', 333}) // ...this would also break on checking a recursive structure against // a recursive pattern... +// XXX support Maps, ... var AT = module.AT = object.makeConstructor('AT', Object.assign(Object.create(LogicType.prototype), { __cmp__: function(obj, cmp, context){ - if(cmp(obj != null ? obj[this.key] : null, this.value, context)){ + var key = this.key instanceof Array ? this.key : [this.key] + var no_result = {} + obj = key + .reduce(function(o, k){ + return (o == null || o === no_result) ? + no_result + : o[k] }, obj) + if(obj !== no_result && cmp(obj, this.value, context)){ return true } return false diff --git a/format.js b/format.js index ccedf8a..ac620d0 100644 --- a/format.js +++ b/format.js @@ -34,9 +34,8 @@ var { var VALUE = module.VALUE = OR( - // XXX use these taken from .placeholders... - OR(EMPTY, LIKE('EMPTY')), - OR(NONE, LIKE('NONE')), + OR(LIKE('EMPTY'), EMPTY), + OR(LIKE('NONE'), NONE), ANY) @@ -54,8 +53,6 @@ module.SIDE_VALUES = OR( var CHANGE = module.CHANGE = AND( AT('path', L), - // XXX optional... - // ...see DIFF_OBJECT's options for description... AT('type', OR(S, undefined)), SIDE_VALUES) @@ -69,6 +66,7 @@ module.DIFF_FLAT = OR( //--------------------------------------------------------------------- // Tree diff... +// Basic... var BASIC_CHANGE = module.BASIC_CHANGE = AND( AT('type', 'Basic'), @@ -76,6 +74,7 @@ module.BASIC_CHANGE = AND( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Object... var OBJECT_ITEM = module.OBJECT_ITEM = OR( [S, DIFF_TREE], @@ -90,6 +89,7 @@ module.OBJECT_CHANGE = AND( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Array... var ARRAY_ITEM = module.ARRAY_ITEM = OR( [ANY, ANY, DIFF_TREE], @@ -100,8 +100,8 @@ module.ARRAY_ITEMS = AND( AT('length', OR( [N, N], undefined)), - AT('items', L( - OR( + AT('items', + L(OR( ARRAY_ITEM, OBJECT_ITEM))), // XXX @@ -109,18 +109,20 @@ module.ARRAY_ITEMS = AND( var ARRAY_CHANGE = module.ARRAY_CHANGE = AND( - AT('type', 'Array'), - ARRAY_ITEMS) + AT('type', 'Array'), + ARRAY_ITEMS) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Text... var TEXT_CHANGE = module.TEXT_CHANGE = AND( - AT('type', 'Text'), - ARRAY_ITEMS) + 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... + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// XXX need to check if we stop on a recursive pattern... // XXX TEST!!! var DIFF_TREE = module.DIFF_TREE = OR( @@ -142,20 +144,22 @@ module.DIFF_OBJECT = AND( AT('version', diff.FORMAT_VERSION), // instance metadata... - AT('options', AND( - AT('tree_diff', OR(B, NULL)), - AT('keep_none', OR(B, NULL)), - AT('min_text_length', OR(N, NULL)), - AT('no_attributes', OR(B, NULL)), - AT('NONE', OR(ANY, NULL)), - AT('EMPTY', OR(ANY, NULL)), - AT('no_length', OR(B, NULL)), - AT('cmp', OR(F, NULL)) )), - AT('placeholders', AND( - AT('NONE', - VAR('NONE', ANY)), - AT('EMPTY', - VAR('EMPTY', ANY)))), + AT('options', + AND( + AT('tree_diff', OR(B, NULL)), + AT('keep_none', OR(B, NULL)), + AT('min_text_length', OR(N, NULL)), + AT('no_attributes', OR(B, NULL)), + AT('NONE', OR(ANY, NULL)), + AT('EMPTY', OR(ANY, NULL)), + AT('no_length', OR(B, NULL)), + AT('cmp', OR(F, NULL)) )), + AT('placeholders', + AND( + AT('NONE', + VAR('NONE', ANY)), + AT('EMPTY', + VAR('EMPTY', ANY)))), AT('timestamp', N), // diff...