Ron 0.1.1 → 0.1.2
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.
- data/History.txt +28 -2
- data/Makefile +19 -8
- data/lib/ron.rb +87 -49
- data/lib/ron/column_order.rb +1 -1
- data/lib/ron/float_accurate_to_s.rb +168 -0
- data/lib/ron/graphedge.rb +86 -16
- data/lib/ron/version.rb +1 -1
- data/ron.gemspec +13 -12
- data/test/test_all.rb +110 -37
- data/test/test_graphcopy.rb +42 -0
- metadata +4 -5
- data/Manifest.txt +0 -9
- data/Rakefile +0 -37
data/History.txt
CHANGED
@@ -1,4 +1,30 @@
|
|
1
|
-
=== 0.1.
|
1
|
+
=== 0.1.2 / 21dec2009
|
2
|
+
* 5 Major Bugfixes:
|
3
|
+
* preserve modules an object was extended by
|
4
|
+
* (but not Recursive, which is an artifact of using ron)
|
5
|
+
* single quote and backslash now handled right in String
|
6
|
+
* all significant digits now preserved in Float (really)
|
7
|
+
* many small improvements to object graph copying (see below)
|
8
|
+
* ported to MRI 1.9
|
9
|
+
|
10
|
+
* 2 Minor Bugfixes:
|
11
|
+
* preserve classes of descendants Regexp, Range, Array and Hash
|
12
|
+
* many changes to tests to improve coverage and correctness
|
13
|
+
* also, tests now work around bugs in yaml
|
14
|
+
|
15
|
+
* 1 Minor Enhancement:
|
16
|
+
* reworked build/gem scripts
|
17
|
+
|
18
|
+
* Improvements to object graph copying:
|
19
|
+
* depth-first copying is now available
|
20
|
+
* call may pass in a hash of objects to replace
|
21
|
+
* replacements when parent is nil or false are now an error
|
22
|
+
* protect against changes to hash, set, or array during traversal
|
23
|
+
* avoid inf-loop if replacing item with many items
|
24
|
+
* now possible to replace an object with another that contains the first
|
25
|
+
* in depth_graphcopy, delay all changes til right before the end
|
26
|
+
|
27
|
+
=== 0.1.1 / 5aug2009
|
2
28
|
* 1 Major Enhancement:
|
3
29
|
* significant improvements and bugfixes in graphcopy
|
4
30
|
|
@@ -7,7 +33,7 @@
|
|
7
33
|
* ported to ruby 1.9
|
8
34
|
* rewrote Class#- to be more compatible with Reg
|
9
35
|
|
10
|
-
=== 0.1.0 /
|
36
|
+
=== 0.1.0 / 7oct2006
|
11
37
|
|
12
38
|
* 1 major enhancement
|
13
39
|
* Birthday!
|
data/Makefile
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
name=Ron
|
2
|
+
lname=ron
|
3
|
+
gemname=Ron
|
4
|
+
|
5
|
+
#everything after this line is generic
|
6
|
+
|
7
|
+
version=$(shell ruby -r ./lib/$(lname)/version.rb -e "puts $(name)::VERSION")
|
8
|
+
filelist=$(shell git ls-files)
|
9
|
+
|
1
10
|
.PHONY: all test docs gem tar pkg email
|
2
11
|
all: test
|
3
12
|
|
@@ -10,23 +19,25 @@ docs:
|
|
10
19
|
pkg: gem tar
|
11
20
|
|
12
21
|
gem:
|
13
|
-
gem build
|
22
|
+
gem build $(lname).gemspec
|
14
23
|
|
15
24
|
tar:
|
16
|
-
tar
|
25
|
+
tar cf - $(filelist) | ( mkdir $(gemname)-$(version); cd $(gemname)-$(version); tar xf - )
|
26
|
+
tar czf $(gemname)-$(version).tar.gz $(gemname)-$(version)
|
27
|
+
rm -rf $(gemname)-$(version)
|
17
28
|
|
18
29
|
email: README.txt History.txt
|
19
30
|
ruby -e ' \
|
20
31
|
require "rubygems"; \
|
21
|
-
load "
|
22
|
-
spec= Gem::Specification.list.find{|x| x.name=="
|
32
|
+
load "./$(lname).gemspec"; \
|
33
|
+
spec= Gem::Specification.list.find{|x| x.name=="$(gemname)"}; \
|
23
34
|
puts "\
|
24
|
-
Subject: [ANN]
|
25
|
-
\n\
|
35
|
+
Subject: [ANN] $(name) #{spec.version} Released \
|
36
|
+
\n\n$(name) version #{spec.version} has been released! \n\n\
|
26
37
|
#{Array(spec.homepage).map{|url| " * #{url}\n" }} \
|
27
38
|
\n\
|
28
|
-
#{
|
39
|
+
#{$(name)::Description} \
|
29
40
|
\n\nChanges:\n\n \
|
30
|
-
#{
|
41
|
+
#{$(name)::Latest_changes} \
|
31
42
|
"\
|
32
43
|
'
|
data/lib/ron.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
#require 'warning'
|
5
5
|
require 'ron/graphedge'
|
6
6
|
require 'continuation' unless defined? Continuation
|
7
|
+
require 'ron/float_accurate_to_s'
|
7
8
|
|
8
9
|
#to_ron
|
9
10
|
|
@@ -41,8 +42,15 @@ module Ron
|
|
41
42
|
def self.load str
|
42
43
|
eval str
|
43
44
|
end
|
45
|
+
|
46
|
+
def self.extension_modules_of(obj)
|
47
|
+
ancs=class<<obj; ancestors end
|
48
|
+
ancs=ancs[0...ancs.index(obj.class)]
|
49
|
+
return ancs
|
50
|
+
rescue TypeError
|
51
|
+
return []
|
52
|
+
end
|
44
53
|
|
45
|
-
CaptureCtx=[]
|
46
54
|
=begin
|
47
55
|
def self.recurse_safe_objects_equal?(o1,o2,session={})
|
48
56
|
pair=[o1.__id__,o2.__id__]
|
@@ -51,13 +59,13 @@ module Ron
|
|
51
59
|
|
52
60
|
o1.class==o2.class and
|
53
61
|
case o1
|
54
|
-
when Array
|
62
|
+
when Array
|
55
63
|
o1.size==o2.size and
|
56
64
|
o1.each_with_index{|i1,idx|
|
57
65
|
recurse_safe_objects_equal?(i1,o2[idx],session) or return
|
58
66
|
}
|
59
67
|
|
60
|
-
when Hash
|
68
|
+
when Hash
|
61
69
|
#oops, this depends on #== and #hash working right for recursive structures, which they don't.
|
62
70
|
o1.size==o2.size or return
|
63
71
|
recurse_safe_objects_equal? o1.default,o2.default,session or return
|
@@ -65,28 +73,28 @@ module Ron
|
|
65
73
|
return unless (o2.key? idx and recurse_safe_objects_equal? i1, o2[idx],session)
|
66
74
|
}
|
67
75
|
|
68
|
-
when Range
|
76
|
+
when Range
|
69
77
|
o1.exclude_end?()==o2.exclude_end?() and
|
70
78
|
recurse_safe_objects_equal? o1.begin, o2.begin,session and
|
71
79
|
recurse_safe_objects_equal? o1.end, o2.end,session
|
72
80
|
|
73
|
-
when Struct
|
81
|
+
when Struct
|
74
82
|
(mems=o1.members).size==o2.members.size and
|
75
83
|
mems.each{|i|
|
76
84
|
recurse_safe_objects_equal? o1[i], (o2[i] rescue return),session or return
|
77
85
|
}
|
78
|
-
when Binding
|
86
|
+
when Binding
|
79
87
|
recurse_safe_objects_equal? o1.to_h, o2.to_h, session
|
80
|
-
when Proc,Integer,Float,String
|
88
|
+
when Proc,Integer,Float,String
|
81
89
|
o1==o2
|
82
90
|
when Thread,ThreadGroup,Process,IO,Symbol,
|
83
|
-
Continuation,Class,Module
|
91
|
+
Continuation,Class,Module
|
84
92
|
return o1.equal?(o2)
|
85
|
-
when Exception
|
93
|
+
when Exception
|
86
94
|
o1.message==o2.message
|
87
|
-
when MatchData
|
95
|
+
when MatchData
|
88
96
|
o1.to_a==o2.to_a
|
89
|
-
when Time
|
97
|
+
when Time
|
90
98
|
o1.eql? o2
|
91
99
|
else true
|
92
100
|
end and
|
@@ -142,40 +150,65 @@ end
|
|
142
150
|
[Fixnum,NilClass,FalseClass,TrueClass,Symbol].each{|k|
|
143
151
|
k.class_eval{ alias to_ron inspect; undef to_ron_list }
|
144
152
|
}
|
145
|
-
|
146
|
-
|
147
|
-
|
153
|
+
|
154
|
+
class Bignum
|
155
|
+
def to_ron_list(session) [inspect] end
|
156
|
+
end
|
157
|
+
|
158
|
+
class Float
|
159
|
+
def to_ron_list(session)
|
160
|
+
[accurate_to_s]
|
161
|
+
end
|
162
|
+
end
|
148
163
|
|
149
164
|
class String
|
150
165
|
def to_ron_list session
|
151
|
-
|
152
|
-
|
166
|
+
result= [ "'", gsub(/['\\]/){ '\\'+$&}, "'" ]
|
167
|
+
if self.class!=String
|
168
|
+
result=[self.class.name, ".new(", result, ")"]
|
169
|
+
end
|
170
|
+
result
|
153
171
|
end
|
154
172
|
end
|
155
173
|
|
156
174
|
class Regexp
|
157
175
|
def to_ron_list session
|
158
|
-
|
159
|
-
|
176
|
+
if self.class==Regexp
|
177
|
+
[ inspect ]
|
178
|
+
else
|
179
|
+
[self.class.name, ".new(", self.source.inspect, ")"]
|
180
|
+
end
|
160
181
|
end
|
161
182
|
end
|
162
183
|
|
163
184
|
class Array
|
164
185
|
def to_ron_list session
|
165
|
-
["["] +
|
186
|
+
result=["["] +
|
166
187
|
map{|i|
|
167
188
|
i.to_ron_list2(session)<<', '
|
168
189
|
}.flatten<<
|
169
190
|
"]"
|
191
|
+
result.unshift self.class.name unless self.class==Array
|
192
|
+
result
|
170
193
|
end
|
171
194
|
end
|
172
195
|
|
173
196
|
class Hash
|
174
197
|
def to_ron_list session
|
175
|
-
|
176
|
-
|
198
|
+
if self.class==Hash
|
199
|
+
leader="{"
|
200
|
+
trailer="}"
|
201
|
+
sep="=>"
|
202
|
+
else
|
203
|
+
leader=self.class.name+"["
|
204
|
+
trailer="]"
|
205
|
+
sep=","
|
206
|
+
end
|
207
|
+
|
208
|
+
[leader]+map{|k,v|
|
209
|
+
Array(k.to_ron_list2(session)).push sep,
|
177
210
|
v.to_ron_list2(session)<<', '
|
178
|
-
}.flatten<<
|
211
|
+
}.flatten<<trailer
|
179
212
|
end
|
180
213
|
end
|
181
214
|
|
@@ -185,7 +218,7 @@ class Object
|
|
185
218
|
#warning "additional modules not handled"
|
186
219
|
#warning "prettified output not supported"
|
187
220
|
|
188
|
-
to_ron_list2.
|
221
|
+
to_ron_list2.join
|
189
222
|
end
|
190
223
|
|
191
224
|
def to_ron_list session
|
@@ -225,13 +258,21 @@ class Object
|
|
225
258
|
result=to_ron_list(session).unshift str
|
226
259
|
if result.last=="}#end object literal"
|
227
260
|
result.last.replace "}"
|
261
|
+
was_obj_syntax=true
|
228
262
|
else
|
229
263
|
#append instance_eval
|
230
|
-
ivars=instance_variables
|
264
|
+
ivars=instance_variables
|
265
|
+
ivars.map!{|iv| iv.to_s } if Symbol===ivars.first
|
266
|
+
ivars-=::Ron::IGNORED_INSTANCE_VARIABLES[self.class.name]
|
231
267
|
ivars.empty? or result.push ".with_ivars(", *ivars.map{|iv|
|
232
268
|
[":",iv.to_s,"=>",instance_variable_get(iv).to_ron_list2(session),', ']
|
233
269
|
}.flatten[0...-1]<<")"
|
234
270
|
end
|
271
|
+
extensions=Ron::extension_modules_of(self)
|
272
|
+
unless extensions.empty?
|
273
|
+
result=["(",result,")"] if was_obj_syntax
|
274
|
+
result.push ".extend(",extensions,")"
|
275
|
+
end
|
235
276
|
result.push ")" if str[/^Recursive\(/]
|
236
277
|
session.objects_seen[__id__]=[session.objects_in_progress.pop[1]]
|
237
278
|
result
|
@@ -268,7 +309,7 @@ Ron::IGNORED_INSTANCE_VARIABLES["Sequence::WeakRefSet"]=%w[@ids]
|
|
268
309
|
class Range
|
269
310
|
def to_ron_list session
|
270
311
|
# result=
|
271
|
-
["
|
312
|
+
[self.class.name, ".new(",first.to_ron_list2(session), ", ",
|
272
313
|
last.to_ron_list2(session),
|
273
314
|
(", true" if exclude_end?),
|
274
315
|
")"
|
@@ -301,7 +342,7 @@ class Binding
|
|
301
342
|
l<<"self"
|
302
343
|
h={}
|
303
344
|
l.each{|i| h[i.to_sym]=Kernel::eval i, self }
|
304
|
-
h[:yield]=Kernel::eval "block_given? and proc{|*
|
345
|
+
h[:yield]=Kernel::eval "block_given? and proc{|*a__| #,&b__\n yield(*a__) #,&b__\n}", self
|
305
346
|
h
|
306
347
|
end
|
307
348
|
|
@@ -316,17 +357,17 @@ class Binding
|
|
316
357
|
keys.empty? or
|
317
358
|
code=keys.map{|k|
|
318
359
|
k.to_s
|
319
|
-
}.join(',')+'
|
360
|
+
}.join(',')+',=*Thread.current[:$__Ron__CaptureCtx]'
|
320
361
|
mname="Ron__capture_binding#{Thread.current.object_id}" #unlikely method name
|
321
|
-
newmname=result=nil
|
362
|
+
oldmname=newmname=result=nil
|
322
363
|
|
323
364
|
eval "
|
324
|
-
Thread.critical=true
|
325
365
|
newmname=class<<the_self;
|
326
366
|
mname=oldmname='#{mname}'
|
327
|
-
im=instance_methods
|
367
|
+
im=instance_methods
|
368
|
+
im.map!{|sym| sym.to_s} if Symbol===im.first
|
328
369
|
mname+='-' while im.include? mname
|
329
|
-
alias_method mname, oldmname
|
370
|
+
alias_method mname, oldmname if im.include? oldmname
|
330
371
|
def #{mname}
|
331
372
|
#{code}
|
332
373
|
binding
|
@@ -334,9 +375,9 @@ class Binding
|
|
334
375
|
mname
|
335
376
|
end
|
336
377
|
"
|
337
|
-
|
378
|
+
Thread.current[:$__Ron__CaptureCtx]= h.values
|
338
379
|
result=the_self.send mname, &the_block
|
339
|
-
|
380
|
+
Thread.current[:$__Ron__CaptureCtx]=nil
|
340
381
|
class<<the_self;
|
341
382
|
self
|
342
383
|
end.send(*if newmname==mname
|
@@ -344,7 +385,6 @@ class Binding
|
|
344
385
|
else
|
345
386
|
[:alias_method, mname, oldmname]
|
346
387
|
end)
|
347
|
-
Thread.critical=false
|
348
388
|
result
|
349
389
|
end
|
350
390
|
alias from_h -
|
@@ -378,22 +418,20 @@ UnboundMethod,
|
|
378
418
|
|
379
419
|
|
380
420
|
#not sure about these:
|
381
|
-
[
|
382
|
-
Continuation,
|
383
|
-
:Thread,
|
384
|
-
:ThreadGroup,
|
385
|
-
|
386
|
-
:Mutex, #??
|
387
421
|
#and other interthead communication mechanisms, like
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
422
|
+
eval("["+%w[
|
423
|
+
Continuation
|
424
|
+
Thread
|
425
|
+
ThreadGroup
|
426
|
+
Mutex
|
427
|
+
Queue
|
428
|
+
SizedQueue
|
429
|
+
RingBuffer
|
430
|
+
ConditionVariable
|
431
|
+
Semaphore
|
432
|
+
CountingSemaphore
|
433
|
+
Multiwait
|
434
|
+
].map{|x| "(#{x} if defined? #{x}), "}.join+"]").compact.each{|k|
|
397
435
|
k.class_eval do
|
398
436
|
def to_ron(x=nil); raise Ron:: NotYetMaybeNeverSerializeableError end
|
399
437
|
alias to_ron_list to_ron
|
data/lib/ron/column_order.rb
CHANGED
@@ -86,7 +86,7 @@ module ForModule
|
|
86
86
|
#column_order defaults to attribute order if not given
|
87
87
|
cols=(@COLUMN_ORDER if defined? @COLUMN_ORDER) || @REG_ATTRIBUTE_ORDER
|
88
88
|
|
89
|
-
meths=instance_methods(false)
|
89
|
+
meths=instance_methods(false).map{|im| im.to_s}
|
90
90
|
|
91
91
|
module_eval <<-"END"
|
92
92
|
private #utility methods
|
@@ -0,0 +1,168 @@
|
|
1
|
+
begin #redparse/float_accurate_to_s overrides this one, if present
|
2
|
+
require 'redparse/float_accurate_to_s'
|
3
|
+
overridden=true
|
4
|
+
rescue Exception #and ignore
|
5
|
+
end
|
6
|
+
|
7
|
+
class Float
|
8
|
+
SIZE=[1.1].pack("d").size
|
9
|
+
BITSIZE=SIZE*8
|
10
|
+
BASE10_DIGITS=(2**BITSIZE-1).to_s.size
|
11
|
+
def accurate_to_s
|
12
|
+
return "#{'-' if self<0}Infinity" if infinite?
|
13
|
+
return "NaN" if nan?
|
14
|
+
return "0.0e0" if zero?
|
15
|
+
|
16
|
+
as_str=sprintf("%.#{BASE10_DIGITS+2}e",self)
|
17
|
+
|
18
|
+
#decompose self into sign, mantissa, and exponent (in string form)
|
19
|
+
all,sign,first,digits,exp=*as_str.match(/^([+-]?)(\d)\.(\d+)e(.*)$/)
|
20
|
+
digits=first<<digits
|
21
|
+
exp=exp.to_i+1
|
22
|
+
lead=sign<<"0."
|
23
|
+
return digits=digits if as_str.to_f.zero? #hopeless
|
24
|
+
|
25
|
+
#recompose back to a float
|
26
|
+
result=[lead,digits,"e",exp].join
|
27
|
+
result_f=result.to_f
|
28
|
+
delta=result_f - self
|
29
|
+
return digits=digits if delta.zero? #if representation is exact, return here
|
30
|
+
|
31
|
+
#figure out which direction to go to get toward the right answer
|
32
|
+
if delta<0
|
33
|
+
incr=1
|
34
|
+
else #delta>0
|
35
|
+
incr=-1
|
36
|
+
end
|
37
|
+
|
38
|
+
#keep adding increasing increments to mantissa
|
39
|
+
#until we get to a value on the other side of the correct answer
|
40
|
+
while true
|
41
|
+
while true
|
42
|
+
try_digits=digits.to_i.+(incr).to_s
|
43
|
+
if try_digits.size>digits.size
|
44
|
+
exp+=1
|
45
|
+
digits="0"+digits
|
46
|
+
end
|
47
|
+
fail if try_digits[0]==?- #can't happen... I think?
|
48
|
+
trying=[lead,try_digits,"e",exp].join
|
49
|
+
trying_f=trying.to_f
|
50
|
+
break unless trying_f.zero?
|
51
|
+
digits[-1,1]='' #workaround 1.8 bug
|
52
|
+
end
|
53
|
+
return digits=try_digits if trying_f==self
|
54
|
+
break if self.between?(*[trying_f,result_f].sort) #(trying_f-self)*delta<0
|
55
|
+
incr*=2
|
56
|
+
end
|
57
|
+
|
58
|
+
#we now have lower and upper bounds on the correct answer
|
59
|
+
lower,upper=*[digits.to_i, digits.to_i.+(incr)].sort
|
60
|
+
|
61
|
+
#maybe one of the bounds is already the correct answer?
|
62
|
+
result=[lead,lower,"e",exp].join
|
63
|
+
return digits=lower if result.to_f==self
|
64
|
+
result=[lead,upper,"e",exp].join
|
65
|
+
return digits=upper if result.to_f==self
|
66
|
+
|
67
|
+
#binary search between lower and upper bounds til we find a correct answer
|
68
|
+
digits=nil
|
69
|
+
while true
|
70
|
+
return as_str if upper-lower <= 1 #hopeless
|
71
|
+
mid=(lower+upper)/2
|
72
|
+
mid_s=[lead,mid,"e",exp].join
|
73
|
+
mid_f=mid_s.to_f
|
74
|
+
return digits=mid if mid_f==self
|
75
|
+
if mid_f<self
|
76
|
+
lower=mid
|
77
|
+
else #mid_f>self
|
78
|
+
upper=mid
|
79
|
+
end
|
80
|
+
end
|
81
|
+
ensure
|
82
|
+
|
83
|
+
#try to drop unneeded trailing digits
|
84
|
+
if digits
|
85
|
+
digits=digits.to_s
|
86
|
+
begin
|
87
|
+
last=digits.slice! -1
|
88
|
+
result=[lead,digits,"e",exp].join.to_f
|
89
|
+
end while result==self or result.zero? && digits.size.nonzero?
|
90
|
+
roundup=(digits.to_i+1).to_s
|
91
|
+
if roundup.size>digits.size
|
92
|
+
exp+=1
|
93
|
+
digits="0"+digits
|
94
|
+
end
|
95
|
+
roundup.slice! /0+\Z/
|
96
|
+
roundup=[lead,roundup,"e",exp].join
|
97
|
+
return roundup if roundup.to_f==self
|
98
|
+
return [lead,digits<<last,"e",exp].join
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end unless overridden
|
102
|
+
|
103
|
+
=begin not quite accurate, tho
|
104
|
+
class String
|
105
|
+
def accurate_to_f
|
106
|
+
all,sign,int,frac,exp=*self.match(/\A([+-])?([0-9_]+)(?:\.([0-9_]+))?(?:[eE]([+-]?[0-9_]+))?/)
|
107
|
+
exp=exp.to_i||0
|
108
|
+
exp-=frac.size
|
109
|
+
mantissa=sign<<int<<frac
|
110
|
+
mantissa=mantissa.to_f
|
111
|
+
scale=10.0**exp
|
112
|
+
return mantissa*scale
|
113
|
+
end
|
114
|
+
end unless overridden
|
115
|
+
=end
|
116
|
+
|
117
|
+
eval DATA.read if __FILE__==$0
|
118
|
+
__END__
|
119
|
+
|
120
|
+
require 'test/unit'
|
121
|
+
|
122
|
+
class FloatRoundTripTest<Test::Unit::TestCase
|
123
|
+
def float_round_trip f
|
124
|
+
str=f.accurate_to_s
|
125
|
+
if str=="Infinity"
|
126
|
+
return 1.0/0
|
127
|
+
elsif str=="-Infinity"
|
128
|
+
return -1.0/0
|
129
|
+
elsif str=="NaN"
|
130
|
+
return 0.0/0.0
|
131
|
+
else
|
132
|
+
str.to_f
|
133
|
+
end
|
134
|
+
end
|
135
|
+
alias frt float_round_trip
|
136
|
+
|
137
|
+
def rand_float
|
138
|
+
base=rand
|
139
|
+
range=Float::MIN_10_EXP..Float::MAX_10_EXP
|
140
|
+
extent=range.last-range.first
|
141
|
+
offset=rand(extent+1)
|
142
|
+
exp=range.first+offset
|
143
|
+
base*=10**exp
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_frt
|
147
|
+
data=[0.399891415240566, 0.198188037200931, 0.90302699802093,
|
148
|
+
7.48121345153454520016e-01, 4.11408313999083175005e-02,
|
149
|
+
2.68070684698467065488e-02, 3.85029229764812574999e-01,
|
150
|
+
"\327\237vY\343n\342?".unpack("d")[0],
|
151
|
+
1.0/0, -1.0/0, 0.0/0.0,
|
152
|
+
"\333\211>4\253Atu".unpack("d")[0],
|
153
|
+
"\2461\220\253\214\267e\021".unpack("d")[0],
|
154
|
+
"\r\032N\f'\336\243\003".unpack("d")[0],
|
155
|
+
"B[\226\001\2175f\021".unpack("d")[0],
|
156
|
+
"%\217\336\362\326\272\026\001".unpack("d")[0],
|
157
|
+
"\312\342\344\206\237\024\"\003".unpack("d")[0],
|
158
|
+
]
|
159
|
+
1_000_000.times{|i|
|
160
|
+
f=data.shift||rand_float
|
161
|
+
p sprintf("%.#{Float::BASE10_DIGITS}e",f)
|
162
|
+
p [f].pack"d"
|
163
|
+
p f.accurate_to_s
|
164
|
+
f2=frt f
|
165
|
+
warn "failed with i=#{i} f=#{f}, #{[f].pack("d").inspect}; f2=#{f2}, #{[f2].pack("d").inspect}" unless [f].pack("d")==[f2].pack("d")
|
166
|
+
}
|
167
|
+
end
|
168
|
+
end
|
data/lib/ron/graphedge.rb
CHANGED
@@ -38,23 +38,69 @@ module Ron
|
|
38
38
|
end
|
39
39
|
|
40
40
|
#--------------------------------
|
41
|
-
|
42
|
-
|
41
|
+
#
|
42
|
+
#NOTE: breadth_graphcopy has a problem; since graphwalk is not depth-first,
|
43
|
+
# if a node is replaced, the subnodes of the new node will not be walked.
|
44
|
+
# Instead, the old nodes will be walked.
|
45
|
+
# If this causes problems, use depth_graphcopy instead
|
46
|
+
def breadth_graphcopy(obj,old2new={})
|
43
47
|
root=nil
|
44
|
-
|
48
|
+
breadth_graphwalk(obj){|cntr,o,i,ty|
|
45
49
|
newo= block_given? && (yield cntr,o,i,ty,useit=[false])
|
46
|
-
useit.first
|
50
|
+
if useit.first
|
51
|
+
#fail unless newo
|
52
|
+
old2new[o.__id__]=newo
|
53
|
+
else
|
54
|
+
#fail unless o
|
55
|
+
newo= old2new[o.__id__] ||= (o.clone rescue o)
|
56
|
+
end
|
47
57
|
#IO objects really shouldn't be dup'd here
|
48
58
|
if Ron::GraphEdge::TopLevel==ty
|
49
59
|
root=newo
|
50
60
|
else
|
61
|
+
#fail unless old2new.has_key? cntr.__id__
|
51
62
|
ty.new(old2new[cntr.__id__],i,1){newo}.replace
|
52
63
|
end
|
53
64
|
}
|
54
65
|
return root
|
55
66
|
end
|
67
|
+
|
68
|
+
#--------------------------------
|
69
|
+
def depth_graphcopy(obj,old2new={})
|
70
|
+
root=nil
|
71
|
+
changes=[]
|
72
|
+
depth_graphwalk(obj){|cntr,o,i,ty|
|
73
|
+
newo=yield cntr,o,i,ty,useit=[false] if block_given?
|
74
|
+
if useit.first
|
75
|
+
#p [cntr.id,cntr,o,:>>,newo,newo.last.__id__]
|
76
|
+
old2new[o.__id__]=o #bad, bad... shouldn't be refs to old tree in old2new
|
77
|
+
else
|
78
|
+
begin
|
79
|
+
newo=o.clone
|
80
|
+
rescue Exception
|
81
|
+
newo=o
|
82
|
+
else
|
83
|
+
old2new[o.__id__]=newo
|
84
|
+
end
|
85
|
+
end
|
86
|
+
#IO objects really shouldn't be dup'd here
|
87
|
+
if Ron::GraphEdge::TopLevel==ty
|
88
|
+
root=newo
|
89
|
+
else
|
90
|
+
changes.push ty,cntr.__id__,i,newo
|
91
|
+
end
|
92
|
+
}
|
93
|
+
until changes.empty?
|
94
|
+
ty,cntr_id,i,newo=*changes.slice!(-4,4)
|
95
|
+
new_cntr=old2new[cntr_id]
|
96
|
+
ty.new(new_cntr,i,1){newo}.replace if old2new.has_key? cntr_id
|
97
|
+
end
|
98
|
+
return root
|
99
|
+
end
|
100
|
+
alias graphcopy depth_graphcopy
|
56
101
|
|
57
102
|
#--------------------------------
|
103
|
+
#breadth-first walk of an object graph
|
58
104
|
def graphwalk(obj)
|
59
105
|
yield nil,obj,nil,GraphEdge::TopLevel
|
60
106
|
todolist=[obj]
|
@@ -69,7 +115,18 @@ module Ron
|
|
69
115
|
}
|
70
116
|
}
|
71
117
|
end
|
72
|
-
|
118
|
+
alias breadth_graphwalk graphwalk
|
119
|
+
|
120
|
+
#--------------------------------
|
121
|
+
#depth-first walk of an object graph
|
122
|
+
def depth_graphwalk(obj,container=nil,index=nil,type=GraphEdge::TopLevel,seen=Set[],&block)
|
123
|
+
seen<<[container.__id__,type,index]
|
124
|
+
traverse(obj){|cntr,o,i,ty|
|
125
|
+
depth_graphwalk(o,cntr,i,ty,seen,&block) unless seen.include? [cntr.__id__,ty,i]
|
126
|
+
}
|
127
|
+
block[ container,obj,index,type ]
|
128
|
+
end
|
129
|
+
|
73
130
|
#--------------------------------
|
74
131
|
def abortable_graphwalk(obj)
|
75
132
|
return unless yield nil,obj,nil,GraphEdge::TopLevel
|
@@ -93,7 +150,7 @@ module Ron
|
|
93
150
|
case obj
|
94
151
|
when nil; #do nothing
|
95
152
|
when (Set if defined? Set)
|
96
|
-
obj.each{|elem|
|
153
|
+
obj.dup.each{|elem|
|
97
154
|
yield(obj,elem, elem, GraphEdge::SetMember)
|
98
155
|
}
|
99
156
|
when Struct;
|
@@ -101,12 +158,12 @@ module Ron
|
|
101
158
|
yield(obj,obj[mem],mem, GraphEdge::BracketsValue)
|
102
159
|
}
|
103
160
|
when Hash;
|
104
|
-
obj.each{|
|
161
|
+
obj.keys.each{|i| elem=obj[i]
|
105
162
|
yield(obj,elem,i, GraphEdge::HashValue)
|
106
163
|
yield(obj,i,i, GraphEdge::HashKey)
|
107
164
|
}
|
108
165
|
when Array;
|
109
|
-
obj.
|
166
|
+
(obj.size-1).downto(0){|i| elem=obj[i]
|
110
167
|
yield(obj,elem,i, GraphEdge::Array)
|
111
168
|
}
|
112
169
|
when Range;
|
@@ -120,7 +177,7 @@ module Ron
|
|
120
177
|
end
|
121
178
|
#traverse instance vars in any case
|
122
179
|
obj.instance_variables.each{|var|
|
123
|
-
yield obj, (obj.instance_variable_get var), var, GraphEdge::ObjectIvarValue
|
180
|
+
yield obj, (obj.instance_variable_get var), var.to_s, GraphEdge::ObjectIvarValue
|
124
181
|
}
|
125
182
|
end
|
126
183
|
|
@@ -158,7 +215,7 @@ module Ron
|
|
158
215
|
def initialize(context,index,len=1,&newval_code)
|
159
216
|
len>=0 or raise ArgumentError
|
160
217
|
@context,@index,@len,@newval_code=context,index,len,newval_code
|
161
|
-
|
218
|
+
fail unless @context
|
162
219
|
end
|
163
220
|
attr_reader :index,:len,:context
|
164
221
|
|
@@ -167,9 +224,9 @@ module Ron
|
|
167
224
|
|
168
225
|
def call; replace; end
|
169
226
|
|
170
|
-
def context_died
|
171
|
-
@context=nil
|
172
|
-
end
|
227
|
+
# def context_died
|
228
|
+
# @context=nil
|
229
|
+
# end
|
173
230
|
|
174
231
|
def new_value
|
175
232
|
@newval_code[self]
|
@@ -191,9 +248,22 @@ module Ron
|
|
191
248
|
context[@index]
|
192
249
|
end
|
193
250
|
|
194
|
-
|
195
|
-
|
196
|
-
|
251
|
+
|
252
|
+
a=[]
|
253
|
+
a[0]=*[1]
|
254
|
+
if a==[1]
|
255
|
+
def replace(*newvals)
|
256
|
+
newvals.empty? and newvals=[new_value]
|
257
|
+
context[@index]=*newvals
|
258
|
+
end
|
259
|
+
elsif a==[[1]] #goddamn 1.9 array multiple assignment semantics!
|
260
|
+
def replace(*newvals)
|
261
|
+
if newvals.empty? then newvals=new_value
|
262
|
+
elsif newvals.size==1 then newvals=newvals[0]
|
263
|
+
end
|
264
|
+
context[@index]=newvals
|
265
|
+
end
|
266
|
+
else fail
|
197
267
|
end
|
198
268
|
end
|
199
269
|
|
data/lib/ron/version.rb
CHANGED
data/ron.gemspec
CHANGED
@@ -1,28 +1,29 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
-
require
|
3
|
+
require "#{File.dirname(__FILE__)}/lib/ron/version"
|
4
4
|
Ron::Description=open("README.txt"){|f| f.read[/^==+ ?description[^\n]*?\n *\n?(.*?\n *\n.*?)\n *\n/im,1] }
|
5
5
|
Ron::Latest_changes="###"+open("History.txt"){|f| f.read[/\A===(.*?)(?====)/m,1] }
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "Ron"
|
9
9
|
s.version = Ron::VERSION
|
10
|
-
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
-
s.authors = ["Caleb Clausen"]
|
13
10
|
s.date = Time.now.strftime("%Y-%m-%d")
|
11
|
+
s.authors = ["Caleb Clausen"]
|
14
12
|
s.email = %q{caleb (at) inforadical (dot) net}
|
15
|
-
s.
|
16
|
-
s.
|
17
|
-
s.has_rdoc = true
|
13
|
+
s.summary = "Ruby Object Notation (Ron) is a ruby-based textual format for representing Ruby data."
|
14
|
+
s.description = Ron::Description
|
18
15
|
s.homepage = %{http://github.com/coatl/ron}
|
19
|
-
s.rdoc_options = %w[--inline-source --main README.txt]
|
20
|
-
s.require_paths = ["lib"]
|
21
16
|
s.rubyforge_project = %q{ron}
|
22
|
-
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split
|
23
19
|
s.test_files = %w[test/test_all.rb]
|
24
|
-
s.
|
25
|
-
s.
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.extra_rdoc_files = ["README.txt", "COPYING", "GPL"]
|
22
|
+
s.has_rdoc = true
|
23
|
+
s.rdoc_options = %w[--main README.txt]
|
24
|
+
|
25
|
+
s.rubygems_version = %q{1.3.0}
|
26
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
26
27
|
|
27
28
|
=begin
|
28
29
|
if s.respond_to? :specification_version then
|
data/test/test_all.rb
CHANGED
@@ -18,6 +18,8 @@ try_require 'rubygems'
|
|
18
18
|
try_require("sequence/weakrefset")
|
19
19
|
try_require 'facets/more/superstruct'
|
20
20
|
|
21
|
+
require "test/test_graphcopy"
|
22
|
+
|
21
23
|
$Verbose=true
|
22
24
|
|
23
25
|
=begin
|
@@ -67,10 +69,33 @@ def == bm
|
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
72
|
+
class MyString<String
|
73
|
+
attr_accessor :ivar
|
74
|
+
end
|
75
|
+
|
76
|
+
class MyRegexp<Regexp
|
77
|
+
attr_accessor :ivar
|
78
|
+
end
|
79
|
+
|
80
|
+
class MyArray<Array
|
81
|
+
attr_accessor :ivar
|
82
|
+
end
|
83
|
+
|
84
|
+
class MyHash<Hash
|
85
|
+
attr_accessor :ivar
|
86
|
+
end
|
87
|
+
|
88
|
+
class MyRange<Range
|
89
|
+
attr_accessor :ivar
|
90
|
+
end
|
91
|
+
|
92
|
+
module M
|
93
|
+
end
|
94
|
+
|
95
|
+
|
70
96
|
class RonTest<Test::Unit::TestCase
|
71
97
|
|
72
98
|
def test_ron
|
73
|
-
|
74
99
|
s1=1.0
|
75
100
|
s2=2.0
|
76
101
|
range=s1..s2
|
@@ -83,13 +108,16 @@ s2.instance_variable_set(:@n, ss)
|
|
83
108
|
s1=1.0
|
84
109
|
s2=2.0
|
85
110
|
sss=SortedSet[s1,s2]
|
86
|
-
s1.instance_variable_set(:@
|
87
|
-
s2.instance_variable_set(:@
|
111
|
+
s1.instance_variable_set(:@o, sss)
|
112
|
+
s2.instance_variable_set(:@o, sss)
|
88
113
|
|
89
114
|
sss.inspect #disable this and tests fail... why?!?!?
|
115
|
+
strongrefs=%w[a b c]
|
90
116
|
data=[
|
91
|
-
|
117
|
+
34565.23458888888*0.5,
|
118
|
+
45245.765735422567*0.5,
|
92
119
|
3.14159,
|
120
|
+
1.2345678901234567,
|
93
121
|
2**2000,
|
94
122
|
|
95
123
|
"string",
|
@@ -111,7 +139,7 @@ data=[
|
|
111
139
|
[1,2,3],
|
112
140
|
{1=>2,3=>4},
|
113
141
|
Set[1,2,3],
|
114
|
-
(Sequence::WeakRefSet[
|
142
|
+
(Sequence::WeakRefSet[*strongrefs] rescue warn 'weakrefset test disabled'),
|
115
143
|
A_Class.new,
|
116
144
|
2,
|
117
145
|
:symbol,
|
@@ -119,10 +147,18 @@ data=[
|
|
119
147
|
true,
|
120
148
|
false,
|
121
149
|
|
122
|
-
|
150
|
+
MyString.new,
|
151
|
+
MyRegexp.new(//),
|
152
|
+
MyArray.new,
|
153
|
+
MyHash.new,
|
154
|
+
MyRange.new(1,2),
|
155
|
+
|
156
|
+
"\\",
|
157
|
+
"'",
|
123
158
|
]
|
124
159
|
data.each{|datum|
|
125
|
-
|
160
|
+
GC.disable
|
161
|
+
#p datum
|
126
162
|
assert_equal datum, datum
|
127
163
|
assert_equal datum, ( dup=eval datum.to_ron )
|
128
164
|
assert_equal internal_state(datum), internal_state(dup)
|
@@ -138,17 +174,30 @@ data.each{|datum|
|
|
138
174
|
datum.instance_eval{@c=self}
|
139
175
|
assert_equal datum, ( dup=eval datum.to_ron )
|
140
176
|
assert_equal internal_state(datum), internal_state(dup)
|
177
|
+
|
178
|
+
datum.extend(M)
|
179
|
+
assert_equal datum, ( dup=eval datum.to_ron )
|
180
|
+
assert_equal internal_state(datum), internal_state(dup)
|
181
|
+
assert M===dup
|
141
182
|
end
|
183
|
+
GC.enable
|
142
184
|
}
|
143
185
|
data.each{|datum|
|
186
|
+
GC.disable
|
144
187
|
if case datum
|
145
188
|
when Fixnum,Symbol,true,false,nil; false
|
146
189
|
else true
|
147
190
|
end
|
148
191
|
datum.instance_eval{@d=data}
|
149
|
-
|
150
|
-
|
192
|
+
assert_equal datum, ( dup=eval datum.to_ron )
|
193
|
+
assert_equal internal_state(datum), internal_state(dup)
|
194
|
+
|
195
|
+
datum.extend(M)
|
196
|
+
assert_equal datum, ( dup=eval datum.to_ron )
|
197
|
+
assert_equal internal_state(datum), internal_state(dup)
|
198
|
+
assert M===dup
|
151
199
|
end
|
200
|
+
GC.enable
|
152
201
|
}
|
153
202
|
|
154
203
|
data2=[
|
@@ -160,35 +209,57 @@ data2=[
|
|
160
209
|
(h={};h[h]=0;h),
|
161
210
|
(h={};h[h]=h;h),
|
162
211
|
(s=Set[];s<<s;s),
|
212
|
+
(o=MyString.new; o.ivar=o; o),
|
213
|
+
(o=MyArray.new; o.ivar=o; o),
|
214
|
+
(o=MyHash.new; o.ivar=o; o),
|
215
|
+
(o=MyArray.new; o<<o),
|
216
|
+
(o=MyHash.new; o[1]=o; o),
|
217
|
+
(o=MyRange.new(1,2); o.ivar=o; o),
|
163
218
|
]
|
164
|
-
data2.each{|datum|
|
165
|
-
|
219
|
+
data2.each{|datum|
|
220
|
+
GC.disable
|
221
|
+
#p datum
|
166
222
|
assert_equal datum.to_yaml, datum.to_yaml
|
167
|
-
|
168
|
-
|
223
|
+
dup=eval datum.to_ron
|
224
|
+
dup.inspect #shouldn't be needed
|
225
|
+
assert_equal datum.to_yaml, dup.to_yaml
|
226
|
+
assert_equal internal_state(datum)[0...2], internal_state(dup)[0...2]
|
227
|
+
assert_equal internal_state(datum)[2..-1].to_yaml, internal_state(dup)[2..-1].to_yaml
|
169
228
|
|
170
229
|
if case datum
|
171
230
|
when Fixnum,Symbol,true,false,nil; false
|
172
231
|
else true
|
173
232
|
end
|
174
233
|
datum.instance_eval{@a,@b=1,2}
|
175
|
-
|
176
|
-
|
234
|
+
dup=eval datum.to_ron
|
235
|
+
dup.inspect #shouldn't be needed
|
236
|
+
assert_equal datum.to_yaml, dup.to_yaml
|
237
|
+
assert_equal internal_state(datum)[0...2], internal_state(dup)[0...2]
|
238
|
+
assert_equal internal_state(datum)[2..-1].to_yaml, internal_state(dup)[2..-1].to_yaml
|
177
239
|
|
178
240
|
datum.instance_eval{@c=self}
|
179
|
-
|
180
|
-
|
241
|
+
dup=eval datum.to_ron
|
242
|
+
dup.inspect #shouldn't be needed
|
243
|
+
assert_equal datum.to_yaml, dup.to_yaml
|
244
|
+
assert_equal internal_state(datum)[0...2], internal_state(dup)[0...2]
|
245
|
+
assert_equal internal_state(datum)[2..-1].to_yaml, internal_state(dup)[2..-1].to_yaml
|
246
|
+
|
247
|
+
datum.extend(M)
|
248
|
+
dup=eval datum.to_ron
|
249
|
+
dup.inspect #shouldn't be needed
|
250
|
+
assert_equal datum.to_yaml, dup.to_yaml
|
251
|
+
assert_equal internal_state(datum)[0...2], internal_state(dup)[0...2]
|
252
|
+
assert_equal internal_state(datum)[2..-1].to_yaml, internal_state(dup)[2..-1].to_yaml
|
253
|
+
assert M===dup
|
181
254
|
end
|
182
|
-
|
183
|
-
|
255
|
+
GC.enable
|
256
|
+
}
|
257
|
+
GC.disable
|
258
|
+
datum= ((w=Sequence::WeakRefSet[];w<<w;w) rescue warn 'weakrefset test disabled')
|
184
259
|
assert_equal datum.inspect, datum.inspect
|
185
260
|
assert_equal datum.inspect, ( dup=eval datum.to_ron ).inspect
|
186
261
|
assert_equal internal_state(datum).inspect, internal_state(dup).inspect
|
187
262
|
|
188
|
-
if case datum
|
189
|
-
when Fixnum,Symbol,true,false,nil; false
|
190
|
-
else true
|
191
|
-
end
|
192
263
|
datum.instance_eval{@a,@b=1,2}
|
193
264
|
assert_equal datum.inspect, ( dup=eval datum.to_ron ).inspect
|
194
265
|
assert_equal internal_state(datum).inspect, internal_state(dup).inspect
|
@@ -196,24 +267,26 @@ datum= ((w=Sequence::WeakRefSet[];w<<w;w) rescue warn 'weakrefset test disabled'
|
|
196
267
|
datum.instance_eval{@c=self}
|
197
268
|
assert_equal datum.inspect, ( dup=eval datum.to_ron ).inspect
|
198
269
|
assert_equal internal_state(datum).inspect, internal_state(dup).inspect
|
199
|
-
end
|
200
270
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
datum.
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
271
|
+
datum= (o=MyRegexp.new(//); o.ivar=o; o)
|
272
|
+
ron=datum.to_ron
|
273
|
+
assert_match %r"Recursive\(v\d+_=\{\}, MyRegexp\.new\(\"\"\)\.with_ivars\(:@ivar=>v\d+_\)\)", ron
|
274
|
+
assert_equal datum,eval(ron)
|
275
|
+
datum.extend M
|
276
|
+
ron=datum.to_ron
|
277
|
+
assert M===eval(ron)
|
278
|
+
GC.enable
|
279
|
+
end
|
280
|
+
|
281
|
+
def nonrecursive_ancestors_of x
|
282
|
+
class<<x;ancestors end-[Recursive]
|
283
|
+
rescue TypeError
|
284
|
+
[]
|
212
285
|
end
|
213
286
|
|
214
287
|
def internal_state x
|
215
|
-
list=(x.instance_variables-::Ron::IGNORED_INSTANCE_VARIABLES[x.class.name]).sort
|
216
|
-
[list]+list.map{|iv| x.instance_variable_get(iv)}
|
288
|
+
list=(x.instance_variables.map!{|iv| iv.to_s}-::Ron::IGNORED_INSTANCE_VARIABLES[x.class.name]).sort
|
289
|
+
[x.class,nonrecursive_ancestors_of(x),list]+list.map{|iv| x.instance_variable_get(iv)}
|
217
290
|
end
|
218
291
|
|
219
292
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'ron'
|
3
|
+
require 'ron/graphedge'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
class TestGraphCopy<Test::Unit::TestCase
|
7
|
+
inner=["foo",nil]
|
8
|
+
TESTDATA=[
|
9
|
+
{:one=>inner, :two=>inner, :three=>nil}
|
10
|
+
]
|
11
|
+
|
12
|
+
def test_depth
|
13
|
+
TESTDATA.each{|td|
|
14
|
+
copy=Ron::GraphWalk::depth_graphcopy(td){|cntr,o,i,ty,useit|
|
15
|
+
if :one==i and Ron::GraphEdge::HashValue==ty
|
16
|
+
useit[0]=true
|
17
|
+
["bar"]
|
18
|
+
elsif "foo"==o
|
19
|
+
useit[0]=true
|
20
|
+
"baz"
|
21
|
+
end
|
22
|
+
}
|
23
|
+
assert_equal({:three=>nil, :one=>["bar"], :two=>["baz", nil]}, copy)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_breadth
|
28
|
+
TESTDATA.each{|td|
|
29
|
+
copy=Ron::GraphWalk::breadth_graphcopy(td){|cntr,o,i,ty,useit|
|
30
|
+
if :one==i and Ron::GraphEdge::HashValue==ty
|
31
|
+
useit[0]=true
|
32
|
+
["bar"]
|
33
|
+
elsif "foo"==o
|
34
|
+
useit[0]=true
|
35
|
+
"baz"
|
36
|
+
end
|
37
|
+
}
|
38
|
+
assert_equal({:three=>nil, :one=>["baz", nil], :two=>["baz", nil]}, copy)
|
39
|
+
#?? is that really the right output ??
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Ron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Caleb Clausen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-03 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -28,20 +28,19 @@ files:
|
|
28
28
|
- GPL
|
29
29
|
- History.txt
|
30
30
|
- Makefile
|
31
|
-
- Manifest.txt
|
32
31
|
- README.txt
|
33
|
-
- Rakefile
|
34
32
|
- lib/ron.rb
|
35
33
|
- lib/ron/column_order.rb
|
34
|
+
- lib/ron/float_accurate_to_s.rb
|
36
35
|
- lib/ron/graphedge.rb
|
37
36
|
- lib/ron/version.rb
|
38
37
|
- ron.gemspec
|
39
38
|
- test/test_all.rb
|
39
|
+
- test/test_graphcopy.rb
|
40
40
|
has_rdoc: true
|
41
41
|
homepage: http://github.com/coatl/ron
|
42
42
|
post_install_message:
|
43
43
|
rdoc_options:
|
44
|
-
- --inline-source
|
45
44
|
- --main
|
46
45
|
- README.txt
|
47
46
|
require_paths:
|
data/Manifest.txt
DELETED
data/Rakefile
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# Copyright (C) 2006 Caleb Clausen
|
2
|
-
# Distributed under the terms of Ruby's license.
|
3
|
-
require 'rubygems'
|
4
|
-
require 'hoe'
|
5
|
-
require 'lib/ron/version.rb'
|
6
|
-
|
7
|
-
if $*==["test"]
|
8
|
-
#hack to get 'rake test' to stay in one process
|
9
|
-
#which keeps netbeans happy
|
10
|
-
$:<<"lib"
|
11
|
-
# require 'ron.rb'
|
12
|
-
# require "test/unit"
|
13
|
-
require "test/test_all.rb"
|
14
|
-
Test::Unit::AutoRunner.run
|
15
|
-
exit
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
Hoe.new("Ron", Ron::VERSION) do |_|
|
21
|
-
|
22
|
-
_.author = "Caleb Clausen"
|
23
|
-
_.email = "ron-owner @at@ inforadical .dot. net"
|
24
|
-
_.url = "http://rubyforge.org/projects/ron"
|
25
|
-
_.summary = "Ron is a ruby-based serialization format for representing any ruby
|
26
|
-
object graph."
|
27
|
-
|
28
|
-
_.description = <<'END'
|
29
|
-
Ron is very much like JSON, but based around Ruby instead of JavaScript.
|
30
|
-
Stardard Ruby literal notation is extended to include an object literal
|
31
|
-
and a way to create self-referencing data structures.
|
32
|
-
END
|
33
|
-
_.changes='' #1st version, no changes
|
34
|
-
end
|
35
|
-
|
36
|
-
# add other tasks here
|
37
|
-
|