fork download
  1. module Domain
  2. module ClassMethods
  3. %w(byte integer clock12 clock24 signed_byte signed_integer).each do |word|
  4. define_method(word.to_sym) do |name|
  5. register_new_variable word.to_sym, name
  6. end
  7. end
  8.  
  9. private
  10.  
  11. attr_reader :domain_storage
  12.  
  13. def register_new_variable(type, name)
  14. @domain_storage ||= Hash.new { |k, v| k[v] = [] }
  15. @domain_storage[type] << name
  16. end
  17. end # module Domain::ClassMethods
  18.  
  19. #
  20. # -------------------------------------
  21. #
  22.  
  23. module InstanceMethods
  24. def initialize
  25. super
  26.  
  27. hsh = self.class.instance_variable_get('@domain_storage')
  28. return if hsh.nil?
  29.  
  30. hsh.each_pair do |type, methods|
  31. signed, base = case type
  32. when :byte
  33. [false, 256]
  34. when :signed_byte
  35. [true, 256]
  36. when :integer
  37. [false, 65_536]
  38. when :signed_integer
  39. [true, 65_536]
  40. when :clock12
  41. [false, 12]
  42. when :clock24
  43. [false, 24]
  44. end
  45.  
  46. methods.each do |m|
  47. warn "method '#{m}' already defined!" if respond_to?(m) || respond_to?("#{m}=")
  48. reg_read(m, base, signed)
  49. reg_write(m, base)
  50. end
  51. end
  52.  
  53. self.class.instance_eval { remove_instance_variable '@domain_storage' }
  54. undef reg_read, reg_write
  55. end
  56.  
  57. def reg_read(attr, base = nil, signed = false)
  58. self.class.class_eval do
  59. if signed
  60. define_method(attr) do
  61. c = instance_variable_get("@#{attr}")
  62. c > (base / 2) ? c - base : c
  63. end
  64. else
  65. define_method(attr) { instance_variable_get "@#{attr}" }
  66. end
  67. end
  68. end
  69.  
  70. def reg_write(attr, base)
  71. self.class.class_eval do
  72. define_method("#{attr}=") do |other|
  73. raise TypeError, " #{other} is not integer!" unless other.integer?
  74. instance_variable_set "@#{attr}", other % base
  75. end
  76. end
  77. end
  78.  
  79. class DomainError < StandardError; end
  80. class TypeError < DomainError; end
  81. end # module Domain::InstanceMethods
  82.  
  83. #
  84. # -------------------------------------
  85. #
  86.  
  87. module Integers
  88. def self.included(obj)
  89. obj.include InstanceMethods
  90. obj.extend ClassMethods
  91. end
  92. end # module Domain::Integers
  93. end # module Domain
  94.  
  95. #
  96. # -------------------------------------
  97. #
  98.  
  99. class Yoba
  100. include Domain::Integers
  101.  
  102. byte :b
  103. clock12 :cl12
  104.  
  105. end
  106.  
  107. d = Yoba.new
  108. d.b = 1
  109. d.b += 255
  110. puts d.b
  111.  
  112.  
  113. c = Yoba.new
  114. puts c.b
  115.  
  116. c.cl12 = 5
  117. c.cl12 += 10
  118. puts c.cl12
Success #stdin #stdout 0.02s 9784KB
stdin
Standard input is empty
stdout
5
251
100
-116
34464