sbuilder-al 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,603 @@
1
+ module Sbuilder
2
+ module Al
3
+ module Model
4
+ # ==================================================================
5
+ # Builder classes called from {Sbuilder::Al::Model::Api}
6
+
7
+ module Builders
8
+
9
+ # ------------------------------------------------------------------
10
+ # @!group Domain
11
+
12
+ class DomainBuilder
13
+ def name(v=nil); @name=v; self;end
14
+ def value( v=nil) values( Sbuilder::Al::Model::Api::constantExpression{ value v } ); self; end
15
+ def literal( v=nil) values( Sbuilder::Al::Model::Api::tlaPlainname( v ) ); self; end
16
+ def values( v = [] )
17
+ @values ||= []
18
+ @values += v.is_a?(Array) ? v : [v]
19
+ self
20
+ end
21
+ def build
22
+ Domain.new( type: :domain, name: @name, values: @values )
23
+ end
24
+ end
25
+
26
+ # @!endgroup
27
+
28
+ # ------------------------------------------------------------------
29
+ # @!group Statements
30
+
31
+ class BlockBuilder
32
+
33
+ # block statemetns
34
+ def nop
35
+ statements( Sbuilder::Al::Model::Api::skipStatement )
36
+ end
37
+ # add a labeled statement
38
+ def label( lab=nil )
39
+ statements( Sbuilder::Al::Model::Api::skipStatement{ labeled lab } )
40
+ end
41
+
42
+ def jump( lab )
43
+ statements( Sbuilder::Al::Model::Api::jumpStatement( lab ) )
44
+ end
45
+
46
+ # Add jump statement to end label
47
+ # @param interfaceOperation [String] interfaceOperation to fail name(operation)
48
+ def done( interfaceOperation )
49
+ statements( Sbuilder::Al::Model::Api::jumpStatement( Sbuilder::Al::Model::Api::strLabelEnd(interfaceOperation) ) )
50
+ end
51
+
52
+ # Add jump statement to Abort failure label
53
+ # @param interfaceOperation [String] interfaceOperation to fail name(operation)
54
+ def failure( interfaceOperation )
55
+ statements( Sbuilder::Al::Model::Api::jumpStatement( Sbuilder::Al::Model::Api::strLabelFail(interfaceOperation) ) )
56
+ end
57
+
58
+ # Add jump statement to Abort label
59
+ # @param interfaceOperation [String] interfaceOperation to fail name(operation)
60
+ def aborted( interfaceOperation )
61
+ statements( Sbuilder::Al::Model::Api::jumpStatement( Sbuilder::Al::Model::Api::strLabelAbort(interfaceOperation) ) )
62
+ end
63
+
64
+ # @param expression [Expression] TLA-expresion to set on
65
+ # reponse value to, no expresion --> set only status
66
+ #
67
+ def ret( status, expression = nil )
68
+ statements( Sbuilder::Al::Model::Api::returnStatement do
69
+ status( status )
70
+ expression( expression ) unless expression.nil?
71
+ end
72
+ )
73
+ end
74
+
75
+ # Create {ReturnStatement} to set 'expression' to variable 'variableName'
76
+ #
77
+ # @param variableName [String] name of return variable to set
78
+ #
79
+ # @param expression [Expression] Expression to set to return
80
+ # variable
81
+ #
82
+ def returnValue( variableName, expression )
83
+ statements( Sbuilder::Al::Model::Api::returnStatement do
84
+ variable( variableName )
85
+ expression( expression )
86
+ end
87
+ )
88
+ end
89
+
90
+ def output( *msg )
91
+ msg = "" if msg.nil?
92
+ # msg = [ msg ] unless msg.is_a?(Array)
93
+ statements( Sbuilder::Al::Model::Api::outputStatement( msg ) )
94
+ end
95
+ def assignTo( &blk )
96
+ stmt = Sbuilder::Al::Model::Api::assignStatement(&blk)
97
+ statements( stmt )
98
+ end
99
+
100
+ def callMacro( meta, svc=nil, &blk )
101
+ # support callMacro( svc )
102
+ if svc.nil?
103
+ svc = meta
104
+ meta = nil
105
+ end
106
+ stmt = Sbuilder::Al::Model::Api::callStatement do
107
+ callType :macro
108
+ meta meta unless meta.nil?
109
+ name svc
110
+ yield self if blk
111
+ end
112
+ statements( stmt )
113
+ end
114
+ def callService( meta, svc, operation, &blk )
115
+ stmt = Sbuilder::Al::Model::Api::callStatement do
116
+ callType :service
117
+ meta meta
118
+ operation( operation )
119
+ name svc
120
+ yield self if blk
121
+ end
122
+ statements( stmt )
123
+ end
124
+ def ifThen( condExpression, &blk )
125
+ stmt = Sbuilder::Al::Model::Api::conditionalStatement() do
126
+ condition Sbuilder::Al::Model::Api::expression(condExpression)
127
+ ifBlock &blk
128
+ end
129
+ statements( stmt )
130
+ stmt
131
+ end
132
+
133
+ # Build block
134
+ def statements( v = [] )
135
+ @statements = @statements || []
136
+ @statements += v.is_a?( Array ) ? v : [v]
137
+ self
138
+ end
139
+ def build
140
+ Block.new( type: :block, statements: @statements )
141
+ end
142
+ end
143
+
144
+ class StatementBuilder
145
+ end
146
+
147
+ class SkipStatementBuilder < StatementBuilder
148
+ def labeled(v=nil) @labeled= v.nil? ? true : v; self; end
149
+ def build
150
+ SkipStatement.new( type: :skipStatement, labeled: @labeled )
151
+ end
152
+ end
153
+
154
+ class ReturnStatementBuilder
155
+ def status(v=nil) @status=Sbuilder::Al::Model::Api::expression(v); self; end
156
+ def expression(v=nil) @expression=Sbuilder::Al::Model::Api::expression(v); self; end
157
+ def variable(v=nil) @variable=v; self; end
158
+ def build
159
+ type =
160
+ if !@status.nil? && !@expression.nil?
161
+ :returnStatement
162
+ elsif !@status.nil?
163
+ :returnStatus
164
+ elsif !@variable.nil?
165
+ :returnValue
166
+ else
167
+ raise "Shuld define: variable+expression/status+expression/status"
168
+ end
169
+ ReturnStatement.new( type: type, status: @status, expression: @expression, variable: @variable )
170
+ end
171
+ end
172
+
173
+ class JumpStatementBuilder
174
+ def label(v=nil) @label=v; self; end
175
+ def build
176
+ JumpStatement.new( type: :jumpStatement, label: @label )
177
+ end
178
+ end
179
+
180
+ class ConditionalStatementBuilder
181
+ def condition(v=nil) @condition=Sbuilder::Al::Model::Api::expression(v); self; end
182
+ def ifBlock( &blk) @ifBlock=Sbuilder::Al::Model::Api::block( &blk ); self; end
183
+ def elseBlock( &blk ) @elseBlock=Sbuilder::Al::Model::Api::block( &blk ); self; end
184
+ def build
185
+ ConditionalStatement.new( type: :conditionalStatement, condition: @condition, ifBlock: @ifBlock, elseBlock: @elseBlock )
186
+ end
187
+ end
188
+
189
+ class AssignStatementBuilder
190
+ # variable referce v1/v2, parameter reference v2
191
+ def variable(v1=nil, v2=nil); @variable=Sbuilder::Al::Model::Api::reference(v1,v2); self;end
192
+ def rval(v=nil); @rval=Sbuilder::Al::Model::Api::expression(v); self;end
193
+ def build
194
+ AssignStatement.new( type: :assignStatement, variable: @variable, rval: @rval )
195
+ end
196
+ end
197
+
198
+ class CallStatementBuilder
199
+ def callType(v=nil); @callType=v; self;end
200
+ def meta(v=nil); @meta=v; self;end
201
+ def name(v=nil); @name=v; self;end
202
+ def operation(v=nil); @operation=v; self;end
203
+ def parameters( v = [] )
204
+ @parameters = @parameters || []
205
+ @parameters += v.is_a?( Array ) ? v : [v]
206
+ self
207
+ end
208
+ # convinience methods
209
+ def parameter( v )
210
+ parameters( Sbuilder::Al::Model::Api::expression(v) )
211
+ end
212
+ def build
213
+ CallStatement.new( type: :callStatement,
214
+ meta: @meta, name: @name, operation: @operation,
215
+ callType: @callType,
216
+ parameters: @parameters
217
+ )
218
+ end
219
+ end
220
+
221
+
222
+ class OutputStatementBuilder
223
+ def expression(v=nil)
224
+ @expression=Sbuilder::Al::Model::Api::expression(v)
225
+ self
226
+ end
227
+ def build
228
+ OutputStatement.new( type: :outputStatement, expression: @expression )
229
+ end
230
+ end
231
+
232
+
233
+ # @!endgroup
234
+
235
+ # ------------------------------------------------------------------
236
+ # @!group Parameter set
237
+
238
+ class ParameterSetBuilder
239
+
240
+ def parameter( name, isArray, domain=nil )
241
+ raise "Expect boolean for isArray, isArray='#{isArray}'" unless isArray.is_a?(TrueClass) || isArray.is_a?(FalseClass)
242
+ v = Sbuilder::Al::Model::Api::property do
243
+ name( name )
244
+ isArray( isArray )
245
+ domain( domain ) unless domain.nil?
246
+ end
247
+ properties(v)
248
+ end
249
+
250
+ def reference( name, isArray, definition )
251
+ v = Sbuilder::Al::Model::Api::property do
252
+ name( name )
253
+ isArray( isArray )
254
+ definition( definition )
255
+ end
256
+ properties(v)
257
+ end
258
+
259
+ def properties(v=[])
260
+ @properties = @properties || []
261
+ @properties += v.is_a?( Array ) ? v : [v]
262
+ self
263
+ end
264
+
265
+ # @return [Int] number of elements in @properties
266
+ def propertiesLength
267
+ @properties.nil? ? 0 : @properties.length
268
+ end
269
+
270
+ end
271
+
272
+ class ApiDefinitionBuilder < ParameterSetBuilder
273
+ def name(v=nil); @name=v; self;end
274
+ end
275
+
276
+ class DefinitionBuilder < ApiDefinitionBuilder
277
+ def build( meta=nil)
278
+ Definition.new( type: :definition, name: @name, properties: @properties )
279
+ end
280
+ end
281
+
282
+ # Build FunctionDefition using 'inputParameter' and
283
+ # 'outputParameter' methods, which accept DOMAIN names and
284
+ # create constant function paramater names, which can
285
+ # (SHOULD!) be mapped to domain names at some point.
286
+ class FunctionDefinitionBuilder < ApiDefinitionBuilder
287
+ # Create parameter 'P{propertiesLength}' with domain assiaction
288
+ def inputParameter( isArray, domain = nil )
289
+ # Create names p1, p2, ...
290
+ # name = "p#{propertiesLength + 1}"
291
+ name = Sbuilder::Al::Model::Api::inputParameterName(propertiesLength + 1)
292
+ parameter( name, isArray, domain )
293
+ end
294
+ def outputParameter( isArray, domain = nil )
295
+ # create names ret1, ret2, ...
296
+ # name = "ret#{ (@returns || []).length + 1 }"
297
+ name = Sbuilder::Al::Model::Api::outputParameterName( (@returns || []).length + 1)
298
+ parameter( name, isArray, domain )
299
+ end
300
+ # Create parameter 'RET{propertiesLength}' with domain assiaction
301
+ def returns( v=[])
302
+ @returns = @returns || []
303
+ @returns += v.is_a?( Array ) ? v : [v]
304
+ self
305
+ end
306
+ def build( meta=nil)
307
+ # Append @returns to last
308
+ FunctionDefinition.new( type: :function_definition, name: @name, properties: (@properties||[]) + (@returns||[]) )
309
+ end
310
+ end
311
+
312
+ class RequestBuilder < ParameterSetBuilder
313
+ def name(v=nil); @name=v; self;end
314
+ def build( meta=nil)
315
+ Request.new( type: :request, name: @name, properties: @properties )
316
+ end
317
+ end
318
+
319
+ class ResponseBuilder < ParameterSetBuilder
320
+ def name(v=nil); @name=v; self;end
321
+ def build( meta=nil)
322
+ Response.new( type: :response, name: @name, properties: @properties )
323
+ end
324
+ end
325
+
326
+ class PropertyBuilder
327
+ def name(v=nil); @name=v; self;end
328
+ def definition(v=nil); @definition=v; self;end
329
+ def isArray(v=nil); @isArray=v; self;end
330
+ def domain(v=nil); @domain=v; self;end
331
+ def build( meta=nil)
332
+ Property.new( type: :property, name: @name, isArray: @isArray, domain: @domain, definition: @definition )
333
+ end
334
+ end
335
+
336
+
337
+
338
+ # @!endgroup
339
+
340
+ # ------------------------------------------------------------------
341
+ # @!group Storage
342
+
343
+ class LocalBuilder
344
+ def name(v=nil); @name=v; self;end
345
+ def build( meta=nil)
346
+ Local.new( type=:local, name=@name, meta=meta )
347
+ end
348
+ end
349
+
350
+ class VariableBuilder
351
+ def name(v=nil); @name=v; self;end
352
+ def init(v=nil); @init=v; self;end
353
+ def build( meta=nil)
354
+ Variable.new( type=:variable, name=@name, meta=meta, init=@init )
355
+ end
356
+ end
357
+
358
+ class ParameterBuilder
359
+ def name(v=nil); @name=v; self;end
360
+ def build( meta=nil)
361
+ Parameter.new( type=:parameter, name=@name, meta=meta )
362
+ end
363
+ end
364
+
365
+ # @!endgroup
366
+ # ------------------------------------------------------------------
367
+ # @!group Expressions
368
+
369
+ class ConstantExpressionBuilder
370
+ def value(v=nil); @value=v; self;end
371
+ def build( meta=nil)
372
+ ConstantExpression.new( type: :constant_expression, value: @value )
373
+ end
374
+ end
375
+
376
+ class BinaryExpressionBuilder
377
+ def lval(v=nil); @lval=Sbuilder::Al::Model::Api::expression(v); self;end
378
+ def op(v=nil); @op=v; self;end
379
+ def rval(v=nil); @rval=Sbuilder::Al::Model::Api::expression(v); self;end
380
+ def build( meta=nil)
381
+ BinaryExpression.new( type: :binary_expression, lval: @lval, op: @op, rval: @rval )
382
+ end
383
+ end
384
+
385
+ class UnaryExpressionBuilder
386
+ def expr(v=nil); @expr=Sbuilder::Al::Model::Api::expression(v); self;end
387
+ def op(v=nil); @op=v; self;end
388
+ def build( meta=nil)
389
+ UnaryExpression.new( type: :unary_expression, expr: @expr, op: @op )
390
+ end
391
+ end
392
+
393
+
394
+
395
+ # Valid template names for TlaExpressionBuilder
396
+ TLA_TEMPLATES = {
397
+ :set => ->(gen, *args) { gen.gen_set( args ) },
398
+ :sequence => ->(gen, *args) { gen.gen_sequence( args ) },
399
+ :nil => ->(gen, *args) { gen.gen_nilElement( args ) },
400
+ :parenthesis => ->(gen, expr) { gen.gen_parenthesis( expr ) },
401
+ :set_iterate => ->(gen, variable, set ) { gen.gen_set_iterate( variable, set ) },
402
+ :set_generate => ->(gen, map, variable, set ) { gen.gen_set_map( map, gen.gen_set_iterate( variable, set )) },
403
+ :set_select => ->(gen, variable, set, select ) { gen.gen_set_map( gen.gen_set_iterate( variable, set ), select ) },
404
+ :plainname => ->(gen, name ) { gen.gen_plainname( name ) },
405
+ :record_field => ->(gen, record, field ) { gen.gen_record_field( record, field ) },
406
+ :record_index => ->(gen, record, index ) { gen.gen_record_named_field( record, index ) },
407
+ :IF_expression => ->(gen, condExpr, thenExpr, elseExpr) { gen.gen_IF( condExpr, thenExpr, elseExpr ) },
408
+ :operator_call => ->(gen, operator, *arguments ) { gen.gen_operator_call( operator, arguments ) },
409
+ :EXCEPT_expression => ->(gen, variable, *excepts) { gen.gen_EXCEPT( variable, excepts ) },
410
+ # :procedure_call => ->( gen, txName, operationName, params ) { gen.gen_procedure_call( gen.txName2ServiceProcedure( txName, operationName ), params ) },
411
+ :record_field_definition => ->( gen, name, value ) { gen.gen_record_field_definition( name, value ) },
412
+ :record => ->( gen, *arrOfFields ) { gen.gen_record_definition( arrOfFields ) },
413
+ }
414
+
415
+ class ParameterizedExpressionBuilder
416
+ def args(v=nil);
417
+ @args=@args|| []
418
+ @args += v.is_a?( Array ) ? v : [v]
419
+ self;
420
+ end
421
+ # convenience builder
422
+ def arg( v )
423
+ args( Sbuilder::Al::Model::Api::expression(v) )
424
+ end
425
+
426
+ end
427
+
428
+ class ReferenceExpressionBuilder
429
+ def reference(v=nil); @reference=Sbuilder::Al::Model::Api::reference(v); self;end
430
+ def build
431
+ ReferenceExpression.new( meta: @meta, reference: @reference )
432
+ end
433
+ end
434
+
435
+ class ReferenceBuilder
436
+ def fields( fld=nil)
437
+ if !fld.nil?
438
+ @fields = @fields||[]
439
+ @fields << fld
440
+ end
441
+ end
442
+ def name(v=nil); @name=v; self;end
443
+ end
444
+
445
+ class SimpleReferenceBuilder < ReferenceBuilder
446
+ def build
447
+ SimpleReference.new( type: :simple_reference, name: @name, fields:@fields )
448
+ end
449
+ end
450
+ class TxParameterReferenceBuilder < ReferenceBuilder
451
+ def meta(v=nil); @meta=v; self;end
452
+ def operation(v=nil); @operation=v; self;end
453
+ def build
454
+ TxParameterReference.new( type: :tx_parameter_reference, meta: @meta, name: @name, operation: @operation, fields:@fields )
455
+ end
456
+ end
457
+ class VariableReferenceBuilder < ReferenceBuilder
458
+ def meta(v=nil); @meta=v; self;end
459
+ def build
460
+ VariableReference.new( type: :variable_reference, meta: @meta, name: @name, fields:@fields )
461
+ end
462
+ end
463
+
464
+ class TlaExpressionBuilder < ParameterizedExpressionBuilder
465
+ def getTemplates
466
+ TLA_TEMPLATES
467
+ end
468
+
469
+ def template(v=nil); @template=v; self;end
470
+ def build( meta=nil)
471
+ raise Sbuilder::Al::Model::Api::ApiError, "Missing 'template' property in tlaExpression - must give one of valid templates: #{getTemplates.keys.join(',')}" if @template.nil?
472
+ raise Sbuilder::Al::Model::Api::ApiError, "Unsupported tla template '#{@template}' - valid templates: #{getTemplates.keys.join(',')}" if getTemplates[@template].nil?
473
+ TlaExpression.new( type: :tla_expression, template: @template, templateEval: getTemplates[@template], args: @args )
474
+ end
475
+ end
476
+
477
+
478
+ # @!endgroup
479
+
480
+ # ------------------------------------------------------------------
481
+ # @!group Transaction, function, macros etc
482
+
483
+ class CallableBuilder
484
+ def name(v=nil); @name=v; self;end
485
+ end
486
+
487
+ class FunctionCallableBuilder < CallableBuilder
488
+ def request(v=nil); @request=v; self;end
489
+ def locals(v=nil)
490
+ @locals = @locals || []
491
+ @locals += v.is_a?( Array ) ? v : [v]
492
+ self
493
+ end
494
+ def response(v=nil); @response=v; self;end
495
+ # Convenience methods:
496
+ def local( v) locals(v);self; end
497
+ def block(v=nil, &blk )
498
+ if block_given?
499
+ @block = Sbuilder::Al::Model::Api::block( &blk )
500
+ else
501
+ @block=v
502
+ end
503
+ self
504
+ end
505
+ end
506
+
507
+ class SnippetBuilder < FunctionCallableBuilder
508
+ def txt(v) @txt=v; self; end
509
+ def build(meta)
510
+ Snippet.new( type: :snippet, meta: meta, name: @name, txt: @txt )
511
+ end
512
+ end
513
+
514
+ class TransactionBuilder < FunctionCallableBuilder
515
+ def operation(v=nil) @operation=v; self; end
516
+ def interfaceOption(v=nil) @interfaceOption=v; self; end
517
+ def returnOption(v=nil) @returnOption=v; self; end
518
+ def sourceModule( v ) @sourceModule = v; self; end
519
+ def sourceLine( v ) @sourceLine = v; self; end
520
+ def sourceColumn( v ) @sourceColumn = v; self; end
521
+ def build(meta)
522
+ Transaction.new(
523
+ type: :transaction, meta: meta, name: @name, operation: @operation, locals: @locals,
524
+ request: @request, response: @response, block: @block,
525
+ interfaceOption: @interfaceOption, returnOption: @returnOption,
526
+ sourceModule: @sourceModule, sourceLine: @sourceLine, sourceColumn: @sourceColumn )
527
+ end
528
+ end
529
+
530
+ class FunctionBuilder < FunctionCallableBuilder
531
+ def build( meta=nil)
532
+ Function.new( type: :function, meta: meta, name: @name, locals: @locals,
533
+ request: @request, response: @response, block: @block )
534
+ end
535
+ end
536
+
537
+ class OperatorBuilder
538
+ def name(v=nil); @name=v; self;end
539
+ def parameters(v=nil)
540
+ @parameters = @parameters || []
541
+ @parameters += v.is_a?( Array ) ? v : [v]
542
+ self
543
+ end
544
+ def rval(v=nil); @rval= v; self; end
545
+ # Convenience methods:
546
+ def parameter( v) parameters(v);self; end
547
+ def expression( e )
548
+ @rval = Sbuilder::Al::Model::Api::expression( e )
549
+ self
550
+ end
551
+ # Build action
552
+ def build( meta=nil)
553
+ Operator.new( type: :operator, meta: meta, name: @name,
554
+ parameters: @parameters,
555
+ # rval: @rval || Sbuilder::Al::Model::Api::constantExpression{ value true }
556
+ rval: @rval || Sbuilder::Al::Model::Api::expression( true )
557
+ )
558
+ end
559
+ end
560
+
561
+ # Map appName to specName without implementation
562
+ class AliasBuilder
563
+ def name(v=nil); @name=v; self;end
564
+ def specName(v=nil); @specName=v; self;end
565
+ # Build action
566
+ def build( meta=nil )
567
+ Sbuilder::Al::Model::Alias.new( type: :alias, meta: meta, name: @name, specName: @specName )
568
+ end
569
+ end
570
+
571
+
572
+ class MacroBuilder
573
+ def name(v=nil); @name=v; self;end
574
+ def parameters(v=nil)
575
+ @parameters = @parameters || []
576
+ @parameters += v.is_a?( Array ) ? v : [v]
577
+ self
578
+ end
579
+ def block(v=nil, &blk )
580
+ if block_given?
581
+ @block = Sbuilder::Al::Model::Api::block( &blk )
582
+ else
583
+ @block=v
584
+ end
585
+ self
586
+ end
587
+
588
+ # Convenience methods:
589
+ def parameter( v) parameters(v);self; end
590
+ # Build action
591
+ def build( meta=nil)
592
+ Macro.new( type: :macro, meta: meta, name: @name, parameters: @parameters, block: @block )
593
+ end
594
+ end
595
+
596
+
597
+ # @!endgroup
598
+
599
+
600
+ end # builders
601
+ end # module Model
602
+ end # module Al
603
+ end # module Sbuilder