* More primops.
This commit is contained in:
		
							parent
							
								
									5b72d8a749
								
							
						
					
					
						commit
						c3aa615a5f
					
				
					 4 changed files with 56 additions and 97 deletions
				
			
		|  | @ -56,10 +56,12 @@ void run(Strings args) | |||
|     doTest("{ x = [ 1 2 ]; } == { x = [ 1 ] ++ [ 2 ]; }"); | ||||
|     doTest("1 != 1"); | ||||
|     doTest("true"); | ||||
|     doTest("builtins.true"); | ||||
|     doTest("true == false"); | ||||
|     doTest("__head [ 1 2 3 ]"); | ||||
|     doTest("__add 1 2"); | ||||
|     doTest("null"); | ||||
|     doTest("null"); | ||||
|     doTest("\"foo\""); | ||||
|     doTest("let s = \"bar\"; in \"foo${s}\""); | ||||
|     doTest("if true then 1 else 2"); | ||||
|  | @ -67,9 +69,9 @@ void run(Strings args) | |||
|     doTest("if false || true then 1 else 2"); | ||||
|     doTest("let x = x; in if true || x then 1 else 2"); | ||||
|     doTest("/etc/passwd"); | ||||
|     doTest("import ./foo.nix"); | ||||
|     //doTest("import ./foo.nix");
 | ||||
