lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Here it is: imagine to have TWO different userdata types, with different
> tags (T1 and T2). Imagine to have a single binary operator (let's say
> "add"). Now, I can register a tagmethod for T1 and one for T2 (say
> addT1() and addT2()), to add T1 with T1 and T2 with T2. This is OK.
> Sadly, I'd also like to add T1 with T2, but lua calls addT1 if I do
> T1+T2, and calls addT2 if I do T2+T1. It looks like there is no "direct"
> way to register a function addT1T2.
>
> Now, this situation is quite simple and could be managed quite
> efficently, but the "real" situation is that I have more than two types,
> and more than one binary operator.
>
> How would you solve this?

Here is some code to play with. The first bit is your userdata binding, the
second bit is the Lua register operator. Its a bit like trying to do friend
operators in C++. You have to specify the operator explicitly using regop.
Hope this answers your question. You may be able to do what you want by just
wrapping your T1 and T2 add methods and testing the incoming tag types but
this is more general...

Regards,
Nick


-- equivalent to binding
T1 = settag({},newtag())
T2 = settag({},newtag())
function T1:new(i) return settag({v=i or 0},tag(T1)) end
function T2:new(i) return settag({v=i or 0},tag(T2)) end

-- operators of various combinations
function T1:add(t)
  assert(tag(t)==tag(T2))
  return T1:new(self.v+t.v)
end

------------
-- register operators
bintypes = {}

-- make unique key from op and types
function opkey(op,t1,t2) return op..tag(t1)..","..tag(t2) end

function regop(op,t1,t2,fn)
  bintypes[opkey(op,t1,t2)] = fn
end

regop("add",T1,T2,T1.add) -- T1 can add T2

function typeop(op,t1,t2)
  --print (op,t1.v,t2.v)
  local fn = bintypes[opkey(op,t1,t2)]
  assert(fn,"Cannot '"..op.."' on types passed")
  return fn (t1,t2) -- invoke and return result
end

function typeTags(t)
    settagmethod(tag(t),"add",function (t1,t2) return typeop("add",t1,t2)
end )
end

t1,t2 = T1:new(3),T2:new(4)
typeTags(t1)
typeTags(t2)
t1 = t1+t2
print (t1.v)  -- 7

t1 = t2+t1 -- this will fail, T2 cannot take T1 as add arg, can be added