tealrb 0.6.0 → 0.9.0

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