Class: Rubycc::Type::EnumType

Inherits:
Object
  • Object
show all
Defined in:
lib/rubycc/type.rb

Overview

An incomplete enumeration type: a reference to an "enum tag" whose enumerator list is not visible (a forward-referenced tag, or one never defined in the translation unit). A complete enum has no dedicated type here — an enum object is an int (6.7.2.2), so #parse_enum_specifier resolves a defined tag straight to Type::Int. This class exists only so an incomplete enum can flow exactly where an incomplete struct may (a pointer's target, a prototype's return type, an extern reference) while any use that needs a size or arithmetic still rejects it. It mirrors an incomplete StructType: every category predicate is false, #complete? is false, and #size/#alignment raise behind the generator's completeness guard. Two are equal when their tags match, so "enum E *" == "enum E *".

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tag) ⇒ EnumType

Returns a new instance of EnumType.



618
619
620
621
# File 'lib/rubycc/type.rb', line 618

def initialize(tag)
  @tag = tag
  @complete = false
end

Instance Attribute Details

#tagObject (readonly)

Returns the value of attribute tag.



616
617
618
# File 'lib/rubycc/type.rb', line 616

def tag
  @tag
end

Instance Method Details

#==(other) ⇒ Object

Value equality by tag while incomplete, so two references to the same undefined tag share a type (which is what a tentative-definition merge and a redeclaration check compare). Once completed, an enum object is an int, so a completed enum is equal to Type::Int (and to any other completed enum) — this is the identity a function-type compatibility check needs when "enum efoo (*)(void)" (resolved to int post-definition) is assigned a function returning the once-incomplete "enum efoo".



723
724
725
726
727
728
729
730
731
# File 'lib/rubycc/type.rb', line 723

def ==(other)
  if @complete
    return true if other.equal?(Type::Int)
    return other.complete? if other.is_a?(EnumType)

    return false
  end
  other.is_a?(EnumType) && !other.complete? && other.tag == tag
end

#alignmentObject



710
711
712
713
714
# File 'lib/rubycc/type.rb', line 710

def alignment
  raise "incomplete enum has no alignment" unless @complete

  4
end

#arithmetic?Boolean

Returns:

  • (Boolean)


646
647
648
# File 'lib/rubycc/type.rb', line 646

def arithmetic?
  @complete
end

#array?Boolean

Returns:

  • (Boolean)


666
667
668
# File 'lib/rubycc/type.rb', line 666

def array?
  false
end

#bool?Boolean

Returns:

  • (Boolean)


662
663
664
# File 'lib/rubycc/type.rb', line 662

def bool?
  false
end

#char?Boolean

Returns:

  • (Boolean)


631
632
633
# File 'lib/rubycc/type.rb', line 631

def char?
  false
end

#complete!Object

Completes this forward-referenced enum in place: the object that stood in for an undefined tag starts answering as the int an enum object is. Idempotent, since one tag may complete after several incomplete references captured the same object.



697
698
699
700
# File 'lib/rubycc/type.rb', line 697

def complete!
  @complete = true
  self
end

#complete?Boolean

A forward-referenced enum tag ("enum efoo;" before its "...") is incomplete until #register_enum_tag sees the definition. A defined enum normally resolves straight to Type::Int, so completion is modeled on the object only for the one case that captured this incomplete type before the definition (a prototype's return type, "enum efoo it_real_fn(void)"). #complete! then turns that very object into an int in place, so both the earlier reference and the later "enum efoo" (an int) agree.

Returns:

  • (Boolean)


689
690
691
# File 'lib/rubycc/type.rb', line 689

def complete?
  @complete
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


733
734
735
# File 'lib/rubycc/type.rb', line 733

def eql?(other)
  self == other
end

#float?Boolean

Returns:

  • (Boolean)


678
679
680
# File 'lib/rubycc/type.rb', line 678

def float?
  false
end

#function?Boolean

Returns:

  • (Boolean)


674
675
676
# File 'lib/rubycc/type.rb', line 674

def function?
  false
end

#hashObject



737
738
739
# File 'lib/rubycc/type.rb', line 737

def hash
  [EnumType, tag].hash
end

#int?Boolean

Returns:

  • (Boolean)


627
628
629
# File 'lib/rubycc/type.rb', line 627

def int?
  false
end

#integer?Boolean

Once completed, an enum object is an int (6.7.2.2), so the integer predicates and measurements answer as int does. Before completion every one is false/raising, exactly as for any other incomplete type.

Returns:

  • (Boolean)


642
643
644
# File 'lib/rubycc/type.rb', line 642

def integer?
  @complete
end

#pointer?Boolean

Returns:

  • (Boolean)


623
624
625
# File 'lib/rubycc/type.rb', line 623

def pointer?
  false
end

#signed?Boolean

Returns:

  • (Boolean)


650
651
652
653
654
# File 'lib/rubycc/type.rb', line 650

def signed?
  raise "incomplete enum has no signedness" unless @complete

  true
end

#sizeObject

Guarded like Type::Void and an incomplete StructType while incomplete; once completed it measures like int (4 bytes, 4-byte aligned).



704
705
706
707
708
# File 'lib/rubycc/type.rb', line 704

def size
  raise "incomplete enum has no size" unless @complete

  4
end

#struct?Boolean

Returns:

  • (Boolean)


670
671
672
# File 'lib/rubycc/type.rb', line 670

def struct?
  false
end

#to_sObject



741
742
743
# File 'lib/rubycc/type.rb', line 741

def to_s
  "enum #{tag}"
end

#unsigned?Boolean

Returns:

  • (Boolean)


656
657
658
659
660
# File 'lib/rubycc/type.rb', line 656

def unsigned?
  raise "incomplete enum has no signedness" unless @complete

  false
end

#void?Boolean

Returns:

  • (Boolean)


635
636
637
# File 'lib/rubycc/type.rb', line 635

def void?
  false
end