FAUST compiler  0.9.9.6b8
uitree.cpp
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021  
00022  
00023  
00024 #include "uitree.hh"
00025 
00026 
00027 
00028 static Tree makeSubFolderChain(Tree path, Tree elem);
00029 static Tree putFolder(Tree folder, Tree item);
00030 static Tree getFolder (Tree folder, Tree ilabel);
00031 
00032 
00033 static void error(const char * s, Tree t)
00034 {
00035     fprintf(stderr, "ERROR : %s (%p)\n", s, t);
00036 }
00037 
00038 #define ERROR(s,t) error(s,t); exit(1)
00039 
00040 
00041 //------------------------------------------------------------------------------
00042 // Property list
00043 //------------------------------------------------------------------------------
00044 
00045 #if 0
00046 // version normale, qui marche, mais qui ne range pas en ordre alphabetique
00047 static bool findKey (Tree pl, Tree key, Tree& val)
00048 {
00049     if (isNil(pl))              return false;
00050     if (left(hd(pl)) == key)    { val= right(hd(pl)); return true; }
00051     /*  left(hd(pl)) != key */  return findKey (tl(pl), key, val); 
00052 }
00053 
00054 static Tree updateKey (Tree pl, Tree key, Tree val)
00055 {
00056     if (isNil(pl))              return cons ( cons(key,val), nil );
00057     if (left(hd(pl)) == key)    return cons ( cons(key,val), tl(pl) );
00058     /*  left(hd(pl)) != key */  return cons ( hd(pl), updateKey( tl(pl), key, val ));
00059 }
00060 
00061 static Tree removeKey (Tree pl, Tree key)
00062 {
00063     if (isNil(pl))              return nil;
00064     if (left(hd(pl)) == key)    return tl(pl);
00065     /*  left(hd(pl)) != key */  return cons (hd(pl), removeKey(tl(pl), key));
00066 }
00067 
00068 #else
00069 
00070 // verion experimentale qui range en ordre alphabetique
00071 
00072 static bool isBefore(Tree k1, Tree k2) 
00073 { 
00074     // before comparing replace (type . label) by label
00075     if (isList(k1)) { k1 = tl(k1); }
00076     if (isList(k2)) { k2 = tl(k2); }
00077     
00078     //fprintf(stderr, "isBefore("); print(k1, stderr); fprintf(stderr,", "); print(k2, stderr); fprintf(stderr,")\n"); 
00079     Sym s1, s2;
00080     if (!isSym(k1->node(), &s1)) {
00081         ERROR("the node of the tree is not a symbol", k1);
00082     }
00083     if (!isSym(k2->node(), &s2)) {
00084         ERROR("the node of the tree is not a symbol", k2);
00085     }
00086     
00087     //fprintf (stderr, "strcmp(\"%s\", \"%s\") = %d\n", name(s1), name(s2), strcmp(name(s1), name(s2)));
00088     return strcmp(name(s1), name(s2)) < 0;
00089 }
00090 
00091 
00092 static bool findKey (Tree pl, Tree key, Tree& val)
00093 {
00094     if (isNil(pl))                  return false;
00095     if (left(hd(pl)) == key)        { val = right(hd(pl)); return true; }
00096     if (isBefore(left(hd(pl)),key)) return findKey (tl(pl), key, val); 
00097     return false;
00098 }
00099 
00100 static Tree updateKey (Tree pl, Tree key, Tree val)
00101 {
00102     if (isNil(pl))                  return cons ( cons(key,val), nil );
00103     if (left(hd(pl)) == key)        return cons ( cons(key,val), tl(pl) );
00104     if (isBefore(left(hd(pl)),key)) return cons ( hd(pl), updateKey( tl(pl), key, val ));
00105     return cons(cons(key,val), pl);
00106 }
00107 
00111 static Tree addKey (Tree pl, Tree key, Tree val)
00112 {
00113     if (isNil(pl))                  return cons ( cons(key,val), nil );
00114     if (isBefore(key, left(hd(pl)))) return cons(cons(key,val), pl);
00115     return cons ( hd(pl), addKey( tl(pl), key, val ));
00116 }
00117 
00118 
00119 #if 0
00120 static Tree removeKey (Tree pl, Tree key)
00121 {
00122     if (isNil(pl))                  return nil;
00123     if (left(hd(pl)) == key)        return tl(pl);
00124     if (isBefore(left(hd(pl)),key)) return cons (hd(pl), removeKey(tl(pl), key));
00125     return pl;
00126 }
00127 #endif
00128 #endif
00129 
00130 //------------------------------------------------------------------------------
00131 // gestion de la construction de l'arbre d'interface utilisateur
00132 //------------------------------------------------------------------------------
00133 
00134 Sym     UIFOLDER = symbol ("uiFolder");
00135 Tree    uiFolder(Tree label, Tree elements)             { return tree(UIFOLDER, label, elements);       }
00136 bool    isUiFolder(Tree t)                              { return isTree(t, UIFOLDER);                   }
00137 bool    isUiFolder(Tree t, Tree& label, Tree& elements) { return isTree(t, UIFOLDER, label, elements);  }
00138 
00139 Sym     UIWIDGET = symbol ("uiWidget");
00140 Tree    uiWidget(Tree label, Tree varname, Tree sig)                    { return tree(UIWIDGET, label, varname, sig); }
00141 bool    isUiWidget(Tree t, Tree& label, Tree& varname, Tree& sig)       { return isTree(t, UIWIDGET, label, varname, sig); }
00142 
00143 
00144 
00145 // place un item dans un folder. Remplace eventuellement l'élément de même nom.
00146 Tree putFolder(Tree folder, Tree item)
00147 {
00148     Tree    label, content;
00149     
00150     if ( ! isUiFolder(folder, label, content)) { fprintf(stderr, "ERROR in addFolder : not a folder\n"); }
00151     return uiFolder(label, updateKey(content, uiLabel(item), item));
00152 }
00153 
00154 // place un item dans un folder. Sans Remplacement
00155 Tree addToFolder(Tree folder, Tree item)
00156 {
00157     Tree    label, content;
00158     
00159     if ( ! isUiFolder(folder, label, content)) { fprintf(stderr, "ERROR in addFolder : not a folder\n"); }
00160     return uiFolder(label, addKey(content, uiLabel(item), item));
00161 }
00162 
00163 // get an item from a folder (or return NIL)
00164 Tree getFolder (Tree folder, Tree ilabel)
00165 {
00166     Tree    flabel, content, item;
00167     if (!isUiFolder(folder, flabel, content))   { fprintf(stderr, "ERROR in getFolder : not a folder\n"); }
00168     if (findKey(content, ilabel, item)) {
00169         return item;
00170     } else {
00171         return nil;
00172     }
00173 }
00174     
00175 // crée une chaine de dossiers correspondant à path et contenant in fine elem
00176 Tree makeSubFolderChain(Tree path, Tree elem)
00177 {
00178     if (isNil(path)) {
00179         return elem;
00180     } else {
00181         return putFolder(uiFolder(hd(path)), makeSubFolderChain(tl(path),elem));
00182     }
00183 } 
00184 
00185     
00186 Tree putSubFolder(Tree folder, Tree path, Tree item) 
00187 {
00188     if (isNil(path)) {
00189         //return putFolder(folder, item);
00190         return addToFolder(folder, item);
00191     } else {
00192         Tree subfolder = getFolder(folder, hd(path));
00193         if (isUiFolder(subfolder)) {
00194             return putFolder(folder, putSubFolder(subfolder, tl(path), item));
00195         } else {
00196             return putFolder(folder, makeSubFolderChain(path, item));
00197         }
00198     }
00199 }
00200 
00201     
00202 /*
00203 Fonctionnement des dossiers. 
00204 Dossier à 1 niveau : Un dossier contient une liste de choses reperées par un nom  :
00205     Dossier[(l1,d1)...(ln,dn)] 
00206 ou (lx,dx) est une chose dx repérée par un nom lx. On suppose les lx tous différents
00207 
00208 On peut ajouter une chose à un dossier : Ajouter(Dossier, Chose) -> Dossier
00209 
00210 Si le dossier contient deja qq chose de meme nom, cette chose est remplacée par la nouvelle.
00211 
00212 AJOUTER (Dossier[(l1,d1)...(ln,dn)], (lx,dx)) -> Dossier[(l1,d1)...(lx,dx)...(ln,dn)]
00213 
00214 AJOUTER (Dossier[(l1,d1)...(lx,dx)...(ln,dn)], (lx,dx')) -> Dossier[(l1,d1)...(lx,dx')...(ln,dn)]
00215 */