named_value_class 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,45 @@
1
1
  require 'delegate'
2
+ require 'named_value_class/core_ext'
3
+
4
+ module NamedValueClass
5
+ OPERATIONS = {}
6
+ # OPERATORS = %w{+ - / * ** % | & ^ << >>}
7
+ OPERATORS = %w{+ - / *} # **}
8
+
9
+ def self.operators(klass, op, rhs_class, policy)
10
+ rhs_class = rhs_class.sub(/^Kernel::/,'')
11
+ OPERATIONS[klass] ||= {}
12
+ OPERATIONS[klass][rhs_class] ||= {}
13
+ OPERATIONS[klass][rhs_class][op] = policy
14
+ end
15
+
16
+ def self.operate(klass, op, rhs_class, lhs, default_policy, rhs)
17
+ rhs_class = rhs_class.sub(/^Kernel::/,'')
18
+ result = (OPERATIONS[klass] && OPERATIONS[klass][rhs_class] &&
19
+ OPERATIONS[klass][rhs_class][op]) ?
20
+ OPERATIONS[klass][rhs_class][op].call(lhs,default_policy,rhs) :
21
+ default_policy.call(rhs)
22
+ result = (result.constrain(lhs.lhs_constrain) rescue result)
23
+ lhs.class[result] || result
24
+ end
25
+ end
2
26
 
3
27
  # see README for documention
4
28
  def NamedValueClass(attrs={},&block)
5
29
  klass_name, superclass = attrs.first
6
30
  attrs.delete(klass_name)
31
+ lhs_constrain = attrs.delete(:constrain)
7
32
  target = (self.class == Object ? Kernel : self)
8
-
9
33
  target.module_eval "class #{klass_name} < DelegateClass(superclass); end"
10
34
  klass = target.const_get(klass_name)
35
+
36
+ if superclass.ancestors.include?(Numeric) && lhs_constrain
37
+ klass.module_eval <<-EVAL
38
+ def lhs_constrain
39
+ #{lhs_constrain}
40
+ end
41
+ EVAL
42
+ end
11
43
 
12
44
  klass.module_eval do
13
45
  def self.inherited(child)
@@ -34,16 +66,102 @@ def NamedValueClass(attrs={},&block)
34
66
  end
35
67
  end
36
68
  end
69
+
70
+ def self.all_operators_with_a *attrs
71
+ rhs_class = attrs.shift
72
+ operators *(NamedValueClass::OPERATORS + [rhs_class] + attrs)
73
+ end
74
+
75
+ def self.all_remaining_operators_with_a *attrs
76
+ end
77
+
78
+ def self.operators *attrs, &block
79
+ policy = attrs.pop if attrs.last.is_a?(Hash)
80
+ with_a = attrs.pop
81
+ attrs.each do |op|
82
+ operator op, *([with_a, policy].compact), &block
83
+ end
84
+ end
85
+
86
+ def self.operator op, rhs_class, attrs={}, &policy
87
+ if value_to_return = (attrs[:return] || attrs[:returns])
88
+ policy = proc do |_,_,_|
89
+ value_to_return
90
+ end
91
+ end
92
+ if klass_to_raise = (attrs[:raise] || attrs[:raises])
93
+ policy = proc do |_,_,_|
94
+ raise klass_to_raise
95
+ end
96
+ end
97
+ NamedValueClass.operators(self, op, rhs_class.to_s, policy)
98
+ end
99
+
100
+ def self.plus_a (*attrs,&policy) operator '+', *attrs, &policy end
101
+ def self.minus_a (*attrs,&policy) operator '-', *attrs, &policy end
102
+ def self.divided_by_a (*attrs,&policy) operator '/', *attrs, &policy end
103
+ def self.multiplied_by_a(*attrs,&policy) operator '*', *attrs, &policy end
104
+ def self.modulus_a (*attrs,&policy) operator '%', *attrs, &policy end
105
+ def self.raised_by_a (*attrs,&policy) operator '**',*attrs, &policy end
106
+
107
+ {
108
+ _plus: '+',
109
+ _minus: '-',
110
+ _multi: '*',
111
+ _divide:'/',
112
+ _mod: '%',
113
+ _raise: '**'
114
+ }.each do |(name,orig)|
115
+ eval "alias #{name} #{orig}" rescue nil
116
+ define_method orig do |rhs|
117
+ NamedValueClass.operate(self.class,orig,rhs.class.to_s,
118
+ self,method(name.to_sym),rhs)
119
+ end
120
+ end
121
+
122
+ # TODO: think about coerce more
123
+ # def coerce(lhs)
124
+ # [lhs,self.value]
125
+ # end
126
+
127
+ # def coerce(rhs)
128
+ # class_eval do
129
+ # if @operators && @operators[rhs.class]
130
+ # @operators[rhs.class].call(self,rhs)
131
+ # end
132
+ # end
133
+ # end
37
134
 
