Use blocks for attribute accessors in Struct to facilitate proper aliasing behavior #91

Merged
merged 8 commits into from May 31, 2012

Projects

None yet

3 participants

@macrotis

Consider the following code:

class Large < Struct.new(:one, :two, :three, :four, :five, :six, :seven, :eight, :nine, :ten, :eleven)
  alias :o :one
  alias :o= :one=
  alias :l :eleven
  alias :l= :eleven=
end

l = Large.new
['o', 'l'].each do |s|
  ['', '='].each do |t|
    begin
      m = s + t
      if t != '=' then
        l.send(m.to_sym)
      else
        l.send(m.to_sym, 4)
      end
      puts "SUCCESS: alias #{m} calls the attribute accessor"
    rescue
      puts "FAILURE: alias #{m} does not call the attribute accessor"
    end
  end
end

The expected output:

SUCCESS: alias o calls the attribute accessor
SUCCESS: alias o= calls the attribute accessor
SUCCESS: alias l calls the attribute accessor
SUCCESS: alias l= calls the attribute accessor

The output as of 69434c9 and release 0.11:

SUCCESS: alias o calls the attribute accessor
FAILURE: alias o= does not call the attribute accessor
FAILURE: alias l does not call the attribute accessor
FAILURE: alias l= does not call the attribute accessor

That is, no alias to an attribute writer of a class derived from Struct will function (attempting to send it a message yields a NameError), and only aliases to attribute readers of the first ten members work properly (similarly, any other attempt to access a member through an alias yields a NameError).

These changes re-implement the Struct attribute accessor methods as blocks in struct.c. Each block is generated in the scope of the for-loop which adds accessor methods to the Objective-C runtime, saving the offset of the member in the block's own scope. The generation of compatible Objective-C method implementations from blocks was officially introduced to OS X in Lion, but by using landonf/plblockimp@372da0b it should work on Snow Leopard as well.

I've only been able to test this on Lion, but it does pass all the same tests as 69434c9 while fixing the issue.

@Watson1978
Member

Hmm, this reqesut can't build on Snow Leopard.

@macrotis

That's odd, plblockimp should support Snow Leopard. Can you post the output of rake up to the failure point?

@Watson1978
Member

Oh, sorry. I needed to clean build. I removed only "./objs" when copied local repository from Lion and compiled it on Snow Leopard.

@Watson1978
Member

It seems to me that this request is good.
However, it will be pulled after releasing 0.12 since this request looks big.

@ferrous26
Member

Is this safe to merge into master now?

@Watson1978
Member

@ferrous26 I think this is safe, however, master version should be up to 0.13(1.0?) before merging :)
https://github.com/MacRuby/MacRuby/blob/master/version.h#L10

@ferrous26 ferrous26 merged commit b7c9b70 into MacRuby:master May 31, 2012
@ferrous26
Member

@macrotis thank you for the fixes! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment