qse/ase/lsp/mem.c

723 lines
17 KiB
C
Raw Normal View History

2005-09-18 11:34:35 +00:00
/*
2006-10-23 10:57:59 +00:00
* $Id: mem.c,v 1.9 2006-10-23 10:57:59 bacon Exp $
2005-09-18 11:34:35 +00:00
*/
2006-10-22 13:10:46 +00:00
#include <sse/lsp/mem.h>
#include <sse/lsp/prim.h>
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
#include <sse/bas/memory.h>
#include <sse/bas/string.h>
#include <sse/bas/assert.h>
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_lsp_mem_t* sse_lsp_mem_new (sse_size_t ubound, sse_size_t ubound_inc)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_mem_t* mem;
sse_size_t i;
2005-09-18 11:34:35 +00:00
// allocate memory
2006-10-23 10:57:59 +00:00
mem = (sse_lsp_mem_t*) sse_malloc (sse_sizeof(sse_lsp_mem_t));
2006-10-22 13:10:46 +00:00
if (mem == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
// create a new root environment frame
2006-10-22 13:10:46 +00:00
mem->frame = sse_lsp_frame_new ();
if (mem->frame == SSE_NULL) {
sse_free (mem);
return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
mem->root_frame = mem->frame;
2006-10-22 13:10:46 +00:00
mem->brooding_frame = SSE_NULL;
2005-09-18 11:34:35 +00:00
// create an array to hold temporary objects
2006-10-22 13:10:46 +00:00
mem->temp_array = sse_lsp_array_new (512);
if (mem->temp_array == SSE_NULL) {
sse_lsp_frame_free (mem->frame);
sse_free (mem);
return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
// initialize object allocation list
mem->ubound = ubound;
mem->ubound_inc = ubound_inc;
mem->count = 0;
2006-10-22 13:10:46 +00:00
for (i = 0; i < SSE_LSP_TYPE_COUNT; i++) {
mem->used[i] = SSE_NULL;
mem->free[i] = SSE_NULL;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
mem->locked = SSE_NULL;
2005-09-18 11:34:35 +00:00
// when "ubound" is too small, the garbage collection can
// be performed while making the common objects.
2006-10-22 13:10:46 +00:00
mem->nil = SSE_NULL;
mem->t = SSE_NULL;
mem->quote = SSE_NULL;
mem->lambda = SSE_NULL;
mem->macro = SSE_NULL;
2005-09-18 11:34:35 +00:00
// initialize common object pointers
2006-10-22 13:10:46 +00:00
mem->nil = sse_lsp_make_nil (mem);
mem->t = sse_lsp_make_true (mem);
mem->quote = sse_lsp_make_symbol (mem, SSE_TEXT("quote"));
mem->lambda = sse_lsp_make_symbol (mem, SSE_TEXT("lambda"));
mem->macro = sse_lsp_make_symbol (mem, SSE_TEXT("macro"));
if (mem->nil == SSE_NULL ||
mem->t == SSE_NULL ||
mem->quote == SSE_NULL ||
mem->lambda == SSE_NULL ||
mem->macro == SSE_NULL) {
sse_lsp_dispose_all (mem);
sse_lsp_array_free (mem->temp_array);
sse_lsp_frame_free (mem->frame);
sse_free (mem);
return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
return mem;
}
2006-10-22 13:10:46 +00:00
void sse_lsp_mem_free (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (mem != SSE_NULL);
2005-09-18 11:34:35 +00:00
// dispose of the allocated objects
2006-10-22 13:10:46 +00:00
sse_lsp_dispose_all (mem);
2005-09-18 11:34:35 +00:00
// dispose of the temporary object arrays
2006-10-22 13:10:46 +00:00
sse_lsp_array_free (mem->temp_array);
2005-09-18 11:34:35 +00:00
// dispose of environment frames
2006-10-22 13:10:46 +00:00
sse_lsp_frame_free (mem->frame);
2005-09-18 11:34:35 +00:00
// free the memory
2006-10-22 13:10:46 +00:00
sse_free (mem);
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
static int __add_prim (sse_lsp_mem_t* mem,
const sse_char_t* name, sse_size_t len, sse_lsp_prim_t prim)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* n, * p;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
n = sse_lsp_make_symbolx (mem, name, len);
if (n == SSE_NULL) return -1;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_lsp_lock (n);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
p = sse_lsp_make_prim (mem, prim);
if (p == SSE_NULL) return -1;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_lsp_unlock (n);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
if (sse_lsp_set_func(mem, n, p) == SSE_NULL) return -1;
2005-09-18 11:34:35 +00:00
return 0;
}
2006-10-22 13:10:46 +00:00
int sse_lsp_add_builtin_prims (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
#define ADD_PRIM(mem,name,len,prim) \
2005-09-19 03:05:37 +00:00
if (__add_prim(mem,name,len,prim) == -1) return -1;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
ADD_PRIM (mem, SSE_TEXT("abort"), 5, sse_lsp_prim_abort);
ADD_PRIM (mem, SSE_TEXT("eval"), 4, sse_lsp_prim_eval);
ADD_PRIM (mem, SSE_TEXT("prog1"), 5, sse_lsp_prim_prog1);
ADD_PRIM (mem, SSE_TEXT("progn"), 5, sse_lsp_prim_progn);
ADD_PRIM (mem, SSE_TEXT("gc"), 2, sse_lsp_prim_gc);
ADD_PRIM (mem, SSE_TEXT("cond"), 4, sse_lsp_prim_cond);
ADD_PRIM (mem, SSE_TEXT("if"), 2, sse_lsp_prim_if);
ADD_PRIM (mem, SSE_TEXT("while"), 5, sse_lsp_prim_while);
ADD_PRIM (mem, SSE_TEXT("car"), 3, sse_lsp_prim_car);
ADD_PRIM (mem, SSE_TEXT("cdr"), 3, sse_lsp_prim_cdr);
ADD_PRIM (mem, SSE_TEXT("cons"), 4, sse_lsp_prim_cons);
ADD_PRIM (mem, SSE_TEXT("set"), 3, sse_lsp_prim_set);
ADD_PRIM (mem, SSE_TEXT("setq"), 4, sse_lsp_prim_setq);
ADD_PRIM (mem, SSE_TEXT("quote"), 5, sse_lsp_prim_quote);
ADD_PRIM (mem, SSE_TEXT("defun"), 5, sse_lsp_prim_defun);
ADD_PRIM (mem, SSE_TEXT("demac"), 5, sse_lsp_prim_demac);
ADD_PRIM (mem, SSE_TEXT("let"), 3, sse_lsp_prim_let);
ADD_PRIM (mem, SSE_TEXT("let*"), 4, sse_lsp_prim_letx);
ADD_PRIM (mem, SSE_TEXT(">"), 1, sse_lsp_prim_gt);
ADD_PRIM (mem, SSE_TEXT("<"), 1, sse_lsp_prim_lt);
ADD_PRIM (mem, SSE_TEXT("+"), 1, sse_lsp_prim_plus);
ADD_PRIM (mem, SSE_TEXT("-"), 1, sse_lsp_prim_minus);
2005-09-20 08:05:32 +00:00
2005-09-18 11:34:35 +00:00
return 0;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_alloc (sse_lsp_mem_t* mem, int type, sse_size_t size)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
if (mem->count >= mem->ubound) sse_lsp_garbage_collect (mem);
2005-09-18 11:34:35 +00:00
if (mem->count >= mem->ubound) {
mem->ubound += mem->ubound_inc;
2006-10-22 13:10:46 +00:00
if (mem->count >= mem->ubound) return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
2006-10-23 10:57:59 +00:00
obj = (sse_lsp_obj_t*) sse_malloc (size);
2006-10-22 13:10:46 +00:00
if (obj == SSE_NULL) {
sse_lsp_garbage_collect (mem);
2005-09-18 11:34:35 +00:00
2006-10-23 10:57:59 +00:00
obj = (sse_lsp_obj_t*) sse_malloc (size);
2006-10-22 13:10:46 +00:00
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
SSE_LSP_TYPE(obj) = type;
SSE_LSP_SIZE(obj) = size;
SSE_LSP_MARK(obj) = 0;
SSE_LSP_LOCK(obj) = 0;
2005-09-18 11:34:35 +00:00
// insert the object at the head of the used list
2006-10-22 13:10:46 +00:00
SSE_LSP_LINK(obj) = mem->used[type];
2005-09-18 11:34:35 +00:00
mem->used[type] = obj;
mem->count++;
2005-09-19 12:04:00 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint1 (SSE_TEXT("mem->count: %u\n"), mem->count);
2005-09-19 12:04:00 +00:00
#endif
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
void sse_lsp_dispose (sse_lsp_mem_t* mem, sse_lsp_obj_t* prev, sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (mem != SSE_NULL);
sse_assert (obj != SSE_NULL);
sse_assert (mem->count > 0);
2005-09-18 11:34:35 +00:00
// TODO: push the object to the free list for more
// efficient memory management
2006-10-22 13:10:46 +00:00
if (prev == SSE_NULL)
mem->used[SSE_LSP_TYPE(obj)] = SSE_LSP_LINK(obj);
else SSE_LSP_LINK(prev) = SSE_LSP_LINK(obj);
2005-09-18 11:34:35 +00:00
mem->count--;
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint1 (SSE_TEXT("mem->count: %u\n"), mem->count);
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_free (obj);
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
void sse_lsp_dispose_all (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj, * next;
sse_size_t i;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
for (i = 0; i < SSE_LSP_TYPE_COUNT; i++) {
2005-09-18 11:34:35 +00:00
obj = mem->used[i];
2006-10-22 13:10:46 +00:00
while (obj != SSE_NULL) {
next = SSE_LSP_LINK(obj);
sse_lsp_dispose (mem, SSE_NULL, obj);
2005-09-18 11:34:35 +00:00
obj = next;
}
}
}
2006-10-22 13:10:46 +00:00
static void sse_lsp_mark_obj (sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (obj != SSE_NULL);
2005-09-18 11:34:35 +00:00
// TODO:....
// can it be recursive?
2006-10-22 13:10:46 +00:00
if (SSE_LSP_MARK(obj) != 0) return;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_MARK(obj) = 1;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_CONS) {
sse_lsp_mark_obj (SSE_LSP_CAR(obj));
sse_lsp_mark_obj (SSE_LSP_CDR(obj));
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
else if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_FUNC) {
sse_lsp_mark_obj (SSE_LSP_FFORMAL(obj));
sse_lsp_mark_obj (SSE_LSP_FBODY(obj));
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
else if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_MACRO) {
sse_lsp_mark_obj (SSE_LSP_MFORMAL(obj));
sse_lsp_mark_obj (SSE_LSP_MBODY(obj));
2005-09-18 11:34:35 +00:00
}
}
/*
2006-10-22 13:10:46 +00:00
* sse_lsp_lock and sse_lsp_unlock_all are just called by sse_lsp_read.
2005-09-18 11:34:35 +00:00
*/
2006-10-22 13:10:46 +00:00
void sse_lsp_lock (sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (obj != SSE_NULL);
SSE_LSP_LOCK(obj) = 1;
//SSE_LSP_MARK(obj) = 1;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
void sse_lsp_unlock (sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (obj != SSE_NULL);
SSE_LSP_LOCK(obj) = 0;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
void sse_lsp_unlock_all (sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_assert (obj != SSE_NULL);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_LOCK(obj) = 0;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_CONS) {
sse_lsp_unlock_all (SSE_LSP_CAR(obj));
sse_lsp_unlock_all (SSE_LSP_CDR(obj));
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
else if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_FUNC) {
sse_lsp_unlock_all (SSE_LSP_FFORMAL(obj));
sse_lsp_unlock_all (SSE_LSP_FBODY(obj));
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
else if (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_MACRO) {
sse_lsp_unlock_all (SSE_LSP_MFORMAL(obj));
sse_lsp_unlock_all (SSE_LSP_MBODY(obj));
2005-09-18 11:34:35 +00:00
}
}
2006-10-22 13:10:46 +00:00
static void sse_lsp_mark (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_frame_t* frame;
sse_lsp_assoc_t* assoc;
sse_lsp_array_t* array;
sse_size_t i;
2005-09-18 11:34:35 +00:00
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint0 (SSE_TEXT("marking environment frames\n"));
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
// mark objects in the environment frames
frame = mem->frame;
2006-10-22 13:10:46 +00:00
while (frame != SSE_NULL) {
2005-09-18 11:34:35 +00:00
assoc = frame->assoc;
2006-10-22 13:10:46 +00:00
while (assoc != SSE_NULL) {
sse_lsp_mark_obj (assoc->name);
2005-09-20 11:19:15 +00:00
2006-10-22 13:10:46 +00:00
if (assoc->value != SSE_NULL)
sse_lsp_mark_obj (assoc->value);
if (assoc->func != SSE_NULL)
sse_lsp_mark_obj (assoc->func);
2005-09-20 11:19:15 +00:00
2005-09-18 11:34:35 +00:00
assoc = assoc->link;
}
frame = frame->link;
}
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint0 (SSE_TEXT("marking interim frames\n"));
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
// mark objects in the interim frames
frame = mem->brooding_frame;
2006-10-22 13:10:46 +00:00
while (frame != SSE_NULL) {
2005-09-18 11:34:35 +00:00
assoc = frame->assoc;
2006-10-22 13:10:46 +00:00
while (assoc != SSE_NULL) {
sse_lsp_mark_obj (assoc->name);
2005-09-20 11:19:15 +00:00
2006-10-22 13:10:46 +00:00
if (assoc->value != SSE_NULL)
sse_lsp_mark_obj (assoc->value);
if (assoc->func != SSE_NULL)
sse_lsp_mark_obj (assoc->func);
2005-09-20 11:19:15 +00:00
2005-09-18 11:34:35 +00:00
assoc = assoc->link;
}
frame = frame->link;
}
/*
2006-10-22 13:10:46 +00:00
sse_dprint0 (SSE_TEXT("marking the locked object\n"));
if (mem->locked != SSE_NULL) sse_lsp_mark_obj (mem->locked);
2005-09-18 11:34:35 +00:00
*/
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint0 (SSE_TEXT("marking termporary objects\n"));
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
array = mem->temp_array;
for (i = 0; i < array->size; i++) {
2006-10-22 13:10:46 +00:00
sse_lsp_mark_obj (array->buffer[i]);
2005-09-18 11:34:35 +00:00
}
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint0 (SSE_TEXT("marking builtin objects\n"));
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
// mark common objects
2006-10-22 13:10:46 +00:00
if (mem->t != SSE_NULL) sse_lsp_mark_obj (mem->t);
if (mem->nil != SSE_NULL) sse_lsp_mark_obj (mem->nil);
if (mem->quote != SSE_NULL) sse_lsp_mark_obj (mem->quote);
if (mem->lambda != SSE_NULL) sse_lsp_mark_obj (mem->lambda);
if (mem->macro != SSE_NULL) sse_lsp_mark_obj (mem->macro);
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
static void sse_lsp_sweep (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj, * prev, * next;
sse_size_t i;
2005-09-18 11:34:35 +00:00
// scan all the allocated objects and get rid of unused objects
2006-10-22 13:10:46 +00:00
for (i = 0; i < SSE_LSP_TYPE_COUNT; i++) {
//for (i = SSE_LSP_TYPE_COUNT; i > 0; /*i--*/) {
prev = SSE_NULL;
2005-09-18 11:34:35 +00:00
obj = mem->used[i];
//obj = mem->used[--i];
2005-09-20 11:19:15 +00:00
#if 0
2006-10-22 13:10:46 +00:00
sse_dprint1 (SSE_TEXT("sweeping objects of type: %u\n"), i);
2005-09-20 11:19:15 +00:00
#endif
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
while (obj != SSE_NULL) {
next = SSE_LSP_LINK(obj);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
if (SSE_LSP_LOCK(obj) == 0 && SSE_LSP_MARK(obj) == 0) {
2005-09-18 11:34:35 +00:00
// dispose of unused objects
2006-10-22 13:10:46 +00:00
sse_lsp_dispose (mem, prev, obj);
2005-09-18 11:34:35 +00:00
}
else {
// unmark the object in use
2006-10-22 13:10:46 +00:00
SSE_LSP_MARK(obj) = 0;
2005-09-18 11:34:35 +00:00
prev = obj;
}
obj = next;
}
}
}
2006-10-22 13:10:46 +00:00
void sse_lsp_garbage_collect (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_mark (mem);
sse_lsp_sweep (mem);
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_nil (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
if (mem->nil != SSE_NULL) return mem->nil;
mem->nil = sse_lsp_alloc (mem, SSE_LSP_OBJ_NIL, sse_sizeof(sse_lsp_obj_nil_t));
2005-09-18 11:34:35 +00:00
return mem->nil;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_true (sse_lsp_mem_t* mem)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
if (mem->t != SSE_NULL) return mem->t;
mem->t = sse_lsp_alloc (mem, SSE_LSP_OBJ_TRUE, sse_sizeof(sse_lsp_obj_true_t));
2005-09-18 11:34:35 +00:00
return mem->t;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_int (sse_lsp_mem_t* mem, sse_lsp_int_t value)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem,
SSE_LSP_OBJ_INT, sse_sizeof(sse_lsp_obj_int_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_IVALUE(obj) = value;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_real (sse_lsp_mem_t* mem, sse_lsp_real_t value)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem,
SSE_LSP_OBJ_REAL, sse_sizeof(sse_lsp_obj_real_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_RVALUE(obj) = value;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_symbol (sse_lsp_mem_t* mem, const sse_char_t* str)
2005-09-20 11:19:15 +00:00
{
2006-10-22 13:10:46 +00:00
return sse_lsp_make_symbolx (mem, str, sse_strlen(str));
2005-09-20 11:19:15 +00:00
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_symbolx (
sse_lsp_mem_t* mem, const sse_char_t* str, sse_size_t len)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
// look for a sysmbol with the given name
2006-10-22 13:10:46 +00:00
obj = mem->used[SSE_LSP_OBJ_SYMBOL];
while (obj != SSE_NULL) {
2005-09-18 11:34:35 +00:00
// if there is a symbol with the same name, it is just used.
2006-10-22 13:10:46 +00:00
if (sse_lsp_comp_symbol2 (obj, str, len) == 0) return obj;
obj = SSE_LSP_LINK(obj);
2005-09-18 11:34:35 +00:00
}
// no such symbol found. create a new one
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_SYMBOL,
sse_sizeof(sse_lsp_obj_symbol_t) + (len + 1) * sse_sizeof(sse_char_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
// fill in the symbol buffer
2006-10-22 13:10:46 +00:00
sse_lsp_copy_string2 (SSE_LSP_SYMVALUE(obj), str, len);
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_string (sse_lsp_mem_t* mem, const sse_char_t* str)
2005-09-20 11:19:15 +00:00
{
2006-10-22 13:10:46 +00:00
return sse_lsp_make_stringx (mem, str, sse_strlen(str));
2005-09-20 11:19:15 +00:00
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_stringx (
sse_lsp_mem_t* mem, const sse_char_t* str, sse_size_t len)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
// allocate memory for the string
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_STRING,
sse_sizeof(sse_lsp_obj_string_t) + (len + 1) * sse_sizeof(sse_char_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
// fill in the string buffer
2006-10-22 13:10:46 +00:00
sse_lsp_copy_string2 (SSE_LSP_STRVALUE(obj), str, len);
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_cons (
sse_lsp_mem_t* mem, sse_lsp_obj_t* car, sse_lsp_obj_t* cdr)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_CONS, sse_sizeof(sse_lsp_obj_cons_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_CAR(obj) = car;
SSE_LSP_CDR(obj) = cdr;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_func (
sse_lsp_mem_t* mem, sse_lsp_obj_t* formal, sse_lsp_obj_t* body)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_FUNC, sse_sizeof(sse_lsp_obj_func_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_FFORMAL(obj) = formal;
SSE_LSP_FBODY(obj) = body;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_macro (
sse_lsp_mem_t* mem, sse_lsp_obj_t* formal, sse_lsp_obj_t* body)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_MACRO, sse_sizeof(sse_lsp_obj_macro_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_MFORMAL(obj) = formal;
SSE_LSP_MBODY(obj) = body;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* sse_lsp_make_prim (sse_lsp_mem_t* mem, void* impl)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_obj_t* obj;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
obj = sse_lsp_alloc (mem, SSE_LSP_OBJ_PRIM, sse_sizeof(sse_lsp_obj_prim_t));
if (obj == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
SSE_LSP_PRIM(obj) = impl;
2005-09-18 11:34:35 +00:00
return obj;
}
2006-10-22 13:10:46 +00:00
sse_lsp_assoc_t* sse_lsp_lookup (sse_lsp_mem_t* mem, sse_lsp_obj_t* name)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_frame_t* frame;
sse_lsp_assoc_t* assoc;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (SSE_LSP_TYPE(name) == SSE_LSP_OBJ_SYMBOL);
2005-09-18 11:34:35 +00:00
frame = mem->frame;
2006-10-22 13:10:46 +00:00
while (frame != SSE_NULL) {
assoc = sse_lsp_frame_lookup (frame, name);
if (assoc != SSE_NULL) return assoc;
2005-09-18 11:34:35 +00:00
frame = frame->link;
}
2006-10-22 13:10:46 +00:00
return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
sse_lsp_assoc_t* sse_lsp_set_value (
sse_lsp_mem_t* mem, sse_lsp_obj_t* name, sse_lsp_obj_t* value)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_assoc_t* assoc;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
assoc = sse_lsp_lookup (mem, name);
if (assoc == SSE_NULL) {
assoc = sse_lsp_frame_insert_value (
2005-09-20 09:17:06 +00:00
mem->root_frame, name, value);
2006-10-22 13:10:46 +00:00
if (assoc == SSE_NULL) return SSE_NULL;
2005-09-18 11:34:35 +00:00
}
else assoc->value = value;
return assoc;
}
2006-10-22 13:10:46 +00:00
sse_lsp_assoc_t* sse_lsp_set_func (
sse_lsp_mem_t* mem, sse_lsp_obj_t* name, sse_lsp_obj_t* func)
2005-09-20 09:17:06 +00:00
{
2006-10-22 13:10:46 +00:00
sse_lsp_assoc_t* assoc;
2005-09-20 09:17:06 +00:00
2006-10-22 13:10:46 +00:00
assoc = sse_lsp_lookup (mem, name);
if (assoc == SSE_NULL) {
assoc = sse_lsp_frame_insert_func (mem->root_frame, name, func);
if (assoc == SSE_NULL) return SSE_NULL;
2005-09-20 09:17:06 +00:00
}
else assoc->func = func;
return assoc;
}
2006-10-22 13:10:46 +00:00
sse_size_t sse_lsp_cons_len (sse_lsp_mem_t* mem, sse_lsp_obj_t* obj)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_size_t count;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (obj == mem->nil || SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_CONS);
2005-09-18 11:34:35 +00:00
count = 0;
//while (obj != mem->nil) {
2006-10-22 13:10:46 +00:00
while (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_CONS) {
2005-09-18 11:34:35 +00:00
count++;
2006-10-22 13:10:46 +00:00
obj = SSE_LSP_CDR(obj);
2005-09-18 11:34:35 +00:00
}
return count;
}
2006-10-22 13:10:46 +00:00
int sse_lsp_probe_args (sse_lsp_mem_t* mem, sse_lsp_obj_t* obj, sse_size_t* len)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_size_t count = 0;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
while (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_CONS) {
2005-09-18 11:34:35 +00:00
count++;
2006-10-22 13:10:46 +00:00
obj = SSE_LSP_CDR(obj);
2005-09-18 11:34:35 +00:00
}
if (obj != mem->nil) return -1;
*len = count;
return 0;
}
2006-10-22 13:10:46 +00:00
int sse_lsp_comp_symbol (sse_lsp_obj_t* obj, const sse_char_t* str)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_char_t* p;
sse_size_t index, length;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_SYMBOL);
2005-09-18 11:34:35 +00:00
index = 0;
2006-10-22 13:10:46 +00:00
length = SSE_LSP_SYMLEN(obj);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
p = SSE_LSP_SYMVALUE(obj);
2005-09-18 11:34:35 +00:00
while (index < length) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
2006-10-22 13:10:46 +00:00
return (*str == SSE_CHAR('\0'))? 0: -1;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
int sse_lsp_comp_symbol2 (sse_lsp_obj_t* obj, const sse_char_t* str, sse_size_t len)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_char_t* p;
sse_size_t index, length;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_SYMBOL);
2005-09-18 11:34:35 +00:00
index = 0;
2006-10-22 13:10:46 +00:00
length = SSE_LSP_SYMLEN(obj);
p = SSE_LSP_SYMVALUE(obj);
2005-09-18 11:34:35 +00:00
while (index < length && index < len) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
return (length < len)? -1:
(length > len)? 1: 0;
}
2006-10-22 13:10:46 +00:00
int sse_lsp_comp_string (sse_lsp_obj_t* obj, const sse_char_t* str)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_char_t* p;
sse_size_t index, length;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_STRING);
2005-09-18 11:34:35 +00:00
index = 0;
2006-10-22 13:10:46 +00:00
length = SSE_LSP_STRLEN(obj);
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
p = SSE_LSP_STRVALUE(obj);
2005-09-18 11:34:35 +00:00
while (index < length) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
2006-10-22 13:10:46 +00:00
return (*str == SSE_CHAR('\0'))? 0: -1;
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
int sse_lsp_comp_string2 (sse_lsp_obj_t* obj, const sse_char_t* str, sse_size_t len)
2005-09-18 11:34:35 +00:00
{
2006-10-22 13:10:46 +00:00
sse_char_t* p;
sse_size_t index, length;
2005-09-18 11:34:35 +00:00
2006-10-22 13:10:46 +00:00
sse_assert (SSE_LSP_TYPE(obj) == SSE_LSP_OBJ_STRING);
2005-09-18 11:34:35 +00:00
index = 0;
2006-10-22 13:10:46 +00:00
length = SSE_LSP_STRLEN(obj);
p = SSE_LSP_STRVALUE(obj);
2005-09-18 11:34:35 +00:00
while (index < length && index < len) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
return (length < len)? -1:
(length > len)? 1: 0;
}
2006-10-22 13:10:46 +00:00
void sse_lsp_copy_string (sse_char_t* dst, const sse_char_t* str)
2005-09-18 11:34:35 +00:00
{
// the buffer pointed by dst should be big enough to hold str
2006-10-22 13:10:46 +00:00
while (*str != SSE_CHAR('\0')) *dst++ = *str++;
*dst = SSE_CHAR('\0');
2005-09-18 11:34:35 +00:00
}
2006-10-22 13:10:46 +00:00
void sse_lsp_copy_string2 (sse_char_t* dst, const sse_char_t* str, sse_size_t len)
2005-09-18 11:34:35 +00:00
{
// the buffer pointed by dst should be big enough to hold str
while (len > 0) {
*dst++ = *str++;
len--;
}
2006-10-22 13:10:46 +00:00
*dst = SSE_CHAR('\0');
2005-09-18 11:34:35 +00:00
}