sweet-js/sweet-core

Accessing the original operator when creating Operator

Jamesernator opened this issue · 1 comments

A pain point I hit really quickly with trying to use operator macro was trying to permit operator overloading using macros, but I quickly realised there doesn't seem to be any way to access the original operator, because even if I try to implement another operator which has the original it also gets replaced.

As an example:

operator + left 12 = (left, right) => {
    return #`(${ left })[Symbol.add](${ right })`
}

Symbol.add = Symbol('Symbol.add')

Number.prototype[Symbol.add] = function(other) {
    // Obviously this a no-go as the operator will get replaced
    return this + other
}

console.log(3 + 4)

So that doesn't work as all operators get replaced in all contexts which is fine, but then I tried adding a second operator to access the original:

operator $plus left 13 = (left, right) => {
    return #`${ left } + ${ right }`
}

operator + left 13 = (left, right) => {
    return #`(${ left })[Symbol.add](${ right })`
}

Symbol.add = Symbol('Symbol.add')

Number.prototype[Symbol.add] = function(other) {
    "use strict"
    return this $plus other
}

console.log(3 + 4)

But this still doesn't work because this $plus other gets replaced with this + other then replaced again with this[Symbol.add](other).


What'd be nice is if we could protect some code from being affected by macros:

Number.prototype[Symbol.add] = function(other) {
    #nomacro {
        return this + other
    }

    // Or maybe if we could exclude specific macros
    #nomacro + {
        return this + other
    }
    
    // Such blocks would be scopable as nearby as needed:
    return #nomacro + { this + other }
}

The syntax above is just for exposition, while not strictly necessary (I could just define a library of normal operators and import it) I think it would make operator a lot more usable.

EDIT: The library definition operators workaround I suggested won't work at all for lazy operators or special tokens like => that aren't really operators just tokens.

I would suggest defining Number.prototype[Symbol.add] in another file in the mean time.