mirror of
https://github.com/antirez/aocla
synced 2024-12-27 09:58:32 +01:00
Bool type added. Fix stackPush() refcount handling.
This commit is contained in:
parent
9465e08d20
commit
b0a58b4236
1 changed files with 44 additions and 5 deletions
49
aocla.c
49
aocla.c
|
@ -18,11 +18,13 @@
|
||||||
#define OBJ_TYPE_TUPLE 2
|
#define OBJ_TYPE_TUPLE 2
|
||||||
#define OBJ_TYPE_STRING 3
|
#define OBJ_TYPE_STRING 3
|
||||||
#define OBJ_TYPE_SYMBOL 4
|
#define OBJ_TYPE_SYMBOL 4
|
||||||
|
#define OBJ_TYPE_BOOL 5
|
||||||
typedef struct obj {
|
typedef struct obj {
|
||||||
int type; /* OBJ_TYPE_... */
|
int type; /* OBJ_TYPE_... */
|
||||||
int refcount; /* Reference count. */
|
int refcount; /* Reference count. */
|
||||||
union {
|
union {
|
||||||
int i; /* Integer. Literal: 1234 */
|
int i; /* Integer. Literal: 1234 */
|
||||||
|
int istrue; /* Boolean. */
|
||||||
struct { /* List: Literal: [1,2,3,4] or [1 2 3 4] */
|
struct { /* List: Literal: [1,2,3,4] or [1 2 3 4] */
|
||||||
struct obj **ele;
|
struct obj **ele;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -102,12 +104,19 @@ void release(obj *o) {
|
||||||
assert(o->refcount >= 0);
|
assert(o->refcount >= 0);
|
||||||
if (--o->refcount == 0) {
|
if (--o->refcount == 0) {
|
||||||
switch(o->type) {
|
switch(o->type) {
|
||||||
case OBJ_TYPE_INT: break; /* Nothing nested to free. */
|
|
||||||
case OBJ_TYPE_LIST:
|
case OBJ_TYPE_LIST:
|
||||||
|
case OBJ_TYPE_TUPLE:
|
||||||
for (size_t j = 0; j < o->l.len; j++)
|
for (size_t j = 0; j < o->l.len; j++)
|
||||||
release(o->l.ele[j]);
|
release(o->l.ele[j]);
|
||||||
free(o->l.ele);
|
free(o->l.ele);
|
||||||
break;
|
break;
|
||||||
|
case OBJ_TYPE_SYMBOL:
|
||||||
|
case OBJ_TYPE_STRING:
|
||||||
|
free(o->str.ptr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
/* Nothing special to free. */
|
||||||
}
|
}
|
||||||
free(o);
|
free(o);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +161,7 @@ obj *newList(aoclactx *ctx, const char *s, const char **next) {
|
||||||
obj *o = myalloc(sizeof(*o));
|
obj *o = myalloc(sizeof(*o));
|
||||||
o->refcount = 1;
|
o->refcount = 1;
|
||||||
while(isspace(s[0])) s++;
|
while(isspace(s[0])) s++;
|
||||||
if (s[0] == '-' || isdigit(s[0])) { /* Integer. */
|
if ((s[0] == '-' && isdigit(s[1])) || isdigit(s[0])) { /* Integer. */
|
||||||
char buf[64];
|
char buf[64];
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
while((*s == '-' || isdigit(*s)) && len < sizeof(buf)-1)
|
while((*s == '-' || isdigit(*s)) && len < sizeof(buf)-1)
|
||||||
|
@ -220,13 +229,24 @@ obj *newList(aoclactx *ctx, const char *s, const char **next) {
|
||||||
o->str.ptr = dest;
|
o->str.ptr = dest;
|
||||||
memcpy(dest,s,o->str.len);
|
memcpy(dest,s,o->str.len);
|
||||||
dest[o->str.len] = 0;
|
dest[o->str.len] = 0;
|
||||||
*next = end;
|
if (next) *next = end;
|
||||||
|
} else if (s[0]=='#') { /* Boolean. */
|
||||||
|
if (s[1] != 't' && s[1] != 'f') {
|
||||||
|
setError(ctx,s,"Booelans are either #t or #f");
|
||||||
|
release(o);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
o->type = OBJ_TYPE_BOOL;
|
||||||
|
o->istrue = s[1] == 't' ? 1 : 0;
|
||||||
|
s += 2;
|
||||||
|
if (next) *next = s;
|
||||||
} else if (s[0] == '"') { /* String. */
|
} else if (s[0] == '"') { /* String. */
|
||||||
printf("IMPLEMENT STRING PARSING\n");
|
printf("IMPLEMENT STRING PARSING\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
/* Syntax error. */
|
/* Syntax error. */
|
||||||
setError(ctx,s,"No object type starts like this");
|
setError(ctx,s,"No object type starts like this");
|
||||||
|
release(o);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
@ -243,6 +263,13 @@ int compare(obj *a, obj *b) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bool vs Bool. */
|
||||||
|
if (a->type == OBJ_TYPE_BOOL && b->type == OBJ_TYPE_BOOL) {
|
||||||
|
if (a->istrue < b->istrue) return -1;
|
||||||
|
else if (a->istrue > b->istrue) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* String|Symbol VS String|Symbol. */
|
/* String|Symbol VS String|Symbol. */
|
||||||
if ((a->type == OBJ_TYPE_STRING || a->type == OBJ_TYPE_SYMBOL) &&
|
if ((a->type == OBJ_TYPE_STRING || a->type == OBJ_TYPE_SYMBOL) &&
|
||||||
(b->type == OBJ_TYPE_STRING || b->type == OBJ_TYPE_SYMBOL))
|
(b->type == OBJ_TYPE_STRING || b->type == OBJ_TYPE_SYMBOL))
|
||||||
|
@ -284,6 +311,7 @@ void printobj(obj *obj, int color) {
|
||||||
case OBJ_TYPE_SYMBOL: escape = "\033[36;1m"; break; /* Cyan. */
|
case OBJ_TYPE_SYMBOL: escape = "\033[36;1m"; break; /* Cyan. */
|
||||||
case OBJ_TYPE_STRING: escape = "\033[32;1m"; break; /* Green. */
|
case OBJ_TYPE_STRING: escape = "\033[32;1m"; break; /* Green. */
|
||||||
case OBJ_TYPE_INT: escape = "\033[37;1m"; break; /* Gray. */
|
case OBJ_TYPE_INT: escape = "\033[37;1m"; break; /* Gray. */
|
||||||
|
case OBJ_TYPE_BOOL: escape = "\033[35;1m"; break; /* Gray. */
|
||||||
}
|
}
|
||||||
printf("%s",escape); /* Set color. */
|
printf("%s",escape); /* Set color. */
|
||||||
}
|
}
|
||||||
|
@ -295,6 +323,9 @@ void printobj(obj *obj, int color) {
|
||||||
case OBJ_TYPE_SYMBOL:
|
case OBJ_TYPE_SYMBOL:
|
||||||
printf("%s",obj->str.ptr);
|
printf("%s",obj->str.ptr);
|
||||||
break;
|
break;
|
||||||
|
case OBJ_TYPE_BOOL:
|
||||||
|
printf("#%c",obj->istrue ? 't' : 'f');
|
||||||
|
break;
|
||||||
case OBJ_TYPE_LIST:
|
case OBJ_TYPE_LIST:
|
||||||
case OBJ_TYPE_TUPLE:
|
case OBJ_TYPE_TUPLE:
|
||||||
printf("%c",obj->type == OBJ_TYPE_LIST ? '[' : '(');
|
printf("%c",obj->type == OBJ_TYPE_LIST ? '[' : '(');
|
||||||
|
@ -324,6 +355,13 @@ obj *newInt(int i) {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a boolean object with value 'b' (1 true, 0 false). */
|
||||||
|
obj *newBool(int b) {
|
||||||
|
obj *o = newObject(OBJ_TYPE_BOOL);
|
||||||
|
o->istrue = b;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
/* Deep copy the passed object. Return an object with refcount = 1. */
|
/* Deep copy the passed object. Return an object with refcount = 1. */
|
||||||
obj *deepCopy(obj *o) {
|
obj *deepCopy(obj *o) {
|
||||||
if (o == NULL) return NULL;
|
if (o == NULL) return NULL;
|
||||||
|
@ -383,7 +421,6 @@ aoclactx *newInterpreter(void) {
|
||||||
void stackPush(aoclactx *ctx, obj *o) {
|
void stackPush(aoclactx *ctx, obj *o) {
|
||||||
ctx->stack = myrealloc(ctx->stack,sizeof(obj*) * (ctx->stacklen+1));
|
ctx->stack = myrealloc(ctx->stack,sizeof(obj*) * (ctx->stacklen+1));
|
||||||
ctx->stack[ctx->stacklen++] = o;
|
ctx->stack[ctx->stacklen++] = o;
|
||||||
retain(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pop an object from the stack without modifying its refcount.
|
/* Pop an object from the stack without modifying its refcount.
|
||||||
|
@ -457,6 +494,7 @@ int eval(aoclactx *ctx, obj *l) {
|
||||||
* any other object they get pushed on the stack. */
|
* any other object they get pushed on the stack. */
|
||||||
if (o->str.quoted) {
|
if (o->str.quoted) {
|
||||||
stackPush(ctx,o);
|
stackPush(ctx,o);
|
||||||
|
retain(o);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (o->str.ptr[0] == '$') { /* Push local var. */
|
if (o->str.ptr[0] == '$') { /* Push local var. */
|
||||||
|
@ -495,6 +533,7 @@ int eval(aoclactx *ctx, obj *l) {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
stackPush(ctx,o);
|
stackPush(ctx,o);
|
||||||
|
retain(o);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,7 +663,7 @@ int procCompare(aoclactx *ctx) {
|
||||||
case '<': res = cmp < 0; break;
|
case '<': res = cmp < 0; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stackPush(ctx,newInt(res));
|
stackPush(ctx,newBool(res));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue