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,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