+++ /dev/null
-/************************************************************************
- ************************************************************************
- FAUST compiler
- Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
- ---------------------------------------------------------------------
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ************************************************************************
- ************************************************************************/
-
-
-
-/*****************************************************************************
-******************************************************************************
- LIST
- Y. Orlarey, (c) Grame 2002
-------------------------------------------------------------------------------
-This file contains several extensions to the tree library :
- - lists : based on a operations like cons, hd , tl, ...
- - environments : list of associations (key value)
- - property list : used to annotate trees
-
-
- API:
- ----
-
- List :
- -----
-
- nil = predefined empty list
- cons (x,l) = create a nex list of head x and tail l
- hd(cons(x,l)) = x,
- tl (cons(x,l)) = l
- nth(l,i) = ith element of l (or nil)
- replace(l,i,e) = a copy of l where the ith element is e
- len(l) = number of elements of l
- isNil(nil) = true (false otherwise)
- isList(cons(x,l)) = true (false otherwise)
- list(a,b,..) = cons(a, list(b,...))
-
- lmap(f, cons(x,l)) = cons(f(x), lmap(f,l))
- reverse([a,b,..,z]) = [z,..,b,a]
- reverseall([a,b,..,z]) = [ra(z),..,ra(b),ra(a)] where ra is reverseall
-
- Set :
- -----
- (Sets are implemented as ordered lists of elements without duplication)
-
- isElement(e,s) = true if e is an element of set s, false otherwise
- addElement(e,s) = s U {e}
- remElement(e,s) = s - {e}
- singleton(e) = {e}
- list2set(l) = convert a list into a set
- setUnion(s1,s2) = s1 U s2
- setIntersection(s1,s2) = s1 intersection s2
- setDifference(s1,s2) = s1 - s2
-
- Environment :
- -------------
-
- An 'environment' is a stack of pairs (key x value) used to keep track of lexical bindings
-
- pushEnv (key, val, env) -> env' create a new environment
- searchEnv (key,&v,env) -> bool search for key in env and set v accordingly
-
- search(k1,&v, push(k2,x,env)) = true and v is set to x if k1==k2
- = search(k1,&v,env) if k1 != k2
- Property list :
- ---------------
-
- Every tree can be annotated with an 'attribut' field. This attribute field
- can be used to manage a property list (pl). A property list is a list of pairs
- key x value, with three basic operations :
-
- setProperty (t, key, val) -> t add the association (key x val) to the pl of t
- getProperty (t, key, &val) -> bool search the pp of t for the value associated to key
- remProperty (t, key) -> t remove any association (key x ?) from the pl of t
-
- Warning :
- ---------
- Since reference counters are used for garbage collecting, one must be careful not to
- create cycles in trees. The only possible source of cycles is by setting the attribut
- of a tree t to a tree t' that contains t as a subtree.
-
- History :
- ---------
- 2002-02-08 : First version
- 2002-02-20 : New description of the API, non recursive lmap and reverse
- 2002-03-29 : Added function remElement(e,set), corrected comment error
-
-******************************************************************************
-*****************************************************************************/
-
-#include <stdlib.h>
-#include "list.hh"
-#include "compatibility.hh"
-#include <map>
-#include <cstdlib>
-
-// predefined symbols CONS and NIL
-Sym CONS = symbol("cons");
-Sym NIL = symbol("nil");
-
-// predefined nil tree
-Tree nil = tree(NIL);
-
-
-//------------------------------------------------------------------------------
-// Printing of trees with special case for lists
-//------------------------------------------------------------------------------
-
-static bool printlist (Tree l, FILE* out)
-{
- if (isList(l)) {
-
- char sep = '(';
-
- do {
- fputc(sep, out); sep = ',';
- print(hd(l));
- l = tl(l);
- } while (isList(l));
-
- if (! isNil(l)) {
- fprintf(out, " . ");
- print(l, out);
- }
-
- fputc(')', out);
- return true;
-
- } else if (isNil(l)) {
-
- fprintf(out, "nil");
- return true;
-
- } else {
-
- return false;
- }
-}
-
-void print (Tree t, FILE* out)
-{
- int i; double f; Sym s; void* p;
-
- if (printlist(t, out)) return;
-
- Node n = t->node();
- if (isInt(n, &i)) fprintf (out, "%d", i);
- else if (isDouble(n, &f)) fprintf (out, "%f", f);
- else if (isSym(n, &s)) fprintf (out, "%s", name(s));
- else if (isPointer(n, &p)) fprintf (out, "#%p", p);
-
- int k = t->arity();
- if (k > 0) {
- char sep = '[';
- for (int i=0; i<k; i++) {
- fputc(sep, out); sep = ',';
- print(t->branch(i), out);
- }
- fputc(']', out);
- }
-}
-
-
-//------------------------------------------------------------------------------
-// Elements of list
-//------------------------------------------------------------------------------
-
-Tree nth (Tree l, int i)
-{
- while (isList(l)) {
- if (i == 0) return hd(l);
- l = tl(l);
- i--;
- }
- return nil;
-}
-
-Tree replace(Tree l, int i, Tree e)
-{
- return (i==0) ? cons(e,tl(l)) : cons( hd(l), replace(tl(l),i-1,e) );
-}
-
-
-int len (Tree l)
-{
- int n = 0;
- while (isList(l)) { l = tl(l); n++; }
- return n;
-}
-
-
-//------------------------------------------------------------------------------
-// Mapping and reversing
-//------------------------------------------------------------------------------
-
-Tree rconcat (Tree l, Tree q)
-{
- while (isList(l)) { q = cons(hd(l),q); l = tl(l); }
- return q;
-}
-
-Tree concat (Tree l, Tree q)
-{
- return rconcat(reverse(l), q);
-}
-
-Tree lrange (Tree l, int i, int j)
-{
- Tree r = nil;
- int c = j;
- while (c>i) r = cons( nth(l,--c), r);
- return r;
-}
-
-//------------------------------------------------------------------------------
-// Mapping and reversing
-//------------------------------------------------------------------------------
-
-static Tree rmap (tfun f, Tree l)
-{
- Tree r = nil;
- while (isList(l)) { r = cons(f(hd(l)),r); l = tl(l); }
- return r;
-}
-
-Tree reverse (Tree l)
-{
- Tree r = nil;
- while (isList(l)) { r = cons(hd(l),r); l = tl(l); }
- return r;
-}
-
-Tree lmap (tfun f, Tree l)
-{
- return reverse(rmap(f,l));
-}
-
-Tree reverseall (Tree l)
-{
- return isList(l) ? rmap(reverseall, l) : l;
-}
-
-
-//------------------------------------------------------------------------------
-// Sets : implemented as ordered list
-//------------------------------------------------------------------------------
-
-bool isElement (Tree e, Tree l)
-{
- while (isList(l)) {
- if (hd(l) == e) return true;
- if (hd(l) > e) return false;
- l = tl(l);
- }
- return false;
-}
-
-Tree addElement(Tree e, Tree l)
-{
- if (isList(l)) {
- if (e < hd(l)) {
- return cons(e,l);
- } else if (e == hd(l)) {
- return l;
- } else {
- return cons(hd(l), addElement(e,tl(l)));
- }
- } else {
- return cons(e,nil);
- }
-}
-
-Tree remElement(Tree e, Tree l)
-{
- if (isList(l)) {
- if (e < hd(l)) {
- return l;
- } else if (e == hd(l)) {
- return tl(l);
- } else {
- return cons(hd(l), remElement(e,tl(l)));
- }
- } else {
- return nil;
- }
-}
-
-Tree singleton (Tree e)
-{
- return list1(e);
-}
-
-Tree list2set (Tree l)
-{
- Tree s = nil;
- while (isList(l)) {
- s = addElement(hd(l),s);
- l = tl(l);
- }
- return s;
-}
-
-Tree setUnion (Tree A, Tree B)
-{
- if (isNil(A)) return B;
- if (isNil(B)) return A;
-
- if (hd(A) == hd(B)) return cons(hd(A), setUnion(tl(A),tl(B)));
- if (hd(A) < hd(B)) return cons(hd(A), setUnion(tl(A),B));
- /* hd(A) > hd(B) */ return cons(hd(B), setUnion(A,tl(B)));
-}
-
-Tree setIntersection (Tree A, Tree B)
-{
- if (isNil(A)) return A;
- if (isNil(B)) return B;
- if (hd(A) == hd(B)) return cons(hd(A), setIntersection(tl(A),tl(B)));
- if (hd(A) < hd(B)) return setIntersection(tl(A),B);
- /* (hd(A) > hd(B)*/ return setIntersection(A,tl(B));
-}
-
-Tree setDifference (Tree A, Tree B)
-{
- if (isNil(A)) return A;
- if (isNil(B)) return A;
- if (hd(A) == hd(B)) return setDifference(tl(A),tl(B));
- if (hd(A) < hd(B)) return cons(hd(A), setDifference(tl(A),B));
- /* (hd(A) > hd(B)*/ return setDifference(A,tl(B));
-}
-
-
-
-//------------------------------------------------------------------------------
-// Environments
-//------------------------------------------------------------------------------
-
-Tree pushEnv (Tree key, Tree val, Tree env)
-{
- return cons (cons(key,val), env);
-}
-
-bool searchEnv (Tree key, Tree& v, Tree env)
-{
- while (isList(env)) {
- if (hd(hd(env)) == key) {
- v = tl(hd(env));
- return true;
- }
- env = tl(env);
- }
- return false;
-}
-
-
-//------------------------------------------------------------------------------
-// Property list
-//------------------------------------------------------------------------------
-
-static bool findKey (Tree pl, Tree key, Tree& val)
-{
- if (isNil(pl)) return false;
- if (left(hd(pl)) == key) { val= right(hd(pl)); return true; }
- /* left(hd(pl)) != key */ return findKey (tl(pl), key, val);
-}
-
-static Tree updateKey (Tree pl, Tree key, Tree val)
-{
- if (isNil(pl)) return cons ( cons(key,val), nil );
- if (left(hd(pl)) == key) return cons ( cons(key,val), tl(pl) );
- /* left(hd(pl)) != key */ return cons ( hd(pl), updateKey( tl(pl), key, val ));
-}
-
-static Tree removeKey (Tree pl, Tree key)
-{
- if (isNil(pl)) return nil;
- if (left(hd(pl)) == key) return tl(pl);
- /* left(hd(pl)) != key */ return cons (hd(pl), removeKey(tl(pl), key));
-}
-
-
-#if 0
-void setProperty (Tree t, Tree key, Tree val)
-{
- CTree* pl = t->attribut();
- if (pl) t->attribut(updateKey(pl, key, val));
- else t->attribut(updateKey(nil, key, val));
-}
-
-void remProperty (Tree t, Tree key)
-{
- CTree* pl = t->attribut();
- if (pl) t->attribut(removeKey(pl, key));
-}
-
-bool getProperty (Tree t, Tree key, Tree& val)
-{
- CTree* pl = t->attribut();
- if (pl) return findKey(pl, key, val);
- else return false;
-}
-
-#else
-// nouvelle implementation
-void setProperty (Tree t, Tree key, Tree val)
-{
- t->setProperty(key, val);
-}
-
-bool getProperty (Tree t, Tree key, Tree& val)
-{
- CTree* pl = t->getProperty(key);
- if (pl) {
- val = pl;
- return true;
- } else {
- return false;
- }
-}
-
-void remProperty (Tree t, Tree key)
-{
- exit(1); // fonction not implemented
-}
-#endif
-
-
-//------------------------------------------------------------------------------
-// Bottom Up Tree Mapping
-//------------------------------------------------------------------------------
-
-Tree tmap (Tree key, tfun f, Tree t)
-{
- //printf("start tmap\n");
- Tree p;
-
- if (getProperty(t, key, p)) {
-
- return (isNil(p)) ? t : p; // truc pour eviter les boucles
-
- } else {
-
- Tree r1=nil;
- switch (t->arity()) {
-
- case 0 :
- r1 = t;
- break;
- case 1 :
- r1 = tree(t->node(), tmap(key,f,t->branch(0)));
- break;
- case 2 :
- r1 = tree(t->node(), tmap(key,f,t->branch(0)), tmap(key,f,t->branch(1)));
- break;
- case 3 :
- r1 = tree(t->node(), tmap(key,f,t->branch(0)), tmap(key,f,t->branch(1)),
- tmap(key,f,t->branch(2)));
- break;
- case 4 :
- r1 = tree(t->node(), tmap(key,f,t->branch(0)), tmap(key,f,t->branch(1)),
- tmap(key,f,t->branch(2)), tmap(key,f,t->branch(3)));
- break;
- }
- Tree r2 = f(r1);
- if (r2 == t) {
- setProperty(t, key, nil);
- } else {
- setProperty(t, key, r2);
- }
- return r2;
- }
-}
-
-
-
-
-
-//------------------------------------------------------------------------------
-// substitute :remplace toutes les occurences de 'id' par 'val' dans 't'
-//------------------------------------------------------------------------------
-
-// genere une clef unique propre � cette substitution
-static Tree substkey(Tree t, Tree id, Tree val)
-{
- char name[256];
- snprintf(name, 255, "SUBST<%p,%p,%p> : ", (CTree*)t, (CTree*)id, (CTree*)val);
- return tree(unique(name));
-}
-
-// realise la substitution proprement dite tout en mettant � jour la propriete
-// pour ne pas avoir � la calculer deux fois
-
-static Tree subst (Tree t, Tree propkey, Tree id, Tree val)
-{
- Tree p;
-
- if (t==id) {
- return val;
-
- } else if (t->arity() == 0) {
- return t;
- } else if (getProperty(t, propkey, p)) {
- return (isNil(p)) ? t : p;
- } else {
- Tree r=nil;
- switch (t->arity()) {
-
- case 1 :
- r = tree(t->node(),
- subst(t->branch(0), propkey, id, val));
- break;
-
- case 2 :
- r = tree(t->node(),
- subst(t->branch(0), propkey, id, val),
- subst(t->branch(1), propkey, id, val));
- break;
-
- case 3 :
- r = tree(t->node(),
- subst(t->branch(0), propkey, id, val),
- subst(t->branch(1), propkey, id, val),
- subst(t->branch(2), propkey, id, val));
- break;
-
- case 4 :
- r = tree(t->node(),
- subst(t->branch(0), propkey, id, val),
- subst(t->branch(1), propkey, id, val),
- subst(t->branch(2), propkey, id, val),
- subst(t->branch(3), propkey, id, val));
- break;
-
- }
- if (r == t) {
- setProperty(t, propkey, nil);
- } else {
- setProperty(t, propkey, r);
- }
- return r;
- }
-
-}
-
-// remplace toutes les occurences de 'id' par 'val' dans 't'
-Tree substitute (Tree t, Tree id, Tree val)
-{
- return subst (t, substkey(t,id,val), id, val);
-}
-
-
-
-
-
-
-//------------------------------------------------------------------------------
-// Fun : implementation of functions as set of pairs (key x value)
-// such that key are uniques : forall (k1,v1) and (k2,v2) in F, k1=k2 ==> v1=v2
-// Uses the order on key to speedup search
-//------------------------------------------------------------------------------
-
-/**
- * Add a pair key x value to "function" l
- */
-Tree addFun(Tree k, Tree v, Tree l)
-{
- if (isList(l)) {
- Tree r = hd(hd(l));
- if (k < r) {
- return cons(cons(k,v),l);
- } else if (k == r) {
- return cons(cons(k,v),tl(l));
- } else {
- return cons(hd(l), addFun(k,v,tl(l)));
- }
- } else {
- return cons(cons(k,v),nil);
- }
-}
-
-/**
- * Get value associated to key k in "function" l
- * returns true if a value was found.
- */
-
-bool getFun(Tree k, Tree& v, Tree l)
-{
- if (isNil(l)) {
- return false;
- } else {
- assert (isList(l));
- Tree r = hd(hd(l));
- if (k < r) {
- return false;
- } else if (k == r) {
- v = tl(hd(l));
- return true;
- } else {
- return getFun(k,v,tl(l));
- }
- }
-}
-
-