effekt-lang / effekt

A research language with effect handlers and lightweight effect polymorphism

Home Page:https://effekt-lang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Structural equality on JavaScript backend doesn't work

jiribenes opened this issue · comments

The structural equality on the JavaScript backend seems to be broken.
Although reflexivity (x == x) holds for simple, user-defined types, it doesn't work for Some(x) == Some(x).

type MyType {
  MySingleCase()
}

record EmptyRecord()

def main() = {
  println(MySingleCase() == MySingleCase())   // ~> true
  println(EmptyRecord() == EmptyRecord())     // ~> true

  println(Some(MySingleCase()) == Some(MySingleCase())) // ~> false
  println(Some(EmptyRecord()) == Some(EmptyRecord()))   // ~> false
}

val other = freshName("other")
def otherGet(field: JSName): js.Expr = js.Member(js.Variable(other), field)
def compare(field: JSName): js.Expr = js"${get(field)} !== ${otherGet(field)}"
val noop = js.Block(Nil)
val abort = js.Return(js"false")
val succeed = js.Return(js"true")
val otherExists = js.If(js"!${js.Variable(other)}", abort, noop)
val compareTags = js.If(compare(`tag`), abort, noop)
val compareFields = params.map(f => js.If(compare(f), abort, noop))
val jsEquals: js.Function = js.Function(`equals`, List(other), otherExists :: compareTags :: compareFields ::: List(succeed))

Line 54 is not correct, we should use equals$impl or something similar here in order to recurse.
Currently, we compare:

  1. the first "layer" structurally
  2. the other layer just based on JavaScript's === equality

One should call this:

$effekt.equals = function(obj1, obj2) {