sbuilder-al 0.0.8
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 +217 -0
- data/VERSION +1 -0
- data/design/al-language-bnf.org +216 -0
- data/lib/meta/etc.rb +265 -0
- data/lib/meta/meta.rb +106 -0
- data/lib/model/api.rb +678 -0
- data/lib/model/builders.rb +603 -0
- data/lib/model/constants.rb +24 -0
- data/lib/model/model.rb +534 -0
- data/lib/model/module.rb +25 -0
- data/lib/plugin/controller.rb +247 -0
- data/lib/plugin/module.rb +2 -0
- data/lib/plugin/plugin.rb +352 -0
- data/lib/sbuilder-al.rb +30 -0
- data/lib/translator/alrules.rb +424 -0
- data/lib/translator/module.rb +31 -0
- data/lib/translator/producer.rb +580 -0
- data/lib/translator/renderer.rb +159 -0
- data/lib/translator/sexp.rb +57 -0
- data/lib/translator/tlagenerator.rb +1348 -0
- data/lib/translator/translator.rb +210 -0
- data/lib/util/exception.rb +16 -0
- data/lib/util/logger.rb +90 -0
- data/lib/util/module.rb +16 -0
- data/lib/util/script_eval.rb +41 -0
- data/sbuilder-al.gemspec +45 -0
- metadata +153 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Sbuilder
|
3
|
+
module Al
|
4
|
+
|
5
|
+
# Module for configurable visitor for hash/struct model for Sbuilder::Al
|
6
|
+
#
|
7
|
+
# Module includes following main classes:
|
8
|
+
#
|
9
|
+
# * Class {Sbuilder::Al::Translator::Translator} visitor
|
10
|
+
# implementation
|
11
|
+
# {Sbuilder::Al::Translator::Translator#translate} using
|
12
|
+
# configuration {Sbuilder::Al::Translator::Translator#rules}
|
13
|
+
#
|
14
|
+
# * Class {Sbuilder::Al::Translator::AlRules} visitor configuration
|
15
|
+
# for {Sbuilder::Al::Model} model
|
16
|
+
#
|
17
|
+
# * Class {Sbuilder::Al::Translator::AlProducer} an abstract class defining
|
18
|
+
# producer rules for {Sbuilder::Al::Translator::AlRules}
|
19
|
+
#
|
20
|
+
#
|
21
|
+
module Translator
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require_relative( "sexp")
|
27
|
+
require_relative( "renderer")
|
28
|
+
require_relative( "tlagenerator")
|
29
|
+
require_relative( "producer")
|
30
|
+
require_relative( "alrules")
|
31
|
+
require_relative( "translator")
|
@@ -0,0 +1,580 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Al
|
3
|
+
module Translator
|
4
|
+
|
5
|
+
# not catched
|
6
|
+
class ProducerException < Sbuilder::Al::Util::AlException; end
|
7
|
+
# to be catched
|
8
|
+
class ProducerError < Sbuilder::Al::Util::AlError; end
|
9
|
+
|
10
|
+
|
11
|
+
##
|
12
|
+
# Produce tla -sexps for {Sbuilder::Al::Translator::Renderer}
|
13
|
+
# template generator using context created by
|
14
|
+
# {Sbuilder::Al::Translator::Translator} with rules in
|
15
|
+
# {Sbuilder::Al::Translator::AlRules}.
|
16
|
+
#
|
17
|
+
# Implementation dispatches sexp production to
|
18
|
+
# {Sbuilder::Al::Translator::TlaGenerator} pointed by
|
19
|
+
# {Sbuilder::Al::Translator::Producer#template_generator}.
|
20
|
+
#
|
21
|
+
#
|
22
|
+
|
23
|
+
class Producer
|
24
|
+
|
25
|
+
include Sbuilder::Al::Meta # meta supportt e.g. attribute accessor
|
26
|
+
include Sbuilder::Al::Util::MyLogger # mix logger
|
27
|
+
extend Forwardable # for easy delegation
|
28
|
+
|
29
|
+
|
30
|
+
# @!attribute template_generator generator to produce snippets
|
31
|
+
attribute_accessor :template_generator
|
32
|
+
|
33
|
+
# ------------------------------------------------------------------
|
34
|
+
# @!group Framework operator services
|
35
|
+
|
36
|
+
# Macro to set return status && return expression
|
37
|
+
INFRA_MACRO_SET_RETURN = "InfrastructureServiceReturn"
|
38
|
+
INFRA_OPERATOR_GET_RESPONSE = "InfrastructureServiceGetResponse"
|
39
|
+
INFRA_OPERATOR_GET_STATUS = "InfrastructureServiceGetStatus"
|
40
|
+
|
41
|
+
|
42
|
+
# @!endgroup
|
43
|
+
|
44
|
+
|
45
|
+
# ------------------------------------------------------------------
|
46
|
+
# @!group Operators
|
47
|
+
|
48
|
+
OPERATOR_SET_MINUS = :set_minus
|
49
|
+
OPERATOR_SET_UNION = :union
|
50
|
+
OPERATOR_PLUS = :plus
|
51
|
+
OPERATOR_MINUS = :minus
|
52
|
+
OPERATOR_MULT = :mult
|
53
|
+
OPERATOR_DIV = :div
|
54
|
+
OPERATOR_EQUAL = :equal
|
55
|
+
OPERATOR_UNEQUAL = :unequal
|
56
|
+
OPERATOR_LE = :le
|
57
|
+
OPERATOR_GE = :ge
|
58
|
+
OPERATOR_GT = :gt
|
59
|
+
OPERATOR_LT = :lt
|
60
|
+
OPERATOR_AND = :and
|
61
|
+
OPERATOR_OR = :or
|
62
|
+
OPERATOR_NOT = :not
|
63
|
+
|
64
|
+
# map operator names to TLA implementation
|
65
|
+
BINARY_OPERATORS = {
|
66
|
+
OPERATOR_SET_MINUS => '\\',
|
67
|
+
OPERATOR_SET_UNION => '\\union',
|
68
|
+
OPERATOR_PLUS => '+',
|
69
|
+
OPERATOR_MINUS => '-',
|
70
|
+
OPERATOR_MULT => '*',
|
71
|
+
OPERATOR_DIV => '/',
|
72
|
+
OPERATOR_UNEQUAL => "#",
|
73
|
+
OPERATOR_EQUAL => '=',
|
74
|
+
OPERATOR_LT => '<',
|
75
|
+
OPERATOR_GT => '>',
|
76
|
+
OPERATOR_LE => '<=',
|
77
|
+
OPERATOR_GE => '>=',
|
78
|
+
OPERATOR_AND => '/\\',
|
79
|
+
OPERATOR_OR => '\\/',
|
80
|
+
}
|
81
|
+
|
82
|
+
UNARY_OPERATORS = {
|
83
|
+
OPERATOR_NOT => '~',
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
# @!endgroup
|
88
|
+
|
89
|
+
# ------------------------------------------------------------------
|
90
|
+
# @!group Delegates to template -generator
|
91
|
+
|
92
|
+
def_delegators :template_generator,
|
93
|
+
:partials, # template generator manages partials
|
94
|
+
:gen_str,
|
95
|
+
:gen_constant,
|
96
|
+
:gen_sequence,
|
97
|
+
:gen_plainname,
|
98
|
+
:gen_record_field,
|
99
|
+
:gen_bin_op,
|
100
|
+
:gen_unary_op,
|
101
|
+
:gen_specname,
|
102
|
+
:gen_labeled_stmt,
|
103
|
+
:gen_label,
|
104
|
+
:gen_state_variable,
|
105
|
+
# statements
|
106
|
+
:gen_stmts,
|
107
|
+
:gen_serviceProcedureLabelStatements,
|
108
|
+
:gen_skip,
|
109
|
+
:gen_goto,
|
110
|
+
:gen_print,
|
111
|
+
:gen_if,
|
112
|
+
:gen_assign,
|
113
|
+
:gen_procedure_call,
|
114
|
+
:gen_macro_call,
|
115
|
+
# elements in tla-model
|
116
|
+
:gen_interface_input_variable_name,
|
117
|
+
:gen_EXCEPT,
|
118
|
+
# macros,function, operators
|
119
|
+
:gen_macro,
|
120
|
+
:gen_operator,
|
121
|
+
:gen_operator_call,
|
122
|
+
:gen_service_procedure
|
123
|
+
|
124
|
+
|
125
|
+
# @!endgroup
|
126
|
+
|
127
|
+
|
128
|
+
# ------------------------------------------------------------------
|
129
|
+
# @!group Constructor
|
130
|
+
private def initialize( options={} )
|
131
|
+
@logger = getLogger( nil, options )
|
132
|
+
@logger.info "#{__method__}: initalized"
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# @param template_generator [TlaGenerator] template generator
|
137
|
+
# to create TlaSexps objects. Thes TlaSexp objects can be
|
138
|
+
# evaluted using partials, also known by template_generator.
|
139
|
+
def self.start( template_generator, options={} )
|
140
|
+
o = self.new( options )
|
141
|
+
o.template_generator = template_generator
|
142
|
+
o
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# @!endgroup
|
147
|
+
|
148
|
+
# ------------------------------------------------------------------
|
149
|
+
# @!group Services
|
150
|
+
|
151
|
+
# Peel of array levels until array contains Sexp's - line flatten but
|
152
|
+
# leave Sexps intact.
|
153
|
+
#
|
154
|
+
# @param sArray [Array<Array*<Sexp>>] Array
|
155
|
+
#
|
156
|
+
# @param level [int] number of levels to pop
|
157
|
+
def unwrap( sArray, level=-1 )
|
158
|
+
return( sArray ) unless sArray.any?
|
159
|
+
return( sArray ) unless sArray[0].is_a?(Array)
|
160
|
+
return( sArray ) unless sArray.length == 1
|
161
|
+
# return( sArray ) if level == 0
|
162
|
+
unwrap( sArray[0], level > 0 ? level -1 : level )
|
163
|
+
end
|
164
|
+
|
165
|
+
# @!endgroup
|
166
|
+
|
167
|
+
# ------------------------------------------------------------------
|
168
|
+
# @!group API loader productions
|
169
|
+
|
170
|
+
def p_interface( name, operation, request, response )
|
171
|
+
{
|
172
|
+
:apiType => :interface,
|
173
|
+
:type => :interface,
|
174
|
+
:name => txInterfaceName(name, operation),
|
175
|
+
:operation => operation,
|
176
|
+
:request => request,
|
177
|
+
:response => response,
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
# def p_request_response( paramSet )
|
183
|
+
# warn "p_request_response missing mplementation :transaction rule";
|
184
|
+
# end
|
185
|
+
|
186
|
+
# @return [Hash] with properties :name and :properties
|
187
|
+
def p_definition( name, properties )
|
188
|
+
@logger.info "#{__method__}: name=#{name}, properties=#{properties}"
|
189
|
+
{
|
190
|
+
:apiType => :definition,
|
191
|
+
:type => :definition,
|
192
|
+
:name => name,
|
193
|
+
:properties => properties
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
# @return [Hash] with properties :name and :properties
|
198
|
+
def p_function_definition( name, properties )
|
199
|
+
@logger.info "#{__method__}: name=#{name}, properties=#{properties}"
|
200
|
+
{
|
201
|
+
:apiType => :function_definition,
|
202
|
+
:type => :function_definition,
|
203
|
+
:name => name,
|
204
|
+
:properties => properties
|
205
|
+
}
|
206
|
+
end
|
207
|
+
|
208
|
+
def p_property( property )
|
209
|
+
@logger.info "#{__method__}: property=#{property}"
|
210
|
+
ret = {
|
211
|
+
:apiType => :definition_property,
|
212
|
+
:type => :definition_property,
|
213
|
+
:isArray => property.isArray,
|
214
|
+
:name => property.name,
|
215
|
+
}
|
216
|
+
if property.domain
|
217
|
+
ret[:domain] = property.domain
|
218
|
+
elsif property.definition
|
219
|
+
ret[:definition] = property.definition
|
220
|
+
else
|
221
|
+
raise ProducerError, "Property must define ':domain' or ':definition' on #{property.strOutput}"
|
222
|
+
end
|
223
|
+
|
224
|
+
ret
|
225
|
+
end
|
226
|
+
|
227
|
+
def p_domain( domainName, values )
|
228
|
+
@logger.info "#{__method__}: domainName=#{domainName}, values=#{values.join(',')}"
|
229
|
+
{
|
230
|
+
:apiType => :domain,
|
231
|
+
:type => :domain,
|
232
|
+
:name => domainName,
|
233
|
+
:values => values,
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
# def p_domain_value( value )
|
238
|
+
# p_constant_expression( value )
|
239
|
+
# end
|
240
|
+
|
241
|
+
# @!endgroup
|
242
|
+
|
243
|
+
# ------------------------------------------------------------------
|
244
|
+
# @!group Snippets (i.e. AL language final entries)
|
245
|
+
|
246
|
+
def p_operator( operator, parameters, rval )
|
247
|
+
@logger.info "#{__method__}: operator.name=#{operator.name}, parameters=#{parameters}, rval=#{rval}"
|
248
|
+
parameters = [] if parameters.nil?
|
249
|
+
rval = gen_constant( "TRUE" ) if rval.nil?
|
250
|
+
gen_operator( gen_specname( operator.meta, operator.name ), parameters, rval )
|
251
|
+
end
|
252
|
+
|
253
|
+
# @param snippet [Model::Snippet] Snippet to render
|
254
|
+
def p_snippet( snippet )
|
255
|
+
@logger.info "#{__method__}: snippet.meta=#{snippet.meta}, snippet.name=#{snippet.name}"
|
256
|
+
@logger.debug "#{__method__}: snippet=#{snippet}" if @logger.debug?
|
257
|
+
gen_plainname( snippet.txt )
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
def p_macro( macro, parameters, stmts )
|
262
|
+
@logger.info "#{__method__}: macroName=#{macro.name}, parameters=#{parameters}"
|
263
|
+
@logger.debug "#{__method__}: macroName=#{macro.name} stmts=#{stmts}" if @logger.debug?
|
264
|
+
gen_macro( gen_specname( macro.meta, macro.name ), parameters, gen_stmts(stmts) )
|
265
|
+
end
|
266
|
+
|
267
|
+
# @param tx [Model::Transaction]
|
268
|
+
# @param stmt [Array<tlaSexp>]
|
269
|
+
def p_transaction( tx, locals, stmts )
|
270
|
+
@logger.info "#{__method__}, tx=#{tx}, locals=#{locals}"
|
271
|
+
@logger.debug "#{__method__}, tx stmts=#{stmts}" if @logger.debug?
|
272
|
+
labelPrefix = tx2ServiceProcedure( tx )
|
273
|
+
labeledStmts = gen_stmts(gen_serviceProcedureLabelStatements( stmts, labelPrefix ))
|
274
|
+
@logger.debug "#{__method__}, labeledStmts=#{labeledStmts}" if @logger.debug?
|
275
|
+
gen_service_procedure( tx2ServiceProcedure( tx ), txInterfaceName(tx.name, tx.operation), locals, labeledStmts )
|
276
|
+
end
|
277
|
+
|
278
|
+
def p_variable_definition( varName, initExpression )
|
279
|
+
@logger.info "#{__method__}: varName=#{varName}, initExpression=#{initExpression}"
|
280
|
+
gen_state_variable( gen_specname( varName.meta, varName.name ), initExpression )
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
# @!endgroup
|
285
|
+
|
286
|
+
# ------------------------------------------------------------------
|
287
|
+
# @!group Expressions
|
288
|
+
|
289
|
+
def p_reference( alReference )
|
290
|
+
case alReference
|
291
|
+
when Sbuilder::Al::Model::SimpleReference
|
292
|
+
variableRef = gen_plainname( alReference.name )
|
293
|
+
when Sbuilder::Al::Model::VariableReference
|
294
|
+
variableRef = gen_specname( alReference.meta, alReference.name )
|
295
|
+
when Sbuilder::Al::Model::TxParameterReference
|
296
|
+
variableRef = p_reference_to_tx_parameter( alReference.meta, alReference.name, alReference.operation )
|
297
|
+
else
|
298
|
+
raise "Unsupported type '#{alReference.class}' for reference object '#{alReference}'"
|
299
|
+
end
|
300
|
+
# no fields - refence to variable
|
301
|
+
return variableRef if alReference.fields.nil?
|
302
|
+
fieldRef = alReference.fields.reduce( variableRef ) do |memo, fld|
|
303
|
+
memo = gen_record_field( memo, fld )
|
304
|
+
memo
|
305
|
+
end
|
306
|
+
fieldRef
|
307
|
+
end
|
308
|
+
|
309
|
+
# # Expression calling 'operatorName' with argumerns 'args'
|
310
|
+
# #
|
311
|
+
# # @param operatorName [String] name of operator to call
|
312
|
+
# # @param args [Array<TlaSexp>] arguments passed to operator
|
313
|
+
# def p_operatorCall(operatorName, args)
|
314
|
+
# raise "not tested"
|
315
|
+
# gen_operator_call( operatorName, args )
|
316
|
+
# end
|
317
|
+
|
318
|
+
|
319
|
+
# def p_tx_parameter_reference( alTx, parameterName )
|
320
|
+
# @logger.info "#{__method__}: alTx=#{alTx}, parameterName=#{parameterName}"
|
321
|
+
# gen_record_field( tx2InputVariable( alTx ), parameterName.reference )
|
322
|
+
# end
|
323
|
+
#
|
324
|
+
|
325
|
+
#
|
326
|
+
# sTla accessing parameter for opration 'txOperation' in tx
|
327
|
+
# 'txName' in namespace 'txMeta'
|
328
|
+
#
|
329
|
+
# @return [sTla] with name to access input paremeter
|
330
|
+
def p_reference_to_tx_parameter( txMeta, txName, txOperation )
|
331
|
+
tx2InputParameter( txMeta, txName, txOperation )
|
332
|
+
end
|
333
|
+
|
334
|
+
def p_reference_to_simple( name )
|
335
|
+
gen_plainname( name )
|
336
|
+
end
|
337
|
+
|
338
|
+
def p_reference_to_variable( varMeta, varName )
|
339
|
+
gen_specname( varMeta, varName )
|
340
|
+
end
|
341
|
+
|
342
|
+
# @return [sTla] Expand binary expression 'tlaLval' 'symOp' 'tlaRval'
|
343
|
+
def p_binary_expression( tlaLval, symOp, tlaRval )
|
344
|
+
@logger.info "#{__method__}: lval=#{tlaLval}, op=#{symOp}, rval=#{tlaRval}"
|
345
|
+
gen_bin_op( p_op(symOp), tlaLval, tlaRval )
|
346
|
+
end
|
347
|
+
|
348
|
+
# @return [sTla] Expand unary expression 'symOp' 'tlaExpr'
|
349
|
+
def p_unary_expression( symOp, tlaExpr )
|
350
|
+
@logger.info "#{__method__}: op=#{symOp}, expr=#{tlaExpr}"
|
351
|
+
gen_unary_op( p_unary_op(symOp), tlaExpr )
|
352
|
+
end
|
353
|
+
|
354
|
+
# Evaluate 'template' using 'template_generator' in '*args' context
|
355
|
+
# @param template [lambda] accepting tlaGenerator and 'args'
|
356
|
+
# @param args [Array] argument to pass to 'template' lambda
|
357
|
+
def p_tla_expression( template, args )
|
358
|
+
@logger.info "#{__method__}: template=#{template}, args=#{args.is_a?(Array) ? args.join(',') : args }"
|
359
|
+
template[template_generator, *args]
|
360
|
+
end
|
361
|
+
|
362
|
+
# @param value [String|Numeric|TrueClass|FalseClass] constant expression
|
363
|
+
def p_constant_expression( value )
|
364
|
+
@logger.info "#{__method__}: val=#{value}"
|
365
|
+
case value
|
366
|
+
when String
|
367
|
+
gen_str( value )
|
368
|
+
when Numeric
|
369
|
+
gen_constant( value )
|
370
|
+
when TrueClass
|
371
|
+
gen_constant( "TRUE" )
|
372
|
+
when FalseClass
|
373
|
+
gen_constant( "FALSE" )
|
374
|
+
when Symbol
|
375
|
+
# map symbol 'val' to sTla for constant expression
|
376
|
+
p_constant_symbol_expression( value )
|
377
|
+
else
|
378
|
+
raise "Unsupported type #{value.class} for val '#{value}'"
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
# @param constSymbol [Symbo] well knwon symbol e.g.
|
383
|
+
def p_constant_symbol_expression( constSymbol )
|
384
|
+
constValue = constantExpressions[constSymbol]
|
385
|
+
raise "Unsupported symbol value #{constSymbol}" if constValue.nil?
|
386
|
+
gen_constant(constValue)
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
# @!endgroup
|
391
|
+
|
392
|
+
# ------------------------------------------------------------------
|
393
|
+
# @!group block and statemetns
|
394
|
+
|
395
|
+
def p_block( arrOfStatements )
|
396
|
+
@logger.info "#{__method__}: arrOfStatements=#{arrOfStatements}:#{arrOfStatements.class}"
|
397
|
+
# arrOfStatements
|
398
|
+
arrOfStatements
|
399
|
+
# gen_stmts( )
|
400
|
+
end
|
401
|
+
|
402
|
+
# @param tx [Model::Transaction] transaction where to return from
|
403
|
+
# @param status [TlaSexp] expression to set in status
|
404
|
+
# @param expression [TlaSexp] return value
|
405
|
+
def p_returnStatement( tx, status, expression )
|
406
|
+
@logger.info "#{__method__}: tx=#{tx}, status=#{status}, expression=#{expression}"
|
407
|
+
gen_macro_call( INFRA_MACRO_SET_RETURN, [gen_str(txInterfaceName(tx.name, tx.operation)), status, expression] )
|
408
|
+
end
|
409
|
+
|
410
|
+
# Set 'expression' to 'variable' as return value for transaction 'tx'
|
411
|
+
#
|
412
|
+
# @param tx [Model::Transaction] transaction where to return from
|
413
|
+
#
|
414
|
+
# @param variable [String] name of return value to set
|
415
|
+
#
|
416
|
+
# @param expression [TlaSexp] return value
|
417
|
+
def p_returnValue( tx, variable, expression )
|
418
|
+
operation = gen_str(txInterfaceName(tx.name, tx.operation))
|
419
|
+
setVariableExpression =
|
420
|
+
gen_EXCEPT(
|
421
|
+
gen_operator_call( INFRA_OPERATOR_GET_RESPONSE, operation ),
|
422
|
+
[ gen_bin_op( "=", gen_record_field( "!", variable ), expression ) ]
|
423
|
+
)
|
424
|
+
gen_macro_call( INFRA_MACRO_SET_RETURN, [ operation, gen_operator_call( INFRA_OPERATOR_GET_STATUS, operation ), setVariableExpression] )
|
425
|
+
end
|
426
|
+
|
427
|
+
# Set return status for transaction 'tx', expression for response is unchanged.
|
428
|
+
#
|
429
|
+
# @param tx [Model::Transaction] transaction where to return from
|
430
|
+
#
|
431
|
+
# @param status [TlaSexp] status value to set
|
432
|
+
def p_returnStatus( tx, status )
|
433
|
+
operation = gen_str(txInterfaceName(tx.name, tx.operation))
|
434
|
+
gen_macro_call( INFRA_MACRO_SET_RETURN, [operation, status, gen_operator_call( INFRA_OPERATOR_GET_RESPONSE, operation ) ] )
|
435
|
+
end
|
436
|
+
|
437
|
+
|
438
|
+
# @param alJump [Model::JumpStatement] statement defininng jump label
|
439
|
+
def p_jumpStatement( alJump )
|
440
|
+
@logger.info "#{__method__}: alJump=#{alJump}, label=#{alJump.label}"
|
441
|
+
gen_goto( alJump.label )
|
442
|
+
end
|
443
|
+
|
444
|
+
# Generate skip; <genratedLabel>: skip;, or label: skip;
|
445
|
+
#
|
446
|
+
# @param alSkipS [Model::SkipStatement] skip statemnet to process, possiby nil
|
447
|
+
def p_skipStatement( alSkipStmt=nil )
|
448
|
+
@logger.info "#{__method__}, alSkipStmt.labeled=#{alSkipStmt.nil? ? 'alSkipStmt was nil' : alSkipStmt.labeled}"
|
449
|
+
if ! alSkipStmt.nil? && alSkipStmt.labeled.is_a?( TrueClass )
|
450
|
+
p = gen_label
|
451
|
+
elsif ! alSkipStmt.nil? && alSkipStmt.labeled
|
452
|
+
p = gen_labeled_stmt(gen_skip, alSkipStmt.labeled )
|
453
|
+
else
|
454
|
+
p = gen_skip
|
455
|
+
end
|
456
|
+
@logger.info "#{__method__}: p=#{p} respod_to?(:sexp_type)=#{p.respond_to?(:sexp_type)}" if @logger.debug?
|
457
|
+
p
|
458
|
+
end
|
459
|
+
|
460
|
+
# @param alServiceCall [Model::CallStatement] AL language call statement
|
461
|
+
# @param tlaParams [Array<TlaSexp>] Evaluated call parameters
|
462
|
+
def p_callServiceStatement( alCallStmt, tlaParams )
|
463
|
+
@logger.info "#{__method__} alCallStmt=#{alCallStmt}"
|
464
|
+
@logger.debug "#{__method__} #{alCallStmt.meta}:#{alCallStmt.name} tlaParams=#{tlaParams.join(',')}" if @logger.debug?
|
465
|
+
gen_procedure_call( tx2ServiceProcedure( alCallStmt), tlaParams )
|
466
|
+
end
|
467
|
+
|
468
|
+
def p_callMacroStatement( alCallStmt, tlaParams )
|
469
|
+
@logger.info "#{__method__} alCallStmt=#{alCallStmt}"
|
470
|
+
@logger.debug "#{__method__} #{alCallStmt.meta}:#{alCallStmt.name} op=#{alCallStmt.operation}, tlaParams=#{tlaParams.join(',')}" if @logger.debug?
|
471
|
+
tlaMacroName = alCallStmt.meta.nil? ? gen_plainname( alCallStmt.name) : gen_specname( alCallStmt.meta, alCallStmt.name)
|
472
|
+
gen_macro_call( tlaMacroName, tlaParams )
|
473
|
+
end
|
474
|
+
|
475
|
+
|
476
|
+
# @param [Array<TlaSexp>] Expressions to output
|
477
|
+
def p_outputStatement( alExpressions )
|
478
|
+
@logger.info "#{__method__}, alExpression=#{alExpressions}"
|
479
|
+
gen_print( gen_sequence(alExpressions) )
|
480
|
+
end
|
481
|
+
|
482
|
+
# @param tlaCondition [TlaSexp] evaluated condition
|
483
|
+
#
|
484
|
+
# @param tlaIfBlock [TlaSexp] evaluated block to exectute when condition true
|
485
|
+
#
|
486
|
+
# @param tlaEleseBlock [TlaSexp,Boolean] evaluated block to
|
487
|
+
# exectute when condition not met, Boolean false if no else block given
|
488
|
+
|
489
|
+
def p_conditionalStatement( tlaCondition, tlaIfBlock, tlaElseBlock )
|
490
|
+
@logger.info "#{__method__}: tlaCondition=#{tlaCondition}"
|
491
|
+
@logger.debug "#{__method__}: ifBlock=#{tlaIfBlock}" if @logger.debug?
|
492
|
+
@logger.debug "#{__method__}: elseBlock=#{tlaElseBlock}" if @logger.debug?
|
493
|
+
gen_if( tlaCondition, tlaIfBlock, tlaElseBlock )
|
494
|
+
end
|
495
|
+
|
496
|
+
# Assign 'tlaRval' to 'tlaLval'
|
497
|
+
#
|
498
|
+
# @param tlaVariable [TlaSexp] evaluated lval
|
499
|
+
# @param tlaRval [TlaSexp] evaluates rval
|
500
|
+
def p_assignTo( tlaLval, tlaRval)
|
501
|
+
@logger.info "#{__method__}: assignTo=#{tlaLval}, rval=#{tlaRval}"
|
502
|
+
gen_assign( tlaLval, tlaRval )
|
503
|
+
end
|
504
|
+
|
505
|
+
# @!endgroup Production rules
|
506
|
+
|
507
|
+
# ------------------------------------------------------------------
|
508
|
+
# @!group Internal helpers
|
509
|
+
|
510
|
+
# Map 'symOp' to 'tlaOperator' using hash table 'ialOperators'
|
511
|
+
private def p_op( symOp )
|
512
|
+
tlaOperator = binaryOperators[symOp]
|
513
|
+
raise "Unsupported operator '#{symOp}' - known operators:#{binaryOperators.keys.join(',')}" if tlaOperator.nil?
|
514
|
+
tlaOperator
|
515
|
+
end
|
516
|
+
|
517
|
+
private def p_unary_op( symOp )
|
518
|
+
tlaOperator = unaryOperators[symOp]
|
519
|
+
raise "Unsupported operator '#{symOp}' - known operators:#{unaryOperators.keys.join(',')}" if tlaOperator.nil?
|
520
|
+
tlaOperator
|
521
|
+
end
|
522
|
+
|
523
|
+
|
524
|
+
|
525
|
+
# @return [Hash] mapping operator symbol to tla symbols
|
526
|
+
private def binaryOperators
|
527
|
+
BINARY_OPERATORS
|
528
|
+
end
|
529
|
+
|
530
|
+
# @return [Hash] mapping operator symbol to tla symbols
|
531
|
+
private def unaryOperators
|
532
|
+
UNARY_OPERATORS
|
533
|
+
end
|
534
|
+
|
535
|
+
|
536
|
+
# @return [Hash] constanExpressions from
|
537
|
+
# 'Sbuilder::Ial::Model::Constants::CONSTANT_EXPRESSIONS'
|
538
|
+
#
|
539
|
+
# @option constanExpressions [:symbol] key constant
|
540
|
+
#
|
541
|
+
# @option constanExpressions [String] value constant in tla
|
542
|
+
# language
|
543
|
+
|
544
|
+
def constantExpressions
|
545
|
+
Sbuilder::Al::Model::Constants::CONSTANT_EXPRESSIONS
|
546
|
+
end
|
547
|
+
|
548
|
+
|
549
|
+
# @return [sTla] TlaSexp for accessing transaction input variable
|
550
|
+
private def tx2InputVariable( tx )
|
551
|
+
# gen_interface_input_variable_name( txInterfaceName( tx.name, tx.operation), tx.meta )
|
552
|
+
tx2InputParameter( tx.meta, tx,name, tx.operation )
|
553
|
+
end
|
554
|
+
|
555
|
+
# @return [sTla] TlaSexp for accessing transaction input variable
|
556
|
+
private def tx2InputParameter( txMeta, txName, txOperation )
|
557
|
+
gen_interface_input_variable_name( txInterfaceName( txName, txOperation), txMeta )
|
558
|
+
end
|
559
|
+
|
560
|
+
|
561
|
+
# @return [sTla] TlaSexp for service procedure of transaction 'tx'
|
562
|
+
private def tx2ServiceProcedure( tx )
|
563
|
+
gen_specname( tx.meta, txInterfaceName( tx.name, tx.operation ))
|
564
|
+
end
|
565
|
+
|
566
|
+
# private def tx2appName( tx )
|
567
|
+
# "#{tx.name}(#{tx.operation})"
|
568
|
+
# end
|
569
|
+
|
570
|
+
private def txInterfaceName( name, operation )
|
571
|
+
"#{name}(#{operation})"
|
572
|
+
end
|
573
|
+
|
574
|
+
# @!endgroup
|
575
|
+
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|