|
Packit |
df99a1 |
/* -*- C -*-
|
|
Packit |
df99a1 |
// -------------------------------------------------------------------
|
|
Packit |
df99a1 |
// MiniExp - Library for handling lisp expressions
|
|
Packit |
df99a1 |
// Copyright (c) 2005 Leon Bottou
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// This software is subject to, and may be distributed under, the
|
|
Packit |
df99a1 |
// GNU General Public License, either Version 2 of the license,
|
|
Packit |
df99a1 |
// or (at your option) any later version. The license should have
|
|
Packit |
df99a1 |
// accompanied the software or you may obtain a copy of the license
|
|
Packit |
df99a1 |
// from the Free Software Foundation at http://www.fsf.org .
|
|
Packit |
df99a1 |
//
|
|
Packit |
df99a1 |
// This program is distributed in the hope that it will be useful,
|
|
Packit |
df99a1 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
df99a1 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
df99a1 |
// GNU General Public License for more details.
|
|
Packit |
df99a1 |
// -------------------------------------------------------------------
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef MINIEXP_H
|
|
Packit |
df99a1 |
#define MINIEXP_H
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef __cplusplus
|
|
Packit |
df99a1 |
extern "C" {
|
|
Packit |
df99a1 |
# ifndef __cplusplus
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef MINILISPAPI
|
|
Packit |
df99a1 |
# ifdef _WIN32
|
|
Packit |
df99a1 |
# ifdef MINILISPAPI_EXPORT
|
|
Packit |
df99a1 |
# define MINILISPAPI __declspec(dllexport)
|
|
Packit |
df99a1 |
# else
|
|
Packit |
df99a1 |
# define MINILISPAPI __declspec(dllimport)
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
#ifndef MINILISPAPI
|
|
Packit |
df99a1 |
# define MINILISPAPI /**/
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifndef __cplusplus
|
|
Packit |
df99a1 |
# ifndef inline
|
|
Packit |
df99a1 |
# if defined(__GNUC__)
|
|
Packit |
df99a1 |
# define inline __inline__
|
|
Packit |
df99a1 |
# elif defined(_MSC_VER)
|
|
Packit |
df99a1 |
# define inline __inline
|
|
Packit |
df99a1 |
# else
|
|
Packit |
df99a1 |
# define inline /**/
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#include <stddef.h>
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
/* LISP EXPRESSIONS */
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_t --
|
|
Packit |
df99a1 |
Opaque pointer type representing a lisp expression,
|
|
Packit |
df99a1 |
also known as s-expression.
|
|
Packit |
df99a1 |
S-expressions can be viewed as a simple and powerful
|
|
Packit |
df99a1 |
alternative to XML. DjVu uses s-expressions to handle
|
|
Packit |
df99a1 |
annotations. Both the decoding api <ddjvuapi.h> and
|
|
Packit |
df99a1 |
program <djvused> use s-expressions to describe the
|
|
Packit |
df99a1 |
hidden text information and the navigation
|
|
Packit |
df99a1 |
information */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
typedef struct miniexp_s* miniexp_t;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* There are four basic types of lisp expressions,
|
|
Packit |
df99a1 |
numbers, symbols, pairs, and objects.
|
|
Packit |
df99a1 |
The latter category can represent any c++ object
|
|
Packit |
df99a1 |
that inherits class <miniobj_t> defined later in this file.
|
|
Packit |
df99a1 |
Strings and floating point numbers are implemented this way.*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- NUMBERS -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Minilisp numbers represent integers
|
|
Packit |
df99a1 |
covering at least range [-2^29...2^29-1] */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_numberp --
|
|
Packit |
df99a1 |
Tests if an expression is a number. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_numberp(miniexp_t p) {
|
|
Packit |
df99a1 |
return (((size_t)(p)&3)==3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_to_int --
|
|
Packit |
df99a1 |
Returns the integer corresponding to a lisp expression.
|
|
Packit |
df99a1 |
Assume that the expression is indeed a number. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_to_int(miniexp_t p) {
|
|
Packit |
df99a1 |
return (((int)(size_t)(p))>>2);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_number --
|
|
Packit |
df99a1 |
Constructs the expression corresponding to an integer. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline miniexp_t miniexp_number(int x) {
|
|
Packit |
df99a1 |
return (miniexp_t) (size_t) ((x<<2)|3);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- SYMBOLS -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* The textual representation of a minilisp symbol is a
|
|
Packit |
df99a1 |
sequence of printable characters forming an identifier.
|
|
Packit |
df99a1 |
Each symbol has a unique representation and remain
|
|
Packit |
df99a1 |
permanently allocated. To compare two symbols,
|
|
Packit |
df99a1 |
simply compare the <miniexp_t> pointers. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_symbolp --
|
|
Packit |
df99a1 |
Tests if an expression is a symbol. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_symbolp(miniexp_t p) {
|
|
Packit |
df99a1 |
return ((((size_t)p)&3)==2);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_to_name --
|
|
Packit |
df99a1 |
Returns the symbol name as a string.
|
|
Packit |
df99a1 |
Returns NULL if the expression is not a symbol. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI const char* miniexp_to_name(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_symbol --
|
|
Packit |
df99a1 |
Returns the unique symbol expression with the specified name. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_symbol(const char *name);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- PAIRS -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Pairs (also named "cons") are the basic building blocks for
|
|
Packit |
df99a1 |
minilisp lists. Each pair contains two expression:
|
|
Packit |
df99a1 |
- the <car> represents the first element of a list.
|
|
Packit |
df99a1 |
- the <cdr> usually is a pair representing the rest of the list.
|
|
Packit |
df99a1 |
The empty list is represented by a null pointer. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_nil --
|
|
Packit |
df99a1 |
The empty list. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define miniexp_nil ((miniexp_t)(size_t)0)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_dummy --
|
|
Packit |
df99a1 |
An invalid expression used to represent
|
|
Packit |
df99a1 |
various exceptional conditions. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define miniexp_dummy ((miniexp_t)(size_t)2)
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_listp --
|
|
Packit |
df99a1 |
Tests if an expression is either a pair or the empty list. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_listp(miniexp_t p) {
|
|
Packit |
df99a1 |
return ((((size_t)p)&3)==0);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_consp --
|
|
Packit |
df99a1 |
Tests if an expression is a pair. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_consp(miniexp_t p) {
|
|
Packit |
df99a1 |
return p && miniexp_listp(p);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_length --
|
|
Packit |
df99a1 |
Returns the length of a list.
|
|
Packit |
df99a1 |
Returns 0 for non lists, -1 for circular lists. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI int miniexp_length(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_car --
|
|
Packit |
df99a1 |
miniexp_cdr --
|
|
Packit |
df99a1 |
Returns the car or cdr of a pair. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline miniexp_t miniexp_car(miniexp_t p) {
|
|
Packit |
df99a1 |
if (miniexp_consp(p))
|
|
Packit |
df99a1 |
return ((miniexp_t*)p)[0];
|
|
Packit |
df99a1 |
return miniexp_nil;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline miniexp_t miniexp_cdr(miniexp_t p) {
|
|
Packit |
df99a1 |
if (miniexp_consp(p))
|
|
Packit |
df99a1 |
return ((miniexp_t*)p)[1];
|
|
Packit |
df99a1 |
return miniexp_nil;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_cXXr --
|
|
Packit |
df99a1 |
Represent common combinations of car and cdr. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_caar (miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_cadr (miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_cdar (miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_cddr (miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_caddr(miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_cdddr(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_nth --
|
|
Packit |
df99a1 |
Returns the n-th element of a list. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_nth(int n, miniexp_t l);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_cons --
|
|
Packit |
df99a1 |
Constructs a pair. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_cons(miniexp_t car, miniexp_t cdr);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_rplaca --
|
|
Packit |
df99a1 |
miniexp_rplacd --
|
|
Packit |
df99a1 |
Changes the car or the cdr of a pair. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_rplaca(miniexp_t pair, miniexp_t newcar);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_rplacd(miniexp_t pair, miniexp_t newcdr);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_reverse --
|
|
Packit |
df99a1 |
Reverses a list in place. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_reverse(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- OBJECTS (GENERIC) -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Object expressions represent a c++ object
|
|
Packit |
df99a1 |
that inherits class <miniobj_t> defined later.
|
|
Packit |
df99a1 |
Each object expression has a symbolic class name
|
|
Packit |
df99a1 |
and a pointer to the c++ object. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_objectp --
|
|
Packit |
df99a1 |
Tests if an expression is an object. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_objectp(miniexp_t p) {
|
|
Packit |
df99a1 |
return ((((size_t)p)&3)==1);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_classof --
|
|
Packit |
df99a1 |
Returns the symbolic class of an expression.
|
|
Packit |
df99a1 |
Returns nil if the expression is not an object. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_classof(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_isa --
|
|
Packit |
df99a1 |
If is an instance of class named <c> or one of
|
|
Packit |
df99a1 |
its subclasses, returns the actual class name.
|
|
Packit |
df99a1 |
Otherwise returns miniexp_nil. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_isa(miniexp_t p, miniexp_t c);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- OBJECTS (STRINGS) -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_stringp --
|
|
Packit |
df99a1 |
Tests if an expression is a string. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI int miniexp_stringp(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_to_str --
|
|
Packit |
df99a1 |
Returns the c string represented by the expression.
|
|
Packit |
df99a1 |
Returns NULL if the expression is not a string.
|
|
Packit |
df99a1 |
The c string remains valid as long as the
|
|
Packit |
df99a1 |
corresponding lisp object exists. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI const char *miniexp_to_str(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_string --
|
|
Packit |
df99a1 |
Constructs a string expression by copying string s. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_string(const char *s);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_substring --
|
|
Packit |
df99a1 |
Constructs a string expression by copying
|
|
Packit |
df99a1 |
at most n character from string s. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_substring(const char *s, int n);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_concat --
|
|
Packit |
df99a1 |
Concat all the string expressions in list <l>. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_concat(miniexp_t l);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- OBJECTS (FLOATNUM) -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_floatnump --
|
|
Packit |
df99a1 |
Tests if an expression is an object
|
|
Packit |
df99a1 |
representing a floating point number. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI int miniexp_floatnump(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_floatnum --
|
|
Packit |
df99a1 |
Returns a new floating point number object. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_floatnum(double x);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_doublep --
|
|
Packit |
df99a1 |
Tests if an expression can be converted
|
|
Packit |
df99a1 |
to a double precision number. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline int miniexp_doublep(miniexp_t p) {
|
|
Packit |
df99a1 |
return miniexp_numberp(p) || miniexp_floatnump(p);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_to_double --
|
|
Packit |
df99a1 |
Returns a double precision number corresponding to
|
|
Packit |
df99a1 |
a lisp expression (a number or a floatnum.) */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI double miniexp_to_double(miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_double --
|
|
Packit |
df99a1 |
Returns a lisp expression representing a double
|
|
Packit |
df99a1 |
precision number. This will be a number if it fits
|
|
Packit |
df99a1 |
and a floatnum otherwise.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_double(double x);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
/* GARBAGE COLLECTION */
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* The garbage collector reclaims the memory allocated for
|
|
Packit |
df99a1 |
lisp expressions no longer in use. It is automatically
|
|
Packit |
df99a1 |
invoked by the pair and object allocation functions when
|
|
Packit |
df99a1 |
the available memory runs low. It is however possible to
|
|
Packit |
df99a1 |
temporarily disable it.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
The trick is to determine which lisp expressions are in
|
|
Packit |
df99a1 |
use at a given moment. This package takes a simplistic
|
|
Packit |
df99a1 |
approach. All objects of type <minivar_t> are chained and
|
|
Packit |
df99a1 |
can reference an arbitrary lisp expression. Garbage
|
|
Packit |
df99a1 |
collection preserves all lisp expressions referenced by a
|
|
Packit |
df99a1 |
minivar, as well as all lisp expressions that can be
|
|
Packit |
df99a1 |
accessed from these. When called automatically,
|
|
Packit |
df99a1 |
garbage collection also preserves the sixteen most recently
|
|
Packit |
df99a1 |
created miniexps in order to make sure that temporaries do
|
|
Packit |
df99a1 |
not vanish in the middle of complicated C expressions.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
The minivar class is designed such that C++ program can
|
|
Packit |
df99a1 |
directly use instances of <minivar_t> as normal
|
|
Packit |
df99a1 |
<miniexp_t> variables. There is almost no overhead
|
|
Packit |
df99a1 |
accessing or changing the lisp expression referenced by a
|
|
Packit |
df99a1 |
minivar. However, the minivar chain must be updated
|
|
Packit |
df99a1 |
whenever the minivar object is constructed or destructed.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Example (in C++ only):
|
|
Packit |
df99a1 |
miniexp_t copy_in_reverse(miniexp_t p) {
|
|
Packit |
df99a1 |
minivar_t l = miniexp_nil;
|
|
Packit |
df99a1 |
while (miniexp_consp(p)) {
|
|
Packit |
df99a1 |
l = miniexp_cons(miniexp_car(p), l);
|
|
Packit |
df99a1 |
p = miniexp_cdr(p);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return l;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
When to use minivar_t instead of miniexp_t?
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
* A function that only navigates properly secured
|
|
Packit |
df99a1 |
s-expressions without modifying them does not need to
|
|
Packit |
df99a1 |
bother about minivars.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
* Only the following miniexp functions can cause a
|
|
Packit |
df99a1 |
garbage collection: miniexp_cons(), miniexp_object(),
|
|
Packit |
df99a1 |
miniexp_string(), miniexp_substring(), miniexp_pname(),
|
|
Packit |
df99a1 |
miniexp_concat(), miniexp_pprin(), miniexp_pprint(),
|
|
Packit |
df99a1 |
miniexp_gc(), and minilisp_release_gc_lock(). A
|
|
Packit |
df99a1 |
function that does not cause calls to these functions
|
|
Packit |
df99a1 |
does not need to bother about minivars.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
* Other functions should make sure that all useful
|
|
Packit |
df99a1 |
s-expression are directly or indirectly secured by a
|
|
Packit |
df99a1 |
minivar_t object. In case of doubt, use minivars
|
|
Packit |
df99a1 |
everywhere.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
* Function arguments should remain <miniexp_t> in order
|
|
Packit |
df99a1 |
to allow interoperability with the C language.
|
|
Packit |
df99a1 |
It is assumed that these arguments have been properly
|
|
Packit |
df99a1 |
secured by the caller and cannot disappear if a
|
|
Packit |
df99a1 |
garbage collection occurs.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
C programs cannot use minivars as easily as C++ programs.
|
|
Packit |
df99a1 |
Wrappers are provided to allocate minivars and to access
|
|
Packit |
df99a1 |
their value. This is somehow inconvenient. It might be
|
|
Packit |
df99a1 |
more practical to control the garbage collector
|
|
Packit |
df99a1 |
invocations with <minilisp_acquire_gc_lock()> and
|
|
Packit |
df99a1 |
<minilisp_release_gc_lock()>... */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minilisp_gc --
|
|
Packit |
df99a1 |
Invokes the garbage collector now. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_gc(void);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minilisp_info --
|
|
Packit |
df99a1 |
Prints garbage collector statistics. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_info(void);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minilisp_acquire_gc_lock --
|
|
Packit |
df99a1 |
minilisp_release_gc_lock --
|
|
Packit |
df99a1 |
Temporarily disables automatic garbage collection.
|
|
Packit |
df99a1 |
Acquire/release pairs may be nested.
|
|
Packit |
df99a1 |
Both functions return their argument unmodified.
|
|
Packit |
df99a1 |
This is practical because <minilisp_release_gc_lock>
|
|
Packit |
df99a1 |
can invoke the garbage collector. Before doing
|
|
Packit |
df99a1 |
so it stores its argument in a minivar to
|
|
Packit |
df99a1 |
preserve it.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Example (in C):
|
|
Packit |
df99a1 |
miniexp_t copy_in_reverse(miniexp_t p) {
|
|
Packit |
df99a1 |
miniexp_t l = 0;
|
|
Packit |
df99a1 |
minilisp_acquire_gc_lock(0);
|
|
Packit |
df99a1 |
while (miniexp_consp(p)) {
|
|
Packit |
df99a1 |
l = miniexp_cons(miniexp_car(p), l);
|
|
Packit |
df99a1 |
p = miniexp_cdr(p);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
return minilisp_release_gc_lock(l);
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
Disabling garbage collection for a long time
|
|
Packit |
df99a1 |
increases the memory consumption. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t minilisp_acquire_gc_lock(miniexp_t);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t minilisp_release_gc_lock(miniexp_t);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minivar_t --
|
|
Packit |
df99a1 |
The minivar type. */
|
|
Packit |
df99a1 |
#ifdef __cplusplus
|
|
Packit |
df99a1 |
class minivar_t;
|
|
Packit |
df99a1 |
#else
|
|
Packit |
df99a1 |
typedef struct minivar_s minivar_t;
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minivar_alloc --
|
|
Packit |
df99a1 |
minivar_free --
|
|
Packit |
df99a1 |
Wrappers for creating and destroying minivars in C. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI minivar_t *minivar_alloc(void);
|
|
Packit |
df99a1 |
MINILISPAPI void minivar_free(minivar_t *v);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minivar_pointer --
|
|
Packit |
df99a1 |
Wrappers to access the lisp expression referenced
|
|
Packit |
df99a1 |
by a minivar. This function returns a pointer
|
|
Packit |
df99a1 |
to the actual miniexp_t variable. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t *minivar_pointer(minivar_t *v);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minilisp_debug --
|
|
Packit |
df99a1 |
Setting the debug flag runs the garbage collector
|
|
Packit |
df99a1 |
very often. This is extremely slow, but can be
|
|
Packit |
df99a1 |
useful to debug memory allocation problems. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_debug(int debugflag);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minilisp_finish --
|
|
Packit |
df99a1 |
Deallocates everything. This is only useful when using
|
|
Packit |
df99a1 |
development tools designed to check for memory leaks.
|
|
Packit |
df99a1 |
No miniexp function can be used after calling this. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_finish(void);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
/* INPUT/OUTPUT */
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Notes about the textual representation of miniexps.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- Special characters are:
|
|
Packit |
df99a1 |
* the parenthesis <(> and <)>,
|
|
Packit |
df99a1 |
* the double quote <">,
|
|
Packit |
df99a1 |
* the vertical bar <|>,
|
|
Packit |
df99a1 |
* any other ascii character with a non zero entry
|
|
Packit |
df99a1 |
in the macro character array.
|
|
Packit |
df99a1 |
* the dieze character <#>, when followed by another
|
|
Packit |
df99a1 |
dieze or by an ascii character with a non zero entry
|
|
Packit |
df99a1 |
in the dieze character array.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- Symbols are represented by their name.
|
|
Packit |
df99a1 |
Symbols whose name contains blanks, special characters,
|
|
Packit |
df99a1 |
non printable characters, non ascii characters,
|
|
Packit |
df99a1 |
or can be confused for a number are delimited
|
|
Packit |
df99a1 |
by vertical bars <|> and can contain two consecutive
|
|
Packit |
df99a1 |
vertical bars to represent a single vertical bar character.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- Numbers follow the syntax specified by the C
|
|
Packit |
df99a1 |
function strtol() with base=0, but are required
|
|
Packit |
df99a1 |
to start with a digit or with a sign character
|
|
Packit |
df99a1 |
followed by another character.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- Floating point follow the syntax specified by the C
|
|
Packit |
df99a1 |
function strtod() with base=0, but are required
|
|
Packit |
df99a1 |
to start with a digit or with a sign character
|
|
Packit |
df99a1 |
followed by another character.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- Strings are delimited by double quotes.
|
|
Packit |
df99a1 |
All non printable ASCII characters must be escaped.
|
|
Packit |
df99a1 |
Besides all the usual C string escape sequences,
|
|
Packit |
df99a1 |
UTF8-encoded Unicode characters in range 0..0x10ffff
|
|
Packit |
df99a1 |
can be represented by escape sequence <\u> followed
|
|
Packit |
df99a1 |
by four hexadecimal digits or escape sequence <\U>
|
|
Packit |
df99a1 |
followed by six hexadecimal digits. Surrogate pairs
|
|
Packit |
df99a1 |
are always recognized as a single Unicode character.
|
|
Packit |
df99a1 |
The effect of invalid escape sequences is unspecified.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- List are represented by an open parenthesis <(>
|
|
Packit |
df99a1 |
followed by the space separated list elements,
|
|
Packit |
df99a1 |
followed by a closing parenthesis <)>.
|
|
Packit |
df99a1 |
When the cdr of the last pair is non zero,
|
|
Packit |
df99a1 |
the closed parenthesis is preceded by
|
|
Packit |
df99a1 |
a space, a dot <.>, a space, and the textual
|
|
Packit |
df99a1 |
representation of the cdr.
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
- When the parser encounters an ascii character corresponding
|
|
Packit |
df99a1 |
to a non zero function pointer in the macro character array,
|
|
Packit |
df99a1 |
the function is invoked and must return a possibly empty
|
|
Packit |
df99a1 |
list of miniexps to be returned by subsequent
|
|
Packit |
df99a1 |
invocations of the parser. The same process happens when
|
|
Packit |
df99a1 |
the parser encounters a dieze character followed by an
|
|
Packit |
df99a1 |
ascii character corresponding to a non zero function pointer
|
|
Packit |
df99a1 |
int the dieze character array. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_pname --
|
|
Packit |
df99a1 |
Returns a string containing the textual representation
|
|
Packit |
df99a1 |
of a minilisp expression. Set argument <width> to zero
|
|
Packit |
df99a1 |
to output a single line, or to a positive value to
|
|
Packit |
df99a1 |
perform pretty line breaks for this intended number of columns.
|
|
Packit |
df99a1 |
This function can cause a garbage collection to occur. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_pname(miniexp_t p, int width);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_io_t --
|
|
Packit |
df99a1 |
This structure is used to describe how to perform input/output
|
|
Packit |
df99a1 |
operations. Input/output operations are performed through function
|
|
Packit |
df99a1 |
pointers <fputs>, <fgetc>, and <ungetc>, which are similar to their
|
|
Packit |
df99a1 |
stdio counterparts. Variable <data> defines four pointers that can
|
|
Packit |
df99a1 |
be used as a closure by the I/O functions.
|
|
Packit |
df99a1 |
Variable <p_flags> optionally points to a flag word that customize the
|
|
Packit |
df99a1 |
printing operation. All ASCII control characters present in strings are
|
|
Packit |
df99a1 |
displayed using C escapes sequences. Flag <miniexp_io_print7bits> causes
|
|
Packit |
df99a1 |
all other non ASCII characters to be escaped. Flag <miniexp_io_u6escape>
|
|
Packit |
df99a1 |
and <miniexp_io_u4escape> respectively authorize using the long and
|
|
Packit |
df99a1 |
short utf8 escape sequences "\U" and "\u". Their absence may force
|
|
Packit |
df99a1 |
using surrogate short escape sequences or only octal sequences.
|
|
Packit |
df99a1 |
Flag <miniexp_io_quotemoresyms> causes the output code to also quote
|
|
Packit |
df99a1 |
all symbols that start with a digit or with a sign character followed
|
|
Packit |
df99a1 |
by another character.
|
|
Packit |
df99a1 |
When both <p_macrochar> and <p_macroqueue> are non zero, a non zero
|
|
Packit |
df99a1 |
entry in <p_macrochar[c]> defines a special parsing function that is called
|
|
Packit |
df99a1 |
when <miniexp_read_r> encounters the character <c> (in range 0 to 127.)
|
|
Packit |
df99a1 |
When both <p_diezechar> and <p_macroqueue> are non zero, a non zero entry
|
|
Packit |
df99a1 |
in <p_diezechar[c]> defines a special parsing function that is called when
|
|
Packit |
df99a1 |
<miniexp_read_r> encounters the character '#' followed by character <c> (in
|
|
Packit |
df99a1 |
range 0 to 127.) These parsing functions return a list of <miniexp_t> that
|
|
Packit |
df99a1 |
function <miniexp_read_r> returns one-by-one before processing more
|
|
Packit |
df99a1 |
input. This list is stored in the variable pointed by <io.p_macroqueue>.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
typedef struct miniexp_io_s miniexp_io_t;
|
|
Packit |
df99a1 |
typedef miniexp_t (*miniexp_macrochar_t)(miniexp_io_t*);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
struct miniexp_io_s
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
int (*fputs)(miniexp_io_t*, const char*);
|
|
Packit |
df99a1 |
int (*fgetc)(miniexp_io_t*);
|
|
Packit |
df99a1 |
int (*ungetc)(miniexp_io_t*, int);
|
|
Packit |
df99a1 |
void *data[4];
|
|
Packit |
df99a1 |
int *p_flags; /* previously named p_print7bits */
|
|
Packit |
df99a1 |
miniexp_macrochar_t *p_macrochar;
|
|
Packit |
df99a1 |
miniexp_macrochar_t *p_diezechar;
|
|
Packit |
df99a1 |
minivar_t *p_macroqueue;
|
|
Packit |
df99a1 |
minivar_t *p_reserved;
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define miniexp_io_print7bits 0x1
|
|
Packit |
df99a1 |
#define miniexp_io_u4escape 0x2
|
|
Packit |
df99a1 |
#define miniexp_io_u6escape 0x4
|
|
Packit |
df99a1 |
#define miniexp_io_quotemoresymbols 0x20
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_io_init --
|
|
Packit |
df99a1 |
Initialize a default <miniexp_io_t> structure
|
|
Packit |
df99a1 |
that reads from stdin and prints to stdout.
|
|
Packit |
df99a1 |
Field <data[0]> is used to hold the stdin file pointer.
|
|
Packit |
df99a1 |
Field <data[1]> is used to hold the stdout file pointer.
|
|
Packit |
df99a1 |
Fields <p_flags>, <p_macrochar>, <p_diezechar>
|
|
Packit |
df99a1 |
and <p_macroqueue> are set to point to zero-initialized
|
|
Packit |
df99a1 |
shared variables. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI void miniexp_io_init(miniexp_io_t *io);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_io_set_{input,output} --
|
|
Packit |
df99a1 |
Override the file descriptor used for input or output.
|
|
Packit |
df99a1 |
You must call <miniexp_io_init> before. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#if defined(stdin)
|
|
Packit |
df99a1 |
MINILISPAPI void miniexp_io_set_output(miniexp_io_t *io, FILE *f);
|
|
Packit |
df99a1 |
MINILISPAPI void miniexp_io_set_input(miniexp_io_t *io, FILE *f);
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_read_r --
|
|
Packit |
df99a1 |
Reads an expression by repeatedly
|
|
Packit |
df99a1 |
invoking <minilisp_getc> and <minilisp_ungetc>.
|
|
Packit |
df99a1 |
Returns <miniexp_dummy> when an error occurs. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_read_r(miniexp_io_t *io);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_prin_r, miniexp_print_r --
|
|
Packit |
df99a1 |
Prints a minilisp expression by repeatedly invoking <minilisp_puts>.
|
|
Packit |
df99a1 |
Only <minilisp_print> outputs a final newline character.
|
|
Packit |
df99a1 |
These functions are safe to call anytime. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_prin_r(miniexp_io_t *io, miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_print_r(miniexp_io_t *io, miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_pprin_r, miniexp_pprint_r --
|
|
Packit |
df99a1 |
Prints a minilisp expression with reasonably pretty line breaks.
|
|
Packit |
df99a1 |
Argument <width> is the intended number of columns.
|
|
Packit |
df99a1 |
Only <minilisp_pprint> outputs a final newline character.
|
|
Packit |
df99a1 |
These functions can cause a garbage collection to occur. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_pprin_r(miniexp_io_t *io, miniexp_t p, int w);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_pprint_r(miniexp_io_t *io, miniexp_t p, int w);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_io, miniexp_read, miniexp_{,p}prin{,t} --
|
|
Packit |
df99a1 |
Variable <miniexp_io> contains the pre-initialized input/output data
|
|
Packit |
df99a1 |
structure that is used by the non-reentrant input/output functions. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
extern MINILISPAPI miniexp_io_t miniexp_io;
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_read(void);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_prin(miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_print(miniexp_t p);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_pprin(miniexp_t p, int width);
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_pprint(miniexp_t p, int width);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* Backward compatibility (will eventually disappear) */
|
|
Packit |
df99a1 |
extern MINILISPAPI int (*minilisp_puts)(const char *);
|
|
Packit |
df99a1 |
extern MINILISPAPI int (*minilisp_getc)(void);
|
|
Packit |
df99a1 |
extern MINILISPAPI int (*minilisp_ungetc)(int);
|
|
Packit |
df99a1 |
extern MINILISPAPI miniexp_t (*minilisp_macrochar_parser[128])(void);
|
|
Packit |
df99a1 |
extern MINILISPAPI miniexp_t (*minilisp_diezechar_parser[128])(void);
|
|
Packit |
df99a1 |
extern MINILISPAPI miniexp_macrochar_t miniexp_macrochar[128];
|
|
Packit |
df99a1 |
extern MINILISPAPI minivar_t miniexp_macroqueue;
|
|
Packit |
df99a1 |
extern MINILISPAPI int minilisp_print_7bits;
|
|
Packit |
df99a1 |
#if defined(stdin)
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_set_output(FILE *f);
|
|
Packit |
df99a1 |
MINILISPAPI void minilisp_set_input(FILE *f);
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
/* STUFF FOR C++ ONLY */
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#ifdef __cplusplus
|
|
Packit |
df99a1 |
# ifndef __cplusplus
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
# endif
|
|
Packit |
df99a1 |
} // extern "C"
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
typedef void minilisp_mark_t(miniexp_t *pp);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- MINIVARS -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* minivar_t --
|
|
Packit |
df99a1 |
A class for protected garbage collector variables. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class MINILISPAPI
|
|
Packit |
df99a1 |
minivar_t
|
|
Packit |
df99a1 |
{
|
|
Packit |
df99a1 |
miniexp_t data;
|
|
Packit |
df99a1 |
minivar_t *next;
|
|
Packit |
df99a1 |
minivar_t **pprev;
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
minivar_t();
|
|
Packit |
df99a1 |
minivar_t(miniexp_t p);
|
|
Packit |
df99a1 |
minivar_t(const minivar_t &v);
|
|
Packit |
df99a1 |
operator miniexp_t&() { return data; }
|
|
Packit |
df99a1 |
miniexp_t* operator&() { return &dat;; }
|
|
Packit |
df99a1 |
minivar_t& operator=(miniexp_t p) { data = p; return *this; }
|
|
Packit |
df99a1 |
minivar_t& operator=(const minivar_t &v) { data = v.data; return *this; }
|
|
Packit |
df99a1 |
~minivar_t();
|
|
Packit |
df99a1 |
#ifdef MINIEXP_IMPLEMENTATION
|
|
Packit |
df99a1 |
static minivar_t *vars;
|
|
Packit |
df99a1 |
static void mark(minilisp_mark_t*);
|
|
Packit |
df99a1 |
#endif
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------- MINIOBJ -------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniobj_t --
|
|
Packit |
df99a1 |
The base class for c++ objects
|
|
Packit |
df99a1 |
represented by object expressions. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
class MINILISPAPI
|
|
Packit |
df99a1 |
miniobj_t {
|
|
Packit |
df99a1 |
public:
|
|
Packit |
df99a1 |
virtual ~miniobj_t();
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* --- stuff defined by MINIOBJ_DECLARE --- */
|
|
Packit |
df99a1 |
/* classname: a symbol characterizing this class. */
|
|
Packit |
df99a1 |
static const miniexp_t classname;
|
|
Packit |
df99a1 |
/* classof: class name symbol for this object. */
|
|
Packit |
df99a1 |
virtual miniexp_t classof() const = 0;
|
|
Packit |
df99a1 |
/* isa -- tests if this is an instance of <classname>. */
|
|
Packit |
df99a1 |
virtual bool isa(miniexp_t classname) const;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* --- optional stuff --- */
|
|
Packit |
df99a1 |
/* pname: returns a printable name for this object.
|
|
Packit |
df99a1 |
The caller must deallocate the result with delete[]. */
|
|
Packit |
df99a1 |
virtual char *pname() const;
|
|
Packit |
df99a1 |
/* mark: calls action() on all member miniexps of the object,
|
|
Packit |
df99a1 |
for garbage collecting purposes. */
|
|
Packit |
df99a1 |
virtual void mark(minilisp_mark_t *action);
|
|
Packit |
df99a1 |
/* destroy: called by the garbage collector to
|
|
Packit |
df99a1 |
deallocate the object. Defaults to 'delete this'. */
|
|
Packit |
df99a1 |
virtual void destroy();
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
};
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* MINIOBJ_DECLARE --
|
|
Packit |
df99a1 |
MINIOBJ_IMPLEMENT --
|
|
Packit |
df99a1 |
Useful code fragments for implementing
|
|
Packit |
df99a1 |
the mandatory part of miniobj subclasses. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define MINIOBJ_DECLARE(cls, supercls, name) \
|
|
Packit |
df99a1 |
public: static const miniexp_t classname; \
|
|
Packit |
df99a1 |
virtual miniexp_t classof() const; \
|
|
Packit |
df99a1 |
virtual bool isa(miniexp_t) const;
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#define MINIOBJ_IMPLEMENT(cls, supercls, name)\
|
|
Packit |
df99a1 |
const miniexp_t cls::classname = miniexp_symbol(name);\
|
|
Packit |
df99a1 |
miniexp_t cls::classof() const {\
|
|
Packit |
df99a1 |
return cls::classname; }\
|
|
Packit |
df99a1 |
bool cls::isa(miniexp_t n) const {\
|
|
Packit |
df99a1 |
return (cls::classname==n) || (supercls::isa(n)); }
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_to_obj --
|
|
Packit |
df99a1 |
Returns a pointer to the object represented by an lisp
|
|
Packit |
df99a1 |
expression. Returns NULL if the expression is not an
|
|
Packit |
df99a1 |
object expression.
|
|
Packit |
df99a1 |
*/
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
static inline miniobj_t *miniexp_to_obj(miniexp_t p) {
|
|
Packit |
df99a1 |
if (miniexp_objectp(p))
|
|
Packit |
df99a1 |
return ((miniobj_t**)(((size_t)p)&~((size_t)3)))[0];
|
|
Packit |
df99a1 |
return 0;
|
|
Packit |
df99a1 |
}
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_object --
|
|
Packit |
df99a1 |
Create an object expression for a given object. */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_object(miniobj_t *obj);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* miniexp_mutate --
|
|
Packit |
df99a1 |
Atomically modifies a member of a garbage collected object.
|
|
Packit |
df99a1 |
The object implementation must call this function to change
|
|
Packit |
df99a1 |
the contents of a member variable <v> of object <obj>.
|
|
Packit |
df99a1 |
Returns */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
MINILISPAPI miniexp_t miniexp_mutate(miniexp_t obj, miniexp_t *v, miniexp_t p);
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#endif /* __cplusplus */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
/* THE END */
|
|
Packit |
df99a1 |
/* -------------------------------------------------- */
|
|
Packit |
df99a1 |
|
|
Packit |
df99a1 |
#endif /* MINIEXP_H */
|