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,1206 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Ethereum
|
3
|
+
|
4
|
+
###
|
5
|
+
# Api to create TLA generate elements i.e. data SEXPs defining TLA
|
6
|
+
# language elements, and mustache partials to render data
|
7
|
+
# SEXPs to TLA language.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
class TlaElementGenerator
|
11
|
+
|
12
|
+
PROGNAME = nil # progname for logger default class name
|
13
|
+
include MyLogger # mix logger
|
14
|
+
|
15
|
+
# @attr [Hash] partials intialized with #setPartials, cumulated
|
16
|
+
# using #addPartial
|
17
|
+
attr_reader :partials
|
18
|
+
|
19
|
+
# @attr [Hash] partials_duplicateCheck, used only as guarantee
|
20
|
+
# againts redefinition
|
21
|
+
attr_reader :partials_duplicateCheck
|
22
|
+
|
23
|
+
# @attr [Hash] validMetatypes raise exception for unknwon mentateyps
|
24
|
+
attr_reader :validMetatypes
|
25
|
+
|
26
|
+
# @attr [Hash] labeledStmts
|
27
|
+
#
|
28
|
+
# @option labeledStmts [:Symbol] <sTlaType> generate template
|
29
|
+
# map to true is label should be followed
|
30
|
+
attr_reader :labeledStmts
|
31
|
+
|
32
|
+
# text to prefix trace print
|
33
|
+
TRACE_PREFIX="TRACE>"
|
34
|
+
|
35
|
+
# ------------------------------------------------------------------
|
36
|
+
# @!group Construct & configure
|
37
|
+
|
38
|
+
def initialize( options = {} )
|
39
|
+
@options = options
|
40
|
+
@logger = getLogger( nil, options )
|
41
|
+
@logger.info "#{__method__}: initalized"
|
42
|
+
|
43
|
+
# initially no known template requiring labe
|
44
|
+
@labeledStmts = {}
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def setPartials( partials )
|
49
|
+
@partials = partials
|
50
|
+
@partials_duplicateCheck = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def setValidMetatypes( validMetatypes )
|
54
|
+
@validMetatypes = validMetatypes
|
55
|
+
end
|
56
|
+
# @!endgroup
|
57
|
+
|
58
|
+
# ------------------------------------------------------------------
|
59
|
+
# @!group Statement labeling
|
60
|
+
|
61
|
+
##
|
62
|
+
# Configure +sTlaType+ in +labeledStmts+ to require a label
|
63
|
+
#
|
64
|
+
# @see requiresLabelAfter
|
65
|
+
def tlaStatementTypeRequiresLabel( sTlaType )
|
66
|
+
labeledStmts[sTlaType] = true
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Flag +stmt+ to include label if +hiddenStmt+ requires label.
|
71
|
+
#
|
72
|
+
# @param [Boolean ] labelFollowingStatemaent used return 'true'
|
73
|
+
# for 'isLabedStatement' if within a block. If not within block delegate
|
74
|
+
# to labedStatement
|
75
|
+
#
|
76
|
+
# @see requiresLabelAfter
|
77
|
+
def statementRequiresLabel( stmt, labedStatement=nil )
|
78
|
+
stmt.define_singleton_method( :labelFollowingStatement ) do |inBlock|
|
79
|
+
return true if labedStatement.nil?
|
80
|
+
inBlock ? true : labedStatement
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Statement 'stmt' contains a block with 'stmts', which should
|
86
|
+
# also be labeled. Later, use :labelBlockStatements to return
|
87
|
+
# 'stmts' to label.
|
88
|
+
def setLabelBlockStatements( stmt, stmts, methodName = :labelBlockStatements )
|
89
|
+
stmt.define_singleton_method( methodName ) do
|
90
|
+
stmts
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
##
|
96
|
+
# Check whether +stmt+ with +stmt.sexp_type+ should be followed
|
97
|
+
# by a labeled statement.
|
98
|
+
#
|
99
|
+
# @param [SexpTla] stmt sexp which may respond to ':labelFollowingStatement'
|
100
|
+
#
|
101
|
+
# @return [Boolean] true is +sTlaType+ is found in
|
102
|
+
# +labeledStmts+ hash OR stmt.labelFollowingStatement
|
103
|
+
def requiresLabelAfter( stmt, inBlock=false )
|
104
|
+
return false unless stmt
|
105
|
+
# if s( s(:sym, ..), s(:sym,)) vs. s(:sym, ..)
|
106
|
+
sTlaType = stmt.any? && !stmt[0].is_a?(Symbol) ? stmt.last.sexp_type : stmt.sexp_type
|
107
|
+
|
108
|
+
# static
|
109
|
+
if labeledStmts[sTlaType] ||
|
110
|
+
( stmt.respond_to?(:labelFollowingStatement) && stmt.labelFollowingStatement(inBlock))
|
111
|
+
return true
|
112
|
+
end
|
113
|
+
# dynamic recursion to block
|
114
|
+
if stmt.respond_to?(:requiresLabelAfterChecker)
|
115
|
+
stmt.requiresLabelAfterChecker.each do |st|
|
116
|
+
return true if requiresLabelAfter( st, true )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
# @!endgroup
|
125
|
+
|
126
|
+
# ------------------------------------------------------------------
|
127
|
+
# @!group Create TLA specific generate element SEXPs
|
128
|
+
|
129
|
+
def gen_label_it( tla )
|
130
|
+
sym = :TLA_label_it
|
131
|
+
tlaStatementTypeRequiresLabel( sym )
|
132
|
+
addPartial( sym, "{|#EVAL|}tla{|/EVAL|}" )
|
133
|
+
stla( sym, { :tla => tla } )
|
134
|
+
end
|
135
|
+
|
136
|
+
def gen_macro( name, parameters, stmts )
|
137
|
+
|
138
|
+
sym = :TLA_macro
|
139
|
+
addPartial(
|
140
|
+
sym,
|
141
|
+
"macro {|#EVAL|}name{|/EVAL|}( {|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|} ) {\n"\
|
142
|
+
"{|#EVAL|}stmts{|/EVAL|}"\
|
143
|
+
"}"
|
144
|
+
)
|
145
|
+
|
146
|
+
# allow singleton parameter
|
147
|
+
parameters = parameters.is_a?( Array ) ? parameters : [parameters]
|
148
|
+
|
149
|
+
stla( sym, {
|
150
|
+
:name => name,
|
151
|
+
:parameters => parameters.any? ?
|
152
|
+
parameters.map.with_index do |p,i|
|
153
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
154
|
+
:parameter => p.is_a?(String) ? gen_plainname( p ): p,
|
155
|
+
}
|
156
|
+
end :
|
157
|
+
false,
|
158
|
+
:stmts => stmts,
|
159
|
+
})
|
160
|
+
end
|
161
|
+
|
162
|
+
def gen_service_procedure( serviceName, interfaceName, localVariables, stmts=gen_stmts(s()) )
|
163
|
+
|
164
|
+
sym = :TLA_Procedure
|
165
|
+
addPartial(
|
166
|
+
sym,
|
167
|
+
<<-EOS.unindent
|
168
|
+
procedure {|#EVAL|}name{|/EVAL|}( {|#EVAL|}name{|/EVAL|}_input )
|
169
|
+
{|#localVariables.length|}variable {|/localVariables.length|}{|#localVariables|} {|#EVAL|}variable{|/EVAL|}{|_comma|}{|/localVariables|}{|#localVariables.length|};{|/localVariables.length|}
|
170
|
+
{
|
171
|
+
{|#EVAL|}name{|/EVAL|}_start:
|
172
|
+
{|#EVAL|}start{|/EVAL|};
|
173
|
+
|
174
|
+
(* body of {|#EVAL|}interfaceName{|/EVAL|} *)
|
175
|
+
{|#EVAL|}stmts{|/EVAL|}
|
176
|
+
|
177
|
+
{|#EVAL|}name{|/EVAL|}_exit:
|
178
|
+
goto {|#EVAL|}name{|/EVAL|}#{TlaElementText::TLA_LABEL_END};
|
179
|
+
{|#EVAL|}name{|/EVAL|}#{TlaElementText::TLA_LABEL_FAIL}:
|
180
|
+
\\* throw command sends here
|
181
|
+
InfrastructureServiceReturn( "{|#EVAL|}interfaceName{|/EVAL|}", FALSE, Nil);
|
182
|
+
goto {|#EVAL|}name{|/EVAL|}_end;
|
183
|
+
|
184
|
+
{|#EVAL|}name{|/EVAL|}#{TlaElementText::TLA_LABEL_ABORT}:
|
185
|
+
\\* should not happen??
|
186
|
+
print <<"ABORT {|#EVAL|}name{|/EVAL|}">>;
|
187
|
+
InfrastructureServiceReturn( "{|#EVAL|}interfaceName{|/EVAL|}", Abort, Nil);
|
188
|
+
\\* schedule_throw( "{|#EVAL|}name{|/EVAL|}_exit" );
|
189
|
+
{|#EVAL|}name{|/EVAL|}#{TlaElementText::TLA_LABEL_END}:
|
190
|
+
ethereum_service_pop( "{|#EVAL|}interfaceName{|/EVAL|}" );
|
191
|
+
{|#EVAL|}return{|/EVAL|};
|
192
|
+
}
|
193
|
+
EOS
|
194
|
+
)
|
195
|
+
|
196
|
+
name = serviceName.is_a?( String) ? gen_plainname(serviceName) : serviceName
|
197
|
+
entry_exit = s(
|
198
|
+
gen_str(serviceName),
|
199
|
+
TlaElementText::FW_STATE_ACCOUNTS_TEMP, gen_specname(:eth, TlaElementText::FW_STATE_ACCOUNTS_TEMP),
|
200
|
+
TlaElementText::FW_STATE_STORAGE_ROOT_TEMP, gen_specname(:eth, TlaElementText::FW_STATE_STORAGE_ROOT_TEMP),
|
201
|
+
# TlaElementText::FW_STATE_GAS_USED_TEMP, gen_specname(:eth, TlaElementText::FW_STATE_GAS_USED_TEMP),
|
202
|
+
TlaElementText::FW_STATE_MINED, gen_specname(:eth, TlaElementText::FW_STATE_MINED),
|
203
|
+
"input", gen_identifier( name, "_input" ),
|
204
|
+
)
|
205
|
+
|
206
|
+
stla( sym, {
|
207
|
+
:name => name,
|
208
|
+
:localVariables => localVariables.map.with_index do |v,i|
|
209
|
+
{
|
210
|
+
:variable => v,
|
211
|
+
:_comma => (i+1) == localVariables.length ? '' : ',',
|
212
|
+
}
|
213
|
+
end,
|
214
|
+
:interfaceName => interfaceName.is_a?( String) ? gen_plainname(interfaceName) : interfaceName,
|
215
|
+
:start => gen_traced_stmt(
|
216
|
+
gen_skip,
|
217
|
+
s( "ENTRY:" ) + entry_exit,
|
218
|
+
),
|
219
|
+
:stmts => stmts,
|
220
|
+
:return =>
|
221
|
+
gen_traced_stmt(
|
222
|
+
gen_return,
|
223
|
+
s( "EXIT:", ) + entry_exit,
|
224
|
+
),
|
225
|
+
})
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
##
|
231
|
+
# @return +specName+
|
232
|
+
def gen_expression2( expr1, op, expr2 )
|
233
|
+
sym = :TLA_expression2
|
234
|
+
addPartial( sym, "{|#EVAL|}expr1{|/EVAL|} {|#EVAL|}op{|/EVAL|} {|#EVAL|}expr2{|/EVAL|}" )
|
235
|
+
stla( sym, {
|
236
|
+
:expr1 => expr1,
|
237
|
+
:op => op,
|
238
|
+
:expr2 => expr2,
|
239
|
+
})
|
240
|
+
end
|
241
|
+
|
242
|
+
##
|
243
|
+
# @return [ f1 |-> type1, f2 |->type2 ]
|
244
|
+
def gen_record_definition( arrOfFields )
|
245
|
+
|
246
|
+
sym = :TLA_record_definition
|
247
|
+
addPartial( sym, "[ {|#fields|}{|#EVAL|}val{|/EVAL|}{|_comma|} {|/fields|}]" )
|
248
|
+
|
249
|
+
# simplify if just one given
|
250
|
+
arrOfFields = arrOfFields[0].is_a?( Symbol ) ? s(arrOfFields) : arrOfFields
|
251
|
+
|
252
|
+
# last element no comma
|
253
|
+
stla( sym,
|
254
|
+
{
|
255
|
+
:fields => arrOfFields.map.with_index { |f,i|
|
256
|
+
{ :_comma => (i+1) == arrOfFields.length ? '' : ',', :val => f }
|
257
|
+
}
|
258
|
+
})
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
##
|
264
|
+
# +variable+ \in +set+
|
265
|
+
def gen_set_iterate( variable, set )
|
266
|
+
|
267
|
+
sym = :TLA_set_iterate
|
268
|
+
addPartial( sym, "{|#EVAL|}variable{|/EVAL|} \\in {|#EVAL|}set{|/EVAL|} " )
|
269
|
+
|
270
|
+
# last element no comma
|
271
|
+
stla( sym,
|
272
|
+
{
|
273
|
+
:variable => variable.is_a?( String) ? gen_plainname(variable) : variable,
|
274
|
+
:set => set.is_a?( String) ? gen_plainname(set) : set,
|
275
|
+
})
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# { map : S}
|
280
|
+
def gen_set_map( map, set )
|
281
|
+
|
282
|
+
sym = :TLA_set_map
|
283
|
+
addPartial( sym, "{ {|#EVAL|}map{|/EVAL|} : {|#EVAL|}set{|/EVAL|} } " )
|
284
|
+
|
285
|
+
# last element no comma
|
286
|
+
stla( sym,
|
287
|
+
{
|
288
|
+
:map => map.is_a?( String) ? gen_plainname(map) : map,
|
289
|
+
:set => set.is_a?( String) ? gen_plainname(set) : set,
|
290
|
+
})
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
# # @return [ idName |-> idVal, f2 |-> Nil, ... ]
|
297
|
+
def gen_new_record( idVal, arrOfFields )
|
298
|
+
|
299
|
+
sym = :TLA_new_record
|
300
|
+
addPartial(
|
301
|
+
sym,
|
302
|
+
<<-EOS.unindent
|
303
|
+
[ {|#EVAL|}idVal{|/EVAL|}, {|#fields|}{|#EVAL|}val{|/EVAL|}{|_comma|} {|/fields|} ]
|
304
|
+
EOS
|
305
|
+
)
|
306
|
+
|
307
|
+
# last element no comma
|
308
|
+
stla( sym,
|
309
|
+
{
|
310
|
+
:idVal => idVal,
|
311
|
+
:fields => arrOfFields.map.with_index do |f,i|
|
312
|
+
{ :_comma => (i+1) == arrOfFields.length ? '' : ',',
|
313
|
+
:val => f
|
314
|
+
}
|
315
|
+
end
|
316
|
+
})
|
317
|
+
|
318
|
+
|
319
|
+
end
|
320
|
+
|
321
|
+
def gen_record_field_definition( name, value )
|
322
|
+
# name |-> value (notice spaces)
|
323
|
+
gen_name_op_operand( name, '|->', value )
|
324
|
+
end
|
325
|
+
def gen_record_field( record, field )
|
326
|
+
# A.x
|
327
|
+
gen_name_op_operand( record, '.', field, "" )
|
328
|
+
end
|
329
|
+
def gen_record_named_field( record, field )
|
330
|
+
# A[x]
|
331
|
+
sym = :TLA_record_named_field
|
332
|
+
|
333
|
+
addPartial( sym, "{|#EVAL|}record{|/EVAL|}{|sepl|}{|#EVAL|}field{|/EVAL|}{|sepr|}" )
|
334
|
+
|
335
|
+
stla( sym,
|
336
|
+
{
|
337
|
+
:record => record.is_a?( String ) ? gen_plainname(record) : record,
|
338
|
+
:sepl => '[',
|
339
|
+
:sepr => ']',
|
340
|
+
:field => field.is_a?( String ) ? gen_plainname(field) : field,
|
341
|
+
})
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
|
346
|
+
def gen_name_op_operand( name, op, operand, sep=" " )
|
347
|
+
|
348
|
+
sym = :TLA_name_op_operand
|
349
|
+
addPartial( sym, "{|#EVAL|}name{|/EVAL|}{|sep|}{|{op}|}{|sep|}{|#EVAL|}operand{|/EVAL|}" )
|
350
|
+
|
351
|
+
stla( sym,
|
352
|
+
{
|
353
|
+
:name => name.is_a?( String ) ? gen_plainname(name) : name,
|
354
|
+
:op => op,
|
355
|
+
:sep => sep,
|
356
|
+
:operand => operand.is_a?( String ) ? gen_plainname(operand) : operand,
|
357
|
+
})
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# Map interface to service name e.g./customer(get), Demo()
|
363
|
+
def gen_service_name( interface )
|
364
|
+
gen_identifier( interface )
|
365
|
+
end
|
366
|
+
|
367
|
+
def gen_identifier( identifier, posfix="" )
|
368
|
+
|
369
|
+
sym = :TLA_identifier
|
370
|
+
addPartial( sym, "{|#EVAL|}identifier{|/EVAL|}{|#EVAL|}postfix{|/EVAL|}" )
|
371
|
+
|
372
|
+
stla( sym, {
|
373
|
+
:identifier => identifier.is_a?( String) ?
|
374
|
+
gen_plainname(identifier) :
|
375
|
+
identifier,
|
376
|
+
:postfix => posfix.is_a?( String) ? gen_plainname(posfix) : posfix,
|
377
|
+
})
|
378
|
+
end
|
379
|
+
|
380
|
+
|
381
|
+
##
|
382
|
+
# @return Nil
|
383
|
+
def gen_empty_set()
|
384
|
+
sym = :TLA_emptyset
|
385
|
+
|
386
|
+
addPartial( sym, "{}" )
|
387
|
+
|
388
|
+
stla(sym, {
|
389
|
+
})
|
390
|
+
end
|
391
|
+
|
392
|
+
def gen_list( elements )
|
393
|
+
sym = :TLA_list
|
394
|
+
addPartial( sym, "{|#elements|}{|#EVAL|}element{|/EVAL|}{|_comma|}{|/elements|}" )
|
395
|
+
|
396
|
+
# allow singleton parameter
|
397
|
+
|
398
|
+
elements = elements.is_a?( String) ? gen_plainname(elements) : elements
|
399
|
+
elements = elements[0].is_a?( Symbol ) ? s(elements) : elements
|
400
|
+
|
401
|
+
stla( sym,
|
402
|
+
{
|
403
|
+
:elements => elements.map.with_index { |f,i|
|
404
|
+
{ :_comma => (i+1) == elements.length ? '' : ',', :element => f }
|
405
|
+
}
|
406
|
+
})
|
407
|
+
|
408
|
+
|
409
|
+
end
|
410
|
+
|
411
|
+
##
|
412
|
+
# @return Nil
|
413
|
+
def gen_set( element )
|
414
|
+
sym = :TLA_set
|
415
|
+
addPartial( sym, "{ {|#EVAL|}element{|/EVAL|} } " )
|
416
|
+
|
417
|
+
stla(sym, {
|
418
|
+
:element => element
|
419
|
+
})
|
420
|
+
end
|
421
|
+
|
422
|
+
def gen_TRUE
|
423
|
+
gen_plainname( "TRUE" )
|
424
|
+
end
|
425
|
+
|
426
|
+
def gen_FALSE
|
427
|
+
gen_plainname( "FALSE" )
|
428
|
+
end
|
429
|
+
|
430
|
+
##
|
431
|
+
# @return Nil
|
432
|
+
def gen_nilElement()
|
433
|
+
sym = :TLA_nil_element
|
434
|
+
|
435
|
+
addPartial( sym, "Nil" )
|
436
|
+
|
437
|
+
stla( sym, {})
|
438
|
+
end
|
439
|
+
|
440
|
+
|
441
|
+
def gen_op_set_minus()
|
442
|
+
gen_op_operator( "\\" )
|
443
|
+
end
|
444
|
+
|
445
|
+
##
|
446
|
+
# Common behavior to output operator +op+
|
447
|
+
def gen_op_operator( op )
|
448
|
+
sym = :TLA_op_operator
|
449
|
+
|
450
|
+
addPartial( sym, "{|operator|}" )
|
451
|
+
|
452
|
+
stla( sym, {
|
453
|
+
:operator => op
|
454
|
+
})
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
##
|
459
|
+
# Define state variable +variable+ and initialize
|
460
|
+
# with +initExpr+
|
461
|
+
def gen_state_variable( variable, initExpr )
|
462
|
+
sym = :TLA_state_variable
|
463
|
+
addPartial( sym, "{|#EVAL|}variable{|/EVAL|} = {|#EVAL|}init_expression{|/EVAL|};" )
|
464
|
+
|
465
|
+
stla( sym, {
|
466
|
+
:variable => variable,
|
467
|
+
:init_expression => initExpr,
|
468
|
+
})
|
469
|
+
end
|
470
|
+
|
471
|
+
##
|
472
|
+
# @param [String] interfaceName e.g. 'Demo()' or 'Demo(set)'
|
473
|
+
#
|
474
|
+
# @return [String] input variable name
|
475
|
+
def gen_interface_input_variable_name( interfaceName, metatype=:solidity_contract_function )
|
476
|
+
gen_identifier( gen_specname( setMetatype( metatype ), interfaceName), "_input" )
|
477
|
+
end
|
478
|
+
|
479
|
+
##
|
480
|
+
# @param [String] interfaceName e.g. 'Demo()' or 'Demo(set)'
|
481
|
+
#
|
482
|
+
def gen_interface_abort_label( interfaceName, serviceName=nil )
|
483
|
+
serviceName = gen_serviceName( interfaceName ) if serviceName.nil?
|
484
|
+
gen_identifier( serviceName, TlaElementText::TLA_LABEL_ABORT )
|
485
|
+
end
|
486
|
+
|
487
|
+
def gen_interface_end_label( interfaceName, serviceName=nil )
|
488
|
+
serviceName = gen_serviceName( interfaceName ) if serviceName.nil?
|
489
|
+
gen_identifier( serviceName, TlaElementText::TLA_LABEL_END )
|
490
|
+
end
|
491
|
+
|
492
|
+
##
|
493
|
+
# Solidity code should check for error
|
494
|
+
def gen_interface_fail_label( interfaceName, serviceName=nil )
|
495
|
+
serviceName = gen_serviceName( interfaceName ) if serviceName.nil?
|
496
|
+
gen_identifier( serviceName, TlaElementText::TLA_LABEL_FAIL )
|
497
|
+
end
|
498
|
+
|
499
|
+
private def gen_serviceName( interfaceName )
|
500
|
+
metatype = :solidity_contract_function
|
501
|
+
gen_specname( metatype, interfaceName)
|
502
|
+
end
|
503
|
+
|
504
|
+
|
505
|
+
##
|
506
|
+
# Create +specName+ corresponging +appName+ in +metatype+
|
507
|
+
def gen_specname( metatype, appName )
|
508
|
+
|
509
|
+
sym = :TLA_specname
|
510
|
+
addPartial( sym, "#{spec_name('specname')}" )
|
511
|
+
|
512
|
+
stla( sym,{
|
513
|
+
:specname => {
|
514
|
+
:metatype => setMetatype( metatype ),
|
515
|
+
:appName => appName,
|
516
|
+
}})
|
517
|
+
end
|
518
|
+
|
519
|
+
# @return name (which can be processed by EVAL)
|
520
|
+
def gen_plainname( name )
|
521
|
+
|
522
|
+
sym = :TLA_plainname
|
523
|
+
addPartial( sym, "{|{name}|}" )
|
524
|
+
|
525
|
+
stla( sym, {
|
526
|
+
:name => name
|
527
|
+
})
|
528
|
+
end
|
529
|
+
|
530
|
+
def gen_constant( constant )
|
531
|
+
gen_plainname( constant )
|
532
|
+
end
|
533
|
+
|
534
|
+
# @return "str"
|
535
|
+
def gen_str( str )
|
536
|
+
|
537
|
+
sym = :TLA_str
|
538
|
+
addPartial( sym, '"{|#EVAL|}str{|/EVAL|}"' )
|
539
|
+
|
540
|
+
stla( sym, {
|
541
|
+
:str=> str.is_a?( String ) ? gen_plainname(str) : str,
|
542
|
+
})
|
543
|
+
end
|
544
|
+
|
545
|
+
# @return "str"
|
546
|
+
def gen_parenthesis( str )
|
547
|
+
|
548
|
+
sym = :TLA_parenthesis
|
549
|
+
addPartial( sym, '( {|#EVAL|}str{|/EVAL|} )' )
|
550
|
+
|
551
|
+
stla( sym, {
|
552
|
+
:str=> str.is_a?( String ) ? gen_plainname(str) : str,
|
553
|
+
})
|
554
|
+
end
|
555
|
+
|
556
|
+
|
557
|
+
# ------------------------------------------------------------------
|
558
|
+
# Statements
|
559
|
+
|
560
|
+
def gen_stmts( stmts )
|
561
|
+
sym = :TLA_stmts
|
562
|
+
addPartial( sym,
|
563
|
+
"{|#stmts|}{|#EVAL|}.{|/EVAL|};\n"\
|
564
|
+
"{|/stmts|}"
|
565
|
+
)
|
566
|
+
|
567
|
+
stmts = stla( sym, {
|
568
|
+
# 1 stmt or array of stmts
|
569
|
+
:stmts => stmts[0].is_a?(Symbol) ? s(stmts) : stmts
|
570
|
+
})
|
571
|
+
|
572
|
+
# add method to return statements in stmts block for checking
|
573
|
+
# the need to add label after if-statement
|
574
|
+
methodName = :requiresLabelAfterChecker
|
575
|
+
stmts.define_singleton_method( methodName ) do
|
576
|
+
# pass if & else
|
577
|
+
stmts[1][:stmts]
|
578
|
+
end
|
579
|
+
|
580
|
+
stmts
|
581
|
+
|
582
|
+
end
|
583
|
+
|
584
|
+
# @param [Integer|String] labelIndex generate unique labels using index
|
585
|
+
#
|
586
|
+
def gen_labeled_stmt( stmt, labelPrefix=false, labelIndex=0 )
|
587
|
+
sym = :TLA_labeled_stmt
|
588
|
+
addPartial( sym, "{|#label|}{|#EVAL|}labelPrefix{|/EVAL|}_{|labelIndex|}: {|/label|}{|#EVAL|}stmt{|/EVAL|}" )
|
589
|
+
labTla = stla( sym, {
|
590
|
+
:stmt => stmt,
|
591
|
+
:label => labelPrefix ? true : false,
|
592
|
+
:labelPrefix => labelPrefix.is_a?( String) ? gen_plainname(labelPrefix) : labelPrefix,
|
593
|
+
:labelIndex => labelIndex,
|
594
|
+
})
|
595
|
+
|
596
|
+
# labelel stmt should be followed by a label - if it is infront
|
597
|
+
# +stmt+, which should be followed by a label or if
|
598
|
+
# label is used within block
|
599
|
+
statementRequiresLabel( labTla, requiresLabelAfter( stmt ))
|
600
|
+
labTla
|
601
|
+
end
|
602
|
+
|
603
|
+
##
|
604
|
+
# Generate statement, which may also generate trace output.
|
605
|
+
#
|
606
|
+
# @param [Array] traceArray message/evaluatable mesage
|
607
|
+
# @option traceArray [String|TlaSexp] parameter for print operation
|
608
|
+
#
|
609
|
+
def gen_traced_stmt( stmt, traceArray=false )
|
610
|
+
sym = :TLA_traced_stmt
|
611
|
+
addPartial( sym,
|
612
|
+
<<-EOS.unindent
|
613
|
+
{|#trace|}{|^preferences.tla-trace|}\\* {|/preferences.tla-trace|} {|#EVAL|}trace_print{|/EVAL|};
|
614
|
+
{|^preferences.tla-trace|}
|
615
|
+
{|/preferences.tla-trace|}{|/trace|}{|#EVAL|}stmt{|/EVAL|}
|
616
|
+
EOS
|
617
|
+
)
|
618
|
+
|
619
|
+
trace_stmt = stla( sym, {
|
620
|
+
:stmt => stmt,
|
621
|
+
:trace => traceArray ? true : false,
|
622
|
+
:trace_print => gen_print( traceArray ),
|
623
|
+
})
|
624
|
+
|
625
|
+
# trace_stmt should be followed by a label - if it is infront
|
626
|
+
# +stmt+, which should be followed by a label
|
627
|
+
statementRequiresLabel( trace_stmt ) if requiresLabelAfter( stmt )
|
628
|
+
trace_stmt
|
629
|
+
|
630
|
+
end
|
631
|
+
|
632
|
+
def gen_print( parameters )
|
633
|
+
sym = :TLA_print
|
634
|
+
addPartial(
|
635
|
+
sym,
|
636
|
+
"print <<"\
|
637
|
+
"{|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|}"\
|
638
|
+
">>"
|
639
|
+
)
|
640
|
+
|
641
|
+
# String mapper to Sexp && convert whole into to s() -array
|
642
|
+
parameters = gen_str( parameters ) if parameters.is_a?( String )
|
643
|
+
parameters = parameters[0].is_a?( Symbol ) ? s(parameters) : parameters
|
644
|
+
parameters.unshift( TRACE_PREFIX )
|
645
|
+
|
646
|
+
stla( sym, {
|
647
|
+
:parameters => parameters.any? ?
|
648
|
+
parameters.map.with_index do |p,i|
|
649
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
650
|
+
:parameter => p.is_a?(String) ? gen_str(p) : p
|
651
|
+
}
|
652
|
+
end :
|
653
|
+
false,
|
654
|
+
})
|
655
|
+
|
656
|
+
end
|
657
|
+
|
658
|
+
def gen_assign( lval, rval )
|
659
|
+
sym = :TLA_assign
|
660
|
+
# tlaStatementTypeRequiresLabel( sym )
|
661
|
+
addPartial( sym, "{|#EVAL|}lval{|/EVAL|} := {|#EVAL|}rval{|/EVAL|}" )
|
662
|
+
stla( sym, {
|
663
|
+
:lval => lval.is_a?( String) ? gen_plainname(lval) : lval,
|
664
|
+
:rval => rval.is_a?( String) ? gen_plainname(rval) : rval,
|
665
|
+
})
|
666
|
+
end
|
667
|
+
|
668
|
+
def gen_return()
|
669
|
+
|
670
|
+
sym = :TLA_return
|
671
|
+
tlaStatementTypeRequiresLabel( sym )
|
672
|
+
addPartial( sym, "return" )
|
673
|
+
stla( sym, {})
|
674
|
+
|
675
|
+
end
|
676
|
+
|
677
|
+
def gen_assert( cond, msg )
|
678
|
+
|
679
|
+
sym = :TLA_assert
|
680
|
+
tlaStatementTypeRequiresLabel( sym )
|
681
|
+
addPartial( sym,
|
682
|
+
"(* {|#EVAL|}msg{|/EVAL|} *)\n"\
|
683
|
+
"assert( {|#EVAL|}cond{|/EVAL|} )"
|
684
|
+
)
|
685
|
+
stla( sym, {
|
686
|
+
:cond => cond.is_a?(String) ? gen_plainname(cond) : cond,
|
687
|
+
:msg => msg.is_a?(String) ? gen_str(msg) : msg,
|
688
|
+
})
|
689
|
+
end
|
690
|
+
|
691
|
+
|
692
|
+
|
693
|
+
|
694
|
+
def gen_free_text( str )
|
695
|
+
sym = :TLA_free_text
|
696
|
+
addPartial( sym, "{|{text}|}" )
|
697
|
+
# tlaStatementTypeRequiresLabel( sym )
|
698
|
+
stla( sym, {
|
699
|
+
:text => str,
|
700
|
+
})
|
701
|
+
end
|
702
|
+
|
703
|
+
##
|
704
|
+
# preable at the start of service procedure
|
705
|
+
def gen_check_resume( procedureName )
|
706
|
+
|
707
|
+
sym = :TLA_check_resume
|
708
|
+
addPartial(
|
709
|
+
sym,
|
710
|
+
<<-EOS.unindent
|
711
|
+
(* check if resuming {|#EVAL|}procedureName{|/EVAL|} *)
|
712
|
+
if ( resume_context # Nil ) {
|
713
|
+
(* prepare stack entry with resume context followed by
|
714
|
+
a return to jump to resume location *)
|
715
|
+
stack := <<resume_context.ret_ctx >> \\o stack[self];
|
716
|
+
{|#EVAL|}procedureName{|/EVAL|}_resumed:
|
717
|
+
return;
|
718
|
+
}
|
719
|
+
EOS
|
720
|
+
)
|
721
|
+
tlaStatementTypeRequiresLabel( sym )
|
722
|
+
stla( sym, {
|
723
|
+
:procedureName => procedureName,
|
724
|
+
})
|
725
|
+
|
726
|
+
end
|
727
|
+
|
728
|
+
def gen_construct_contract( stateVariable, newContract, idPool, id )
|
729
|
+
sym = :TLA_construct_contract
|
730
|
+
addPartial( sym,
|
731
|
+
<<-EOS.unindent
|
732
|
+
\\* construct {|#EVAL|}contracts{|/EVAL|}
|
733
|
+
create_new_contract( {|#EVAL|}contracts{|/EVAL|}, {|#EVAL|}newContract{|/EVAL|}, {|#EVAL|}idPool{|/EVAL|}, {|#EVAL|}id{|/EVAL|} )
|
734
|
+
EOS
|
735
|
+
)
|
736
|
+
stla( sym, {
|
737
|
+
:contracts => stateVariable,
|
738
|
+
:newContract => newContract,
|
739
|
+
:idPool => idPool,
|
740
|
+
:id => id,
|
741
|
+
})
|
742
|
+
|
743
|
+
end
|
744
|
+
|
745
|
+
|
746
|
+
def gen_debug_msg( str )
|
747
|
+
sym = :TLA_debug_msg
|
748
|
+
# addPartial( sym, '{|^preferences.tla-debug|}\*{|/preferences.tla-debug|} print << "DEBUG: {|#EVAL|}text{|/EVAL|}" >>' )
|
749
|
+
addPartial( sym, 'print << "DEBUG: {|#EVAL|}text{|/EVAL|}" >>' )
|
750
|
+
# tlaStatementTypeRequiresLabel( sym )
|
751
|
+
stla( sym, {
|
752
|
+
:text => str.is_a?( String ) ? gen_plainname(str) : str,
|
753
|
+
})
|
754
|
+
end
|
755
|
+
|
756
|
+
def gen_commented( content )
|
757
|
+
sym = :TLA_commented
|
758
|
+
addPartial( sym,
|
759
|
+
"(* {|#EVAL|}content{|/EVAL|} *)\n"\
|
760
|
+
"skip"
|
761
|
+
)
|
762
|
+
stla( sym, {
|
763
|
+
:content => content.is_a?( String ) ? gen_plainname(content) : content,
|
764
|
+
})
|
765
|
+
end
|
766
|
+
|
767
|
+
|
768
|
+
def gen_procedure_call( procedure, parameters=s() )
|
769
|
+
sym = :TLA_procedure_call
|
770
|
+
# add label after proc.call
|
771
|
+
tlaStatementTypeRequiresLabel( sym )
|
772
|
+
addPartial(
|
773
|
+
sym,
|
774
|
+
"call {|#EVAL|}procedure{|/EVAL|}( {|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|})"
|
775
|
+
)
|
776
|
+
|
777
|
+
parameters = parameters.is_a?( String ) ? gen_plainname(parameters) : parameters
|
778
|
+
parameters = parameters[0].is_a?( Symbol ) ? s(parameters) : parameters
|
779
|
+
stla( sym, {
|
780
|
+
:procedure => procedure.is_a?( String ) ? gen_plainname(procedure) : procedure,
|
781
|
+
# false or [ {:p, _comma: }]
|
782
|
+
:parameters => parameters.any? ?
|
783
|
+
parameters.map.with_index do |p,i|
|
784
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
785
|
+
:parameter => p
|
786
|
+
}
|
787
|
+
end :
|
788
|
+
false,
|
789
|
+
})
|
790
|
+
end
|
791
|
+
|
792
|
+
def gen_and( lhs, rhs )
|
793
|
+
gen_bin_op( '/\\', lhs, rhs )
|
794
|
+
end
|
795
|
+
|
796
|
+
def gen_not( expression )
|
797
|
+
gen_unary_op( '~', expression )
|
798
|
+
# sym = :TLA_not
|
799
|
+
# addPartial(
|
800
|
+
# sym,
|
801
|
+
# "~{|#EVAL|}expression{|/EVAL|}"
|
802
|
+
# )
|
803
|
+
# stla( sym, {
|
804
|
+
# :expression =>expression,
|
805
|
+
# })
|
806
|
+
end
|
807
|
+
|
808
|
+
def gen_unary_op( op, expr )
|
809
|
+
sym = :TLA_unary_op
|
810
|
+
addPartial(
|
811
|
+
sym, "{|{op}|} {|#EVAL|}expr{|/EVAL|}"
|
812
|
+
)
|
813
|
+
|
814
|
+
stla( sym, {
|
815
|
+
:expr => expr.is_a?( String) ? gen_plainname(expr) : expr,
|
816
|
+
:op => op,
|
817
|
+
})
|
818
|
+
end
|
819
|
+
|
820
|
+
def gen_bin_op( op, lhs, rhs )
|
821
|
+
sym = :TLA_bin_op
|
822
|
+
addPartial(
|
823
|
+
sym, "{|#EVAL|}lhs{|/EVAL|} {|{op}|} {|#EVAL|}rhs{|/EVAL|}"
|
824
|
+
)
|
825
|
+
|
826
|
+
stla( sym, {
|
827
|
+
:lhs => lhs.is_a?( String) ? gen_plainname(lhs) : lhs,
|
828
|
+
:op => op,
|
829
|
+
:rhs => rhs.is_a?( String) ? gen_plainname(rhs) : rhs,
|
830
|
+
})
|
831
|
+
end
|
832
|
+
|
833
|
+
def gen_either( stmt, stmts )
|
834
|
+
sym = :TLA_either
|
835
|
+
tlaStatementTypeRequiresLabel( sym )
|
836
|
+
addPartial(
|
837
|
+
sym,
|
838
|
+
"either {|#EVAL|}stmt{|/EVAL|}" \
|
839
|
+
"{|#stmts|} or {|#EVAL|}.{|/EVAL|}"\
|
840
|
+
"{|/stmts|}"
|
841
|
+
)
|
842
|
+
|
843
|
+
stla( sym, {
|
844
|
+
:stmt => stmt,
|
845
|
+
:stmts => stmts[0].is_a?(Symbol) ? s(stmts) : stmts,
|
846
|
+
})
|
847
|
+
|
848
|
+
end
|
849
|
+
|
850
|
+
def gen_if( expression, thenStatement, elseStatement=nil )
|
851
|
+
sym = :TLA_if
|
852
|
+
addPartial(
|
853
|
+
sym,
|
854
|
+
|
855
|
+
"if ( {|#EVAL|}cond{|/EVAL|} ) {\n"\
|
856
|
+
' {|#EVAL|}then{|/EVAL|}'\
|
857
|
+
'}{|#else_given|} '\
|
858
|
+
"else {\n"\
|
859
|
+
' {|#EVAL|}else{|/EVAL|}'\
|
860
|
+
'}{|/else_given|}'
|
861
|
+
)
|
862
|
+
|
863
|
+
|
864
|
+
stmt_if = stla( sym, {
|
865
|
+
:cond => expression.is_a?(String) ? gen_plainname(expression) : expression,
|
866
|
+
# :then => gen_stmts( thenStatement.length == 1 ? s(stmt) : thenStatement ),
|
867
|
+
:then => gen_stmts( thenStatement ),
|
868
|
+
:else_given => elseStatement ? true : false,
|
869
|
+
:else => elseStatement ? gen_stmts( elseStatement ) : false,
|
870
|
+
})
|
871
|
+
|
872
|
+
# add label if then part of else part requires label
|
873
|
+
# statementRequiresLabel( stmt_if ) if requiresLabelAfter( thenStatement) || requiresLabelAfter(elseStatement)
|
874
|
+
|
875
|
+
# add method to return statements in then/else braches for
|
876
|
+
# checking the need to add label after if-statement
|
877
|
+
methodName = :requiresLabelAfterChecker
|
878
|
+
stmt_if.define_singleton_method( methodName ) do
|
879
|
+
# pass if & else
|
880
|
+
stmt_if[1][:then][1][:stmts] + ( stmt_if[1][:else] ? stmt_if[1][:else][1][:stmts] : [] )
|
881
|
+
end
|
882
|
+
|
883
|
+
# add method to recurse into then/else block to label
|
884
|
+
# statements within these blocks
|
885
|
+
setLabelBlockStatements( stmt_if, stmt_if[1][:then][1][:stmts] )
|
886
|
+
setLabelBlockStatements( stmt_if, stmt_if[1][:else][1][:stmts], :labelBlockStatementsElse ) if elseStatement
|
887
|
+
|
888
|
+
stmt_if
|
889
|
+
end
|
890
|
+
|
891
|
+
def gen_IF( expression, thenExpr, elseExpr )
|
892
|
+
sym = :TLA_IF
|
893
|
+
addPartial(
|
894
|
+
sym,
|
895
|
+
|
896
|
+
"IF {|#EVAL|}cond{|/EVAL|} THEN "\
|
897
|
+
'{|#EVAL|}then{|/EVAL|} '\
|
898
|
+
'ELSE '\
|
899
|
+
'{|#EVAL|}else{|/EVAL|}'
|
900
|
+
)
|
901
|
+
|
902
|
+
stla( sym, {
|
903
|
+
:cond => expression.is_a?( String) ? gen_plainname(expression) : expression,
|
904
|
+
# :then => gen_stmts( thenExpr.length == 1 ? s(stmt) : thenExpr ),
|
905
|
+
:then => thenExpr.is_a?( String) ? gen_plainname(thenExpr) : thenExpr,
|
906
|
+
:else => elseExpr.is_a?( String) ? gen_plainname(elseExpr) : elseExpr,
|
907
|
+
})
|
908
|
+
end
|
909
|
+
|
910
|
+
def gen_EXCEPT( variable, excepts )
|
911
|
+
sym = :TLA_EXCEPT
|
912
|
+
addPartial(
|
913
|
+
sym,
|
914
|
+
"[ {|#EVAL|}variable{|/EVAL|} "\
|
915
|
+
"EXCEPT "\
|
916
|
+
'{|#excepts|}{|#EVAL|}except{|/EVAL|}{|_comma|}{|/excepts|} '\
|
917
|
+
']'
|
918
|
+
)
|
919
|
+
|
920
|
+
# if signleton given
|
921
|
+
excepts = excepts[0].is_a?(Symbol) ? s(excepts) : excepts
|
922
|
+
stla( sym, {
|
923
|
+
:variable => variable.is_a?( String ) ? gen_plainname(variable ) : variable,
|
924
|
+
# :then => gen_stmts( thenExpr.length == 1 ? s(stmt) : thenExpr ),
|
925
|
+
:excepts => excepts.any? ?
|
926
|
+
excepts.map.with_index do |p,i|
|
927
|
+
{ :_comma => (i+1) == excepts.length ? '' : ',',
|
928
|
+
:except => p
|
929
|
+
}
|
930
|
+
end :
|
931
|
+
false,
|
932
|
+
})
|
933
|
+
end
|
934
|
+
|
935
|
+
|
936
|
+
def gen_skip()
|
937
|
+
sym = :TLA_skip
|
938
|
+
addPartial( sym, "skip" )
|
939
|
+
# tlaStatementTypeRequiresLabel( sym )
|
940
|
+
stla( sym, {})
|
941
|
+
end
|
942
|
+
|
943
|
+
##
|
944
|
+
# skip statement, but reqeuires label
|
945
|
+
def gen_label()
|
946
|
+
sym = :TLA_label
|
947
|
+
tlaStatementTypeRequiresLabel( sym )
|
948
|
+
addPartial( sym, "skip" )
|
949
|
+
stla( sym, {})
|
950
|
+
end
|
951
|
+
|
952
|
+
|
953
|
+
|
954
|
+
# ------------------------------------------------------------------
|
955
|
+
# NOT USED
|
956
|
+
|
957
|
+
|
958
|
+
# Generate element for a lval to set a +return_variable+ of +function_name+
|
959
|
+
def lval_function_return( function_name, return_variable )
|
960
|
+
|
961
|
+
sym = :TLA_lval_function_return
|
962
|
+
addPartial( sym,
|
963
|
+
"{|function_name|}_{|return_variable|}" )
|
964
|
+
|
965
|
+
stla( sym,
|
966
|
+
{
|
967
|
+
:function_name =>function_name,
|
968
|
+
:return_variable =>return_variable,
|
969
|
+
})
|
970
|
+
|
971
|
+
end
|
972
|
+
|
973
|
+
# TODO: remove
|
974
|
+
def rval_todo_remove
|
975
|
+
|
976
|
+
sym = :TLA_rval_todo_remove
|
977
|
+
addPartial( sym, "{|demo|}" )
|
978
|
+
|
979
|
+
stla( sym,
|
980
|
+
{
|
981
|
+
:demo =>1,
|
982
|
+
})
|
983
|
+
end
|
984
|
+
|
985
|
+
# Usefull as a placeholder
|
986
|
+
def gen_operator_dummy( metatype, name )
|
987
|
+
gen_operator(
|
988
|
+
gen_specname( metatype, name ),
|
989
|
+
s(),
|
990
|
+
gen_free_text( "TRUE" ),
|
991
|
+
)
|
992
|
+
end
|
993
|
+
|
994
|
+
def gen_operator_call( operatorName, parameters=[] )
|
995
|
+
sym = :TLA_operator_call
|
996
|
+
addPartial(
|
997
|
+
sym,
|
998
|
+
"{|#EVAL|}operatorName{|/EVAL|}"\
|
999
|
+
"{|#parameters.length|}( {|/parameters.length|}"\
|
1000
|
+
"{|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|}"\
|
1001
|
+
"{|#parameters.length|} ){|/parameters.length|}"
|
1002
|
+
)
|
1003
|
+
|
1004
|
+
parameters = parameters[0].is_a?( Symbol ) ? s(parameters) : parameters
|
1005
|
+
|
1006
|
+
stla( sym, {
|
1007
|
+
:operatorName => operatorName.is_a?( String ) ? gen_plainname(operatorName ) : operatorName,
|
1008
|
+
:parameters => parameters.any? ?
|
1009
|
+
parameters.map.with_index do |p,i|
|
1010
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
1011
|
+
:parameter => p
|
1012
|
+
}
|
1013
|
+
end :
|
1014
|
+
false,
|
1015
|
+
})
|
1016
|
+
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
##
|
1020
|
+
# Like operator call, but allways use ()
|
1021
|
+
def gen_macro_call( macroName, parameters=[] )
|
1022
|
+
sym = :TLA_macro_call
|
1023
|
+
addPartial(
|
1024
|
+
sym,
|
1025
|
+
"{|#EVAL|}macroName{|/EVAL|}("\
|
1026
|
+
"{|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|}"\
|
1027
|
+
")"
|
1028
|
+
)
|
1029
|
+
|
1030
|
+
parameters = parameters[0].is_a?( Symbol ) ? s(parameters) : parameters
|
1031
|
+
|
1032
|
+
stla( sym, {
|
1033
|
+
:macroName => macroName.is_a?( String ) ? gen_plainname(macroName ) : macroName,
|
1034
|
+
:parameters => parameters.any? ?
|
1035
|
+
parameters.map.with_index do |p,i|
|
1036
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
1037
|
+
:parameter => p
|
1038
|
+
}
|
1039
|
+
end :
|
1040
|
+
false,
|
1041
|
+
})
|
1042
|
+
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
|
1046
|
+
|
1047
|
+
def gen_goto( label )
|
1048
|
+
sym = :TLA_goto
|
1049
|
+
tlaStatementTypeRequiresLabel( sym )
|
1050
|
+
addPartial( sym, "goto {|#EVAL|}goto{|/EVAL|}" )
|
1051
|
+
|
1052
|
+
stla( sym, {
|
1053
|
+
:goto => label.is_a?( String) ? gen_plainname(label) : label,
|
1054
|
+
})
|
1055
|
+
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
|
1059
|
+
|
1060
|
+
#
|
1061
|
+
def gen_operator( operatorName, parameters, operatorBody )
|
1062
|
+
sym = :TLA_operator
|
1063
|
+
addPartial(
|
1064
|
+
sym,
|
1065
|
+
"{|#EVAL|}operatorName{|/EVAL|}{|#parameters.length|}({|/parameters.length|}{|#parameters|}{|#EVAL|}parameter{|/EVAL|}{|_comma|}{|/parameters|}{|#parameters.length|}){|/parameters.length|} == {|#EVAL|}operatorBody{|/EVAL|}"
|
1066
|
+
)
|
1067
|
+
|
1068
|
+
stla( sym,
|
1069
|
+
{
|
1070
|
+
:operatorName => operatorName,
|
1071
|
+
:parameters => parameters.any? ?
|
1072
|
+
parameters.map.with_index do |p,i|
|
1073
|
+
{ :_comma => (i+1) == parameters.length ? '' : ',',
|
1074
|
+
:parameter => p
|
1075
|
+
}
|
1076
|
+
end :
|
1077
|
+
false,
|
1078
|
+
:operatorBody => operatorBody
|
1079
|
+
})
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
def return_stmt( functionNameDef )
|
1083
|
+
sym = :TLA_return_stmt
|
1084
|
+
addPartial( sym, "goto #{spec_name('return_from')}_exit; \\* return contract '{| return_from |}'" )
|
1085
|
+
|
1086
|
+
stla( sym,
|
1087
|
+
{
|
1088
|
+
:return_from =>functionNameDef
|
1089
|
+
})
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
|
1093
|
+
# NOT USED
|
1094
|
+
# ------------------------------------------------------------------
|
1095
|
+
|
1096
|
+
|
1097
|
+
|
1098
|
+
|
1099
|
+
# ------------------------------------------------------------------
|
1100
|
+
# @!group Utitilities to create generate elements
|
1101
|
+
|
1102
|
+
# create s() with +sym+ (to dispatch correct template) and +hash+ as
|
1103
|
+
# template data to render.
|
1104
|
+
def stla( sym, hash)
|
1105
|
+
sTla = s( sym, hash )
|
1106
|
+
|
1107
|
+
# sTla.define_singleton_method( :patch, lambda { |key,val| self[1][key] = val } )
|
1108
|
+
# sTla.define_singleton_method( :h ) do
|
1109
|
+
# self[1]
|
1110
|
+
# end
|
1111
|
+
# sTla.define_singleton_method( :e ) do
|
1112
|
+
# s(self[1])
|
1113
|
+
# end
|
1114
|
+
sTla
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
|
1118
|
+
###
|
1119
|
+
# Add +partialTemplate+ with name +partialSymbol+ to partial
|
1120
|
+
# collection.
|
1121
|
+
#
|
1122
|
+
# NOTICE: as an optimization Mustache template implementation
|
1123
|
+
# can use partials, which are initalized using
|
1124
|
+
# 'Mustache.templateify' to speed up rendering phase.
|
1125
|
+
#
|
1126
|
+
# @param [Symbol] partialSymbol identifying partial
|
1127
|
+
#
|
1128
|
+
# @param [String] partialTemplate to render element SEXP
|
1129
|
+
#
|
1130
|
+
#
|
1131
|
+
def addPartial( partialSymbol, partialTemplate )
|
1132
|
+
raise "Should have called #setPartials before actions" if partials.nil?
|
1133
|
+
# would like to guarantee that no template refinition takes
|
1134
|
+
# place - currently assume that implementation is correct and
|
1135
|
+
# just return
|
1136
|
+
|
1137
|
+
return if partials.key?(partialSymbol)
|
1138
|
+
raise <<-EOS.unindent if partials_duplicateCheck.key?(partialSymbol) && partials_duplicateCheckpartials[partialSymbol] != partialTemplate
|
1139
|
+
Partial #{partialSymbol} redefinitition:
|
1140
|
+
|
1141
|
+
Previous:
|
1142
|
+
#{partials[partialSymbol]}
|
1143
|
+
|
1144
|
+
New:
|
1145
|
+
#{partialTemplate}
|
1146
|
+
|
1147
|
+
EOS
|
1148
|
+
|
1149
|
+
partials[partialSymbol] = Mustache.templateify(partialTemplate)
|
1150
|
+
partials_duplicateCheck[partialSymbol] = partialTemplate
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
# @!endgroup
|
1154
|
+
|
1155
|
+
# ------------------------------------------------------------------
|
1156
|
+
# @!group common idioms
|
1157
|
+
|
1158
|
+
##
|
1159
|
+
# Mustache SPEC_NAME lamba call for +metatype+ & +appName+
|
1160
|
+
# access unique name for +metatype+/+appName+ combination in
|
1161
|
+
# specification code.
|
1162
|
+
#
|
1163
|
+
# @param [Hash] specNameDef name in tla generate element
|
1164
|
+
# @options specNameDef [Symbol] :metatype
|
1165
|
+
# @options specNameDef [Symbol] :appName
|
1166
|
+
#
|
1167
|
+
# @return [String] string wrapped within SPEC_NAME mustache
|
1168
|
+
# lambda call
|
1169
|
+
def spec_name( specNameDef )
|
1170
|
+
# "{{#SPEC_NAME}}#{specNameDef[:metatype]}.#{specNameDef[:appName]}{{/SPEC_NAME}}"
|
1171
|
+
# "{{#SPEC_NAME}}{{#{specNameDef}.metatype}}.{{#{specNameDef}.appName}}{{/SPEC_NAME}}"
|
1172
|
+
# "{{#SPEC_NAME}}{{metatype}}.{{appName}}{{/SPEC_NAME}}"
|
1173
|
+
"{{#SPEC_NAME}}{|#{specNameDef}.metatype|}.{|#{specNameDef}.appName|}{{/SPEC_NAME}}"
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
def appName( specNameDef )
|
1177
|
+
"{|#{specNameDef}.metatype|}.{|#{specNameDef}.appName|}"
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
|
1181
|
+
def exit_label( funcNameDef )
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
##
|
1185
|
+
# Pass +metatype+ trough, and ensure that it exists in
|
1186
|
+
# +metatypes+
|
1187
|
+
|
1188
|
+
def setMetatype( metatype )
|
1189
|
+
raise SbuilderEtherumException, <<-EOS unless validMetatypes.key?( metatype )
|
1190
|
+
Unknown metatype '#{metatype}' type '#{metatype.class}'
|
1191
|
+
|
1192
|
+
Known metatypes: #{validMetatypes.keys.join(',')}
|
1193
|
+
|
1194
|
+
EOS
|
1195
|
+
|
1196
|
+
metatype
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
|
1200
|
+
# @!endgroup
|
1201
|
+
|
1202
|
+
|
1203
|
+
end # class TlaElementGenerator
|
1204
|
+
|
1205
|
+
end
|
1206
|
+
end
|