-
Notifications
You must be signed in to change notification settings - Fork 10
/
s9core.h
553 lines (463 loc) · 14.4 KB
/
s9core.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
/*
* S9core Toolkit, Mk IVd
* By Nils M Holm, 2007-2019
* In the public domain
*
* Under jurisdictions without a public domain, the CC0 applies:
* https://creativecommons.org/publicdomain/zero/1.0/
*/
#define S9_VERSION "20190402"
/*
* Ugly prelude to deal with some system-dependent stuff.
*/
#ifdef __NetBSD__
#ifndef unix
#define unix
#endif
#endif
#ifdef __unix
#ifndef unix
#define unix
#endif
#endif
#ifdef __linux
#ifndef unix
#define unix
#endif
#endif
#ifdef __GNUC__
#ifndef unix
#define unix
#endif
#endif
#ifdef __clang__
#ifndef unix
#define unix
#endif
#endif
#ifndef unix
#ifndef plan9
#error "Either 'unix' or 'plan9' must be #defined."
#endif
#endif
#ifdef _MSC_VER
#if _MSC_VER > 1200
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#endif
#ifndef _POSIX_
#define _POSIX_
#endif
#endif
#ifdef plan9
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <ctype.h>
#include <ape/limits.h>
#define size_t uvlong
#define bye(x) exits((x)? "error": NULL)
#define ptrdiff_t vlong
#endif
#ifdef unix
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#define bye(x) exit((x)? EXIT_FAILURE: EXIT_SUCCESS)
#endif
/*
* Tunable parameters
*/
/* Default memory limits in K nodes and K cells; 0 = none */
#define S9_NODE_LIMIT 14013
#define S9_VECTOR_LIMIT 14013
/* Initial memory pool sizes */
#define S9_INITIAL_SEGMENT_SIZE 32768
/* Primitive segment size (slots) */
#define S9_PRIM_SEG_SIZE 256
/* Maximum number of open I/O ports */
#define S9_MAX_PORTS 32
/* Use 64-bit cells (don't do this!) */
/* #define S9_BITS_PER_WORD_64 */
/*
* Non-tunable parameters
*/
/* A cell must be large enough to hold an integer segment;
* see S9_INT_SEG_LIMIT, below
*/
#ifdef S9_BITS_PER_WORD_64
#define s9_cell ptrdiff_t
#else
#define s9_cell int
#endif
#ifdef S9_BITS_PER_WORD_64
#define S9_DIGITS_PER_CELL 18
#define S9_INT_SEG_LIMIT 1000000000000000000LL
#define S9_MANTISSA_SEGMENTS 1
#else
#define S9_DIGITS_PER_CELL 9
#define S9_INT_SEG_LIMIT 1000000000L
#define S9_MANTISSA_SEGMENTS 2
#endif
#define S9_MANTISSA_SIZE (S9_MANTISSA_SEGMENTS * S9_DIGITS_PER_CELL)
/*
* Node tags
*/
#define S9_ATOM_TAG 0x01 /* Atom, car = type, cdr = next */
#define S9_MARK_TAG 0x02 /* Mark */
#define S9_STATE_TAG 0x04 /* State */
#define S9_VECTOR_TAG 0x08 /* Vector, car = type, cdr = content */
#define S9_PORT_TAG 0x10 /* Atom is an I/O port (with ATOM_TAG) */
#define S9_USED_TAG 0x20 /* Port: in use */
#define S9_LOCK_TAG 0x40 /* Port: locked (do not finalize) */
#define S9_CONST_TAG 0x80 /* Node is immutable */
/*
* Special objects
*/
#define s9_special_p(x) ((x) < 0)
#define S9_NIL (-1)
#define S9_TRUE (-2)
#define S9_FALSE (-3)
#define S9_END_OF_FILE (-4)
#define S9_UNDEFINED (-5)
#define S9_UNSPECIFIC (-6)
#define S9_VOID (-7)
/*
* Type tags
*/
#define S9_T_ANY (-10)
#define S9_T_BOOLEAN (-11)
#define S9_T_CHAR (-12)
#define S9_T_INPUT_PORT (-13)
#define S9_T_INTEGER (-14)
#define S9_T_LIST (-17)
#define S9_T_OUTPUT_PORT (-15)
#define S9_T_PAIR (-16)
#define S9_T_PRIMITIVE (-18)
#define S9_T_FUNCTION (-19)
#define S9_T_REAL (-20)
#define S9_T_STRING (-21)
#define S9_T_SYMBOL (-22)
#define S9_T_SYNTAX (-23)
#define S9_T_VECTOR (-24)
#define S9_T_CONTINUATION (-25)
#define S9_T_FIXNUM (-26)
#define S9_T_NONE (-99)
#define S9_USER_SPECIALS (-100)
/*
* Structures
*/
struct S9_counter {
int n, n1k, n1m, n1g, n1t;
};
#define s9_counter struct S9_counter
struct S9_primitive {
char *name;
s9_cell (*handler)(void);
int min_args;
int max_args; /* -1 = variadic */
int arg_types[3];
};
#define S9_PRIM struct S9_primitive
/*
* I/O
*/
#define s9_nl() s9_prints("\n")
/*
* Nested lists
*/
#define s9_car(x) (S9_car[x])
#define s9_cdr(x) (S9_cdr[x])
#define s9_caar(x) (S9_car[S9_car[x]])
#define s9_cadr(x) (S9_car[S9_cdr[x]])
#define s9_cdar(x) (S9_cdr[S9_car[x]])
#define s9_cddr(x) (S9_cdr[S9_cdr[x]])
#define s9_caaar(x) (S9_car[S9_car[S9_car[x]]])
#define s9_caadr(x) (S9_car[S9_car[S9_cdr[x]]])
#define s9_cadar(x) (S9_car[S9_cdr[S9_car[x]]])
#define s9_caddr(x) (S9_car[S9_cdr[S9_cdr[x]]])
#define s9_cdaar(x) (S9_cdr[S9_car[S9_car[x]]])
#define s9_cdadr(x) (S9_cdr[S9_car[S9_cdr[x]]])
#define s9_cddar(x) (S9_cdr[S9_cdr[S9_car[x]]])
#define s9_cdddr(x) (S9_cdr[S9_cdr[S9_cdr[x]]])
#define s9_caaaar(x) (S9_car[S9_car[S9_car[S9_car[x]]]])
#define s9_caaadr(x) (S9_car[S9_car[S9_car[S9_cdr[x]]]])
#define s9_caadar(x) (S9_car[S9_car[S9_cdr[S9_car[x]]]])
#define s9_caaddr(x) (S9_car[S9_car[S9_cdr[S9_cdr[x]]]])
#define s9_cadaar(x) (S9_car[S9_cdr[S9_car[S9_car[x]]]])
#define s9_cadadr(x) (S9_car[S9_cdr[S9_car[S9_cdr[x]]]])
#define s9_caddar(x) (S9_car[S9_cdr[S9_cdr[S9_car[x]]]])
#define s9_cadddr(x) (S9_car[S9_cdr[S9_cdr[S9_cdr[x]]]])
#define s9_cdaaar(x) (S9_cdr[S9_car[S9_car[S9_car[x]]]])
#define s9_cdaadr(x) (S9_cdr[S9_car[S9_car[S9_cdr[x]]]])
#define s9_cdadar(x) (S9_cdr[S9_car[S9_cdr[S9_car[x]]]])
#define s9_cdaddr(x) (S9_cdr[S9_car[S9_cdr[S9_cdr[x]]]])
#define s9_cddaar(x) (S9_cdr[S9_cdr[S9_car[S9_car[x]]]])
#define s9_cddadr(x) (S9_cdr[S9_cdr[S9_car[S9_cdr[x]]]])
#define s9_cdddar(x) (S9_cdr[S9_cdr[S9_cdr[S9_car[x]]]])
#define s9_cddddr(x) (S9_cdr[S9_cdr[S9_cdr[S9_cdr[x]]]])
/*
* Access to fields of atoms
*/
#define s9_tag(n) (S9_tag[n])
#define s9_string(n) ((char *) &Vectors[S9_cdr[n]])
#define s9_string_len(n) (Vectors[S9_cdr[n] - 1])
#define s9_symbol_name(n) (string(n))
#define s9_symbol_len(n) (string_len(n))
#define s9_vector(n) (&Vectors[S9_cdr[n]])
#define s9_vector_link(n) (Vectors[S9_cdr[n] - 3])
#define s9_vector_index(n) (Vectors[S9_cdr[n] - 2])
#define s9_vector_size(k) (((k)+sizeof(s9_cell)-1) / \
sizeof(s9_cell) + 3)
#define s9_vector_len(n) (vector_size(string_len(n)) - 3)
#define s9_fixval(x) cadr(x)
#define s9_small_int_value(x) cadr(x)
#define s9_port_no(n) (cadr(n))
#define s9_char_value(n) (cadr(n))
#define s9_prim_slot(n) (cadr(n))
#define s9_prim_info(n) (&Primitives[prim_slot(n)])
/*
* Type predicates
*/
#define s9_eof_p(n) ((n) == S9_END_OF_FILE)
#define s9_undefined_p(n) ((n) == S9_UNDEFINED)
#define s9_unspecific_p(n) ((n) == S9_UNSPECIFIC)
#define s9_boolean_p(n) \
((n) == S9_TRUE || (n) == S9_FALSE)
#define s9_integer_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && car(n) == S9_T_INTEGER)
#define s9_real_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && car(n) == S9_T_REAL)
#define s9_fix_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && T_FIXNUM == car(n))
#define s9_number_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
(car(n) == S9_T_REAL || car(n) == S9_T_INTEGER))
#define s9_primitive_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
car(n) == S9_T_PRIMITIVE)
#define s9_function_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
car(n) == S9_T_FUNCTION)
#define s9_continuation_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
car(n) == S9_T_CONTINUATION)
#define s9_char_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && car(n) == S9_T_CHAR)
#define s9_syntax_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && car(n) == S9_T_SYNTAX)
#define s9_input_port_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
(tag(n) & S9_PORT_TAG) && car(n) == S9_T_INPUT_PORT)
#define s9_output_port_p(n) \
(!s9_special_p(n) && (tag(n) & S9_ATOM_TAG) && \
(tag(n) & S9_PORT_TAG) && car(n) == S9_T_OUTPUT_PORT)
#define s9_symbol_p(n) \
(!s9_special_p(n) && (tag(n) & S9_VECTOR_TAG) && car(n) == S9_T_SYMBOL)
#define s9_vector_p(n) \
(!s9_special_p(n) && (tag(n) & S9_VECTOR_TAG) && car(n) == S9_T_VECTOR)
#define s9_string_p(n) \
(!s9_special_p(n) && (tag(n) & S9_VECTOR_TAG) && car(n) == S9_T_STRING)
#define s9_constant_p(n) \
(!s9_special_p(n) && (tag(n) & S9_CONST_TAG))
#define s9_atom_p(n) \
(s9_special_p(n) || (tag(n) & S9_ATOM_TAG) || (tag(n) & S9_VECTOR_TAG))
#define s9_pair_p(x) (!s9_atom_p(x))
#define s9_small_int_p(n) (NIL == cddr(n))
#define s9_type_tag(n) \
(S9_TRUE == (n)? S9_T_BOOLEAN: \
S9_FALSE == (n)? S9_T_BOOLEAN: \
(!s9_special_p(n) && (tag(n) & (S9_ATOM_TAG|S9_VECTOR_TAG))? car(n): \
S9_T_NONE))
/*
* Allocators
*/
#define s9_cons(pa, pd) s9_cons3((pa), (pd), 0)
#define s9_new_atom(pa, pd) s9_cons3((pa), (pd), S9_ATOM_TAG)
#define s9_save(n) (Stack = s9_cons((n), Stack))
/*
* Bignum arithmetics
*/
#define s9_bignum_negative_p(a) ((cadr(a)) < 0)
#define s9_bignum_zero_p(a) ((cadr(a)) == 0)
#define s9_bignum_positive_p(a) ((cadr(a)) > 0)
/*
* Real number structure
*/
#define S9_real_flags(x) (cadr(x))
#define S9_real_exponent(x) (caddr(x))
#define S9_real_mantissa(x) (cdddr(x))
#define S9_REAL_NEGATIVE 0x01
#define S9_real_negative_flag(x) (S9_real_flags(x) & S9_REAL_NEGATIVE)
/*
* Real-number arithmetics
*/
#define S9_real_zero_p(x) \
(car(S9_real_mantissa(x)) == 0 && cdr(S9_real_mantissa(x)) == S9_NIL)
#define S9_real_negative_p(x) \
(S9_real_negative_flag(x) && !S9_real_zero_p(x))
#define S9_real_positive_p(x) \
(!S9_real_negative_flag(x) && !S9_real_zero_p(x))
#define S9_real_negate(a) \
S9_make_quick_real(S9_real_flags(a) & S9_REAL_NEGATIVE? \
S9_real_flags(a) & ~S9_REAL_NEGATIVE: \
S9_real_flags(a) | S9_REAL_NEGATIVE, \
S9_real_exponent(a), S9_real_mantissa(a))
/*
* Globals
*/
extern s9_cell *S9_car,
*S9_cdr;
extern char *S9_tag;
extern s9_cell *S9_vectors;
extern s9_cell S9_stack;
extern s9_cell *S9_gc_stack;
extern int *S9_gc_stkptr;
extern S9_PRIM *S9_primitives;
extern s9_cell S9_zero,
S9_one,
S9_two,
S9_ten;
extern s9_cell S9_epsilon;
extern FILE *S9_ports[];
extern int S9_input_port,
S9_output_port,
S9_error_port;
/*
* Prototypes
*/
#ifdef plan9
int system(char *s);
#endif
void s9_abort(void);
int s9_aborted(void);
void s9_add_image_vars(s9_cell **v);
s9_cell s9_apply_prim(s9_cell f);
s9_cell s9_argv_to_list(char **argv);
long s9_asctol(char *s);
s9_cell s9_bignum_abs(s9_cell a);
s9_cell s9_bignum_add(s9_cell a, s9_cell b);
s9_cell s9_bignum_divide(s9_cell a, s9_cell b);
int s9_bignum_equal_p(s9_cell a, s9_cell b);
int s9_bignum_even_p(s9_cell a);
int s9_bignum_less_p(s9_cell a, s9_cell b);
s9_cell s9_bignum_multiply(s9_cell a, s9_cell b);
s9_cell s9_bignum_negate(s9_cell a);
s9_cell s9_bignum_shift_left(s9_cell a, int fill);
s9_cell s9_bignum_shift_right(s9_cell a);
s9_cell s9_bignum_subtract(s9_cell a, s9_cell b);
s9_cell s9_bignum_to_int(s9_cell x, int *of);
s9_cell s9_bignum_to_real(s9_cell a);
s9_cell s9_bignum_to_string(s9_cell x);
int s9_blockread(char *s, int k);
void s9_blockwrite(char *s, int k);
void s9_close_port(int port);
void s9_close_input_string(void);
s9_cell s9_cons3(s9_cell pcar, s9_cell pcdr, int ptag);
int s9_conses(s9_cell a);
void s9_cons_stats(int x);
s9_cell s9_copy_string(s9_cell x);
void s9_count(s9_counter *c);
void s9_countn(s9_counter *c, int n);
char *s9_dump_image(char *path, char *magic);
int s9_error_port(void);
void s9_exponent_chars(char *s);
void s9_fatal(char *msg);
s9_cell s9_find_symbol(char *s);
s9_cell s9_flat_copy(s9_cell n, s9_cell *lastp);
void s9_flush(void);
int s9_gc(void);
int s9_gcv(void);
void s9_gc_verbosity(int n);
void s9_get_counters(s9_counter **nc, s9_counter **cc, s9_counter **vc,
s9_counter **gc);
void s9_mem_error_handler(void (*h)(int src));
void s9_image_vars(s9_cell **v);
int s9_input_port(void);
int s9_inport_open_p(void);
int s9_integer_string_p(char *s);
s9_cell s9_intern_symbol(s9_cell y);
s9_cell s9_int_to_bignum(int v);
int s9_io_status(void);
void s9_io_reset(void);
int s9_length(s9_cell n);
char *s9_load_image(char *path, char *magic);
int s9_lock_port(int port);
s9_cell s9_make_char(int c);
s9_cell s9_make_integer(s9_cell i);
s9_cell s9_make_norm_real(int flags, s9_cell exp, s9_cell mant);
s9_cell s9_make_port(int portno, s9_cell type);
s9_cell s9_make_primitive(S9_PRIM *p);
s9_cell S9_make_real(int flags, s9_cell exp, s9_cell mant);
s9_cell s9_make_real(int sign, s9_cell exp, s9_cell mant);
s9_cell s9_make_string(char *s, int k);
s9_cell s9_make_symbol(char *s, int k);
s9_cell s9_make_vector(int k);
s9_cell s9_mkfix(int i);
int s9_new_port(void);
s9_cell s9_new_vec(s9_cell type, int size);
int s9_open_input_port(char *path);
char *s9_open_input_string(char *s);
int s9_open_output_port(char *path, int append);
int s9_output_port(void);
int s9_outport_open_p(void);
int s9_port_eof(int p);
void s9_prints(char *s);
int s9_printer_limit(void);
void s9_print_bignum(s9_cell n);
void s9_print_expanded_real(s9_cell n);
void s9_print_real(s9_cell n);
void s9_print_sci_real(s9_cell n);
int s9_readc(void);
s9_cell s9_read_counter(s9_counter *c);
s9_cell s9_real_abs(s9_cell a);
s9_cell s9_real_add(s9_cell a, s9_cell b);
int s9_real_approx_p(s9_cell a, s9_cell b);
s9_cell s9_real_ceil(s9_cell x);
s9_cell s9_real_divide(s9_cell a, s9_cell b);
int s9_real_equal_p(s9_cell a, s9_cell b);
s9_cell s9_real_exponent(s9_cell x);
s9_cell s9_real_floor(s9_cell x);
s9_cell s9_real_integer_p(s9_cell x);
int s9_real_less_p(s9_cell a, s9_cell b);
s9_cell s9_real_mantissa(s9_cell x);
s9_cell s9_real_multiply(s9_cell a, s9_cell b);
s9_cell s9_real_negate(s9_cell a);
s9_cell s9_real_negative_p(s9_cell a);
s9_cell s9_real_positive_p(s9_cell a);
s9_cell s9_real_power(s9_cell x, s9_cell y);
s9_cell s9_real_round(s9_cell x);
s9_cell s9_real_sqrt(s9_cell x);
s9_cell s9_real_subtract(s9_cell a, s9_cell b);
s9_cell s9_real_to_bignum(s9_cell r);
s9_cell s9_real_to_string(s9_cell r, int mode);
s9_cell s9_real_trunc(s9_cell x);
s9_cell s9_real_zero_p(s9_cell a);
void s9_rejectc(int c);
void s9_reset(void);
void s9_reset_counter(s9_counter *c);
void s9_reset_std_ports(void);
void s9_run_stats(int x);
void s9_fini(void);
void s9_init(s9_cell **extroots, s9_cell *stack, int *stkptr);
s9_cell s9_set_input_port(s9_cell port);
void s9_set_node_limit(int k);
s9_cell s9_set_output_port(s9_cell port);
void s9_set_printer_limit(int k);
void s9_set_vector_limit(int k);
int s9_string_numeric_p(char *s);
s9_cell s9_string_to_bignum(char *s);
s9_cell s9_string_to_number(char *s);
s9_cell s9_string_to_real(char *s);
s9_cell s9_string_to_symbol(s9_cell x);
s9_cell s9_symbol_ref(char *s);
s9_cell s9_symbol_table(void);
s9_cell s9_symbol_to_string(s9_cell x);
char *s9_typecheck(s9_cell f);
int s9_unlock_port(int port);
s9_cell s9_unsave(int k);
void s9_writec(int c);