sbuilder-al 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/sbuilder-al.rb
ADDED
@@ -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
|