sbuilder-eth 0.0.4
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/README.org +19 -0
- data/VERSION +1 -0
- data/bin/state-explorer.sh +215 -0
- data/lib/eth/al_api.rb +12 -0
- data/lib/eth/ast_sexp.rb +519 -0
- data/lib/eth/constants.rb +354 -0
- data/lib/eth/ethereum.rb +2054 -0
- data/lib/eth/ethereum_expression.rb +476 -0
- data/lib/eth/exception.rb +9 -0
- data/lib/eth/global_scope.rb +100 -0
- data/lib/eth/module.rb +18 -0
- data/lib/eth/sexp_processor.rb +66 -0
- data/lib/eth/sexp_processor_call_separator.rb +163 -0
- data/lib/eth/sexp_processor_getter.rb +125 -0
- data/lib/eth/sexp_processor_resolve.rb +122 -0
- data/lib/eth/sexp_processor_scope.rb +355 -0
- data/lib/eth/sexp_utils.rb +214 -0
- data/lib/eth/solidity_compiler.rb +145 -0
- data/lib/eth/solidity_loader.rb +53 -0
- data/lib/eth/solidity_translator.rb +840 -0
- data/lib/mixer/reference.rb +30 -0
- data/lib/mixer/scope.rb +100 -0
- data/lib/mixer/scoped.rb +18 -0
- data/lib/plugin/controller.rb +267 -0
- data/lib/plugin/module.rb +3 -0
- data/lib/plugin/plugin.rb +33 -0
- data/lib/sbuilder-eth.rb +6 -0
- data/sbuilder-eth.gemspec +38 -0
- metadata +149 -0
@@ -0,0 +1,476 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Sbuilder
|
3
|
+
|
4
|
+
module Eth
|
5
|
+
|
6
|
+
# Module to include to Ethreum class containing methods to
|
7
|
+
# translate Solidity expression to Al language expressions.
|
8
|
+
module EthereumExpression
|
9
|
+
|
10
|
+
# ------------------------------------------------------------------
|
11
|
+
# @!group Distpath reference to lvalue
|
12
|
+
|
13
|
+
# @!endgroup
|
14
|
+
|
15
|
+
|
16
|
+
# Dispatch lval reference based lval AST node sexp_type.
|
17
|
+
#
|
18
|
+
# @return [TlaSexp] :Identifier -> name (='value' attribute),
|
19
|
+
# :IndexAccess => [ raise TODO ]
|
20
|
+
def lvalAccessDistpatcher
|
21
|
+
@lvalAccessDistpatched || {
|
22
|
+
:Identifier => ->(identifierAst) { identifierAst['value'] },
|
23
|
+
:IndexAccess => ->(indexAccessAst) do
|
24
|
+
#intetifierAst = indexAccessAst.identifier
|
25
|
+
indexerAst = indexAccessAst.indexer
|
26
|
+
indexer = Ethereum.dispatcher( expressionDispatcher, indexerAst.sexp_type, indexerAst)
|
27
|
+
alApi.tlaRecordIndex(indexAccessAst.identifier['value'], indexer )
|
28
|
+
end,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
# ------------------------------------------------------------------
|
33
|
+
# @!group Expression translation
|
34
|
+
|
35
|
+
# Translate 'expressionAst' using {#expressionDispatcher}.
|
36
|
+
#
|
37
|
+
# @return [Al::Expression] trasnalation of 'expressionAst'
|
38
|
+
#
|
39
|
+
def dispatchExpression( expressionAst ) #
|
40
|
+
@logger.debug( "#{__method__}: expressionAst=#{expressionAst}" ) if @logger.debug?
|
41
|
+
Ethereum.dispatcher( expressionDispatcher, expressionAst.sexp_type, expressionAst)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Dispatch tranlation for Solidity AST expression based
|
45
|
+
# sexp_type of expression sexp_type.
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# @return [Hash] :sexp_type => lambda(AstSexp) to tranlate
|
49
|
+
# Solidity AST node to AL language expression
|
50
|
+
def expressionDispatcher
|
51
|
+
@expressionDispatcher ||= {
|
52
|
+
:ExpressionContext => ->(contextAst) do
|
53
|
+
# dispatch again using sexp_type of the wrapped expressionAst
|
54
|
+
Ethereum.dispatcher( expressionDispatcher, contextAst.expressionAst.sexp_type, contextAst)
|
55
|
+
end,
|
56
|
+
:BinaryOperation => method(:binaryExpr),
|
57
|
+
:Literal => method(:constantExpr),
|
58
|
+
:FunctionCall => method(:functionResponseExpr),
|
59
|
+
:Identifier => method(:identifierExpr),
|
60
|
+
:MemberAccess => method( :memberAccessExpr),
|
61
|
+
:IndexAccess => method( :indexAccessExpr ),
|
62
|
+
:TupleExpression => method( :tupleExpression ),
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Translate expression for 'functionCall' to read operator call
|
67
|
+
# reading function response, and accessing return value.
|
68
|
+
#
|
69
|
+
# Assume: pre-processor has added function call just prior to
|
70
|
+
# the statement accessing function response value)
|
71
|
+
#
|
72
|
+
# TODO: should add support to manage tuple return values from
|
73
|
+
# function call
|
74
|
+
#
|
75
|
+
# @param ast [ExpressionContext,:FunctionCall] function call (or
|
76
|
+
# function wrapped into context) to create expression to
|
77
|
+
# access response from function call
|
78
|
+
|
79
|
+
def functionResponseExpr( ast )
|
80
|
+
@logger.info "#{__method__}: ast=#{ast}" if @logger.debug?
|
81
|
+
|
82
|
+
if ast.sexp_type == :ExpressionContext
|
83
|
+
functionCallStmt = ast.expressionAst
|
84
|
+
else
|
85
|
+
functionCallStmt = ast
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# call target
|
90
|
+
functionCalled = functionCallStmt.callTarget # functionCallStmt.functionCalled.reference
|
91
|
+
contractCalled = functionCalled.enclosingScope
|
92
|
+
@logger.info "#{__method__} called= #{contractCalled['name']}(#{functionCalled['name']})"
|
93
|
+
|
94
|
+
# TODO: add suppport for tuples
|
95
|
+
if ( functionCallStmt.isConstructorCall )
|
96
|
+
# contrcutors return addres
|
97
|
+
returnParameter = Constants::FIELD_NAME_ADDRESS
|
98
|
+
else
|
99
|
+
# normal function
|
100
|
+
raise MissingImplementation, "Support only 1 return value, called f with #{functionCalled.responseParameters.parameters.length} params" if functionCalled.responseParameters.parameters.length != 1
|
101
|
+
returnParameter = functionCalled.responseParameters.parameters[0]['name']
|
102
|
+
end
|
103
|
+
|
104
|
+
# access return variable in function response
|
105
|
+
alApi.tlaRecordField(
|
106
|
+
alApi.tlaOperatorCall(alApi.tlaPlainname(Constants::SBUILDER_GET_RESPONSE), [exprInterfaceOperation(contractCalled['name'], functionCalled['name'])]),
|
107
|
+
returnParameter
|
108
|
+
)
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# Translate tupleExpression by translating each tuple element
|
114
|
+
# indididually with {#dispatchExpression}.
|
115
|
+
#
|
116
|
+
# @return [Array<AlExpression>] array of translated expressions
|
117
|
+
#
|
118
|
+
def tupleExpression( tupleAst )
|
119
|
+
|
120
|
+
@logger.info "#{__method__}: proces tuple with #{tupleAst.children.length} elements"
|
121
|
+
tupleAst.children.map do |tupleElement|
|
122
|
+
dispatchExpression( tupleElement )
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
# Translate Solidity AST node of type :BinaryOperation to
|
129
|
+
# al-binary expression. Left hand side and right hand side
|
130
|
+
# expresions are dispatched using {#expressionDispatcher}, and
|
131
|
+
# operator translated using {#binaryOperator}. Evaluate in
|
132
|
+
# {ExpressionContext}, if 'ast' is defined within
|
133
|
+
# {ExpressionContext}.
|
134
|
+
#
|
135
|
+
# @param ast [ExpressionContext,Identifier] identifier (or
|
136
|
+
# identifier wrapped in context) to create expression for.
|
137
|
+
#
|
138
|
+
def binaryExpr( ast )
|
139
|
+
|
140
|
+
if ast.sexp_type == :ExpressionContext
|
141
|
+
|
142
|
+
# Evaluate lval and rval in ExpressionContext
|
143
|
+
lExpr = Ethereum.dispatcher( expressionDispatcher,
|
144
|
+
ast.expressionAst.children[0].sexp_type,
|
145
|
+
ExpressionContext.createExpressionContext( ast.expressionAst.children[0], ast.context )
|
146
|
+
)
|
147
|
+
rExpr = Ethereum.dispatcher( expressionDispatcher,
|
148
|
+
ast.expressionAst.children[1].sexp_type,
|
149
|
+
ExpressionContext.createExpressionContext( ast.expressionAst.children[1], ast.context )
|
150
|
+
)
|
151
|
+
operator = ast.expressionAst['operator']
|
152
|
+
|
153
|
+
else
|
154
|
+
# No context given - extract element of bin expression
|
155
|
+
lExpr = Ethereum.dispatcher( expressionDispatcher,
|
156
|
+
ast.children[0].sexp_type,
|
157
|
+
ast.children[0]
|
158
|
+
)
|
159
|
+
operator = ast['operator']
|
160
|
+
rExpr = Ethereum.dispatcher( expressionDispatcher,
|
161
|
+
ast.children[1].sexp_type,
|
162
|
+
ast.children[1]
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
166
|
+
alApi.binaryExpression do
|
167
|
+
lval lExpr
|
168
|
+
op binaryOperator(operator)
|
169
|
+
rval rExpr
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
# Translate 'solidityOperator' to 'alOperator. Raise
|
176
|
+
# {#MissingImplementation} if no translation found.
|
177
|
+
def binaryOperator( solidityOperator )
|
178
|
+
# TODO : map to AL-constants
|
179
|
+
solidityOperators = {
|
180
|
+
"*" => :mult,
|
181
|
+
"+" => :plus,
|
182
|
+
"-" => :minus,
|
183
|
+
"&&" => :and,
|
184
|
+
"||" => :or,
|
185
|
+
"==" => :equal,
|
186
|
+
"!=" => :unequal,
|
187
|
+
">=" => :ge,
|
188
|
+
">" => :gt,
|
189
|
+
"<" => :lt,
|
190
|
+
"<=" => :le,
|
191
|
+
}
|
192
|
+
alOperator = solidityOperators[solidityOperator]
|
193
|
+
raise MissingImplementation, "Unknown solidity operator #{solidityOperator} - known Solidity operators #{solidityOperators.keys.join(',')}" if alOperator.nil?
|
194
|
+
alOperator
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
# Translate Solidity :Literal to AL Constant
|
199
|
+
# expression. Translation inspects AST 'type' attribute to
|
200
|
+
# choose correct intepration for AST 'value' attribute.
|
201
|
+
#
|
202
|
+
# @param ast [ExpressionContext,Constant] constant (or constant
|
203
|
+
# wrapped in context) to create expression for.
|
204
|
+
#
|
205
|
+
#
|
206
|
+
def constantExpr( ast )
|
207
|
+
|
208
|
+
# Context does no impact constant trasnlation
|
209
|
+
if ast.sexp_type == :ExpressionContext
|
210
|
+
constantAst = ast.expressionAst
|
211
|
+
else
|
212
|
+
constantAst = ast
|
213
|
+
end
|
214
|
+
|
215
|
+
case constantAst.attribute("type")
|
216
|
+
when /^literal_string/
|
217
|
+
alApi.constantExpression do
|
218
|
+
value constantAst.attribute('value')
|
219
|
+
end
|
220
|
+
when /^int_const */
|
221
|
+
alApi.constantExpression do
|
222
|
+
value constantAst.attribute('value').to_i
|
223
|
+
end
|
224
|
+
when /^bool/
|
225
|
+
alApi.constantExpression do
|
226
|
+
value constantAst.attribute('value') == "true"
|
227
|
+
end
|
228
|
+
else
|
229
|
+
raise TranslatorException, "Missing implementation for constant expression type '#{constantAst.attribute('type')}' in #{constantAst}"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Create expression to access member in an identifier.
|
234
|
+
#
|
235
|
+
# Implementation find path for member variables, and creates an
|
236
|
+
# {#identifierExpression}. expression to access member of the
|
237
|
+
# identifier of 'memberAccessAst'
|
238
|
+
#
|
239
|
+
# @param ast [ExpressionContext,MemberAccess] MemberAccess (or
|
240
|
+
# MemberAccess wrapped in context) to create expression
|
241
|
+
# for.
|
242
|
+
#
|
243
|
+
def memberAccessExpr( ast )
|
244
|
+
@logger.debug "#{__method__}: ast=#{ast}" if @logger.debug?
|
245
|
+
|
246
|
+
if ast.sexp_type == :ExpressionContext
|
247
|
+
memberAccessAst = ast.expressionAst
|
248
|
+
# Evaluate idExpression within context
|
249
|
+
idExpression = Ethereum.dispatcher( expressionDispatcher,
|
250
|
+
ast.expressionAst.identifierAst.sexp_type,
|
251
|
+
ExpressionContext.createExpressionContext( ast.expressionAst.identifierAst, ast.context )
|
252
|
+
)
|
253
|
+
|
254
|
+
else
|
255
|
+
memberAccessAst = ast
|
256
|
+
# Create id expression
|
257
|
+
idExpression = Ethereum.dispatcher( expressionDispatcher,
|
258
|
+
ast.identifierAst.sexp_type,
|
259
|
+
ast.identifierAst )
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
@logger.debug "#{__method__}: memberAccessAst.member=#{memberAccessAst.memberName}, idExpression=#{idExpression}" if @logger.debug?
|
264
|
+
# Translation to 'idExpression.member'
|
265
|
+
alApi.tlaRecordField( idExpression, memberAccessAst.memberName )
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
# Create expression for Solidity identifier. Evaluate identifier
|
271
|
+
# in 3 cases 1) in existing contract context (e.g. assign
|
272
|
+
# statement) 2) in context (but not for contract) 3) without
|
273
|
+
# context.
|
274
|
+
#
|
275
|
+
# Expression identifier may be available in execution context,
|
276
|
+
# for example in TLA action updating contract variable uses set
|
277
|
+
# operation and an iteration variable for contracts. In this
|
278
|
+
# case, reference to a contract should be resolved to set
|
279
|
+
# iteration variable.
|
280
|
+
#
|
281
|
+
#
|
282
|
+
#
|
283
|
+
# @param ast [ExpressionContext,Identifier] identifier (or
|
284
|
+
# identifier wrapped in context) to create expression for.
|
285
|
+
#
|
286
|
+
# @return [Al::Expression] 1) Al expression such as 'a.idName'
|
287
|
+
# if ast.sexp_type == :ExpressionContext && context for
|
288
|
+
# scope of variable declation found in context. 2)
|
289
|
+
# create expression using {#identifierReference} - else
|
290
|
+
def identifierExpr( ast )
|
291
|
+
@logger.debug "#{__method__}: ast=#{ast}" if @logger.debug?
|
292
|
+
|
293
|
+
if ast.sexp_type == :ExpressionContext && ast.getContext( ast.expressionAst.reference.scopeDefining.sexp_type ) && ast.expressionAst['value'] != Constants::SOL_THIS
|
294
|
+
|
295
|
+
# if context found for variable scope
|
296
|
+
translation = alApi.tlaRecordField(
|
297
|
+
ast.getContext( ast.expressionAst.reference.scopeDefining.sexp_type ),
|
298
|
+
ast.expressionAst['value']
|
299
|
+
)
|
300
|
+
|
301
|
+
elsif ast.sexp_type == :ExpressionContext
|
302
|
+
|
303
|
+
# in context but no match -> continue evaluation in context
|
304
|
+
translation = alApi.expression(identifierReference( ast.expressionAst ))
|
305
|
+
|
306
|
+
else
|
307
|
+
|
308
|
+
# Resolve direct reference to identifier
|
309
|
+
translation = alApi.expression(identifierReference( ast ))
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
@logger.debug( "#{__method__}: translation=#{translation.strOutput}") if @logger.debug?
|
314
|
+
translation
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
# Create expression to access indexed element of identifer. Use
|
319
|
+
# {#expressionDispatcher} to dispatch 'identifier' and 'indexer'
|
320
|
+
# expresion of IndexAccess AST node (possible wrapped within
|
321
|
+
# ExpressionContext).
|
322
|
+
#
|
323
|
+
# @param ast [ExpressionContext,IndexAccess] IndexAccess (or
|
324
|
+
# IndexAccess wrapped in context) to create expression
|
325
|
+
# for.
|
326
|
+
#
|
327
|
+
#
|
328
|
+
# @return [Al::Expression] expression to access indexed member
|
329
|
+
def indexAccessExpr( ast )
|
330
|
+
@logger.debug "#{__method__}: ast=#{ast}" if @logger.debug?
|
331
|
+
|
332
|
+
if ast.sexp_type == :ExpressionContext
|
333
|
+
indexerAst = ast.expressionAst
|
334
|
+
# eval identifier with context
|
335
|
+
indexExpr = Ethereum.dispatcher(
|
336
|
+
expressionDispatcher,
|
337
|
+
indexerAst.identifier.sexp_type,
|
338
|
+
ExpressionContext.createExpressionContext(indexerAst.identifier, ast.context )
|
339
|
+
)
|
340
|
+
indexer = Ethereum.dispatcher(
|
341
|
+
expressionDispatcher, indexerAst.indexer.sexp_type,
|
342
|
+
ExpressionContext.createExpressionContext(indexerAst.indexer, ast.context )
|
343
|
+
)
|
344
|
+
else
|
345
|
+
indexAccessAst = ast
|
346
|
+
indexExpr = Ethereum.dispatcher(
|
347
|
+
expressionDispatcher,
|
348
|
+
indexerAst.identifier.sexp_type,
|
349
|
+
indexerAst.identifier
|
350
|
+
)
|
351
|
+
indexer = Ethereum.dispatcher(
|
352
|
+
expressionDispatcher, indexerAst.indexer.sexp_type,
|
353
|
+
indexerAst.indexer
|
354
|
+
)
|
355
|
+
end
|
356
|
+
|
357
|
+
alApi.tlaRecordIndex( indexExpr, indexer )
|
358
|
+
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
|
363
|
+
# @!endgroup
|
364
|
+
|
365
|
+
|
366
|
+
# ------------------------------------------------------------------
|
367
|
+
# @!group Resolve identifier reference
|
368
|
+
|
369
|
+
# Use dispatcher {#referenceContextDispatcher} to create a
|
370
|
+
# reference to 'identifierAst'.
|
371
|
+
#
|
372
|
+
# Impelementation user pointer chain
|
373
|
+
# identifierAst.reference.scopeDefining to find 1) variable
|
374
|
+
# declaration and 2) scope of declaration to dispatch correct
|
375
|
+
# translation method in {#referenceContextDispatcher}.
|
376
|
+
#
|
377
|
+
# @param identifierAst [Identifier] AST node to resolve.
|
378
|
+
def identifierReference( identifierAst )
|
379
|
+
# identifierAst = context[:identifierAst]
|
380
|
+
@logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
381
|
+
@logger.info "#{__method__}: ident:'#{identifierAst['value']}'" +
|
382
|
+
" decl.ref='#{identifierAst.reference.key?( "name") ? identifierAst.reference['name'] : '??' }:#{identifierAst&.reference.sexp_type}'" +
|
383
|
+
", scope='#{identifierAst.reference.scopeDefining.respond_to?( :sexp_type) ? identifierAst.reference.scopeDefining.sexp_type : identifierAst.reference.scopeDefining.class }'"
|
384
|
+
|
385
|
+
ref = identifierAst.reference.scopeDefining
|
386
|
+
|
387
|
+
# Reference has already been resolde (e.g. :ModifierIncation)
|
388
|
+
return( ref ) if ref.is_a? Sbuilder::Al::Model::Expression
|
389
|
+
#
|
390
|
+
Ethereum.dispatcher( referenceContextDispatcher, ref.sexp_type, identifierAst )
|
391
|
+
end
|
392
|
+
|
393
|
+
|
394
|
+
# Reference to identifier depends on the type of the scope,
|
395
|
+
# where the variable, referenced by 'identifierAst', is declared
|
396
|
+
# in.
|
397
|
+
#
|
398
|
+
# Scope may be ::GlobalScope -> e.g. this, :ContractDefinition
|
399
|
+
# --> contract member variable #{contractContextReference},
|
400
|
+
# :FunctionDefinition --> function local varibale
|
401
|
+
# {#functionContextReference}, :ParameterList --> to access
|
402
|
+
# Solidity 'msg' {#parameterContextReference},
|
403
|
+
#
|
404
|
+
def referenceContextDispatcher
|
405
|
+
@referenceContextDispatcher ||= {
|
406
|
+
:GlobalScope => method(:globalContextReference),
|
407
|
+
:ContractDefinition =>method(:contractContextReference),
|
408
|
+
:FunctionDefinition =>method(:functionContextReference),
|
409
|
+
:ParameterList=>method(:parameterContextReference),
|
410
|
+
}
|
411
|
+
end
|
412
|
+
|
413
|
+
# Currently runnign contract found in local variable 'refRunningContractAddress'
|
414
|
+
#
|
415
|
+
# @return [Al::Reference] reference to currenly running contract
|
416
|
+
def globalContextReference(identifierAst)
|
417
|
+
@logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
418
|
+
raise "Supports only '#{Constants::SOL_THIS}' - unkwon #{identifierAst['value']}" unless identifierAst['value'] == Constants::SOL_THIS
|
419
|
+
|
420
|
+
refRunningContractAddress
|
421
|
+
end
|
422
|
+
|
423
|
+
# # Create a reference for an identifier in :ModifierDefinition
|
424
|
+
# # context, which has been invoked :ModifierInvocation for a
|
425
|
+
# # function (sexp_type :FunctionDefinition).
|
426
|
+
# def modifierContextReference( identifierAst )
|
427
|
+
# @logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
428
|
+
# functionAst = identifierAst.reference.scopeDefining
|
429
|
+
# raise "identifierAst=#{identifierAst}\n\nidentifierAst.reference=#{identifierAst.reference}\n\nfunctionAst=#{functionAst}"
|
430
|
+
# end
|
431
|
+
|
432
|
+
# Create a reference to member variable of currently running
|
433
|
+
# contract.
|
434
|
+
#
|
435
|
+
# Contract members variables are fields in records in
|
436
|
+
# 'storageRoot' variable. Current contract is pointed by
|
437
|
+
# {#refRunningContractAddress} (, which is local variable with
|
438
|
+
# the 'address' of currently running contract ).
|
439
|
+
#
|
440
|
+
def contractContextReference( identifierAst )
|
441
|
+
@logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
442
|
+
contract = identifierAst.reference.scopeDefining
|
443
|
+
if identifierAst['value'] == Constants::SOL_THIS
|
444
|
+
# this found in local varible thisCid
|
445
|
+
refRunningContractAddress
|
446
|
+
else
|
447
|
+
ethContractVariableReference( refStorageRoot, refRunningContractAddress, identifierAst['value'] )
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
# Translate reference to function local variable.
|
452
|
+
def functionContextReference( identifierAst )
|
453
|
+
@logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
454
|
+
function = identifierAst.reference.scopeDefining
|
455
|
+
contract = function.enclosingScope
|
456
|
+
|
457
|
+
ethFunctionParameterReference( contract['name'], function['name'] )
|
458
|
+
end
|
459
|
+
|
460
|
+
# Translate reference to an identifier in function paramers (=Solidity 'msg')
|
461
|
+
#
|
462
|
+
# Msg variable is accessed in a parameter passed to the
|
463
|
+
# procedure created to model 'contract' 'function'.
|
464
|
+
def parameterContextReference( identifierAst )
|
465
|
+
@logger.debug "#{__method__}: identifierAst=#{identifierAst}" if @logger.debug?
|
466
|
+
function = identifierAst.reference.scopeDefining.enclosingScope
|
467
|
+
contract = function.enclosingScope
|
468
|
+
ethFunctionParameterReference( contract['name'], function['name'], identifierAst['value'] )
|
469
|
+
end
|
470
|
+
|
471
|
+
|
472
|
+
# @!endgroup
|
473
|
+
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|