HDLRuby 2.4.27 → 2.6.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.
- checksums.yaml +4 -4
- data/lib/HDLRuby/drivers/xcd.rb +79 -0
- data/lib/HDLRuby/drivers/xcd/dummy.xcd +4 -0
- data/lib/HDLRuby/hdr_samples/adder.rb +1 -1
- data/lib/HDLRuby/hdr_samples/adder_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/adder_gen.rb +1 -1
- data/lib/HDLRuby/hdr_samples/constant_in_function.rb +27 -0
- data/lib/HDLRuby/hdr_samples/dff_properties.rb +19 -0
- data/lib/HDLRuby/hdr_samples/dff_unit.rb +54 -0
- data/lib/HDLRuby/hdr_samples/huge_rom.rb +25 -0
- data/lib/HDLRuby/hdr_samples/logic_bench.rb +21 -0
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/music.rb +79 -0
- data/lib/HDLRuby/hdr_samples/named_sub.rb +42 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +16 -0
- data/lib/HDLRuby/hdr_samples/seqpar_bench.rb +59 -0
- data/lib/HDLRuby/hdr_samples/with_function_generator.rb +25 -0
- data/lib/HDLRuby/hdrcc.rb +140 -24
- data/lib/HDLRuby/hruby_decorator.rb +250 -0
- data/lib/HDLRuby/hruby_high.rb +468 -91
- data/lib/HDLRuby/hruby_low.rb +913 -45
- data/lib/HDLRuby/hruby_low2c.rb +189 -168
- data/lib/HDLRuby/hruby_low2hdr.rb +738 -0
- data/lib/HDLRuby/hruby_low2high.rb +331 -549
- data/lib/HDLRuby/hruby_low2vhd.rb +39 -2
- data/lib/HDLRuby/hruby_low_bool2select.rb +29 -0
- data/lib/HDLRuby/hruby_low_casts_without_expression.rb +27 -0
- data/lib/HDLRuby/hruby_low_fix_types.rb +25 -0
- data/lib/HDLRuby/hruby_low_mutable.rb +70 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +28 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +6 -3
- data/lib/HDLRuby/hruby_low_without_namespace.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_parinseq.rb +151 -0
- data/lib/HDLRuby/hruby_low_without_select.rb +13 -0
- data/lib/HDLRuby/hruby_tools.rb +11 -1
- data/lib/HDLRuby/hruby_verilog.rb +1602 -1629
- data/lib/HDLRuby/sim/hruby_sim.h +25 -2
- data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +5 -1
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +22 -6
- data/lib/HDLRuby/std/fixpoint.rb +9 -0
- data/lib/HDLRuby/std/function_generator.rb +139 -0
- data/lib/HDLRuby/std/hruby_unit.rb +75 -0
- data/lib/HDLRuby/template_expander.rb +61 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +22 -5
@@ -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/
|
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'
|
@@ -20,6 +21,7 @@ require 'HDLRuby/hruby_low_with_var'
|
|
20
21
|
require 'HDLRuby/hruby_low_without_concat'
|
21
22
|
require 'HDLRuby/hruby_low_without_connection'
|
22
23
|
require 'HDLRuby/hruby_low_casts_without_expression'
|
24
|
+
require 'hruby_low_without_parinseq'
|
23
25
|
require 'HDLRuby/hruby_low_cleanup'
|
24
26
|
|
25
27
|
require 'HDLRuby/hruby_verilog.rb'
|
@@ -49,12 +51,21 @@ module HDLRuby
|
|
49
51
|
# The required files.
|
50
52
|
attr_reader :requires
|
51
53
|
|
52
|
-
# Creates a new loader for a +top_system+ system in file +
|
54
|
+
# Creates a new loader for a +top_system+ system in file +top_file_name+
|
53
55
|
# from directory +dir+ with generic parameters +params+.
|
56
|
+
#
|
57
|
+
# NOTE: +top_file+ can either be a file or a file name.
|
54
58
|
def initialize(top_system,top_file,dir,*params)
|
55
59
|
# Sets the top and the looking directory.
|
56
60
|
@top_system = top_system.to_s
|
57
|
-
@top_file
|
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
|
58
69
|
@dir = dir.to_s
|
59
70
|
@params = params
|
60
71
|
|
@@ -81,31 +92,48 @@ module HDLRuby
|
|
81
92
|
end
|
82
93
|
|
83
94
|
# Loads a single +file+.
|
95
|
+
#
|
96
|
+
# NOTE: +file+ can either be a file or a file name.
|
84
97
|
def read(file)
|
85
98
|
# Resolve the file.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
97
116
|
end
|
98
117
|
end
|
99
118
|
# Load the file.
|
100
|
-
# @texts << File.read(File.join(@dir,file) )
|
101
119
|
@texts << File.read(found)
|
102
|
-
|
103
|
-
|
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
|
104
125
|
return true
|
105
126
|
end
|
106
127
|
|
107
128
|
# Loads all the files from +file+.
|
108
|
-
def read_all(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
|
109
137
|
# puts "read_all with file=#{file}"
|
110
138
|
# Read the file
|
111
139
|
# read(file)
|
@@ -173,7 +201,7 @@ module HDLRuby
|
|
173
201
|
# Maybe it is a parse error, look for it.
|
174
202
|
bind = TOPLEVEL_BINDING.clone
|
175
203
|
eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
|
176
|
-
eval(@texts[0],bind,@
|
204
|
+
eval(@texts[0],bind,@top_file_name,1)
|
177
205
|
# No parse error found.
|
178
206
|
raise "Cannot find a top system." unless @top_system
|
179
207
|
end
|
@@ -182,7 +210,7 @@ module HDLRuby
|
|
182
210
|
bind = TOPLEVEL_BINDING.clone
|
183
211
|
eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
|
184
212
|
# Process it.
|
185
|
-
eval(@texts[0],bind,@
|
213
|
+
eval(@texts[0],bind,@top_file_name,1)
|
186
214
|
# Get the resulting instance
|
187
215
|
if @params.empty? then
|
188
216
|
# There is no generic parameter
|
@@ -309,14 +337,24 @@ $optparse = OptionParser.new do |opts|
|
|
309
337
|
opts.on("-D", "--debug","Set the HDLRuby debug mode") do |d|
|
310
338
|
$options[:debug] = d
|
311
339
|
end
|
340
|
+
opts.on("-T","--test t0,t1,t2","Compile the unit tests named t0,t1,...") do |t|
|
341
|
+
$options[:test] = t
|
342
|
+
end
|
343
|
+
opts.on("--testall","Compile all the available unit tests.") do |t|
|
344
|
+
$options[:testall] = t
|
345
|
+
end
|
312
346
|
opts.on("-t", "--top system", "Specify the top system to process") do|t|
|
313
347
|
$options[:top] = t
|
314
348
|
end
|
315
349
|
opts.on("-p", "--param x,y,z", "Specify the generic parameters") do |p|
|
316
350
|
$options[:param] = p
|
317
351
|
end
|
318
|
-
opts.on("--
|
319
|
-
|
352
|
+
opts.on("--dump","Dump all the properties to yaml files") do |v|
|
353
|
+
$options[:dump] = v
|
354
|
+
$options[:multiple] = v
|
355
|
+
end
|
356
|
+
opts.on("--version", "Shows the version of HDLRuby.") do |v|
|
357
|
+
puts VERSION
|
320
358
|
exit
|
321
359
|
end
|
322
360
|
# opts.on_tail("-h", "--help", "Show this message") do
|
@@ -369,6 +407,28 @@ if $input == nil then
|
|
369
407
|
exit
|
370
408
|
end
|
371
409
|
|
410
|
+
if ($options[:test] || $options[:testall]) then
|
411
|
+
$top = "__test__"
|
412
|
+
tests = $options[:test]
|
413
|
+
if tests then
|
414
|
+
tests = tests.to_s.split(",")
|
415
|
+
tests.map! {|test| ":\"#{test}\"" }
|
416
|
+
tests = ", #{tests.join(",")}"
|
417
|
+
else
|
418
|
+
tests = ""
|
419
|
+
end
|
420
|
+
# Generate the unit test file.
|
421
|
+
$test_file = Tempfile.new('tester.rb',Dir.getwd)
|
422
|
+
$test_file.write("require 'std/hruby_unit.rb'\nrequire_relative '#{$input}'\n\n" +
|
423
|
+
"HDLRuby::Unit.test(:\"#{$top}\"#{tests})\n")
|
424
|
+
# $test_file.rewind
|
425
|
+
# puts $test_file.read
|
426
|
+
# exit
|
427
|
+
$test_file.rewind
|
428
|
+
# It is the new input file.
|
429
|
+
$input = $test_file
|
430
|
+
end
|
431
|
+
|
372
432
|
# Open the output.
|
373
433
|
if $output then
|
374
434
|
if $options[:multiple] then
|
@@ -381,7 +441,7 @@ if $output then
|
|
381
441
|
$output = File.open($output,"w")
|
382
442
|
end
|
383
443
|
else
|
384
|
-
if $
|
444
|
+
if $options[:multiple] then
|
385
445
|
raise "Need a target directory in multiple files generation mode."
|
386
446
|
end
|
387
447
|
$output = $stdout
|
@@ -393,6 +453,12 @@ $loader = HDRLoad.new($top,$input,$options[:directory].to_s,*$params)
|
|
393
453
|
$loader.read_all
|
394
454
|
$loader.check_all
|
395
455
|
|
456
|
+
# Remove the test file if any, it is not needed any longer.
|
457
|
+
if $test_file then
|
458
|
+
$test_file.close
|
459
|
+
$test_file.unlink
|
460
|
+
end
|
461
|
+
|
396
462
|
if $options[:syntax] then
|
397
463
|
if $options[:multiple] then
|
398
464
|
raise "Multiple files generation mode not supported for syntax tree output."
|
@@ -413,6 +479,24 @@ end
|
|
413
479
|
# Get the top systemT.
|
414
480
|
$top_system = $top_instance.to_low.systemT
|
415
481
|
|
482
|
+
|
483
|
+
# Apply the pre drivers if any.
|
484
|
+
Hdecorator.each_with_property(:pre_driver) do |obj, value|
|
485
|
+
unless value.is_a?(Array) && value.size == 2 then
|
486
|
+
raise "pre_driver requires a driver file name command name."
|
487
|
+
end
|
488
|
+
# Load the driver.
|
489
|
+
require_relative(value[0].to_s)
|
490
|
+
# Ensure obj is the low version.
|
491
|
+
if obj.properties.key?(:high2low) then
|
492
|
+
# obj is high, get the corresponding low.
|
493
|
+
obj = obj.properties[:high2low][0]
|
494
|
+
end
|
495
|
+
# Execute it.
|
496
|
+
send(value[1].to_sym,obj,*value[2..-1])
|
497
|
+
end
|
498
|
+
|
499
|
+
|
416
500
|
# Gather the non-HDLRuby code.
|
417
501
|
$non_hdlruby = []
|
418
502
|
$top_system.each_systemT_deep do |systemT|
|
@@ -454,12 +538,15 @@ elsif $options[:hdr] then
|
|
454
538
|
# $output << systemT.to_high
|
455
539
|
# end
|
456
540
|
# $output << $top_instance.to_low.systemT.to_high
|
457
|
-
$output << $top_system.
|
541
|
+
$output << $top_system.to_hdr
|
458
542
|
elsif $options[:clang] then
|
459
543
|
# top_system = $top_instance.to_low.systemT
|
460
544
|
# top_system = $top_system
|
461
545
|
# Preprocess the HW description for valid C generation.
|
462
546
|
$top_system.each_systemT_deep do |systemT|
|
547
|
+
# Coverts the par blocks in seq blocks to seq blocks to match
|
548
|
+
# the simulation engine.
|
549
|
+
systemT.par_in_seq2seq!
|
463
550
|
# Converts the connections to behaviors.
|
464
551
|
systemT.connections_to_behaviors!
|
465
552
|
# Break the RefConcat.
|
@@ -583,6 +670,7 @@ elsif $options[:verilog] then
|
|
583
670
|
systemT.to_global_systemTs!
|
584
671
|
# systemT.break_types!
|
585
672
|
# systemT.expand_types!
|
673
|
+
systemT.par_in_seq2seq!
|
586
674
|
systemT.initial_concat_to_timed!
|
587
675
|
systemT.with_port!
|
588
676
|
end
|
@@ -673,3 +761,31 @@ elsif $options[:vhdl] then
|
|
673
761
|
end
|
674
762
|
end
|
675
763
|
end
|
764
|
+
|
765
|
+
# Apply the post drivers if any.
|
766
|
+
Hdecorator.each_with_property(:post_driver) do |obj, value|
|
767
|
+
# Load the driver.
|
768
|
+
require_relative(value[0].to_s)
|
769
|
+
# Execute it.
|
770
|
+
send(value[1].to_sym,obj,$output)
|
771
|
+
end
|
772
|
+
|
773
|
+
# Dump the properties
|
774
|
+
if $options[:dump] then
|
775
|
+
# Decorate with the parent ids.
|
776
|
+
Hdecorator.decorate_parent_id
|
777
|
+
|
778
|
+
# Generate the directory for the properties
|
779
|
+
property_dir = $output + "/properties"
|
780
|
+
unless File.directory?(property_dir)
|
781
|
+
FileUtils.mkdir_p(property_dir)
|
782
|
+
end
|
783
|
+
|
784
|
+
# Dump to one file per key
|
785
|
+
Properties.each_key do |key|
|
786
|
+
File.open(property_dir + "/#{key}.yaml", "w") do |f|
|
787
|
+
Hdecorator.dump(key,f)
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
791
|
+
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
|