sbuilder-ethereum 0.0.6

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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/VERSION +1 -0
  3. data/lib/mixer/decl_ref.rb +19 -0
  4. data/lib/mixer/domain_ref.rb +18 -0
  5. data/lib/mixer/scope.rb +92 -0
  6. data/lib/mixer/scoped.rb +17 -0
  7. data/lib/mixer/symbol_ref.rb +16 -0
  8. data/lib/mixer/type_symbol.rb +75 -0
  9. data/lib/plugin/plugin.rb +332 -0
  10. data/lib/resources/correctness/accouns_type.tla +1 -0
  11. data/lib/resources/correctness/accounts_unique.tla +2 -0
  12. data/lib/resources/correctness/accounts_valid.tla +2 -0
  13. data/lib/resources/correctness/storage_root_unique.tla +2 -0
  14. data/lib/resources/correctness/total_value.tla +1 -0
  15. data/lib/resources/eth/accounts_state.tla +2 -0
  16. data/lib/resources/eth/accounts_temp.tla +2 -0
  17. data/lib/resources/eth/address_free.tla +2 -0
  18. data/lib/resources/eth/mined_state.tla +1 -0
  19. data/lib/resources/eth/storageRoot.tla +1 -0
  20. data/lib/resources/eth/storageRoot_temp.tla +1 -0
  21. data/lib/resources/mine/mine_entry.tla +4 -0
  22. data/lib/resources/mine/mine_service.tla +22 -0
  23. data/lib/resources/operators/elementExists.tla +4 -0
  24. data/lib/resources/operators/gasPrice.tla +2 -0
  25. data/lib/resources/operators/gasValue.tla +2 -0
  26. data/lib/resources/operators/getElement.tla +5 -0
  27. data/lib/resources/operators/intrinsicGas.tla +4 -0
  28. data/lib/resources/operators/transactionGas.tla +4 -0
  29. data/lib/resources/operators/upFrontCost.tla +6 -0
  30. data/lib/resources/personal_newAccount/personal_newAccount_done.tla +14 -0
  31. data/lib/resources/personal_newAccount/personal_newAccount_entry.tla +10 -0
  32. data/lib/resources/personal_newAccount/personal_newAccount_service.tla +29 -0
  33. data/lib/resources/removed/sendTransaction_entry.tla +5 -0
  34. data/lib/resources/removed/sendTransaction_service.tla +36 -0
  35. data/lib/resources/removed/tst.tla +1 -0
  36. data/lib/resources/transaction/ethereum_service_done.tla +24 -0
  37. data/lib/resources/transaction/ethereum_service_pop.tla +24 -0
  38. data/lib/resources/transaction/ethereum_service_push.tla +14 -0
  39. data/lib/resources/transaction/ethereum_service_start.tla +13 -0
  40. data/lib/resources/transaction/status_fail.tla +1 -0
  41. data/lib/resources/transaction/status_ok.tla +1 -0
  42. data/lib/sbuilder-ethereum.rb +52 -0
  43. data/lib/sbuilder/compile.rb +163 -0
  44. data/lib/sbuilder/constants.rb +93 -0
  45. data/lib/sbuilder/exception.rb +22 -0
  46. data/lib/sbuilder/generate/sexp_processor_tla.rb +2674 -0
  47. data/lib/sbuilder/generate/tla_element_generator.rb +1206 -0
  48. data/lib/sbuilder/generate/tla_element_text.rb +703 -0
  49. data/lib/sbuilder/load.rb +119 -0
  50. data/lib/sbuilder/mustache/renderer.rb +152 -0
  51. data/lib/sbuilder/render.rb +141 -0
  52. data/lib/sbuilder/s.rb +21 -0
  53. data/lib/sbuilder/sexp_ast.rb +1378 -0
  54. data/lib/sbuilder/sexp_processor_api.rb +184 -0
  55. data/lib/sbuilder/sexp_processor_canonize.rb +326 -0
  56. data/lib/sbuilder/sexp_processor_dataflow.rb +461 -0
  57. data/lib/sbuilder/sexp_processor_ethereum.rb +127 -0
  58. data/lib/sbuilder/sexp_processor_need_to_canonize.rb +572 -0
  59. data/lib/sbuilder/sexp_processor_snippet.rb +154 -0
  60. data/lib/sbuilder/sexp_processor_symboltable1.rb +296 -0
  61. data/lib/sbuilder/sexp_processor_symboltable2.rb +175 -0
  62. data/lib/sbuilder/sexp_utils.rb +417 -0
  63. data/lib/utils/logger.rb +82 -0
  64. data/lib/utils/string_inject.rb +11 -0
  65. data/sbuilder-ethereum.gemspec +39 -0
  66. metadata +190 -0
