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.
@@ -0,0 +1,30 @@
1
+ module Sbuilder
2
+
3
+ ##
4
+ # Api language for Sbuilder
5
+ #
6
+ # * Model : {Sbuilder::Al::Model} : Application model classes and
7
+ # Domain Scpecific (DSL) language to build application
8
+ # model for {Sbuilder::Al}
9
+ #
10
+ # * Translator : {Sbuilder::Al::Tranlator} : Module for configurable
11
+ # visitor for hash/struct model for {Sbuilder::Al}
12
+ #
13
+ # * Util: {Sbuilder::Al::Util}: Generic helpers and utilities for
14
+ # {Sbuilder::Al}
15
+ module Al
16
+ end
17
+ end
18
+
19
+ require 'forwardable'
20
+
21
+ require_relative( "meta/meta")
22
+ # require_relative( "./test" )
23
+ # require_relative( "model/model" )
24
+
25
+ #
26
+ require_relative( "util/module" )
27
+ require_relative( "model/module" )
28
+ require_relative( "translator/module" )
29
+ # require_relative( "controller/module" )
30
+ require_relative( "plugin/module" )
@@ -0,0 +1,424 @@
1
+ module Sbuilder
2
+ module Al
3
+ module Translator
4
+
5
+ ##
6
+ # Visitor configuration to translate {Sbuilder::Al::Model}
7
+ # application model structrure using
8
+ # {Sbuilder::Al::Translator::Translator} visitor/translator.
9
+ #
10
+
11
+ class AlRules
12
+
13
+ # @return [Hash] tranlation rules for
14
+ # {Sbuilder::Al::Translator::Translator} visitor algorithm,
15
+ # see {Sbuilder::Al::Translator::Translator#rules}
16
+ def self.rules( producer = nil )
17
+ {
18
+ :domain => {
19
+ # :translator => ->( ctx ) { { :name => ctx[:domain].name, :values => nil } }
20
+ :navigations => [ { :navigate => :values, :rule => :rval } ],
21
+ :translator => ->( ctx ) do
22
+ values = ctx[:navigationResults][:rval].flatten(1)
23
+ producer.p_domain( ctx[:domain].name, values )
24
+ end
25
+ },
26
+
27
+ :definition => {
28
+ :navigations => [ { :navigate => :properties, :rule => :property } ],
29
+ :translator => ->( ctx ) { producer.p_definition( ctx[:definition].name, ctx[:navigationResults][:property].flatten ) }
30
+ # :translator => ->( ctx ) { producer.p_definition( ctx[:definition].name, ctx[:definition][:properties] ) }
31
+ },
32
+
33
+ :function_definition => {
34
+ :navigations => [ { :navigate => :properties, :rule => :property } ],
35
+ :translator => ->( ctx ) { producer.p_function_definition( ctx[:function_definition].name, ctx[:navigationResults][:property].flatten ) }
36
+ },
37
+
38
+ # transaction nodes processes alos as interface
39
+ :interface => {
40
+ :navigations => [
41
+ { :navigate => :request, :rule => :interface_request },
42
+ { :navigate => :response, :rule => :interface_response },
43
+ ],
44
+ :translator => ->( ctx ) do
45
+ iface = ctx[:interface]
46
+ request = ctx[:navigationResults][:interface_request].flatten
47
+ response = ctx[:navigationResults][:interface_response].flatten
48
+ producer.p_interface( iface.name, iface.operation, request, response )
49
+ end
50
+ },
51
+ :interface_request => {
52
+ :navigations => [ { :navigate => :properties, :rule => :property } ],
53
+ :translator => ->( ctx ) do
54
+ ctx[:navigationResults][:property].flatten
55
+ end
56
+ },
57
+ :interface_response => {
58
+ :navigations => [ { :navigate => :properties, :rule => :property } ],
59
+ :translator => ->( ctx ) do
60
+ ctx[:navigationResults][:property].flatten
61
+ end
62
+ },
63
+
64
+ :snippet => {
65
+ # :navigations => [ { :navigate => :properties, :rule => :property } ],
66
+ :translator => ->( ctx ) do
67
+ producer.p_snippet( ctx[:snippet] )
68
+ end
69
+ },
70
+
71
+ :transaction => {
72
+ :navigations => [
73
+ { :navigate => :block, :rule => :block },
74
+ { :navigate => :locals, :rule => :locals },
75
+ ],
76
+ :translator => ->( ctx ) do
77
+ tx = ctx[:transaction]
78
+ stmts = ctx[:navigationResults][:block].flatten(1)
79
+ locals = ctx[:navigationResults][:locals]
80
+ producer.p_transaction( tx, locals, stmts )
81
+ end
82
+ },
83
+
84
+ :macro => {
85
+ :navigations => [
86
+ { :navigate => :block, :rule => :block },
87
+ { :navigate => :parameters, :rule => :parameters },
88
+ ],
89
+ :translator => ->( ctx ) do
90
+ macro = ctx[:macro]
91
+ parameteres = ctx[:navigationResults][:parameters].flatten(1)
92
+ stmts = ctx[:navigationResults][:block].flatten(1)
93
+ producer.p_macro( macro, parameteres, stmts )
94
+ end
95
+ },
96
+
97
+ :operator => {
98
+ :navigations => [
99
+ { :navigate => :rval, :rule => :rval },
100
+ { :navigate => :parameters, :rule => :parameters },
101
+ ],
102
+ :translator => ->( ctx ) do
103
+ operator = ctx[:operator]
104
+ parameteres = ctx[:navigationResults][:parameters].flatten(1)
105
+ rval = producer.unwrap(ctx[:navigationResults][:rval])
106
+ producer.p_operator( operator, parameteres, rval )
107
+ end
108
+ },
109
+
110
+ # ------------------------------------------------------------------
111
+ # Elements in operators, macros, function and transactions
112
+
113
+ :locals => {
114
+ :translator => ->( ctx ) do
115
+ ctx[:locals]
116
+ end
117
+ },
118
+
119
+ :parameters => {
120
+ :translator => ->( ctx ) do
121
+ ctx[:parameters]
122
+ end
123
+ },
124
+
125
+ :block => {
126
+ :debug => false,
127
+ :navigations => [ { :navigate => :statements, :rule => :statement } ],
128
+ :translator => ->( ctx ) do
129
+ stmts = ctx[:navigationResults][:statement].flatten(1)
130
+ if stmts && stmts.any?
131
+ # producer.p_block( stmts.reduce(&:concat) )
132
+ producer.p_block( stmts )
133
+ else
134
+ []
135
+ end
136
+ end,
137
+ },
138
+
139
+ # ------------------------------------------------------------------
140
+ # statements
141
+ :statement => {
142
+ :debug => false,
143
+ :navigations => [ { :rule => ->(node) do
144
+ nodeType = node[:type]
145
+ case nodeType
146
+ when :outputStatement
147
+ [:stmt_type, :output_statement ]
148
+ when :skipStatement
149
+ [:stmt_type, :skip_statement ]
150
+ when :callStatement
151
+ [:stmt_type, :call_statement ]
152
+ when :conditionalStatement
153
+ [:stmt_type, :conditional_statement ]
154
+ when :returnStatement
155
+ [:stmt_type, :return_statement ]
156
+ when :returnStatus
157
+ [:stmt_type, :return_status ]
158
+ when :returnValue
159
+ [:stmt_type, :return_value ]
160
+ when :jumpStatement
161
+ [:stmt_type, :jump_statement ]
162
+ when :assignStatement
163
+ [:stmt_type, :assign_statement ]
164
+ else
165
+ raise "Unknwon node type '#{nodeType}' for #{node}"
166
+ end
167
+ end
168
+ } ],
169
+ :translator => ->( ctx ) { ctx[:navigationResults][:stmt_type] }
170
+ },
171
+
172
+ # various statement types s( s(), s(), ... )
173
+ :skip_statement => {
174
+ :translator => ->( ctx ) { producer.p_skipStatement(ctx[:skip_statement]) }
175
+ },
176
+ :jump_statement => {
177
+ :translator => ->( ctx ) { producer.p_jumpStatement(ctx[:jump_statement]) }
178
+ },
179
+ :return_statement => {
180
+ :navigations => [
181
+ { :navigate => :status, :rule => ->(node) { [:status, :rval] } },
182
+ { :navigate => :expression, :rule => ->(node) { [:expression, :rval] } },
183
+ ],
184
+ :translator => ->( ctx ) {
185
+ raise "return_statement context error: could not find :transaction in [#{ctx.keys.join(',')}]" unless ctx[:transaction]
186
+ tx = ctx[:transaction]
187
+ status = producer.unwrap(ctx[:navigationResults][:status])
188
+ expression = producer.unwrap(ctx[:navigationResults][:expression])
189
+ producer.p_returnStatement( tx, status, expression )
190
+ }
191
+ },
192
+ :return_status => {
193
+ :navigations => [
194
+ { :navigate => :status, :rule => ->(node) { [:status, :rval] } },
195
+ ],
196
+ :translator => ->( ctx ) {
197
+ raise "return_statement context error: could not find :transaction in [#{ctx.keys.join(',')}]" unless ctx[:transaction]
198
+ tx = ctx[:transaction]
199
+ status = producer.unwrap(ctx[:navigationResults][:status])
200
+ producer.p_returnStatus( tx, status )
201
+ }
202
+ },
203
+ :return_value => {
204
+ :navigations => [
205
+ { :navigate => :expression, :rule => ->(node) { [:expression, :rval] } },
206
+ ],
207
+ :translator => ->( ctx ) {
208
+ raise "return_value context error: could not find :transaction in [#{ctx.keys.join(',')}]" unless ctx[:transaction]
209
+ tx = ctx[:transaction]
210
+ variable = ctx[:return_value].variable
211
+ expression = producer.unwrap(ctx[:navigationResults][:expression])
212
+ producer.p_returnValue( tx, variable, expression )
213
+ }
214
+ },
215
+ :conditional_statement => {
216
+ :debug => false,
217
+ :navigations => [
218
+ { :navigate => :condition, :rule => :rval },
219
+ { :navigate => :ifBlock, :rule => ->(node) { [ :ifBlock, :block ]} },
220
+ { :navigate => :elseBlock, :rule => ->(node) {
221
+ if node.elseBlock == false
222
+ # no else block to traverse
223
+ [ :elseBlock, false ]
224
+ else
225
+ [ :elseBlock, :block ]
226
+ end
227
+ }
228
+ },
229
+ ],
230
+ :translator => ->( ctx ) do
231
+ condition = producer.unwrap(ctx[:navigationResults][:rval])
232
+ ifBlock = producer.unwrap(ctx[:navigationResults][:ifBlock])
233
+ elseBlock = producer.unwrap(ctx[:navigationResults][:elseBlock])
234
+ producer.p_conditionalStatement( condition, ifBlock, elseBlock )
235
+ end
236
+ },
237
+ :call_statement => {
238
+ :navigations => [ { :navigate => :parameters, :rule => :rval } ],
239
+ :translator => ->( ctx ) {
240
+ alCallStmt = ctx[:call_statement]
241
+ tlaParams = ctx[:navigationResults][:rval]
242
+ tlaParams = tlaParams.map{ |e| producer.unwrap(e) }
243
+ case alCallStmt.callType
244
+ when :service
245
+ producer.p_callServiceStatement( alCallStmt, tlaParams )
246
+ when :macro
247
+ producer.p_callMacroStatement( alCallStmt, tlaParams )
248
+ else
249
+ raise "Unknown callType '#{alCallStmt.callType}' in #{alCallStmt}"
250
+ end
251
+
252
+ }
253
+ },
254
+ :output_statement => {
255
+ :navigations => [ { :navigate => :expression, :rule => :rval } ],
256
+ :translator => ->( ctx ) {
257
+ expressions = ctx[:navigationResults][:rval]
258
+ # process array of expressions (which should be unwrapped)
259
+ expressions = expressions.map{ |e| producer.unwrap(e) }
260
+ producer.p_outputStatement( expressions )
261
+ }
262
+ },
263
+ :assign_statement => {
264
+ :debug => false,
265
+ :navigations => [
266
+ # { :navigate => [:variable ], :rule => :rval_reference },
267
+ { :navigate => :rval, :rule => :rval },
268
+ ],
269
+ :translator => ->( ctx ) do
270
+ variableReference = ctx[:assign_statement].variable
271
+ tlaReference = producer.p_reference(variableReference)
272
+ tlaRval = producer.unwrap(ctx[:navigationResults][:rval])
273
+ producer.p_assignTo(tlaReference, tlaRval )
274
+ end
275
+ },
276
+
277
+ :property => {
278
+ # :navigations => [ { :navigate => :properties, :rule => :property } ],
279
+ :translator => ->( ctx ) { producer.p_property( ctx[:property] ) }
280
+ },
281
+
282
+ :variable => {
283
+ :debug => false,
284
+ :navigations => [ { :navigate => :init, :rule => :rval } ],
285
+ :translator => ->( ctx ) do
286
+ nameSexp = ctx[:variable]
287
+ initSexp = ctx[:navigationResults][:rval].flatten
288
+ producer.p_variable_definition( nameSexp, initSexp )
289
+ end
290
+ },
291
+
292
+
293
+ # expression rval
294
+ :rval => {
295
+ :debug => false,
296
+ :navigations => [ { :rule => ->(node) do
297
+ nodeType = node[:type]
298
+ case nodeType
299
+ when :constant_expression
300
+ [:rval, :rval_constant ]
301
+ when :reference_expression
302
+ [:rval, :rval_reference ]
303
+ when :binary_expression
304
+ [:rval, :rval_binary_expression ]
305
+ when :unary_expression
306
+ [:rval, :rval_unary_expression ]
307
+ when :tla_expression
308
+ [:rval, :rval_tla_expression ]
309
+ when :simple_reference
310
+ [:rval, :rval_simple_reference ]
311
+ # when :operatorExpression
312
+ # [:rval, :rval_operator_expr ]
313
+ # when :variable
314
+ # [:rval, :rval_variable ]
315
+ else
316
+ raise "Unknwon node type '#{nodeType}' for #{node}"
317
+ end
318
+ end
319
+ } ],
320
+ :translator => ->( ctx ) { ctx[:navigationResults][:rval] }
321
+ },
322
+ :rval_reference => {
323
+ :translator => ->( ctx ) {
324
+ reference = ctx[:rval_reference].reference
325
+ producer.p_reference( reference )
326
+
327
+ # # Reference makes sense only in context of [:transaction, :macro, :operator] for parameters
328
+ # if ctx[:rval_reference].referenceType == :parameter
329
+ # if ctx[:transaction]
330
+ # producer.p_tx_parameter_reference( ctx[:transaction], ctx[:rval_reference] )
331
+ # elsif ctx[:macro]
332
+ # # reference implemented as a simple name
333
+ # producer.p_reference( ctx[:rval_reference] )
334
+ # elsif ctx[:operator]
335
+ # # reference implemented as a simple name
336
+ # producer.p_reference( ctx[:rval_reference] )
337
+ # else
338
+ # # Error in context: raise exception showing context
339
+ # raise "Reference context error: could not find any of [:transaction, :operator, :macro_entry] in [#{ctx.keys.join(',')}]"
340
+ # end
341
+ # elsif ctx[:rval_reference].referenceType == :variable
342
+ # producer.p_reference( ctx[:rval_reference] )
343
+ # else
344
+ # raise "Unknown reference type '#{ctx[:rval_reference].referenceType}' in #{ctx[:rval_reference]}"
345
+ # end
346
+ }
347
+ },
348
+ :rval_binary_expression => {
349
+ :navigations => [
350
+ { :navigate => :lval, :rule => :lval },
351
+ { :navigate => :rval, :rule => :rval }
352
+ ],
353
+ :translator => ->( ctx ) {
354
+ lval = producer.unwrap(ctx[:navigationResults][:lval])
355
+ rval = producer.unwrap(ctx[:navigationResults][:rval])
356
+ producer.p_binary_expression( lval, ctx[:rval_binary_expression].op, rval )
357
+ }
358
+ },
359
+ :rval_unary_expression => {
360
+ :navigations => [
361
+ { :navigate => :expr, :rule => :rval }
362
+ ],
363
+ :translator => ->( ctx ) {
364
+ expr = producer.unwrap(ctx[:navigationResults][:rval])
365
+ producer.p_unary_expression( ctx[:rval_unary_expression].op, expr )
366
+ }
367
+ },
368
+ :lval => {
369
+ # used in binary operator where lval and rval are both
370
+ # expressions, just forward to :rval,
371
+ :debug => false,
372
+ :navigations => [ { :rule => :rval } ],
373
+ :translator => ->( ctx ) { ctx[:navigationResults][:rval] },
374
+ },
375
+ :rval_constant => {
376
+ :translator => ->( ctx ) { producer.p_constant_expression( ctx[:rval_constant].value ) }
377
+ },
378
+ :rval_simple_reference => {
379
+ :translator => ->( ctx ) { producer.p_reference_to_simple( ctx[:rval_simple_reference].name ) }
380
+ },
381
+ :rval_tla_expression => {
382
+ # TlaExpression
383
+ :navigations => [ { :navigate => :args, :rule => :tla_rval } ],
384
+ # :navigations => [ { :navigate => :args, :rule => :rval } ],
385
+ :translator => ->( ctx ) {
386
+ templateEval = ctx[:rval_tla_expression].templateEval
387
+ # args = ctx[:rval_tla_expression].args
388
+ # args = producer.unwrap(ctx[:navigationResults][:tla_rval]) # .flatten(1)
389
+ args = ctx[:navigationResults][:tla_rval].flatten(1)
390
+ # args = ctx[:navigationResults][:rval].flatten(1)
391
+ producer.p_tla_expression( templateEval, args )
392
+ }
393
+ },
394
+ :tla_rval => {
395
+ # :navigations => [ { :rule => :rval } ],
396
+ :navigations => [
397
+ { :rule => ->(node) do
398
+ # for Al objects use rule :rval
399
+ return [ :tla_rval, :rval] if node.is_a?(Sbuilder::Al::Model::RootObject)
400
+ # prune traslation for non Al-objects
401
+ [ :tla_rval, nil ]
402
+ end
403
+ }
404
+ ],
405
+ # :translator => ->( ctx ) {
406
+ # ctx[:navigationResults][:tla_rval].flatten(1)
407
+ # },
408
+ :translator => ->( ctx ) {
409
+ if ctx[:tla_rval].is_a?(Sbuilder::Al::Model::RootObject)
410
+ # Transated Al object
411
+ ctx[:navigationResults][:tla_rval].flatten(1)
412
+ else
413
+ # Non (pruned) Al object - no change
414
+ [ctx[:tla_rval]]
415
+ end
416
+ }
417
+ },
418
+ } # rules hash
419
+ end
420
+
421
+ end
422
+ end
423
+ end
424
+ end