Class: Types::Typed::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/solidity/typed/metatypes/literals.rb,
lib/solidity/typed/metatypes/types.rb

Overview

todo - break-up literal_norm and move into types - why? why not?

Direct Known Subclasses

DataType, EnumType, ReferenceType, ValueType

Instance Method Summary collapse

Instance Method Details

#==(other) ⇒ Object

todo/check for minimal required methods required for

compare and equal support??


85
86
87
# File 'lib/solidity/typed/metatypes/types.rb', line 85

def ==(other)
  raise "no required == method defined for Type subclass #{self.class.name}; sorry"
end

#array?Boolean

Returns:

  • (Boolean)


79
# File 'lib/solidity/typed/metatypes/types.rb', line 79

def array?()    is_a?( ArrayType ); end

#check_and_normalize_literal(literal) ⇒ Object

Raises:

  • (TypeError)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/solidity/typed/metatypes/literals.rb', line 26

def check_and_normalize_literal( literal )
   ### todo/check - split up and move to type classes - why? why not?


## fix fix fix:  allow typed passed in as literals here?

##    if literal.is_a?(TypedVariable)

##     raise TypeError, "Only literals can be passed to check_and_normalize_literal: #{literal.inspect}"

##    end



  if is_a?(AddressType)
 ##  fix fix fix: add contract support     

 #     if literal.is_a?(ContractType::Proxy)

 #       return literal.address

 #     end

 
    unless literal.is_a?(::String) && literal.match?(/\A0x[a-f0-9]{40}\z/i)
      raise_type_error(literal)
    end
    
    ## note: always downcase & freeze address - why? why not?

    return literal == ADDRESS_ZERO ? literal : literal.downcase.freeze
  elsif is_a?( ContractType )  
    ## elsif is_contract_type?

    ##   uses in original. 

    ##     def is_contract_type?

    ##       ContractImplementation.valid_contract_types.include?(name)

    ##     end

  
    ## todo/check - use a different base class for contracts - why? why not?

    ##   fix fix fix: check matching contract type/class too - why? why not?

     if literal.is_a?( ContractBase )
       return literal
     else
       raise TypeError, "No literals allowed for contract types  got: #{literal}; sorry"
     end
 

  elsif is_a?(UIntType)
    if literal.is_a?(::String)
      literal = parse_integer(literal)
    end
      
    if literal.is_a?(::Integer) && literal.between?(0, 2 ** 256 - 1)
      return literal
    end
    
    raise_type_error(literal)
  elsif is_a?( IntType )
    if literal.is_a?(::String)
      literal = parse_integer(literal)
    end
      
    if literal.is_a?(::Integer) && literal.between?(-2 ** 255, 2 ** 255 - 1)
      return literal
    end
    
    raise_type_error(literal)
  elsif is_a?( EnumType )
     if literal.is_a?( ::Integer )  ## todo - check literal is withing min/max

        return literal
     end
     raise_type_error(literal)
  elsif is_a?( StringType )
    unless literal.is_a?( ::String)
      raise_type_error(literal)
    end
    
    return literal.freeze
  elsif is_a?( BoolType )
    ## fix-fix-fix- check if solidity support 0|1 for bools in function args???

    unless literal == true || literal == false
      raise_type_error(literal)
    end
    
    return literal
  elsif is_a?( InscriptionIdType ) || is_a?( Bytes32Type )
    unless literal.is_a?( ::String) && literal.match?(/\A0x[a-f0-9]{64}\z/i)
      raise_type_error(literal)
    end

    ## note: always downcase & freeze address - why? why not?

    ##   fix-fix-fix - check - use BYTES32_ZERO - why? why not?

    return literal == INSCRIPTION_ID_ZERO ? literal : literal.downcase.freeze

  elsif is_a?( BytesType )
    ## note:  assume empty string is bytes literal!!!

    if literal.is_a?( ::String) && literal.length == 0
      return literal
    end
    
    unless literal.is_a?( ::String) && 
            literal.match?(/\A0x[a-fA-F0-9]*\z/)  && 
            literal.size.even?
      raise_type_error( literal )
    end
    
    ##

    ##  check if dynamic? (like bytebuffer) - freeze? why? why not?

    return literal.downcase


  elsif is_a?( TimestampType ) || is_a?( TimedeltaType )
    dummy_uint = UIntType.instance
    
    begin
      return dummy_uint.check_and_normalize_literal(literal)
    rescue TypeError   ## TypeError => e

      raise_type_error(literal)
    end
  elsif is_a?( MappingType )
    if literal.is_a?( TypedMapping)   ## todo - check if possible (literal) typed mapping

      return literal    
    end
 
    unless literal.is_a?(Hash)
      raise_type_error(literal)
    end
    
    ## add types (wrap literal in types)

    ## todo - do a quick check - if hash populated with vars - why? why not?

    ## todo/fix: check for nested arrays/mappings!!!

    ##    do NOT wrap in SafeMapping/SafeArray

    data = literal.map do |key, value|
      [
        key_type.check_and_normalize_literal( key ),
        value_type.check_and_normalize_literal( value )
      ]
    end.to_h

    return data
  elsif is_a?( ArrayType )  
    
    ## todo/fix: check for matching sub_type!!!!

    ## check if possible to get TypedArray passed in as literal!!!

    if literal.is_a?(TypedArray)
      return literal    ## .data   ## note: return nested (inside) data e.g. array!!!

    end
    
    unless literal.is_a?(::Array)
      raise_type_error(literal)
    end
    
    ## check types only - wrap literal in types - why? why not?

    data = literal.map do |value|
      sub_type.check_and_normalize_literal( value )
    end

    return data    
  end


  raise TypeError, "invalid type; expected #{self.format}; got #{literal.inspect}"
end

#eql?(other) ⇒ Boolean

check eql? used for what?

Returns:

  • (Boolean)


98
# File 'lib/solidity/typed/metatypes/types.rb', line 98

def eql?(other)  hash == other.hash; end

#formatObject

change format to type or typesig/type_sig

or sig or signature or typespec   - why? why not?


51
52
53
54
55
# File 'lib/solidity/typed/metatypes/types.rb', line 51

def format    
    ## check/todo: what error to raise for not implemented / method not defined???

    ### note: raise (will use RuntimeError/Exception?)

    raise "no required format method defined for Type subclass #{self.class.name}; sorry"
end

#hashObject

note: format MUST be unique for types

        if self.format == other.format than same type
use for hash?  
 check default eql?  is self.object_id == other.object_id ???
  change to hash == other.hash; why? why not?


97
# File 'lib/solidity/typed/metatypes/types.rb', line 97

def hash()    [format].hash;  end

#mapping?Boolean

Returns:

  • (Boolean)


78
# File 'lib/solidity/typed/metatypes/types.rb', line 78

def mapping?()  is_a?( MappingType ); end

#mut?Boolean

is mutable (read/write)

Returns:

  • (Boolean)


68
69
70
# File 'lib/solidity/typed/metatypes/types.rb', line 68

def mut?  # is mutable (read/write)

  raise "no require mut(ability)? helper for Type subclass #{self.class.name}; sorry"
end

#parse_integer(literal) ⇒ Object



15
16
17
18
19
20
21
22
23
# File 'lib/solidity/typed/metatypes/literals.rb', line 15

def parse_integer(literal)
  base = literal.start_with?( '0x' ) ? 16 : 10
  
  begin
    Integer(literal, base)
  rescue ArgumentError 
    raise_type_error( literal )
  end
end

#pretty_print(printer) ⇒ Object

return type signature string - why? why not?

e.g.     string
         mapping(address=>uint256)
         string[]
    and so on...


61
# File 'lib/solidity/typed/metatypes/types.rb', line 61

def pretty_print( printer ) printer.text( "<type #{format}>" ); end

#raise_type_error(literal) ⇒ Object

Raises:

  • (TypeError)


9
10
11
12
# File 'lib/solidity/typed/metatypes/literals.rb', line 9

def raise_type_error(literal)
  ## change to typeerror or such - why? why not?

  raise TypeError, "expected type #{self.format}; got #{literal.inspect}"
end

#zeroObject

change to zero_literal (returns 0, [], {} - NOT typed version) - why? why not?



63
64
65
66
# File 'lib/solidity/typed/metatypes/types.rb', line 63

def zero   ## change to zero_literal (returns 0, [], {} - NOT typed version) - why? why not?

  #    ## check/todo: what error to raise for not implemented / method not defined???

  raise "no required zero method defined for Type subclass #{self.class.name}; sorry"
end