Created
March 17, 2019 02:42
-
-
Save simenge/2d8e0f60b3df3f4e8503319f58eb5c79 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def annotate_tc(s : LispObject) | |
# Automatically annotating tail calls can be tricky, because we need to | |
# properly recurse while terminating at the right points. In particular: | |
# * The last expr in a function body is in tail position (TP) | |
# * If a function call is in TP, we need to annotate it | |
# * If an if expr is in TP, we need to annotate each branch | |
# * If a fn literal is in TP, we need to recursively call annotate_tc. | |
# However, we will not do this from within annotate_tc; rather, | |
# Interpreter#eval_fn, which evaluates a function literal and | |
# returns a Lisp::Lambda object, will call | |
# annotate_tc once it evaluates the inner function | |
# * Otherwise, we need to return the value unchanged | |
# | |
# This function receives only the function body, and returns another | |
# properly annotated function body. | |
return s unless s.is_a?(List) | |
s = s.as(List) | |
last = s[-1] | |
return s unless last.is_a?(List) | |
return s if last.empty? | |
last = last.as List | |
if last.first == sym("if") | |
s[-1] = annotate_tc_if last | |
return s | |
elsif funcall?(last) | |
s[-1].as(List).unshift sym("tailcall") | |
return s | |
else | |
return s | |
end | |
end | |
def annotate_tc_if(s : List) : LispObject | |
if s.size < 3 | |
error("if must have at least 2 args") | |
end | |
_then = s[2] | |
if funcall?(_then) | |
s[2].as(List).unshift sym("tailcall").as(Lisp::Symbol) | |
else | |
s[2] = annotate_tc s[2] | |
end | |
if s.size == 4 | |
if funcall? s[3] | |
s[3].as(List).unshift sym("tailcall").as(Lisp::Symbol) | |
else | |
s[3] = annotate_tc s[3] | |
end | |
end | |
s | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment