solidity-typed 0.1.0

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: 634cc8c8ee7cf10c3a67c0a8dbcc7c5efad7fe17a5a961128a5140f7648a8ff0
4
+ data.tar.gz: f6956a85d7b3e7ae5aa021052ddcc9981f0c5f394acb29f0457e2587a3cc8e56
5
+ SHA512:
6
+ metadata.gz: 9537d4935ea267c3ace17ac3625552fab903dee944718e9163392167c39cdcff478f3494c9780e09db327c6228458dac5d33e3738fddd3fa08463322d9fff99e
7
+ data.tar.gz: 6210074c6e54f778fca18fbb738f8a884421702ceede73d73e4b5efd32ccce35ea2b30fd7507ed76f0d820753723c735bdd0f3af58ff252b480dfed2c9cf5833
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ### 0.1.0
2
+ ### 0.0.1 / 2023-09-10
3
+
4
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,24 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/solidity/typed.rb
6
+ lib/solidity/typed/array.rb
7
+ lib/solidity/typed/array_builder.rb
8
+ lib/solidity/typed/bool.rb
9
+ lib/solidity/typed/conversion.rb
10
+ lib/solidity/typed/enum.rb
11
+ lib/solidity/typed/enum_builder.rb
12
+ lib/solidity/typed/mapping.rb
13
+ lib/solidity/typed/mapping_builder.rb
14
+ lib/solidity/typed/metatypes/array.rb
15
+ lib/solidity/typed/metatypes/bool.rb
16
+ lib/solidity/typed/metatypes/literals.rb
17
+ lib/solidity/typed/metatypes/mapping.rb
18
+ lib/solidity/typed/metatypes/types.rb
19
+ lib/solidity/typed/numbers.rb
20
+ lib/solidity/typed/struct.rb
21
+ lib/solidity/typed/struct_builder.rb
22
+ lib/solidity/typed/typed.rb
23
+ lib/solidity/typed/values.rb
24
+ lib/solidity/typed/version.rb
data/README.md ADDED
@@ -0,0 +1,318 @@
1
+ # Solidity Typed
2
+
3
+ solidity-typed - "zero-dependency" 100%-solidity compatible data type and application binary interface (abi) machinery incl. bool, (frozen) string, address, bytes, uint, int, enum, struct, array, mapping, event, and more for solidity-inspired contract (blockchain) programming languages incl. rubidity et al
4
+
5
+
6
+
7
+
8
+ * home :: [github.com/s6ruby/rubidity](https://github.com/s6ruby/rubidity)
9
+ * bugs :: [github.com/s6ruby/rubidity/issues](https://github.com/s6ruby/rubidity/issues)
10
+ * gem :: [rubygems.org/gems/solidity-typed](https://rubygems.org/gems/solidity-typed)
11
+ * rdoc :: [rubydoc.info/gems/solidity-typed](http://rubydoc.info/gems/solidity-typed)
12
+
13
+
14
+ ## What's Solidity?! What's Rubidity?!
15
+
16
+ See [**Solidity - Contract Application Binary Interface (ABI) Specification** »](https://docs.soliditylang.org/en/latest/abi-spec.html)
17
+
18
+ See [**Rubidity - Ruby for Layer 1 (L1) Contracts / Protocols with "Off-Chain" Indexer** »](https://github.com/s6ruby/rubidity)
19
+
20
+
21
+
22
+
23
+ ## Data Types
24
+
25
+
26
+
27
+ ### Available Value & Reference Types
28
+
29
+ Value Types
30
+
31
+ * `String`: Text-based data (in utf8 encoding). Note: Solditity (-typed) strings are immutable (frozen).
32
+ * `Address`: User or contract (blockchain) address (in hexadecimal) - 20 bytes (40 hexchars).
33
+ * `InscriptionId`: Unique identifiers for inscriptions (in hexadecimal) - 32 bytes (64 hexchars).
34
+ * `Bool`: Boolean values (true or false).
35
+ * `UInt`: Unsigned (natural) 256-bit integer numbers (0..2^256-1)
36
+ * `Int`: Signed (negative or positive) 256-bit integer numbers.
37
+ * `Timestamp`: Date and time (stored as unsigned 256-bit integers. Seconds since "unix epoch" starting on January 1st, 1970 at 0:00).
38
+
39
+
40
+ <!--
41
+ * `:dumbContract`: A specific type of contract ID (hexadecimal).
42
+ * `:addressOrDumbContract`: Either an Ethereum address or a specific type of contract ID.
43
+ -->
44
+
45
+
46
+ Reference Types
47
+
48
+ * `Mapping`: Key-value storage for different types.
49
+ * `Array`: Lists of other types.
50
+
51
+
52
+ ### Zero (Default) Values
53
+
54
+ In Solidity, every type comes with a zero (default) value
55
+ that gets assigned when a variable is declared but not initialized.
56
+ Understanding these defaults is crucial for avoiding unintended behavior in your code.
57
+ Here is the rundown:
58
+
59
+ * **Integers (Int, UInt, Timestamp, Timedelta)**: Default to `0`.
60
+ * **Address Types (Address)**: Default to a zero-address, which is `0x0000000000000000000000000000000000000000`.
61
+ * **Inscription Identifiers (InscriptionId)**: Default to a zero-identifier, `0x0000000000000000000000000000000000000000000000000000000000000000`.
62
+ * **String (String)**: Default to an empty string `''`.
63
+ * **Boolean (Bool)**: Default to `false`.
64
+ * **Mapping (Mapping)**: Default to an empty mapping object. The key and value types are set according to your specifications.
65
+ * **Array (Array)**: Default to an empty array object. The sub type is set according to your specification.
66
+
67
+
68
+
69
+ ### Literals & Type Coercion and Validation
70
+
71
+ Solidity (-Typed) employs a strong system of type validation and coercion to ensure that variables adhere to their declared types. This involves transforming literal values into the corresponding solidity types and reporting type mismatches.
72
+
73
+ Here's a brief rundown of type coercion rules:
74
+
75
+ * **Address**: Accepts hexadecimal strings that match the contract or user (blockchain) address format (`0x` followed by 40 hexadecimal characters). The address is then normalized to lowercase.
76
+ * **UInt and Int**: These types accept both integer and string representations. Strings are attempted to be coerced into integers. uint and int cannot be out of the range of their Solidity counterparts.
77
+ * **String**: Only accepts string literals. Note: strings are immutable (frozen).
78
+ * **Bool**: Accepts only `true` or `false`.
79
+ * **InscriptionId**: Accepts hexadecimal strings matching specific patterns (`0x` followed by 64 hexadecimal characters).
80
+ * **Timestamp**: Relies on `UInt` type coercion, as it's represented as an unsigned integer (32-bit) internally.
81
+ * **Mapping**: Accepts a Hash and ensures that keys and values match the specified types. Coerces these into a typed mapping object (`Mapping`).
82
+ * **Array**: Accepts an array and ensures that the values match the specified type. Coerces these into a typed array object (`Array`).
83
+
84
+
85
+
86
+
87
+ ## Usage
88
+
89
+
90
+ Let's try some random use:
91
+
92
+
93
+
94
+
95
+ ``` ruby
96
+ require 'solidity/typed'
97
+
98
+
99
+ module Sandbox ## note: "wrap" in sandbox (auto-)incl. (solidity) types
100
+
101
+ #####################################
102
+ # frozen (immutable ) value types
103
+
104
+
105
+ # note: (typed) strings always use utf-8 encoding AND
106
+ # are frozen/immutable!!!
107
+ a = String.new #=> <val string:"">
108
+ a = String.new( 'hello, world!' ) #=> <val string:"hello, world!">
109
+
110
+
111
+ a = UInt.new #=> <val uint:0>
112
+ a = UInt.new( 100 ) #=> <val uint:100>
113
+ a += 100 #=> <val uint:200>
114
+ a -= 100 #=> <val uint:100>
115
+
116
+ # use/add TypedNat(ural) (natural integer number) alias - why? why not?
117
+ # check if natural numbers start at 0 (or exclude 0 ????)
118
+
119
+ a = Int.new #=> <val int:0>
120
+ a = Int.new( 100 ) #=> <val int:100>
121
+ a += 100 #=> <val int:200>
122
+ a -= 100 #=> <val int:100>
123
+
124
+ #
125
+ # idea - use "plain" integer as TypedInt - why? why not?
126
+
127
+
128
+ a = false #=> <val bool:false>
129
+ a = true #=> <val bool:true>
130
+
131
+ #
132
+ # idea - use "plain" true|false as TypedBool (frozen|typed) - done
133
+
134
+
135
+ a = Address.new
136
+ #=> <val address:"0x0000000000000000000000000000000000000000">
137
+ a = Address.new( '0x'+ 'aa'*20 )
138
+ #=> <val address:"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">
139
+
140
+
141
+ a = InscriptionId.new
142
+ #=> <val inscriptionId:"0x0000000000000000000000000000000000000000000000000000000000000000">
143
+ a = InscriptionId.new( '0x'+'ab'*32 )
144
+ #=> <val inscriptionId:"0xabababababababababababababababababababababababababababababababab">
145
+
146
+
147
+ a = Bytes32.new
148
+ #=> <val bytes32:"0x0000000000000000000000000000000000000000000000000000000000000000">
149
+ a = Bytes32.new( '0x'+'ab'*32 )
150
+ #=> <val bytes32:"0xabababababababababababababababababababababababababababababababab">
151
+
152
+ a = Timestamp.new #=> <val timestamp:0>
153
+
154
+ # use/change/rename to Timestamp - why? why not?
155
+ # ALWAYS uses epoch time starting at 0 (no time zone or such)
156
+
157
+ a = Timedelta.new #=> <val timedelta:0>
158
+
159
+
160
+ #
161
+ # todo/check: is bytes a (mutabale)bytebuffer or a frozen/immutable?
162
+ a = Bytes.new #=> <val bytes:"">
163
+
164
+
165
+ ###########################
166
+ # reference types
167
+
168
+
169
+ Array‹String› = Array.new( String )
170
+ Array‹String›.type #=> <type string[]>
171
+
172
+ a = Array‹String›.new #=> <ref string[]:[]>
173
+
174
+ a = Array‹String›.new( ['zero', 'one', 'two'] )
175
+ #=> <ref string[]:
176
+ # [<val string:"zero">, <val string:"one">, <val string:"two">]>
177
+ a[0] #=> <val string:"zero">
178
+ a[1] #=> <val string:"one">
179
+ a[2] #=> <val string:"two">
180
+ a.length #=> 3
181
+ a.push( 'three' )
182
+ a[3] #=> <val string:"three">
183
+ a.push( 'four' )
184
+ a[4] #=> <val string:"four">
185
+ a.length #=> 5
186
+ a.serialize #=> ["zero", "one", "two", "three", "four"]
187
+
188
+
189
+
190
+ Array‹UInt› = Array.new( UInt )
191
+ Array‹UInt›.type #=> <type uint[]>
192
+
193
+ a = Array‹UInt›.new #=> <ref uint[]:[]>
194
+
195
+ a = Array‹UInt›.new( [0,1,2] )
196
+ #=> <ref uint[]:
197
+ # [<val uint:0>, <val uint:1>, <val uint:2>]>
198
+ a[0] #=> <val uint:0>
199
+ a[1] #=> <val uint:1>
200
+ a[2] #=> <val uint:2>
201
+ a.length #=> 3
202
+ a.push( 3 )
203
+ a[3] #=> <val uint:3>
204
+ a.push( 4 )
205
+ a[4] #=> <val uint:4>
206
+ a.length #=> 5
207
+ a.serialize #=> [0, 1, 2, 3, 4]
208
+
209
+ # todo/check: add a "convenience" TypedUIntArray or TypedArray<UInt>
210
+ # use special unicode-chars for <>??
211
+
212
+
213
+ alice = '0x'+ 'aa'*20
214
+ bob = '0x'+ 'bb'*20
215
+ charlie = '0x'+ 'cc'*20
216
+
217
+
218
+ Mapping‹Address→UInt› = Mapping.new( Address, UInt )
219
+ Mapping‹Address→UInt›.type #=> <type mapping(address=>uint)>
220
+
221
+ a = Mapping‹Address→UInt›.new
222
+ #=> <ref mapping(address=>uint):{}>
223
+
224
+ a = Mapping‹Address→UInt›.new( { alice => 100,
225
+ bob => 200 },
226
+ )
227
+ #=> <ref mapping(address=>uint):
228
+ # {<val address:"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">=><val uint:100>,
229
+ # <val address:"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb">=><val uint:200>}>
230
+
231
+ a[ alice ] #=> <val uint:100>
232
+ a[ bob ] #=> <val uint:200>
233
+ a[ charlie ] #=> <val uint:0>
234
+ a[ charlie ] = 300
235
+ a[ charlie ] #=> <val uint:300>
236
+
237
+ a.serialize
238
+ #=> {"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"=>100,
239
+ # "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"=>200,
240
+ # "0xcccccccccccccccccccccccccccccccccccccccc"=>300}
241
+
242
+
243
+ #
244
+ # more - enums, structs, etc.
245
+
246
+ Color = Enum.new( :Color, :red, :green, :blue )
247
+ Color.type #=> <type Color enum(red,green,blue)>
248
+
249
+ Color::RED #=> <val Color enum(red,green,blue):red(0)>
250
+ Color.red #=> <val Color enum(red,green,blue):red(0)>
251
+
252
+ Color::GREEN #=> <val Color enum(red,green,blue):red(0)>
253
+ Color.green #=> <val Color enum(red,green,blue):red(0)>
254
+
255
+ Color.min #=> <val Color enum(red,green,blue):red(0)>
256
+ Color.max #=> <val Color enum(red,green,blue):blue(2)>
257
+
258
+ color = Color.green
259
+ color.serialize #=> 1
260
+
261
+ color = Color.red
262
+ color.serialize #=> 0
263
+
264
+
265
+
266
+ Bet = Struct.new( :Bet,
267
+ user: Address,
268
+ block: UInt,
269
+ cap: UInt,
270
+ amount: UInt )
271
+ Bet.type
272
+
273
+
274
+ bet = Bet.new
275
+ bet.user
276
+ bet.amount
277
+
278
+ bet.user = Address.new( '0x'+'aa'*20 )
279
+ bet.amount = UInt.new( 123 )
280
+
281
+ bet.user = '0x'+'bb'*20 ## literal assign (with typecheck)
282
+ bet.amount = 234 ## literal assign (with typecheck)
283
+
284
+ bet.serialize
285
+
286
+ bet = Bet.new( '0x'+'cc'*20, 0, 0, 456,
287
+ bet.serialize
288
+
289
+ # ...
290
+
291
+ end # module Sandbox
292
+ ```
293
+
294
+
295
+ And so on. To be continued ...
296
+
297
+
298
+
299
+
300
+
301
+
302
+ ## Bonus - More Blockchain (Crypto) Tools, Libraries & Scripts In Ruby
303
+
304
+ See [**/blockchain**](https://github.com/rubycocos/blockchain)
305
+ at the ruby code commons (rubycocos) org.
306
+
307
+
308
+
309
+
310
+
311
+
312
+ ## Questions? Comments?
313
+
314
+ Join us in the [Rubidity (community) discord (chat server)](https://discord.gg/3JRnDUap6y). Yes you can.
315
+ Your questions and commetary welcome.
316
+
317
+ Or post them over at the [Help & Support](https://github.com/geraldb/help) page. Thanks.
318
+
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'hoe'
2
+ require './lib/solidity/typed/version.rb'
3
+
4
+
5
+ Hoe.spec 'solidity-typed' do
6
+ self.version = Solidity::Module::Typed::VERSION
7
+
8
+ self.summary = 'solidity-typed - "zero-dependency" 100%-solidity compatible data type and application binary interface (abi) machinery incl. bool, (frozen) string, address, bytes, uint, int, enum, struct, array, mapping, event, and more for solidity-inspired contract (blockchain) programming languages incl. rubidity et al'
9
+ self.description = summary
10
+
11
+ self.urls = { home: 'https://github.com/s6ruby/rubidity' }
12
+
13
+ self.author = 'Gerald Bauer'
14
+ self.email = 'gerald.bauer@gmail.com'
15
+
16
+ # switch extension to .markdown for gihub formatting
17
+ self.readme_file = 'README.md'
18
+ self.history_file = 'CHANGELOG.md'
19
+
20
+ self.extra_deps = []
21
+
22
+ self.licenses = ['Public Domain']
23
+
24
+ self.spec_extras = {
25
+ required_ruby_version: '>= 2.3'
26
+ }
27
+ end
@@ -0,0 +1,166 @@
1
+
2
+
3
+ module Types
4
+ class Array < TypedReference
5
+
6
+ ## todo/check: make "internal" data (array) available? why? why not?
7
+ ## attr_reader :data
8
+
9
+ def self.zero() @zero ||= new; end
10
+ def zero?()
11
+ if type.size == 0 ## assume dynamic (starts with empty array)
12
+ @data.empty?
13
+ else ## assume fixed size array (initialized with x zero items)
14
+ ## use zero to check - why? why not?
15
+ ## fix-fix-fix - add support for fixed Array here or use a new class - why? why not?
16
+ self == self.class.zero
17
+ end
18
+ end
19
+
20
+
21
+
22
+ def initialize( initial_value = [] )
23
+ ## was: initial_value ||= []
24
+ ## check if nil gets passed in - default not used?
25
+ raise ArgumentError, "expected literal of type #{type}; got typed #{initial_value.pretty_print_inspect}" if initial_value.is_a?( Typed )
26
+
27
+ @data = type.check_and_normalize_literal( initial_value ).map do |item|
28
+ type.sub_type.new( item )
29
+ end
30
+
31
+ ## check size if fixed (must all set to zero up to size!!!)
32
+ if type.size > 0 ## auto-init with zeros
33
+ if @data.size >= type.size ## note: allow ("fixed") array to grow bigger for now - why? why not?
34
+ # bingo! already setup with inital values
35
+ else
36
+ self.size = type.size
37
+ end
38
+ end
39
+ end
40
+
41
+
42
+
43
+ extend Forwardable ## pulls in def_delegator
44
+ ## add more Array forwards here!!!!
45
+ ## todo/fix: wrap size, empty? return value literals into typed values - why? why not?
46
+ def_delegators :@data, :size, :length,
47
+ :empty?,
48
+ :each, :each_with_index
49
+
50
+
51
+ def []( index )
52
+ ## use serialize to get value (why not value) - why? why not?
53
+ index = index.is_a?( Typed ) ? index.as_data : index
54
+
55
+ ## fix: use index out of bounds error - why? why not?
56
+ raise ArgumentError, "Index out of bounds - #{index} : #{index.class.name} >= #{@data.size}" if index >= @data.size
57
+
58
+ obj = @data[ index ]
59
+ if obj.nil?
60
+ obj = type.sub_type.new_zero
61
+ @data[ index ] = obj
62
+ end
63
+ obj
64
+ end
65
+
66
+ def []=(index, new_value)
67
+ ## use serialize to get value (why not value) - why? why not?
68
+ index = index.is_a?( Typed ) ? index.as_data : index
69
+
70
+ raise ArgumentError, "Sparse arrays are not supported; index out of bounds - sorry" if index >= @data.size
71
+
72
+ # fix-fix-fix: allow typed value here (not only literals)!!!
73
+ obj = if new_value.is_a?( Typed )
74
+ new_value
75
+ else
76
+ type.sub_type.new( new_value )
77
+ end
78
+
79
+ @data[ index ] = obj
80
+ end
81
+
82
+
83
+ def pop
84
+ ## note: pop will decrease size/lenght!!!
85
+ ## will remove LAST item in array!!!
86
+ ##
87
+ ## Pop is used to delete or remove an element
88
+ ## in a dynamic array from the end.
89
+ @data.pop
90
+ end
91
+
92
+ def push( new_value )
93
+ ## note: push will increase size/length!!!
94
+ ##
95
+ ## Push is used to add new element to a dynamic array,
96
+ ## when you push a value to an array, it becomes the last value
97
+ obj = if new_value.is_a?( Typed )
98
+ new_value
99
+ else
100
+ type.sub_type.new( new_value )
101
+ end
102
+ @data.push( obj )
103
+
104
+ ## note: returns array.size (NOT array itself!!!) to keep compatible with solidity - why? why not?
105
+ @data.size
106
+ end
107
+
108
+
109
+ def delete( index )
110
+ ## note sets the element to zero!!!
111
+ ## will NOT remove from array itself!!!
112
+
113
+ ## use serialize to get value (why not value) - why? why not?
114
+ index = index.is_a?( Typed ) ? index.as_data : index
115
+
116
+ ## fix: use index out of bounds error - why? why not?
117
+ raise ArgumentError, "Index out of bounds - #{index} : #{index.class.name} >= #{@data.size}" if index >= @data.size
118
+
119
+ @data[ index ] = type.sub_type.new_zero
120
+ self
121
+ end
122
+
123
+
124
+ def size=( new_size )
125
+ ## todo/check: value must be greater 0 and greater than current size
126
+ diff = new_size - @data.size
127
+ if diff == 0
128
+ ## stay as is; do nothing
129
+ elsif diff > 0
130
+ ## todo/check:
131
+ ## always return (deep) frozen zero object - why? why not?
132
+ ## let user change the returned zero object - why? why not?
133
+ if type.sub_type.respond_to?( :new_zero )
134
+ ## note: use a new unfrozen copy of the zero object
135
+ ## changes to the object MUST be possible (new "empty" modifable object expected)
136
+ diff.times { @data << type.sub_type.new_zero }
137
+ else
138
+ raise "[Array]#length= cannot create new_zero for type #{type.sub_type} - sorry"
139
+ end
140
+ else ## diff < 0
141
+ ## fix-fix-fix - raise error here - cannot shrink/delete via length!!!
142
+ end
143
+ self # return reference to self
144
+ end
145
+ alias_method :length=, :size= ## always use length (and remove size?) - why? why not?
146
+
147
+
148
+ def clear
149
+ ## note: reset ary to zero (NOT empty e.g. [])
150
+ ## differes for "fixed" size arrays
151
+ @data.clear
152
+ self.size = type.size if type.size > 0 ## auto-init with zeros
153
+ self # return reference to self
154
+ end
155
+
156
+
157
+ def as_data
158
+ @data.map {|item| item.as_data }
159
+ end
160
+
161
+ def pretty_print( printer )
162
+ printer.text( "<ref #{type}:#{@data.pretty_print_inspect}>" );
163
+ end
164
+ end # class Array
165
+ end # module Types
166
+
@@ -0,0 +1,53 @@
1
+
2
+ module Types
3
+ class Array
4
+
5
+ ## note: add size option here (size=0) default is dynamic (not fixed)!!!
6
+ def self.build_class( sub_type, size=0 )
7
+ ## add convenience sub_type helper here - why? why not?
8
+ ## sub_type = Type.create( sub_type ) if sub_type.is_a?( Symbol ) ||
9
+ ## sub_type.is_a?( String )
10
+ ## sub_type = sub_type.type if sub_type.is_a?( Class ) && sub_type.ancestors.include?( Typed )
11
+ sub_type = typeof( sub_type )
12
+
13
+ type = ArrayType.instance( sub_type, size )
14
+
15
+ class_name = type.typedclass_name
16
+
17
+ ## note: keep a class cache
18
+ ## note: klasses may have different init sizes (default 0)
19
+ cache = @@cache ||= {}
20
+ klass = cache[ class_name ]
21
+ ## fix-fix-fix - check if const klass defined for cache (no cache needed)!!!!!!!!
22
+
23
+ if klass.nil?
24
+ klass = Class.new( Array )
25
+ klass.define_singleton_method( :type ) do
26
+ @type ||= type
27
+ end
28
+
29
+ ## add self.new too - note: call/forward to "old" orginal self.new of Event (base) class
30
+ klass.define_singleton_method( :new ) do |*args|
31
+ old_new( *args )
32
+ end
33
+
34
+ ## add to cache for later (re)use
35
+ cache[ class_name ] = klass
36
+
37
+ ## for default scope use Kernel - why? why not?
38
+ ## or Globals or Typed - why? why not?
39
+ Types.const_set( class_name, klass )
40
+ end
41
+
42
+ klass
43
+ end # method self.build_class
44
+
45
+ class << self
46
+ alias_method :old_new, :new # note: store "old" orginal version of new
47
+ alias_method :new, :build_class # replace original version with create
48
+ end
49
+
50
+
51
+ end # class Array
52
+ end # module Types
53
+
@@ -0,0 +1,47 @@
1
+ #########
2
+ ### monkey patch built-in FalseClass & TrueClass
3
+ ## move to core-ext directory or such - why? why not?
4
+
5
+
6
+ ## note. Bool is a module (NOT a class)
7
+ ## adding a new superclass in ruby NOT possible
8
+ ## still waiting for common base clase for bools in ruby!!!
9
+ ## see https://github.com/geraldb/talks/blob/master/bool.md
10
+ ## or https://github.com/rubycocos/core/tree/master/safebool
11
+
12
+
13
+ module Bool
14
+ def type() self.class.type; end
15
+ def as_data() self; end ## that is, return true or false
16
+
17
+ ## note:
18
+ ## self.type or such WILL not get included
19
+ ## via module include in TrueClass & FalseClass
20
+ ## add in TrueClass & FalseClass
21
+ ## TrueClass.type will NOT work via "inheritance" like a "true" superclass - why? why not?
22
+ def self.type() Types::Typed::BoolType.instance; end
23
+ ## note: lets you use Bool.type
24
+ def self.zero() false; end
25
+ end # module Bool
26
+
27
+
28
+
29
+
30
+ class FalseClass
31
+ include Bool ## "hack" - enables false.is_a?(Bool)
32
+ ## and false.type
33
+ ## and false.as_data
34
+
35
+ def self.type() Types::Typed::BoolType.instance; end
36
+ def zero?() true; end
37
+ end
38
+
39
+ class TrueClass
40
+ include Bool ## "hack" - enables true.is_a?(Bool)
41
+ ## and true.type
42
+ ## and true.as_data
43
+
44
+ def self.type() Types::Typed::BoolType.instance; end
45
+ def zero?() false; end
46
+ end
47
+