HDLRuby 2.4.29 → 2.6.4

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/HDLRuby/drivers/xcd.rb +79 -0
  3. data/lib/HDLRuby/drivers/xcd/dummy.xcd +4 -0
  4. data/lib/HDLRuby/hdr_samples/adder.rb +1 -1
  5. data/lib/HDLRuby/hdr_samples/adder_bench.rb +1 -1
  6. data/lib/HDLRuby/hdr_samples/adder_gen.rb +1 -1
  7. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +27 -0
  8. data/lib/HDLRuby/hdr_samples/dff_properties.rb +19 -0
  9. data/lib/HDLRuby/hdr_samples/dff_unit.rb +54 -0
  10. data/lib/HDLRuby/hdr_samples/huge_rom.rb +25 -0
  11. data/lib/HDLRuby/hdr_samples/logic_bench.rb +21 -0
  12. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
  13. data/lib/HDLRuby/hdr_samples/multi_timed_bench.rb +54 -0
  14. data/lib/HDLRuby/hdr_samples/music.rb +79 -0
  15. data/lib/HDLRuby/hdr_samples/named_sub.rb +42 -0
  16. data/lib/HDLRuby/hdr_samples/rom.rb +16 -0
  17. data/lib/HDLRuby/hdr_samples/with_function_generator.rb +25 -0
  18. data/lib/HDLRuby/hdrcc.rb +162 -26
  19. data/lib/HDLRuby/hruby_decorator.rb +250 -0
  20. data/lib/HDLRuby/hruby_high.rb +468 -91
  21. data/lib/HDLRuby/hruby_low.rb +913 -45
  22. data/lib/HDLRuby/hruby_low2c.rb +122 -168
  23. data/lib/HDLRuby/hruby_low2hdr.rb +738 -0
  24. data/lib/HDLRuby/hruby_low2high.rb +331 -549
  25. data/lib/HDLRuby/hruby_low2vhd.rb +39 -2
  26. data/lib/HDLRuby/hruby_low_bool2select.rb +29 -0
  27. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +27 -0
  28. data/lib/HDLRuby/hruby_low_fix_types.rb +25 -0
  29. data/lib/HDLRuby/hruby_low_mutable.rb +70 -0
  30. data/lib/HDLRuby/hruby_low_resolve.rb +28 -0
  31. data/lib/HDLRuby/hruby_low_without_connection.rb +6 -3
  32. data/lib/HDLRuby/hruby_low_without_namespace.rb +7 -4
  33. data/lib/HDLRuby/hruby_low_without_select.rb +13 -0
  34. data/lib/HDLRuby/hruby_tools.rb +11 -1
  35. data/lib/HDLRuby/hruby_verilog.rb +1577 -1709
  36. data/lib/HDLRuby/sim/hruby_sim.h +29 -3
  37. data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
  38. data/lib/HDLRuby/sim/hruby_sim_core.c +24 -9
  39. data/lib/HDLRuby/sim/hruby_sim_vcd.c +5 -1
  40. data/lib/HDLRuby/sim/hruby_sim_vizualize.c +22 -6
  41. data/lib/HDLRuby/std/fixpoint.rb +9 -0
  42. data/lib/HDLRuby/std/function_generator.rb +139 -0
  43. data/lib/HDLRuby/std/hruby_unit.rb +75 -0
  44. data/lib/HDLRuby/template_expander.rb +61 -0
  45. data/lib/HDLRuby/version.rb +1 -1
  46. metadata +21 -5
@@ -14,3 +14,19 @@ system :rom4_8 do
14
14
  data1 <= content1[addr]
15
15
  data2 <= content2[addr]
16
16
  end
17
+
18
+
19
+
20
+ system :test_rom do
21
+ [2..0].inner :addr
22
+ [7..0].inner :data0,:data1,:data2
23
+
24
+ rom4_8(:my_rom).(addr,data0,data1,data2)
25
+
26
+ timed do
27
+ 8.times do |i|
28
+ addr <= i
29
+ !10.ns
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ require 'std/function_generator.rb'
2
+
3
+ include HDLRuby::High::Std
4
+
5
+ # System for testing the function generator standard library.
6
+ system :with_function_generator do
7
+ # signed[8].inner :x
8
+ # signed[32].inner :y
9
+ bit[8].inner :x
10
+ signed[8].inner :y
11
+
12
+ # function_generator(Math.method(:sin).to_proc,
13
+ # signed[8],signed[32],4,-Math::PI..Math::PI,-2..2).
14
+ function_generator(Math.method(:sin).to_proc,
15
+ bit[8],signed[8],4,-Math::PI..Math::PI,-2..2).
16
+ (:my_sin).(x,y)
17
+
18
+ timed do
19
+ # (-128..127).each do |i|
20
+ (0..255).each do |i|
21
+ x <= i
22
+ !10.ns
23
+ end
24
+ end
25
+ end
data/lib/HDLRuby/hdrcc.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
3
  require 'fileutils'
4
+ require 'tempfile'
4
5
  require 'HDLRuby'
5
6
  require 'HDLRuby/hruby_check.rb'
6
7
  # require 'ripper'
7
- require 'HDLRuby/hruby_low2high'
8
+ require 'HDLRuby/hruby_low2hdr'
8
9
  require 'HDLRuby/hruby_low2c'
9
10
  require 'HDLRuby/hruby_low2vhd'
10
11
  require 'HDLRuby/hruby_low_fix_types'
@@ -50,12 +51,21 @@ module HDLRuby
50
51
  # The required files.
51
52
  attr_reader :requires
52
53
 
53
- # Creates a new loader for a +top_system+ system in file +top_file+
54
+ # Creates a new loader for a +top_system+ system in file +top_file_name+
54
55
  # from directory +dir+ with generic parameters +params+.
56
+ #
57
+ # NOTE: +top_file+ can either be a file or a file name.
55
58
  def initialize(top_system,top_file,dir,*params)
56
59
  # Sets the top and the looking directory.
57
60
  @top_system = top_system.to_s
58
- @top_file = top_file.to_s
61
+ # @top_file can either be a file or a string giving the file name.
62
+ if top_file.respond_to?(:path) then
63
+ @top_file = top_file
64
+ @top_file_name = top_file.path
65
+ else
66
+ @top_file = nil
67
+ @top_file_name = top_file.to_s
68
+ end
59
69
  @dir = dir.to_s
60
70
  @params = params
61
71
 
@@ -82,31 +92,48 @@ module HDLRuby
82
92
  end
83
93
 
84
94
  # Loads a single +file+.
95
+ #
96
+ # NOTE: +file+ can either be a file or a file name.
85
97
  def read(file)
86
98
  # Resolve the file.
87
- found = File.join(@dir,file)
88
- unless File.exist?(found) then
89
- founds = Dir.glob(@std_dirs.map {|path| File.join(path,file) })
90
- if founds.empty? then
91
- # No standard file with this name, this is an error.
92
- raise "Unknown required file: #{file}."
93
- else
94
- # A standard file is found, skip it since it does not
95
- # need to be read.
96
- # puts "Standard files: #{founds}"
97
- return false
99
+ if file.respond_to?(:read) then
100
+ found = file
101
+ else
102
+ found = File.join(@dir,file)
103
+ unless File.exist?(found) then
104
+ founds = Dir.glob(@std_dirs.map do |path|
105
+ File.join(path,file)
106
+ end)
107
+ if founds.empty? then
108
+ # No standard file with this name, this is an error.
109
+ raise "Unknown required file: #{file}."
110
+ else
111
+ # A standard file is found, skip it since it does not
112
+ # need to be read.
113
+ # puts "Standard files: #{founds}"
114
+ return false
115
+ end
98
116
  end
99
117
  end
100
118
  # Load the file.
101
- # @texts << File.read(File.join(@dir,file) )
102
119
  @texts << File.read(found)
103
- # @checks << Checker.new(@texts[-1],file)
104
- @checks << Checker.new(@texts[-1],found)
120
+ if found.respond_to?(:path) then
121
+ @checks << Checker.new(@texts[-1],found.path)
122
+ else
123
+ @checks << Checker.new(@texts[-1])
124
+ end
105
125
  return true
106
126
  end
107
127
 
108
128
  # Loads all the files from +file+.
109
- def read_all(file = @top_file)
129
+ def read_all(file = nil)
130
+ unless file then
131
+ if @top_file then
132
+ file = @top_file
133
+ else
134
+ file = @top_file_name
135
+ end
136
+ end
110
137
  # puts "read_all with file=#{file}"
111
138
  # Read the file
112
139
  # read(file)
@@ -174,7 +201,7 @@ module HDLRuby
174
201
  # Maybe it is a parse error, look for it.
175
202
  bind = TOPLEVEL_BINDING.clone
176
203
  eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
177
- eval(@texts[0],bind,@top_file,1)
204
+ eval(@texts[0],bind,@top_file_name,1)
178
205
  # No parse error found.
179
206
  raise "Cannot find a top system." unless @top_system
180
207
  end
@@ -183,7 +210,7 @@ module HDLRuby
183
210
  bind = TOPLEVEL_BINDING.clone
184
211
  eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
185
212
  # Process it.
186
- eval(@texts[0],bind,@top_file,1)
213
+ eval(@texts[0],bind,@top_file_name,1)
187
214
  # Get the resulting instance
188
215
  if @params.empty? then
189
216
  # There is no generic parameter
@@ -225,6 +252,20 @@ module HDLRuby
225
252
 
226
253
  end
227
254
 
255
+ # Locate an executable from cmd.
256
+ def which(cmd)
257
+ # Get the possible exetensions (for windows case).
258
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
259
+ # Look for the command within the executable paths.
260
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
261
+ exts.each do |ext|
262
+ exe = File.join(path, "#{cmd}#{ext}")
263
+ return exe if File.executable?(exe) && !File.directory?(exe)
264
+ end
265
+ end
266
+ nil
267
+ end
268
+
228
269
 
229
270
 
230
271
  if __FILE__ == $0 then
@@ -310,14 +351,24 @@ $optparse = OptionParser.new do |opts|
310
351
  opts.on("-D", "--debug","Set the HDLRuby debug mode") do |d|
311
352
  $options[:debug] = d
312
353
  end
354
+ opts.on("-T","--test t0,t1,t2","Compile the unit tests named t0,t1,...") do |t|
355
+ $options[:test] = t
356
+ end
357
+ opts.on("--testall","Compile all the available unit tests.") do |t|
358
+ $options[:testall] = t
359
+ end
313
360
  opts.on("-t", "--top system", "Specify the top system to process") do|t|
314
361
  $options[:top] = t
315
362
  end
316
363
  opts.on("-p", "--param x,y,z", "Specify the generic parameters") do |p|
317
364
  $options[:param] = p
318
365
  end
319
- opts.on("--version", "Print the version number, then exit") do
320
- puts "hdrcc: HDLRuby #{HDLRuby::VERSION} compiler"
366
+ opts.on("--dump","Dump all the properties to yaml files") do |v|
367
+ $options[:dump] = v
368
+ $options[:multiple] = v
369
+ end
370
+ opts.on("--version", "Shows the version of HDLRuby.") do |v|
371
+ puts VERSION
321
372
  exit
322
373
  end
323
374
  # opts.on_tail("-h", "--help", "Show this message") do
@@ -370,6 +421,28 @@ if $input == nil then
370
421
  exit
371
422
  end
372
423
 
424
+ if ($options[:test] || $options[:testall]) then
425
+ $top = "__test__"
426
+ tests = $options[:test]
427
+ if tests then
428
+ tests = tests.to_s.split(",")
429
+ tests.map! {|test| ":\"#{test}\"" }
430
+ tests = ", #{tests.join(",")}"
431
+ else
432
+ tests = ""
433
+ end
434
+ # Generate the unit test file.
435
+ $test_file = Tempfile.new('tester.rb',Dir.getwd)
436
+ $test_file.write("require 'std/hruby_unit.rb'\nrequire_relative '#{$input}'\n\n" +
437
+ "HDLRuby::Unit.test(:\"#{$top}\"#{tests})\n")
438
+ # $test_file.rewind
439
+ # puts $test_file.read
440
+ # exit
441
+ $test_file.rewind
442
+ # It is the new input file.
443
+ $input = $test_file
444
+ end
445
+
373
446
  # Open the output.
374
447
  if $output then
375
448
  if $options[:multiple] then
@@ -382,7 +455,7 @@ if $output then
382
455
  $output = File.open($output,"w")
383
456
  end
384
457
  else
385
- if $option[:multiple] then
458
+ if $options[:multiple] then
386
459
  raise "Need a target directory in multiple files generation mode."
387
460
  end
388
461
  $output = $stdout
@@ -394,6 +467,12 @@ $loader = HDRLoad.new($top,$input,$options[:directory].to_s,*$params)
394
467
  $loader.read_all
395
468
  $loader.check_all
396
469
 
470
+ # Remove the test file if any, it is not needed any longer.
471
+ if $test_file then
472
+ $test_file.close
473
+ $test_file.unlink
474
+ end
475
+
397
476
  if $options[:syntax] then
398
477
  if $options[:multiple] then
399
478
  raise "Multiple files generation mode not supported for syntax tree output."
@@ -414,6 +493,24 @@ end
414
493
  # Get the top systemT.
415
494
  $top_system = $top_instance.to_low.systemT
416
495
 
496
+
497
+ # Apply the pre drivers if any.
498
+ Hdecorator.each_with_property(:pre_driver) do |obj, value|
499
+ unless value.is_a?(Array) && value.size == 2 then
500
+ raise "pre_driver requires a driver file name command name."
501
+ end
502
+ # Load the driver.
503
+ require_relative(value[0].to_s)
504
+ # Ensure obj is the low version.
505
+ if obj.properties.key?(:high2low) then
506
+ # obj is high, get the corresponding low.
507
+ obj = obj.properties[:high2low][0]
508
+ end
509
+ # Execute it.
510
+ send(value[1].to_sym,obj,*value[2..-1])
511
+ end
512
+
513
+
417
514
  # Gather the non-HDLRuby code.
418
515
  $non_hdlruby = []
419
516
  $top_system.each_systemT_deep do |systemT|
@@ -455,7 +552,7 @@ elsif $options[:hdr] then
455
552
  # $output << systemT.to_high
456
553
  # end
457
554
  # $output << $top_instance.to_low.systemT.to_high
458
- $output << $top_system.to_high
555
+ $output << $top_system.to_hdr
459
556
  elsif $options[:clang] then
460
557
  # top_system = $top_instance.to_low.systemT
461
558
  # top_system = $top_system
@@ -572,8 +669,19 @@ elsif $options[:clang] then
572
669
  end
573
670
  end
574
671
  Dir.chdir($output)
575
- # Kernel.system("make -s")
576
- Kernel.system("cc -o3 -o hruby_simulator *.c -lpthread")
672
+ # Find the compiler.
673
+ cc_cmd = which('cc')
674
+ unless cc_cmd then
675
+ cc_cmd = which('gcc')
676
+ end
677
+ unless cc_cmd then
678
+ raise "Could not find any compiler, please compile by hand as follows:\n" +
679
+ " In folder #{$output} execute:\n" +
680
+ " <my compiler> -o hruby_simulator *.c -lpthread\n" +
681
+ " Then execute:\n hruby_simulator"
682
+ end
683
+ # Use it.
684
+ Kernel.system("#{cc_cmd} -o3 -o hruby_simulator *.c -lpthread")
577
685
  Kernel.system("./hruby_simulator")
578
686
  end
579
687
  elsif $options[:verilog] then
@@ -678,3 +786,31 @@ elsif $options[:vhdl] then
678
786
  end
679
787
  end
680
788
  end
789
+
790
+ # Apply the post drivers if any.
791
+ Hdecorator.each_with_property(:post_driver) do |obj, value|
792
+ # Load the driver.
793
+ require_relative(value[0].to_s)
794
+ # Execute it.
795
+ send(value[1].to_sym,obj,$output)
796
+ end
797
+
798
+ # Dump the properties
799
+ if $options[:dump] then
800
+ # Decorate with the parent ids.
801
+ Hdecorator.decorate_parent_id
802
+
803
+ # Generate the directory for the properties
804
+ property_dir = $output + "/properties"
805
+ unless File.directory?(property_dir)
806
+ FileUtils.mkdir_p(property_dir)
807
+ end
808
+
809
+ # Dump to one file per key
810
+ Properties.each_key do |key|
811
+ File.open(property_dir + "/#{key}.yaml", "w") do |f|
812
+ Hdecorator.dump(key,f)
813
+ end
814
+ end
815
+
816
+ end
@@ -0,0 +1,250 @@
1
+ require 'yaml'
2
+ require 'set'
3
+
4
+ module HDLRuby
5
+
6
+ ##
7
+ # Library for describing a decorator used for adding properties to
8
+ # HDLRuby objects that are persistent and can be used for back annotation
9
+ ########################################################################
10
+
11
+ ##
12
+ # Gives a decorator the HDLRuby object.
13
+ module Hdecorator
14
+ # The decorator requires that each HDLRuby object has a uniq
15
+ # persistent id
16
+
17
+ # The id
18
+ attr_reader :hdr_id
19
+
20
+ # The id to object table
21
+ @@id_map = {}
22
+
23
+ # Generate the ID
24
+ @@id_gen = 0
25
+
26
+ # Ensures the ID is generated when object is initialized
27
+ def self.included(base) # built-in Ruby hook for modules
28
+ base.class_eval do
29
+ original_method = instance_method(:initialize)
30
+ define_method(:initialize) do |*args, &block|
31
+ original_method.bind(self).call(*args, &block)
32
+ # Generate the id.
33
+ @hdr_id = @@id_gen
34
+ @@id_gen += 1
35
+ # Update the id to object table
36
+ @@id_map[@hdr_id] = self
37
+ end
38
+ end
39
+ end
40
+
41
+ # Get an object by id.
42
+ def self.get(id)
43
+ return @@id_map[id]
44
+ end
45
+
46
+ # Iterate over all the id with their object.
47
+ #
48
+ # Returns an enumerator if no ruby block is given.
49
+ #
50
+ # NOTE: converts the hash to an array to allow on-the-fly modification.
51
+ def self.each(&ruby_block)
52
+ # No ruby block? Return an enumerator.
53
+ return to_enum(:each) unless ruby_block
54
+ # A ruby block? Apply it on each object.
55
+ @@id_map.to_a.each(&ruby_block)
56
+ end
57
+
58
+ # The decorator also need to add properties to the HDLRuby objects.
59
+
60
+ # Access the set of properties
61
+ def properties
62
+ # Create the properties if not present.
63
+ unless @properties then
64
+ @properties = Properties.new(self)
65
+ end
66
+ return @properties
67
+ end
68
+
69
+ # Iterate over all the objects from +top+ with +prop+ property.
70
+ #
71
+ # Returns an enumerator if no ruby block is given.
72
+ # NOTE: if +top+ is not given, iterate over all the objects.
73
+ def self.each_with_property(prop, top = nil, &ruby_block)
74
+ # No ruby block? Return an enumerator.
75
+ return to_enum(:each_with_property) unless ruby_block
76
+ # A ruby block? Apply the ruby_block...
77
+ if (top) then
78
+ # A top... on each object from it.
79
+ top.each_deep do |obj|
80
+ if (obj.properties.key?(prop)) then
81
+ ruby_block.call(obj, *obj.properties[prop])
82
+ end
83
+ end
84
+ else
85
+ # No top... on all the objects.
86
+ self.each do |id,obj|
87
+ if (obj.properties.key?(prop)) then
88
+ ruby_block.call(obj, *obj.properties[prop])
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ # # Access the set of properties and the inherited properties from
95
+ # # the high objects.
96
+ # def all_properties
97
+ # high_id = self.properties[:low2high]
98
+ # if high_id && high_id >= 0 then
99
+ # return properties.merge(Hdecorator.get(high_id))
100
+ # else
101
+ # return properties.clone
102
+ # end
103
+ # end
104
+
105
+ # Saves properties +key+ of all the object associated with
106
+ # their id to +target+.
107
+ def self.dump(key, target = "")
108
+ # Build the table to dump
109
+ tbl = {}
110
+ self.each do |id,obj|
111
+ value = obj.properties[key]
112
+ if value.any? then
113
+ tbl[id] = value
114
+ end
115
+ end
116
+ # Dump the table.
117
+ target << YAML.dump(tbl)
118
+ return target
119
+ end
120
+
121
+ # Loads properties to +key+ for all objects from +source+.
122
+ def self.load(source,key)
123
+ # Load the id to property table.
124
+ tbl = YAML.load(source)
125
+ # Adds the property of each object according to tbl
126
+ tbl.each do |id,value|
127
+ @@id_map[id].properties[key] = value
128
+ end
129
+ end
130
+
131
+ # Some predefined properties to set.
132
+
133
+ def self.decorate_parent_id
134
+ @@id_map.each do |id, obj|
135
+ parent = obj.parent
136
+ if parent then
137
+ obj.properties[:parent_id] = obj.parent.hdr_id
138
+ else
139
+ obj.properties[:parent_id] = -1
140
+ end
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+
147
+ ## A HDLRuby set of properties
148
+ class Properties
149
+
150
+ # The set of all the property keys
151
+ @@property_keys = Set.new
152
+
153
+ # The HDLRuby object owning of the set of properties
154
+ attr_reader :owner
155
+
156
+ # Create a new set of properties and attach it to HDLRuby object
157
+ # +owner+.
158
+ def initialize(owner)
159
+ # Attach the owner.
160
+ @owner = owner
161
+ # Create the set.
162
+ @content = {}
163
+ end
164
+
165
+ # Clones the properties: also clone the contents.
166
+ def clone
167
+ result = Properties.new(owner)
168
+ @contents.each do |k,vals|
169
+ vals.each { |v| result[k] = v }
170
+ end
171
+ return result
172
+ end
173
+
174
+ # Create a new set of properties by merging with +prop+
175
+ def merge(prop)
176
+ result = self.clone
177
+ prop.each do |k,vals|
178
+ vals.each { |v| result[k] = v }
179
+ end
180
+ return result
181
+ end
182
+
183
+ # Tells if +key+ is present.
184
+ def key?(key)
185
+ @content.key?(key)
186
+ end
187
+
188
+ # Add a property
189
+ def []=(key,value)
190
+ @@property_keys << key
191
+ # Add an entry if not present.
192
+ @content[key] = [] unless @content.key?(key)
193
+ # Add the value to the entry.
194
+ @content[key] << value
195
+ end
196
+
197
+ # Get a property
198
+ def [](key)
199
+ return @content[key]
200
+ end
201
+
202
+ # Iterate over each value associated with +key+.
203
+ def each_with_key(key,&ruby_block)
204
+ return unless @content.key?(key)
205
+ @content[key].each(&ruby_block)
206
+ end
207
+
208
+ # Iterate over the properties of the current set.
209
+ #
210
+ # Returns an enumerator if no ruby block is given.
211
+ def each(&ruby_block)
212
+ # No ruby block? Return an enumerator.
213
+ return to_enum(:each) unless ruby_block
214
+ # A ruby block? Apply it on each input signal instance.
215
+ @content.each(&ruby_block)
216
+ end
217
+
218
+ # Iterator over all the property keys
219
+ #
220
+ # Returns an enumerator if no ruby block is given.
221
+ def self.each_key(&ruby_block)
222
+ # No ruby block? Return an enumerator.
223
+ return to_enum(:each_key) unless ruby_block
224
+ # A ruby block? Apply it on each input signal instance.
225
+ @@property_keys.each(&ruby_block)
226
+ end
227
+
228
+ # # Iterate over the property set of all the objects from current owner.
229
+ # #
230
+ # # Returns an enumerator if no ruby block is given.
231
+ # def each_properties(&ruby_block)
232
+ # # No ruby block? Return an enumerator.
233
+ # return to_enum(:each_properties) unless ruby_block
234
+ # # A ruby block? Apply it.
235
+ # # On current property set
236
+ # ruby_block.call(self)
237
+ # # And on the properties set of sub objects of the owner.
238
+ # self.owner.instance_variables.each do |var|
239
+ # obj = owner.instance_variable_get(var)
240
+ # if (obj.is_a?(Hproperties)) then
241
+ # # obj has properties, recurse on them.
242
+ # obj.properties.each_properties(&ruby_block)
243
+ # end
244
+ # end
245
+ # end
246
+
247
+ end
248
+
249
+
250
+ end