.include "include/data.s" # | fun | arg | -> cont .thunkcode apply1 # push a thunk for eval push %rsi # cont push %rbp # ret (self) pushq 030(%rbp) # arg pushq $3 pushq $apply1_fini mov %rsp, %rsi # return to above thunk enter 020(%rbp) # evaluate fun # fun -> | arg | ret | cont | .thunkcode apply1_fini # we now know that fun points to a FUN with at least one arg missing. # we're certainly going to copy a lot of args. mov 020(%rsi), %r11 # amount of args applied now # the copying code is shared so let's do that first: pushq 020(%rbp) #push the new arg lea 030(%rsi), %rdx # the end (first arg) lea (%rdx, %r11, 8), %rbx # address behind the last arg cmp %rdx, %rbx jle apply1_fini_cont apply1_fini_copy: sub $010, %rbx # iterate down pushq (%rbx) # push what we have cmp %rdx, %rbx # check if we are at the end jg apply1_fini_copy # if not, continue apply1_fini_cont: add $1, %r11 pushq %r11 # new number of args of fun/thunk pushq 010(%rsi) # thunk code pointer # copying of all args and their thunky header is now done, let's find # out how we need to finish it. mov (%rsi), %rdi # infotable for the original fun mov -010(%rdi), %r12 # amount of args required to make the thunk cmp %r11, %r12 jg apply1_fini_feed # not enough args, just make a bigger FUN # if there was enough args, we simply have a thunk that we want to # continue evaluating, so let's jump to it. mov 030(%rbp), %rdi # load the original thunk mov %rsp, 010(%rdi) # set indirect to the new thunk movq $IND_code, 0(%rdi) mov 040(%rbp), %rsi # set continuation to the original continuation enter %rsp # evaluate the new thunk apply1_fini_feed: # if there were not enough args, we push the function info and return pushq (%rsi) # copy the function infoptr mov 030(%rbp), %rdi # load the original thunk mov %rsp, 010(%rdi) # set the indirect to the new FUN movq $IND_code, 0(%rdi) mov %rsp, %rsi # return the new FUN enter 040(%rbp) # jump to the continuation # TODO generalize to N args