M
mijoryx
Hello all.
A few weeks ago I received very useful guidance
on the subject of garbage-collection for a programming language
interpreter. Well here's the
result for scrutiny and critique.
What horribly stupid things have I overlooked?
Am I trying too much cleverness with macros?
/* object.h
global constants
object structures and typedefs
*/
//#include <ctype.h>
//#include <float.h>
//#include <math.h>
//#include <stdarg.h>
//#include <stdbool.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//limits
#define MAXNAMES 1000
#define MAXTOKEN 256
#define OSSIZE 500
#define ESSIZE 250
#define DSSIZE 20
//postscript inline
#define O(x) O ## x
#define ps(x) O(x)();
#define ps2(x,y) ps(x) ps(y)
#define ps3(x,y,z) ps2(x,y) ps(z)
#define ps4(a,b,c,d) ps3(a,b,c) ps(d)
#define ps5(a,b,c,d,e) ps4(a,b,c,d) ps(e)
#define ps6(a,b,c,d,e,f) ps5(a,b,c,d,e) ps(f)
#define ps7(a,b,c,d,e,f,g) ps6(a,b,c,d,e,f) ps(g)
#define ps8(a,b,c,d,e,f,g,h) ps7(a,b,c,d,e,f,g) ps(h)
//eg.
//ps8(dup,exch,array,astore,def,dict,currentpoint,matrix)
/* Objects */
#define Types \
X(null, int dummy) \
X(mark, int dummy2) \
X(boolean, bool b) \
X(integer, int i) \
X(real, float f) \
X(name, int n) \
X(string, String *s) \
X(array, Array *a) \
X(dict, Dict *d) \
X(operator, Operator op) \
X(file, FILE *file) \
X(font, void *font) \
X(packedarray, void *pa) \
X(save, void *save) \
struct s_operator {
char *name;
void (*fp)();
};
typedef struct s_object Object;
typedef struct s_string String;
typedef struct s_array Array;
typedef struct s_dict Dict;
typedef struct s_operator Operator;
struct s_object {
#define X(a, b) a ## type ,
enum e_type { Types } type;
#undef X
unsigned char flags;
#define READ 1
#define WRITE 2
#define EXEC 4
#define COMP 8
#define X(a, b) b;
union { Types } u;
#undef X
};
struct s_string {
int ref;
size_t length;
int offset;
char *s; };
struct s_array {
int ref;
size_t length;
int offset;
struct s_array *copyof;
Object *a; };
struct s_pair { Object key, value; };
struct s_dict {
int ref;
size_t length;
size_t maxlength;
struct s_pair *p; };
// Singular Objects
extern Object null;
extern Object mark;
// exported functions
int error (char *fmt, ...);
Object boolean (char b);
Object integer (int i);
Object real (float f);
extern char *names[];
//int nameslen;
Object name (char *s);
Object stringn (int n);
Object string (char *s);
void kill_string (String *s);
void inc_string (String *s);
Object array (int n);
void kill_array (Array *a);
void inc_array (Array *a);
Object car (Array *a);
Array * cdr (Array *a);
Object dict (int n);
int eq (Object a, Object b);
struct
s_pair * lookup (Dict *d, Object key);
bool define (Dict *d, Object key, Object value);
void kill_dict (Dict *d);
void inc_dict (Dict *d);
void kill (Object *o);
void inc (Object *o);
Object executable (Object o);
Object operator (char *name, void (*fp)());
/* eof: object.h */
/* object.c
error function (to avoid a main.h or misc.c)
object allocators
and storage for singular objects null and mark
*/
#include <float.h> //FLT_EPSILON
#include <math.h> //fabsf
#include <stdarg.h> //...
#include <stdbool.h> //true false
#include <stdio.h> //vfprintf
#include <stdlib.h> //exit malloc free
#include <string.h> //strcmp strdup
#include "object.h"
int error(char *fmt, ...) {
va_list argptr;
va_start( argptr, fmt );
(void)vfprintf(stderr, fmt, argptr);
(void)fputc('\n',stderr);
va_end(argptr);
exit(EXIT_FAILURE);
}
Object null = { .type = nulltype, .flags = 0, .u.dummy = 0};
Object mark = { .type = marktype, .flags = 0, .u.dummy2 = 0};
/* Object Allocators and Convenience Functions */
Object boolean (char b) {
Object o = { .type = booleantype, .flags = 0, .u.b = b };
return o; }
Object integer (int i) {
Object o = { .type = integertype, .flags = 0, .u.i = i };
return o; }
Object real (float f) {
Object o = { .type = realtype, .flags = 0, .u.f = f };
return o; }
char *names[MAXNAMES];
int nameslen = 0;
Object name (char *s) {
Object o = { .type = nametype, .flags = 0, .u.dummy = 0 };
int i;
for (i=0; i<nameslen; i++) { //look
if (strcmp(s, names) == 0) { //found
o.u.n = i;
return o;
}
}
o.u.n = i; //new
names = strdup(s);
nameslen++;
return o;
}
Object stringn (int n) {
Object o = { .type = stringtype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.s = (String *)malloc(sizeof *o.u.s))
|| error("VMerror in stringn"));
o.u.s->ref = 1;
o.u.s->length = (size_t)n;
o.u.s->offset = 0;
(void)((o.u.s->s = malloc((size_t)n+1))
|| error("VMerror in stringn"));
return o; }
Object string (char *s) {
Object o;
size_t n;
n = strlen(s);
o = stringn((int)n);
strncpy(o.u.s->s, s, n);
return o; }
void kill_string(String *s) {
if (--s->ref == 0) {
free(s->s);
free(s);
}
}
void inc_string(String *s) { s->ref++; }
Object array (int n) {
Object o = { .type = arraytype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.a = (Array *)malloc(sizeof *o.u.a))
|| error("VMerror in array"));
o.u.a->ref = 1;
o.u.a->length = (size_t)n;
o.u.a->offset = 0;
o.u.a->copyof = NULL;
(void)((o.u.a->a = (Object *)calloc((size_t)n, sizeof o))
|| error("VMerror in array"));
return o; }
void kill_array(Array *a) {
if (--a->ref == 0) {
int i;
for (i=0; i < (int)a->length; i++) {
//kill elements
}
if(a->copyof) kill_array(a->copyof);
else free(a->a);
free(a);
}
}
void inc_array(Array *a) { a->ref++; }
Object car(Array *a) {
return a->a[a->offset];
}
Array *cdr(Array *a) {
Array *new;
(void)((new = (Array *)malloc(sizeof *new))
|| error("VMerror in cdr"));
new->ref = 1;
new->length = a->length - 1;
new->offset = a->offset + 1;
new->copyof = a;
new->a = a->a;
return new;
}
Object dict (int n) {
Object o = { .type = dicttype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.d = (Dict *)malloc(sizeof *o.u.d))
|| error("VMerror in dict"));
o.u.d->ref = 1;
o.u.d->maxlength = (size_t)n;
o.u.d->length = 0;
(void)((o.u.d->p = (struct s_pair *)calloc((size_t)n,sizeof *o.u.d-
return o; }
int eq (Object a, Object b) {
if (a.type != b.type) { return false; }
switch(a.type) {
case nulltype:
case marktype: return true;
case booleantype: return a.u.b == b.u.b;
case nametype: //ints
case integertype: return a.u.i == b.u.i;
case realtype: return fabsf(a.u.f - b.u.f) > FLT_EPSILON;
case stringtype: //composites (pointers)
case arraytype:
case filetype:
case dicttype: return a.u.d == b.u.d;
case operatortype: return a.u.op.fp == b.u.op.fp;
default:
return false;
}
}
struct s_pair *lookup (Dict *d, Object key) {
struct s_pair *p = NULL;
int i;
for (i=0; i < (int)d->length; i++) {
if (eq(d->p.key,key)) {
p = &d->p;
break;
}
}
return p;
}
bool define(Dict *d, Object key, Object value) {
struct s_pair *p;
p = lookup(d, key);
if (p) {
p->value = value;
return true;
} else {
if (d->length >= d->maxlength) {
//error("dictfull in define");
return false;
}
p = &d->p[d->length++];
p->key = key;
p->value = value;
return true;
}
}
void kill_dict(Dict *d) {
if (--d->ref == 0) {
int i;
for (i=0; i < (int)d->length; i++) {
//kill elements
}
free(d->p);
free(d);
}
}
void inc_dict(Dict *d) { d->ref++; }
void kill(Object *o) {
if (o->flags & COMP ) { //if killable,
switch(o->type) { //kill whatever
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
void inc(Object *o) {
if (o->flags & COMP) {
switch(o->type) {
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
Object executable (Object o) { o.flags |= EXEC; return o; }
Object operator (char *name, void (*fp)()) {
Object o = { .type = operatortype, .flags = EXEC,
.u.op = { .name = name, .fp = fp } };
return o; }
/* object.c
error function (to avoid a main.h or misc.c)
object allocators
and storage for singular objects null and mark
*/
#include <float.h> //FLT_EPSILON
#include <math.h> //fabsf
#include <stdarg.h> //...
#include <stdbool.h> //true false
#include <stdio.h> //vfprintf
#include <stdlib.h> //exit malloc free
#include <string.h> //strcmp strdup
#include "object.h"
int error(char *fmt, ...) {
va_list argptr;
va_start( argptr, fmt );
(void)vfprintf(stderr, fmt, argptr);
(void)fputc('\n',stderr);
va_end(argptr);
exit(EXIT_FAILURE);
}
Object null = { .type = nulltype, .flags = 0, .u.dummy = 0};
Object mark = { .type = marktype, .flags = 0, .u.dummy2 = 0};
/* Object Allocators and Convenience Functions */
Object boolean (char b) {
Object o = { .type = booleantype, .flags = 0, .u.b = b };
return o; }
Object integer (int i) {
Object o = { .type = integertype, .flags = 0, .u.i = i };
return o; }
Object real (float f) {
Object o = { .type = realtype, .flags = 0, .u.f = f };
return o; }
char *names[MAXNAMES];
int nameslen = 0;
Object name (char *s) {
Object o = { .type = nametype, .flags = 0, .u.dummy = 0 };
int i;
for (i=0; i<nameslen; i++) { //look
if (strcmp(s, names) == 0) { //found
o.u.n = i;
return o;
}
}
o.u.n = i; //new
names = strdup(s);
nameslen++;
return o;
}
Object stringn (int n) {
Object o = { .type = stringtype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.s = (String *)malloc(sizeof *o.u.s))
|| error("VMerror in stringn"));
o.u.s->ref = 1;
o.u.s->length = (size_t)n;
o.u.s->offset = 0;
(void)((o.u.s->s = malloc((size_t)n+1))
|| error("VMerror in stringn"));
return o; }
Object string (char *s) {
Object o;
size_t n;
n = strlen(s);
o = stringn((int)n);
strncpy(o.u.s->s, s, n);
return o; }
void kill_string(String *s) {
if (--s->ref == 0) {
free(s->s);
free(s);
}
}
void inc_string(String *s) { s->ref++; }
Object array (int n) {
Object o = { .type = arraytype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.a = (Array *)malloc(sizeof *o.u.a))
|| error("VMerror in array"));
o.u.a->ref = 1;
o.u.a->length = (size_t)n;
o.u.a->offset = 0;
o.u.a->copyof = NULL;
(void)((o.u.a->a = (Object *)calloc((size_t)n, sizeof o))
|| error("VMerror in array"));
return o; }
void kill_array(Array *a) {
if (--a->ref == 0) {
int i;
for (i=0; i < (int)a->length; i++) {
//kill elements
}
if(a->copyof) kill_array(a->copyof);
else free(a->a);
free(a);
}
}
void inc_array(Array *a) { a->ref++; }
Object car(Array *a) {
return a->a[a->offset];
}
Array *cdr(Array *a) {
Array *new;
(void)((new = (Array *)malloc(sizeof *new))
|| error("VMerror in cdr"));
new->ref = 1;
new->length = a->length - 1;
new->offset = a->offset + 1;
new->copyof = a;
new->a = a->a;
return new;
}
Object dict (int n) {
Object o = { .type = dicttype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.d = (Dict *)malloc(sizeof *o.u.d))
|| error("VMerror in dict"));
o.u.d->ref = 1;
o.u.d->maxlength = (size_t)n;
o.u.d->length = 0;
(void)((o.u.d->p = (struct s_pair *)calloc((size_t)n,sizeof *o.u.d-
return o; }
int eq (Object a, Object b) {
if (a.type != b.type) { return false; }
switch(a.type) {
case nulltype:
case marktype: return true;
case booleantype: return a.u.b == b.u.b;
case nametype: //ints
case integertype: return a.u.i == b.u.i;
case realtype: return fabsf(a.u.f - b.u.f) > FLT_EPSILON;
case stringtype: //composites (pointers)
case arraytype:
case filetype:
case dicttype: return a.u.d == b.u.d;
case operatortype: return a.u.op.fp == b.u.op.fp;
default:
return false;
}
}
struct s_pair *lookup (Dict *d, Object key) {
struct s_pair *p = NULL;
int i;
for (i=0; i < (int)d->length; i++) {
if (eq(d->p.key,key)) {
p = &d->p;
break;
}
}
return p;
}
bool define(Dict *d, Object key, Object value) {
struct s_pair *p;
p = lookup(d, key);
if (p) {
p->value = value;
return true;
} else {
if (d->length >= d->maxlength) {
//error("dictfull in define");
return false;
}
p = &d->p[d->length++];
p->key = key;
p->value = value;
return true;
}
}
void kill_dict(Dict *d) {
if (--d->ref == 0) {
int i;
for (i=0; i < (int)d->length; i++) {
//kill elements
}
free(d->p);
free(d);
}
}
void inc_dict(Dict *d) { d->ref++; }
void kill(Object *o) {
if (o->flags & COMP ) { //if killable,
switch(o->type) { //kill whatever
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
void inc(Object *o) {
if (o->flags & COMP) {
switch(o->type) {
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
Object executable (Object o) { o.flags |= EXEC; return o; }
Object operator (char *name, void (*fp)()) {
Object o = { .type = operatortype, .flags = EXEC,
.u.op = { .name = name, .fp = fp } };
return o; }
/* eof: object.c */
tia
luXer-ex-trog
A few weeks ago I received very useful guidance
on the subject of garbage-collection for a programming language
interpreter. Well here's the
result for scrutiny and critique.
What horribly stupid things have I overlooked?
Am I trying too much cleverness with macros?
/* object.h
global constants
object structures and typedefs
*/
//#include <ctype.h>
//#include <float.h>
//#include <math.h>
//#include <stdarg.h>
//#include <stdbool.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//limits
#define MAXNAMES 1000
#define MAXTOKEN 256
#define OSSIZE 500
#define ESSIZE 250
#define DSSIZE 20
//postscript inline
#define O(x) O ## x
#define ps(x) O(x)();
#define ps2(x,y) ps(x) ps(y)
#define ps3(x,y,z) ps2(x,y) ps(z)
#define ps4(a,b,c,d) ps3(a,b,c) ps(d)
#define ps5(a,b,c,d,e) ps4(a,b,c,d) ps(e)
#define ps6(a,b,c,d,e,f) ps5(a,b,c,d,e) ps(f)
#define ps7(a,b,c,d,e,f,g) ps6(a,b,c,d,e,f) ps(g)
#define ps8(a,b,c,d,e,f,g,h) ps7(a,b,c,d,e,f,g) ps(h)
//eg.
//ps8(dup,exch,array,astore,def,dict,currentpoint,matrix)
/* Objects */
#define Types \
X(null, int dummy) \
X(mark, int dummy2) \
X(boolean, bool b) \
X(integer, int i) \
X(real, float f) \
X(name, int n) \
X(string, String *s) \
X(array, Array *a) \
X(dict, Dict *d) \
X(operator, Operator op) \
X(file, FILE *file) \
X(font, void *font) \
X(packedarray, void *pa) \
X(save, void *save) \
struct s_operator {
char *name;
void (*fp)();
};
typedef struct s_object Object;
typedef struct s_string String;
typedef struct s_array Array;
typedef struct s_dict Dict;
typedef struct s_operator Operator;
struct s_object {
#define X(a, b) a ## type ,
enum e_type { Types } type;
#undef X
unsigned char flags;
#define READ 1
#define WRITE 2
#define EXEC 4
#define COMP 8
#define X(a, b) b;
union { Types } u;
#undef X
};
struct s_string {
int ref;
size_t length;
int offset;
char *s; };
struct s_array {
int ref;
size_t length;
int offset;
struct s_array *copyof;
Object *a; };
struct s_pair { Object key, value; };
struct s_dict {
int ref;
size_t length;
size_t maxlength;
struct s_pair *p; };
// Singular Objects
extern Object null;
extern Object mark;
// exported functions
int error (char *fmt, ...);
Object boolean (char b);
Object integer (int i);
Object real (float f);
extern char *names[];
//int nameslen;
Object name (char *s);
Object stringn (int n);
Object string (char *s);
void kill_string (String *s);
void inc_string (String *s);
Object array (int n);
void kill_array (Array *a);
void inc_array (Array *a);
Object car (Array *a);
Array * cdr (Array *a);
Object dict (int n);
int eq (Object a, Object b);
struct
s_pair * lookup (Dict *d, Object key);
bool define (Dict *d, Object key, Object value);
void kill_dict (Dict *d);
void inc_dict (Dict *d);
void kill (Object *o);
void inc (Object *o);
Object executable (Object o);
Object operator (char *name, void (*fp)());
/* eof: object.h */
/* object.c
error function (to avoid a main.h or misc.c)
object allocators
and storage for singular objects null and mark
*/
#include <float.h> //FLT_EPSILON
#include <math.h> //fabsf
#include <stdarg.h> //...
#include <stdbool.h> //true false
#include <stdio.h> //vfprintf
#include <stdlib.h> //exit malloc free
#include <string.h> //strcmp strdup
#include "object.h"
int error(char *fmt, ...) {
va_list argptr;
va_start( argptr, fmt );
(void)vfprintf(stderr, fmt, argptr);
(void)fputc('\n',stderr);
va_end(argptr);
exit(EXIT_FAILURE);
}
Object null = { .type = nulltype, .flags = 0, .u.dummy = 0};
Object mark = { .type = marktype, .flags = 0, .u.dummy2 = 0};
/* Object Allocators and Convenience Functions */
Object boolean (char b) {
Object o = { .type = booleantype, .flags = 0, .u.b = b };
return o; }
Object integer (int i) {
Object o = { .type = integertype, .flags = 0, .u.i = i };
return o; }
Object real (float f) {
Object o = { .type = realtype, .flags = 0, .u.f = f };
return o; }
char *names[MAXNAMES];
int nameslen = 0;
Object name (char *s) {
Object o = { .type = nametype, .flags = 0, .u.dummy = 0 };
int i;
for (i=0; i<nameslen; i++) { //look
if (strcmp(s, names) == 0) { //found
o.u.n = i;
return o;
}
}
o.u.n = i; //new
names = strdup(s);
nameslen++;
return o;
}
Object stringn (int n) {
Object o = { .type = stringtype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.s = (String *)malloc(sizeof *o.u.s))
|| error("VMerror in stringn"));
o.u.s->ref = 1;
o.u.s->length = (size_t)n;
o.u.s->offset = 0;
(void)((o.u.s->s = malloc((size_t)n+1))
|| error("VMerror in stringn"));
return o; }
Object string (char *s) {
Object o;
size_t n;
n = strlen(s);
o = stringn((int)n);
strncpy(o.u.s->s, s, n);
return o; }
void kill_string(String *s) {
if (--s->ref == 0) {
free(s->s);
free(s);
}
}
void inc_string(String *s) { s->ref++; }
Object array (int n) {
Object o = { .type = arraytype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.a = (Array *)malloc(sizeof *o.u.a))
|| error("VMerror in array"));
o.u.a->ref = 1;
o.u.a->length = (size_t)n;
o.u.a->offset = 0;
o.u.a->copyof = NULL;
(void)((o.u.a->a = (Object *)calloc((size_t)n, sizeof o))
|| error("VMerror in array"));
return o; }
void kill_array(Array *a) {
if (--a->ref == 0) {
int i;
for (i=0; i < (int)a->length; i++) {
//kill elements
}
if(a->copyof) kill_array(a->copyof);
else free(a->a);
free(a);
}
}
void inc_array(Array *a) { a->ref++; }
Object car(Array *a) {
return a->a[a->offset];
}
Array *cdr(Array *a) {
Array *new;
(void)((new = (Array *)malloc(sizeof *new))
|| error("VMerror in cdr"));
new->ref = 1;
new->length = a->length - 1;
new->offset = a->offset + 1;
new->copyof = a;
new->a = a->a;
return new;
}
Object dict (int n) {
Object o = { .type = dicttype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.d = (Dict *)malloc(sizeof *o.u.d))
|| error("VMerror in dict"));
o.u.d->ref = 1;
o.u.d->maxlength = (size_t)n;
o.u.d->length = 0;
(void)((o.u.d->p = (struct s_pair *)calloc((size_t)n,sizeof *o.u.d-
|| error("VMerror in dict"));
return o; }
int eq (Object a, Object b) {
if (a.type != b.type) { return false; }
switch(a.type) {
case nulltype:
case marktype: return true;
case booleantype: return a.u.b == b.u.b;
case nametype: //ints
case integertype: return a.u.i == b.u.i;
case realtype: return fabsf(a.u.f - b.u.f) > FLT_EPSILON;
case stringtype: //composites (pointers)
case arraytype:
case filetype:
case dicttype: return a.u.d == b.u.d;
case operatortype: return a.u.op.fp == b.u.op.fp;
default:
return false;
}
}
struct s_pair *lookup (Dict *d, Object key) {
struct s_pair *p = NULL;
int i;
for (i=0; i < (int)d->length; i++) {
if (eq(d->p.key,key)) {
p = &d->p;
break;
}
}
return p;
}
bool define(Dict *d, Object key, Object value) {
struct s_pair *p;
p = lookup(d, key);
if (p) {
p->value = value;
return true;
} else {
if (d->length >= d->maxlength) {
//error("dictfull in define");
return false;
}
p = &d->p[d->length++];
p->key = key;
p->value = value;
return true;
}
}
void kill_dict(Dict *d) {
if (--d->ref == 0) {
int i;
for (i=0; i < (int)d->length; i++) {
//kill elements
}
free(d->p);
free(d);
}
}
void inc_dict(Dict *d) { d->ref++; }
void kill(Object *o) {
if (o->flags & COMP ) { //if killable,
switch(o->type) { //kill whatever
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
void inc(Object *o) {
if (o->flags & COMP) {
switch(o->type) {
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
Object executable (Object o) { o.flags |= EXEC; return o; }
Object operator (char *name, void (*fp)()) {
Object o = { .type = operatortype, .flags = EXEC,
.u.op = { .name = name, .fp = fp } };
return o; }
/* object.c
error function (to avoid a main.h or misc.c)
object allocators
and storage for singular objects null and mark
*/
#include <float.h> //FLT_EPSILON
#include <math.h> //fabsf
#include <stdarg.h> //...
#include <stdbool.h> //true false
#include <stdio.h> //vfprintf
#include <stdlib.h> //exit malloc free
#include <string.h> //strcmp strdup
#include "object.h"
int error(char *fmt, ...) {
va_list argptr;
va_start( argptr, fmt );
(void)vfprintf(stderr, fmt, argptr);
(void)fputc('\n',stderr);
va_end(argptr);
exit(EXIT_FAILURE);
}
Object null = { .type = nulltype, .flags = 0, .u.dummy = 0};
Object mark = { .type = marktype, .flags = 0, .u.dummy2 = 0};
/* Object Allocators and Convenience Functions */
Object boolean (char b) {
Object o = { .type = booleantype, .flags = 0, .u.b = b };
return o; }
Object integer (int i) {
Object o = { .type = integertype, .flags = 0, .u.i = i };
return o; }
Object real (float f) {
Object o = { .type = realtype, .flags = 0, .u.f = f };
return o; }
char *names[MAXNAMES];
int nameslen = 0;
Object name (char *s) {
Object o = { .type = nametype, .flags = 0, .u.dummy = 0 };
int i;
for (i=0; i<nameslen; i++) { //look
if (strcmp(s, names) == 0) { //found
o.u.n = i;
return o;
}
}
o.u.n = i; //new
names = strdup(s);
nameslen++;
return o;
}
Object stringn (int n) {
Object o = { .type = stringtype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.s = (String *)malloc(sizeof *o.u.s))
|| error("VMerror in stringn"));
o.u.s->ref = 1;
o.u.s->length = (size_t)n;
o.u.s->offset = 0;
(void)((o.u.s->s = malloc((size_t)n+1))
|| error("VMerror in stringn"));
return o; }
Object string (char *s) {
Object o;
size_t n;
n = strlen(s);
o = stringn((int)n);
strncpy(o.u.s->s, s, n);
return o; }
void kill_string(String *s) {
if (--s->ref == 0) {
free(s->s);
free(s);
}
}
void inc_string(String *s) { s->ref++; }
Object array (int n) {
Object o = { .type = arraytype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.a = (Array *)malloc(sizeof *o.u.a))
|| error("VMerror in array"));
o.u.a->ref = 1;
o.u.a->length = (size_t)n;
o.u.a->offset = 0;
o.u.a->copyof = NULL;
(void)((o.u.a->a = (Object *)calloc((size_t)n, sizeof o))
|| error("VMerror in array"));
return o; }
void kill_array(Array *a) {
if (--a->ref == 0) {
int i;
for (i=0; i < (int)a->length; i++) {
//kill elements
}
if(a->copyof) kill_array(a->copyof);
else free(a->a);
free(a);
}
}
void inc_array(Array *a) { a->ref++; }
Object car(Array *a) {
return a->a[a->offset];
}
Array *cdr(Array *a) {
Array *new;
(void)((new = (Array *)malloc(sizeof *new))
|| error("VMerror in cdr"));
new->ref = 1;
new->length = a->length - 1;
new->offset = a->offset + 1;
new->copyof = a;
new->a = a->a;
return new;
}
Object dict (int n) {
Object o = { .type = dicttype, .flags = COMP, .u.dummy = 0 };
(void)((o.u.d = (Dict *)malloc(sizeof *o.u.d))
|| error("VMerror in dict"));
o.u.d->ref = 1;
o.u.d->maxlength = (size_t)n;
o.u.d->length = 0;
(void)((o.u.d->p = (struct s_pair *)calloc((size_t)n,sizeof *o.u.d-
|| error("VMerror in dict"));
return o; }
int eq (Object a, Object b) {
if (a.type != b.type) { return false; }
switch(a.type) {
case nulltype:
case marktype: return true;
case booleantype: return a.u.b == b.u.b;
case nametype: //ints
case integertype: return a.u.i == b.u.i;
case realtype: return fabsf(a.u.f - b.u.f) > FLT_EPSILON;
case stringtype: //composites (pointers)
case arraytype:
case filetype:
case dicttype: return a.u.d == b.u.d;
case operatortype: return a.u.op.fp == b.u.op.fp;
default:
return false;
}
}
struct s_pair *lookup (Dict *d, Object key) {
struct s_pair *p = NULL;
int i;
for (i=0; i < (int)d->length; i++) {
if (eq(d->p.key,key)) {
p = &d->p;
break;
}
}
return p;
}
bool define(Dict *d, Object key, Object value) {
struct s_pair *p;
p = lookup(d, key);
if (p) {
p->value = value;
return true;
} else {
if (d->length >= d->maxlength) {
//error("dictfull in define");
return false;
}
p = &d->p[d->length++];
p->key = key;
p->value = value;
return true;
}
}
void kill_dict(Dict *d) {
if (--d->ref == 0) {
int i;
for (i=0; i < (int)d->length; i++) {
//kill elements
}
free(d->p);
free(d);
}
}
void inc_dict(Dict *d) { d->ref++; }
void kill(Object *o) {
if (o->flags & COMP ) { //if killable,
switch(o->type) { //kill whatever
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
void inc(Object *o) {
if (o->flags & COMP) {
switch(o->type) {
#define X(a,b) case a ## type: kill_ ## a (o->u. b ); break;
X(string,s)
X(array,a)
X(dict,d)
#undef X
default: break;
}
}
}
Object executable (Object o) { o.flags |= EXEC; return o; }
Object operator (char *name, void (*fp)()) {
Object o = { .type = operatortype, .flags = EXEC,
.u.op = { .name = name, .fp = fp } };
return o; }
/* eof: object.c */
tia
luXer-ex-trog