@@ -0,0 +1,127 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ # A class allowing sbuilder ethereum to extend 'SexpProcessor'
5
+ # behaviour. (Possible candidate for extension env)
6
+
7
+ class SexpProcessorEthereum < SexpProcessor
8
+
9
+ PROGNAME = nil # progname for logger default class name
10
+ include MyLogger # mix logger
11
+
12
+ # @attr [Hash] options
13
+ # @option options [String] :log e.g. "WARN"
14
+ # @option options [String|STDOUT] :logfile e.g. STDOUT
15
+ attr_reader :options
16
+
17
+ # @attr [Logger] logger
18
+ attr_reader :logger
19
+
20
+ # ------------------------------------------------------------------
21
+ # @!group Contstruct and configure
22
+
23
+ def initialize( options={} )
24
+ super()
25
+
26
+ @options = options
27
+ @logger = getLogger( nil, options )
28
+
29
+ # Override defaults in parent class
30
+ self.strict = false
31
+
32
+ # Allow Sexp nodes to remain intact, see 'process_rest'
33
+ self.require_empty = false
34
+
35
+ # visitors just recurses - do not shift sexp (as sexp_processor default does)
36
+ self.default_method = :process_rest
37
+
38
+ # no warning needed when using default method
39
+ self.warn_on_default = false
40
+
41
+ end
42
+
43
+ # @!endgroup
44
+
45
+ # ------------------------------------------------------------------
46
+ # @!group Node rules
47
+
48
+ # @!endgroup
49
+
50
+ # ------------------------------------------------------------------
51
+ # @!group Visitor helpers
52
+
53
+ ##
54
+ # Process each element of #exp in turn.
55
+
56
+ # def process_until_empty exp
57
+ # until exp.empty?
58
+ # sexp = exp.shift
59
+ # process sexp if Sexp === sexp
60
+ # end
61
+ # s()
62
+ # end
63
+
64
+
65
+ ##
66
+ # Process each element of +exp+ in turn
67
+
68
+ def process_rest exp
69
+ pos = 0
70
+ ret = s()
71
+ until pos >= exp.length
72
+ sexp = exp[pos]
73
+ pos += 1
74
+ psexps = process( sexp ) if Sexp === sexp
75
+ if !psexps.nil? && psexps.sexp_type == :dummy
76
+ # :dummy get flattened
77
+ psexps.rest.each do |psexp|
78
+ ret << psexp
79
+ end
80
+ else # non-dummy sexp || nil sexp
81
+ ret << psexps unless psexps.nil?
82
+ end
83
+ end
84
+ ret
85
+ end
86
+
87
+
88
+ # Default operation: current node does not contribute to sexp,
89
+ # flatten it
90
+ def process_skip exp
91
+ ret = process_rest( exp )
92
+ return ret if ret.length == 0
93
+ return ret.first if ret.length == 1
94
+ raise <<-EOS
95
+ Expect child nodes to return s() or s( s(:any, ...)) -
96
+
97
+ When processing exp: #{exp}
98
+
99
+ process_rest returns: #{ret}
100
+
101
+ EOS
102
+ end
103
+
104
+ # Default operation: do nothing
105
+ def process_none exp
106
+ s()
107
+ end
108
+
109
+
110
+ def process_abort exp
111
+
112
+ raise <<-EOS
113
+ Implementation missing for #{exp}
114
+ EOS
115
+
116
+ end
117
+
118
+
119
+
120
+ # @!endgroup
121
+
122
+
123
+ end
124
+
125
+
126
+ end
127
+ end
@@ -0,0 +1,572 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ ##
5
+ #
6
+ # Add
7
+ # - constructor - if missing
8
+ # - balance - if missing
9
+ # - getter methods - if missing
10
+
11
+ class SexpProcessorNeedToCanonize < SexpProcessorEthereum
12
+
13
+ # ------------------------------------------------------------------
14
+ # @!group canonize operations
15
+
16
+ # @attr [Boolean] needConstructor
17
+ attr_reader :needConstructor
18
+
19
+ # @attr [String:Array] needVariableDeclarations, initialized
20
+ # with variable names, which will be added (unless they are defined)
21
+ attr_reader :needVariableDeclarations
22
+
23
+ # @attr [String:Array] neededGetters variable names missing
24
+ # getters, add entry each variable declation, and remove for
25
+ # each getter.
26
+ attr_reader :neededGetters
27
+
28
+ # @attr [Assignment:Array] assignmentOperatorSplits
29
+ attr_reader :assignmentOperatorSplits
30
+
31
+
32
+ # @attr [SexpAst:Array] functionCallsToSplit s(Block, Statement, FunctionCall)
33
+ attr_reader :functionCallsToSplit
34
+
35
+
36
+ # @attr [s(FunctionDef, s(s(:parameter, name,domain), s(:parameter, name, domain)]), ... )]
37
+ attr_reader :missing_request_parameters
38
+
39
+ # @attr [VariableDeclaration:Array] variable_declarations_without_name
40
+ attr_reader :variable_declarations_without_name
41
+
42
+ # @attr [s(Sexp(Literal), value ):Array]
43
+ attr_reader :map_literalValue
44
+
45
+ # @!endgroup
46
+
47
+ # @attr [Hash] optionss
48
+ attr_reader :options
49
+
50
+ # @!endgroup
51
+
52
+ # ------------------------------------------------------------------
53
+ # @!group Configs
54
+
55
+ # https://github.com/ethereum/wiki/wiki/Solidity-Features#contracts-inherit-all-members-from-address
56
+ #
57
+ # a contract type contains all members of the address type with
58
+ # the semantics applying to the contract's address, unless
59
+ # overwritten by the contract.
60
+ #
61
+ # Balance is hold in 'eth_accounts' not in eth_storageRoot
62
+ INHERITED_VARIABLE_DECLARATIONS = [
63
+ Constants::FIELD_NAME_ADDRESS,
64
+ # Constants::FIELD_NAME_BALANCE,
65
+ ]
66
+
67
+ ##
68
+ # Require 'expLiteral.type' to have TLA-value, if this is not the case
69
+ # check if 'expLiteral.value' is defined
70
+ LITERAL_MAPPINGS = {
71
+
72
+ # solc integer literals 'int_const 42', no rule to change
73
+ # value needed
74
+ /int_const/ => {
75
+ :rules => nil
76
+ },
77
+
78
+ # solc 'bool' is mapped to TLA-domain 'BOOLEAN' with values
79
+ # 'TRUE' and 'FALSE'
80
+ 'bool' => {
81
+ :rules => {
82
+ # TLA-value => solc value
83
+ 'TRUE' => 'true',
84
+ 'FALSE' => 'false',
85
+ }
86
+ }
87
+ }
88
+
89
+ # @!endgroup
90
+
91
+ # ------------------------------------------------------------------
92
+ # @!group Construct & configure
93
+
94
+ def initialize( options={} )
95
+ super( options )
96
+ logger.debug "#{__method__}: created" if logger.debug?
97
+
98
+ @options = options
99
+
100
+ # reset state
101
+ initIt
102
+
103
+ end
104
+
105
+ def initIt()
106
+ ##
107
+ logger.info "#{__method__} called"
108
+
109
+ # default - constructor should be added
110
+ @needConstructor = true
111
+
112
+ # default - no getters need
113
+ @neededGetters = []
114
+
115
+ # default - inherited variables should be added. NOTICE:
116
+ # clone here because later we are using
117
+ # needVariableDeclarations.delete opreation!!
118
+ @needVariableDeclarations = INHERITED_VARIABLE_DECLARATIONS.clone
119
+
120
+ # split assignment/conditional/.. with function calls
121
+ @functionCallsToSplit = []
122
+
123
+ # add: msg.value, msg.sender, etc. to FunctionDefinition
124
+ @missing_request_parameters = []
125
+
126
+ # invent a name: (function definition)
127
+ @variable_declarations_without_name = []
128
+
129
+ # map literal.value to tlavalue
130
+ @map_literalValue = []
131
+
132
+ # split assigment operator += etc.
133
+ @assignmentOperatorSplits = []
134
+
135
+ # currentCall initially nil
136
+ @currentCall = nil
137
+
138
+ end
139
+
140
+ # @!endgroup
141
+
142
+ # ------------------------------------------------------------------
143
+ # @!group scope support
144
+
145
+ # @attr [Contract] currentContract which currently processing
146
+ attr_accessor :currentContract
147
+
148
+ # @attr [FunctionDefinition] currentFunction
149
+ attr_accessor :currentFunction
150
+
151
+ # @attr [IfStatement] currentIf
152
+ attr_accessor :currentIf
153
+
154
+ # @attr [Block] currentBlock
155
+ attr_accessor :currentBlock
156
+
157
+ # @attr [IfStatement] currentAssign
158
+ attr_accessor :currentAssign
159
+
160
+ # @attr [FunctionCall] currentCall
161
+ attr_accessor :currentCall
162
+
163
+ # @attr [Sexp] s(s(:parameter, name domain), ...)
164
+ attr_accessor :request
165
+
166
+ # @attr [Sexp] s(s(:parameter, name domain), ...)
167
+ attr_accessor :response
168
+
169
+ def contracted( expContract )
170
+
171
+ self.currentContract = expContract
172
+ begin
173
+ yield
174
+ ensure
175
+ self.currentContract = nil
176
+ end
177
+ end
178
+
179
+ def functed( expFunctionDef )
180
+ self.currentFunction = expFunctionDef
181
+ begin
182
+ yield
183
+ ensure
184
+ self.currentFunction = nil
185
+ end
186
+
187
+ end
188
+
189
+ def funcCalled( exp )
190
+ self.currentCall = exp
191
+ begin
192
+ yield
193
+ ensure
194
+ self.currentCall = nil
195
+ end
196
+
197
+ end
198
+
199
+
200
+ def iffed( expIf )
201
+ prevIf = currentIf
202
+ self.currentIf = expIf
203
+ begin
204
+ yield
205
+ ensure
206
+ self.currentIf = prevIf
207
+ end
208
+
209
+ end
210
+
211
+ def blocked( expBlock )
212
+ prevBlock = currentBlock
213
+ self.currentBlock = expBlock
214
+ begin
215
+ yield
216
+ ensure
217
+ self.currentBlock = prevBlock
218
+ end
219
+
220
+ end
221
+
222
+ def assigned( expAssign )
223
+ prevAssign = currentAssign
224
+ self.currentAssign = expAssign
225
+ begin
226
+ yield
227
+ ensure
228
+ self.currentAssign = prevAssign
229
+ end
230
+
231
+ end
232
+
233
+
234
+
235
+ # @!endgroup
236
+
237
+ # ------------------------------------------------------------------
238
+ # @!group Rules triggering actions
239
+
240
+ # @return [Boolean] true if +expFunction+ is constructor for +currentContract+
241
+ def isConstructor( expFunction )
242
+ currentContract && expFunction.name == currentContract.name
243
+ end
244
+
245
+
246
+ # @!endgroup
247
+
248
+
249
+ # ------------------------------------------------------------------
250
+ # @!group Tree traversal
251
+
252
+ def process_GlobalScope( exp )
253
+ logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
254
+
255
+ # wrap
256
+ contracted( exp ) do
257
+ process_rest( exp )
258
+ end
259
+
260
+ end
261
+
262
+
263
+ def process_ContractDefinition( exp )
264
+ logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
265
+
266
+ # wrap
267
+ contracted( exp ) do
268
+
269
+ logger.debug "#{__method__}: start iterating FindVariableDeclarations for exp=#{exp}" if logger.debug?
270
+ FindVariableDeclarations.new( self, options ).process( exp )
271
+ FindMissingSetters.new( self, options ).process( exp )
272
+
273
+ process_rest( exp )
274
+ end
275
+ s()
276
+ end
277
+
278
+ ##
279
+ # see if it is a constructor - toggle if not
280
+ #
281
+ # - adds method #interfaceName
282
+ #
283
+ def process_FunctionDefinition( exp )
284
+ logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
285
+ if isConstructor( exp )
286
+ logger.info "#{__method__}: consructor already defined #{exp}"
287
+ @needConstructor = false
288
+ interfaceName = "#{currentContract.name}()"
289
+ else
290
+ interfaceName = "#{currentContract.name}(#{exp.name})"
291
+ end
292
+
293
+ if !exp.respond_to?( :interfaceName ) then
294
+ logger.info "#{__method__}: addeded method :interfaceName to return #{interfaceName}"
295
+ SexpUtils.defineInterfaceName( exp, interfaceName )
296
+ # exp.define_singleton_method( :interfaceName ) do
297
+ # interfaceName
298
+ # end
299
+ end
300
+
301
+ # parameter lists
302
+ functed( exp ) do
303
+
304
+ logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
305
+ formalParametersToFunction = exp.parameterList.parameters ? exp.parameterList.parameters.map { |varDecl| varDecl.name } : []
306
+
307
+ # should add parameters which are NOT found on current formal parameter list
308
+ parametersNeeds = TlaElementText.commonMsgProperties( 'request', isConstructor(exp)).
309
+ select { |par| !formalParametersToFunction.include?(par[1] ) }
310
+
311
+ if parametersNeeds.any?
312
+ logger.info "#{__method__}: parametersNeeds=#{parametersNeeds} in #{exp.name}"
313
+ @missing_request_parameters << s(exp, parametersNeeds )
314
+ end
315
+
316
+ # process function stmts
317
+ process_rest( exp )
318
+ end
319
+ s()
320
+ end
321
+
322
+ def process_Block( exp )
323
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
324
+
325
+ #wrap
326
+ blocked( exp ) do
327
+ process_rest( exp )
328
+ end
329
+ s()
330
+ end
331
+
332
+ ##
333
+ # Identify: 'if ( !msg.sender.send( msg.value ) )'
334
+ def process_IfStatement( exp )
335
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
336
+
337
+ # if
338
+ iffed( exp ) do
339
+ process( exp.condition )
340
+ end
341
+
342
+ # then
343
+ blocked( exp.then_branch ) do
344
+ process( exp.then_branch )
345
+ end
346
+
347
+ # else
348
+ if exp.else_branch
349
+ blocked( exp.else_branch ) do
350
+ process( exp.else_branch )
351
+ end
352
+ end
353
+ s()
354
+ end
355
+
356
+
357
+
358
+ ##
359
+ # Identify 'var = func()'
360
+ def process_ExpressionStatement( exp )
361
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
362
+ assigned( exp ) do
363
+ process_rest( exp )
364
+ end
365
+ s()
366
+ end
367
+
368
+ def process_FunctionCallReadReturn( exp )
369
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
370
+ # FunctionCallReadReturn indicates that canonzation has
371
+ # already taken place. no need to go down anymore
372
+ s()
373
+ end
374
+
375
+ def process_Assignment( exp )
376
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
377
+ if exp.operator != '='
378
+ logger.info "#{__method__}: split assignment #{exp}"
379
+ assignmentOperatorSplits << exp
380
+ end
381
+ process_rest( exp )
382
+ end
383
+
384
+ def process_FunctionCall( exp )
385
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
386
+
387
+ # split only fist level function in functionOnFunction -case
388
+ if currentAssign && currentCall.nil?
389
+ @functionCallsToSplit << s( currentBlock, currentAssign, exp )
390
+ logger.info "#{__method__}: function-call in assingment split #{currentAssign}"
391
+ elsif currentIf && currentCall.nil?
392
+ @functionCallsToSplit << s( currentBlock, currentIf, exp )
393
+ logger.info "#{__method__}: function-call in if split #{currentIf}"
394
+ end
395
+
396
+ funcCalled( exp ) do
397
+ process_rest( exp )
398
+ end
399
+ end
400
+
401
+ def process_Literal( exp )
402
+ logger.debug "#{__method__}: #{exp}" if logger.debug?
403
+ # should literal be remapped (e.g. true -> TRUE),
404
+ # no need to remap integers
405
+ tlaValue = checkLiteralMapping( exp )
406
+ if tlaValue
407
+ # add to task list
408
+ logger.info "#{__method__}: map-literal tlaValue=#{tlaValue} on #{exp}"
409
+
410
+ @map_literalValue << s(exp, tlaValue)
411
+ end
412
+ process_rest( exp )
413
+ end
414
+
415
+ # def match( parameter )
416
+ # matchRule.is_a?( String ) ? parameter.name == matchRule : (parameter.name =~ matchRule) != nil
417
+ # end
418
+
419
+
420
+ ##
421
+ # @return [Hash] mapper
422
+ # @option mapper [:Symbol] :rules defining mapping, nil if no mapping needed
423
+ private def findMapperHash( expLiteral )
424
+ mapperes = LITERAL_MAPPINGS
425
+ literalType = expLiteral.type.to_s
426
+ mapperes.each do |key,mapper|
427
+ # quit block && subroutine if found
428
+ return mapper if key.is_a?( String ) ? literalType == key : (literalType =~ key) != nil
429
+ end
430
+
431
+ nil
432
+ end
433
+
434
+ # @!endgroup
435
+
436
+ # ------------------------------------------------------------------
437
+ # @!group utils
438
+
439
+ ##
440
+ # Check if literal should be remapped, and return mapper suggesion
441
+ # @return [Hash] tlaValue
442
+ # @option tlaValue [String] key as solcValue
443
+ # @option tlaValue [String] value in tla
444
+ private def checkLiteralMapping( expLiteral )
445
+ logger.debug "#{__method__}: check in solc type '#{expLiteral.type}' that value '#{expLiteral.value}' valid for tla " if logger.debug?
446
+
447
+ #
448
+ mapperHash = findMapperHash( expLiteral )
449
+ logger.debug "#{__method__}: mapperHash=#{mapperHash}" if logger.debug?
450
+
451
+
452
+ # Must be known literal type
453
+ raise SbuilderEtherumException, "Unkown literal type '#{expLiteral.type}', supported types #{mapperHash.keys}" if mapperHash.nil?
454
+
455
+
456
+ # No need to map if no rules defined
457
+ return nil unless mapperHash[:rules]
458
+ # Literal value valid TLA value in :rules
459
+ return nil if mapperHash[:rules][expLiteral.value]
460
+
461
+ # Invert mapper table for 'epx.type' i.e map solc=>tla
462
+ reverseMapper = mapperHash[:rules].inject( {}){ |solc2tla,(tla,solc)| solc2tla[solc] = tla; solc2tla }
463
+
464
+ # use inverted mapper to find TLA-name,
465
+ tlaValue = reverseMapper[expLiteral.value]
466
+ raise SbuilderEtherumException, "Could not map literal value '#{expLiteral.value}' for #{expLiteral} using #{reverseMapper}" unless tlaValue
467
+ logger.info "#{__method__}: map literal value '#{expLiteral.value}' to TLA value '#{tlaValue}' in #{expLiteral}"
468
+ tlaValue
469
+
470
+ end
471
+
472
+
473
+ # @!endgroup
474
+
475
+ # ------------------------------------------------------------------
476
+ # @!group Specialized processeros
477
+
478
+ ##
479
+ # For each contract 'VariableDeclaration' remove in
480
+ # +needVariableDeclarations+, and add +neededGetters+.
481
+ #
482
+
483
+ class FindVariableDeclarations < SexpProcessorEthereum
484
+
485
+ # @attr [SexpProcessorNeedToCanonize] parent
486
+ attr_reader :parent
487
+
488
+ def initialize( parent, options={} )
489
+ super( options )
490
+ logger.debug "#{__method__}: created" if logger.debug?
491
+ @parent = parent
492
+ end
493
+
494
+
495
+ ##
496
+ # Actions: 1 ) add contract variables to
497
+ # +parent.neededGetters+, remove from
498
+ # +parent.needVariableDeclarations+ 2) if variable declation
499
+ # does not have a name
500
+ def process_VariableDeclaration( exp )
501
+ logger.debug "#{__method__}: exp=#{exp}, exp.parent=#{exp.parent}" if logger.debug?
502
+ # parent.gettersNeeded << exp
503
+
504
+ if !exp.name or exp.name.length == 0
505
+ logger.info "#{__method__}: variable declared without name #{exp}"
506
+ parent.variable_declarations_without_name << exp
507
+ end
508
+
509
+ if exp.parent && exp.parent.sexp_type == :ContractDefinition
510
+
511
+ logger.debug "#{__method__}: variable declaration for contract, exp=#{exp}" if logger.debug?
512
+
513
+ # contract variable declared - remove it form the list
514
+ deleted = parent.needVariableDeclarations.delete( exp.name )
515
+ logger.debug "#{__method__}: variable already declared #{deleted}" if logger.debug?
516
+
517
+ # each contact varibale decl should have a getter
518
+ parent.neededGetters << exp.name
519
+ end
520
+
521
+ s()
522
+ end
523
+
524
+ end
525
+
526
+ class FindMissingSetters < SexpProcessorEthereum
527
+
528
+ # @attr [SexpProcessorNeedToCanonize] parent
529
+ attr_reader :parent
530
+
531
+ def initialize( parent, options={} )
532
+ super( options )
533
+ logger.debug "#{__method__}: created" if logger.debug?
534
+ @parent = parent
535
+ end
536
+
537
+
538
+ ##
539
+ # remove from +parent.neededGetters+ if getter
540
+ def process_FunctionDefinition( exp )
541
+ logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
542
+
543
+ # if getXaaB --> XaaB (or nil)
544
+ getterForVariable = exp.name[/get([A-Z]\w*)/, 1]
545
+ logger.debug "#{__method__}: exp.name=#{exp.name} --> extracted=#{getterForVariable}" if logger.debug?
546
+
547
+ # function name parses like getter
548
+ if ! getterForVariable.nil?
549
+ # xaaB --> xaaB
550
+ getterForVariable = getterForVariable[0,1].downcase + getterForVariable[1..-1]
551
+ logger.debug "#{__method__}: variable to get =#{getterForVariable}" if logger.debug?
552
+
553
+ # Getter implemented -> remove it from +parent.neededGetters+
554
+ parent.neededGetters.delete( getterForVariable )
555
+ end
556
+
557
+ s()
558
+ end
559
+
560
+
561
+ end
562
+
563
+
564
+
565
+
566
+ # @!endgroup
567
+
568
+
569
+ end
570
+
571
+ end
572
+ end