* 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 { | typedef enum { | ||||||
|     tInt = 1, |     tInt = 1, | ||||||
|     tAttrs, |     tAttrs, | ||||||
|  |     tList, | ||||||
|     tThunk, |     tThunk, | ||||||
|     tLambda, |     tLambda, | ||||||
|     tCopy, |     tCopy, | ||||||
|  | @ -41,6 +42,10 @@ struct Value | ||||||
|     { |     { | ||||||
|         int integer; |         int integer; | ||||||
|         Bindings * attrs; |         Bindings * attrs; | ||||||
|  |         struct { | ||||||
|  |             unsigned int length; | ||||||
|  |             Value * elems; | ||||||
|  |         } list; | ||||||
|         struct { |         struct { | ||||||
|             Env * env; |             Env * env; | ||||||
|             Expr expr; |             Expr expr; | ||||||
|  | @ -64,9 +69,15 @@ std::ostream & operator << (std::ostream & str, Value & v) | ||||||
|     case tAttrs: |     case tAttrs: | ||||||
|         str << "{ "; |         str << "{ "; | ||||||
|         foreach (Bindings::iterator, i, *v.attrs) |         foreach (Bindings::iterator, i, *v.attrs) | ||||||
|             str << i->first << " = " << i->second << "; "; |             str << aterm2String(i->first) << " = " << i->second << "; "; | ||||||
|         str << "}"; |         str << "}"; | ||||||
|         break; |         break; | ||||||
|  |     case tList: | ||||||
|  |         str << "[ "; | ||||||
|  |         for (unsigned int n = 0; n < v.list.length; ++n) | ||||||
|  |             str << v.list.elems[n] << " "; | ||||||
|  |         str << "]"; | ||||||
|  |         break; | ||||||
|     case tThunk: |     case tThunk: | ||||||
|         str << "<CODE>"; |         str << "<CODE>"; | ||||||
|         break; |         break; | ||||||
|  | @ -141,9 +152,7 @@ static Value * lookupVar(Env * env, Sym name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| unsigned long nrValues = 0; | unsigned long nrValues = 0, nrEnvs = 0; | ||||||
| 
 |  | ||||||
| unsigned long nrEnvs = 0; |  | ||||||
| 
 | 
 | ||||||
| static Env * allocEnv() | static Env * allocEnv() | ||||||
| { | { | ||||||
|  | @ -207,7 +216,7 @@ static void eval(Env * env, Expr e, Value & v) | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Expr e2; |     Expr e1, e2; | ||||||
|     if (matchSelect(e, e2, name)) { |     if (matchSelect(e, e2, name)) { | ||||||
|         eval(env, e2, v); |         eval(env, e2, v); | ||||||
|         if (v.type != tAttrs) throw TypeError("expected attribute set"); |         if (v.type != tAttrs) throw TypeError("expected attribute set"); | ||||||
|  | @ -310,7 +319,52 @@ static void eval(Env * env, Expr e, Value & v) | ||||||
|         return; |         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, "/"); |     Expr e = parseExprFromString(state, s, "/"); | ||||||
|     printMsg(lvlError, format(">>>>> %1%") % e); |     printMsg(lvlError, format(">>>>> %1%") % e); | ||||||
|     Value v; |     Value v; | ||||||
|     eval(0, e, v); |     strictEval(0, e, v); | ||||||
|     printMsg(lvlError, format("result: %1%") % v); |     printMsg(lvlError, format("result: %1%") % v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -348,6 +402,8 @@ void run(Strings args) | ||||||
|     doTest("with { x = 1; }; x"); |     doTest("with { x = 1; }; x"); | ||||||
|     doTest("let x = 2; in with { x = 1; }; x"); // => 2
 |     doTest("let x = 2; in with { x = 1; }; x"); // => 2
 | ||||||
|     doTest("with { x = 1; }; with { x = 2; }; x"); // => 1
 |     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% values") % nrValues); | ||||||
|     printMsg(lvlError, format("alloced %1% environments") % nrEnvs); |     printMsg(lvlError, format("alloced %1% environments") % nrEnvs); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue