named_value_class 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: