tealrb 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|