0xfacet-typed 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a0ed00364240e4bb50034acabd0cec233cd24cae34ccda46f7e245a52d43b666
4
+ data.tar.gz: 359636ba089c58bf1fdd97d45b425dec14d63ee30f58815d9a268cfba5a3fa8e
5
+ SHA512:
6
+ metadata.gz: 2bb991ecfa5a60979e4998e13613dc9400df98d09ee892d5e6747107d3675944b9178c072b1c3ae39d54d3ce1e7f7b06f523312c24d35e5efe1e8c7b04649c58
7
+ data.tar.gz: 70c0e53db248bb2f12353059bf1d42adc468d7d2d7bb27b8f25b17df30d7143df6be72ce621df153506e388b3d888dfe89fe77b8e224f4cb7e00b783a27dafac
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2023-11-16
2
+
3
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,12 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/0xfacet/typed.rb
6
+ lib/0xfacet/typed/array_type.rb
7
+ lib/0xfacet/typed/attr_public_read_private_write.rb
8
+ lib/0xfacet/typed/contract_errors.rb
9
+ lib/0xfacet/typed/contract_type.rb
10
+ lib/0xfacet/typed/mapping_type.rb
11
+ lib/0xfacet/typed/type.rb
12
+ lib/0xfacet/typed/typed_variable.rb
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # 0xFacet Typed
2
+
3
+ 0xfacet-typed - solidity-like value and reference types for rubidity o.g.
4
+
5
+
6
+ * home :: [github.com/s6ruby/rubidity.review](https://github.com/s6ruby/rubidity.review)
7
+ * bugs :: [github.com/s6ruby/rubidity.review/issues](https://github.com/s6ruby/rubidity/issues)
8
+ * gem :: [rubygems.org/gems/0xfacet-typed](https://rubygems.org/gems/0xfacet-typed)
9
+ * rdoc :: [rubydoc.info/gems/0xfacet-typed](http://rubydoc.info/gems/0xfacet-typed)
10
+
11
+
12
+
13
+ ## About
14
+
15
+ What's happening herè?
16
+
17
+ The idea is to look at the facet vm code as-is (that is, NOT suggesting new or alternate syntax and semantics) in the review / commentary
18
+ and start to (re)package / modular-ize
19
+ code in "place holder" gems (waiting for adoption by the founders) such as 0xfacet and 0xfacet-typed and 0xfacet-rubidity.
20
+
21
+ See [Rubidity O.G. (Dumb Contracts) Public Code Review / (More) Tests / Gems & More »](https://github.com/s6ruby/rubidity.review)
22
+
23
+
24
+
25
+
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'hoe'
2
+
3
+ # require './lib/0xfacet/typed/version.rb'
4
+
5
+
6
+ Hoe.spec '0xfacet-typed' do
7
+
8
+ self.version = '0.0.1'
9
+
10
+ self.summary = '0xfacet-typed - solidity-like value and reference types for rubidity o.g.'
11
+ self.description = summary
12
+
13
+ self.urls = { home: 'https://github.com/s6ruby/rubidity.review' }
14
+
15
+ self.author = 'Gerald Bauer'
16
+ self.email = 'gerald.bauer@gmail.com'
17
+
18
+ # switch extension to .markdown for gihub formatting
19
+ self.readme_file = 'README.md'
20
+ self.history_file = 'CHANGELOG.md'
21
+
22
+ self.extra_deps = [
23
+ ]
24
+
25
+
26
+ self.licenses = ['Public Domain']
27
+
28
+ self.spec_extras = {
29
+ required_ruby_version: '>= 2.3'
30
+ }
31
+ end
@@ -0,0 +1,89 @@
1
+ class ArrayType < TypedVariable
2
+ def initialize(...)
3
+ super(...)
4
+ value.on_change = on_change
5
+ end
6
+
7
+ def serialize
8
+ value.data.map(&:serialize)
9
+ end
10
+
11
+ class Proxy
12
+ extend AttrPublicReadPrivateWrite
13
+
14
+ attr_accessor :on_change
15
+ attr_public_read_private_write :value_type, :data
16
+
17
+ def ==(other)
18
+ return false unless other.is_a?(self.class)
19
+
20
+ other.value_type == value_type &&
21
+ other.data == data
22
+ end
23
+
24
+ def initialize(
25
+ initial_value = [],
26
+ value_type:,
27
+ initial_length: nil,
28
+ on_change: nil
29
+ )
30
+ unless value_type.is_value_type?
31
+ raise VariableTypeError.new("Only value types can me array elements")
32
+ end
33
+
34
+ self.value_type = value_type
35
+ self.data = initial_value
36
+
37
+ if initial_length
38
+ amount_to_pad = initial_length - data.size
39
+
40
+ amount_to_pad.times do
41
+ data << TypedVariable.create(value_type)
42
+ end
43
+ end
44
+
45
+ self.on_change = on_change
46
+ end
47
+
48
+ def [](index)
49
+ index_var = TypedVariable.create_or_validate(:uint256, index, on_change: on_change)
50
+
51
+ raise "Index out of bounds" if index_var >= data.size
52
+
53
+ value = data[index_var]
54
+ value || TypedVariable.create_or_validate(value_type, on_change: on_change)
55
+ end
56
+
57
+ def []=(index, value)
58
+ index_var = TypedVariable.create_or_validate(:uint256, index, on_change: on_change)
59
+
60
+ raise "Sparse arrays are not supported" if index_var > data.size
61
+
62
+ old_value = self.data[index_var]
63
+ val_var = TypedVariable.create_or_validate(value_type, value, on_change: on_change)
64
+
65
+ if old_value != val_var
66
+ on_change&.call
67
+ self.data[index_var] ||= val_var
68
+ self.data[index_var].value = val_var.value
69
+ end
70
+ end
71
+
72
+ def push(value)
73
+ next_index = data.size
74
+
75
+ self.[]=(next_index, value)
76
+ nil
77
+ end
78
+
79
+ def pop
80
+ on_change&.call
81
+
82
+ data.pop
83
+ end
84
+
85
+ def length
86
+ data.length
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,9 @@
1
+ module AttrPublicReadPrivateWrite
2
+ def attr_public_read_private_write(*names)
3
+ attr_accessor(*names)
4
+
5
+ names.each do |name|
6
+ private "#{name}="
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module ContractErrors
2
+ class ContractError < StandardError
3
+ attr_accessor :contract
4
+ attr_accessor :error_status
5
+
6
+ def initialize(message, contract = nil)
7
+ super(message)
8
+ @contract = contract
9
+ end
10
+
11
+ def message
12
+ return super if contract.blank?
13
+
14
+ trace = !Rails.env.production? ? backtrace.join("\n") : ''
15
+
16
+ "#{contract.class.name} error: " + super
17
+ end
18
+ end
19
+
20
+ class StaticCallError < StandardError; end
21
+ class TransactionError < StandardError; end
22
+ class ContractRuntimeError < ContractError; end
23
+ class ContractDefinitionError < ContractError; end
24
+ class StateVariableTypeError < StandardError; end
25
+ class VariableTypeError < StandardError; end
26
+ class StateVariableMutabilityError < StandardError; end
27
+ class ContractArgumentError < StandardError; end
28
+ class CallingNonExistentContractError < TransactionError; end
29
+ class InvalidOverrideError < StandardError; end
30
+ class FunctionAlreadyDefinedError < StandardError; end
31
+ class InvalidEthscriptionError < StandardError; end
32
+ class InvalidDestructuringError < StandardError; end
33
+ class InvalidStateVariableChange < StandardError; end
34
+ end
@@ -0,0 +1,64 @@
1
+ class ContractType < TypedVariable
2
+ def initialize(...)
3
+ super(...)
4
+ end
5
+
6
+ def serialize
7
+ value.address
8
+ end
9
+
10
+ def method_missing(name, *args, **kwargs, &block)
11
+ value.send(name, *args, **kwargs, &block)
12
+ end
13
+
14
+ def respond_to_missing?(name, include_private = false)
15
+ value.respond_to?(name, include_private) || super
16
+ end
17
+
18
+ class Proxy
19
+ include ContractErrors
20
+ extend AttrPublicReadPrivateWrite
21
+
22
+ attr_public_read_private_write :contract_type, :address,
23
+ :uncast_address, :contract_interface
24
+
25
+ def ==(other)
26
+ return false unless other.is_a?(self.class)
27
+
28
+ other.contract_type == contract_type &&
29
+ other.address == address
30
+ end
31
+
32
+ def initialize(contract_type:, address:, contract_interface:)
33
+ self.uncast_address = address
34
+ address = TypedVariable.create_or_validate(:address, address).value
35
+
36
+ self.contract_type = contract_type
37
+ self.address = address
38
+ self.contract_interface = contract_interface
39
+ end
40
+
41
+ def method_missing(name, *args, **kwargs, &block)
42
+ computed_args = args.presence || kwargs
43
+
44
+ super unless contract_interface
45
+
46
+ known_function = contract_interface.public_abi[name]
47
+
48
+ unless known_function && known_function.args.length == computed_args.length
49
+ raise ContractError.new("Contract doesn't implement interface: #{contract_type}, #{name}")
50
+ end
51
+
52
+ TransactionContext.call_stack.execute_in_new_frame(
53
+ to_contract_address: address,
54
+ function: name,
55
+ args: computed_args,
56
+ type: :call
57
+ )
58
+ end
59
+
60
+ def respond_to_missing?(name, include_private = false)
61
+ !!contract_interface.public_abi[name] || super
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,102 @@
1
+ class MappingType < TypedVariable
2
+ def initialize(...)
3
+ super(...)
4
+ value.on_change = on_change
5
+ end
6
+
7
+ def serialize
8
+ value.serialize
9
+ end
10
+
11
+ class Proxy
12
+ extend AttrPublicReadPrivateWrite
13
+
14
+ attr_accessor :on_change
15
+ attr_public_read_private_write :transformed_keys, :data, :key_type, :value_type
16
+
17
+ def serialize
18
+ serialized_dirty_data = {}
19
+
20
+ transformed_keys.each do |key|
21
+ value = data[key]
22
+
23
+ unless value.value == value.type.default_value
24
+ serialized_dirty_data[key.serialize.to_s] = value.serialize
25
+ end
26
+ end
27
+
28
+ clean_data = data.except(*transformed_keys)
29
+ clean_data.merge(serialized_dirty_data).deep_dup
30
+ end
31
+
32
+ def ==(other)
33
+ return false unless other.is_a?(self.class)
34
+
35
+ other.key_type == key_type &&
36
+ other.value_type == value_type &&
37
+ other.serialize == serialize
38
+ end
39
+
40
+ def initialize(initial_value = {}, key_type:, value_type:, on_change: nil)
41
+ self.key_type = key_type
42
+ self.value_type = value_type
43
+
44
+ self.data = initial_value
45
+ self.transformed_keys = Set.new
46
+ self.on_change = on_change
47
+ end
48
+
49
+ def [](key_var)
50
+ raw_key = key_var.is_a?(TypedVariable) ? key_var.value : key_var
51
+ string_key = raw_key.to_s
52
+
53
+ typed_key_var = TypedVariable.create_or_validate(key_type, key_var, on_change: on_change)
54
+
55
+ # First, attempt a lookup using the typed key
56
+ value = data[typed_key_var]
57
+
58
+ # If no value is found, try looking it up as a string (how it would be stored in JSONB)
59
+ if value.nil? && data.key?(string_key)
60
+ value = TypedVariable.create_or_validate(value_type, data[string_key], on_change: on_change)
61
+
62
+ data.delete(string_key)
63
+ set_value(typed_key_var, value)
64
+ end
65
+
66
+ # If the value is still nil, it truly doesn't exist; create a new default value
67
+ if value.nil?
68
+ value = TypedVariable.create_or_validate(value_type, on_change: on_change)
69
+ set_value(typed_key_var, value)
70
+ end
71
+
72
+ value
73
+ end
74
+
75
+ def []=(key_var, value)
76
+ key_var = TypedVariable.create_or_validate(key_type, key_var, on_change: on_change)
77
+ val_var = TypedVariable.create_or_validate(value_type, value, on_change: on_change)
78
+
79
+ if value_type.mapping?
80
+ raise TypeError, "Mappings cannot be assigned to mappings"
81
+ end
82
+
83
+ old_value = self.data[key_var]
84
+
85
+ if old_value != val_var
86
+ on_change&.call
87
+
88
+ transformed_keys.add(key_var)
89
+
90
+ data[key_var] ||= val_var
91
+ data[key_var].value = val_var.value
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ def set_value(key, value)
98
+ data[key] = value
99
+ transformed_keys.add(key)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,290 @@
1
+ class Type
2
+ include ContractErrors
3
+
4
+ attr_accessor :name, :metadata, :key_type, :value_type, :initial_length
5
+
6
+ INTEGER_TYPES = (8..256).step(8).flat_map do |num|
7
+ ["uint#{num}", "int#{num}"]
8
+ end.map(&:to_sym)
9
+
10
+ TYPES = [:string, :mapping, :address, :bytes32, :contract,
11
+ :bool, :address, :uint256, :int256, :array, :datetime, :bytes] + INTEGER_TYPES
12
+
13
+ TYPES.each do |type|
14
+ define_method("#{type}?") do
15
+ self.name == type
16
+ end
17
+ end
18
+
19
+ def self.value_types
20
+ TYPES.select do |type|
21
+ create(type).is_value_type?
22
+ end
23
+ end
24
+
25
+ def initialize(type_name, metadata = {})
26
+ if type_name.is_a?(Array)
27
+ if type_name.length != 1
28
+ raise "Invalid array type #{type_name.inspect}"
29
+ end
30
+
31
+ value_type = type_name.first
32
+
33
+ if TYPES.exclude?(value_type)
34
+ raise "Invalid type #{value_type.inspect}"
35
+ end
36
+
37
+ metadata = { value_type: value_type }
38
+ type_name = :array
39
+ end
40
+
41
+ type_name = type_name.to_sym
42
+
43
+ if TYPES.exclude?(type_name)
44
+ raise "Invalid type #{type_name}"
45
+ end
46
+
47
+ self.name = type_name.to_sym
48
+ self.metadata = metadata.deep_dup
49
+ end
50
+
51
+ def self.create(type_or_name, metadata = {})
52
+ return type_or_name if type_or_name.is_a?(self)
53
+
54
+ new(type_or_name, metadata)
55
+ end
56
+
57
+ def key_type=(type)
58
+ return if type.nil?
59
+ @key_type = self.class.create(type)
60
+ end
61
+
62
+ def value_type=(type)
63
+ return if type.nil?
64
+ @value_type = self.class.create(type)
65
+ end
66
+
67
+ def metadata=(metadata)
68
+ self.key_type = metadata[:key_type]
69
+ self.value_type = metadata[:value_type]
70
+ self.initial_length = metadata[:initial_length] if metadata[:initial_length]
71
+ end
72
+
73
+ def can_be_assigned_from?(other_type)
74
+ return true if self == other_type
75
+
76
+ if is_uint? && other_type.is_uint? || is_int? && other_type.is_int?
77
+ return extract_integer_bits >= other_type.extract_integer_bits
78
+ end
79
+
80
+ if address? && other_type.contract?
81
+ return true
82
+ end
83
+
84
+ false
85
+ end
86
+
87
+ def values_can_be_compared?(other_type)
88
+ return true if can_be_assigned_from?(other_type)
89
+
90
+ if is_uint? && other_type.is_uint? || is_int? && other_type.is_int?
91
+ return true
92
+ end
93
+ false
94
+ end
95
+
96
+ def metadata
97
+ (@metadata ||= {}).with_indifferent_access
98
+ end
99
+
100
+ def to_s
101
+ name.to_s
102
+ end
103
+
104
+ def default_value
105
+ is_int256_uint256_datetime = is_int? || is_uint? || datetime?
106
+
107
+ val = case
108
+ when is_int256_uint256_datetime
109
+ 0
110
+ when address?
111
+ "0x" + "0" * 40
112
+ when bytes32?
113
+ "0x" + "0" * 64
114
+ when string? || bytes?
115
+ ''
116
+ when bool?
117
+ false
118
+ when mapping?
119
+ MappingType::Proxy.new(key_type: key_type, value_type: value_type)
120
+ when array?
121
+ ArrayType::Proxy.new(value_type: value_type, initial_length: initial_length)
122
+ when contract?
123
+ ContractType::Proxy.new(contract_interface: metadata[:interface], address: nil, contract_type: nil)
124
+ else
125
+ raise "Unknown default value for #{self.inspect}"
126
+ end
127
+
128
+ check_and_normalize_literal(val)
129
+ end
130
+
131
+ def raise_variable_type_error(literal)
132
+ raise VariableTypeError.new("Invalid #{self}: #{literal.inspect}")
133
+ end
134
+
135
+ def parse_integer(literal)
136
+ base = literal.start_with?("0x") ? 16 : 10
137
+
138
+ begin
139
+ Integer(literal, base)
140
+ rescue ArgumentError => e
141
+ raise_variable_type_error(literal)
142
+ end
143
+ end
144
+
145
+ def check_and_normalize_literal(literal)
146
+ if literal.is_a?(TypedVariable)
147
+ raise VariableTypeError, "Only literals can be passed to check_and_normalize_literal: #{literal.inspect}"
148
+ end
149
+
150
+ if address?
151
+ if literal.is_a?(ContractType::Proxy)
152
+ return literal.address
153
+ end
154
+
155
+ unless literal.is_a?(String) && literal.match?(/\A0x[a-f0-9]{40}\z/i)
156
+ raise_variable_type_error(literal)
157
+ end
158
+
159
+ return literal.downcase
160
+ elsif is_uint?
161
+ if literal.is_a?(String)
162
+ literal = parse_integer(literal)
163
+ end
164
+
165
+ if literal.is_a?(Integer) && literal.between?(0, 2 ** extract_integer_bits - 1)
166
+ return literal
167
+ end
168
+
169
+ raise_variable_type_error(literal)
170
+ elsif is_int?
171
+ if literal.is_a?(String)
172
+ literal = parse_integer(literal)
173
+ end
174
+
175
+ if literal.is_a?(Integer) && literal.between?(-2 ** (extract_integer_bits - 1), 2 ** (extract_integer_bits - 1) - 1)
176
+ return literal
177
+ end
178
+
179
+ raise_variable_type_error(literal)
180
+ elsif string?
181
+ unless literal.is_a?(String)
182
+ raise_variable_type_error(literal)
183
+ end
184
+
185
+ return literal.freeze
186
+ elsif bool?
187
+ unless literal == true || literal == false
188
+ raise_variable_type_error(literal)
189
+ end
190
+
191
+ return literal
192
+ elsif bytes32?
193
+ unless literal.is_a?(String) && literal.match?(/\A0x[a-f0-9]{64}\z/i)
194
+ raise_variable_type_error(literal)
195
+ end
196
+
197
+ return literal.downcase
198
+ elsif bytes?
199
+ if literal.is_a?(String) && literal.length == 0
200
+ return literal
201
+ end
202
+
203
+ unless literal.is_a?(String) && literal.match?(/\A0x[a-fA-F0-9]*\z/) && literal.size.even?
204
+ raise_variable_type_error(literal)
205
+ end
206
+
207
+ return literal.downcase
208
+ elsif datetime?
209
+ dummy_uint = Type.create(:uint256)
210
+
211
+ begin
212
+ return dummy_uint.check_and_normalize_literal(literal)
213
+ rescue VariableTypeError => e
214
+ raise_variable_type_error(literal)
215
+ end
216
+ elsif mapping?
217
+ if literal.is_a?(MappingType::Proxy)
218
+ return literal
219
+ end
220
+
221
+ unless literal.is_a?(Hash)
222
+ raise VariableTypeError.new("invalid #{literal}")
223
+ end
224
+
225
+ proxy = MappingType::Proxy.new(literal, key_type: key_type, value_type: value_type)
226
+
227
+ return proxy
228
+ elsif array?
229
+ if literal.is_a?(ArrayType::Proxy)
230
+ return literal
231
+ end
232
+
233
+ unless literal.is_a?(Array)
234
+ raise_variable_type_error(literal)
235
+ end
236
+
237
+ data = literal.map do |value|
238
+ TypedVariable.create(value_type, value)
239
+ end
240
+
241
+ proxy = ArrayType::Proxy.new(data, value_type: value_type, initial_length: initial_length)
242
+
243
+ return proxy
244
+ elsif contract?
245
+ if literal.is_a?(ContractType::Proxy)
246
+ return literal
247
+ else
248
+ raise_variable_type_error("No literals allowed for contract types")
249
+ end
250
+ end
251
+
252
+ raise VariableTypeError.new("Unknown type #{self.inspect}: #{literal.inspect}")
253
+ end
254
+
255
+ def is_uint?
256
+ name.to_s.start_with?('uint')
257
+ end
258
+
259
+ def is_int?
260
+ name.to_s.start_with?('int')
261
+ end
262
+
263
+ def extract_integer_bits
264
+ return name.to_s[4..-1].to_i if is_uint?
265
+ return name.to_s[3..-1].to_i if is_int?
266
+ raise "Not an integer type: #{self}"
267
+ end
268
+
269
+ def ==(other)
270
+ other.is_a?(self.class) &&
271
+ other.name == name &&
272
+ other.metadata.except(:initial_length) == metadata.except(:initial_length)
273
+ end
274
+
275
+ def !=(other)
276
+ !(self == other)
277
+ end
278
+
279
+ def hash
280
+ [name, metadata].hash
281
+ end
282
+
283
+ def eql?(other)
284
+ hash == other.hash
285
+ end
286
+
287
+ def is_value_type?
288
+ !mapping? && !array?
289
+ end
290
+ end
@@ -0,0 +1,129 @@
1
+ class TypedVariable
2
+ include ContractErrors
3
+ extend AttrPublicReadPrivateWrite
4
+
5
+ attr_accessor :value, :on_change
6
+ attr_public_read_private_write :type
7
+
8
+ def initialize(type, value = nil, on_change: nil, **options)
9
+ self.type = type
10
+ self.value = value || type.default_value
11
+ self.on_change = on_change
12
+ end
13
+
14
+ def self.create(type, value = nil, on_change: nil, **options)
15
+ type = Type.create(type)
16
+
17
+ options[:on_change] = on_change
18
+
19
+ if type.mapping?
20
+ MappingType.new(type, value, **options)
21
+ elsif type.array?
22
+ ArrayType.new(type, value, **options)
23
+ elsif type.contract?
24
+ ContractType.new(type, value, **options)
25
+ else
26
+ new(type, value, **options)
27
+ end
28
+ end
29
+
30
+ def self.create_or_validate(type, value = nil, on_change: nil)
31
+ if value.is_a?(TypedVariable)
32
+ unless Type.create(type).can_be_assigned_from?(value.type)
33
+ raise VariableTypeError.new("invalid #{type}: #{value.inspect}")
34
+ end
35
+
36
+ value = value.value
37
+ end
38
+
39
+ create(type, value, on_change: on_change)
40
+ end
41
+
42
+ def as_json(args = {})
43
+ serialize
44
+ end
45
+
46
+ def serialize
47
+ value
48
+ end
49
+
50
+ def to_s
51
+ if value.is_a?(String) || value.is_a?(Integer)
52
+ value.to_s
53
+ else
54
+ raise "No string conversion"
55
+ end
56
+ end
57
+
58
+ def deserialize(serialized_value)
59
+ self.value = serialized_value
60
+ end
61
+
62
+ def value=(new_value)
63
+ new_value = type.check_and_normalize_literal(new_value)
64
+
65
+ if @value != new_value
66
+ on_change&.call
67
+
68
+ if new_value.respond_to?(:on_change=)
69
+ new_value.on_change = on_change
70
+ end
71
+
72
+ @value = new_value
73
+ end
74
+ end
75
+
76
+ def method_missing(name, *args, &block)
77
+ if value.respond_to?(name)
78
+ result = value.send(name, *args, &block)
79
+
80
+ if result.class == value.class
81
+ begin
82
+ result = type.check_and_normalize_literal(result)
83
+ rescue ContractErrors::VariableTypeError => e
84
+ if type.is_uint?
85
+ result = TypedVariable.create(:uint256, result)
86
+ else
87
+ raise
88
+ end
89
+ end
90
+ end
91
+
92
+ result
93
+
94
+ if name.to_s.end_with?("=") && !%w[>= <=].include?(name.to_s[-2..])
95
+ self.value = result if type.is_value_type?
96
+ self
97
+ else
98
+ result
99
+ end
100
+ else
101
+ super
102
+ end
103
+ end
104
+
105
+ def respond_to_missing?(name, include_private = false)
106
+ value.respond_to?(name, include_private) || super
107
+ end
108
+
109
+ def !=(other)
110
+ !(self == other)
111
+ end
112
+
113
+ def ==(other)
114
+ if other.is_a?(self.class)
115
+ return false unless type.values_can_be_compared?(other.type)
116
+ return value == other.value
117
+ else
118
+ return value == TypedVariable.create(type, other).value
119
+ end
120
+ end
121
+
122
+ def hash
123
+ [value, type].hash
124
+ end
125
+
126
+ def eql?(other)
127
+ hash == other.hash
128
+ end
129
+ end
@@ -0,0 +1,16 @@
1
+
2
+
3
+ require 'active_support/all'
4
+
5
+
6
+ ## our own code
7
+ require_relative 'typed/contract_errors' ## move upstream to 0xfacet !!!
8
+
9
+ require_relative 'typed/attr_public_read_private_write'
10
+ require_relative 'typed/type'
11
+ require_relative 'typed/typed_variable'
12
+ require_relative 'typed/array_type'
13
+ require_relative 'typed/mapping_type'
14
+ require_relative 'typed/contract_type'
15
+
16
+
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: 0xfacet-typed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-11-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdoc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '4.0'
47
+ description: 0xfacet-typed - solidity-like value and reference types for rubidity
48
+ o.g.
49
+ email: gerald.bauer@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files:
53
+ - CHANGELOG.md
54
+ - Manifest.txt
55
+ - README.md
56
+ files:
57
+ - CHANGELOG.md
58
+ - Manifest.txt
59
+ - README.md
60
+ - Rakefile
61
+ - lib/0xfacet/typed.rb
62
+ - lib/0xfacet/typed/array_type.rb
63
+ - lib/0xfacet/typed/attr_public_read_private_write.rb
64
+ - lib/0xfacet/typed/contract_errors.rb
65
+ - lib/0xfacet/typed/contract_type.rb
66
+ - lib/0xfacet/typed/mapping_type.rb
67
+ - lib/0xfacet/typed/type.rb
68
+ - lib/0xfacet/typed/typed_variable.rb
69
+ homepage: https://github.com/s6ruby/rubidity.review
70
+ licenses:
71
+ - Public Domain
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options:
75
+ - "--main"
76
+ - README.md
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '2.3'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.4.10
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: 0xfacet-typed - solidity-like value and reference types for rubidity o.g.
94
+ test_files: []