1. my class Attribute { # declared in BOOTSTRAP
  2. # class Attribute is Any
  3. # has str $!name;
  4. # has int $!rw;
  5. # has int $!has_accessor;
  6. # has Mu $!type;
  7. # has Mu $!container_descriptor;
  8. # has Mu $!auto_viv_container;
  9. # has Mu $!build_closure;
  10. # has Mu $!package;
  11. # has int $!inlined;
  12. # has int $!positional_delegate;
  13. # has int $!associative_delegate;
  14. # has Mu $!why;
  15. # has int $!required;
  16. # has Mu $!container_initializer;
  17. method compose(Mu $package, :$compiler_services) {
  18. # Generate accessor method, if we're meant to have one.
  19. if self.has_accessor {
  20. my str $name = nqp::unbox_s(self.name);
  21. my $meth_name := nqp::substr($name, 2);
  22. unless $package.^declares_method($meth_name) {
  23. my $dcpkg := nqp::decont($package);
  24. my $meth;
  25. my int $attr_type = nqp::objprimspec($!type);
  26. # Get the compiler to generate us an accessor when possible.
  27. if $compiler_services.DEFINITE {
  28. $meth := $compiler_services.generate_accessor($meth_name,
  29. $dcpkg, $name, $!type, self.rw ?? 1 !! 0);
  30. }
  31. # No compiler services available, so do it as a closure.
  32. elsif self.rw {
  33. $meth := nqp::p6bool(nqp::iseq_i($attr_type, 0))
  34. ??
  35. method (Mu:D \fles:) is raw {
  36. nqp::getattr(nqp::decont(fles), $dcpkg, $name)
  37. }
  38. !!
  39. nqp::p6bool(nqp::iseq_i($attr_type, 1))
  40. ??
  41. method (Mu:D \fles:) is raw {
  42. nqp::getattrref_i(nqp::decont(fles), $dcpkg, $name)
  43. }
  44. !!
  45. nqp::p6bool(nqp::iseq_i($attr_type, 2))
  46. ??
  47. method (Mu:D \fles:) is raw {
  48. nqp::getattrref_n(nqp::decont(fles), $dcpkg, $name)
  49. }
  50. !!
  51. method (Mu:D \fles:) is raw {
  52. nqp::getattrref_s(nqp::decont(fles), $dcpkg, $name)
  53. }
  54. $meth.set_name($meth_name);
  55. } else {
  56. # ro accessor
  57. $meth := nqp::p6bool(nqp::iseq_i($attr_type, 0))
  58. ??
  59. method (Mu:D \fles:) {
  60. nqp::getattr(nqp::decont(fles), $dcpkg, $name)
  61. }
  62. !!
  63. nqp::p6bool(nqp::iseq_i($attr_type, 1))
  64. ??
  65. method (Mu:D \fles:) {
  66. nqp::p6box_i(
  67. nqp::getattr_i(nqp::decont(fles), $dcpkg, $name)
  68. );
  69. }
  70. !!
  71. nqp::p6bool(nqp::iseq_i($attr_type, 2))
  72. ??
  73. method (Mu:D \fles:) {
  74. nqp::p6box_n(
  75. nqp::getattr_n(nqp::decont(fles), $dcpkg, $name)
  76. );
  77. }
  78. !!
  79. method (Mu:D \fles:) {
  80. nqp::p6box_s(
  81. nqp::getattr_s(nqp::decont(fles), $dcpkg, $name)
  82. );
  83. }
  84. $meth.set_name($meth_name);
  85. }
  86. $package.^add_method($meth_name, $meth);
  87. }
  88. }
  89. # Apply any handles trait we may have.
  90. self.apply_handles($package);
  91. }
  92. method apply_handles(Mu $pkg) {
  93. # None by default.
  94. }
  95. method get_value(Mu $obj) {
  96. nqp::if(
  97. nqp::iseq_i((my int $t = nqp::objprimspec($!type)),0),
  98. nqp::getattr(nqp::decont($obj),$!package,$!name),
  99. nqp::if(
  100. nqp::iseq_i($t,1),
  101. nqp::p6box_i(nqp::getattr_i(nqp::decont($obj),$!package,$!name)),
  102. nqp::if(
  103. nqp::iseq_i($t,2),
  104. nqp::p6box_n(nqp::getattr_n(nqp::decont($obj),
  105. $!package,$!name)),
  106. nqp::if(
  107. nqp::iseq_i($t,3),
  108. nqp::p6box_s(nqp::getattr_s(nqp::decont($obj),
  109. $!package,$!name))
  110. )
  111. )
  112. )
  113. )
  114. }
  115. method set_value(Mu $obj, Mu \value) {
  116. nqp::if(
  117. nqp::iseq_i((my int $t = nqp::objprimspec($!type)),0),
  118. nqp::bindattr(nqp::decont($obj),$!package,$!name,value),
  119. nqp::if(
  120. nqp::iseq_i($t,1),
  121. nqp::p6box_i(nqp::bindattr_i(nqp::decont($obj),
  122. $!package,$!name,value)),
  123. nqp::if(
  124. nqp::iseq_i($t,2),
  125. nqp::p6box_n(nqp::bindattr_n(nqp::decont($obj),
  126. $!package,$!name,value)),
  127. nqp::if(
  128. nqp::iseq_i($t,3),
  129. nqp::p6box_s(nqp::bindattr_s(nqp::decont($obj),
  130. $!package,$!name,value))
  131. )
  132. )
  133. )
  134. )
  135. }
  136. method container() is raw { nqp::ifnull($!auto_viv_container,Nil) }
  137. method readonly() { !self.rw }
  138. method package() { $!package }
  139. method inlined() { $!inlined }
  140. multi method Str(Attribute:D:) { self.name }
  141. multi method gist(Attribute:D:) { self.type.^name ~ " " ~ self.name }
  142. method WHY() {
  143. if nqp::isnull($!why) {
  144. Nil
  145. } else {
  146. $!why.set_docee(self);
  147. $!why
  148. }
  149. }
  150. method set_why($why) {
  151. $!why := $why;
  152. }
  153. }