1 /* -*- C -*-
2 // -------------------------------------------------------------------
3 // MiniExp - Library for handling lisp expressions
4 // Copyright (c) 2005 Leon Bottou
5 //
6 // This software is subject to, and may be distributed under, the GNU
7 // Lesser General Public License, either Version 2.1 of the license,
8 // or (at your option) any later version. The license should have
9 // accompanied the software or you may obtain a copy of the license
10 // from the Free Software Foundation at http://www.fsf.org .
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but 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 */
18
19 #ifndef MINIEXP_H
20 #define MINIEXP_H
21
22 #ifdef __cplusplus
23 extern "C" {
24 # ifndef __cplusplus
25 }
26 # endif
27 #endif
28
29 #ifndef MINILISPAPI
30 # ifdef _WIN32
31 # ifdef MINILISPAPI_EXPORT
32 # define MINILISPAPI __declspec(dllexport)
33 # else
34 # define MINILISPAPI __declspec(dllimport)
35 # endif
36 # endif
37 #endif
38 #ifndef MINILISPAPI
39 # define MINILISPAPI /**/
40 #endif
41
42 #ifndef __cplusplus
43 # ifndef inline
44 # if defined(__GNUC__)
45 # define inline __inline__
46 # elif defined(_MSC_VER)
47 # define inline __inline
48 # else
49 # define inline /**/
50 # endif
51 # endif
52 #endif
53
54 #include <stddef.h>
55
56 /* -------------------------------------------------- */
57 /* LISP EXPRESSIONS */
58 /* -------------------------------------------------- */
59
60 /* miniexp_t --
61 Opaque pointer type representing a lisp expression,
62 also known as s-expression.
63 S-expressions can be viewed as a simple and powerful
64 alternative to XML. DjVu uses s-expressions to handle
65 annotations. Both the decoding api <ddjvuapi.h> and
66 program <djvused> use s-expressions to describe the
67 hidden text information and the navigation
68 information */
69
70
71 typedef struct miniexp_s* miniexp_t;
72
73
74 /* There are four basic types of lisp expressions,
75 numbers, symbols, pairs, and objects.
76 The latter category can represent any c++ object
77 that inherits class <miniobj_t> defined later in this file.
78 Strings and floating point numbers are implemented this way.*/
79
80
81 /* -------- NUMBERS -------- */
82
83 /* Minilisp numbers represent integers
84 covering at least range [-2^29...2^29-1] */
85
86
87 /* miniexp_numberp --
88 Tests if an expression is a number. */
89
miniexp_numberp(miniexp_t p)90 static inline int miniexp_numberp(miniexp_t p) {
91 return (((size_t)(p)&3)==3);
92 }
93
94 /* miniexp_to_int --
95 Returns the integer corresponding to a lisp expression.
96 Assume that the expression is indeed a number. */
97
miniexp_to_int(miniexp_t p)98 static inline int miniexp_to_int(miniexp_t p) {
99 return (((int)(size_t)(p))>>2);
100 }
101
102 /* miniexp_number --
103 Constructs the expression corresponding to an integer. */
104
miniexp_number(int x)105 static inline miniexp_t miniexp_number(int x) {
106 return (miniexp_t) (size_t) ((x<<2)|3);
107 }
108
109
110
111 /* -------- SYMBOLS -------- */
112
113 /* The textual representation of a minilisp symbol is a
114 sequence of printable characters forming an identifier.
115 Each symbol has a unique representation and remain
116 permanently allocated. To compare two symbols,
117 simply compare the <miniexp_t> pointers. */
118
119
120 /* miniexp_symbolp --
121 Tests if an expression is a symbol. */
122
miniexp_symbolp(miniexp_t p)123 static inline int miniexp_symbolp(miniexp_t p) {
124 return ((((size_t)p)&3)==2);
125 }
126
127 /* miniexp_to_name --
128 Returns the symbol name as a string.
129 Returns NULL if the expression is not a symbol. */
130
131 MINILISPAPI const char* miniexp_to_name(miniexp_t p);
132
133 /* miniexp_symbol --
134 Returns the unique symbol expression with the specified name. */
135
136 MINILISPAPI miniexp_t miniexp_symbol(const char *name);
137
138
139
140 /* -------- PAIRS -------- */
141
142 /* Pairs (also named "cons") are the basic building blocks for
143 minilisp lists. Each pair contains two expression:
144 - the <car> represents the first element of a list.
145 - the <cdr> usually is a pair representing the rest of the list.
146 The empty list is represented by a null pointer. */
147
148
149 /* miniexp_nil --
150 The empty list. */
151
152 #define miniexp_nil ((miniexp_t)(size_t)0)
153
154 /* miniexp_dummy --
155 An invalid expression used to represent
156 various exceptional conditions. */
157
158 #define miniexp_dummy ((miniexp_t)(size_t)2)
159
160 /* miniexp_listp --
161 Tests if an expression is either a pair or the empty list. */
162
miniexp_listp(miniexp_t p)163 static inline int miniexp_listp(miniexp_t p) {
164 return ((((size_t)p)&3)==0);
165 }
166
167 /* miniexp_consp --
168 Tests if an expression is a pair. */
169
miniexp_consp(miniexp_t p)170 static inline int miniexp_consp(miniexp_t p) {
171 return p && miniexp_listp(p);
172 }
173
174 /* miniexp_length --
175 Returns the length of a list.
176 Returns 0 for non lists, -1 for circular lists. */
177
178 MINILISPAPI int miniexp_length(miniexp_t p);
179
180 /* miniexp_car --
181 miniexp_cdr --
182 Returns the car or cdr of a pair. */
183
miniexp_car(miniexp_t p)184 static inline miniexp_t miniexp_car(miniexp_t p) {
185 if (miniexp_consp(p))
186 return ((miniexp_t*)p)[0];
187 return miniexp_nil;
188 }
189
miniexp_cdr(miniexp_t p)190 static inline miniexp_t miniexp_cdr(miniexp_t p) {
191 if (miniexp_consp(p))
192 return ((miniexp_t*)p)[1];
193 return miniexp_nil;
194 }
195
196 /* miniexp_cXXr --
197 Represent common combinations of car and cdr. */
198
199 MINILISPAPI miniexp_t miniexp_caar (miniexp_t p);
200 MINILISPAPI miniexp_t miniexp_cadr (miniexp_t p);
201 MINILISPAPI miniexp_t miniexp_cdar (miniexp_t p);
202 MINILISPAPI miniexp_t miniexp_cddr (miniexp_t p);
203 MINILISPAPI miniexp_t miniexp_caddr(miniexp_t p);
204 MINILISPAPI miniexp_t miniexp_cdddr(miniexp_t p);
205
206 /* miniexp_nth --
207 Returns the n-th element of a list. */
208
209 MINILISPAPI miniexp_t miniexp_nth(int n, miniexp_t l);
210
211 /* miniexp_cons --
212 Constructs a pair. */
213
214 MINILISPAPI miniexp_t miniexp_cons(miniexp_t car, miniexp_t cdr);
215
216 /* miniexp_rplaca --
217 miniexp_rplacd --
218 Changes the car or the cdr of a pair. */
219
220 MINILISPAPI miniexp_t miniexp_rplaca(miniexp_t pair, miniexp_t newcar);
221 MINILISPAPI miniexp_t miniexp_rplacd(miniexp_t pair, miniexp_t newcdr);
222
223 /* miniexp_reverse --
224 Reverses a list in place. */
225
226 MINILISPAPI miniexp_t miniexp_reverse(miniexp_t p);
227
228
229 /* -------- OBJECTS (GENERIC) -------- */
230
231 /* Object expressions represent a c++ object
232 that inherits class <miniobj_t> defined later.
233 Each object expression has a symbolic class name
234 and a pointer to the c++ object. */
235
236 /* miniexp_objectp --
237 Tests if an expression is an object. */
238
miniexp_objectp(miniexp_t p)239 static inline int miniexp_objectp(miniexp_t p) {
240 return ((((size_t)p)&3)==1);
241 }
242
243 /* miniexp_classof --
244 Returns the symbolic class of an expression.
245 Returns nil if the expression is not an object. */
246
247 MINILISPAPI miniexp_t miniexp_classof(miniexp_t p);
248
249 /* miniexp_isa --
250 If <p> is an instance of class named <c> or one of
251 its subclasses, returns the actual class name.
252 Otherwise returns miniexp_nil. */
253
254 MINILISPAPI miniexp_t miniexp_isa(miniexp_t p, miniexp_t c);
255
256
257 /* -------- OBJECTS (STRINGS) -------- */
258
259 /* miniexp_stringp --
260 Tests if an expression is a string. */
261
262 MINILISPAPI int miniexp_stringp(miniexp_t p);
263
264 /* miniexp_to_str --
265 Returns the c string represented by the expression.
266 Returns NULL if the expression is not a string.
267 The c string remains valid as long as the
268 corresponding lisp object exists. */
269
270 MINILISPAPI const char *miniexp_to_str(miniexp_t p);
271
272 /* miniexp_to_lstr ----
273 Returns the length of the string represented by the expression.
274 Optionally returns the c string into *sp.
275 Return 0 and makes *sp null if the expression is not a string. */
276
277 MINILISPAPI size_t miniexp_to_lstr(miniexp_t p, const char **sp);
278
279 /* miniexp_string --
280 Constructs a string expression by copying zero terminated string s. */
281
282 MINILISPAPI miniexp_t miniexp_string(const char *s);
283
284 /* miniexp_lstring --
285 Constructs a string expression by copying len bytes from s. */
286
287 MINILISPAPI miniexp_t miniexp_lstring(size_t len, const char *s);
288
289 /* miniexp_substring --
290 Constructs a string expression by copying at most len bytes
291 from zero terminated string s. */
292
293 MINILISPAPI miniexp_t miniexp_substring(const char *s, int len);
294
295 /* miniexp_concat --
296 Concat all the string expressions in list <l>. */
297
298 MINILISPAPI miniexp_t miniexp_concat(miniexp_t l);
299
300
301
302 /* -------- OBJECTS (FLOATNUM) -------- */
303
304 /* miniexp_floatnump --
305 Tests if an expression is an object
306 representing a floating point number. */
307
308 MINILISPAPI int miniexp_floatnump(miniexp_t p);
309
310 /* miniexp_floatnum --
311 Returns a new floating point number object. */
312
313 MINILISPAPI miniexp_t miniexp_floatnum(double x);
314
315 /* miniexp_doublep --
316 Tests if an expression can be converted
317 to a double precision number. */
318
319 MINILISPAPI int miniexp_doublep(miniexp_t p);
320
321 /* miniexp_to_double --
322 Returns a double precision number corresponding to
323 a lisp expression. */
324
325 MINILISPAPI double miniexp_to_double(miniexp_t p);
326
327 /* miniexp_double --
328 Returns a lisp expression representing a double
329 precision number. This will be a number if it fits
330 and a floatnum otherwise.
331 */
332
333 MINILISPAPI miniexp_t miniexp_double(double x);
334
335
336 /* -------------------------------------------------- */
337 /* GARBAGE COLLECTION */
338 /* -------------------------------------------------- */
339
340
341 /* The garbage collector reclaims the memory allocated for
342 lisp expressions no longer in use. It is automatically
343 invoked by the pair and object allocation functions when
344 the available memory runs low. It is however possible to
345 temporarily disable it.
346
347 The trick is to determine which lisp expressions are in
348 use at a given moment. This package takes a simplistic
349 approach. All objects of type <minivar_t> are chained and
350 can reference an arbitrary lisp expression. Garbage
351 collection preserves all lisp expressions referenced by a
352 minivar, as well as all lisp expressions that can be
353 accessed from these. When called automatically,
354 garbage collection also preserves the sixteen most recently
355 created miniexps in order to make sure that temporaries do
356 not vanish in the middle of complicated C expressions.
357
358 The minivar class is designed such that C++ program can
359 directly use instances of <minivar_t> as normal
360 <miniexp_t> variables. There is almost no overhead
361 accessing or changing the lisp expression referenced by a
362 minivar. However, the minivar chain must be updated
363 whenever the minivar object is constructed or destructed.
364
365 Example (in C++ only):
366 miniexp_t copy_in_reverse(miniexp_t p) {
367 minivar_t l = miniexp_nil;
368 while (miniexp_consp(p)) {
369 l = miniexp_cons(miniexp_car(p), l);
370 p = miniexp_cdr(p);
371 }
372 return l;
373 }
374
375 When to use minivar_t instead of miniexp_t?
376
377 * A function that only navigates properly secured
378 s-expressions without modifying them does not need to
379 bother about minivars.
380
381 * Otherwise all functions should make sure that all useful
382 s-expression are directly or indirectly secured by a
383 minivar_t object. In case of doubt, use minivars
384 everywhere.
385
386 * Function arguments should remain <miniexp_t> in order
387 to allow interoperability with the C language.
388 It is assumed that these arguments have been properly
389 secured by the caller and cannot disappear if a
390 garbage collection occurs.
391
392 C programs cannot use minivars as easily as C++ programs.
393 Wrappers are provided to allocate minivars and to access
394 their value. This is somehow inconvenient. It might be
395 more practical to control the garbage collector
396 invocations with <minilisp_acquire_gc_lock()> and
397 <minilisp_release_gc_lock()>... */
398
399
400 /* minilisp_gc --
401 Invokes the garbage collector now. */
402
403 MINILISPAPI void minilisp_gc(void);
404
405 /* minilisp_info --
406 Prints garbage collector statistics. */
407
408 MINILISPAPI void minilisp_info(void);
409
410 /* minilisp_acquire_gc_lock --
411 minilisp_release_gc_lock --
412 Temporarily disables automatic garbage collection.
413 Acquire/release pairs may be nested.
414 Both functions return their argument unmodified.
415 This is practical because <minilisp_release_gc_lock>
416 can invoke the garbage collector. Before doing
417 so it stores its argument in a minivar to
418 preserve it.
419
420 Example (in C):
421 miniexp_t copy_in_reverse(miniexp_t p) {
422 miniexp_t l = 0;
423 minilisp_acquire_gc_lock(0);
424 while (miniexp_consp(p)) {
425 l = miniexp_cons(miniexp_car(p), l);
426 p = miniexp_cdr(p);
427 }
428 return minilisp_release_gc_lock(l);
429 }
430
431 Disabling garbage collection for a long time
432 increases the memory consumption. */
433
434 MINILISPAPI miniexp_t minilisp_acquire_gc_lock(miniexp_t);
435 MINILISPAPI miniexp_t minilisp_release_gc_lock(miniexp_t);
436
437 /* minivar_t --
438 The minivar type. */
439 #ifdef __cplusplus
440 class minivar_t;
441 #else
442 typedef struct minivar_s minivar_t;
443 #endif
444
445 /* minivar_alloc --
446 minivar_free --
447 Wrappers for creating and destroying minivars in C. */
448
449 MINILISPAPI minivar_t *minivar_alloc(void);
450 MINILISPAPI void minivar_free(minivar_t *v);
451
452 /* minivar_pointer --
453 Wrappers to access the lisp expression referenced
454 by a minivar. This function returns a pointer
455 to the actual miniexp_t variable. */
456
457 MINILISPAPI miniexp_t *minivar_pointer(minivar_t *v);
458
459 /* minilisp_debug --
460 Setting the debug flag runs the garbage collector
461 very often. This is extremely slow, but can be
462 useful to debug memory allocation problems. */
463
464 MINILISPAPI void minilisp_debug(int debugflag);
465
466 /* minilisp_finish --
467 Deallocates everything. This is only useful when using
468 development tools designed to check for memory leaks.
469 No miniexp function can be used after calling this. */
470
471 MINILISPAPI void minilisp_finish(void);
472
473
474 /* -------------------------------------------------- */
475 /* INPUT/OUTPUT */
476 /* -------------------------------------------------- */
477
478 /* Notes about the textual representation of miniexps.
479
480 - Special characters are:
481 * the parenthesis <(> and <)>,
482 * the double quote <">,
483 * the vertical bar <|>,
484 * any other ascii character with a non zero entry
485 in the macro character array.
486 * the dieze character <#>, when followed by another
487 dieze or by an ascii character with a non zero entry
488 in the dieze character array.
489
490 - Symbols are represented by their name.
491 Symbols whose name contains blanks, special characters,
492 non printable characters, non ascii characters,
493 or can be confused for a number are delimited
494 by vertical bars <|> and can contain two consecutive
495 vertical bars to represent a single vertical bar character.
496
497 - Numbers follow the syntax specified by the C
498 function strtol() with base=0, but are required
499 to start with a digit or with a sign character
500 followed by another character.
501
502 - Floating point follow the syntax specified by the C
503 function strtod() with base=0, but are required
504 to start with a digit or with a sign character
505 followed by another character.
506
507 - Strings are delimited by double quotes.
508 All non printable ASCII characters must be escaped.
509 Besides all the usual C string escape sequences,
510 UTF8-encoded Unicode characters in range 0..0x10ffff
511 can be represented by escape sequence <\u> followed
512 by four hexadecimal digits or escape sequence <\U>
513 followed by six hexadecimal digits. Surrogate pairs
514 are always recognized as a single Unicode character.
515 The effect of invalid escape sequences is unspecified.
516
517 - List are represented by an open parenthesis <(>
518 followed by the space separated list elements,
519 followed by a closing parenthesis <)>.
520 When the cdr of the last pair is non zero,
521 the closed parenthesis is preceded by
522 a space, a dot <.>, a space, and the textual
523 representation of the cdr.
524
525 - When the parser encounters an ascii character corresponding
526 to a non zero function pointer in the macro character array,
527 the function is invoked and must return a possibly empty
528 list of miniexps to be returned by subsequent
529 invocations of the parser. The same process happens when
530 the parser encounters a dieze character followed by an
531 ascii character corresponding to a non zero function pointer
532 int the dieze character array. */
533
534
535 /* miniexp_pname --
536 Returns a string containing the textual representation
537 of a minilisp expression. Set argument <width> to zero
538 to output a single line, or to a positive value to
539 perform pretty line breaks for this intended number of columns.
540 This function can cause a garbage collection to occur. */
541
542 MINILISPAPI miniexp_t miniexp_pname(miniexp_t p, int width);
543
544
545 /* miniexp_io_t --
546 This structure is used to describe how to perform input/output
547 operations. Input/output operations are performed through function
548 pointers <fputs>, <fgetc>, and <ungetc>, which are similar to their
549 stdio counterparts. Variable <data> defines four pointers that can
550 be used as a closure by the I/O functions.
551 Variable <p_flags> optionally points to a flag word that customize the
552 printing operation. All ASCII control characters present in strings are
553 displayed using C escapes sequences. Flag <miniexp_io_print7bits> causes
554 all other non ASCII characters to be escaped. Flag <miniexp_io_u6escape>
555 and <miniexp_io_u4escape> respectively authorize using the long and
556 short utf8 escape sequences "\U" and "\u". Their absence may force
557 using surrogate short escape sequences or only octal sequences.
558 Flag <miniexp_io_quotemoresyms> causes the output code to also quote
559 all symbols that start with a digit or with a sign character followed
560 by another character.
561 When both <p_macrochar> and <p_macroqueue> are non zero, a non zero
562 entry in <p_macrochar[c]> defines a special parsing function that is called
563 when <miniexp_read_r> encounters the character <c> (in range 0 to 127.)
564 When both <p_diezechar> and <p_macroqueue> are non zero, a non zero entry
565 in <p_diezechar[c]> defines a special parsing function that is called when
566 <miniexp_read_r> encounters the character '#' followed by character <c> (in
567 range 0 to 127.) These parsing functions return a list of <miniexp_t> that
568 function <miniexp_read_r> returns one-by-one before processing more
569 input. This list is stored in the variable pointed by <io.p_macroqueue>.
570 */
571
572 typedef struct miniexp_io_s miniexp_io_t;
573 typedef miniexp_t (*miniexp_macrochar_t)(miniexp_io_t*);
574
575 struct miniexp_io_s
576 {
577 int (*fputs)(miniexp_io_t*, const char*);
578 int (*fgetc)(miniexp_io_t*);
579 int (*ungetc)(miniexp_io_t*, int);
580 void *data[4];
581 int *p_flags; /* previously named p_print7bits */
582 miniexp_macrochar_t *p_macrochar;
583 miniexp_macrochar_t *p_diezechar;
584 minivar_t *p_macroqueue;
585 minivar_t *p_reserved;
586 };
587
588 #define miniexp_io_print7bits 0x1
589 #define miniexp_io_u4escape 0x2
590 #define miniexp_io_u6escape 0x4
591 #define miniexp_io_quotemoresymbols 0x20
592
593 /* miniexp_io_init --
594 Initialize a default <miniexp_io_t> structure
595 that reads from stdin and prints to stdout.
596 Field <data[0]> is used to hold the stdin file pointer.
597 Field <data[1]> is used to hold the stdout file pointer.
598 Fields <p_flags>, <p_macrochar>, <p_diezechar>
599 and <p_macroqueue> are set to point to zero-initialized
600 shared variables. */
601
602 MINILISPAPI void miniexp_io_init(miniexp_io_t *io);
603
604 /* miniexp_io_set_{input,output} --
605 Override the file descriptor used for input or output.
606 You must call <miniexp_io_init> before. */
607
608 #if defined(stdin)
609 MINILISPAPI void miniexp_io_set_output(miniexp_io_t *io, FILE *f);
610 MINILISPAPI void miniexp_io_set_input(miniexp_io_t *io, FILE *f);
611 #endif
612
613 /* miniexp_read_r --
614 Reads an expression by repeatedly
615 invoking <minilisp_getc> and <minilisp_ungetc>.
616 Returns <miniexp_dummy> when an error occurs. */
617
618 MINILISPAPI miniexp_t miniexp_read_r(miniexp_io_t *io);
619
620 /* miniexp_prin_r, miniexp_print_r --
621 Prints a minilisp expression by repeatedly invoking <minilisp_puts>.
622 Only <minilisp_print> outputs a final newline character.
623 These functions are safe to call anytime. */
624
625 MINILISPAPI miniexp_t miniexp_prin_r(miniexp_io_t *io, miniexp_t p);
626 MINILISPAPI miniexp_t miniexp_print_r(miniexp_io_t *io, miniexp_t p);
627
628 /* miniexp_pprin_r, miniexp_pprint_r --
629 Prints a minilisp expression with reasonably pretty line breaks.
630 Argument <width> is the intended number of columns.
631 Only <minilisp_pprint> outputs a final newline character.
632 These functions can cause a garbage collection to occur. */
633
634 MINILISPAPI miniexp_t miniexp_pprin_r(miniexp_io_t *io, miniexp_t p, int w);
635 MINILISPAPI miniexp_t miniexp_pprint_r(miniexp_io_t *io, miniexp_t p, int w);
636
637 /* miniexp_io, miniexp_read, miniexp_{,p}prin{,t} --
638 Variable <miniexp_io> contains the pre-initialized input/output data
639 structure that is used by the non-reentrant input/output functions. */
640
641 extern MINILISPAPI miniexp_io_t miniexp_io;
642 MINILISPAPI miniexp_t miniexp_read(void);
643 MINILISPAPI miniexp_t miniexp_prin(miniexp_t p);
644 MINILISPAPI miniexp_t miniexp_print(miniexp_t p);
645 MINILISPAPI miniexp_t miniexp_pprin(miniexp_t p, int width);
646 MINILISPAPI miniexp_t miniexp_pprint(miniexp_t p, int width);
647
648
649 /* Backward compatibility (will eventually disappear) */
650 extern MINILISPAPI int (*minilisp_puts)(const char *);
651 extern MINILISPAPI int (*minilisp_getc)(void);
652 extern MINILISPAPI int (*minilisp_ungetc)(int);
653 extern MINILISPAPI miniexp_t (*minilisp_macrochar_parser[128])(void);
654 extern MINILISPAPI miniexp_t (*minilisp_diezechar_parser[128])(void);
655 extern MINILISPAPI miniexp_macrochar_t miniexp_macrochar[128];
656 extern MINILISPAPI minivar_t miniexp_macroqueue;
657 extern MINILISPAPI int minilisp_print_7bits;
658 #if defined(stdin)
659 MINILISPAPI void minilisp_set_output(FILE *f);
660 MINILISPAPI void minilisp_set_input(FILE *f);
661 #endif
662
663 /* -------------------------------------------------- */
664 /* STUFF FOR C++ ONLY */
665 /* -------------------------------------------------- */
666
667 #ifdef __cplusplus
668 # ifndef __cplusplus
669 {
670 # endif
671 } // extern "C"
672
673 typedef void minilisp_mark_t(miniexp_t *pp);
674
675 /* -------- MINIVARS -------- */
676
677 /* minivar_t --
678 A class for protected garbage collector variables. */
679
680 class MINILISPAPI
681 minivar_t
682 {
683 miniexp_t data;
684 minivar_t *next;
685 minivar_t **pprev;
686 public:
687 minivar_t();
688 minivar_t(miniexp_t p);
689 minivar_t(const minivar_t &v);
690 operator miniexp_t&() { return data; }
691 miniexp_t* operator&() { return &data; }
692 minivar_t& operator=(miniexp_t p) { data = p; return *this; }
693 minivar_t& operator=(const minivar_t &v) { data = v.data; return *this; }
694 ~minivar_t();
695 #ifdef MINIEXP_IMPLEMENTATION
696 static minivar_t *vars;
697 static void mark(minilisp_mark_t*);
698 #endif
699 };
700
701
702 /* -------- MINIOBJ -------- */
703
704
705 /* miniobj_t --
706 The base class for c++ objects
707 represented by object expressions. */
708
709 class MINILISPAPI
710 miniobj_t {
711 public:
712 virtual ~miniobj_t();
713
714 /* --- stuff defined by MINIOBJ_DECLARE --- */
715 /* classname: a symbol characterizing this class. */
716 static const miniexp_t classname;
717 /* classof: class name symbol for this object. */
718 virtual miniexp_t classof() const = 0;
719 /* isa -- tests if this is an instance of <classname>. */
720 virtual bool isa(miniexp_t classname) const;
721
722 /* --- optional stuff --- */
723 /* pname: returns a printable name for this object.
724 The caller must deallocate the result with delete[]. */
725 virtual char *pname() const;
726 /* stringp, doublep: tells whether this object should be
727 interpreted/printed as a generic string (for miniexp_strinp)
728 or a double (for miniexp_doublep). */
729 virtual bool stringp(const char* &s, size_t &l) const;
730 virtual bool doublep(double &d) const;
731 /* mark: calls action() on all member miniexps of the object,
732 for garbage collecting purposes. */
733 virtual void mark(minilisp_mark_t *action);
734 /* destroy: called by the garbage collector to
735 deallocate the object. Defaults to 'delete this'. */
736 virtual void destroy();
737
738 };
739
740 /* MINIOBJ_DECLARE --
741 MINIOBJ_IMPLEMENT --
742 Useful code fragments for implementing
743 the mandatory part of miniobj subclasses. */
744
745 #define MINIOBJ_DECLARE(cls, supercls, name) \
746 public: static const miniexp_t classname; \
747 virtual miniexp_t classof() const; \
748 virtual bool isa(miniexp_t) const;
749
750 #define MINIOBJ_IMPLEMENT(cls, supercls, name)\
751 const miniexp_t cls::classname = miniexp_symbol(name);\
752 miniexp_t cls::classof() const {\
753 return cls::classname; }\
754 bool cls::isa(miniexp_t n) const {\
755 return (cls::classname==n) || (supercls::isa(n)); }
756
757
758 /* miniexp_to_obj --
759 Returns a pointer to the object represented by an lisp
760 expression. Returns NULL if the expression is not an
761 object expression.
762 */
763
miniexp_to_obj(miniexp_t p)764 static inline miniobj_t *miniexp_to_obj(miniexp_t p) {
765 if (miniexp_objectp(p))
766 return ((miniobj_t**)(((size_t)p)&~((size_t)3)))[0];
767 return 0;
768 }
769
770 /* miniexp_object --
771 Create an object expression for a given object. */
772
773 MINILISPAPI miniexp_t miniexp_object(miniobj_t *obj);
774
775
776 /* miniexp_mutate --
777 Atomically modifies a member of a garbage collected object.
778 The object implementation must call this function to change
779 the contents of a member variable <v> of object <obj>.
780 Returns <p>*/
781
782 MINILISPAPI miniexp_t miniexp_mutate(miniexp_t obj, miniexp_t *v, miniexp_t p);
783
784
785 #endif /* __cplusplus */
786
787
788
789
790
791 /* -------------------------------------------------- */
792 /* THE END */
793 /* -------------------------------------------------- */
794
795 #endif /* MINIEXP_H */
796