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,154 @@
|
|
1
|
+
module Sbuilder;
|
2
|
+
module Ethereum
|
3
|
+
##
|
4
|
+
# Load Snippet information to sbuilder using facade
|
5
|
+
|
6
|
+
class SexpProcessorSnippet < SexpProcessorEthereum
|
7
|
+
|
8
|
+
# ------------------------------------------------------------------
|
9
|
+
# Attributes
|
10
|
+
|
11
|
+
# @attr [SnippetLoaderFacade] snippetFacade, Must be set before
|
12
|
+
# using #process.
|
13
|
+
attr_reader :snippetFacade
|
14
|
+
|
15
|
+
# @attr [Render] renderer rendering TLA generate element to TLA
|
16
|
+
# language snippets. Must be set before using #process.
|
17
|
+
attr_reader :renderer
|
18
|
+
|
19
|
+
# @attr [Hash] metatypes map snippet metatype to metatype
|
20
|
+
# desciption. Must be set before using #process.
|
21
|
+
attr_reader :metatypes
|
22
|
+
|
23
|
+
# ------------------------------------------------------------------
|
24
|
+
# @!group Construct & configure
|
25
|
+
|
26
|
+
def initialize( options={} )
|
27
|
+
super( options )
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Configure +@renderer+ to render TLA generate elements to TLA language snippets
|
32
|
+
def setRenderer( renderer )
|
33
|
+
@renderer = renderer
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
# Configure +snippetFacade+ used to communicate with sbuilder framework
|
39
|
+
def setSnippetFacade( snippetFacade )
|
40
|
+
@snippetFacade = snippetFacade
|
41
|
+
|
42
|
+
# before anythin else - configure
|
43
|
+
configureSnippetFacade
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
private def configureSnippetFacade
|
48
|
+
# set snippet wrappers with known text
|
49
|
+
snippetFacade.setSnippetHeader( TlaElementText::SNIPPET_HEADER )
|
50
|
+
snippetFacade.setSnippetFooter( TlaElementText::SNIPPET_FOOTER )
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Configure +metatypes+ used in +partials+
|
56
|
+
def setMetatypes( metatypes )
|
57
|
+
@metatypes = metatypes
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# @!endgroup
|
62
|
+
|
63
|
+
# ------------------------------------------------------------------
|
64
|
+
# @!group render TLA snippet
|
65
|
+
|
66
|
+
##
|
67
|
+
# Render body of snippit in TLA-language.
|
68
|
+
#
|
69
|
+
# @param [Snippet] snippet SexpAst to render
|
70
|
+
def render( snippet, &blk )
|
71
|
+
raise SbuilderEtherumException, "Invalid call sequence, should have called '#setRenderer' before #process" unless metatypes
|
72
|
+
renderer.renderSnippet( snippet, &blk )
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# @!endgroup
|
77
|
+
|
78
|
+
# ------------------------------------------------------------------
|
79
|
+
# @!group Sexp node actions
|
80
|
+
|
81
|
+
##
|
82
|
+
# Register metatypes in Snippets Sexp tree.
|
83
|
+
#
|
84
|
+
|
85
|
+
def process_Snippets( exp )
|
86
|
+
|
87
|
+
logger.debug( "#{__method__}: exp=#{exp}") if logger.debug?
|
88
|
+
|
89
|
+
registerMetatypes
|
90
|
+
|
91
|
+
# exp.return_nodes_with_type( :Snippet ).each do |snippet|
|
92
|
+
# metatypeDescription = metatypes[snippet.metatype]
|
93
|
+
# if metatypeDescription.nil?
|
94
|
+
# msg = <<-EOS
|
95
|
+
# Unknown metatype '#{snippet.metatype}' in #{snippet}
|
96
|
+
|
97
|
+
# Known metatypes #{metatypes.keys.join(',')}
|
98
|
+
# EOS
|
99
|
+
# logger.error "#{__method__}: #{msg}"
|
100
|
+
# raise SbuilderEtherumException, msg
|
101
|
+
# end
|
102
|
+
|
103
|
+
# # valid metatype found, register it before processing snippets
|
104
|
+
# snippetFacade.registerMetatype( snippet.metatype.to_s, metatypeDescription )
|
105
|
+
# end
|
106
|
+
|
107
|
+
# continue with tree traversal
|
108
|
+
process_rest( exp )
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Register metatypes over snippet facade
|
114
|
+
def registerMetatypes
|
115
|
+
raise SbuilderEtherumException, "Invalid call sequence, should have called '#setMetatypes' before #process" unless metatypes
|
116
|
+
logger.debug "#{__method__}: #{metatypes}" if logger.debug?
|
117
|
+
|
118
|
+
metatypes.each do |metatype,metatypeDef|
|
119
|
+
metatypeDescription = metatypeDef[:name]
|
120
|
+
metatypePrefix = metatypeDef[:prefix]
|
121
|
+
snippetFacade.registerMetatype( metatype.to_s, metatypeDescription, metatypePrefix )
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Render +exp+ to create +snippetBody+, pass +snippetBody+
|
127
|
+
# together with +snippet.metatype+, and +snippet.appName+ to
|
128
|
+
# +snippetFacade+
|
129
|
+
def process_Snippet( exp )
|
130
|
+
logger.debug( "#{__method__}: exp=#{exp}") if logger.debug?
|
131
|
+
raise SbuilderEtherumException, "Invalid call sequence, should have called '#setSnippetFacade' before #process" unless snippetFacade
|
132
|
+
|
133
|
+
# create TLA language body && hand over to sbuilder facede
|
134
|
+
render( exp ) do |metatype,appName, snippetBody|
|
135
|
+
logger.info "#{__method__}: rendered metatype=#{metatype}, appName=#{appName}, specName=#{exp.specName}"
|
136
|
+
logger.debug "#{__method__}: rendered snippetBody=#{snippetBody}" if logger.debug?
|
137
|
+
|
138
|
+
# pass to sbuilder (using 'Strings' as metatype),
|
139
|
+
# 'specName', if given, overrides name generated in sbuilder
|
140
|
+
snippetFacade.handOver( metatype.to_s, appName, snippetBody, exp.specName )
|
141
|
+
|
142
|
+
end
|
143
|
+
s()
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
# @!endgroup
|
148
|
+
|
149
|
+
|
150
|
+
end # class
|
151
|
+
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Sbuilder
|
3
|
+
module Ethereum
|
4
|
+
|
5
|
+
##
|
6
|
+
# Create scope hierarchy for symbol table
|
7
|
+
#
|
8
|
+
# Traverse sexp AST, and
|
9
|
+
# - initializes & returns GlobalScope (for process)
|
10
|
+
# - build scope hierarchy (mixer Scope) for SexpAst -nodes
|
11
|
+
# -- GlobalScope
|
12
|
+
# -- ContractDefinition
|
13
|
+
# -- FunctionDefinition
|
14
|
+
# - add references to currentScope
|
15
|
+
# -- VariableDeclaration#scopeDefining (Scoped)
|
16
|
+
# -- Return#scopeDefining (Scoped)
|
17
|
+
# -- Identifier#enclosingScope (DeclRef)
|
18
|
+
|
19
|
+
class SexpProcessorSymbolTable1 < SexpProcessorEthereum
|
20
|
+
|
21
|
+
# ------------------------------------------------------------------
|
22
|
+
# @!group Construct & configure
|
23
|
+
|
24
|
+
def initialize( options={} )
|
25
|
+
super( options )
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!endgroup
|
29
|
+
|
30
|
+
# ------------------------------------------------------------------
|
31
|
+
# @!group scope support
|
32
|
+
|
33
|
+
# @attr [GlobalScope] globalScope the one
|
34
|
+
attr_accessor :globalScope
|
35
|
+
|
36
|
+
# @attr [Scope] currentScope which currently opened
|
37
|
+
attr_accessor :currentScope
|
38
|
+
|
39
|
+
# @attr [Contract] currentContract which currently processing
|
40
|
+
attr_accessor :currentContract
|
41
|
+
|
42
|
+
|
43
|
+
def contracted( expContract )
|
44
|
+
|
45
|
+
self.currentContract = expContract
|
46
|
+
begin
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
self.currentContract = nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# Use +scoped+ allowing scope object passed as a parameter, instead
|
55
|
+
# of +SexpProcessor#scope+, which uses fixed hash to manage scope
|
56
|
+
# entries.
|
57
|
+
#
|
58
|
+
# @param [Scope] ethScope to push to @env
|
59
|
+
#
|
60
|
+
# @param [String] prefix distinguish variable declaration in funtion return list
|
61
|
+
#
|
62
|
+
def scoped( ethScope )
|
63
|
+
|
64
|
+
raise "Scope support missing in #{ethScope}" unless ethScope.respond_to?( :isScope ) && ethScope.isScope
|
65
|
+
logger.debug "#{__method__}: create scope for '#{ethScope.sexp_type}' over #{ currentScope ? currentScope.sexp_type : 'starting global scope' }" if logger.debug?
|
66
|
+
|
67
|
+
# remember 'prevScope', update enclosing scope, switch '@currentScope',
|
68
|
+
prevScope = currentScope
|
69
|
+
ethScope.enclosing_scope = currentScope
|
70
|
+
self.currentScope = ethScope
|
71
|
+
|
72
|
+
|
73
|
+
begin
|
74
|
+
# traverse the tree under the newly created scope
|
75
|
+
yield
|
76
|
+
ensure
|
77
|
+
logger.debug "#{__method__}: pop scope for '#{ethScope.sexp_type}' - resume #{prevScope ? prevScope.sexp_type : 'global scope'}" if logger.debug?
|
78
|
+
self.currentScope = prevScope
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Scope] gloabalScope with ethereum declarations
|
83
|
+
#
|
84
|
+
def startWithGlobalScope
|
85
|
+
# start with global scope with sexp_type :GlobalScope
|
86
|
+
warn "Global scope not initialized" if globalScope.nil?
|
87
|
+
self.currentScope = globalScope || GlobalScope.new
|
88
|
+
end
|
89
|
+
|
90
|
+
# ------------------------------------------------------------------
|
91
|
+
# @!group Access processors
|
92
|
+
|
93
|
+
def getSymbolTable1ExpressionsProcessor( scope )
|
94
|
+
proc = SymbolTable1Expressions.new( options )
|
95
|
+
proc.currentScope = scope
|
96
|
+
proc
|
97
|
+
end
|
98
|
+
|
99
|
+
# @!endgroup
|
100
|
+
|
101
|
+
# ------------------------------------------------------------------
|
102
|
+
# @!group starting point && return value
|
103
|
+
|
104
|
+
|
105
|
+
# @return [GlobalScope] globalScope
|
106
|
+
def process_SourceUnit( exp )
|
107
|
+
|
108
|
+
# global declarations are always there
|
109
|
+
startWithGlobalScope
|
110
|
+
# tree traversal
|
111
|
+
process_rest( exp )
|
112
|
+
|
113
|
+
# returns sexp, which should be +GlobalScope+
|
114
|
+
currentScope
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
# @!endgroup
|
119
|
+
|
120
|
+
# ------------------------------------------------------------------
|
121
|
+
# @!group Node rules creating scopes
|
122
|
+
def process_GlobalScope( exp )
|
123
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
124
|
+
|
125
|
+
# address is top level type for functions in globalScope
|
126
|
+
contracted( exp.resolve(Constants::SOL_ADDRESS ) ) do
|
127
|
+
scoped( exp ) do
|
128
|
+
process_rest( exp )
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def process_ContractDefinition( exp )
|
134
|
+
logger.debug "#{__method__}: name=#{exp.name}" if logger.debug?
|
135
|
+
# add name of contract (to top-level scope?)
|
136
|
+
currentScope.define( exp.name, exp )
|
137
|
+
contracted( exp ) do
|
138
|
+
scoped( exp ) do
|
139
|
+
# contracted & scoped!!
|
140
|
+
process_rest( exp )
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def process_FunctionDefinition( exp )
|
146
|
+
logger.debug "#{__method__}: #{exp} entered" if logger.debug?
|
147
|
+
|
148
|
+
exp.contractDefinition = currentContract
|
149
|
+
currentScope.define( exp.name, exp )
|
150
|
+
# TODO - remove this
|
151
|
+
|
152
|
+
# add interfacename to contract
|
153
|
+
if exp.respond_to?( :interfaceName )
|
154
|
+
logger.info "#{__method__}: scope-definition for interface #{exp.interfaceName}"
|
155
|
+
currentScope.define( exp.interfaceName, exp )
|
156
|
+
else
|
157
|
+
warn "Exp #{exp} does not respond to :interfaceName - preprocessing problem??"
|
158
|
+
end
|
159
|
+
|
160
|
+
scoped( exp ) do
|
161
|
+
|
162
|
+
# add 'msg': pointing to function parameter list & process variable declaration
|
163
|
+
currentScope.define( Constants::SOL_MSG, exp.parameterList )
|
164
|
+
exp.parameterList.scopeDefining = currentScope
|
165
|
+
exp.parameterList.enclosing_scope = currentScope
|
166
|
+
process( exp.parameterList )
|
167
|
+
|
168
|
+
# add 'return-': pointing to return list
|
169
|
+
currentScope.define( Constants::SYMBOL_RETURN_PREFIX, exp.returnList )
|
170
|
+
exp.returnList.scopeDefining = currentScope
|
171
|
+
exp.returnList.enclosing_scope = currentScope
|
172
|
+
process( exp.returnList )
|
173
|
+
|
174
|
+
# local variables
|
175
|
+
process( exp.block )
|
176
|
+
end
|
177
|
+
|
178
|
+
# expression resolved within parameterlist block
|
179
|
+
getSymbolTable1ExpressionsProcessor( exp.parameterList ).process( exp.block )
|
180
|
+
|
181
|
+
|
182
|
+
s()
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
##
|
187
|
+
def process_ParameterList( exp )
|
188
|
+
logger.info "#{__method__}: #{exp} entered"
|
189
|
+
|
190
|
+
|
191
|
+
scoped( exp ) do
|
192
|
+
process_rest( exp )
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
# @!endgroup
|
199
|
+
|
200
|
+
# ------------------------------------------------------------------
|
201
|
+
# @!group Node rules using scopes
|
202
|
+
|
203
|
+
def process_VariableDeclaration( exp )
|
204
|
+
|
205
|
+
logger.debug "#{__method__}: define variable name=#{exp.name}, type=#{exp.type}" if logger.debug?
|
206
|
+
|
207
|
+
# declaration defines
|
208
|
+
currentScope.define( exp.name, exp )
|
209
|
+
|
210
|
+
# add back pointer to the scope where the variable is defined
|
211
|
+
exp.scopeDefining = currentScope
|
212
|
+
|
213
|
+
process_rest( exp )
|
214
|
+
end
|
215
|
+
|
216
|
+
def process_ElementaryTypeName( exp)
|
217
|
+
|
218
|
+
# add back pointer to the scope where the variable is defined
|
219
|
+
exp.scopeDefining = currentScope
|
220
|
+
|
221
|
+
s()
|
222
|
+
end
|
223
|
+
|
224
|
+
def process_UserDefinedTypeName( exp )
|
225
|
+
exp.scopeDefining = currentScope
|
226
|
+
s()
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
def process_Domain( exp )
|
231
|
+
exp.scopeDefining = currentScope
|
232
|
+
s()
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
end # SexpProcessorSymbolTable1
|
238
|
+
|
239
|
+
# process expressions (within function body)
|
240
|
+
|
241
|
+
class SymbolTable1Expressions < SexpProcessorEthereum
|
242
|
+
|
243
|
+
def initialize( options={} )
|
244
|
+
super( options )
|
245
|
+
end
|
246
|
+
|
247
|
+
# @attr [Scope] currentScope which currently opened
|
248
|
+
attr_accessor :currentScope
|
249
|
+
|
250
|
+
def process_NewExpression( exp )
|
251
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
252
|
+
exp.enclosingScope = currentScope
|
253
|
+
# No need to recurse furher
|
254
|
+
# process_rest( exp )
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
def process_Return( exp )
|
259
|
+
|
260
|
+
# advance above parameter list
|
261
|
+
functionScope = currentScope.enclosing_scope
|
262
|
+
# functionScope = currentScope
|
263
|
+
functionScopeExpect = :FunctionDefinition
|
264
|
+
raise SexpProcessorDataflowException.new "Incorrect sexp_type '#{functionScope.sexp_type}' in #{exp}, expecting '#{functionScopeExpect}'" if functionScopeExpect != functionScope.sexp_type
|
265
|
+
|
266
|
+
# back pointer to function scope where the return expression is set
|
267
|
+
exp.scopeDefining = functionScope
|
268
|
+
|
269
|
+
process_rest( exp )
|
270
|
+
|
271
|
+
end
|
272
|
+
def process_MemberAccess( exp )
|
273
|
+
|
274
|
+
logger.debug "#{__method__}: exp=#{exp}" if logger.debug?
|
275
|
+
# register scope of reference
|
276
|
+
exp.enclosingScope = currentScope
|
277
|
+
|
278
|
+
process_rest( exp )
|
279
|
+
|
280
|
+
end
|
281
|
+
def process_Identifier( exp )
|
282
|
+
|
283
|
+
logger.debug "#{__method__}: exp-value=#{exp.value}, type=#{exp.type}" if logger.debug?
|
284
|
+
|
285
|
+
# register scope of reference
|
286
|
+
exp.enclosingScope = currentScope
|
287
|
+
|
288
|
+
process_rest( exp )
|
289
|
+
end
|
290
|
+
|
291
|
+
# @!endgroup
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Ethereum
|
3
|
+
|
4
|
+
|
5
|
+
# Assumes that
|
6
|
+
# - scope hierarchy has been created
|
7
|
+
# - declarations added to scopes
|
8
|
+
#
|
9
|
+
# Traverse AST and
|
10
|
+
# - resolve declarations
|
11
|
+
|
12
|
+
class SexpProcessorSymbolTable2 < SexpProcessorEthereum
|
13
|
+
|
14
|
+
# ------------------------------------------------------------------
|
15
|
+
# @!group Construct & configure
|
16
|
+
|
17
|
+
def initialize( options={} )
|
18
|
+
super( options )
|
19
|
+
end
|
20
|
+
|
21
|
+
# @!endgroup
|
22
|
+
|
23
|
+
# ------------------------------------------------------------------
|
24
|
+
# @!group Resolve references
|
25
|
+
|
26
|
+
def process_ContractDefinition( exp )
|
27
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
28
|
+
|
29
|
+
# all contract inherit from 'address'
|
30
|
+
exp.inherits( exp.globalScope.resolveOrReportError( Constants::SOL_ADDRESS ) )
|
31
|
+
process_rest( exp )
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def process_MemberAccess( exp )
|
36
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
37
|
+
|
38
|
+
# Cases:
|
39
|
+
#
|
40
|
+
# * s( :MemberAccess, s(:Identifier s(:ElementaryTypeName)))
|
41
|
+
#
|
42
|
+
# * msg.sender.send s( :MemberAccess, s( :MemberAccess,
|
43
|
+
# s(:Idenfier, s(:UserDefinedTypeName)))
|
44
|
+
#
|
45
|
+
# * s(:MemberAccess, "value", s(:TupleExpression,
|
46
|
+
# s(:NewExpression, "function () returns (contract Demo1)",
|
47
|
+
# s(:UserDefinedTypeName, "Demo1"))))
|
48
|
+
|
49
|
+
# resolve 'declationRef' under 'memberStruct' before
|
50
|
+
# processing 'exp'
|
51
|
+
process_rest( exp )
|
52
|
+
|
53
|
+
logger.debug "#{__method__}: use exp.memberStruct=#{exp.memberStruct} with declationRef #{exp.memberStruct.declationRef} to resolve '#{exp.member_name}'" if logger.debug?
|
54
|
+
|
55
|
+
if exp.isFunctionOnFunction
|
56
|
+
# calling "function on a function"
|
57
|
+
# e.g. f.gas(2).value(20)(), which calls the modified
|
58
|
+
# function 'f' and thereby sending 20 Wei and limiting the
|
59
|
+
# gas to 2.
|
60
|
+
#
|
61
|
+
# we catch 'FunctionOnFunction' separately in code
|
62
|
+
# generation phase, and have no need for declationRef
|
63
|
+
decl = nil
|
64
|
+
# elsif exp.memberStruct.declationRef.respond_to?( :isTypeSymbol ) && exp.memberStruct.declationRef.isTypeSymbol
|
65
|
+
# # points contract - resolve in type hierarchy
|
66
|
+
# decl = exp.memberStruct.declationRef.resolveMemberOrReportError( exp.member_name )
|
67
|
+
elsif exp.memberStruct.declationRef.respond_to?( :isScope ) && exp.memberStruct.declationRef.isScope
|
68
|
+
# points to scope (parameterlist?) - resolve within scope
|
69
|
+
decl = exp.memberStruct.declationRef.resolveOrReportError( exp.member_name )
|
70
|
+
else
|
71
|
+
# it is variable declaration
|
72
|
+
logger.debug "#{__method__}: use exp.memberStruct.declationRef=#{exp.memberStruct.declationRef} to resolve '#{exp.member_name}'" if logger.debug?
|
73
|
+
declarationType = exp.memberStruct.declationRef.typeSexp
|
74
|
+
decl = declarationType.symbolTypeReference.resolveOrReportError( exp.member_name )
|
75
|
+
end
|
76
|
+
|
77
|
+
# and finally set the result
|
78
|
+
exp.declationRef= decl
|
79
|
+
logger.info "#{__method__}: resolved declaration #{decl} on member access #{exp}"
|
80
|
+
|
81
|
+
s()
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# s( :NewExpression, s(:UserDefinedTypeName) -> resolve fist
|
86
|
+
# contract and then resolve constructor
|
87
|
+
def process_NewExpression( exp )
|
88
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
89
|
+
|
90
|
+
# name of constructor called
|
91
|
+
contructorCalled = exp.contractConstructed.name
|
92
|
+
|
93
|
+
# TODO: use some DRY method to map contract to constructor interface
|
94
|
+
constructorInterface="#{contructorCalled}()"
|
95
|
+
|
96
|
+
# Find contract, and within it resolve construtor interface
|
97
|
+
contractResolved = exp.enclosingScope.resolveOrReportError( contructorCalled )
|
98
|
+
constructorResolved = contractResolved.resolveOrReportError( constructorInterface )
|
99
|
+
logger.info "#{__method__}: contractResolved=#{contractResolved}, constructorResolved=#{constructorResolved}"
|
100
|
+
|
101
|
+
# Resolve succsess
|
102
|
+
exp.declationRef = constructorResolved
|
103
|
+
s()
|
104
|
+
end
|
105
|
+
|
106
|
+
def process_Identifier( exp )
|
107
|
+
raise "Could not set declaration ref on #{exp}" unless exp.isDeclarationRef
|
108
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
109
|
+
|
110
|
+
# was set in SexpProcessorSymbolTable1
|
111
|
+
scope = exp.enclosingScope
|
112
|
+
|
113
|
+
# now resolve reference
|
114
|
+
decl = scope.resolveOrReportError( exp.value )
|
115
|
+
logger.info "#{__method__}, resolved #{exp.value} -> #{decl.inspect}"
|
116
|
+
exp.declationRef= decl
|
117
|
+
|
118
|
+
# continue with tree traversal
|
119
|
+
process_rest( exp )
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
def process_Domain( exp)
|
124
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
125
|
+
typeName = exp.solidityType
|
126
|
+
|
127
|
+
if typeName
|
128
|
+
|
129
|
+
# typeName defined, for example on address domain, resolve
|
130
|
+
# 'symbolTypeReference' to point to solidity elementary type
|
131
|
+
# defined on global scope.
|
132
|
+
|
133
|
+
typeSymbol = exp.scopeDefining.globalScope.resolveOrReportError(typeName)
|
134
|
+
logger.info "#{__method__}: type resolve --> typeName=#{typeName} resolved to typeSymbol=#{typeSymbol}"
|
135
|
+
|
136
|
+
exp.symbolTypeReference = typeSymbol
|
137
|
+
end
|
138
|
+
process_rest( exp );
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def process_ElementaryTypeName( exp)
|
144
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
145
|
+
|
146
|
+
typeName = exp.typeName
|
147
|
+
# elementary types defined in global scope
|
148
|
+
typeSymbol = exp.scopeDefining.globalScope.resolveOrReportError( typeName )
|
149
|
+
logger.info "#{__method__}: type resolve --> typeName=#{typeName} resolved to typeSymbol=#{typeSymbol}"
|
150
|
+
|
151
|
+
exp.symbolTypeReference = typeSymbol
|
152
|
+
process_rest( exp )
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# resolve type of variable declarion
|
158
|
+
def process_UserDefinedTypeName( exp )
|
159
|
+
logger.debug "#{__method__}: #{exp}" if logger.debug?
|
160
|
+
|
161
|
+
typeName = exp.name
|
162
|
+
typeSymbol = exp.scopeDefining.resolveOrReportError( typeName )
|
163
|
+
raise "typeSymbol #{typeSymbol} is not 'TypeSymbol'" unless typeSymbol.respond_to?(:isTypeSymbol) && typeSymbol.isTypeSymbol
|
164
|
+
logger.info "#{__method__}: type resolve --> typeName=#{typeName} resolved to typeSymbol=#{typeSymbol}"
|
165
|
+
|
166
|
+
exp.symbolTypeReference = typeSymbol
|
167
|
+
process_rest( exp )
|
168
|
+
end
|
169
|
+
|
170
|
+
# @!endgroup
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|