tealrb 0.6.0 → 0.9.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ebe163f8903cf66046698ddfebe36e615359bd568e76be4eb30f368011b1ce0
4
- data.tar.gz: 64db7183fe7b170d7b80881cd66272e5016e6a50cb6886a5300df729520d539d
3
+ metadata.gz: d027d915afa0ccb6383791a694d6ca747bd07c14a2803d6ecaa8119b3277ffe9
4
+ data.tar.gz: e09162d147464ba6a7c0ada5c18bc9884832f164bb43f02a87d6d3f733093ce4
5
5
  SHA512:
6
- metadata.gz: 94f4791ca50e11afb7937670b976a87f75aaeaa4b364e5eea104541c571fce4f2b41e73c05c7d743772fb37657cf9dc3690e869d49007b3bd77ea4c5168ff1e5
7
- data.tar.gz: f77f3513679a82d255a8a1e10cc51c8e593b66d0faae844df461a36d50b211a62b5cd9761a93c1f34591b375439766eba38238f4670a7205cc00eb72bd553c57
6
+ metadata.gz: e9b80748e7716e45b0bb87efcd0e70560bbb46fde5f6907ca6beaac59cd77ba4518acb41337df2fb5bb0aa6c9c8c86a6cfb28042ae95736028f4bcbdffc30c96
7
+ data.tar.gz: 791cb92688f986e2807770797c4ba5f61cd20e675c2887169126eb34bbbc40196e9a52ac64ecc79a4a9338ddb37632d20b5e08828a3d5b7cce9a2aa122ee2c57
@@ -4,13 +4,15 @@ module TEALrb
4
4
  class Contract
5
5
  include TEALrb
6
6
  include Opcodes
7
+ include Opcodes::AllOpcodes
7
8
  include ABI
8
9
  include Rewriters
9
10
 
10
11
  attr_reader :teal
11
12
 
12
13
  class << self
13
- attr_accessor :subroutines, :version, :teal_methods, :abi_method_hash, :abi_description, :debug
14
+ attr_accessor :subroutines, :version, :teal_methods, :abi_method_hash, :abi_description, :debug,
15
+ :disable_abi_routing
14
16
 
15
17
  private
16
18
 
@@ -21,6 +23,7 @@ module TEALrb
21
23
  klass.abi_description = ABI::ABIDescription.new
22
24
  klass.abi_method_hash = {}
23
25
  klass.debug = false
26
+ klass.disable_abi_routing = false
24
27
  super
25
28
  end
26
29
  end
@@ -69,7 +72,8 @@ module TEALrb
69
72
  # sets the `#pragma version`, defines teal methods, and defines subroutines
70
73
  def initialize
71
74
  @teal = TEAL.new ["#pragma version #{self.class.version}"]
72
- @scratch = Scratch.new(@teal)
75
+ IfBlock.id = 0
76
+ @scratch = Scratch.new
73
77
 
74
78
  self.class.subroutines.each_key do |name|
75
79
  define_singleton_method(name) do |*_args|
@@ -86,6 +90,25 @@ module TEALrb
86
90
  end
87
91
  end
88
92
 
93
+ def teal_source
94
+ teal_lines = []
95
+
96
+ @teal.each do |line|
97
+ ln = line.strip
98
+
99
+ if (ln[%r{\S+:($| //)}] && !ln[/^if\d+/]) || ln == 'b main' || ln[/^#/]
100
+ teal_lines << ln
101
+ elsif ln == 'retsub'
102
+ teal_lines << " #{ln}"
103
+ teal_lines << ''
104
+ else
105
+ teal_lines << " #{ln}"
106
+ end
107
+ end
108
+
109
+ teal_lines.join("\n")
110
+ end
111
+
89
112
  # return the input without transpiling to TEAL
90
113
  def rb(input)
91
114
  input
@@ -96,8 +119,6 @@ module TEALrb
96
119
  # @param definition [Lambda, Proc, UnboundMethod] the method definition
97
120
  # @return [nil]
98
121
  def define_teal_method(name, definition)
99
- @teal.set_as_current
100
-
101
122
  new_source = generate_method_source(name, definition)
102
123
 
103
124
  define_singleton_method(name) do |*_args|
@@ -112,13 +133,11 @@ module TEALrb
112
133
  # @param definition [Lambda, Proc, UnboundMethod] the method definition
113
134
  # @return [nil]
114
135
  def define_subroutine(name, definition)
115
- @teal.set_as_current
116
-
117
136
  define_singleton_method(name) do |*_args|
118
137
  callsub(name)
119
138
  end
120
139
 
121
- @teal << 'b main' unless @teal.include? 'b main'
140
+ TEAL.instance << 'b main' unless TEAL.instance.include? 'b main'
122
141
 
123
142
  label(name) # add teal label
124
143
 
@@ -140,17 +159,18 @@ module TEALrb
140
159
  def comment(content, inline: false)
141
160
  content = " #{content}" unless content[0] == ' '
142
161
  if inline
143
- last_line = @teal.pop
144
- @teal << "#{last_line} //#{content}"
162
+ last_line = TEAL.instance.pop
163
+ TEAL.instance << "#{last_line} //#{content}"
145
164
  else
146
- @teal << "//#{content}"
165
+ TEAL.instance << '' unless TEAL.instance.last[%r{^//}]
166
+ TEAL.instance << "//#{content}"
147
167
  end
148
168
  end
149
169
 
150
170
  # inserts a string into TEAL source
151
171
  # @param string [String] the string to insert
152
172
  def placeholder(string)
153
- @teal << string
173
+ TEAL.instance << string
154
174
  end
155
175
 
156
176
  # the hash of the abi description
@@ -162,20 +182,32 @@ module TEALrb
162
182
  # @param string [String] string to transpile
163
183
  # @return [nil]
164
184
  def compile_string(string)
165
- @teal.set_as_current
166
185
  eval_tealrb(rewrite(string), debug_context: 'compile_string')
167
186
  nil
168
187
  end
169
188
 
170
- # transpiles #main
189
+ # transpiles #main and routes abi methods. To disable abi routing, set `@disable_abi_routing` to true in your
190
+ # Contract subclass
171
191
  def compile
172
- @teal.set_as_current
173
- @teal << 'main:' if @teal.include? 'b main'
174
- eval_tealrb(rewrite(method(:main).source, method_rewriter: true), debug_context: 'main')
192
+ TEAL.instance << 'main:' if TEAL.instance.include? 'b main'
193
+ route_abi_methods unless self.class.disable_abi_routing
194
+ eval_tealrb(rewrite(method(:main).source, method_rewriter: true), debug_context: 'main') if respond_to? :main
175
195
  end
176
196
 
177
197
  private
178
198
 
199
+ def route_abi_methods
200
+ self.class.abi_description.methods.each do |meth|
201
+ signature = "#{meth[:name]}(#{meth[:args].map { _1[:type] }.join(',')})#{meth[:returns][:type]}"
202
+ selector = OpenSSL::Digest.new('SHA512-256').hexdigest(signature)[..7]
203
+
204
+ IfBlock.new(AppArgs[0] == byte(selector)) do
205
+ callsub(meth[:name])
206
+ approve
207
+ end
208
+ end
209
+ end
210
+
179
211
  def generate_method_source(name, definition)
180
212
  new_source = rewrite(definition.source, method_rewriter: true)
181
213
 
@@ -211,7 +243,8 @@ module TEALrb
211
243
  puts ''
212
244
  end
213
245
 
214
- [CommentRewriter, ComparisonRewriter, WhileRewriter, IfRewriter, OpRewriter, AssignRewriter].each do |rw|
246
+ [CommentRewriter, ComparisonRewriter, WhileRewriter, InlineIfRewriter, IfRewriter, OpRewriter,
247
+ AssignRewriter].each do |rw|
215
248
  string = rewrite_with_rewriter(string, rw)
216
249
  end
217
250
 
@@ -227,7 +260,7 @@ module TEALrb
227
260
  end
228
261
 
229
262
  def eval_tealrb(s, debug_context:)
230
- pre_teal = Array.new @teal
263
+ pre_teal = Array.new TEAL.instance
231
264
 
232
265
  if self.class.debug
233
266
  puts "DEBUG: Evaluating the following code (#{debug_context}):"
@@ -239,13 +272,13 @@ module TEALrb
239
272
 
240
273
  if self.class.debug
241
274
  puts "DEBUG: Resulting TEAL (#{debug_context}):"
242
- puts Array.new(@teal) - pre_teal
275
+ puts Array.new(TEAL.instance) - pre_teal
243
276
  puts ''
244
277
  end
245
278
  rescue SyntaxError, StandardError => e
246
279
  @eval_tealrb_rescue_count ||= 0
247
280
 
248
- eval_locations = e.backtrace.select {_1[/\(eval\)/]}
281
+ eval_locations = e.backtrace.select { _1[/\(eval\)/] }
249
282
  error_line = eval_locations[@eval_tealrb_rescue_count].split(':')[1].to_i
250
283
 
251
284
  warn "'#{e}' when evaluating transpiled TEALrb source" if @eval_tealrb_rescue_count.zero?
@@ -6,39 +6,38 @@ module TEALrb
6
6
  attr_accessor :id
7
7
  end
8
8
 
9
- @id = {}.compare_by_identity
9
+ @id = 0
10
10
 
11
- def initialize(teal, _cond, &blk)
12
- self.class.id[teal] ||= 0
13
- @teal = teal
11
+ def initialize(_cond, &blk)
12
+ self.class.id ||= 0
14
13
  @else_count = 0
15
- @id = self.class.id[@teal]
14
+ @id = self.class.id
16
15
  @end_label = "if#{@id}_end:"
17
16
 
18
- self.class.id[@teal] += 1
17
+ self.class.id += 1
19
18
 
20
- @teal << "bz if#{@id}_else0"
19
+ TEAL.instance << "bz if#{@id}_else0"
21
20
  blk.call
22
- @teal << "b if#{@id}_end"
23
- @teal << "if#{@id}_else0:"
24
- @teal << @end_label
21
+ TEAL.instance << "b if#{@id}_end"
22
+ TEAL.instance << "if#{@id}_else0:"
23
+ TEAL.instance << @end_label
25
24
  end
26
25
 
27
26
  def elsif(_cond, &blk)
28
27
  @else_count += 1
29
- @teal.delete @end_label
30
- @teal << "bz if#{@id}_else#{@else_count}"
28
+ TEAL.instance.delete @end_label
29
+ TEAL.instance << "bz if#{@id}_else#{@else_count}"
31
30
  blk.call
32
- @teal << "b if#{@id}_end"
33
- @teal << "if#{@id}_else#{@else_count}:"
34
- @teal << @end_label
31
+ TEAL.instance << "b if#{@id}_end"
32
+ TEAL.instance << "if#{@id}_else#{@else_count}:"
33
+ TEAL.instance << @end_label
35
34
  self
36
35
  end
37
36
 
38
37
  def else(&blk)
39
- @teal.delete @end_label
38
+ TEAL.instance.delete @end_label
40
39
  blk.call
41
- @teal << @end_label
40
+ TEAL.instance << @end_label
42
41
  end
43
42
  end
44
43
  end