microsoft/BosqueLanguage

List.sort can't use custom functions

brakmic opened this issue · 3 comments

Describe the bug

Currently, List.sort has LessFunctor as its "default" lambda in cppbody_emitter.ts (as commited by me in PR #291). This of course should be made more flexible.

For example, List.filter uses pcode from idecl map and in fact List.sort is also able to generate those pcodes but they seem to disappear while going through various internal functions (located in cppdecls_emitter.ts and mir_emitter.ts).

I have tried to track it down, but wasn't 100% successful. But the fact is, that List.sort creates a proper pcode entry that looks like this when printed in console.

{
   "code": "fn--sort.bsq%5%0",
   "cargs": []
}

Example Code

namespace NSMain;

entrypoint function main(): List<Int> {
  let nums = List<Int>@{5, 6, 3, 8, 0, 11, 23};
  return nums.sort(fn(a, b) => a > b);
}

However, after going through various functions it then "disappears" leaving an undefined variable behind, which then provokes an error when I use this line in generateBuiltinBody from cppbody_emitter.ts

const lambda = this.createLambdaFor(idecl.pcodes.get("p") as MIRPCode);
Error -- TypeError: Cannot read property 'code' of undefined

But this should be possible, because List.filter does the same and it's behavior is very similar to List.sort.

However, as I still don't know much about the internals of Bosque, I don't see a way how to fix this properly.

The compiler "defunctionalizes" the lambdas into first order functions. So, in your example it converts sort(fn(a, b) => a > b) into top level functions that are specialized for each different lambda invocation.

The code in the createLambdaFor helper should access this correctly when you give it the parameter name of the lambda function, which for sort should be cmp instead of p.

The compiler "defunctionalizes" the lambdas into first order functions. So, in your example it converts sort(fn(a, b) => a > b) into top level functions that are specialized for each different lambda invocation.

The code in the createLambdaFor helper should access this correctly when you give it the parameter name of the lambda function, which for sort should be cmp instead of p.

Oops, I didn't expect it to be that easy. Thanks!
This is maybe the "don't see the forest for the trees" moment for me :)

Yes, it works. Will open a PR.