kadena-io / pact-5

The New Pact
BSD 3-Clause "New" or "Revised" License
9 stars 7 forks source link

Wrong evaluation order during object creation #260

Closed CryptoPascal31 closed 1 month ago

CryptoPascal31 commented 1 month ago

Issue description

As usual, a simple non-working example is always better than a long speech. :)

Steps to reproduce

(module my-mod G
  @doc "A simple module that manages a counter"
  (defcap G() true)

  (defschema counter-schema
    cnt:integer)

  (deftable counter-table:{counter-schema})

  (defun init:string ()
    @doc "Initialize the counter"
    (insert counter-table "SINGLETON" {'cnt:0})
  )

  (defun increment:integer ()
    @doc "Increment the counter and return the old value"
    (with-read counter-table "SINGLETON" {'cnt:=old-value}
      (update counter-table "SINGLETON" {'cnt:(+ 1 old-value)})
      old-value)
  )

)
; Init the counter
(create-table counter-table)
(my-mod.init)

; Create an object with 3 values of the counter
{'a:(my-mod.increment), 'b:(my-mod.increment), 'c:(my-mod.increment)}

Pact 4 has the expected behavior:

{"a": 0,"b": 1,"c": 2}

But Pact 5.0 (recent commit c948d933b2c0ddff15c8809ab69e32f91f1cb20e) gives a different result:

{"a": 2,"b": 1,"c": 0}
jmcardon commented 1 month ago

We will fix this only because this is a particularly simple fix (reversing element order in our parser), but I do think that it's certainly wrong to rely on object field evaluation order when it comes to side effects. In many other languages (e.g C) this would be undefined behavior.