feat: Support better error messages for list/attrs element checks
This commit is contained in:
		
							parent
							
								
									fe33a82a07
								
							
						
					
					
						commit
						040b719570
					
				
					 1 changed files with 13 additions and 5 deletions
				
			
		
							
								
								
									
										18
									
								
								yants.nix
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								yants.nix
									
										
									
									
									
								
							| 
						 | 
					@ -4,17 +4,16 @@
 | 
				
			||||||
# All types (should) compose as expected.
 | 
					# All types (should) compose as expected.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# TODO:
 | 
					# TODO:
 | 
				
			||||||
#  - error messages for type-checks of map/list elements are bad
 | 
					 | 
				
			||||||
#  - enums?
 | 
					#  - enums?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{ toPretty ? ((import <nixpkgs> {}).lib.generators.toPretty) }:
 | 
					{ toPretty ? ((import <nixpkgs> {}).lib.generators.toPretty {}) }:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Checks are simply functions of the type `a -> bool` which check
 | 
					# Checks are simply functions of the type `a -> bool` which check
 | 
				
			||||||
# whether `a` conforms to the specification.
 | 
					# whether `a` conforms to the specification.
 | 
				
			||||||
with builtins; let
 | 
					with builtins; let
 | 
				
			||||||
  # Internal utilities:
 | 
					  # Internal utilities:
 | 
				
			||||||
  typeError = type: val:
 | 
					  typeError = type: val:
 | 
				
			||||||
  throw "Expected type '${type}', but value '${toPretty {} val}' is of type '${typeOf val}'";
 | 
					  throw "Expected type '${type}', but value '${toPretty val}' is of type '${typeOf val}'";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  typedef = name: check: {
 | 
					  typedef = name: check: {
 | 
				
			||||||
    inherit name check;
 | 
					    inherit name check;
 | 
				
			||||||
| 
						 | 
					@ -80,9 +79,18 @@ in (typeSet [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Polymorphic types
 | 
					  # Polymorphic types
 | 
				
			||||||
  (poly "option" (t: v: (isNull v) || t.check v))
 | 
					  (poly "option" (t: v: (isNull v) || t.check v))
 | 
				
			||||||
  (poly "list" (t: v: isList v && (foldl' (s: e: s && (t.check e)) true v)))
 | 
					
 | 
				
			||||||
 | 
					  (poly "list" (t: v: isList v && (foldl' (s: e: s && (
 | 
				
			||||||
 | 
					    if t.check e then true
 | 
				
			||||||
 | 
					    else throw "Expected list element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
 | 
				
			||||||
 | 
					  )) true v)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (poly "attrs" (t: v:
 | 
					  (poly "attrs" (t: v:
 | 
				
			||||||
    isAttrs v && (foldl' (s: e: s && (t.check e)) true (attrValues v))
 | 
					    isAttrs v && (foldl' (s: e: s && (
 | 
				
			||||||
 | 
					      if t.check e then true
 | 
				
			||||||
 | 
					      else throw "Expected attribute set element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
 | 
				
			||||||
 | 
					    )) true (attrValues v))
 | 
				
			||||||
  ))
 | 
					  ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (poly2 "either" (t1: t2: v: t1.check v || t2.check v))
 | 
					  (poly2 "either" (t1: t2: v: t1.check v || t2.check v))
 | 
				
			||||||
]) // { inherit struct; }
 | 
					]) // { inherit struct; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue