a new idea for modelling nested recursion
Haldean Brown
4 years ago

109 | 109 | : inner_with_inner_ = inner_with_x_ inner_with_x_ |

110 | 110 | } |

111 | 111 | |

112 | But that doesn't work either. Hm. | |

112 | But that doesn't work either. Hm. Instead, we introduce a secret atom type, | |

113 | SELFREF, which is a reference to the innermost enclosing function. So we end up | |

114 | rewriting inner to be: | |

115 | ||

116 | : inner = (\x y -> { | |

117 | : inner = SELFREF x | |

118 | ! inner (+ x y) | |

119 | }) x | |

120 | ||

121 | Now the "inner" on the inside doesn't actually reference a named binding on the | |

122 | outside. When this is compiled down to a graph, SELFREF will be transformed | |

123 | into a VALUE node that points at the value currently being compiled. | |

124 | ||

125 | With more-heavily-nested recursion, this ends up transforming: | |

126 | ||

127 | : outer = \a -> { | |

128 | : inner = \b -> outer (+ (inner a) b) | |

129 | ! inner a | |

130 | } | |

131 | ||

132 | Into: | |

133 | ||

134 | : outer = \a -> { | |

135 | : outer = SELFREF | |

136 | : inner = (\a outer b -> { | |

137 | : inner = SELFREF a outer | |

138 | ! outer (+ inner a) b | |

139 | } | |

140 | } | |

141 | ||

142 | Which actually ends up being pretty pleasantly readable. |