FAUST compiler  0.9.9.6b8
environment.cpp
Go to the documentation of this file.
00001 #include "environment.hh"
00002 #include "errormsg.hh"
00003 #include "boxes.hh"
00004 #include "ppbox.hh"
00005 #include "names.hh"
00006 
00007 
00008 //-----------------------new environment management----------------------------
00009 //
00010 // The environement is made of layers. Each layer contains a set of definitions
00011 // stored as properties of the layer. Each definition can refers to other
00012 // definitions of the same layer or of subsequent layers. Recursive
00013 // definitions are not allowed. Multiple defintions of the same symbol
00014 // in a layer is allowed but generate a warning when the definition is
00015 // different
00016 //-----------------------------------------------------------------------------
00017 
00018 
00019 
00026 static Tree pushNewLayer(Tree lenv)
00027 {
00028     return tree(unique("ENV_LAYER"), lenv);
00029 }
00030 
00031 
00032 
00041 Sym BARRIER = symbol ("BARRIER");
00042 
00043 Tree pushEnvBarrier(Tree lenv)
00044 {
00045     return tree(BARRIER, lenv);
00046 }
00047 
00048 
00056 bool isEnvBarrier(Tree lenv)
00057 {
00058     return isNil(lenv) || (lenv->node() == Node(BARRIER));
00059 }
00060 
00061 
00069 static void addLayerDef(Tree id, Tree def, Tree lenv)
00070 {
00071     // check for multiple definitions of a symbol in the same layer
00072     Tree olddef;
00073     if (getProperty(lenv, id, olddef)) {
00074         if (def == olddef) {
00075             evalwarning(getDefFileProp(id), getDefLineProp(id), "equivalent re-definitions of", id);
00076         } else {
00077             fprintf(stderr, "%s:%d: ERROR: redefinition of symbols are not allowed : ", getDefFileProp(id), getDefLineProp(id));
00078             print(id,stderr);
00079             fprintf(stderr, " is already defined in file \"%s\" line %d \n", getDefFileProp(id), getDefLineProp(id));
00080             gErrorCount++;
00081         }
00082     }
00083     setProperty(lenv, id, def);
00084 }
00085 
00086 
00094 Tree pushValueDef(Tree id, Tree def, Tree lenv)
00095 {
00096     Tree lenv2 = pushNewLayer(lenv);
00097     addLayerDef(id, def, lenv2);
00098     return lenv2;
00099 }
00100 
00101 
00109 Tree pushMultiClosureDefs(Tree ldefs, Tree visited, Tree lenv)
00110 {
00111     Tree lenv2 = pushNewLayer(lenv);
00112     while (!isNil(ldefs)) {
00113         Tree def = hd(ldefs);
00114         Tree id = hd(def);
00115         Tree rhs= tl(def);
00116         Tree cl = closure(tl(def),nil,visited,lenv2);
00117         stringstream s; s << boxpp(id);
00118         if (!isBoxCase(rhs)) setDefNameProperty(cl,s.str());
00119         addLayerDef( id, cl, lenv2 );
00120         ldefs = tl(ldefs);
00121     }
00122     return lenv2;
00123 }
00124 
00125 
00135 bool searchIdDef(Tree id, Tree& def, Tree lenv)
00136 {
00137     // search the environment until a definition is found
00138     // or a barrier (or nil) is reached
00139 
00140     while (!isEnvBarrier(lenv) && !getProperty(lenv, id, def)) {
00141         lenv = lenv->branch(0);
00142     }
00143     return !isEnvBarrier(lenv);
00144 }
00145 
00149 static void updateClosures(vector<Tree>& clos, Tree oldEnv, Tree newEnv)
00150 {
00151     for (unsigned int i=0; i < clos.size(); i++) {
00152         Tree exp, genv, visited, lenv;
00153         if (isClosure(clos[i], exp, genv, visited, lenv)) {
00154             if (lenv == oldEnv) {
00155                 clos[i] = closure(exp, genv, visited, newEnv);
00156             }
00157         }
00158     }
00159 }
00160 
00169 Tree copyEnvReplaceDefs(Tree anEnv, Tree ldefs, Tree visited, Tree curEnv)
00170 {
00171     vector<Tree>    ids, clos;
00172     Tree            copyEnv;
00173 
00174     anEnv->exportProperties(ids, clos);             // get the definitions of the environment
00175     copyEnv = pushNewLayer(anEnv->branch(0));       // create new environment with same stack
00176     updateClosures(clos, anEnv, copyEnv);           // update the closures replacing oldEnv with newEnv
00177 
00178     for (unsigned int i=0; i < clos.size(); i++) {           // transfers the updated definitions to the new environment
00179         setProperty(copyEnv, ids[i], clos[i]);
00180     }
00181 
00182     while (!isNil(ldefs)) {                         // replace the old definitions with the new ones
00183         Tree def = hd(ldefs);
00184         Tree id = hd(def);
00185         Tree rhs= tl(def);
00186         Tree cl = closure(rhs,nil,visited,curEnv);
00187         stringstream s; s << boxpp(id);
00188         if (!isBoxCase(rhs)) setDefNameProperty(cl,s.str());
00189         setProperty(copyEnv, id, cl);
00190         ldefs = tl(ldefs);
00191     }
00192     return copyEnv;
00193 }
00194 
00195