|     doTest("map (x: __add 1 x) [ 1 2 3 ]"); | ||||
|     doTest("map (__add 1) [ 1 2 3 ]"); | ||||
|     doTest("map (builtins.add 1) [ 1 2 3 ]"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -95,14 +95,26 @@ EvalState::EvalState() : baseEnv(allocEnv()) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::addConstant(const string & name, Value & v) | ||||
| { | ||||
|     baseEnv.bindings[toATerm(name)] = v; | ||||
|     string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; | ||||
|     (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v; | ||||
|     nrValues += 2; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::addPrimOp(const string & name, | ||||
|     unsigned int arity, PrimOp primOp) | ||||
| { | ||||
|     Value & v = baseEnv.bindings[toATerm(name)]; | ||||
|     nrValues++; | ||||
|     Value v; | ||||
|     v.type = tPrimOp; | ||||
|     v.primOp.arity = arity; | ||||
|     v.primOp.fun = primOp; | ||||
|     baseEnv.bindings[toATerm(name)] = v; | ||||
|     string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; | ||||
|     (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v; | ||||
|     nrValues += 2; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -212,6 +224,14 @@ Env & EvalState::allocEnv() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::mkList(Value & v, unsigned int length) | ||||
| { | ||||
|     v.type = tList; | ||||
|     v.list.length = length; | ||||
|     v.list.elems = allocValues(length); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void EvalState::evalFile(const Path & path, Value & v) | ||||
| { | ||||
|     startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); | ||||
|  | @ -349,9 +369,7 @@ void EvalState::eval(Env & env, Expr e, Value & v) | |||
|     } | ||||
| 
 | ||||
|     if (matchList(e, es)) { | ||||
|         v.type = tList; | ||||
|         v.list.length = ATgetLength(es); | ||||
|         v.list.elems = allocValues(v.list.length); | ||||
|         mkList(v, ATgetLength(es)); | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es)) | ||||
|             mkThunk(v.list.elems[n], env, ATgetFirst(es)); | ||||
|         return; | ||||
|  | @ -376,9 +394,7 @@ void EvalState::eval(Env & env, Expr e, Value & v) | |||
|         forceList(v1); | ||||
|         Value v2; eval(env, e2, v2); | ||||
|         forceList(v2); | ||||
|         v.type = tList; | ||||
|         v.list.length = v1.list.length + v2.list.length; | ||||
|         v.list.elems = allocValues(v.list.length); | ||||
|         mkList(v, v1.list.length + v2.list.length); | ||||
|         /* !!! This loses sharing with the original lists.  We could
 | ||||
|            use a tCopy node, but that would use more memory. */ | ||||
|         for (unsigned int n = 0; n < v1.list.length; ++n) | ||||
|  |  | |||
|  | @ -196,6 +196,8 @@ private: | |||
| 
 | ||||
|     void createBaseEnv(); | ||||
|      | ||||
|     void addConstant(const string & name, Value & v); | ||||
| 
 | ||||
|     void addPrimOp(const string & name, | ||||
|         unsigned int arity, PrimOp primOp); | ||||
| 
 | ||||
|  | @ -210,6 +212,8 @@ public: | |||
|     /* Allocation primitives. */ | ||||
|     Value * allocValues(unsigned int count); | ||||
|     Env & allocEnv(); | ||||
| 
 | ||||
|     void mkList(Value & v, unsigned int length); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,63 +20,6 @@ | |||
| namespace nix { | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /*************************************************************
 | ||||
|  * Constants | ||||
|  *************************************************************/ | ||||
| 
 | ||||
| 
 | ||||
| static Expr prim_builtins(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     /* Return an attribute set containing all primops.  This allows
 | ||||
|        Nix expressions to test for new primops and take appropriate | ||||
|        action if they're not available.  For instance, rather than | ||||
|        calling a primop `foo' directly, they could say `if builtins ? | ||||
|        foo then builtins.foo ... else ...'. */ | ||||
| 
 | ||||
|     ATermMap builtins(state.primOps.size()); | ||||
| 
 | ||||
|     for (ATermMap::const_iterator i = state.primOps.begin(); | ||||
|          i != state.primOps.end(); ++i) | ||||
|     { | ||||
|         string name = aterm2String(i->key); | ||||
|         if (string(name, 0, 2) == "__") | ||||
|             name = string(name, 2); | ||||
|         /* !!! should use makePrimOp here, I guess. */ | ||||
|         builtins.set(toATerm(name), makeAttrRHS(makeVar(i->key), makeNoPos())); | ||||
|     } | ||||
| 
 | ||||
|     return makeAttrs(builtins); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Boolean constructors. */ | ||||
| static Expr prim_true(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     return eTrue; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Expr prim_false(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     return eFalse; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Return the null value. */ | ||||
| static Expr prim_null(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     return makeNull(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Expr prim_currentTime(EvalState & state, const ATermVector & args) | ||||
| { | ||||
|     return ATmake("Int(<int>)", time(0)); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************
 | ||||
|  * Miscellaneous | ||||
|  *************************************************************/ | ||||
|  | @ -903,17 +846,17 @@ static void prim_head(EvalState & state, Value * * args, Value & v) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /* Return a list consisting of everything but the the first element of
 | ||||
|    a list. */ | ||||
| static Expr prim_tail(EvalState & state, const ATermVector & args) | ||||
| static void prim_tail(EvalState & state, Value * * args, Value & v) | ||||
| { | ||||
|     ATermList list = evalList(state, args[0]); | ||||
|     if (ATisEmpty(list)) | ||||
|     state.forceList(*args[0]); | ||||
|     if (args[0]->list.length == 0) | ||||
|         throw Error("`tail' called on an empty list"); | ||||
|     return makeList(ATgetNext(list)); | ||||
|     state.mkList(v, args[0]->list.length - 1); | ||||
|     for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|         v.list.elems[n] = args[0]->list.elems[n + 1]; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Apply a function to every element of a list. */ | ||||
|  | @ -922,9 +865,7 @@ static void prim_map(EvalState & state, Value * * args, Value & v) | |||
|     state.forceFunction(*args[0]); | ||||
|     state.forceList(*args[1]); | ||||
| 
 | ||||
|     v.type = tList; | ||||
|     v.list.length = args[1]->list.length; | ||||
|     v.list.elems = state.allocValues(v.list.length); | ||||
|     state.mkList(v, args[1]->list.length); | ||||
| 
 | ||||
|     for (unsigned int n = 0; n < v.list.length; ++n) { | ||||
|         v.list.elems[n].type = tApp; | ||||
|  | @ -1123,26 +1064,24 @@ void EvalState::createBaseEnv() | |||
|     } | ||||
| 
 | ||||
|     /* Add global constants such as `true' to the base environment. */ | ||||
|     {   Value & v = baseEnv.bindings[toATerm("true")]; | ||||
|         mkBool(v, true); | ||||
|     } | ||||
|     {   Value & v = baseEnv.bindings[toATerm("false")]; | ||||
|         mkBool(v, false); | ||||
|     } | ||||
|     {   Value & v = baseEnv.bindings[toATerm("null")]; | ||||
|         v.type = tNull; | ||||
|     } | ||||
|     {   Value & v = (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm("currentSystem")]; | ||||
|         mkString(v, strdup(thisSystem.c_str())); | ||||
|     } | ||||
|     Value v; | ||||
| 
 | ||||
| #if 0    
 | ||||
|     // Constants
 | ||||
|     addPrimOp("__currentSystem", 0, prim_currentSystem); | ||||
|     addPrimOp("__currentTime", 0, prim_currentTime); | ||||
|     mkBool(v, true); | ||||
|     addConstant("true", v); | ||||
|      | ||||
|     mkBool(v, false); | ||||
|     addConstant("false", v); | ||||
|      | ||||
|     v.type = tNull; | ||||
|     addConstant("null", v); | ||||
| 
 | ||||
|     mkInt(v, time(0)); | ||||
|     addConstant("__currentTime", v); | ||||
| 
 | ||||
|     mkString(v, strdup(thisSystem.c_str())); | ||||
|     addConstant("__currentSystem", v); | ||||
| 
 | ||||
|     // Miscellaneous
 | ||||
| #endif | ||||
|     addPrimOp("import", 1, prim_import); | ||||
| #if 0 | ||||
|     addPrimOp("isNull", 1, prim_isNull); | ||||
|  | @ -1193,9 +1132,7 @@ void EvalState::createBaseEnv() | |||
|     addPrimOp("__isList", 1, prim_isList); | ||||
| #endif | ||||
|     addPrimOp("__head", 1, prim_head); | ||||
| #if 0 | ||||
|     addPrimOp("__tail", 1, prim_tail); | ||||
| #endif | ||||
|     addPrimOp("map", 2, prim_map); | ||||
| #if 0 | ||||
|     addPrimOp("__length", 1, prim_length); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue