primitive_wrapper 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +491 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/primitive_wrapper.rb +610 -0
- data/lib/primitive_wrapper/version.rb +3 -0
- data/primitive_wrapper.gemspec +38 -0
- metadata +144 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "primitive_wrapper"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,610 @@
|
|
1
|
+
require "primitive_wrapper/version"
|
2
|
+
require "blockify"
|
3
|
+
|
4
|
+
|
5
|
+
#
|
6
|
+
# Standard Object upgrades
|
7
|
+
#
|
8
|
+
class Object
|
9
|
+
def prim_value
|
10
|
+
self
|
11
|
+
end
|
12
|
+
def to_wrapper
|
13
|
+
return Bit.new(nil) if self.nil?
|
14
|
+
return Bool.new(true) if self==true
|
15
|
+
return Bool.new(false) if self==false
|
16
|
+
return Int.new(self) if self.kind_of? Integer
|
17
|
+
return FloatW.new(self) if self.kind_of? Float
|
18
|
+
return Number.new(self) if self.kind_of? Numeric
|
19
|
+
return Datum.new(self) if self.kind_of? String
|
20
|
+
return SymbolW.new(self) if self.kind_of? Symbol
|
21
|
+
return Property.new(self) if self.kind_of? Hash
|
22
|
+
return Value.new(self)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Symbol
|
27
|
+
def ~
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class TrueClass
|
33
|
+
def ~
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class FalseClass
|
39
|
+
def ~
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class NilClass
|
45
|
+
def ~
|
46
|
+
self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# BASE CLASS == Value ... a wrapper for any ruby object
|
52
|
+
#
|
53
|
+
class Value
|
54
|
+
def self.raise_on_freeze
|
55
|
+
@freeze_raise = true
|
56
|
+
end
|
57
|
+
def self.ignore_on_freeze
|
58
|
+
@freeze_raise = false
|
59
|
+
end
|
60
|
+
def self.freeze_raise?
|
61
|
+
@freeze_raise
|
62
|
+
end
|
63
|
+
ignore_on_freeze
|
64
|
+
|
65
|
+
def initialize(obj=nil)
|
66
|
+
obj = obj.prim_value
|
67
|
+
ensure_valid(obj)
|
68
|
+
@value = obj
|
69
|
+
end
|
70
|
+
|
71
|
+
def ensure_valid(obj, mess = "Incompatible type")
|
72
|
+
unless valid_type(obj)
|
73
|
+
raise mess
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def freeze # never allow the wrapper to be frozen
|
78
|
+
raise "this object cannot be frozen" if self.class.freeze_raise?
|
79
|
+
end
|
80
|
+
|
81
|
+
def val
|
82
|
+
@value
|
83
|
+
end
|
84
|
+
|
85
|
+
def ~
|
86
|
+
@value
|
87
|
+
end
|
88
|
+
|
89
|
+
def val=(dat)
|
90
|
+
replace(dat)
|
91
|
+
end
|
92
|
+
|
93
|
+
def prim_value
|
94
|
+
@value
|
95
|
+
end
|
96
|
+
|
97
|
+
def unwrap
|
98
|
+
@value
|
99
|
+
end
|
100
|
+
|
101
|
+
def ==(other)
|
102
|
+
other.prim_value == @value
|
103
|
+
end
|
104
|
+
|
105
|
+
def !=(other)
|
106
|
+
other.prim_value != @value
|
107
|
+
end
|
108
|
+
|
109
|
+
def valid_type(prm=nil)
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
113
|
+
def replace(other)
|
114
|
+
@value = other if valid_type(other)
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_s
|
118
|
+
@value.to_s
|
119
|
+
end
|
120
|
+
|
121
|
+
def inspect
|
122
|
+
str = @value.nil? ? "nil" : @value.inspect
|
123
|
+
"(#{self.class}==>#{str})"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class Bool < Value
|
128
|
+
def valid_type(prm)
|
129
|
+
return true if prm.kind_of? TrueClass
|
130
|
+
return true if prm.kind_of? FalseClass
|
131
|
+
return true if prm.kind_of? TrueW
|
132
|
+
return true if prm.kind_of? FalseW
|
133
|
+
return true if prm.kind_of? Bool
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
def |(other)
|
138
|
+
Bool.new(@value | other.prim_value)
|
139
|
+
end
|
140
|
+
|
141
|
+
def &(other)
|
142
|
+
Bool.new(@value & other.prim_value)
|
143
|
+
end
|
144
|
+
|
145
|
+
def ^(other)
|
146
|
+
Bool.new(@value ^ other.prim_value)
|
147
|
+
end
|
148
|
+
|
149
|
+
def !
|
150
|
+
Bool.new(!@value)
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_i
|
154
|
+
@value ? 1:0
|
155
|
+
end
|
156
|
+
def to_int
|
157
|
+
Int.new(@value ? 1:0)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Bit < Bool
|
162
|
+
def valid_type(prm)
|
163
|
+
return true if prm.kind_of? TrueClass
|
164
|
+
return true if prm.kind_of? FalseClass
|
165
|
+
return true if prm.kind_of? NilClass
|
166
|
+
return true if prm.kind_of? Bool
|
167
|
+
false
|
168
|
+
end
|
169
|
+
def |(other)
|
170
|
+
@value | other.prim_value
|
171
|
+
end
|
172
|
+
|
173
|
+
def &(other)
|
174
|
+
@value & other.prim_value
|
175
|
+
end
|
176
|
+
|
177
|
+
def ^(other)
|
178
|
+
@value ^ other.prim_value
|
179
|
+
end
|
180
|
+
|
181
|
+
def !
|
182
|
+
!@value
|
183
|
+
end
|
184
|
+
def to_i
|
185
|
+
@value ? 1:0
|
186
|
+
end
|
187
|
+
def to_int
|
188
|
+
Int.new(@value ? 1:0)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class FixedBit < Bit
|
193
|
+
def initialize
|
194
|
+
raise "FixedBit cannot create instance"
|
195
|
+
end
|
196
|
+
def replace(other)
|
197
|
+
raise "can't assign primitive type"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class FalseW < FixedBit
|
202
|
+
def initialize
|
203
|
+
@value = false
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class TrueW < FixedBit
|
208
|
+
def initialize
|
209
|
+
@value = true
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class Null < FixedBit
|
214
|
+
def initialize
|
215
|
+
@value = nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class SymbolW < Value
|
220
|
+
def valid_type(prm)
|
221
|
+
return true if prm.kind_of? Symbol
|
222
|
+
return true if prm.kind_of? SymbolW
|
223
|
+
false
|
224
|
+
end
|
225
|
+
|
226
|
+
FIX_ARGS = lambda do |elm|
|
227
|
+
rtn = elm
|
228
|
+
if elm.kind_of? Symbol
|
229
|
+
rtn = elm.to_s
|
230
|
+
elsif elm.kind_of? SymbolW
|
231
|
+
rtn = elm.to_s
|
232
|
+
end
|
233
|
+
rtn
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.bestow_string_mutate_method(meth_def_name, meth_call_name)
|
237
|
+
define_method meth_def_name do |*args, &block|
|
238
|
+
prms = args.blockify_elements &FIX_ARGS
|
239
|
+
str = @value.to_s
|
240
|
+
str.send(meth_call_name, *prms, &block)
|
241
|
+
@value = str.to_sym
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.bestow_string_non_mutate_method(meth_def_name, meth_call_name, return_type = SymbolW)
|
246
|
+
if return_type==Symbol
|
247
|
+
define_method meth_def_name do |*args, &block|
|
248
|
+
prms = args.blockify_elements &FIX_ARGS
|
249
|
+
@value.to_s.send(meth_call_name, *prms, &block).to_sym
|
250
|
+
end
|
251
|
+
elsif return_type==String
|
252
|
+
define_method meth_def_name do |*args, &block|
|
253
|
+
prms = args.blockify_elements &FIX_ARGS
|
254
|
+
@value.to_s.send(meth_call_name, *prms, &block).to_s
|
255
|
+
end
|
256
|
+
elsif return_type==SymbolW
|
257
|
+
define_method meth_def_name do |*args, &block|
|
258
|
+
prms = args.blockify_elements &FIX_ARGS
|
259
|
+
SymbolW.new @value.to_s.send(meth_call_name, *prms, &block).to_s.to_sym
|
260
|
+
end
|
261
|
+
else # default type
|
262
|
+
define_method meth_def_name do |*args, &block|
|
263
|
+
prms = args.blockify_elements &FIX_ARGS
|
264
|
+
@value.to_s.send(meth_call_name, *prms, &block)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def self.bestow_symbol_method(meth_def_name, meth_call_name, mutate_self=false)
|
270
|
+
if mutate_self
|
271
|
+
define_method meth_def_name do |*args, &block|
|
272
|
+
margs = args.blockify_elements { |t| t.prim_value }
|
273
|
+
tval = @value.send(meth_call_name, *margs, &block)
|
274
|
+
ensure_valid(tval, "symbol mutate method not valid")
|
275
|
+
@value = tval
|
276
|
+
return self
|
277
|
+
end
|
278
|
+
else
|
279
|
+
define_method meth_def_name do |*args, &block|
|
280
|
+
margs = args.blockify_elements { |t| t.prim_value }
|
281
|
+
rtn = @value.send(meth_call_name, *margs, &block)
|
282
|
+
return rtn
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.bestow_string_mutate_methods(meths)
|
288
|
+
meths.each do |meth|
|
289
|
+
bestow_string_mutate_method(meth, meth)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.bestow_string_non_mutate_methods(meths, return_type = SymbolW)
|
294
|
+
meths.each do |meth|
|
295
|
+
bestow_string_non_mutate_method(meth, meth, return_type)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.bestow_symbol_methods(meths, mutate_self=false)
|
300
|
+
meths.each do |meth|
|
301
|
+
dmeth=meth
|
302
|
+
if mutate_self
|
303
|
+
dmeth = (meth.to_s + '!').to_sym
|
304
|
+
end
|
305
|
+
bestow_symbol_method(dmeth, meth, mutate_self)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# create non-mutate SymbolW methods
|
310
|
+
bestow_symbol_methods( [:next, :succ, :[], :length, :size, :upcase, :downcase, :capitalize, :swapcase, :<, :>, :<=, :>=, :between?, :empty? ], false)
|
311
|
+
|
312
|
+
# create mutate SymbolW methods ... these will auto-bang!
|
313
|
+
bestow_symbol_methods([:next, :succ, :upcase, :downcase, :capitalize, :swapcase, :succ], true)
|
314
|
+
|
315
|
+
# string non-mutate methods
|
316
|
+
bestow_string_non_mutate_methods([:match, :include?], nil)
|
317
|
+
bestow_string_non_mutate_methods([:prepend], SymbolW)
|
318
|
+
bestow_string_non_mutate_method(:append, :<<, SymbolW)
|
319
|
+
|
320
|
+
# string mutate methods
|
321
|
+
bestow_string_mutate_method(:prepend!, :prepend)
|
322
|
+
bestow_string_mutate_method(:append!, :<<)
|
323
|
+
bestow_string_mutate_method(:[]=, :[]=)
|
324
|
+
|
325
|
+
# why did I redefine this? don't remember ... investigate later
|
326
|
+
def include? pat
|
327
|
+
self.to_s.include? pat.to_s
|
328
|
+
end
|
329
|
+
|
330
|
+
# old-fashioned defines:
|
331
|
+
def to_sym
|
332
|
+
@value
|
333
|
+
end
|
334
|
+
def to_str
|
335
|
+
@value.to_s
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
class ValueAdd < Value
|
340
|
+
def valid_type(prm) # must override
|
341
|
+
false
|
342
|
+
end
|
343
|
+
def self.bestow_methods(*args)
|
344
|
+
args = args.first if args.first.kind_of? Array
|
345
|
+
args.each do |meth|
|
346
|
+
define_method meth do |*args, &block|
|
347
|
+
@value.send(meth, *args, &block)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
def self.capture_base_methods(type, except=Object)
|
352
|
+
add_me = type.instance_methods - except.instance_methods - Value.instance_methods - [:singleton_method_added]
|
353
|
+
bestow_methods add_me
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
class Int < ValueAdd
|
358
|
+
capture_base_methods(Fixnum) # Bignum also works here ... :to_f, :* etc
|
359
|
+
def valid_type(prm)
|
360
|
+
return true if prm.kind_of? Integer
|
361
|
+
return true if prm.kind_of? Int
|
362
|
+
false
|
363
|
+
end
|
364
|
+
def inc # simulates post-increment
|
365
|
+
@value+= 1
|
366
|
+
return @value-1
|
367
|
+
end
|
368
|
+
def dec # simulates post-deccrement
|
369
|
+
@value-= 1
|
370
|
+
return @value+1
|
371
|
+
end
|
372
|
+
def to_int
|
373
|
+
self
|
374
|
+
end
|
375
|
+
def ~
|
376
|
+
~@value
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
class FloatW < ValueAdd
|
381
|
+
capture_base_methods(Float)
|
382
|
+
def valid_type(prm)
|
383
|
+
return true if prm.kind_of? Float
|
384
|
+
return true if prm.kind_of? FloatW
|
385
|
+
false
|
386
|
+
end
|
387
|
+
def to_int
|
388
|
+
Int.new @value.to_i
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
class Number < ValueAdd
|
393
|
+
capture_base_methods(Fixnum)
|
394
|
+
capture_base_methods(Float, self)
|
395
|
+
capture_base_methods(Complex, self)
|
396
|
+
capture_base_methods(Rational, self)
|
397
|
+
def valid_type(prm)
|
398
|
+
return true if prm.kind_of? Numeric
|
399
|
+
return true if prm.kind_of? Number
|
400
|
+
false
|
401
|
+
end
|
402
|
+
def ~ # make sure capture did not muck things up
|
403
|
+
@value # If you need ~ use Int instead of Number
|
404
|
+
end
|
405
|
+
def to_int
|
406
|
+
Int.new @value.to_i
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
# string, number
|
411
|
+
class Datum < ValueAdd
|
412
|
+
capture_base_methods(Number)
|
413
|
+
capture_base_methods(String, self)
|
414
|
+
def valid_type(prm)
|
415
|
+
return true if prm.kind_of? Numeric
|
416
|
+
return true if prm.kind_of? String
|
417
|
+
return true if prm.kind_of? Datum
|
418
|
+
false
|
419
|
+
end
|
420
|
+
|
421
|
+
# methods that broke ... fixed here
|
422
|
+
def to_s
|
423
|
+
@value.to_s
|
424
|
+
end
|
425
|
+
def ~ # make sure capture did not muck things up
|
426
|
+
@value # If you need ~ use Int instead of Number
|
427
|
+
end
|
428
|
+
def to_int
|
429
|
+
Int.new @value.to_i
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
class Property < Value
|
434
|
+
GOOD_KEY_RGX = /\A[a-zA-Z_][a-zA-Z_0-9]*\z/
|
435
|
+
|
436
|
+
def initialize(hash={})
|
437
|
+
self.val=(hash)
|
438
|
+
end
|
439
|
+
|
440
|
+
def self.bad_key?(idx)
|
441
|
+
@badkeys ||= {}
|
442
|
+
true==@badkeys[idx]
|
443
|
+
end
|
444
|
+
|
445
|
+
def self.good_candidate_name? name
|
446
|
+
name = name.prim_value
|
447
|
+
return false unless name.kind_of? Symbol
|
448
|
+
tst = GOOD_KEY_RGX.match name
|
449
|
+
return false if tst.nil?
|
450
|
+
true
|
451
|
+
end
|
452
|
+
|
453
|
+
def self.good_key?(idx) # syntax and not bad ... does not check to see if taken as only instansts can do that
|
454
|
+
idx = idx.prim_value
|
455
|
+
return false unless good_candidate_name? idx
|
456
|
+
return false if bad_key?(idx)
|
457
|
+
true
|
458
|
+
end
|
459
|
+
|
460
|
+
def self.reserve_property_names!(*names)
|
461
|
+
@badkeys ||= {}
|
462
|
+
names = names.first if names.first.kind_of? Array
|
463
|
+
names.each do |key|
|
464
|
+
next if key[-1]=='!'
|
465
|
+
next if key[-1]=='?'
|
466
|
+
kw = key[-1]=='=' ? key[0..-2] : key[0..-1]
|
467
|
+
md = GOOD_KEY_RGX.match kw
|
468
|
+
next if md.nil? # bad key
|
469
|
+
@badkeys[key]=true
|
470
|
+
end
|
471
|
+
end
|
472
|
+
reserve_property_names!(self.instance_methods)
|
473
|
+
reserve_property_names!(Object.new.private_methods)
|
474
|
+
|
475
|
+
# assign replacement hash
|
476
|
+
def val=(hash)
|
477
|
+
ensure_valid(hash)
|
478
|
+
hash = hash.prim_value
|
479
|
+
@value = hash # keep this as prime as possible
|
480
|
+
rekey!
|
481
|
+
end
|
482
|
+
|
483
|
+
def rekey!
|
484
|
+
@good_keys = {} # these keys can be properties
|
485
|
+
@hold_keys = {} # these keys can't
|
486
|
+
@value.each_pair do |pkey,val|
|
487
|
+
key = pkey.prim_value
|
488
|
+
if self.class.good_key? key
|
489
|
+
@good_keys[key.prim_value]=true
|
490
|
+
else
|
491
|
+
@hold_keys[key.prim_value]=true
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
def method_missing(method, *args, &block)
|
497
|
+
flag_good = @good_keys.include? method
|
498
|
+
unless flag_good
|
499
|
+
unless method[-1]=='='
|
500
|
+
if @value.include? method
|
501
|
+
rekey!
|
502
|
+
flag_good = @good_keys.include? method
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
raise "Illegal Block attachment" unless block.nil?
|
507
|
+
if flag_good
|
508
|
+
raise "*** ArgumentError Exception: wrong number of arguments (given #{args.count}, expected 0)" unless args.empty?
|
509
|
+
return @value[method]
|
510
|
+
end
|
511
|
+
if method[-1]=='=' # assignment
|
512
|
+
key = method[0..-2].to_sym
|
513
|
+
if args.count==1
|
514
|
+
if @good_keys.include? key
|
515
|
+
@value[key] = args[0]
|
516
|
+
return true
|
517
|
+
end
|
518
|
+
# creating a new key here ... good or bad?
|
519
|
+
if self.class.good_key? key
|
520
|
+
@good_keys[key]=true
|
521
|
+
else
|
522
|
+
@hold_keys[key]=true
|
523
|
+
end
|
524
|
+
return @value[key] = args[0]
|
525
|
+
end
|
526
|
+
raise "*** ArgumentError Exception: wrong number of arguments (given #{args.count}, expected 1)"
|
527
|
+
else
|
528
|
+
# lookup failed ... punt
|
529
|
+
super
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
def split!
|
534
|
+
good = {}
|
535
|
+
bad = {}
|
536
|
+
@good_keys.each_pair do |key,val|
|
537
|
+
good[key] = @value[key]
|
538
|
+
end
|
539
|
+
@hold_keys.each_pair do |key,val|
|
540
|
+
bad[key] = @value[key]
|
541
|
+
end
|
542
|
+
return [good,bad]
|
543
|
+
end
|
544
|
+
|
545
|
+
def [](idx)
|
546
|
+
@value[idx]
|
547
|
+
end
|
548
|
+
|
549
|
+
def []=(idx,val)
|
550
|
+
idx = idx.prim_value # in case it is wrapped
|
551
|
+
rtn = @value[idx] = val
|
552
|
+
# now put key in one of two bins
|
553
|
+
if self.class.good_key? idx
|
554
|
+
@good_keys[idx]=true
|
555
|
+
else
|
556
|
+
@hold_keys[idx]=true
|
557
|
+
end
|
558
|
+
return rtn
|
559
|
+
end
|
560
|
+
|
561
|
+
def import_hash!(hash)
|
562
|
+
hash.each_pair do |key,val|
|
563
|
+
self[key]=val
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
def valid_type(prm)
|
568
|
+
return true if prm.kind_of? Hash
|
569
|
+
return true if prm.kind_of? Property
|
570
|
+
false
|
571
|
+
end
|
572
|
+
|
573
|
+
def defined_properties!
|
574
|
+
rekey!
|
575
|
+
@good_keys.keys.sort
|
576
|
+
end
|
577
|
+
def deferred_properties!
|
578
|
+
rekey!
|
579
|
+
@hold_keys.keys # can't sort bad keys without a ton of work
|
580
|
+
end
|
581
|
+
|
582
|
+
def property?(tst)
|
583
|
+
rekey!
|
584
|
+
tst = tst.prim_value
|
585
|
+
return true if @good_keys.include? tst
|
586
|
+
false
|
587
|
+
end
|
588
|
+
|
589
|
+
def deferred?(tst)
|
590
|
+
rekey!
|
591
|
+
tst = tst.prim_value
|
592
|
+
return true if @hold_keys.include? tst
|
593
|
+
false
|
594
|
+
end
|
595
|
+
|
596
|
+
def define_properties!(ary, dflt="")
|
597
|
+
ary.each do |item|
|
598
|
+
key = item.prim_value
|
599
|
+
raise "*** Property Error: must use Symbol type to define properties" unless key.kind_of? Symbol
|
600
|
+
raise "*** Property Error: property #{key.inspect} already defined" if @good_keys.include? key
|
601
|
+
raise "*** Property Error: property #{key.inspect} violates naming convention" unless self.class.good_candidate_name? key
|
602
|
+
raise "*** Property Error: property #{key.inspect} is reserved" if self.class.bad_key? key
|
603
|
+
@good_keys[key]=true
|
604
|
+
@value[key]=dflt
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
end
|
609
|
+
|
610
|
+
|