sbuilder-ethereum 0.0.6

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