* Implemented lists.
This commit is contained in:
		
							parent
							
								
									25eedf085d
								
							
						
					
					
						commit
						c2ba4313fb
					
				
					 1 changed files with 63 additions and 7 deletions
				
			
		|  | @ -27,6 +27,7 @@ struct Env | |||
| typedef enum { | ||||
|     tInt = 1, | ||||
|     tAttrs, | ||||
|     tList, | ||||
|     tThunk, | ||||
|     tLambda, | ||||
|     tCopy, | ||||
|  | @ -41,6 +42,10 @@ struct Value | |||
|     { | ||||
|         int integer; | ||||
|         Bindings * attrs; | ||||
|         struct { | ||||
|             unsigned int length; | ||||
|             Value * elems; | ||||
|         } list; | ||||
|         struct { | ||||
|             Env * env; | ||||
|             Expr expr; | ||||
|  | @ -64,9 +69,15 @@ std::ostream & operator << (std::ostream & str, Value & v) | |||
|     case tAttrs: | ||||
|         str << "{ "; | ||||
|         foreach (Bindings::iterator, i, *v.attrs) | ||||
|             str << i->first << " = " << i->second << "; "; | ||||
|             str << aterm2String(i->first) << " = " << i->second << "; "; | ||||
|         str << "}"; | ||||
|         break; | ||||
|     case tList: | ||||
|         str << "[ "; | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|             str << v.list.elems[n] << " "; | ||||
|         str << "]"; | ||||
|         break; | ||||
|     case tThunk: | ||||
|         str << "<CODE>"; | ||||
|         break; | ||||
|  | @ -141,9 +152,7 @@ static Value * lookupVar(Env * env, Sym name) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned long nrValues = 0; | ||||
| 
 | ||||
| unsigned long nrEnvs = 0; | ||||
| unsigned long nrValues = 0, nrEnvs = 0; | ||||
| 
 | ||||
| static Env * allocEnv() | ||||
| { | ||||
|  | @ -207,7 +216,7 @@ static void eval(Env * env, Expr e, Value & v) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     Expr e2; | ||||
|     Expr e1, e2; | ||||
|     if (matchSelect(e, e2, name)) { | ||||
|         eval(env, e2, v); | ||||
|         if (v.type != tAttrs) throw TypeError("expected attribute set"); | ||||
|  | @ -310,7 +319,52 @@ static void eval(Env * env, Expr e, Value & v) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     abort(); | ||||
|     if (matchList(e, es)) { | ||||
|         v.type = tList; | ||||
|         v.list.length = ATgetLength(es); | ||||
|         v.list.elems = new Value[v.list.length]; // !!! check destructor
 | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es)) { | ||||
|             v.list.elems[n].type = tThunk; | ||||
|             v.list.elems[n].thunk.env = env; | ||||
|             v.list.elems[n].thunk.expr = ATgetFirst(es); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (matchOpConcat(e, e1, e2)) { | ||||
|         Value v1; eval(env, e1, v1); | ||||
|         if (v1.type != tList) throw TypeError("list expecteed"); | ||||
|         Value v2; eval(env, e2, v2); | ||||
|         if (v2.type != tList) throw TypeError("list expecteed"); | ||||
|         v.type = tList; | ||||
|         v.list.length = v1.list.length + v2.list.length; | ||||
|         v.list.elems = new Value[v.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) | ||||
|             v.list.elems[n] = v1.list.elems[n]; | ||||
|         for (unsigned int n = 0; n < v2.list.length; ++n) | ||||
|             v.list.elems[n + v1.list.length] = v2.list.elems[n]; | ||||
|         return; | ||||
|     } | ||||
|          | ||||
|     throw Error("unsupported term"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void strictEval(Env * env, Expr e, Value & v) | ||||
| { | ||||
|     eval(env, e, v); | ||||
|      | ||||
|     if (v.type == tAttrs) { | ||||
|         foreach (Bindings::iterator, i, *v.attrs) | ||||
|             forceValue(i->second); | ||||
|     } | ||||
|      | ||||
|     else if (v.type == tList) { | ||||
|         for (unsigned int n = 0; n < v.list.length; ++n) | ||||
|             forceValue(v.list.elems[n]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -320,7 +374,7 @@ void doTest(string s) | |||
|     Expr e = parseExprFromString(state, s, "/"); | ||||
|     printMsg(lvlError, format(">>>>> %1%") % e); | ||||
|     Value v; | ||||
|     eval(0, e, v); | ||||
|     strictEval(0, e, v); | ||||
|     printMsg(lvlError, format("result: %1%") % v); | ||||
| } | ||||
| 
 | ||||
|  | @ -348,6 +402,8 @@ void run(Strings args) | |||
|     doTest("with { x = 1; }; x"); | ||||
|     doTest("let x = 2; in with { x = 1; }; x"); // => 2
 | ||||
|     doTest("with { x = 1; }; with { x = 2; }; x"); // => 1
 | ||||
|     doTest("[ 1 2 3 ]"); | ||||
|     doTest("[ 1 2 ] ++ [ 3 4 5 ]"); | ||||
|      | ||||
|     printMsg(lvlError, format("alloced %1% values") % nrValues); | ||||
|     printMsg(lvlError, format("alloced %1% environments") % nrEnvs); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue