Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
slib_list.cc
1 /*
2  * COPYRIGHT (c) 1988-1994 BY *
3  * PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS. *
4  * See the source file SLIB.C for more information. *
5 
6  * Reorganization of files (Mar 1999) by Alan W Black <awb@cstr.ed.ac.uk>
7 
8  * General list functions
9 
10 */
11 #include <cstdio>
12 #include "siod.h"
13 #include "siodp.h"
14 
15 static LISP llength(LISP obj)
16 {LISP l;
17  long n;
18  switch TYPE(obj)
19  {case tc_string:
20  return(flocons(obj->storage_as.string.dim));
21  case tc_double_array:
22  return(flocons(obj->storage_as.double_array.dim));
23  case tc_long_array:
24  return(flocons(obj->storage_as.long_array.dim));
25  case tc_lisp_array:
26  return(flocons(obj->storage_as.lisp_array.dim));
27  case tc_nil:
28  return(flocons(0.0));
29  case tc_cons:
30  for(l=obj,n=0;CONSP(l);l=CDR(l),++n) INTERRUPT_CHECK();
31  if NNULLP(l) err("improper list to length",obj);
32  return(flocons(n));
33  default:
34  return(err("wrong type of argument to length",obj));}}
35 
36 LISP assoc(LISP x,LISP alist)
37 {LISP l,tmp;
38  for(l=alist;CONSP(l);l=CDR(l))
39  {tmp = CAR(l);
40  if (CONSP(tmp) && equal(CAR(tmp),x)) return(tmp);
41  INTERRUPT_CHECK();}
42  if EQ(l,NIL) return(NIL);
43  return(err("improper list to assoc",alist));}
44 
45 LISP assq(LISP x,LISP alist)
46 {LISP l,tmp;
47  for(l=alist;CONSP(l);l=CDR(l))
48  {tmp = CAR(l);
49  if (CONSP(tmp) && EQ(CAR(tmp),x)) return(tmp);
50  INTERRUPT_CHECK();}
51  if EQ(l,NIL) return(NIL);
52  return(err("improper list to assq",alist));}
53 
54 LISP setcar(LISP cell, LISP value)
55 {if NCONSP(cell) err("wrong type of argument to setcar",cell);
56  return(CAR(cell) = value);}
57 
58 LISP setcdr(LISP cell, LISP value)
59 {if NCONSP(cell) err("wrong type of argument to setcdr",cell);
60  return(CDR(cell) = value);}
61 
62 LISP delq(LISP elem,LISP l)
63 {if NULLP(l) return(l);
64  STACK_CHECK(&elem);
65  if EQ(elem,car(l)) return(cdr(l));
66  setcdr(l,delq(elem,cdr(l)));
67  return(l);}
68 
69 LISP copy_list(LISP x)
70 {if NULLP(x) return(NIL);
71  STACK_CHECK(&x);
72  return(cons(car(x),copy_list(cdr(x))));}
73 
74 static LISP eq(LISP x,LISP y)
75 {if EQ(x,y) return(truth); else return(NIL);}
76 
77 LISP eql(LISP x,LISP y)
78 {if EQ(x,y) return(truth); else
79  if NFLONUMP(x) return(NIL); else
80  if NFLONUMP(y) return(NIL); else
81  if (FLONM(x) == FLONM(y)) return(truth);
82  return(NIL);}
83 
84 static LISP nullp(LISP x)
85 {if EQ(x,NIL) return(truth); else return(NIL);}
86 
87 LISP siod_flatten(LISP tree)
88 {
89  if (tree == NIL)
90  return NIL;
91  else if (consp(tree))
92  return append(siod_flatten(car(tree)),siod_flatten(cdr(tree)));
93  else
94  return cons(tree,NIL);
95 }
96 
97 LISP cons(LISP x,LISP y)
98 {LISP z;
99  NEWCELL(z,tc_cons);
100  CAR(z) = x;
101  CDR(z) = y;
102  return(z);}
103 
104 LISP atomp(LISP x)
105 {
106  if ((x==NIL) || CONSP(x))
107  return NIL;
108  else
109  return truth;
110 }
111 
112 LISP consp(LISP x)
113 {if CONSP(x) return(truth); else return(NIL);}
114 
115 LISP car(LISP x)
116 {switch TYPE(x)
117  {case tc_nil:
118  return(NIL);
119  case tc_cons:
120  return(CAR(x));
121  default:
122  return(err("wrong type of argument to car",x));}}
123 
124 LISP cdr(LISP x)
125 {switch TYPE(x)
126  {case tc_nil:
127  return(NIL);
128  case tc_cons:
129  return(CDR(x));
130  default:
131  return(err("wrong type of argument to cdr",x));}}
132 
133 LISP equal(LISP a,LISP b)
134 {struct user_type_hooks *p;
135  long atype;
136  STACK_CHECK(&a);
137  loop:
138  INTERRUPT_CHECK();
139  if EQ(a,b) return(truth);
140  atype = TYPE(a);
141  if (atype != TYPE(b)) return(NIL);
142  switch(atype)
143  {case tc_cons:
144  if NULLP(equal(car(a),car(b))) return(NIL);
145  a = cdr(a);
146  b = cdr(b);
147  goto loop;
148  case tc_flonum:
149  return((FLONM(a) == FLONM(b)) ? truth : NIL);
150  case tc_symbol:
151  case tc_closure:
152  case tc_subr_0:
153  case tc_subr_1:
154  case tc_subr_2:
155  case tc_subr_3:
156  case tc_subr_4:
157  case tc_lsubr:
158  case tc_fsubr:
159  case tc_msubr:
160  return(NIL);
161  default:
162  p = get_user_type_hooks(atype);
163  if (p->equal)
164  return((*p->equal)(a,b));
165  else if (p) /* a user type */
166  return ((USERVAL(a) == USERVAL(b)) ? truth : NIL);
167  else
168  return(NIL);}}
169 
170 LISP reverse(LISP l)
171 {LISP n,p;
172  n = NIL;
173  for(p=l;NNULLP(p);p=cdr(p)) n = cons(car(p),n);
174  return(n);}
175 
176 LISP append(LISP l1, LISP l2)
177 {LISP n=l2,p,rl1 = reverse(l1);
178  for(p=rl1;NNULLP(p);p=cdr(p))
179  n = cons(car(p),n);
180  return(n);}
181 
182 void init_subrs_list(void)
183 {
184  init_subr_2("assoc",assoc,
185  "(assoc KEY A-LIST)\n\
186  Return pair with KEY in A-LIST or nil.");
187  init_subr_1("length",llength,
188  "(length LIST)\n\
189  Return length of LIST, or 0 if LIST is not a list.");
190  init_subr_1("flatten",siod_flatten,
191  "(flatten LIST)\n\
192  Return flatend list (list of all atoms in LIST).");
193  init_subr_2("assq",assq,
194  "(assq ITEM ALIST)\n\
195  Returns pairs from ALIST whose car is ITEM or nil if ITEM is not in ALIST.");
196  init_subr_2("delq",delq,
197  "(delq ITEM LIST)\n\
198  Destructively delete ITEM from LIST, returns LIST, if ITEM is not first\n\
199  in LIST, cdr of LIST otherwise. If ITEM is not in LIST, LIST is\n\
200  returned unchanged." );
201  init_subr_1("copy-list",copy_list,
202  "(copy-list LIST)\n\
203  Return new list with same members as LIST.");
204  init_subr_2("cons",cons,
205  "(cons DATA1 DATA2)\n\
206  Construct cons pair whose car is DATA1 and cdr is DATA2.");
207  init_subr_1("pair?",consp,
208  "(pair? DATA)\n\
209  Returns t if DATA is a cons cell, nil otherwise.");
210  init_subr_1("car",car,
211  "(car DATA1)\n\
212  Returns car of DATA1. If DATA1 is nil or a symbol, return nil.");
213  init_subr_1("cdr",cdr,
214  "(cdr DATA1)\n\
215  Returns cdr of DATA1. If DATA1 is nil or a symbol, return nil.");
216  init_subr_2("set-car!",setcar,
217  "(set-car! CONS1 DATA1)\n\
218  Set car of CONS1 to be DATA1. Returns CONS1. If CONS1 not of type\n\
219  consp an error is is given. This is a destructive operation.");
220  init_subr_2("set-cdr!",setcdr,
221  "(set-cdr! CONS1 DATA1)\n\
222  Set cdr of CONS1 to be DATA1. Returns CONS1. If CONS1 not of type\n\
223  consp an error is is given. This is a destructive operation.");
224  init_subr_2("eq?",eq,
225  "(eq? DATA1 DATA2)\n\
226  Returns t if DATA1 and DATA2 are the same object.");
227  init_subr_2("eqv?",eql,
228  "(eqv? DATA1 DATA2)\n\
229  Returns t if DATA1 and DATA2 are the same object or equal numbers.");
230  init_subr_2("equal?",equal,
231  "(equal? A B)\n\
232  t if s-expressions A and B are recursively equal, nil otherwise.");
233  init_subr_1("not",nullp,
234  "(not DATA)\n\
235  Returns t if DATA is nil, nil otherwise.");
236  init_subr_1("null?",nullp,
237  "(null? DATA)\n\
238  Returns t if DATA is nil, nil otherwise.");
239  init_subr_1("reverse",reverse,
240  "(reverse LIST)\n\
241  Returns destructively reversed LIST.");
242  init_subr_2("append",append,
243  "(append LIST1 LIST2)\n\
244  Returns LIST2 appended to LIST1, LIST1 is distroyed.");
245 }