Recursive functions + bugfix for stack reallocation.
This commit is contained in:
1 parent
cbdeddbab8
commit
49cf2e67fe
5 files changed
+32
-10
No files matched your search
@@ -164,6 +164,13 @@ block gen_op_block_defn(opcode op, const char* name, block block) {
|
|||||||
return inst_block(i);
|
return inst_block(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void block_bind_subblock(block binder, block body, int bindflags);
|
||||||
|
block gen_op_block_defn_rec(opcode op, const char* name, block blk) {
|
||||||
|
block b = gen_op_block_defn(op, name, blk);
|
||||||
|
block_bind_subblock(b, b, OP_IS_CALL_PSEUDO | OP_HAS_BINDING);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
block gen_op_block_unbound(opcode op, const char* name) {
|
block gen_op_block_unbound(opcode op, const char* name) {
|
||||||
assert(opcode_describe(op)->flags & OP_IS_CALL_PSEUDO);
|
assert(opcode_describe(op)->flags & OP_IS_CALL_PSEUDO);
|
||||||
inst* i = inst_new(op);
|
inst* i = inst_new(op);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ block gen_op_target(opcode op, block target);
|
|||||||
block gen_op_var_unbound(opcode op, const char* name);
|
block gen_op_var_unbound(opcode op, const char* name);
|
||||||
block gen_op_var_bound(opcode op, block binder);
|
block gen_op_var_bound(opcode op, block binder);
|
||||||
block gen_op_block_defn(opcode op, const char* name, block block);
|
block gen_op_block_defn(opcode op, const char* name, block block);
|
||||||
|
block gen_op_block_defn_rec(opcode op, const char* name, block block);
|
||||||
block gen_op_block_unbound(opcode op, const char* name);
|
block gen_op_block_unbound(opcode op, const char* name);
|
||||||
block gen_op_call(opcode op, block arglist);
|
block gen_op_call(opcode op, block arglist);
|
||||||
block gen_op_symbol(opcode op, const char* name);
|
block gen_op_symbol(opcode op, const char* name);
|
||||||
|
|||||||
+16
-8
@@ -6,7 +6,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct forkable_stack_header {
|
struct forkable_stack_header {
|
||||||
int next;
|
/* distance in bytes between this header and the header
|
||||||
|
of the next object on the stack */
|
||||||
|
int next_delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FORKABLE_STACK_HEADER struct forkable_stack_header fk_header_
|
#define FORKABLE_STACK_HEADER struct forkable_stack_header fk_header_
|
||||||
@@ -54,11 +56,12 @@ static void forkable_stack_free(struct forkable_stack* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_push(struct forkable_stack* s, size_t sz_size) {
|
static void* forkable_stack_push(struct forkable_stack* s, size_t sz_size) {
|
||||||
|
assert(sz_size > 0 && sz_size % sizeof(struct forkable_stack_header) == 0);
|
||||||
int size = (int)sz_size;
|
int size = (int)sz_size;
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
int curr = s->pos < s->savedlimit ? s->pos : s->savedlimit;
|
int curr = s->pos < s->savedlimit ? s->pos : s->savedlimit;
|
||||||
if (curr - size < 0) {
|
if (curr - size < 0) {
|
||||||
assert(0);
|
//assert(0);
|
||||||
int oldlen = s->length;
|
int oldlen = s->length;
|
||||||
s->length = (size + oldlen + 1024) * 2;
|
s->length = (size + oldlen + 1024) * 2;
|
||||||
s->stk = realloc(s->stk, s->length);
|
s->stk = realloc(s->stk, s->length);
|
||||||
@@ -68,9 +71,11 @@ static void* forkable_stack_push(struct forkable_stack* s, size_t sz_size) {
|
|||||||
s->savedlimit += shift;
|
s->savedlimit += shift;
|
||||||
curr += shift;
|
curr += shift;
|
||||||
}
|
}
|
||||||
void* ret = (void*)(s->stk + curr - size);
|
int newpos = curr - size;
|
||||||
((struct forkable_stack_header*)ret)->next = s->pos;
|
assert(newpos < s->pos);
|
||||||
s->pos = curr - size;
|
void* ret = (void*)(s->stk + newpos);
|
||||||
|
((struct forkable_stack_header*)ret)->next_delta = s->pos - newpos;
|
||||||
|
s->pos = newpos;
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -84,8 +89,11 @@ static void* forkable_stack_peek(struct forkable_stack* s) {
|
|||||||
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
|
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = top;
|
struct forkable_stack_header* elem = top;
|
||||||
if (elem->next < s->length) {
|
int elempos = (char*)top - s->stk;
|
||||||
return (void*)(s->stk + elem->next);
|
assert(elempos >= 0 && elempos < s->length);
|
||||||
|
assert(elempos + elem->next_delta <= s->length);
|
||||||
|
if (elempos + elem->next_delta < s->length) {
|
||||||
|
return (void*)(s->stk + elempos + elem->next_delta);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -100,7 +108,7 @@ static int forkable_stack_pop_will_free(struct forkable_stack* s) {
|
|||||||
static void forkable_stack_pop(struct forkable_stack* s) {
|
static void forkable_stack_pop(struct forkable_stack* s) {
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = forkable_stack_peek(s);
|
struct forkable_stack_header* elem = forkable_stack_peek(s);
|
||||||
s->pos = elem->next;
|
s->pos += elem->next_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -165,14 +165,14 @@ program: Exp { *answer = $1; }
|
|||||||
Exp:
|
Exp:
|
||||||
"def" IDENT ':' Exp ';' Exp {
|
"def" IDENT ':' Exp ';' Exp {
|
||||||
block body = block_join($4, gen_op_simple(RET));
|
block body = block_join($4, gen_op_simple(RET));
|
||||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body),
|
$$ = block_bind(gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body),
|
||||||
$6, OP_IS_CALL_PSEUDO);
|
$6, OP_IS_CALL_PSEUDO);
|
||||||
jv_free($2);
|
jv_free($2);
|
||||||
} |
|
} |
|
||||||
|
|
||||||
"def" IDENT '(' IDENT ')' ':' Exp ';' Exp {
|
"def" IDENT '(' IDENT ')' ':' Exp ';' Exp {
|
||||||
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
|
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
|
||||||
$$ = block_bind(gen_op_block_defn(CLOSURE_CREATE, jv_string_value($2), body), $9, OP_IS_CALL_PSEUDO);
|
$$ = block_bind(gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body), $9, OP_IS_CALL_PSEUDO);
|
||||||
jv_free($2);
|
jv_free($2);
|
||||||
jv_free($4);
|
jv_free($4);
|
||||||
} |
|
} |
|
||||||
|
|||||||
@@ -262,6 +262,12 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x
|
|||||||
999999999
|
999999999
|
||||||
[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
|
[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
|
||||||
|
|
||||||
|
# test recursion
|
||||||
|
def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac]
|
||||||
|
[1,2,3,4]
|
||||||
|
[1,2,6,24]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Assignment
|
# Assignment
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in new issue
Block a user