summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ast.h6
-rw-r--r--eval.c21
-rw-r--r--tests/02_runtime/06_recursion35
3 files changed, 48 insertions, 14 deletions
diff --git a/ast.h b/ast.h
index 5c4d2ab..f86d93f 100644
--- a/ast.h
+++ b/ast.h
@@ -74,7 +74,7 @@ struct ut_op {
struct ut_scope {
struct ut_scope *next;
- struct json_object *scope, *ctx, *parent;
+ struct json_object *scope, *parent;
size_t refs;
};
@@ -88,7 +88,7 @@ struct ut_source {
struct ut_function {
char *name;
struct json_object *args;
- struct ut_scope *scope, *parent_scope;
+ struct ut_scope *parent_scope;
struct ut_source *source;
uint32_t entry;
};
@@ -96,6 +96,8 @@ struct ut_function {
struct ut_callstack {
struct ut_callstack *next;
struct ut_source *source;
+ struct ut_scope *scope;
+ struct json_object *ctx;
char *funcname;
uint32_t off;
};
diff --git a/eval.c b/eval.c
index 1eff9fc..2230bb9 100644
--- a/eval.c
+++ b/eval.c
@@ -985,6 +985,7 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
callstack.source = state->source;
callstack.funcname = state->function ? state->function->name : NULL;
callstack.off = op ? op->off : 0;
+ callstack.ctx = json_object_get(this ? this : state->ctx);
state->callstack = &callstack;
/* is native function */
@@ -996,19 +997,19 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
/* is utpl function */
else {
fn = tag->tag.data;
- fn->scope = ut_new_scope(state, fn->parent_scope);
- fn->scope->ctx = json_object_get(this ? this : state->ctx);
+
+ callstack.scope = ut_new_scope(state, fn->parent_scope);
sc = state->scope;
- state->scope = ut_acquire_scope(fn->scope);
+ state->scope = ut_acquire_scope(callstack.scope);
prev_fn = state->function;
state->function = fn;
if (fn->args)
for (arridx = 0; arridx < json_object_array_length(fn->args); arridx++)
- ut_setval(fn->scope->scope, json_object_array_get_idx(fn->args, arridx),
+ ut_setval(callstack.scope->scope, json_object_array_get_idx(fn->args, arridx),
argvals ? json_object_array_get_idx(argvals, arridx) : NULL);
rv = ut_execute_op_sequence(state, fn->entry);
@@ -1033,17 +1034,13 @@ ut_invoke(struct ut_state *state, uint32_t off, struct json_object *this,
ut_release_scope(state->scope);
state->scope = sc;
- /* ... and remove the "this" context... */
- json_object_put(fn->scope->ctx);
- fn->scope->ctx = NULL;
-
- /* ... and reset the function scope... */
- ut_release_scope(fn->scope);
- fn->scope = NULL;
+ /* ... and release it */
+ ut_release_scope(callstack.scope);
state->function = prev_fn;
}
+ json_object_put(callstack.ctx);
state->callstack = callstack.next;
return rv;
@@ -1369,7 +1366,7 @@ ut_execute_function(struct ut_state *state, uint32_t off)
static struct json_object *
ut_execute_this(struct ut_state *state, uint32_t off)
{
- return json_object_get(state->scope->ctx);
+ return json_object_get(state->callstack->ctx);
}
static struct json_object *
diff --git a/tests/02_runtime/06_recursion b/tests/02_runtime/06_recursion
new file mode 100644
index 0000000..e707c86
--- /dev/null
+++ b/tests/02_runtime/06_recursion
@@ -0,0 +1,35 @@
+Testing recursive invocations.
+
+
+1. Testing recursive invocation.
+
+-- Expect stdout --
+1
+2
+4
+8
+16
+32
+64
+128
+256
+512
+1024
+2048
+4096
+8192
+16384
+-- End --
+
+-- Testcase --
+{%
+ function test(x) {
+ print(x, "\n");
+
+ if (x < 10000)
+ test(x * 2);
+ }
+
+ test(1);
+%}
+-- End --