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 |   <listitem><para>TODO: new built-ins | ||||||
|   <function>builtins.attrNames</function>, |   <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> | </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) | static Expr primLessThan(EvalState & state, const ATermVector & args) | ||||||
| { | { | ||||||
|     int i1 = evalInt(state, args[0]); |     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() | void EvalState::addPrimOps() | ||||||
| { | { | ||||||
|     addPrimOp("builtins", 0, primBuiltins); |     addPrimOp("builtins", 0, primBuiltins); | ||||||
|  | @ -813,10 +851,14 @@ void EvalState::addPrimOps() | ||||||
|     addPrimOp("removeAttrs", 2, primRemoveAttrs); |     addPrimOp("removeAttrs", 2, primRemoveAttrs); | ||||||
|     addPrimOp("relativise", 2, primRelativise); |     addPrimOp("relativise", 2, primRelativise); | ||||||
|     addPrimOp("__add", 2, primAdd); |     addPrimOp("__add", 2, primAdd); | ||||||
|  |     addPrimOp("__sub", 2, primSub); | ||||||
|     addPrimOp("__lessThan", 2, primLessThan); |     addPrimOp("__lessThan", 2, primLessThan); | ||||||
|     addPrimOp("__toFile", 2, primToFile); |     addPrimOp("__toFile", 2, primToFile); | ||||||
|     addPrimOp("__filterSource", 2, primFilterSource); |     addPrimOp("__filterSource", 2, primFilterSource); | ||||||
|  | 
 | ||||||
|  |     addPrimOp("__substring", 3, prim_substring); | ||||||
|  |     addPrimOp("__stringLength", 1, prim_stringLength); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|   | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,9 @@ derivation { | ||||||
|   builder = "@shell@"; |   builder = "@shell@"; | ||||||
|   args = ["-e" "-x" (builtins.toFile "builder" "PATH=@testPath@; ln -s $input $out")]; |   args = ["-e" "-x" (builtins.toFile "builder" "PATH=@testPath@; ln -s $input $out")]; | ||||||
|   input = |   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; |     in builtins.filterSource filter ./test-tmp/filterin; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,9 @@ mkdir $TEST_ROOT/filterin | ||||||
| mkdir $TEST_ROOT/filterin/foo | mkdir $TEST_ROOT/filterin/foo | ||||||
| touch $TEST_ROOT/filterin/foo/bar | touch $TEST_ROOT/filterin/foo/bar | ||||||
| touch $TEST_ROOT/filterin/xyzzy | 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 | ln -s xyzzy $TEST_ROOT/filterin/link | ||||||
| 
 | 
 | ||||||
| $NIX_BIN_DIR/nix-build ./filter-source.nix -o $TEST_ROOT/filterout | $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 | set -x | ||||||
| test ! -e $TEST_ROOT/filterout/foo/bar | test ! -e $TEST_ROOT/filterout/foo/bar | ||||||
| test -e $TEST_ROOT/filterout/xyzzy | 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 | 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 { | rec { | ||||||
| 
 | 
 | ||||||
|   fold = op: nul: list: |   fold = op: nul: list: | ||||||
|     if list == [] |     if list == [] | ||||||
|     then nul |     then nul | ||||||
|     else op (builtins.head list) (fold op nul (builtins.tail list)); |     else op (head list) (fold op nul (tail list)); | ||||||
| 
 | 
 | ||||||
|   concat = |   concat = | ||||||
|     fold (x: y: x + y) ""; |     fold (x: y: x + y) ""; | ||||||
| 
 | 
 | ||||||
|   flatten = x: |   flatten = x: | ||||||
|     if builtins.isList x |     if isList x | ||||||
|     then fold (x: y: (flatten x) ++ y) [] x |     then fold (x: y: (flatten x) ++ y) [] x | ||||||
|     else [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