mirror of
				https://github.com/flynx/diff.js.git
				synced 2025-10-30 19:40:10 +00:00 
			
		
		
		
	AT(..) now supports patterns in keys or paths + docs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									a559ed7aeb
								
							
						
					
					
						commit
						a70605f742
					
				
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -554,6 +554,22 @@ Matches a *container* if it contains `A`. | |||||||
| `AT(K, A)`   | `AT(K, A)`   | ||||||
| Matches a *container* if it contains `A` *at* index/key `K` | Matches a *container* if it contains `A` *at* index/key `K` | ||||||
| 
 | 
 | ||||||
|  | If `K` is a pattern or a path containing a pattern then matching is done as follows: | ||||||
|  | 1. select all keys/paths that match `K` | ||||||
|  | 2. get all values at the selected keys/paths | ||||||
|  | 3. match iff *all* of the selected values match `A` | ||||||
|  | 
 | ||||||
|  | Note that to use an explicit array for `K`, wrap it in an array, e.g. to use `[item, ..]` as key write: `AT([[item, ..]], ..)`. | ||||||
|  | 
 | ||||||
|  | `AT(K)`   | ||||||
|  | Matches if a *container* has an index/key `K`. | ||||||
|  | 
 | ||||||
|  | This is equivalent to `AT(K, ANY)`. | ||||||
|  | 
 | ||||||
|  | ~~`ORDERED(A, B)`~~   | ||||||
|  | 
 | ||||||
|  | ~~`ADJACENT(A, B, ...)`~~   | ||||||
|  | 
 | ||||||
| ~~`OF(A, N)`~~   | ~~`OF(A, N)`~~   | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										97
									
								
								diff.js
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								diff.js
									
									
									
									
									
								
							| @ -667,10 +667,11 @@ object.makeConstructor('TEST', Object.assign(Object.create(LogicType.prototype), | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | ||||||
| // IN(A) == L iff A in L
 | // IN(A) == L iff A contained 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...
 | ||||||
|  | // NOTE: to test if a key exists use AT(key)
 | ||||||
| var IN =  | var IN =  | ||||||
| module.IN =  | module.IN =  | ||||||
| object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { | object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { | ||||||
| @ -678,7 +679,7 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { | |||||||
| 	// 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 Map || obj instanceof Set ?  | 		return ((obj instanceof Map || obj instanceof Set) ?  | ||||||
| 			[...obj.values()] | 			[...obj.values()] | ||||||
| 			: []) | 			: []) | ||||||
| 				.concat(Object.values(obj)) | 				.concat(Object.values(obj)) | ||||||
| @ -693,7 +694,13 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { | |||||||
| })) | })) | ||||||
| 
 | 
 | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | ||||||
| // AT(A, K) == L iff A in L and L[K] == A
 | // AT(K, A) == L iff A in L and L[K] == A
 | ||||||
|  | //
 | ||||||
|  | // If K is a pattern or a path containing a pattern this works in the 
 | ||||||
|  | // following stages:
 | ||||||
|  | // 	1) select all the keys/paths that match K
 | ||||||
|  | // 	2) get all the values at the matching paths
 | ||||||
|  | // 	3) return true if ALL the values match A
 | ||||||
| //
 | //
 | ||||||
| // NOTE: this also supports path keys -- i.e. array of path elements that
 | // NOTE: this also supports path keys -- i.e. array of path elements that
 | ||||||
| // 		will be traversed and the last one checked...
 | // 		will be traversed and the last one checked...
 | ||||||
| @ -701,10 +708,10 @@ object.makeConstructor('IN', Object.assign(Object.create(LogicType.prototype), { | |||||||
| // 		an array:
 | // 		an array:
 | ||||||
| // 			AT([[123]], ...)
 | // 			AT([[123]], ...)
 | ||||||
| //
 | //
 | ||||||
| // XXX .key can't be a pattern at this point...
 | // XXX pattern keys are still experimental, and the exact matching rules 
 | ||||||
| // 		...to implement this we would need to do:
 | // 		may still change...
 | ||||||
| // 			1) a search for a matching pattern...
 | // 		...not yet sure if on step #3 we should require ALL or at least 
 | ||||||
| // 			2) handle multiple matches in some manner (first, all?)...
 | // 		one match, though I'm leaning towards ALL...
 | ||||||
| // XXX this falls into recursion on:
 | // XXX this falls into recursion on:
 | ||||||
| // 		X = AT('moo')
 | // 		X = AT('moo')
 | ||||||
| // 		X.value = OR(123, X)
 | // 		X.value = OR(123, X)
 | ||||||
| @ -717,23 +724,79 @@ module.AT = | |||||||
| object.makeConstructor('AT', Object.assign(Object.create(LogicType.prototype), { | object.makeConstructor('AT', Object.assign(Object.create(LogicType.prototype), { | ||||||
| 	__cmp__: function(obj, cmp, context){ | 	__cmp__: function(obj, cmp, context){ | ||||||
| 		var key = this.key instanceof Array ? this.key : [this.key] | 		var key = this.key instanceof Array ? this.key : [this.key] | ||||||
| 		var no_result = {} | 		var value = this.value | ||||||
| 		obj = key | 		//return key
 | ||||||
|  | 		var res = key | ||||||
| 			.reduce(function(o, k){ | 			.reduce(function(o, k){ | ||||||
| 				return (o == null || o === no_result) ?  | 				return o | ||||||
| 					no_result  | 					.map(function(o){ | ||||||
| 					: o[k] }, obj) | 						return o == null ?  | ||||||
| 		if(obj !== no_result && cmp(obj, this.value, context)){ | 								[] | ||||||
| 			return true | 							// pattern key,,,
 | ||||||
| 		} | 							: k instanceof LogicType ? | ||||||
| 		return false | 								Object.entries(o) | ||||||
|  | 									.filter(function(e){ | ||||||
|  | 										return cmp(k, e[0], context) }) | ||||||
|  | 									.map(function(e){  | ||||||
|  | 										return e[1] }) | ||||||
|  | 							// normal key...
 | ||||||
|  | 							// NOTE: we are not using 'k in o' here because 
 | ||||||
|  | 							// 		only objects are supported by the in 
 | ||||||
|  | 							// 		operator and we can get any value...
 | ||||||
|  | 							: Object.keys(o).indexOf(k) >= 0 ? | ||||||
|  | 								[o[k]]  | ||||||
|  | 							// key not in container...
 | ||||||
|  | 							: [] }) | ||||||
|  | 					// flatten the list of candidates...
 | ||||||
|  | 					.reduce(function(o, e){  | ||||||
|  | 						return o.concat(e) }, []) }, [obj]) | ||||||
|  | 			/* | ||||||
|  | 			.filter(function(e){ | ||||||
|  | 				return cmp(e, value, context)}) | ||||||
|  | 			// at least one must match...
 | ||||||
|  | 			.length > 0 | ||||||
|  | 			//*/
 | ||||||
|  | 		return obj != null | ||||||
|  | 	   		&& res.length > 0	 | ||||||
|  | 			&& res | ||||||
|  | 				.filter(function(e){ | ||||||
|  | 					return cmp(e, value, context)}) | ||||||
|  | 				// all must match...
 | ||||||
|  | 				.length == res.length | ||||||
| 	}, | 	}, | ||||||
| 	__init__: function(key, value){ | 	__init__: function(key, value){ | ||||||
| 		this.key = key | 		this.key = key | ||||||
| 		this.value = value | 		this.value = arguments.length < 2 ? ANY : value | ||||||
| 	}, | 	}, | ||||||
| })) | })) | ||||||
| 
 | 
 | ||||||
|  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | ||||||
|  | // XXX ORDERED(A, B, ..) == L iff A is before B, B is before C, ... etc.
 | ||||||
|  | var ORDERED =  | ||||||
|  | module.ORDERED =  | ||||||
|  | object.makeConstructor('ORDERED', Object.assign(Object.create(LogicType.prototype), { | ||||||
|  | 	__cmp__: function(obj, cmp){ | ||||||
|  | 		// XXX
 | ||||||
|  | 	}, | ||||||
|  | 	__init__: function(...items){ | ||||||
|  | 		this.items = items | ||||||
|  | 	}, | ||||||
|  | })) | ||||||
|  | 
 | ||||||
|  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | ||||||
|  | // XXX ADJACENT(A, B, ..) == L iff A directly before B, B directly before C, ...
 | ||||||
|  | var ADJACENT =  | ||||||
|  | module.ADJACENT =  | ||||||
|  | object.makeConstructor('ADJACENT', Object.assign(Object.create(LogicType.prototype), { | ||||||
|  | 	__cmp__: function(obj, cmp){ | ||||||
|  | 		// XXX
 | ||||||
|  | 	}, | ||||||
|  | 	__init__: function(...items){ | ||||||
|  | 		this.items = items | ||||||
|  | 	}, | ||||||
|  | })) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | ||||||
| // XXX OF(A, N) == L iff L contains N occurrences of A
 | // XXX OF(A, N) == L iff L contains N occurrences of A
 | ||||||
| // XXX this is a potential problem as it would require us to look ahead 
 | // XXX this is a potential problem as it would require us to look ahead 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user