c_extensions/c_classes_no_parens.rb

tests/_examples/c_extensions/c_classes_no_parens.rb in the metorex repository.

# A C extension working with classes: calling the method a C method
# overrides, paths, instance methods by visibility, new classes and
# instances, superclasses, class variables, attributes, included modules,
# type tags, and the checks rb_define_class_under makes.
require "tmpdir"
require_relative "build_helper"

class Greeting
  def text
    "hello"
  end

  def repeat count
    "hello " * count
  end

  def itself_from_super
    self
  end
end

class LoudGreeting < Greeting
end

class LouderGreeting < LoudGreeting
end

directory = Dir.mktmpdir
require build_extension("c_classes.c", "c_classes", directory)
classes = CClasses.new

classes.super_calling LoudGreeting, "text"
classes.super_calling LouderGreeting, "text"
classes.super_calling_with LoudGreeting, "repeat"
classes.super_calling LoudGreeting, "itself_from_super"
classes.super_calling LoudGreeting, "nothing_above"
loud = LoudGreeting.new
p [LouderGreeting.new.text, loud.repeat(2), loud.itself_from_super.equal?(loud)]
report { loud.nothing_above }

module Outer
  class Inner
  end

  VALUE = 1
end
p [classes.path(Outer::Inner), classes.path(File::Stat)]
p [classes.path2class("Outer::Inner"), classes.path_to_class("Outer")]
report { classes.path2class "Outer::Missing" }
report { classes.path2class "Outer::String" }
report { classes.path_to_class "Outer::VALUE" }

class Visibilities
  def shown
  end

  protected

  def guarded
  end

  private

  def hidden
  end
end
p classes.instance_methods_of(Visibilities, false)

made = classes.class_new(Greeting)
p [made.superclass, made.name, made.new.text]
report { classes.class_new Class }
report { classes.class_new Object.new.singleton_class }
report { classes.class_new Comparable }

class Options
  attr_reader :positional, :keywords

  def initialize(*positional, **keywords)
    @positional = positional
    @keywords = keywords
  end
end
built = classes.new_instance_kw([{ first: 1 }, { second: 2 }], Options)
p [built.positional, built.keywords]
report { classes.new_instance_kw [42], Options }

special = LoudGreeting.new
def special.extra
end
p [classes.real(special), classes.real(LoudGreeting.new), classes.real_of_null]
p [classes.superclasses(LoudGreeting), classes.superclasses(BasicObject)]
report { classes.superclasses Comparable }

class Counted
  @@count = 0
  @level = 1
end
p [classes.cvar_defined(Counted, "@@count"), classes.cvar_defined(Counted, "@@other"), classes.cvar_defined(Counted, "@level")]
p classes.cvars(Counted)
p Counted.class_variables.sort
report { classes.cv_get Counted, "@@missing" }

class Stored
  def initialize
    @readable = 1
    @both = 3
  end
end
classes.attrs Stored
stored = Stored.new
stored.writable = 2
stored.both = 4
p [stored.readable, stored.instance_variable_get(:@writable), stored.both]
report { stored.readable = 5 }

module Waves
  def wave
    :waving
  end
end
p classes.include_module(Class.new, Waves).new.wave

p [1, nil, true, false, 1.5, "text", :text, [], {}, Object, Kernel, 2**70, 1..2, Object.new].map { |held| classes.type_of(held) }
p [classes.is_type(1, CClasses::T_FIXNUM), classes.is_type("text", CClasses::T_STRING), classes.is_type(1, CClasses::T_STRING)]

report { classes.define_class Outer, "NoParent", nil }
report { classes.define_class Outer, "FromModule", Comparable }
report { classes.define_class Outer, "Inner", Greeting }
report { classes.define_class Outer, "VALUE", Object }
report { classes.define_class Object, "LoudGreeting", Object }
hidden = classes.define_class(Outer, "_hidden", Greeting)
p [hidden.name, classes.define_class(Outer, "_hidden", Greeting).equal?(hidden)]

FileUtils.rm_rf directory

Output:

["hello", "hello hello ", true]
NoMethodError: super: no superclass method 'nothing_above' for an instance of LoudGreeting
["Outer::Inner", "File::Stat"]
[Outer::Inner, Outer]
ArgumentError: undefined class/module Outer::Missing
ArgumentError: undefined class/module Outer::String
TypeError: Outer::VALUE does not refer to class/module
[[:guarded, :shown], [:shown], [:guarded], [:hidden]]
[Greeting, nil, "hello"]
TypeError: can't make subclass of Class
TypeError: can't make subclass of singleton class
TypeError: superclass must be an instance of Class (given an instance of Module)
[[{first: 1}], {second: 2}]
TypeError: no implicit conversion of Integer into Hash
[LoudGreeting, LoudGreeting, true]
[[Greeting, Greeting], [nil, false]]
NoMethodError: undefined method 'superclass' for module Comparable
[true, false, true]
[1, 2, 3]
[:@@by_id, :@@by_name, :@@count, :@@defined]
NameError: uninitialized class variable @@missing in Counted
[1, 2, 4]
NoMethodError: undefined method 'readable=' for an instance of Stored
:waving
[21, 17, 18, 19, 4, 5, 20, 7, 8, 2, 3, 10, 9, 1]
[true, true, false]
ArgumentError: no super class for 'Outer::NoParent'
TypeError: superclass must be an instance of Class (given an instance of Module)
TypeError: superclass mismatch for class Outer::Inner (Greeting is given but was Object)
TypeError: Outer::VALUE is not a class (Integer)
TypeError: superclass mismatch for class LoudGreeting
["Outer::_hidden", true]