/* Copyright 1989-93 GROUPE BULL -- See license conditions in file COPYRIGHT */
/**************************\
* *
* KlO Collection *
* BODY *
* *
\**************************/
#include "EXTERN.h"
#include "klone.h"
#include "kl_number.h"
#include "kl_atom.h"
#include "kl_list.h"
#include "kl_string.h"
#include "kl_stream.h"
#include "kl_func.h"
#include "INTERN.h"
#include "kl_coll.h"
#define INITIAL_COLLECTION_SIZE 7 /* initial size allocated in
* KlCollectionMake */
KlO KlCollectionRelease();
/*
* klcf (klone collection free)
*
* management of an stack of free collections to avoid calls to malloc
*/
#define KlCF_LIMIT 32
#if KlCF_LIMIT
static KlCollection klcf[KlCF_LIMIT];
#else
static KlCollection klcf[1];
#endif
static KlCollection *klcf_last = klcf;
static int klcf_size, klcf_limit = KlCF_LIMIT;
/* to be called once */
#ifdef STATS
KlO
KlCfstats()
{
KlPrintf("klone-coll-free (klcf) has %d", klcf_size);
KlPrintf("/%d slots\n", klcf_limit);
return NIL;
}
#endif /* STATS */
/* to release klcf */
KlCfFlush()
{
KlCollection *p = klcf_last - 1;
while (p >= klcf) {
KlCollectionRelease(*p);
p--;
}
klcf_size = 0;
klcf_last = klcf;
}
/* put in klcf */
KlO
KlCollectionFree(col)
KlCollection col;
{
if (klcf_size >= klcf_limit) {
KlCollectionRelease(col);
} else {
klcf_size++;
*klcf_last++ = col;
col->size = 0;
}
return (KlO) col;
}
/*
* Constructor:
* KlCollectionMake
* do a klcf_get in fact...
*/
KlCollection
KlCollectionMake()
{
KlCollection col;
if (klcf_size) {
col = *(--klcf_last);
klcf_size--;
KlZrtPut(col);
} else {
col = (KlCollection) KlOMake(KlCollectionType);
col->size = 0;
col->limit = INITIAL_COLLECTION_SIZE;
col->list = (KlO *) Malloc(col->limit * KLSO);
}
return col;
}
/*
* KlCollectionPrint:
* Normally, never to be called.
*/
KlO
KlCollectionPrint(obj, stream)
KlCollection obj;
KlO stream;
{
KlSequencePrint(obj, stream, "{ }");
return (KlO) obj;
}
/*
* KlCollectionFree
*/
KlO
KlCollectionRelease(col)
KlCollection col;
{
Free(col->list);
Free(col);
return (KlO) col;
}
/*
* KlCollectionAdd:
* Adds arg2 to arg1, just catenating if there is room, increasing limit
* of collection if not.
* (we know we have KLSO bytes of overhead, thats the reason for our
* growing scheme: )
* WARNING: since a KlZrtGc cannot occur during parsing, we do not set
* the reference count on the sons!
*/
KlCollection
KlCollectionAdd(col, obj)
KlCollection col;
KlO obj;
{
/* special case for Assigns: var = value
* if last elt of col is '=, create an assign, dont concat
*/
if ((col->size >= 2) && (col->list[col->size - 1] == (KlO) KlA_equal)
&& KlInfixAssigns) {
col->size--;
col->list[col->size - 1] = (KlO)
KlAssignMake(col->list[col->size - 1], obj);
return col;
}
if (col->size >= col->limit) {
col->limit = col->limit << 1 + 1;
col->list = (KlO *) Realloc(col->list, (col->limit) * KLSO);
}
*(col->list + (col->size)++) = obj;
return col;
}
/* evaluates a {<list>} on-line call
returns 0 in case of error
*/
KlO
KlCollectionEvalOnLine(col)
KlCollection col;
{
int normal;
KlO result;
if (KlQuoteInlines) {
KlList l = col->size ? KlListMake(col) : KlListNMake(0);
l->type = KlListInlineType;
return (KlO) l;
} else {
KlCatch(KlA_ALL, KlListEval(col), result, normal);
return (normal ? result : 0);
}
}
/*****************************************************************************\
* *
* QuotedExpr package for speeding up quoted constructs *
* *
\*****************************************************************************/
/* Quoted Expr are a subtype of lists
*/
KlQuotedExpr
KlAnyQuotedExprMake(symbol, expr, eval)
KlAtom symbol;
KlO expr;
KlMethod eval;
{
KlQuotedExpr object = (KlQuotedExpr) KlOMake(KlQuotedExprType);
KlIncRef(object->expr = expr);
object->symbol = symbol;
object->eval = eval;
object->size = 2;
object->list = (KlO *) &(object->symbol);
return (KlQuotedExpr) object;
}
KlO
KlQuotedExprCopy(obj)
KlQuotedExpr obj;
{
return (KlO) KlAnyQuotedExprMake(obj->symbol, obj->expr, obj->eval);
}
/* the generic eval method */
KlO
KlQuotedExprEval(obj)
KlQuotedExpr obj;
{
return (KlO) CFAPPLY(obj->eval, (obj->expr));
}
KlO
KlQuotedExprPrint(obj, stream)
KlQuotedExpr obj;
KlO stream;
{
KlSend_print(obj->symbol, stream);
KlSend_print(obj->expr, stream);
return (KlO) obj;
}
KlO
KlQuotedExprFree(obj)
KlQuotedExpr obj;
{
KlDecRef(obj->expr);
Free(obj);
return (KlO) obj;
}
/*ARGSUSED*/
KlO
KlQuotedExprPut(o, n, expr)
KlQuotedExpr o;
KlNumber n;
KlAtom expr;
{
if (KlIsANumber(n) && n->number == 0) { /* first arg = symbol */
KlMustBeAtom(expr, 2);
if ((KlIsASubr(expr->c_val) || KlIsAFSubr(expr->c_val))
&& ((KlSubr) expr->c_val)->arity == 1){
o->eval = ((KlSubr) expr->c_val)->body;
} else {
return KlError(KlE_NO_PUT, o);
}
} else { /* other = expr */
KlDecRef(o->expr);
KlIncRef(o->expr = (KlO) expr);
}
return (KlO) o;
}
/****************************************** specialized methods for ' ` , ,@ */
/* the eval method for ' : KlQuote */
KlO
KlQuote(obj)
KlO obj;
{
return obj;
}
/* the eval method for ` : KlBackquote */
/* backquoting:
* parses argument (must be list) and expands only (, foo) and (,@ foo)
* sublists
*/
KlO
KlBackquote(obj)
KlList obj;
{
KlList result;
int i, j;
KlO *p;
if (KlIsAList(obj)) { /* `(...) */
if (!obj->size) /* `() = () */
return (KlO) obj;
if (obj->list[0] == (KlO) KlA_unquote) /* `,a = a */
return KlSend_eval(obj->list[1]);
if (obj->list[0] == (KlO) KlA_backquote) /* ``a = `a */
return (KlO) obj;
KlListNMakeZ(result, (size_t) obj->size);
p = result->list;
for (i = 0; i < obj->size; i++) {
KlQuotedExpr l = (KlQuotedExpr) obj->list[i];
if (KlIsAQuotedExpr(l)) {
if (l->symbol == KlA_quote) { /* recurse into 'foo */
KlIncRef(*p++ = (KlO)
KlQuotedExprMake(KlBackquote(l->expr)));
} else if (l->symbol == KlA_unquote) { /* ,foo */
KlIncRef(*p++ = KlSend_eval(l->list[1]));
} else if (l->symbol == KlA_unquotesplicing) { /* ,@(foo) */
KlList el = (KlList) KlSend_eval(l->list[1]);
if (KlIsAList(el)) {
result->size += el->size - 1;
if (el->size > 1) {
int offset = p - result->list;
result->list = (KlO *)
Realloc(result->list, result->size
* sizeof(KlO));
p = result->list + offset;
}
for (j = 0; j < el->size; j++) {
KlIncRef(*p++ = el->list[j]);
}
} else { /* verbatim copy other objects */
KlIncRef(*p++ = (KlO) el);
}
} else if (l->symbol == KlA_backquote) { /* ``() */
KlIncRef(*p++ = (KlO) l);
} else {
KlIncRef(*p++ = (KlO) l); /* unknown quote char? */
}
} else if (KlIsAList(l) && l->size) { /* non-nil list */
KlIncRef(*p++ = KlBackquote(l));
} else { /* other KlOs */
KlIncRef(*p++ = (KlO) l);
}
}
if (obj->type != KlListType) {
if (obj->type == KlVectorType || obj->type == KlLocatorType)
result->type = obj->type; /* optim */
else /* regular case */
result = (KlList) KlCoerce(result, obj->type);
}
} else { /* `a = 'a */
return (KlO) obj;
}
return (KlO) result;
}
/* create a quoted expr from pair */
KlO
KlQuotedExprCoerce(totype, obj)
KlType totype;
KlList obj;
{
if (KlIsAList(obj) && obj->size == 2) {
KlAtom qc = (KlAtom) obj->list[0];
KlMethod func = 0;
if (qc == KlA_quote)
func = KlQuote;
else if (qc == KlA_backquote)
func = KlBackquote;
else if (qc == KlA_unquote)
func = KlQuotedExprCommaEval;
else if (qc == KlA_unquotesplicing)
func = KlQuotedExprCommaEval;
else
return 0;
return (KlO) KlAnyQuotedExprMake(qc, obj->list[1], func);
} else {
return 0;
}
}
/* the eval method for , and ,@ : error KlE_COMMA_OUTSIDE_BACKQUOTE */
KlO
KlQuotedExprCommaEval(obj)
KlO obj;
{
return KlError0(KlE_COMMA_OUTSIDE_BACKQUOTE);
}
/*****************************************************************************\
* TYPE INIT *
\*****************************************************************************/
KlCollectionInit()
{
KlDeclareSubType(&KlCollectionType, "Collection", KlListType,
sizeof(struct _KlCollection));
KlDeclareMethod1(KlCollectionType, KlSelPrint, KlCollectionPrint);
KlDeclareMethod1(KlCollectionType, KlSelFree, KlCollectionFree);
KlDeclareSubType(&KlQuotedExprType, "QuotedExpr", KlListType,
sizeof(struct _KlQuotedExpr));
KlDeclareMethod1(KlQuotedExprType, KlSelEval, KlQuotedExprEval);
KlDeclareMethod1(KlQuotedExprType, KlSelPrint, KlQuotedExprPrint);
KlDeclareMethod1(KlQuotedExprType, KlSelFree, KlQuotedExprFree);
KlDeclareMethod1(KlQuotedExprType, KlSelPut, KlQuotedExprPut);
KlDeclareMethod1(KlQuotedExprType, KlSelCopy, KlQuotedExprCopy);
KlDeclareMethodUndefined(KlQuotedExprType, KlSelInsert);
KlDeclareMethodUndefined(KlQuotedExprType, KlSelDelete);
}
syntax highlighted by Code2HTML, v. 0.9.1