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.
- checksums.yaml +7 -0
- data/VERSION +1 -0
- data/lib/mixer/decl_ref.rb +19 -0
- data/lib/mixer/domain_ref.rb +18 -0
- data/lib/mixer/scope.rb +92 -0
- data/lib/mixer/scoped.rb +17 -0
- data/lib/mixer/symbol_ref.rb +16 -0
- data/lib/mixer/type_symbol.rb +75 -0
- data/lib/plugin/plugin.rb +332 -0
- data/lib/resources/correctness/accouns_type.tla +1 -0
- data/lib/resources/correctness/accounts_unique.tla +2 -0
- data/lib/resources/correctness/accounts_valid.tla +2 -0
- data/lib/resources/correctness/storage_root_unique.tla +2 -0
- data/lib/resources/correctness/total_value.tla +1 -0
- data/lib/resources/eth/accounts_state.tla +2 -0
- data/lib/resources/eth/accounts_temp.tla +2 -0
- data/lib/resources/eth/address_free.tla +2 -0
- data/lib/resources/eth/mined_state.tla +1 -0
- data/lib/resources/eth/storageRoot.tla +1 -0
- data/lib/resources/eth/storageRoot_temp.tla +1 -0
- data/lib/resources/mine/mine_entry.tla +4 -0
- data/lib/resources/mine/mine_service.tla +22 -0
- data/lib/resources/operators/elementExists.tla +4 -0
- data/lib/resources/operators/gasPrice.tla +2 -0
- data/lib/resources/operators/gasValue.tla +2 -0
- data/lib/resources/operators/getElement.tla +5 -0
- data/lib/resources/operators/intrinsicGas.tla +4 -0
- data/lib/resources/operators/transactionGas.tla +4 -0
- data/lib/resources/operators/upFrontCost.tla +6 -0
- data/lib/resources/personal_newAccount/personal_newAccount_done.tla +14 -0
- data/lib/resources/personal_newAccount/personal_newAccount_entry.tla +10 -0
- data/lib/resources/personal_newAccount/personal_newAccount_service.tla +29 -0
- data/lib/resources/removed/sendTransaction_entry.tla +5 -0
- data/lib/resources/removed/sendTransaction_service.tla +36 -0
- data/lib/resources/removed/tst.tla +1 -0
- data/lib/resources/transaction/ethereum_service_done.tla +24 -0
- data/lib/resources/transaction/ethereum_service_pop.tla +24 -0
- data/lib/resources/transaction/ethereum_service_push.tla +14 -0
- data/lib/resources/transaction/ethereum_service_start.tla +13 -0
- data/lib/resources/transaction/status_fail.tla +1 -0
- data/lib/resources/transaction/status_ok.tla +1 -0
- data/lib/sbuilder-ethereum.rb +52 -0
- data/lib/sbuilder/compile.rb +163 -0
- data/lib/sbuilder/constants.rb +93 -0
- data/lib/sbuilder/exception.rb +22 -0
- data/lib/sbuilder/generate/sexp_processor_tla.rb +2674 -0
- data/lib/sbuilder/generate/tla_element_generator.rb +1206 -0
- data/lib/sbuilder/generate/tla_element_text.rb +703 -0
- data/lib/sbuilder/load.rb +119 -0
- data/lib/sbuilder/mustache/renderer.rb +152 -0
- data/lib/sbuilder/render.rb +141 -0
- data/lib/sbuilder/s.rb +21 -0
- data/lib/sbuilder/sexp_ast.rb +1378 -0
- data/lib/sbuilder/sexp_processor_api.rb +184 -0
- data/lib/sbuilder/sexp_processor_canonize.rb +326 -0
- data/lib/sbuilder/sexp_processor_dataflow.rb +461 -0
- data/lib/sbuilder/sexp_processor_ethereum.rb +127 -0
- data/lib/sbuilder/sexp_processor_need_to_canonize.rb +572 -0
- data/lib/sbuilder/sexp_processor_snippet.rb +154 -0
- data/lib/sbuilder/sexp_processor_symboltable1.rb +296 -0
- data/lib/sbuilder/sexp_processor_symboltable2.rb +175 -0
- data/lib/sbuilder/sexp_utils.rb +417 -0
- data/lib/utils/logger.rb +82 -0
- data/lib/utils/string_inject.rb +11 -0
- data/sbuilder-ethereum.gemspec +39 -0
- metadata +190 -0
@@ -0,0 +1,461 @@
|
|
1
|
+
|
2
|
+
require 'yaml'
|
3
|
+
require 'tsort'
|
4
|
+
|
5
|
+
module Sbuilder
|
6
|
+
module Ethereum
|
7
|
+
|
8
|
+
|
9
|
+
# Assume
|
10
|
+
# - symbols defined && resolved
|
11
|
+
# -- Scope#enclosing_scope set
|
12
|
+
# -- DeclRef#enclosingScope set
|
13
|
+
# -- DeclRef#declarationRef set
|
14
|
+
#
|
15
|
+
# Actions
|
16
|
+
# - traverse AST and collect dataflow edges
|
17
|
+
# -- Identifier: exp - exp#declarationRef
|
18
|
+
# -- Assignment: exp.variable - exp.expression
|
19
|
+
# -- Return: exp.functionReturnList.parameters[] - exp.expressions[]
|
20
|
+
# - identify domains
|
21
|
+
# -- use tsort#strongly_connected_components to identify
|
22
|
+
#
|
23
|
+
# Implementation uses +id+ -property assigned by solc compiler to
|
24
|
+
# distinguish nodes in SexpAst -tree.
|
25
|
+
|
26
|
+
class SexpProcessorDataflow < SexpProcessorEthereum
|
27
|
+
|
28
|
+
# @attr [Hash] dataflowEdges map SexpAst#id --> [SexpAst#id:Array]
|
29
|
+
attr_accessor :dataflowEdges
|
30
|
+
|
31
|
+
# @attr [Hash] dataflowNodes map SexpAst#id -> [SexpAst]
|
32
|
+
attr_accessor :dataflowNodes
|
33
|
+
|
34
|
+
# # @attr [Domains] domains
|
35
|
+
attr_accessor :domains
|
36
|
+
|
37
|
+
# Map sexp_type to (priority, domain) to use SexpAst -node to give name
|
38
|
+
SEXP_TYPE_2_PRIORITY = {
|
39
|
+
:ContractDefinition => ->(sexp) {
|
40
|
+
return 80, nil
|
41
|
+
},
|
42
|
+
:VariableDeclaration => ->(sexp) {
|
43
|
+
if sexp.typeSexp.sexp_type == :Domain
|
44
|
+
# has already been determined. e.g. adding common msg
|
45
|
+
# properties
|
46
|
+
return 100, sexp.typeSexp
|
47
|
+
elsif sexp.typeSexp.sexp_type == :UserDefinedTypeName && sexp.typeSexp.symbolTypeReference.sexp_type == :ContractDefinition
|
48
|
+
# pointing contract
|
49
|
+
return 100, Domain.s( Constants::DOMAIN_ADDRESS )
|
50
|
+
else
|
51
|
+
case sexp.scopeDefining.sexp_type
|
52
|
+
when :ContractDefinition
|
53
|
+
return 80, nil
|
54
|
+
# return 100, Domain.s( Constants::DOMAIN_ADDRESS )
|
55
|
+
when :ParameterList
|
56
|
+
return 35, nil
|
57
|
+
when :FunctionDefinition
|
58
|
+
return 40, nil
|
59
|
+
when :ParameterList
|
60
|
+
return 35, nil
|
61
|
+
else
|
62
|
+
raise SexpProcessorDataflowException.new "Unknown scope type '#{sexp.scopeDefining.sexp_type}' for #{sexp}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
},
|
66
|
+
:Literal => ->(sexp) {
|
67
|
+
if sexp.type == Constants::SOL_BOOLEAN_TYPE
|
68
|
+
# Map boolean to fixed domain name
|
69
|
+
return 100, Domain.s( Constants::DOMAIN_BOOLEAN )
|
70
|
+
elsif sexp.type =~ /int_const /
|
71
|
+
# Integer const does identify domain - nor results to error
|
72
|
+
return nil, nil
|
73
|
+
else
|
74
|
+
raise SexpProcessorDataflowException.new "Unknown literal type '#{sexp.type}' for #{sexp}"
|
75
|
+
end
|
76
|
+
},
|
77
|
+
:MemberAccess => ->(sexp) { return 30, nil },
|
78
|
+
:Identifier => ->(sexp) { return 30, nil },
|
79
|
+
:IndexAccess => ->(sexp) {
|
80
|
+
# variable declartion of identifier must be 'Mapping', resolve
|
81
|
+
# to domain of 'mapping-function'
|
82
|
+
domainOfMapping = sexp.identifier.declationRef.typeSexp.mapTo.domainReference
|
83
|
+
return 100, sexp.identifier.declationRef.typeSexp.mapTo.domainReference unless domainOfMapping.nil?
|
84
|
+
return nil, nil
|
85
|
+
},
|
86
|
+
:ElementaryTypeName => ->(sexp) {
|
87
|
+
if sexp.typeName == Constants::SOL_ADDRESS
|
88
|
+
return 100, Domain.s( Constants::DOMAIN_ADDRESS )
|
89
|
+
elsif sexp.typeName == Constants::SOL_UINT
|
90
|
+
# uint value domain overridden by better candiadate
|
91
|
+
# (e.g. msg.value)
|
92
|
+
return 10, Domain.s( Constants::DOMAIN_DEFAULT )
|
93
|
+
else
|
94
|
+
return nil, nil
|
95
|
+
# raise SexpProcessorDataflowException.new "Unknown elementary type name for #{sexp}"
|
96
|
+
end
|
97
|
+
},
|
98
|
+
:FunctionCallReadReturn => ->(sexp) { return nil, nil },
|
99
|
+
:FunctionDefinition => ->(sexp) {
|
100
|
+
if sexp.returnList.parameters.length == 1 && sexp.returnList.parameters[0].type == Constants::DOMAIN_BOOLEAN
|
101
|
+
return 100, Domain.s( Constants::DOMAIN_BOOLEAN )
|
102
|
+
elsif sexp.returnList.parameters.length == 1 && sexp.returnList.parameters[0].type == Constants::SOL_BOOLEAN_TYPE
|
103
|
+
return 100, Domain.s( Constants::DOMAIN_BOOLEAN )
|
104
|
+
elsif sexp.returnList.parameters.length == 0
|
105
|
+
return 100, Domain.s( Constants::DOMAIN_BOOLEAN )
|
106
|
+
else
|
107
|
+
raise SexpProcessorDataflowException.new "Unknown function return type '#{sexp.returnList}' for #{sexp}"
|
108
|
+
end
|
109
|
+
},
|
110
|
+
:BinaryOperation => ->(sexp) { return nil, nil },
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
# ------------------------------------------------------------------
|
116
|
+
# @!group Construct & configure
|
117
|
+
|
118
|
+
def initialize( options={} )
|
119
|
+
|
120
|
+
super( options )
|
121
|
+
|
122
|
+
# see addEdge to populate
|
123
|
+
self.dataflowEdges = THash.new
|
124
|
+
self.dataflowNodes = {}
|
125
|
+
end
|
126
|
+
|
127
|
+
# @!endgroup
|
128
|
+
|
129
|
+
# ------------------------------------------------------------------
|
130
|
+
# @!group scope support
|
131
|
+
|
132
|
+
# @attr [VariableDeclaration] currentDecl
|
133
|
+
attr_accessor :currentDecl
|
134
|
+
|
135
|
+
def varDecled( expDecl )
|
136
|
+
prevDecl = currentDecl
|
137
|
+
self.currentDecl = expDecl
|
138
|
+
begin
|
139
|
+
yield
|
140
|
+
ensure
|
141
|
+
self.currentDecl = prevDecl
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
# @!endgroup
|
147
|
+
|
148
|
+
|
149
|
+
# ------------------------------------------------------------------
|
150
|
+
# @!group Entry point & return the identified domains
|
151
|
+
|
152
|
+
# private def processGlobals( exp )
|
153
|
+
# return if @processGlobals
|
154
|
+
|
155
|
+
# # identify data flows in function global
|
156
|
+
# exp.globalScope.symbolDefinitions.
|
157
|
+
# select { |globalExp| globalExp.sexp_type == :FunctionDefinition }.
|
158
|
+
# each { |expFunction| process_rest( expFunction ) }
|
159
|
+
|
160
|
+
# @processGlobals = true
|
161
|
+
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
#
|
165
|
+
# @return [Domains] domains Sexp, with domain -property
|
166
|
+
def process_SourceUnit( exp )
|
167
|
+
|
168
|
+
logger.debug "#{__method__}: starting with '#{exp}" if logger.debug?
|
169
|
+
|
170
|
+
# traverse tree collect 'dataflowEdges', 'dataflowNodes'
|
171
|
+
process_rest( exp )
|
172
|
+
|
173
|
+
analyzeDomains
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
def process_GlobalScope( exp )
|
178
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
179
|
+
# identify data flows in function global
|
180
|
+
# exp.globalScope.symbolDefinitions.
|
181
|
+
# select { |globalExp| globalExp.sexp_type == :FunctionDefinition }.
|
182
|
+
# each { |expFunction| process_rest( expFunction ) }
|
183
|
+
|
184
|
+
# traverse tree collect 'dataflowEdges', 'dataflowNodes'
|
185
|
+
process_rest( exp )
|
186
|
+
|
187
|
+
analyzeDomains
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Cm
|
193
|
+
private def analyzeDomains
|
194
|
+
# Identify domains after tree traversal
|
195
|
+
|
196
|
+
# identify strongly connected components in 'dataflowEdges'
|
197
|
+
strong_components = find_strong_components()
|
198
|
+
logger.debug "#{__method__}: strong_components: #{strong_components}" if logger.debug?
|
199
|
+
|
200
|
+
# for each 'strong_component' find representative sexp to generate
|
201
|
+
# name for the domain
|
202
|
+
domainsIdentified=[]
|
203
|
+
strong_components.each do |strong_component|
|
204
|
+
|
205
|
+
# find SexpAst -node to give name for the domain
|
206
|
+
strong_component_name_sexp = find_representative_name_sexp( strong_component )
|
207
|
+
|
208
|
+
# Create Domain with +domainName+
|
209
|
+
domain = Domain.new( domainName(strong_component_name_sexp) )
|
210
|
+
logger.info "#{__method__}: identified domain #{domain}"
|
211
|
+
domainsIdentified << domain
|
212
|
+
|
213
|
+
# update pointer to domain on sexp node
|
214
|
+
update_domain_on_sexps( domain, strong_component )
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
# Sexp with collection of domains
|
219
|
+
self.domains = Domains.new( domainsIdentified )
|
220
|
+
|
221
|
+
logger.info "#{__method__}: analyzed domains='#{domains}"
|
222
|
+
domains
|
223
|
+
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
# @!endgroup
|
230
|
+
|
231
|
+
# ------------------------------------------------------------------
|
232
|
+
# @!group Collect dataflow edges
|
233
|
+
|
234
|
+
|
235
|
+
def process_ContractDefinition( exp )
|
236
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
237
|
+
|
238
|
+
# # Add globals also domain analysis
|
239
|
+
# processGlobals( exp )
|
240
|
+
|
241
|
+
# add a domain to configure number of contracts
|
242
|
+
addEdge( exp.sexp_type, exp, nil )
|
243
|
+
process_rest( exp )
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
def process_VariableDeclaration( exp )
|
248
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
249
|
+
|
250
|
+
# declaration is part of its own strong component
|
251
|
+
addEdge( exp.sexp_type, exp, exp ) unless exp.isMapping
|
252
|
+
varDecled( exp ) do
|
253
|
+
process_rest( exp )
|
254
|
+
end
|
255
|
+
s()
|
256
|
+
end
|
257
|
+
|
258
|
+
def process_ElementaryTypeName( exp )
|
259
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
260
|
+
|
261
|
+
# non elemenary declaration
|
262
|
+
if currentDecl && currentDecl.isMapping
|
263
|
+
logger.info "#{__method__} compposite #{currentDecl.name} for #{exp}"
|
264
|
+
addEdge( exp.sexp_type, exp, exp )
|
265
|
+
end
|
266
|
+
s()
|
267
|
+
end
|
268
|
+
|
269
|
+
def process_MemberAccess( exp )
|
270
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
271
|
+
if exp.isFunctionOnFunction
|
272
|
+
# AST in 'function on function' case, e.g. demo1.set.value(20)(
|
273
|
+
# 6 ) like s(:MemberAccess, "value", s(:MemberAccess, "set",
|
274
|
+
# s(:Identifier, "contract Demo1", "demo1")))
|
275
|
+
#
|
276
|
+
# we are processing s(:MemberAccess, "value", just recurse
|
277
|
+
process_rest( exp )
|
278
|
+
else
|
279
|
+
raise SexpProcessorDataflowException.new "Missing declationRef in #{exp}" unless exp.isDeclarationRef && !exp.declationRef.nil?
|
280
|
+
addEdge( exp.sexp_type, exp, exp.declationRef )
|
281
|
+
end
|
282
|
+
s()
|
283
|
+
end
|
284
|
+
|
285
|
+
def process_Identifier( exp )
|
286
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
287
|
+
raise SexpProcessorDataflowException.new "Missing declationRef in #{exp}" unless exp.isDeclarationRef && !exp.declationRef.nil?
|
288
|
+
addEdge( exp.sexp_type, exp, exp.declationRef )
|
289
|
+
process_rest( exp )
|
290
|
+
end
|
291
|
+
|
292
|
+
def process_Assignment( exp )
|
293
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
294
|
+
|
295
|
+
addEdge( exp.sexp_type, exp.lval, exp.rval )
|
296
|
+
process_rest( exp )
|
297
|
+
end
|
298
|
+
|
299
|
+
def process_Return( exp )
|
300
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
301
|
+
logger.debug "#{__method__}, exp.functionReturnList=#{exp.functionReturnList}" if logger.debug?
|
302
|
+
|
303
|
+
# iterate each return expression/output parameter mapping
|
304
|
+
exp.functionReturnList.parameters.each_with_index do |parameter,i|
|
305
|
+
logger.debug "#{__method__}, parameter[#{i}]=#{parameter}" if logger.debug?
|
306
|
+
addEdge( exp.sexp_type, parameter, exp.expressions[i] )
|
307
|
+
end
|
308
|
+
|
309
|
+
process_rest( exp )
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
# @!endgroup
|
315
|
+
# ------------------------------------------------------------------
|
316
|
+
# @!group Methods to build edges
|
317
|
+
|
318
|
+
# Add bidirectional edge '+sexp1+ --- +sexp2+' to +dataflowEdges+
|
319
|
+
# when processing +sexp_type+ node. If +sexp2+ is nil add just node.
|
320
|
+
#
|
321
|
+
# @param [SexpAst|nil] sexp1 data flown between +sexp1+ - +sexp2+,
|
322
|
+
#
|
323
|
+
# @param [SexpAst|nil] sexp2 may be nil, in which case add just node +sexp1+
|
324
|
+
#
|
325
|
+
private def addEdge( sexp_type, sexp1, sexp2 )
|
326
|
+
logger.debug "#{__method__}: '#{sexp1.id}:#{sexp1} --- #{sexp2.nil? ? 'nil' : sexp2.id}:#{sexp2}' for process_#{sexp_type}" if logger.debug?
|
327
|
+
|
328
|
+
# make sura that the nodes are there
|
329
|
+
addNode( sexp1 )
|
330
|
+
addNode( sexp2 ) unless sexp2.nil?
|
331
|
+
|
332
|
+
# ensure key known
|
333
|
+
self.dataflowEdges[sexp1.id] = [] unless dataflowEdges.key?(sexp1.id)
|
334
|
+
self.dataflowEdges[sexp2.id] = [] unless sexp2.nil? || dataflowEdges.key?(sexp2.id)
|
335
|
+
|
336
|
+
# add to directional edges - unless either node nil, or it is
|
337
|
+
# already there
|
338
|
+
if sexp1 && sexp2 then
|
339
|
+
self.dataflowEdges[sexp1.id] << sexp2.id unless dataflowEdges[sexp1.id].include?( sexp2.id )
|
340
|
+
self.dataflowEdges[sexp2.id] << sexp1.id unless dataflowEdges[sexp2.id].include?( sexp1.id )
|
341
|
+
end
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
private def addNode( sexp )
|
347
|
+
self.dataflowNodes[sexp.id] = sexp unless dataflowNodes.key?(sexp.id)
|
348
|
+
end
|
349
|
+
|
350
|
+
# @!endgroup
|
351
|
+
|
352
|
+
# ------------------------------------------------------------------
|
353
|
+
# @!group Propage domain information
|
354
|
+
|
355
|
+
|
356
|
+
|
357
|
+
private def update_domain_on_sexps( domain, strong_component )
|
358
|
+
|
359
|
+
strong_component.each do |sexpAstId|
|
360
|
+
|
361
|
+
sexp_node = dataflowNodes[sexpAstId]
|
362
|
+
|
363
|
+
# should mix DomainRef
|
364
|
+
sexp_node.domainReference = domain
|
365
|
+
logger.info "#{__method__}: --> set domain: domain=#{domain} -> #{sexp_node[0]},#{sexp_node[1]}"
|
366
|
+
logger.debug "#{__method__}: set domain: domain=#{domain} in full #{sexp_node}" if logger.debug?
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
# @!endgroup
|
373
|
+
|
374
|
+
# ------------------------------------------------------------------
|
375
|
+
# @!group Helper class to implement tsort#strongly_connected_components
|
376
|
+
|
377
|
+
|
378
|
+
class THash < Hash
|
379
|
+
|
380
|
+
include TSort
|
381
|
+
|
382
|
+
# methods used by tsort
|
383
|
+
alias tsort_each_node each_key
|
384
|
+
def tsort_each_child(node, &block)
|
385
|
+
fetch(node).each(&block)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
# @return [Array] strong_components
|
390
|
+
|
391
|
+
private def find_strong_components
|
392
|
+
dataflowEdges.strongly_connected_components
|
393
|
+
end
|
394
|
+
|
395
|
+
# @!endgroup
|
396
|
+
|
397
|
+
# ------------------------------------------------------------------
|
398
|
+
# @!group Use strong components to define domain
|
399
|
+
|
400
|
+
# Identify SexpAst -node among +strong_component+ array, which gives
|
401
|
+
# name for the domain.
|
402
|
+
#
|
403
|
+
# @param [Id:Array] strong_component array of SexpAst#id values mapping to 'dataflowNodes'
|
404
|
+
#
|
405
|
+
# @return [SexpAst] name_sexp used to generate name for the domain entry
|
406
|
+
#
|
407
|
+
private def find_representative_name_sexp( strong_component )
|
408
|
+
#
|
409
|
+
name_sexp_priority=0
|
410
|
+
name_sexp = nil
|
411
|
+
if logger.debug?
|
412
|
+
logger.debug "#{__method__}: strong_component=#{strong_component.map { |sexpAstId | dataflowNodes[sexpAstId].inspect }.join(';')}" if logger.debug?
|
413
|
+
end
|
414
|
+
strong_component.each do |sexpAstId|
|
415
|
+
sexp_type = dataflowNodes[sexpAstId].sexp_type
|
416
|
+
sexp_node = dataflowNodes[sexpAstId]
|
417
|
+
logger.debug "Lookup in SEXP_TYPE_2_PRIORITY #{dataflowNodes[sexpAstId]}" if logger.debug?
|
418
|
+
raise "Missing implementation in SEXP_TYPE_2_PRIORITY for #{sexp_type}(is symbol or string?= #{sexp_type.class}) for #{sexp_node}" unless SEXP_TYPE_2_PRIORITY.key?(sexp_type)
|
419
|
+
# Use lambda to callucate priority
|
420
|
+
priority, domain_sexp = SEXP_TYPE_2_PRIORITY[sexp_type].call( sexp_node )
|
421
|
+
logger.debug "#{__method__}: id=#{sexpAstId}->#{sexp_type}->#{priority}, node=#{sexp_node}" if logger.debug?
|
422
|
+
# better name candiate found
|
423
|
+
if domain_sexp
|
424
|
+
# lambda new it best
|
425
|
+
name_sexp, name_sexp_priority = domain_sexp, priority if !priority.nil? && (priority > name_sexp_priority)
|
426
|
+
else
|
427
|
+
name_sexp, name_sexp_priority = dataflowNodes[sexpAstId], priority if !priority.nil? && (priority > name_sexp_priority)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
raise SexpProcessorDataflowException.new "Could not find domain for components #{strong_component.nil? ? 'nil' : strong_component.map{ |c| dataflowNodes[c].to_s }.join(',')}" if name_sexp.nil?
|
432
|
+
|
433
|
+
logger.info "#{__method__}: name_sexp=#{name_sexp} for strong_component=#{strong_component.map { |sexpAstId | dataflowNodes[sexpAstId].inspect }.join(';')}"
|
434
|
+
|
435
|
+
name_sexp
|
436
|
+
end
|
437
|
+
|
438
|
+
# @param [SexpAst] name_sexp used to generate name for the domain entry
|
439
|
+
#
|
440
|
+
# @return [String] domainName to use for domain
|
441
|
+
private def domainName( name_sexp )
|
442
|
+
case name_sexp.sexp_type
|
443
|
+
when :VariableDeclaration
|
444
|
+
"#{ name_sexp.scopeDefining.name}_#{name_sexp.name}"
|
445
|
+
when :ContractDefinition
|
446
|
+
"#{name_sexp.name}"
|
447
|
+
when :Domain
|
448
|
+
"#{name_sexp.name}"
|
449
|
+
else
|
450
|
+
raise SexpProcessorDataflowException.new "Do not know how to create name for '#{name_sexp.sexp_type}' for #{name_sexp}"
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
# @!endgroup
|
455
|
+
end # class
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|