solidity-typed 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +4 -0
- data/Manifest.txt +24 -0
- data/README.md +318 -0
- data/Rakefile +27 -0
- data/lib/solidity/typed/array.rb +166 -0
- data/lib/solidity/typed/array_builder.rb +53 -0
- data/lib/solidity/typed/bool.rb +47 -0
- data/lib/solidity/typed/conversion.rb +52 -0
- data/lib/solidity/typed/enum.rb +116 -0
- data/lib/solidity/typed/enum_builder.rb +101 -0
- data/lib/solidity/typed/mapping.rb +108 -0
- data/lib/solidity/typed/mapping_builder.rb +54 -0
- data/lib/solidity/typed/metatypes/array.rb +56 -0
- data/lib/solidity/typed/metatypes/bool.rb +39 -0
- data/lib/solidity/typed/metatypes/literals.rb +186 -0
- data/lib/solidity/typed/metatypes/mapping.rb +46 -0
- data/lib/solidity/typed/metatypes/types.rb +492 -0
- data/lib/solidity/typed/numbers.rb +108 -0
- data/lib/solidity/typed/struct.rb +73 -0
- data/lib/solidity/typed/struct_builder.rb +145 -0
- data/lib/solidity/typed/typed.rb +114 -0
- data/lib/solidity/typed/values.rb +113 -0
- data/lib/solidity/typed/version.rb +23 -0
- data/lib/solidity/typed.rb +128 -0
- metadata +111 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
###
|
2
|
+
# add global type conversion functions here
|
3
|
+
#
|
4
|
+
# include via Kernel module - why? why not?
|
5
|
+
|
6
|
+
|
7
|
+
module ConversionFunctions
|
8
|
+
#####
|
9
|
+
# todo/check: use AddressType.try_convert( literal_or_obj ) or such - why? why not?
|
10
|
+
def address( literal=0 )
|
11
|
+
## hack for now support address(0)
|
12
|
+
## todo/fix: address( '0x0' ) too!!!!
|
13
|
+
return Types::Typed::AddressType.instance.zero if literal.is_a?(::Integer) && literal == 0
|
14
|
+
|
15
|
+
Types::Typed::AddressType.instance.check_and_normalize_literal( literal )
|
16
|
+
end # methdod address
|
17
|
+
|
18
|
+
|
19
|
+
=begin
|
20
|
+
def uint( obj=0 )
|
21
|
+
## check if typed?
|
22
|
+
## raise exception on error
|
23
|
+
end
|
24
|
+
=end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
=begin
|
29
|
+
def string(i)
|
30
|
+
if i.is_a?(TypedVariable) && i.type.is_value_type?
|
31
|
+
return TypedVariable.create(:string, i.value.to_s)
|
32
|
+
else
|
33
|
+
raise "Input must be typed"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def address(i)
|
38
|
+
return TypedVariable.create(:address) if i == 0
|
39
|
+
|
40
|
+
if i.is_a?(TypedVariable) && i.type == Type.create(:addressOrDumbContract)
|
41
|
+
return TypedVariable.create(:address, i.value)
|
42
|
+
end
|
43
|
+
|
44
|
+
raise "Not implemented"
|
45
|
+
end
|
46
|
+
=end
|
47
|
+
|
48
|
+
end # module ConversionFunctions
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
Kernel.include( ConversionFunctions )
|
@@ -0,0 +1,116 @@
|
|
1
|
+
###############################
|
2
|
+
## base class for enum
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# notes on enum:
|
6
|
+
# do NOT ever create new typed enums with new/create!!!!
|
7
|
+
# only create zeros with new_zero!!!!!
|
8
|
+
# otherwise always reuse and assign CONSTANTS!!!!
|
9
|
+
##
|
10
|
+
## todo - fix-fix-fix - enforce rules in code here - why? why not?
|
11
|
+
## make new private or such - why? why not?
|
12
|
+
## check TrueClass|FalseClass as example - why? why not?
|
13
|
+
|
14
|
+
## for bool and enum
|
15
|
+
## use TypedData - only allow assignment of existing instances
|
16
|
+
## no NEW possible!!!
|
17
|
+
## thus - deserialize has a switch for TypedData!!
|
18
|
+
|
19
|
+
module Types
|
20
|
+
class Enum < Typed
|
21
|
+
|
22
|
+
def self.zero() members[0]; end
|
23
|
+
def zero?() self == self.class.zero; end ## note: use compare by identity (object_id) and NOT value e.g. 0
|
24
|
+
|
25
|
+
|
26
|
+
## return a new Enum read-only class
|
27
|
+
attr_reader :key
|
28
|
+
attr_reader :value
|
29
|
+
|
30
|
+
|
31
|
+
def initialize( key, value )
|
32
|
+
@key = key
|
33
|
+
@value = value
|
34
|
+
self.freeze ## make "immutable"
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def self._typecheck_enum!( o )
|
39
|
+
if o.instance_of?( self )
|
40
|
+
o
|
41
|
+
else
|
42
|
+
raise TypeError.new( "[enum] enum >#{name}< type expected; got >#{o.class.inspect}<" )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
def _typecheck_enum!( o ) self.class._typecheck_enum!( o ); end
|
46
|
+
|
47
|
+
|
48
|
+
def ==( other )
|
49
|
+
if other.is_a?( Integer ) && other == 0 ## note: only allow compare by zero (0) integer - why? why not?
|
50
|
+
@value == 0
|
51
|
+
else
|
52
|
+
@value == _typecheck_enum!( other ).value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
## keep eql? compare by object_id(entity) - why? why not?
|
56
|
+
### alias_method :eql?, :==
|
57
|
+
|
58
|
+
|
59
|
+
def self.keys
|
60
|
+
@keys ||= members.map {|member| member.key}.freeze
|
61
|
+
@keys
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.key( key )
|
65
|
+
## note: returns nil now for unknown keys
|
66
|
+
## use/raise IndexError or something - why? why not?
|
67
|
+
@hash_by_key ||= Hash[ keys.zip( members ) ].freeze
|
68
|
+
@hash_by_key[key]
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
alias_method :[], :key ## convenience alias for key
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.values
|
76
|
+
@values ||= members.map {|member| member.value}.freeze
|
77
|
+
@values
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.value( value )
|
81
|
+
## note: returns nil now for unknown values
|
82
|
+
## use/raise IndexError or something - why? why not?
|
83
|
+
@hash_by_value ||= Hash[ values.zip( members ) ].freeze
|
84
|
+
@hash_by_value[value]
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.min() members[0]; end
|
88
|
+
def self.max() members[-1]; end
|
89
|
+
|
90
|
+
def self.size() keys.size; end
|
91
|
+
class << self
|
92
|
+
alias_method :length, :size ## alias (as is the ruby tradition)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.convert( arg )
|
96
|
+
## todo/check: support keys too - why? why not?
|
97
|
+
## e.g. Color(0), Color(1)
|
98
|
+
## Color(:red), Color(:blue) - why? why not?
|
99
|
+
## note: will ALWAYS look-up by (member) index and NOT by value (integer number value might be different!!)
|
100
|
+
members[ arg ]
|
101
|
+
end
|
102
|
+
|
103
|
+
## add to_i, to_int - why? why not?
|
104
|
+
def to_i() @value; end
|
105
|
+
def to_int() @value; end ## allows Integer( .. )
|
106
|
+
|
107
|
+
## add to_b/to_bool support (see safebool @ https://github.com/s6ruby/safebool) - why? why not?
|
108
|
+
# def parse_bool() @value != 0; end ## nonzero == true, zero == false like numbers
|
109
|
+
|
110
|
+
def as_data() @value; end
|
111
|
+
|
112
|
+
def pretty_print( printer )
|
113
|
+
printer.text( "<val #{type}:#{@key}(#{@value})>" );
|
114
|
+
end
|
115
|
+
end # class Enum
|
116
|
+
end # module Types
|
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
module Types
|
3
|
+
class Enum
|
4
|
+
|
5
|
+
###################
|
6
|
+
## meta-programming "macro" - build class (on the fly)
|
7
|
+
#
|
8
|
+
# todo/fix: scope: keep empty by default
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
def self.build_class( class_name, *args, scope: Types )
|
13
|
+
if args.size > 0
|
14
|
+
## e.g. :Color, :red, :green, :blue
|
15
|
+
## or
|
16
|
+
## :Color, [:red, :green, :blue]
|
17
|
+
## note: start counting a zero (0) !!!
|
18
|
+
keys = args
|
19
|
+
values = (0...keys.size).to_a # note: use ... (exclusive) range
|
20
|
+
e = Hash[ keys.zip( values ) ]
|
21
|
+
else
|
22
|
+
raise ArgumentError, "[enum] no members declared - min. one member required; got #{args}; sorry"
|
23
|
+
end
|
24
|
+
|
25
|
+
## todo/fix:
|
26
|
+
## check class name MUST start with uppercase letter
|
27
|
+
|
28
|
+
## check if all keys are symbols and follow the ruby id(entifier) naming rules
|
29
|
+
## todo/check - allow uppercase fist A-Z letters - why? why not?
|
30
|
+
e.keys.each do |key|
|
31
|
+
if key.is_a?( Symbol ) && key =~ /\A[a-z][a-zA-Z0-9_]*\z/
|
32
|
+
else
|
33
|
+
raise ArgumentError.new( "[enum] members to enum must be all symbols following the ruby/solidity id naming rules; >#{key}< failed" )
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
klass = Class.new( Enum )
|
38
|
+
|
39
|
+
|
40
|
+
## add self.new too - note: call/forward to "old" orginal self.new of Event (base) class
|
41
|
+
klass.define_singleton_method( :new ) do |*new_args|
|
42
|
+
raise ArgumentError, "enum #{klass.name} - do NOT call new EVER; reuse existing enum members! sorry"
|
43
|
+
end
|
44
|
+
## make new - private too - why? why not?
|
45
|
+
|
46
|
+
|
47
|
+
e.each do |key,value|
|
48
|
+
klass.class_eval( <<RUBY )
|
49
|
+
#{key.upcase} = old_new( :#{key}, #{value} )
|
50
|
+
|
51
|
+
def #{key}?
|
52
|
+
self == #{key.upcase}
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.#{key}
|
56
|
+
#{key.upcase}
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
end
|
60
|
+
|
61
|
+
klass.class_eval( <<RUBY )
|
62
|
+
def self.members
|
63
|
+
@members ||= [#{e.keys.map {|key|key.upcase}.join(',')}].freeze
|
64
|
+
end
|
65
|
+
RUBY
|
66
|
+
|
67
|
+
|
68
|
+
type = EnumType.new( class_name, klass )
|
69
|
+
klass.define_singleton_method( :type ) do
|
70
|
+
@type ||= type
|
71
|
+
end
|
72
|
+
|
73
|
+
=begin
|
74
|
+
## note: use Kernel for "namespacing"
|
75
|
+
## make all enums Kernel convenience converters (always) global
|
76
|
+
## including uppercase methods (e.g. State(), Color(), etc.) does NOT work otherwise (with other module includes)
|
77
|
+
|
78
|
+
## add global convenience converter function
|
79
|
+
## e.g. State(0) is same as State.convert(0)
|
80
|
+
## Color(0) is same as Color.convert(0)
|
81
|
+
Kernel.class_eval( <<RUBY )
|
82
|
+
def #{class_name}( arg )
|
83
|
+
#{class_name}.convert( arg )
|
84
|
+
end
|
85
|
+
RUBY
|
86
|
+
=end
|
87
|
+
## note: use scoped(class) and NO Object for namespacing
|
88
|
+
scope.const_set( class_name, klass ) ## returns klass (plus sets global constant class name)
|
89
|
+
klass
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
class << self
|
94
|
+
alias_method :old_new, :new # note: store "old" orginal version of new
|
95
|
+
alias_method :new, :build_class # replace original version with create
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
end # class Enum
|
101
|
+
end # module Types
|
@@ -0,0 +1,108 @@
|
|
1
|
+
|
2
|
+
module Types
|
3
|
+
class Mapping < TypedReference
|
4
|
+
|
5
|
+
def self.zero() @zero ||= new; end
|
6
|
+
def zero?() @data.empty? end
|
7
|
+
|
8
|
+
## add short-cut helpers why? why not?
|
9
|
+
def key_type() self.class.type.key_type; end
|
10
|
+
def value_type() self.class.type.value_type; end
|
11
|
+
|
12
|
+
## todo/check: make "internal" data/hash available? why? why not?
|
13
|
+
## attr_reader :data
|
14
|
+
|
15
|
+
def initialize( initial_value = {} )
|
16
|
+
## was: initial_value ||= {}
|
17
|
+
## check if nil gets passed in - default not used?
|
18
|
+
|
19
|
+
raise ArgumentError, "expected literal of type #{type}; got typed #{initial_value.pretty_print_inspect}" if initial_value.is_a?( Typed )
|
20
|
+
|
21
|
+
@data = type.check_and_normalize_literal( initial_value ).map do |key, value|
|
22
|
+
[
|
23
|
+
type.key_type.new( key ),
|
24
|
+
type.value_type.new( value )
|
25
|
+
]
|
26
|
+
end.to_h
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
extend Forwardable ## pulls in def_delegator
|
31
|
+
## add more Hash forwards here!!!!
|
32
|
+
def_delegators :@data, :size, :empty?, :clear
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
def [](key)
|
37
|
+
puts "[debug] Mapping#[]( #{key} )"
|
38
|
+
key_var = key.is_a?( Typed ) ? key : key_type.new( key )
|
39
|
+
obj = @data[key_var]
|
40
|
+
|
41
|
+
## was:
|
42
|
+
## if value_type.mapping? && obj.nil?
|
43
|
+
## obj =
|
44
|
+
## @data[key_var] = obj
|
45
|
+
## end
|
46
|
+
##
|
47
|
+
## note:
|
48
|
+
## change to
|
49
|
+
## allow access to ref to struct and than update change to assign !!=!!!!!!
|
50
|
+
|
51
|
+
if obj.nil?
|
52
|
+
obj = value_type.new_zero
|
53
|
+
@data[ key_var ] = obj
|
54
|
+
end
|
55
|
+
|
56
|
+
obj
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
def []=(key, new_value)
|
62
|
+
puts "[debug] Mapping#[]=( #{key}:#{key.class.name}, #{new_value}:#{new_value.class.name})"
|
63
|
+
pp type.key_type
|
64
|
+
key_var = key.is_a?( Typed ) ? key : key_type.new( key )
|
65
|
+
pp key_var
|
66
|
+
obj = new_value.is_a?( Typed ) ? new_value : value_type.new( new_value )
|
67
|
+
pp obj
|
68
|
+
|
69
|
+
if value_type.mapping?
|
70
|
+
## val_var = Proxy.new(keytype: valuetype.keytype, valuetype: valuetype.valuetype)
|
71
|
+
raise 'What?'
|
72
|
+
end
|
73
|
+
|
74
|
+
@data[key_var] = obj
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def key?( key )
|
79
|
+
key_var = key.is_a?( Typed ) ? key : key_type.new( key )
|
80
|
+
@data.key?( key_var )
|
81
|
+
end
|
82
|
+
alias_method :has_key?, :key?
|
83
|
+
|
84
|
+
def delete( key )
|
85
|
+
key_var = key.is_a?( Typed ) ? key : key_type.new( key )
|
86
|
+
@data.delete( key_var )
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
## note: pass through value!!!!
|
91
|
+
## in new scheme - only "plain" ruby arrays/hash/string/integer/bool used!!!!
|
92
|
+
## no wrappers!!! - no need to convert!!!
|
93
|
+
def as_data
|
94
|
+
puts "[debug] Mapping#as_data"
|
95
|
+
@data.reduce({}) do |h, (k, v)|
|
96
|
+
## todo/fix:
|
97
|
+
## check if value is zero/ do not serialize zero - why? why not?
|
98
|
+
h[k.as_data] = v.as_data
|
99
|
+
h
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def pretty_print( printer )
|
104
|
+
printer.text( "<ref #{type}:#{@data.pretty_print_inspect}>" );
|
105
|
+
end
|
106
|
+
end # class Mapping
|
107
|
+
end # module Types
|
108
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Types
|
3
|
+
|
4
|
+
class Mapping
|
5
|
+
|
6
|
+
def self.build_class( key_type, value_type )
|
7
|
+
|
8
|
+
# key_type = Type.create( key_type ) if key_type.is_a?( Symbol ) ||
|
9
|
+
# key_type.is_a?( String )
|
10
|
+
# value_type = Type.create( value_type ) if value_type.is_a?( Symbol ) ||
|
11
|
+
# value_type.is_a?( String )
|
12
|
+
# key_type = key_type.type if key_type.is_a?( Class ) && key_type.ancestors.include?( Typed )
|
13
|
+
# value_type = value_type.type if value_type.is_a?( Class ) && value_type.ancestors.include?( Typed )
|
14
|
+
|
15
|
+
key_type = typeof( key_type )
|
16
|
+
value_type = typeof( value_type )
|
17
|
+
|
18
|
+
type = MappingType.instance( key_type, value_type )
|
19
|
+
|
20
|
+
class_name = type.typedclass_name
|
21
|
+
|
22
|
+
## note: keep a class cache
|
23
|
+
## note: klasses may have different init sizes (default 0)
|
24
|
+
cache = @@cache ||= {}
|
25
|
+
klass = cache[ class_name ]
|
26
|
+
## fix-fix-fix - check if const klass defined for cache (no cache needed)!!!!!!!!
|
27
|
+
|
28
|
+
if klass.nil?
|
29
|
+
klass = Class.new( Mapping )
|
30
|
+
klass.define_singleton_method( :type ) do
|
31
|
+
@type ||= type
|
32
|
+
end
|
33
|
+
|
34
|
+
## add self.new too - note: call/forward to "old" orginal self.new of Event (base) class
|
35
|
+
klass.define_singleton_method( :new ) do |*args|
|
36
|
+
old_new( *args )
|
37
|
+
end
|
38
|
+
|
39
|
+
## add to cache for later (re)use
|
40
|
+
cache[ class_name ] = klass
|
41
|
+
Types.const_set( class_name, klass )
|
42
|
+
end
|
43
|
+
|
44
|
+
klass
|
45
|
+
end # method self.build_class
|
46
|
+
|
47
|
+
class << self
|
48
|
+
alias_method :old_new, :new # note: store "old" orginal version of new
|
49
|
+
alias_method :new, :build_class # replace original version with create
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end # class Mapping
|
54
|
+
end # module Types
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Types
|
2
|
+
class Typed ## note: use class Typed as namespace (all metatype etc. nested here - the beginning)
|
3
|
+
|
4
|
+
|
5
|
+
class ArrayType < ReferenceType ## note: dynamic array for now (NOT fixed!!!! - add FixedArray - why? why not?)
|
6
|
+
def self.instance( sub_type, size=0 )
|
7
|
+
raise ArgumentError, "[ArrayType.instance] sub_type not a type - got #{sub_type}; sorry" unless sub_type.is_a?( Type )
|
8
|
+
@instances ||= {}
|
9
|
+
key = '' ## note: String.new('') will pick-up TypedString!!; thus, use literal for now
|
10
|
+
key += sub_type.format
|
11
|
+
key += "×#{size}" if size != 0
|
12
|
+
@instances[ key ] ||= new( sub_type, size )
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
attr_reader :sub_type
|
17
|
+
attr_reader :size ## rename size to dim(ension) or such - why? why not?
|
18
|
+
def initialize( sub_type, size=0 )
|
19
|
+
@sub_type = sub_type
|
20
|
+
@size = size
|
21
|
+
end
|
22
|
+
def format
|
23
|
+
if @size == 0 ## assume dynamic
|
24
|
+
"#{@sub_type.format}[]"
|
25
|
+
else
|
26
|
+
"#{@sub_type.format}[#{@size}]"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method :to_s, :format
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
other.is_a?( ArrayType ) &&
|
33
|
+
@sub_type == other.sub_type &&
|
34
|
+
@size == other.size ### add check for size too - why? why not?
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def typedclass_name
|
39
|
+
## return/use symbol (not string here) - why? why not?
|
40
|
+
## or use TypedArrayOf<sub-type.typedclass_name> - why? why not?
|
41
|
+
sub_name = _sanitize_class_name( @sub_type.typedclass_name )
|
42
|
+
name = '' ## note: String.new('') will pick-up TypedString!!; thus, use literal for now
|
43
|
+
name += "Array‹#{sub_name}›"
|
44
|
+
name += "×#{size}" if @size != 0
|
45
|
+
name
|
46
|
+
end
|
47
|
+
def typedclass() Types.const_get( typedclass_name ); end
|
48
|
+
|
49
|
+
def mut?() true; end
|
50
|
+
def new_zero() typedclass.new; end
|
51
|
+
def new( initial_value ) typedclass.new( initial_value ); end
|
52
|
+
end # class ArrayType
|
53
|
+
|
54
|
+
|
55
|
+
end # class Typed ## note: use class Typed as namespace (all metatype etc. nested here - the beginning)
|
56
|
+
end # module Types
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Types
|
2
|
+
class Typed ## note: use class Typed as namespace (all metatype etc. nested here - the beginning)
|
3
|
+
|
4
|
+
|
5
|
+
class BoolType < DataType
|
6
|
+
def self.instance() @instance ||= new; end
|
7
|
+
|
8
|
+
def format() 'bool'; end
|
9
|
+
alias_method :to_s, :format
|
10
|
+
|
11
|
+
def ==(other) other.is_a?( BoolType ); end
|
12
|
+
|
13
|
+
## note: class is really a module for bool - hack!!!
|
14
|
+
## remove class from methods (typedclass_name|typedclass) - why? why not?
|
15
|
+
## change typedclass_name to typed_name !!!
|
16
|
+
## and typedclass to typed !!! - why? why not??
|
17
|
+
def typedclass_name() Bool.name; end
|
18
|
+
def typedclass() Bool; end
|
19
|
+
|
20
|
+
def mut?() false; end
|
21
|
+
def zero() Bool.zero; end ## note: Bool.zero is false
|
22
|
+
alias_method :new_zero, :zero ## add/keep (convenience) alias for new_zero - why? why not?
|
23
|
+
def new( initial_value ) ## check - add default zero value - why? why not?
|
24
|
+
## allow integer 0|1 here too - why? why not?
|
25
|
+
## fix-fix-fix check solidity functions with bool (if they use 0|1 or true|false)!!!
|
26
|
+
if initial_value == true # instance_of( TrueClass )
|
27
|
+
true
|
28
|
+
elsif initial_value == false # instance_of?( FalseClass )
|
29
|
+
false
|
30
|
+
else
|
31
|
+
## use value error?
|
32
|
+
raise ArgumentError, "BoolType.new - true or false arg expected; got: #{initial_value}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end # class BoolType
|
36
|
+
|
37
|
+
end # class Typed ## note: use class Typed as namespace (all metatype etc. nested here - the beginning)
|
38
|
+
end # module Types
|
39
|
+
|