135
+ attr_reader :value
136
+
38
137
  def initialize(attrs = {})
39
138
  @name, value = attrs.first
40
139
  attrs.delete(@name)
41
140
  @name = @name.to_s
42
- super(value)
43
-
141
+ super(@value = value)
142
+
143
+ this = self
44
144
  attrs.each do |(attr,val)|
45
145
  self.class.instance_eval do
46
146
  attr_accessor attr
147
+ if [FalseClass,TrueClass].include?(val.class)
148
+ booleans = begin
149
+ const_get((attr.to_s+'s').upcase)
150
+ rescue NameError
151
+ const_set((attr.to_s+'s').upcase, {})
152
+ end
153
+
154
+ booleans[value] = this if val
155
+
156
+ self.class.instance_eval do
157
+ define_method(attr.to_s + 's') do
158
+ const_get((attr.to_s+'s').upcase)
159
+ end
160
+ end
161
+ define_method "is_#{attr}?" do
162
+ self.send(attr)
163
+ end
164
+ end
47
165
  end
48
166
  instance_variable_set "@#{attr}", val
49
167
  end
@@ -0,0 +1,68 @@
1
+ #
2
+ # core_ext.rb: useful additions to basic Ruby objects
3
+ #
4
+ # Copyright October 2010, Adam Florin. All rights reserved.
5
+ #
6
+
7
+
8
+ # Monkeypatch Array so we can cleanly get SUM
9
+ #
10
+ class Array
11
+ def sum
12
+ inject( nil ) { |sum,x| sum ? sum+x : x }
13
+ end
14
+ end
15
+
16
+ # So that we can do the neat Railsy syntax like array.map(&:method) in Ruby 1.8.6
17
+ # See http://jlaine.net/2008/5/8/amp-lified
18
+ #
19
+ class Symbol
20
+ def to_proc
21
+ lambda {|i| i.send(self)}
22
+ end
23
+ end
24
+
25
+ # Numeric extensions
26
+ #
27
+ class Numeric
28
+
29
+ # constrain number within a given range
30
+ #
31
+ def constrain(range)
32
+ if self > range.end
33
+ return range.end
34
+ elsif self < range.begin
35
+ return range.begin
36
+ else
37
+ return self
38
+ end
39
+ end
40
+
41
+ # to manage things like timescale shifts which for now
42
+ # must be divisible by 2
43
+ #
44
+ def round_to_power(power = 2)
45
+ power ** (Math.log(self) / Math.log(power)).round
46
+ end
47
+ end
48
+
49
+ # To convert :symbol_names to ClassNames and back.
50
+ #
51
+ class String
52
+ def camelize
53
+ self.gsub(/[^_]+/){|c| c.capitalize}.gsub('_', '')
54
+ end
55
+
56
+ def underscorize
57
+ self.gsub(/[A-Z]/, "_\\0").gsub(/^_/, '').downcase
58
+ end
59
+ end
60
+
61
+ # for Rails-like method chaining
62
+ #
63
+ class Module
64
+ def alias_method_chain(target, feature)
65
+ alias_method "#{target}_without_#{feature}", target
66
+ alias_method target, "#{target}_with_#{feature}"
67
+ end
68
+ end
@@ -0,0 +1,9 @@
1
+ module NamedValueClass
2
+ module Immutable
3
+ # %w[= += -= *= /= **= %= |= ^= &= <<= >>= &&= ||=].each do |op|
4
+ # define_method op do |rhs|
5
+ # raise SyntaxError
6
+ # end
7
+ # end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module NamedValueClass
2
+ VERSION = '0.7.0'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: named_value_class
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-18 00:00:00.000000000Z
12
+ date: 2011-12-20 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: Quickly add customizable class delegate constants which output their
15
15
  names, not their values. This may be desirable for some DSLs.
@@ -19,6 +19,9 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - lib/named_value_class.rb
22
+ - lib/named_value_class/core_ext.rb
23
+ - lib/named_value_class/immutable.rb
24
+ - lib/named_value_class/version.rb
22
25
  homepage: http://github.com/mgarriss/named_value_class
23
26
  licenses: []
24
27
  post_install_message: