diff options
author | Nicolas Williams <nico@cryptonector.com> | 2014-07-01 22:40:40 -0500 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2014-07-01 22:40:40 -0500 |
commit | 9deee38dc8b419bf9401cc04ccc0aeca47052658 (patch) | |
tree | 76d3ec7006fc20c874de33dd42bb6c334527444e /execute.c | |
parent | 436941d48b1d89a3663c1173f382ea9e2688a61f (diff) |
Fix off-by-one in TCO
Now we have the ability to define a generator in jq:
def for(cond; update):
def _for:
if cond then ., (update | _for) else . end;
_for;
for(. < 10; . + 1) # generates numbers between `.` and 10
Running this by hand with --debug-dump-disasm (with a fix for that
coming up next) we can see that the call to _for is optimized:
_for:0:
0000 DUP
0001 CALL_JQ cond:0^1
0005 JUMP_F 0022
0007 POP
0008 FORK 0012
0010 JUMP 0020
0012 CALL_JQ update:1^1
0016 TAIL_CALL_JQ _for:0^1
0020 JUMP 0023
0022 POP
0023 RET
And timing this with 1000, 10000, 100000 iterations shows that
indeed we must be applying TCO; otherwise, without TCO, this gets
very slow very quickly.
Diffstat (limited to 'execute.c')
-rw-r--r-- | execute.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -801,7 +801,7 @@ static int ret_follows(uint16_t *pc) { return 1; if (*pc++ != JUMP) return 0; - return ret_follows(pc + *pc); // FIXME, might be ironic + return ret_follows(pc + *pc + 1); // FIXME, might be ironic } /* |