aboutsummaryrefslogtreecommitdiff
path: root/include/apply.s
diff options
context:
space:
mode:
authorMirek Kratochvil <exa.exa@gmail.com>2023-08-11 22:30:22 +0200
committerMirek Kratochvil <exa.exa@gmail.com>2023-08-11 22:30:22 +0200
commit5184299c7dfddeba4d2d2ba95d390040368f9736 (patch)
treee3debfdc11073435a5459266d6dcec61b1fc30b1 /include/apply.s
parent74cad993376dc269e8389fbf150be9ecc36890c7 (diff)
downloaduskel-5184299c7dfddeba4d2d2ba95d390040368f9736.tar.gz
uskel-5184299c7dfddeba4d2d2ba95d390040368f9736.tar.bz2
ap aps
Diffstat (limited to 'include/apply.s')
-rw-r--r--include/apply.s65
1 files changed, 65 insertions, 0 deletions
diff --git a/include/apply.s b/include/apply.s
new file mode 100644
index 0000000..124e434
--- /dev/null
+++ b/include/apply.s
@@ -0,0 +1,65 @@
+
+.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