module Domain
module ClassMethods
%w(byte integer clock12 clock24 signed_byte signed_integer).each do |word|
define_method(word.to_sym) do |name|
register_new_variable word.to_sym, name
end
end
private
attr_reader :domain_storage
def register_new_variable(type, name)
@domain_storage ||= Hash.new { |k, v| k[v] = [] }
@domain_storage[type] << name
end
end # module Domain::ClassMethods
#
# -------------------------------------
#
module InstanceMethods
def initialize
super
hsh = self.class.instance_variable_get('@domain_storage')
return if hsh.nil?
hsh.each_pair do |type, methods|
signed, base = case type
when :byte
[false, 256]
when :signed_byte
[true, 256]
when :integer
[false, 65_536]
when :signed_integer
[true, 65_536]
when :clock12
[false, 12]
when :clock24
[false, 24]
end
methods.each do |m|
warn "method '#{m}' already defined!" if respond_to?(m) || respond_to?("#{m}=")
reg_read(m, base, signed)
reg_write(m, base)
end
end
self.class.instance_eval { remove_instance_variable '@domain_storage' }
undef reg_read, reg_write
end
def reg_read(attr, base = nil, signed = false)
self.class.class_eval do
if signed
define_method(attr) do
c = instance_variable_get("@#{attr}")
c > (base / 2) ? c - base : c
end
else
define_method(attr) { instance_variable_get "@#{attr}" }
end
end
end
def reg_write(attr, base)
self.class.class_eval do
define_method("#{attr}=") do |other|
raise TypeError, " #{other} is not integer!" unless other.integer?
instance_variable_set "@#{attr}", other % base
end
end
end
class DomainError < StandardError; end
class TypeError < DomainError; end
end # module Domain::InstanceMethods
#
# -------------------------------------
#
module Integers
def self.included(obj)
obj.include InstanceMethods
obj.extend ClassMethods
end
end # module Domain::Integers
end # module Domain
#
# -------------------------------------
#
class Yoba
include Domain::Integers
byte :b
clock12 :cl12
end
d = Yoba.new
d.b = 1
d.b += 255
puts d.b
c = Yoba.new
puts c.b
c.cl12 = 5
c.cl12 += 10
puts c.cl12
bW9kdWxlIERvbWFpbgogIG1vZHVsZSBDbGFzc01ldGhvZHMKICAgICV3KGJ5dGUgaW50ZWdlciBjbG9jazEyIGNsb2NrMjQgc2lnbmVkX2J5dGUgc2lnbmVkX2ludGVnZXIpLmVhY2ggZG8gfHdvcmR8CiAgICAgIGRlZmluZV9tZXRob2Qod29yZC50b19zeW0pIGRvIHxuYW1lfAogICAgICAgIHJlZ2lzdGVyX25ld192YXJpYWJsZSB3b3JkLnRvX3N5bSwgbmFtZQogICAgICBlbmQKICAgIGVuZAoKICAgIHByaXZhdGUKCiAgICBhdHRyX3JlYWRlciA6ZG9tYWluX3N0b3JhZ2UKCiAgICBkZWYgcmVnaXN0ZXJfbmV3X3ZhcmlhYmxlKHR5cGUsIG5hbWUpCiAgICAgIEBkb21haW5fc3RvcmFnZSB8fD0gSGFzaC5uZXcgeyB8aywgdnwga1t2XSA9IFtdIH0KICAgICAgQGRvbWFpbl9zdG9yYWdlW3R5cGVdIDw8IG5hbWUKICAgIGVuZAogIGVuZCAjIG1vZHVsZSBEb21haW46OkNsYXNzTWV0aG9kcwoKICAjCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIwoKICBtb2R1bGUgSW5zdGFuY2VNZXRob2RzCiAgICBkZWYgaW5pdGlhbGl6ZQogICAgICBzdXBlcgoKICAgICAgaHNoID0gc2VsZi5jbGFzcy5pbnN0YW5jZV92YXJpYWJsZV9nZXQoJ0Bkb21haW5fc3RvcmFnZScpCiAgICAgIHJldHVybiBpZiBoc2gubmlsPwoKICAgICAgaHNoLmVhY2hfcGFpciBkbyB8dHlwZSwgbWV0aG9kc3wKICAgICAgICBzaWduZWQsIGJhc2UgPSBjYXNlIHR5cGUKICAgICAgICAgICAgICAgICAgICAgICB3aGVuIDpieXRlCiAgICAgICAgICAgICAgICAgICAgICAgICBbZmFsc2UsIDI1Nl0KICAgICAgICAgICAgICAgICAgICAgICB3aGVuIDpzaWduZWRfYnl0ZQogICAgICAgICAgICAgICAgICAgICAgICAgW3RydWUsIDI1Nl0KICAgICAgICAgICAgICAgICAgICAgICB3aGVuIDppbnRlZ2VyCiAgICAgICAgICAgICAgICAgICAgICAgICBbZmFsc2UsIDY1XzUzNl0KICAgICAgICAgICAgICAgICAgICAgICB3aGVuIDpzaWduZWRfaW50ZWdlcgogICAgICAgICAgICAgICAgICAgICAgICAgW3RydWUsIDY1XzUzNl0KICAgICAgICAgICAgICAgICAgICAgICB3aGVuIDpjbG9jazEyCiAgICAgICAgICAgICAgICAgICAgICAgICBbZmFsc2UsIDEyXQogICAgICAgICAgICAgICAgICAgICAgIHdoZW4gOmNsb2NrMjQKICAgICAgICAgICAgICAgICAgICAgICAgIFtmYWxzZSwgMjRdCiAgICAgICAgICAgICAgICAgICAgICAgZW5kCgogICAgICAgIG1ldGhvZHMuZWFjaCBkbyB8bXwKICAgICAgICAgIHdhcm4gIm1ldGhvZCAnI3ttfScgYWxyZWFkeSBkZWZpbmVkISIgaWYgcmVzcG9uZF90bz8obSkgfHwgcmVzcG9uZF90bz8oIiN7bX09IikKICAgICAgICAgIHJlZ19yZWFkKG0sIGJhc2UsIHNpZ25lZCkKICAgICAgICAgIHJlZ193cml0ZShtLCBiYXNlKQogICAgICAgIGVuZAogICAgICBlbmQKCiAgICAgIHNlbGYuY2xhc3MuaW5zdGFuY2VfZXZhbCB7IHJlbW92ZV9pbnN0YW5jZV92YXJpYWJsZSAnQGRvbWFpbl9zdG9yYWdlJyB9CiAgICAgIHVuZGVmIHJlZ19yZWFkLCByZWdfd3JpdGUKICAgIGVuZAoKICAgIGRlZiByZWdfcmVhZChhdHRyLCBiYXNlID0gbmlsLCBzaWduZWQgPSBmYWxzZSkKICAgICAgc2VsZi5jbGFzcy5jbGFzc19ldmFsIGRvCiAgICAgICAgaWYgc2lnbmVkCiAgICAgICAgICBkZWZpbmVfbWV0aG9kKGF0dHIpIGRvCiAgICAgICAgICAgIGMgPSBpbnN0YW5jZV92YXJpYWJsZV9nZXQoIkAje2F0dHJ9IikKICAgICAgICAgICAgYyA+IChiYXNlIC8gMikgPyBjIC0gYmFzZSA6IGMKICAgICAgICAgIGVuZAogICAgICAgIGVsc2UKICAgICAgICAgIGRlZmluZV9tZXRob2QoYXR0cikgeyBpbnN0YW5jZV92YXJpYWJsZV9nZXQgIkAje2F0dHJ9IiB9CiAgICAgICAgZW5kCiAgICAgIGVuZAogICAgZW5kCgogICAgZGVmIHJlZ193cml0ZShhdHRyLCBiYXNlKQogICAgICBzZWxmLmNsYXNzLmNsYXNzX2V2YWwgZG8KICAgICAgICBkZWZpbmVfbWV0aG9kKCIje2F0dHJ9PSIpIGRvIHxvdGhlcnwKICAgICAgICAgIHJhaXNlIFR5cGVFcnJvciwgIiAje290aGVyfSBpcyBub3QgaW50ZWdlciEiIHVubGVzcyBvdGhlci5pbnRlZ2VyPwogICAgICAgICAgaW5zdGFuY2VfdmFyaWFibGVfc2V0ICJAI3thdHRyfSIsIG90aGVyICUgYmFzZQogICAgICAgIGVuZAogICAgICBlbmQKICAgIGVuZAoKICAgIGNsYXNzIERvbWFpbkVycm9yIDwgU3RhbmRhcmRFcnJvcjsgZW5kCiAgICBjbGFzcyBUeXBlRXJyb3IgPCBEb21haW5FcnJvcjsgZW5kCiAgZW5kICMgbW9kdWxlIERvbWFpbjo6SW5zdGFuY2VNZXRob2RzCgogICMKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjCgogIG1vZHVsZSBJbnRlZ2VycwogICAgZGVmIHNlbGYuaW5jbHVkZWQob2JqKQogICAgICBvYmouaW5jbHVkZSBJbnN0YW5jZU1ldGhvZHMKICAgICAgb2JqLmV4dGVuZCBDbGFzc01ldGhvZHMKICAgIGVuZAogIGVuZCAjIG1vZHVsZSBEb21haW46OkludGVnZXJzCmVuZCAjIG1vZHVsZSBEb21haW4KCiMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMKCmNsYXNzIFlvYmEKICBpbmNsdWRlIERvbWFpbjo6SW50ZWdlcnMKCiAgYnl0ZSA6YgogIGNsb2NrMTIgOmNsMTIKCmVuZAoKZCA9IFlvYmEubmV3CmQuYiA9IDEKZC5iICs9IDI1NQpwdXRzIGQuYgoKCmMgPSBZb2JhLm5ldwpwdXRzIGMuYgoKYy5jbDEyICA9IDUKYy5jbDEyICs9IDEwCnB1dHMgYy5jbDEy