* Use a linked list of substitutions. This reduces the amount of
copying.
This commit is contained in:
		
							parent
							
								
									c791e94aee
								
							
						
					
					
						commit
						68174bdc7d
					
				
					 4 changed files with 54 additions and 19 deletions
				
			
		|  | @ -71,7 +71,7 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg) | ||||||
|             throw Error(format("required function argument `%1%' missing") |             throw Error(format("required function argument `%1%' missing") | ||||||
|                 % aterm2String(*i)); |                 % aterm2String(*i)); | ||||||
|      |      | ||||||
|     return substitute(subs, body); |     return substitute(Substitution(0, &subs), body); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -97,11 +97,13 @@ ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds) | ||||||
|         subs.set(name, e2); |         subs.set(name, e2); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     Substitution subs_(0, &subs); | ||||||
|  | 
 | ||||||
|     /* Create the non-recursive set. */ |     /* Create the non-recursive set. */ | ||||||
|     ATermMap as; |     ATermMap as; | ||||||
|     for (ATermIterator i(rbnds); i; ++i) { |     for (ATermIterator i(rbnds); i; ++i) { | ||||||
|         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ |         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||||
|         as.set(name, makeAttrRHS(substitute(subs, e2), pos)); |         as.set(name, makeAttrRHS(substitute(subs_, e2), pos)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Copy the non-recursive bindings.  !!! inefficient */ |     /* Copy the non-recursive bindings.  !!! inefficient */ | ||||||
|  | @ -344,7 +346,7 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|             try { |             try { | ||||||
|                 ATermMap subs; |                 ATermMap subs; | ||||||
|                 subs.set(name, e2); |                 subs.set(name, e2); | ||||||
|                 return evalExpr(state, substitute(subs, e4)); |                 return evalExpr(state, substitute(Substitution(0, &subs), e4)); | ||||||
|             } catch (Error & e) { |             } catch (Error & e) { | ||||||
|                 e.addPrefix(format("while evaluating the function at %1%:\n") |                 e.addPrefix(format("while evaluating the function at %1%:\n") | ||||||
|                     % showPos(pos)); |                     % showPos(pos)); | ||||||
|  | @ -402,7 +404,7 @@ Expr evalExpr2(EvalState & state, Expr e) | ||||||
|             throw; |             throw; | ||||||
|         } |         } | ||||||
|         try { |         try { | ||||||
|             e2 = substitute(attrs, e2); |             e2 = substitute(Substitution(0, &attrs), e2); | ||||||
|             checkVarDefs(state.primOps, e2); |             checkVarDefs(state.primOps, e2); | ||||||
|             return evalExpr(state, e2); |             return evalExpr(state, e2); | ||||||
|         } catch (Error & e) { |         } catch (Error & e) { | ||||||
|  | @ -534,4 +536,5 @@ void printEvalStats(EvalState & state) | ||||||
|         % state.nrEvaluated % state.nrCached |         % state.nrEvaluated % state.nrCached | ||||||
|         % ((float) state.nrCached / (float) state.nrEvaluated * 100) |         % ((float) state.nrCached / (float) state.nrEvaluated * 100) | ||||||
|         % AT_calcAllocatedSize()); |         % AT_calcAllocatedSize()); | ||||||
|  |     sleep(100); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ Uri | string | Expr | | ||||||
| List | ATermList | Expr | | List | ATermList | Expr | | ||||||
| BlackHole | | Expr | | BlackHole | | Expr | | ||||||
| Undefined | | Expr | | Undefined | | Expr | | ||||||
|  | Removed | | Expr | | ||||||
| PrimOp | int ATermBlob ATermList | Expr | | PrimOp | int ATermBlob ATermList | Expr | | ||||||
| Attrs | ATermList | Expr | | Attrs | ATermList | Expr | | ||||||
| Closed | Expr | Expr | | Closed | Expr | Expr | | ||||||
|  |  | ||||||
|  | @ -222,7 +222,7 @@ Expr makeAttrs(const ATermMap & attrs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Expr substitute(const ATermMap & subs, Expr e) | Expr substitute(const Substitution & subs, Expr e) | ||||||
| { | { | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
| 
 | 
 | ||||||
|  | @ -235,7 +235,8 @@ Expr substitute(const ATermMap & subs, Expr e) | ||||||
|     if (matchClosed(e, e2)) return e; |     if (matchClosed(e, e2)) return e; | ||||||
| 
 | 
 | ||||||
|     if (matchVar(e, name)) { |     if (matchVar(e, name)) { | ||||||
|         Expr sub = subs.get(name); |         Expr sub = subs.lookup(name); | ||||||
|  |         if (sub == makeRemoved()) sub = 0; | ||||||
|         Expr wrapped; |         Expr wrapped; | ||||||
|         /* Add a "closed" wrapper around terms that aren't already
 |         /* Add a "closed" wrapper around terms that aren't already
 | ||||||
|            closed.  The check is necessary to prevent repeated |            closed.  The check is necessary to prevent repeated | ||||||
|  | @ -249,36 +250,37 @@ Expr substitute(const ATermMap & subs, Expr e) | ||||||
|     ATermList formals; |     ATermList formals; | ||||||
|     ATerm body, def; |     ATerm body, def; | ||||||
|     if (matchFunction(e, formals, body, pos)) { |     if (matchFunction(e, formals, body, pos)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap map; | ||||||
|         for (ATermIterator i(formals); i; ++i) { |         for (ATermIterator i(formals); i; ++i) { | ||||||
|             if (!matchNoDefFormal(*i, name) && |             if (!matchNoDefFormal(*i, name) && | ||||||
|                 !matchDefFormal(*i, name, def)) |                 !matchDefFormal(*i, name, def)) | ||||||
|                 abort(); |                 abort(); | ||||||
|             subs2.remove(name); |             map.set(name, makeRemoved()); | ||||||
|         } |         } | ||||||
|  |         Substitution subs2(&subs, &map); | ||||||
|         return makeFunction( |         return makeFunction( | ||||||
|             (ATermList) substitute(subs2, (ATerm) formals), |             (ATermList) substitute(subs2, (ATerm) formals), | ||||||
|             substitute(subs2, body), pos); |             substitute(subs2, body), pos); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (matchFunction1(e, name, body, pos)) { |     if (matchFunction1(e, name, body, pos)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap map; | ||||||
|         subs2.remove(name); |         map.set(name, makeRemoved()); | ||||||
|         return makeFunction1(name, substitute(subs2, body), pos); |         return makeFunction1(name, substitute(Substitution(&subs, &map), body), pos); | ||||||
|     } |     } | ||||||
|          |          | ||||||
|     /* Idem for a mutually recursive attribute set. */ |     /* Idem for a mutually recursive attribute set. */ | ||||||
|     ATermList rbnds, nrbnds; |     ATermList rbnds, nrbnds; | ||||||
|     if (matchRec(e, rbnds, nrbnds)) { |     if (matchRec(e, rbnds, nrbnds)) { | ||||||
|         ATermMap subs2(subs); |         ATermMap map; | ||||||
|         for (ATermIterator i(rbnds); i; ++i) |         for (ATermIterator i(rbnds); i; ++i) | ||||||
|             if (matchBind(*i, name, e2, pos)) subs2.remove(name); |             if (matchBind(*i, name, e2, pos)) map.set(name, makeRemoved()); | ||||||
|             else abort(); /* can't happen */ |             else abort(); /* can't happen */ | ||||||
|         for (ATermIterator i(nrbnds); i; ++i) |         for (ATermIterator i(nrbnds); i; ++i) | ||||||
|             if (matchBind(*i, name, e2, pos)) subs2.remove(name); |             if (matchBind(*i, name, e2, pos)) map.set(name, makeRemoved()); | ||||||
|             else abort(); /* can't happen */ |             else abort(); /* can't happen */ | ||||||
|         return makeRec( |         return makeRec( | ||||||
|             (ATermList) substitute(subs2, (ATerm) rbnds), |             (ATermList) substitute(Substitution(&subs, &map), (ATerm) rbnds), | ||||||
|             (ATermList) substitute(subs, (ATerm) nrbnds)); |             (ATermList) substitute(subs, (ATerm) nrbnds)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -286,11 +288,15 @@ Expr substitute(const ATermMap & subs, Expr e) | ||||||
|         AFun fun = ATgetAFun(e); |         AFun fun = ATgetAFun(e); | ||||||
|         int arity = ATgetArity(fun); |         int arity = ATgetArity(fun); | ||||||
|         ATerm args[arity]; |         ATerm args[arity]; | ||||||
|  |         bool changed = false; | ||||||
| 
 | 
 | ||||||
|         for (int i = 0; i < arity; ++i) |         for (int i = 0; i < arity; ++i) { | ||||||
|             args[i] = substitute(subs, ATgetArgument(e, i)); |             ATerm arg = ATgetArgument(e, i); | ||||||
|  |             args[i] = substitute(subs, arg); | ||||||
|  |             if (args[i] != arg) changed = true; | ||||||
|  |         } | ||||||
|          |          | ||||||
|         return (ATerm) ATmakeApplArray(fun, args); |         return changed ? (ATerm) ATmakeApplArray(fun, args) : e; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (ATgetType(e) == AT_LIST) { |     if (ATgetType(e) == AT_LIST) { | ||||||
|  |  | ||||||
|  | @ -60,6 +60,31 @@ private: | ||||||
| typedef vector<ATerm> ATermVector; | typedef vector<ATerm> ATermVector; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* A substitution is a linked list of ATermMaps that map names to
 | ||||||
|  |    identifiers.  We use a list of ATermMaps rather than a single to | ||||||
|  |    make it easy to grow or shrink a substitution when entering a | ||||||
|  |    scope. */ | ||||||
|  | struct Substitution | ||||||
|  | { | ||||||
|  |     ATermMap * map; | ||||||
|  |     const Substitution * prev; | ||||||
|  | 
 | ||||||
|  |     Substitution(const Substitution * prev, ATermMap * map) | ||||||
|  |     { | ||||||
|  |         this->prev = prev; | ||||||
|  |         this->map = map; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     Expr lookup(Expr name) const | ||||||
|  |     { | ||||||
|  |         Expr x; | ||||||
|  |         for (const Substitution * s(this); s; s = s->prev) | ||||||
|  |             if (x = s->map->get(name)) return x; | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Show a position. */ | /* Show a position. */ | ||||||
| string showPos(ATerm pos); | string showPos(ATerm pos); | ||||||
| 
 | 
 | ||||||
|  | @ -85,7 +110,7 @@ Expr queryAttr(Expr e, const string & name, ATerm & pos); | ||||||
| Expr makeAttrs(const ATermMap & attrs); | Expr makeAttrs(const ATermMap & attrs); | ||||||
| 
 | 
 | ||||||
| /* Perform a set of substitutions on an expression. */ | /* Perform a set of substitutions on an expression. */ | ||||||
| Expr substitute(const ATermMap & subs, Expr e); | Expr substitute(const Substitution & subs, Expr e); | ||||||
| 
 | 
 | ||||||
| /* Check whether all variables are defined in the given expression.
 | /* Check whether all variables are defined in the given expression.
 | ||||||
|    Throw an exception if this isn't the case. */ |    Throw an exception if this isn't the case. */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue