mirror of
https://github.com/antirez/aocla
synced 2025-01-13 20:01:40 +01:00
Variables capturing.
This commit is contained in:
parent
260d379cd5
commit
fd274cad34
1 changed files with 41 additions and 5 deletions
46
aocla.c
46
aocla.c
|
@ -308,6 +308,26 @@ obj *newInt(int i) {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Deep copy the passed object. Return an object with refcount = 1. */
|
||||||
|
obj *deepCopy(obj *o) {
|
||||||
|
if (o == NULL) return NULL;
|
||||||
|
/* TODO: actually implement it. */
|
||||||
|
printf("IMPLEMENT ME \\o/\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function performs a deep copy of the object if it has a refcount > 1.
|
||||||
|
* The copy is returned. Otherwise if refcount is 1, the function returns
|
||||||
|
* the same object we passed as argument. This is useful when we want to
|
||||||
|
* modify a shared object. */
|
||||||
|
obj *getUnsharedObject(obj *o) {
|
||||||
|
if (o->refcount > 1) {
|
||||||
|
return deepCopy(o);
|
||||||
|
} else {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== Interpreter state ============================= */
|
/* ========================== Interpreter state ============================= */
|
||||||
|
|
||||||
/* Set the syntax or runtime error, if the context is not NULL. */
|
/* Set the syntax or runtime error, if the context is not NULL. */
|
||||||
|
@ -329,8 +349,7 @@ stackframe *newStackFrame(void) {
|
||||||
|
|
||||||
/* Free a stack frame. */
|
/* Free a stack frame. */
|
||||||
void freeStackFrame(stackframe *sf) {
|
void freeStackFrame(stackframe *sf) {
|
||||||
for (int j = 0; j < AOCLA_NUMVARS; j++)
|
for (int j = 0; j < AOCLA_NUMVARS; j++) release(sf->locals[j]);
|
||||||
if (sf->locals[j]) release(sf->locals[j]);
|
|
||||||
free(sf);
|
free(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,10 +422,25 @@ int eval(aoclactx *ctx, obj *l) {
|
||||||
aproc *proc;
|
aproc *proc;
|
||||||
|
|
||||||
switch(o->type) {
|
switch(o->type) {
|
||||||
case OBJ_TYPE_SYMBOL:
|
case OBJ_TYPE_TUPLE: /* Capture variables. */
|
||||||
|
if (ctx->stacklen < o->l.len) {
|
||||||
|
setError(ctx,NULL,"Out of stack while capturing locals");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->stacklen -= o->l.len;
|
||||||
|
for (size_t i = 0; i < o->l.len; i++) {
|
||||||
|
int idx = o->l.ele[i]->str.ptr[0] - 'a';
|
||||||
|
release(ctx->frame->locals[idx]);
|
||||||
|
ctx->frame->locals[idx] =
|
||||||
|
ctx->stack[ctx->stacklen - o->l.len];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OBJ_TYPE_SYMBOL: /* Execute procedure. */
|
||||||
proc = lookupProc(ctx,o->str.ptr);
|
proc = lookupProc(ctx,o->str.ptr);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
setError(ctx,o->str.ptr,"Symbol not bound to procedure");
|
setError(ctx,o->str.ptr,
|
||||||
|
"Symbol not bound to procedure");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (proc->cproc) {
|
if (proc->cproc) {
|
||||||
|
@ -545,8 +579,10 @@ int procCompare(const char *fname, aoclactx *ctx) {
|
||||||
int procSortList(const char *fname, aoclactx *ctx) {
|
int procSortList(const char *fname, aoclactx *ctx) {
|
||||||
NOTUSED(fname);
|
NOTUSED(fname);
|
||||||
if (checkStackType(ctx,1,OBJ_TYPE_LIST)) return 1;
|
if (checkStackType(ctx,1,OBJ_TYPE_LIST)) return 1;
|
||||||
obj *l = stackPeek(ctx);
|
obj *l = stackPop(ctx);
|
||||||
|
l = getUnsharedObject(l);
|
||||||
qsort(l->l.ele,l->l.len,sizeof(obj*),qsort_obj_cmp);
|
qsort(l->l.ele,l->l.len,sizeof(obj*),qsort_obj_cmp);
|
||||||
|
stackPush(ctx,l);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue