tealrb 0.11.0 → 0.12.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 +4 -4
- data/lib/tealrb/abi.rb +1 -1
- data/lib/tealrb/account.rb +78 -0
- data/lib/tealrb/algod.rb +19 -0
- data/lib/tealrb/app.rb +132 -0
- data/lib/tealrb/app_args.rb +10 -0
- data/lib/tealrb/asset.rb +106 -0
- data/lib/tealrb/box.rb +17 -0
- data/lib/tealrb/byte_opcodes.rb +13 -0
- data/lib/tealrb/contract.rb +332 -121
- data/lib/tealrb/enums.rb +45 -0
- data/lib/tealrb/global.rb +94 -0
- data/lib/tealrb/group_txn.rb +42 -0
- data/lib/tealrb/if_block.rb +17 -24
- data/lib/tealrb/inner_txn.rb +95 -0
- data/lib/tealrb/local.rb +27 -0
- data/lib/tealrb/logs.rb +10 -0
- data/lib/tealrb/maybe_ops.rb +96 -0
- data/lib/tealrb/opcode_type.rb +31 -0
- data/lib/tealrb/opcodes.rb +541 -260
- data/lib/tealrb/rewriters.rb +71 -66
- data/lib/tealrb/scratch.rb +5 -4
- data/lib/tealrb/this_txn.rb +13 -0
- data/lib/tealrb/txn_fields.rb +333 -0
- data/lib/tealrb.rb +47 -18
- metadata +47 -3
- data/lib/tealrb/opcode_modules.rb +0 -904
data/lib/tealrb/contract.rb
CHANGED
@@ -3,81 +3,104 @@
|
|
3
3
|
module TEALrb
|
4
4
|
class Contract
|
5
5
|
include TEALrb
|
6
|
-
include Opcodes
|
7
|
-
include
|
6
|
+
include Opcodes::TEALOpcodes
|
7
|
+
include MaybeOps
|
8
|
+
include ByteOpcodes
|
8
9
|
include ABI
|
9
10
|
include Rewriters
|
11
|
+
include Enums
|
10
12
|
|
11
|
-
|
13
|
+
alias global_opcode global
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
:disable_abi_routing, :method_hashes
|
15
|
+
attr_reader :eval_location
|
16
|
+
attr_accessor :teal, :if_count
|
16
17
|
|
17
|
-
|
18
|
+
class << self
|
19
|
+
attr_accessor :subroutines, :version, :abi_interface, :debug,
|
20
|
+
:disable_abi_routing, :method_hashes, :src_map
|
18
21
|
|
19
22
|
def inherited(klass)
|
20
23
|
klass.version = 6
|
21
24
|
klass.subroutines = {}
|
22
|
-
klass.teal_methods = {}
|
23
25
|
klass.abi_interface = ABI::ABIDescription.new
|
24
26
|
klass.abi_interface.name = klass.to_s
|
25
27
|
klass.method_hashes = []
|
26
28
|
klass.debug = false
|
27
29
|
klass.disable_abi_routing = false
|
28
|
-
|
30
|
+
klass.src_map = true
|
29
31
|
super
|
30
32
|
end
|
31
33
|
|
32
34
|
def parse(klass)
|
33
35
|
YARD::Tags::Library.define_tag('ABI Method', :abi)
|
34
36
|
YARD::Tags::Library.define_tag('Subroutine', :subroutine)
|
35
|
-
YARD::Tags::Library.define_tag('
|
37
|
+
YARD::Tags::Library.define_tag('OnCompletes', :on_completion)
|
38
|
+
YARD::Tags::Library.define_tag('Create', :create)
|
36
39
|
|
37
40
|
YARD.parse Object.const_source_location(klass.to_s).first
|
38
41
|
|
42
|
+
parsed_methods = {}
|
39
43
|
YARD::Registry.all.each do |y|
|
40
44
|
next unless y.type == :method
|
41
|
-
next unless
|
45
|
+
next unless klass.instance_methods.include? y.name
|
46
|
+
next if y.parent.type == :class && y.parent.to_s != klass.to_s
|
42
47
|
|
43
|
-
|
48
|
+
if parsed_methods.keys.include? y.name
|
49
|
+
raise "#{y.name} defined in two locations: \n #{parsed_methods[y.name]}\n #{y.file}:#{y.line}"
|
50
|
+
end
|
44
51
|
|
45
|
-
|
46
|
-
method_hash = { name: y.name.to_s, desc: y.base_docstring, args: [], returns: { type: 'void' } }
|
52
|
+
parsed_methods[y.name] = "#{y.file}:#{y.line}"
|
47
53
|
|
48
|
-
|
49
|
-
|
54
|
+
tags = y.tags.map(&:tag_name)
|
55
|
+
|
56
|
+
next unless tags.include?('abi') || tags.include?('subroutine')
|
50
57
|
|
51
|
-
|
58
|
+
method_hash = { name: y.name.to_s, desc: y.base_docstring, args: [], returns: { type: 'void' },
|
59
|
+
on_completion: ['NoOp'], create: y.has_tag?('create') }
|
52
60
|
|
53
|
-
|
54
|
-
|
61
|
+
y.tags.each do |t|
|
62
|
+
method_hash[:returns] = { type: t.types&.first&.downcase } if t.tag_name == 'return'
|
55
63
|
|
56
|
-
|
64
|
+
method_hash[:on_completion] = t.text[1..-2].split(',').map(&:strip) if t.tag_name == 'on_completion'
|
65
|
+
next unless t.tag_name == 'param'
|
57
66
|
|
58
|
-
|
59
|
-
elsif tags.include? 'teal'
|
60
|
-
klass.teal_methods[y.name.to_s] = y
|
67
|
+
method_hash[:args] << { name: t.name, type: t.types&.first&.downcase, desc: t.text }
|
61
68
|
end
|
69
|
+
|
70
|
+
klass.method_hashes << method_hash
|
71
|
+
|
72
|
+
klass.abi_interface.add_method(**method_hash) if tags.include? 'abi'
|
62
73
|
end
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
77
|
+
TEALrb::Opcodes::BINARY_OPCODE_METHOD_MAPPING.each do |meth, opcode|
|
78
|
+
define_method(meth) do |other|
|
79
|
+
@contract.send(opcode, self, other)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
TEALrb::Opcodes::UNARY_OPCODE_METHOD_MAPPING.each do |meth, opcode|
|
84
|
+
define_method(meth) do
|
85
|
+
@contract.send(opcode, self)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
66
89
|
# sets the `#pragma version`, defines teal methods, and defines subroutines
|
67
90
|
def initialize
|
68
|
-
|
69
|
-
|
70
|
-
@
|
91
|
+
self.class.parse(self.class)
|
92
|
+
|
93
|
+
@teal = TEAL.new ["#pragma version #{self.class.version}"], self
|
94
|
+
@scratch = Scratch.new self
|
71
95
|
|
72
|
-
|
96
|
+
@contract = self
|
97
|
+
@if_count = 0
|
73
98
|
|
74
99
|
self.class.method_hashes.each do |mh|
|
75
100
|
define_subroutine(mh[:name], method(mh[:name]))
|
76
101
|
end
|
77
102
|
|
78
|
-
|
79
|
-
define_teal_method(name, definition)
|
80
|
-
end
|
103
|
+
compile
|
81
104
|
end
|
82
105
|
|
83
106
|
VOID_OPS = %w[assert err return app_global_put b bnz bz store
|
@@ -85,47 +108,209 @@ module TEALrb
|
|
85
108
|
log itxn_submit itxn_next].freeze
|
86
109
|
|
87
110
|
def teal_source
|
88
|
-
|
111
|
+
@teal.compact.join("\n")
|
112
|
+
end
|
89
113
|
|
90
|
-
|
91
|
-
|
114
|
+
def account(_account = nil)
|
115
|
+
@account ||= Account.new self
|
116
|
+
end
|
92
117
|
|
93
|
-
|
118
|
+
alias accounts account
|
94
119
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
120
|
+
def app(_app = nil)
|
121
|
+
@app ||= App.new self
|
122
|
+
end
|
123
|
+
|
124
|
+
alias apps app
|
125
|
+
|
126
|
+
def asset(_asset = nil)
|
127
|
+
@asset ||= Asset.new self
|
128
|
+
end
|
129
|
+
|
130
|
+
alias assets asset
|
131
|
+
|
132
|
+
def group_txn(_group_txn = nil)
|
133
|
+
@group_txn ||= GroupTxn.new self
|
134
|
+
end
|
135
|
+
|
136
|
+
alias group_txns group_txn
|
137
|
+
|
138
|
+
def global(field = nil, *_args)
|
139
|
+
if field
|
140
|
+
global_opcode(field)
|
141
|
+
else
|
142
|
+
@global ||= Global.new self
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def this_txn
|
147
|
+
ThisTxn.new self
|
148
|
+
end
|
149
|
+
|
150
|
+
def box
|
151
|
+
Box.new self
|
152
|
+
end
|
153
|
+
|
154
|
+
def inner_txn
|
155
|
+
InnerTxn.new self
|
156
|
+
end
|
157
|
+
|
158
|
+
def logs
|
159
|
+
Logs.new self
|
160
|
+
end
|
161
|
+
|
162
|
+
def app_args
|
163
|
+
AppArgs.new self
|
164
|
+
end
|
165
|
+
|
166
|
+
def local
|
167
|
+
Local.new self
|
168
|
+
end
|
169
|
+
|
170
|
+
def txn_type
|
171
|
+
TxnType.new self
|
172
|
+
end
|
173
|
+
|
174
|
+
def generate_source_map(src)
|
175
|
+
last_location = nil
|
176
|
+
src_map_hash = {}
|
177
|
+
|
178
|
+
src.each_line.with_index do |ln, i|
|
179
|
+
if ln[/src_map:/]
|
180
|
+
last_location = ln[/(?<=src_map:)\S+/]
|
181
|
+
next
|
102
182
|
end
|
183
|
+
|
184
|
+
src_map_hash[i + 1] ||= { location: last_location } if last_location
|
103
185
|
end
|
104
186
|
|
105
|
-
|
106
|
-
|
187
|
+
compile_response = Algod.new.compile(src)
|
188
|
+
|
189
|
+
case compile_response.status
|
190
|
+
when 400
|
191
|
+
msg = JSON.parse(compile_response.body)['message']
|
192
|
+
e_msg = StringIO.new
|
193
|
+
e_msg.puts 'Error(s) while attempting to compile TEAL'
|
194
|
+
msg.each_line do |ln|
|
195
|
+
teal_line = ln.split(':').first.to_i
|
196
|
+
ln_msg = ln.split(':')[1..].join(':').strip
|
197
|
+
next if ln_msg == '"0"'
|
198
|
+
|
199
|
+
if src_map_hash[teal_line]
|
200
|
+
e_msg.puts " #{teal_line} - #{src_map_hash[teal_line][:location]}: #{ln_msg}"
|
201
|
+
else
|
202
|
+
e_msg.puts " #{ln}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
raise e_msg.string
|
206
|
+
when 200
|
207
|
+
json_body = JSON.parse(compile_response.body)
|
208
|
+
pc_mapping = json_body['sourcemap']['mapping']
|
209
|
+
|
210
|
+
pc_array = pc_mapping.split(';').map do |v|
|
211
|
+
SourceMap::VLQ.decode_array(v)[2]
|
212
|
+
end
|
213
|
+
|
214
|
+
last_line = 1
|
215
|
+
|
216
|
+
line_to_pc = {}
|
217
|
+
pc_to_line = {}
|
218
|
+
pc_array.each_with_index do |line_delta, pc|
|
219
|
+
last_line += line_delta.to_i
|
220
|
+
|
221
|
+
next if last_line == 1
|
222
|
+
|
223
|
+
line_to_pc[last_line] ||= []
|
224
|
+
line_to_pc[last_line] << pc
|
225
|
+
pc_to_line[pc] = last_line
|
226
|
+
end
|
227
|
+
|
228
|
+
line_to_pc.each do |line, pcs|
|
229
|
+
src_map_hash[line][:pcs] = pcs if src_map_hash[line]
|
230
|
+
end
|
107
231
|
end
|
108
232
|
|
109
|
-
|
233
|
+
src_map_hash
|
110
234
|
end
|
111
235
|
|
112
|
-
|
113
|
-
|
114
|
-
|
236
|
+
def dump(directory = Dir.pwd, name: self.class.to_s.downcase, abi: true, src_map: true)
|
237
|
+
src = formatted_teal
|
238
|
+
|
239
|
+
File.write(File.join(directory, "#{name}.teal"), src)
|
240
|
+
File.write(File.join(directory, "#{name}.abi.json"), JSON.pretty_generate(abi_hash)) if abi
|
241
|
+
|
242
|
+
return unless src_map
|
243
|
+
|
244
|
+
src_map_json = JSON.pretty_generate(generate_source_map(src))
|
245
|
+
File.write(File.join(directory, "#{name}.src_map.json"), src_map_json)
|
115
246
|
end
|
116
247
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
# @return [nil]
|
121
|
-
def define_teal_method(name, definition)
|
122
|
-
new_source = generate_method_source(name, definition)
|
248
|
+
def formatted_teal
|
249
|
+
new_lines = []
|
250
|
+
comments = []
|
123
251
|
|
124
|
-
|
125
|
-
|
252
|
+
@teal.compact.each do |ln|
|
253
|
+
ln = ln.strip
|
254
|
+
|
255
|
+
next if ln.empty?
|
256
|
+
|
257
|
+
if ln[/^#pragma/]
|
258
|
+
new_lines << { text: ln, void: true, comments: comments }
|
259
|
+
comments = []
|
260
|
+
elsif ln[%r{^//}]
|
261
|
+
comments << ln
|
262
|
+
else
|
263
|
+
op = ln.split.first
|
264
|
+
label_regex = %r{\S+:($| //)}
|
265
|
+
|
266
|
+
label_type = label_number = label_end = nil
|
267
|
+
|
268
|
+
if ln[label_regex]
|
269
|
+
label_type = ln[/^if/] || ln[/^while/]
|
270
|
+
label_number = ln[/(?<=^if)\d+/] || ln[/(?<=^while)\d+/]
|
271
|
+
label_end = ln[/_end:/]
|
272
|
+
end
|
273
|
+
|
274
|
+
new_lines << { text: ln, void: VOID_OPS.include?(op), comments: comments, label: ln[label_regex],
|
275
|
+
label_type: label_type, label_number: label_number, label_end: label_end }
|
276
|
+
comments = []
|
277
|
+
end
|
126
278
|
end
|
127
279
|
|
128
|
-
|
280
|
+
output = []
|
281
|
+
indent_level = 0
|
282
|
+
current_labels = { 'while' => [], 'if' => [] }
|
283
|
+
|
284
|
+
new_lines.each do |ln|
|
285
|
+
indent_level = 1 if ln[:label] && indent_level.zero? && !ln[:label_type]
|
286
|
+
|
287
|
+
if ln[:label_type]
|
288
|
+
indent_level += 1 unless current_labels[ln[:label_type]].include?(ln[:label_number])
|
289
|
+
current_labels[ln[:label_type]] << ln[:label_number]
|
290
|
+
end
|
291
|
+
|
292
|
+
ln_indent_level = indent_level
|
293
|
+
ln_indent_level -= 1 if ln[:label]
|
294
|
+
|
295
|
+
output << '' if !output.last&.empty? && (ln[:label] || ln[:comments].any?)
|
296
|
+
|
297
|
+
ln[:comments].each { output << (("\t" * ln_indent_level) + _1) }
|
298
|
+
output << (("\t" * ln_indent_level) + ln[:text])
|
299
|
+
|
300
|
+
output << '' if ln[:void] && !output.last.empty?
|
301
|
+
|
302
|
+
next unless ln[:label_end]
|
303
|
+
|
304
|
+
indent_level -= 1
|
305
|
+
current_labels[ln[:label_type]].delete ln[:label_number]
|
306
|
+
end
|
307
|
+
|
308
|
+
output.join("\n")
|
309
|
+
end
|
310
|
+
|
311
|
+
# return the input without transpiling to TEAL
|
312
|
+
def rb(input)
|
313
|
+
input
|
129
314
|
end
|
130
315
|
|
131
316
|
# defines a TEAL subroutine
|
@@ -133,11 +318,15 @@ module TEALrb
|
|
133
318
|
# @param definition [Lambda, Proc, UnboundMethod] the method definition
|
134
319
|
# @return [nil]
|
135
320
|
def define_subroutine(name, definition)
|
321
|
+
return if method(name).source_location.first == __FILE__
|
322
|
+
|
323
|
+
@eval_location = method(name).source_location
|
324
|
+
|
136
325
|
define_singleton_method(name) do |*_args|
|
137
326
|
callsub(name)
|
138
327
|
end
|
139
328
|
|
140
|
-
|
329
|
+
@teal << 'b main' unless @teal.include? 'b main'
|
141
330
|
|
142
331
|
label(name) # add teal label
|
143
332
|
|
@@ -161,18 +350,17 @@ module TEALrb
|
|
161
350
|
def comment(content, inline: false)
|
162
351
|
content = " #{content}" unless content[0] == ' '
|
163
352
|
if inline
|
164
|
-
last_line =
|
165
|
-
|
353
|
+
last_line = @teal.pop
|
354
|
+
@teal << "#{last_line} //#{content}"
|
166
355
|
else
|
167
|
-
|
168
|
-
TEAL.instance << "//#{content}"
|
356
|
+
@teal << "//#{content}"
|
169
357
|
end
|
170
358
|
end
|
171
359
|
|
172
360
|
# inserts a string into TEAL source
|
173
361
|
# @param string [String] the string to insert
|
174
362
|
def placeholder(string)
|
175
|
-
|
363
|
+
@teal << string
|
176
364
|
end
|
177
365
|
|
178
366
|
# the hash of the abi description
|
@@ -191,29 +379,52 @@ module TEALrb
|
|
191
379
|
# transpiles #main and routes abi methods. To disable abi routing, set `@disable_abi_routing` to true in your
|
192
380
|
# Contract subclass
|
193
381
|
def compile
|
194
|
-
|
382
|
+
@teal << 'main:' if @teal.include? 'b main'
|
195
383
|
route_abi_methods unless self.class.disable_abi_routing
|
196
|
-
|
384
|
+
return unless respond_to? :main
|
385
|
+
|
386
|
+
@eval_location = method(:main).source_location
|
387
|
+
|
388
|
+
eval_tealrb(
|
389
|
+
rewrite(
|
390
|
+
method(:main).source,
|
391
|
+
method_rewriter: true
|
392
|
+
),
|
393
|
+
debug_context: 'main'
|
394
|
+
)
|
395
|
+
end
|
396
|
+
|
397
|
+
def main
|
398
|
+
nil
|
399
|
+
end
|
400
|
+
|
401
|
+
def compiled_program
|
402
|
+
compile_response = Algod.new.compile(formatted_teal)
|
403
|
+
|
404
|
+
generate_source_map(formatted_teal) if compile_response.status != 200
|
405
|
+
|
406
|
+
JSON.parse(compile_response.body)['result']
|
197
407
|
end
|
198
408
|
|
199
409
|
private
|
200
410
|
|
201
411
|
def route_abi_methods
|
202
|
-
self.class.abi_interface.methods.
|
412
|
+
self.class.abi_interface.methods.each_with_index do |meth, i|
|
203
413
|
signature = "#{meth[:name]}(#{meth[:args].map { _1[:type] }.join(',')})#{meth[:returns][:type]}"
|
204
414
|
selector = OpenSSL::Digest.new('SHA512-256').hexdigest(signature)[..7]
|
205
415
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
416
|
+
app_args[int(0)] == byte(selector) # rubocop:disable Lint/Void
|
417
|
+
bz("abi_routing#{i}")
|
418
|
+
callsub(meth[:name])
|
419
|
+
approve
|
420
|
+
label("abi_routing#{i}")
|
210
421
|
end
|
211
422
|
end
|
212
423
|
|
213
424
|
def generate_method_source(name, definition)
|
214
425
|
new_source = rewrite(definition.source, method_rewriter: true)
|
215
426
|
|
216
|
-
pre_string =
|
427
|
+
pre_string = []
|
217
428
|
|
218
429
|
scratch_names = []
|
219
430
|
definition.parameters.reverse.each_with_index do |param, _i|
|
@@ -221,17 +432,17 @@ module TEALrb
|
|
221
432
|
scratch_name = [name, param_name].map(&:to_s).join(': ')
|
222
433
|
scratch_names << scratch_name
|
223
434
|
|
224
|
-
pre_string
|
225
|
-
pre_string
|
435
|
+
pre_string << "@scratch.store('#{scratch_name}')"
|
436
|
+
pre_string << "#{param_name} = -> { @scratch['#{scratch_name}'] }"
|
226
437
|
end
|
227
438
|
|
228
|
-
"#{pre_string.
|
439
|
+
"#{pre_string.join(';')};#{new_source}"
|
229
440
|
end
|
230
441
|
|
231
442
|
def generate_subroutine_source(definition, method_hash)
|
232
443
|
new_source = rewrite(definition.source, method_rewriter: true)
|
233
444
|
|
234
|
-
pre_string =
|
445
|
+
pre_string = []
|
235
446
|
|
236
447
|
scratch_names = []
|
237
448
|
|
@@ -245,29 +456,42 @@ module TEALrb
|
|
245
456
|
account_param_index = 0
|
246
457
|
args_index = 0
|
247
458
|
|
459
|
+
method_hash[:on_completion].each_with_index do |oc, i|
|
460
|
+
this_txn.on_completion
|
461
|
+
int(oc)
|
462
|
+
equal
|
463
|
+
boolean_or unless i.zero?
|
464
|
+
end
|
465
|
+
assert
|
466
|
+
|
467
|
+
assert(this_txn.application_id == (int(0))) if method_hash[:create]
|
468
|
+
|
248
469
|
if abi_hash['methods'].find { _1[:name] == method_hash[:name].to_s }
|
249
470
|
definition.parameters.each_with_index do |param, i|
|
250
471
|
param_name = param.last
|
251
472
|
|
252
|
-
scratch_name = "#{definition.original_name}: #{param_name} [#{arg_types[i] || 'any'}] #{
|
253
|
-
|
254
|
-
end}"
|
473
|
+
scratch_name = "#{definition.original_name}: #{param_name} [#{arg_types[i] || 'any'}] #{
|
474
|
+
args[i][:desc] if args[i]}"
|
255
475
|
scratch_names << scratch_name
|
256
476
|
|
257
|
-
|
258
|
-
|
477
|
+
type = arg_types[i]&.downcase
|
478
|
+
|
479
|
+
if txn_types.include? type
|
480
|
+
@scratch[scratch_name] = group_txns[this_txn.group_index.subtract int(txn_params)]
|
259
481
|
txn_params -= 1
|
260
|
-
elsif
|
261
|
-
|
262
|
-
elsif
|
263
|
-
|
264
|
-
elsif
|
265
|
-
|
482
|
+
elsif type == 'application'
|
483
|
+
@scratch[scratch_name] = apps[app_param_index += 1]
|
484
|
+
elsif type == 'asset'
|
485
|
+
@scratch[scratch_name] = assets[asset_param_index += 1]
|
486
|
+
elsif type == 'account'
|
487
|
+
@scratch[scratch_name] = accounts[account_param_index += 1]
|
488
|
+
elsif type == 'uint64'
|
489
|
+
@scratch[scratch_name] = btoi(app_args[args_index += 1])
|
266
490
|
else
|
267
|
-
|
491
|
+
@scratch[scratch_name] = app_args[args_index += 1]
|
268
492
|
end
|
269
493
|
|
270
|
-
pre_string
|
494
|
+
pre_string << "#{param_name} = -> {@scratch['#{scratch_name}'] }"
|
271
495
|
end
|
272
496
|
|
273
497
|
else
|
@@ -277,34 +501,35 @@ module TEALrb
|
|
277
501
|
definition.parameters.reverse.each_with_index do |param, i|
|
278
502
|
param_name = param.last
|
279
503
|
|
280
|
-
scratch_name = "#{definition.original_name}: #{param_name} [#{arg_types[i] || 'any'}] #{
|
281
|
-
|
282
|
-
end}"
|
504
|
+
scratch_name = "#{definition.original_name}: #{param_name} [#{arg_types[i] || 'any'}] #{
|
505
|
+
args[i][:desc] if args[i]}"
|
283
506
|
scratch_names << scratch_name
|
284
507
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
elsif
|
290
|
-
|
291
|
-
elsif
|
292
|
-
|
508
|
+
type = arg_types[i]&.downcase
|
509
|
+
|
510
|
+
if txn_types.include? type
|
511
|
+
@scratch[scratch_name] = group_txn
|
512
|
+
elsif type == 'application'
|
513
|
+
@scratch[scratch_name] = application
|
514
|
+
elsif type == 'asset'
|
515
|
+
@scratch[scratch_name] = asset
|
516
|
+
elsif type == 'account'
|
517
|
+
@scratch[scratch_name] = account
|
293
518
|
else
|
294
|
-
|
519
|
+
@scratch.store(scratch_name)
|
295
520
|
end
|
296
521
|
|
297
|
-
pre_string
|
522
|
+
pre_string << "#{param_name} = -> { @scratch['#{scratch_name}'] }"
|
298
523
|
end
|
299
524
|
|
300
525
|
end
|
301
526
|
|
302
|
-
"#{pre_string.
|
527
|
+
"#{pre_string.join(';')};#{new_source}"
|
303
528
|
end
|
304
529
|
|
305
530
|
def rewrite_with_rewriter(string, rewriter)
|
306
531
|
process_source = RuboCop::ProcessedSource.new(string, RUBY_VERSION[/\d\.\d/].to_f)
|
307
|
-
rewriter.new.rewrite(process_source)
|
532
|
+
rewriter.new.rewrite(process_source, self)
|
308
533
|
end
|
309
534
|
|
310
535
|
def rewrite(string, method_rewriter: false)
|
@@ -315,7 +540,7 @@ module TEALrb
|
|
315
540
|
end
|
316
541
|
|
317
542
|
[CommentRewriter, ComparisonRewriter, WhileRewriter, InlineIfRewriter, IfRewriter, OpRewriter,
|
318
|
-
AssignRewriter
|
543
|
+
AssignRewriter].each do |rw|
|
319
544
|
string = rewrite_with_rewriter(string, rw)
|
320
545
|
end
|
321
546
|
|
@@ -331,7 +556,7 @@ module TEALrb
|
|
331
556
|
end
|
332
557
|
|
333
558
|
def eval_tealrb(s, debug_context:)
|
334
|
-
pre_teal = Array.new
|
559
|
+
pre_teal = Array.new @teal
|
335
560
|
|
336
561
|
if self.class.debug
|
337
562
|
puts "DEBUG: Evaluating the following code (#{debug_context}):"
|
@@ -343,7 +568,7 @@ module TEALrb
|
|
343
568
|
|
344
569
|
if self.class.debug
|
345
570
|
puts "DEBUG: Resulting TEAL (#{debug_context}):"
|
346
|
-
puts Array.new(
|
571
|
+
puts Array.new(@teal) - pre_teal
|
347
572
|
puts ''
|
348
573
|
end
|
349
574
|
rescue SyntaxError, StandardError => e
|
@@ -354,23 +579,9 @@ module TEALrb
|
|
354
579
|
error_line = eval_locations[@eval_tealrb_rescue_count].split(':')[1].to_i
|
355
580
|
end
|
356
581
|
|
357
|
-
|
358
|
-
|
359
|
-
warn "Backtrace location (#{@eval_tealrb_rescue_count + 1} / #{eval_locations.size}):"
|
360
|
-
|
361
|
-
@eval_tealrb_rescue_count += 1
|
362
|
-
|
363
|
-
s.lines.each_with_index do |line, i|
|
364
|
-
line_num = i + 1
|
365
|
-
if error_line == line_num
|
366
|
-
warn "=> #{line_num}: #{line}"
|
367
|
-
else
|
368
|
-
warn " #{line_num}: #{line}"
|
369
|
-
end
|
370
|
-
end
|
582
|
+
msg = "#{@eval_location.first}:#{error_line + @eval_location.last}"
|
371
583
|
|
372
|
-
|
373
|
-
raise e
|
584
|
+
raise e, "#{msg}: #{e}"
|
374
585
|
end
|
375
586
|
end
|
376
587
|
end
|