New primitives:
* `sub' to subtract two numbers. * `stringLength' to get the length of a string. * `substring' to get a substring of a string. These should be enough to allow most string operations to be expressed.
This commit is contained in:
		
							parent
							
								
									7dedbd896a
								
							
						
					
					
						commit
						7349bd0176
					
				
					 8 changed files with 88 additions and 6 deletions
				
			
		|  | @ -55,7 +55,10 @@ | |||
| 
 | ||||
|   <listitem><para>TODO: new built-ins | ||||
|   <function>builtins.attrNames</function>, | ||||
|   <function>builtins.filterSource</function>.</para></listitem> | ||||
|   <function>builtins.filterSource</function>, | ||||
|   <function>builtins.sub</function>, | ||||
|   <function>builtins.stringLength</function>, | ||||
|   <function>builtins.substring</function>.</para></listitem> | ||||
|    | ||||
| 
 | ||||
| </itemizedlist> | ||||
|  |  | |||
|  | @ -723,6 +723,14 @@ static Expr primAdd(EvalState & state, const ATermVector & args) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Expr primSub(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     int i1 = evalInt(state, args[0]); | ||||
|     int i2 = evalInt(state, args[1]); | ||||
|     return makeInt(i1 - i2); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Expr primLessThan(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     int i1 = evalInt(state, args[0]); | ||||
|  | @ -779,6 +787,36 @@ static Expr primFilterSource(EvalState & state, const ATermVector & args) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************
 | ||||
|  * String manipulation | ||||
|  *************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| /* `substr start len str' returns the substring of `str' starting at
 | ||||
|    character position `min(start, stringLength str)' inclusive and | ||||
|    ending at `min(start + len, stringLength str)'.  `start' must be | ||||
|    non-negative. */ | ||||
| static Expr prim_substring(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     int start = evalInt(state, args[0]); | ||||
|     int len = evalInt(state, args[1]); | ||||
|     PathSet context; | ||||
|     string s = coerceToString(state, args[2], context); | ||||
| 
 | ||||
|     if (start < 0) throw EvalError("negative start position in `substring'"); | ||||
| 
 | ||||
|     return makeStr(string(s, start, len), context); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Expr prim_stringLength(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     PathSet context; | ||||
|     string s = coerceToString(state, args[0], context); | ||||
|     return makeInt(s.size()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::addPrimOps() | ||||
| { | ||||
|     addPrimOp("builtins", 0, primBuiltins); | ||||
|  | @ -813,9 +851,13 @@ void EvalState::addPrimOps() | |||
|     addPrimOp("removeAttrs", 2, primRemoveAttrs); | ||||
|     addPrimOp("relativise", 2, primRelativise); | ||||
|     addPrimOp("__add", 2, primAdd); | ||||
|     addPrimOp("__sub", 2, primSub); | ||||
|     addPrimOp("__lessThan", 2, primLessThan); | ||||
|     addPrimOp("__toFile", 2, primToFile); | ||||
|     addPrimOp("__filterSource", 2, primFilterSource); | ||||
| 
 | ||||
|     addPrimOp("__substring", 3, prim_substring); | ||||
|     addPrimOp("__stringLength", 1, prim_stringLength); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,9 @@ derivation { | |||
|   builder = "@shell@"; | ||||
|   args = ["-e" "-x" (builtins.toFile "builder" "PATH=@testPath@; ln -s $input $out")]; | ||||
|   input = | ||||
|     let filter = path: type: type != "symlink" && baseNameOf (toString path) != "foo"; | ||||
|     let filter = path: type: | ||||
|       type != "symlink" | ||||
|       && baseNameOf path != "foo" | ||||
|       && !((import ./lang/lib.nix).hasSuffix ".bak" (baseNameOf path)); | ||||
|     in builtins.filterSource filter ./test-tmp/filterin; | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,9 @@ mkdir $TEST_ROOT/filterin | |||
| mkdir $TEST_ROOT/filterin/foo | ||||
| touch $TEST_ROOT/filterin/foo/bar | ||||
| touch $TEST_ROOT/filterin/xyzzy | ||||
| touch $TEST_ROOT/filterin/b | ||||
| touch $TEST_ROOT/filterin/bak | ||||
| touch $TEST_ROOT/filterin/bla.c.bak | ||||
| ln -s xyzzy $TEST_ROOT/filterin/link | ||||
| 
 | ||||
| $NIX_BIN_DIR/nix-build ./filter-source.nix -o $TEST_ROOT/filterout | ||||
|  | @ -12,4 +15,6 @@ $NIX_BIN_DIR/nix-build ./filter-source.nix -o $TEST_ROOT/filterout | |||
| set -x | ||||
| test ! -e $TEST_ROOT/filterout/foo/bar | ||||
| test -e $TEST_ROOT/filterout/xyzzy | ||||
| test -e $TEST_ROOT/filterout/bak | ||||
| test ! -e $TEST_ROOT/filterout/bla.c.bak | ||||
| test ! -L $TEST_ROOT/filterout/link | ||||
|  |  | |||
							
								
								
									
										1
									
								
								tests/lang/eval-fail-substring.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/lang/eval-fail-substring.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| builtins.substring (builtins.sub 0 1) 1 "x" | ||||
							
								
								
									
										1
									
								
								tests/lang/eval-okay-substring.exp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/lang/eval-okay-substring.exp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| Str("ooxfoobarybarzobaabb",[]) | ||||
							
								
								
									
										19
									
								
								tests/lang/eval-okay-substring.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/lang/eval-okay-substring.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| with builtins; | ||||
| 
 | ||||
| let | ||||
| 
 | ||||
|   s = "foobar"; | ||||
| 
 | ||||
| in | ||||
| 
 | ||||
| substring 1 2 s | ||||
| + "x" | ||||
| + substring 0 (stringLength s) s | ||||
| + "y" | ||||
| + substring 3 100 s | ||||
| + "z" | ||||
| + substring 2 (sub (stringLength s) 3) s | ||||
| + "a" | ||||
| + substring 3 0 s | ||||
| + "b" | ||||
| + substring 3 1 s | ||||
|  | @ -1,18 +1,26 @@ | |||
| with builtins; | ||||
| 
 | ||||
| rec { | ||||
| 
 | ||||
|   fold = op: nul: list: | ||||
|     if list == [] | ||||
|     then nul | ||||
|     else op (builtins.head list) (fold op nul (builtins.tail list)); | ||||
|     else op (head list) (fold op nul (tail list)); | ||||
| 
 | ||||
|   concat = | ||||
|     fold (x: y: x + y) ""; | ||||
| 
 | ||||
|   flatten = x: | ||||
|     if builtins.isList x | ||||
|     if isList x | ||||
|     then fold (x: y: (flatten x) ++ y) [] x | ||||
|     else [x]; | ||||
| 
 | ||||
|   sum = fold (x: y: builtins.add x y) 0; | ||||
|   sum = fold (x: y: add x y) 0; | ||||
| 
 | ||||
|   hasSuffix = ext: fileName: | ||||
|     let lenFileName = stringLength fileName; | ||||
|         lenExt = stringLength ext; | ||||
|     in !(lessThan lenFileName lenExt) && | ||||
|        substring (sub lenFileName lenExt) lenFileName fileName == ext; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue