Revert "core: Add member."
[mes.git] / src / lib.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017,2018 Jan Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 int g_depth;
22 SCM fdisplay_ (SCM, int, int);
23
24 SCM
25 display_helper (SCM x, int cont, char* sep, int fd, int write_p)
26 {
27   fputs (sep, fd);
28   if (g_depth == 0)
29     return cell_unspecified;
30   g_depth = g_depth - 1;
31   
32   switch (TYPE (x))
33     {
34     case TCHAR:
35       {
36         if (!write_p)
37           fputc (VALUE (x), fd);
38         else
39           {
40             fputs ("#\\", fd);
41             switch (VALUE (x))
42               {
43               case '\0': fputs ("nul", fd); break;
44               case '\a': fputs ("alarm", fd); break;
45               case '\b': fputs ("backspace", fd); break;
46               case '\t': fputs ("tab", fd); break;
47               case '\n': fputs ("newline", fd); break;
48               case '\v': fputs ("vtab", fd); break;
49               case '\f': fputs ("page", fd); break;
50               case '\r': fputs ("return", fd); break;
51               case ' ': fputs ("space", fd); break;
52               default: fputc (VALUE (x), fd);
53               }
54           }
55         break;
56       }
57     case TCLOSURE:
58       {
59         fputs ("#<closure ", fd);
60         //display_helper (CDR (x), cont, "", fd, 0);
61         fputs (">", fd);
62         break;
63       }
64     case TFUNCTION:
65       {
66         fputs ("#<procedure ", fd);
67         char const *p = "?";
68         if (FUNCTION (x).name != 0)
69           p = FUNCTION (x).name;
70         fputs (p, fd);
71         fputs ("[", fd);
72         fputs (itoa (CDR (x)), fd);
73         fputs (",", fd);
74         fputs (itoa (x), fd);
75         fputs ("]>", fd);
76         break;
77       }
78     case TMACRO:
79       {
80         fputs ("#<macro ", fd);
81         display_helper (CDR (x), cont, "", fd, 0);
82         fputs (">", fd);
83         break;
84       }
85     case TVARIABLE:
86       {
87         fputs ("#<variable ", fd);
88         if (VARIABLE_GLOBAL_P (x) == cell_t)
89           fputs ("*global* ", fd);
90         display_helper (CAR (VARIABLE (x)), cont, "", fd, 0);
91         fputs (">", fd);
92         break;
93       }
94     case TNUMBER:
95       {
96         fputs (itoa (VALUE (x)), fd);
97         break;
98       }
99     case TPAIR:
100       {
101         if (!cont)
102           fputs ("(", fd);
103         if (CAR (x) == cell_closure)
104           fputs ("*closure* ", fd);
105         else
106         if (CAAR (x) == cell_closure)
107           fputs ("(*closure* ...) ", fd);
108         else
109         if (CAR (x) == cell_circular)
110           {
111             fputs ("(*circ* . ", fd);
112             int i = 0;
113             x = CDR (x);
114             while (x != cell_nil && i++ < 10)
115               {
116                 g_depth = 1;
117                 display_helper (CAAR (x), 0, "", fd, write_p); fputs (" ", fd);
118                 //fdisplay_ (CAAR (x), fd, write_p); fputs (" ", fd);
119                 x = CDR (x);
120               }
121             fputs (" ...)", fd);
122           }
123         else
124           {
125             if (x && x != cell_nil)
126               fdisplay_ (CAR (x), fd, write_p);
127             if (CDR (x) && TYPE (CDR (x)) == TPAIR)
128               display_helper (CDR (x), 1, " ", fd, write_p);
129             else if (CDR (x) && CDR (x) != cell_nil)
130               {
131                 if (TYPE (CDR (x)) != TPAIR)
132                   fputs (" . ", fd);
133                 fdisplay_ (CDR (x), fd, write_p);
134               }
135           }
136         if (!cont)
137           fputs (")", fd);
138         break;
139       }
140     case TKEYWORD:
141     case TSPECIAL:
142     case TSTRING:
143     case TSYMBOL:
144       {
145         if (TYPE (x) == TKEYWORD)
146           fputs ("#:", fd);
147         if (write_p && TYPE (x) == TSTRING)
148           fputc ('"', fd);
149         SCM t = CAR (x);
150         while (t && t != cell_nil)
151           {
152             switch (write_p ? VALUE (CAR (t)) : 0)
153               {
154               case '\t': fputs ("\\t", fd); break;
155               case '\n': fputs ("\\n", fd); break;
156               case '\\': fputs ("\\\\", fd); break;
157               case '"': fputs ("\\\"", fd); break;
158               default: fputc (VALUE (CAR (t)), fd);
159               }
160             t = CDR (t);
161           }
162         if (write_p && TYPE (x) == TSTRING)
163           fputc ('"', fd);
164         break;
165       }
166     case TVECTOR:
167       {
168         fputs ("#(", fd);
169         SCM t = CAR (x);
170         for (int i = 0; i < LENGTH (x); i++)
171           {
172             if (i)
173               fputc (' ', fd);
174             fdisplay_ (VECTOR (x) + i, fd, write_p);
175           }
176         fputc (')', fd);
177         break;
178       }
179     default:
180       {
181         fputs ("<", fd);
182         fputs (itoa (TYPE (x)), fd);
183         fputs (":", fd);
184         fputs (itoa (x), fd);
185         fputs (">", fd);
186         break;
187       }
188     }
189   return 0;
190 }
191
192 SCM
193 display_ (SCM x)
194 {
195   g_depth = 5;
196   return display_helper (x, 0, "", g_stdout, 0);
197 }
198
199 SCM
200 display_error_ (SCM x)
201 {
202   g_depth = 5;
203   return display_helper (x, 0, "", STDERR, 0);
204 }
205
206 SCM
207 display_port_ (SCM x, SCM p)
208 {
209   assert (TYPE (p) == TNUMBER);
210   return fdisplay_ (x, VALUE (p), 0);
211 }
212
213 SCM
214 write_ (SCM x)
215 {
216   g_depth = 5;
217   return display_helper (x, 0, "", g_stdout, 1);
218 }
219
220 SCM
221 write_error_ (SCM x)
222 {
223   g_depth = 5;
224   return display_helper (x, 0, "", STDERR, 1);
225 }
226
227 SCM
228 write_port_ (SCM x, SCM p)
229 {
230   assert (TYPE (p) == TNUMBER);
231   return fdisplay_ (x, VALUE (p), 1);
232 }
233
234 SCM
235 fdisplay_ (SCM x, int fd, int write_p) ///((internal))
236 {
237   g_depth = 5;
238   return display_helper (x, 0, "", fd, write_p);
239 }
240
241 SCM
242 exit_ (SCM x) ///((name . "exit"))
243 {
244   assert (TYPE (x) == TNUMBER);
245   exit (VALUE (x));
246 }
247
248 SCM
249 xassq (SCM x, SCM a) ///for speed in core only
250 {
251   while (a != cell_nil && x != CDAR (a))
252     a = CDR (a);
253   return a != cell_nil ? CAR (a) : cell_f;
254 }
255
256 SCM
257 memq (SCM x, SCM a)
258 {
259   switch (TYPE (x))
260     {
261     case TCHAR:
262     case TNUMBER:
263       {
264         SCM v = VALUE (x);
265         while (a != cell_nil && v != VALUE (CAR (a)))
266           a = CDR (a);
267         break;
268       }
269     case TKEYWORD:
270       {
271         SCM v = STRING (x);
272         while (a != cell_nil && v != STRING (CAR (a)))
273           a = CDR (a);
274         break;
275       }
276       // case TSYMBOL:
277       // case TSPECIAL:
278     default:
279       while (a != cell_nil && x != CAR (a))
280         a = CDR (a);
281     }
282   return a != cell_nil ? a : cell_f;
283 }
284
285 SCM
286 equal2_p (SCM a, SCM b)
287 {
288   if (a == cell_nil && b == cell_nil)
289     return cell_t;
290   if (TYPE (a) == TPAIR && TYPE (b) == TPAIR)
291     return equal2_p (CAR (a), CAR (b)) == cell_t
292       && equal2_p (CDR (a), CDR (b)) == cell_t
293       ? cell_t : cell_f;
294   if (TYPE (a) == TSTRING && TYPE (b) == TSTRING)
295     return equal2_p (STRING (a), STRING (b));
296   if (TYPE (a) == TVECTOR && TYPE (b) == TVECTOR)
297     {
298       if (LENGTH (a) != LENGTH (b))
299         return cell_f;
300       for (int i=0; i < LENGTH (a); i++)
301         {
302           SCM ai = VECTOR (a) + i;
303           SCM bi = VECTOR (b) + i;
304           if (TYPE (ai) == TREF)
305             ai = REF (ai);
306           if (TYPE (bi) == TREF)
307             bi = REF (bi);
308           if (equal2_p (ai, bi) == cell_f)
309             return cell_f;
310         }
311       return cell_t;
312     }
313   return eq_p (a, b);
314 }