caramel icon indicating copy to clipboard operation
caramel copied to clipboard

Should && and || translate to short-circuiting andalso and orelse?

Open michallepicki opened this issue 5 years ago • 3 comments

To Reproduce

  1. Create a file main.ml with
let print_int number = Io.format "~0tp~n" [ number ]

let print_and_return_true number =
  print_int number ;
  true

let main _ =
  print_int 0 ;
  false && print_and_return_true 1 ;
  true || print_and_return_true 2 ;
  print_int 3
  1. Run command caramel compile main.ml && escript main.erl
  2. See result:
0
1
2
3

Expected behavior If the operators should be short-circuiting, the correct result would be:

0
3

just like when running this ocaml file:

(* let print_int number = Io.format "~0tp~n" [ number ] *)

let print_and_return_true number =
  print_int number ;
  true ;;

let main _ =
  print_int 0 ;
  false && print_and_return_true 1 ;
  true || print_and_return_true 2 ;
  print_int 3 ;;

main ()
$ ocaml main.ml
0
3

If the operators should be short-circuiting, I think the correct Erlang to generate here might be:

-spec main(_) -> ok.
main(_) ->
  print_int(0),
  false andalso print_and_return_true(1),
  true orelse print_and_return_true(2),
  print_int(3).

Environment (please complete the following information):

  • OS: Ubuntu Linux 18.04
  • Caramel version: 0.1
  • Erlang version: 23.2.2

michallepicki avatar Feb 11 '21 11:02 michallepicki

I am not super sure about the short-circuit operators semantics in OCaml, I found this issue that confuses me more than helps: https://stackoverflow.com/questions/23833221/order-of-evaluation-for-short-circuit-operators-and-let-in-ocaml

But in general, OCaml stdlib documentation says they should be short-circuiting, so I think they should translate to andalso and orelse as noted above.

michallepicki avatar Feb 11 '21 11:02 michallepicki

I looked into fixing this and it seems that the way the code generation currently works, it would be easiest to have additional functions in caramel_runtime because andalso and orelse are not functions exported from the erlang module. I am honestly surprised the other operators are. I think there's no guarantee that it will stay this way as they are not documented there.

Should I send a PR that adds those functions to the runtime module? I think ideally all operators would get inlined without additional function calls but I understand this would complicate supporting passing them as arguments to higher order functions.

edit: but then, if these would work through a function call, they would no longer be short-circuiting anymore I think (?)

michallepicki avatar Feb 11 '21 22:02 michallepicki

edit: comment moved to https://github.com/AbstractMachinesLab/caramel/issues/70

michallepicki avatar Feb 12 '21 09:02 michallepicki