git @ Cat's Eye Technologies
Properly handle `letrec` of functions with more than one argument. Chris Pressey 6 months ago
3 changed file(s) with 51 addition(s) and 9 deletion(s).
 99 99 hygiene. 100 100 * The transformation should retain the names of the original 101 101 arguments of the functions. 102 * There needs to be a test confirming that it can handle multiple 103 arguments in the original functions. 104 102 105 103 Appendix A 106 104 ---------- 287 285 in 288 286 if oddp(target) then factopen(factopen, target) else 0 289 287 ===> 5040 288 289 `letrec` works on functions that have more than one argument. 290 291 letrec 292 oddsump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then false else evensump(sub(x, 1), y, z) 293 evensump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then true else oddsump(sub(x, 1), y, z) 294 in 295 evensump(5,3,1) 296 ===> false 297 298 letrec 299 oddsump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then false else evensump(sub(x, 1), y, z) 300 evensump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then true else oddsump(sub(x, 1), y, z) 301 in 302 evensump(6,3,1) 303 ===> true 304 305 -> Tests for functionality "Desugar Lanthorn Program" 306 307 Let's see how that gets desugared. The innermost `let`s bind the plain 308 names to functions with the same arity as the original functions. 309 310 letrec 311 oddsump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then false else evensump(sub(x, 1), y, z) 312 evensump = fun(x,y,z) -> if eq(add(x, add(y, z)), add(y, z)) then true else oddsump(sub(x, 1), y, z) 313 in 314 evensump(5,3,1) 315 => let 316 => oddsump0 = fun(x, y, z, oddsump1, evensump1) -> let 317 => oddsump = fun(x1, y1, z1) -> oddsump1(x1, y1, z1, oddsump1, evensump1) 318 => evensump = fun(x1, y1, z1) -> evensump1(x1, y1, z1, oddsump1, evensump1) 319 => in 320 => if eq(add(x, add(y, z)), add(y, z)) then false else evensump(sub(x, 1), y, z) 321 => evensump0 = fun(x, y, z, oddsump1, evensump1) -> let 322 => oddsump = fun(x1, y1, z1) -> oddsump1(x1, y1, z1, oddsump1, evensump1) 323 => evensump = fun(x1, y1, z1) -> evensump1(x1, y1, z1, oddsump1, evensump1) 324 => in 325 => if eq(add(x, add(y, z)), add(y, z)) then true else oddsump(sub(x, 1), y, z) 326 => oddsump = fun(x, y, z) -> oddsump0(x, y, z, oddsump0, evensump0) 327 => evensump = fun(x, y, z) -> evensump0(x, y, z, oddsump0, evensump0) 328 => in 329 => evensump(5, 3, 1)
 21 21 [ 22 22 ("true", Boolean True), 23 23 ("false", Boolean False), 24 ("add", Function (\[Number a, Number b] -> Number (a + b))), 24 25 ("sub", Function (\[Number a, Number b] -> Number (a - b))), 25 26 ("mul", Function (\[Number a, Number b] -> Number (a * b))), 26 27 ("eq", Function (\[a, b] -> Boolean (a == b)))
 33 33 let 34 34 name' = wrapperNameOuter name 35 35 formals' = formals ++ (map (wrapperNameInner) injecteds) 36 body' = (LetStar (createLocalBindings injecteds injecteds) body) 36 body' = (LetStar (createLocalBindings injecteds injecteds formals) body) 37 37 expr' = (Fun formals' body') 38 38 binding = (name', expr') 39 39 in 41 41 createEnrichedBindings (binding:rest) injecteds = 42 42 (binding:createEnrichedBindings rest injecteds) 43 43 44 createLocalBindings [] _ = [] 45 createLocalBindings (injected:injecteds) allInjecteds = 44 createLocalBindings [] _ _ = [] 45 createLocalBindings (injected:injecteds) allInjecteds formals = 46 46 let 47 -- FIXME use the real formals of each injected identifier! also, allow shadowing! 48 actuals = map (ValueOf) (["x1"] ++ (map (wrapperNameInner) allInjecteds)) 49 binding = (injected, Fun ["x1"] (Apply (wrapperNameInner injected) actuals)) 47 formals' = map (wrapperNameInner) formals 48 actuals = map (ValueOf) (formals' ++ (map (wrapperNameInner) allInjecteds)) 49 binding = (injected, Fun formals' (Apply (wrapperNameInner injected) actuals)) 50 rest = createLocalBindings injecteds allInjecteds formals 50 51 in 51 (binding:createLocalBindings injecteds allInjecteds) 52 (binding:rest) 52 53 53 54 createWrapperBindings [] injecteds = [] 54 55 createWrapperBindings ((name, (Fun formals body)):rest) injecteds =