|
FAUST compiler
0.9.9.6b8
|
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 */
1.8.0