sbuilder-ial 0.0.1
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/VERSION +1 -0
- data/lib/action/exception.rb +13 -0
- data/lib/action/extender.rb +30 -0
- data/lib/action/file_path.rb +35 -0
- data/lib/action/model_builder.rb +74 -0
- data/lib/action/render/exception.rb +12 -0
- data/lib/action/render/producer.rb +193 -0
- data/lib/action/render/producer_ethereum.rb +404 -0
- data/lib/action/render/producer_ethereum_const.rb +221 -0
- data/lib/action/render/renderer.rb +142 -0
- data/lib/action/render/tla_element_generator.rb +1306 -0
- data/lib/action/script_eval.rb +32 -0
- data/lib/action/text.rb +17 -0
- data/lib/action/tla_rules.rb +512 -0
- data/lib/action/translator.rb +160 -0
- data/lib/app/app.rb +259 -0
- data/lib/ethereum/api.rb +669 -0
- data/lib/ethereum.rb +1 -0
- data/lib/fp/compositable.rb +185 -0
- data/lib/fp/error.rb +19 -0
- data/lib/fp/exception.rb +9 -0
- data/lib/fp/result.rb +19 -0
- data/lib/fp/sequence.rb +65 -0
- data/lib/ial/build.rb +12 -0
- data/lib/ial/exception.rb +13 -0
- data/lib/model/constants.rb +72 -0
- data/lib/model/model.rb +74 -0
- data/lib/model/model_dsl.rb +1038 -0
- data/lib/model/sexp.rb +58 -0
- data/lib/plugin/plugin.rb +273 -0
- data/lib/sbuilder-ial.rb +44 -0
- data/lib/utils/logger.rb +82 -0
- data/sbuilder-ial.gemspec +36 -0
- metadata +137 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Ial
|
3
|
+
module Action
|
4
|
+
|
5
|
+
# not catched in 'Fp'
|
6
|
+
class TranslatorException < ActionException; end
|
7
|
+
# catched in 'Fp'
|
8
|
+
class TranslatorError < ActionError; end
|
9
|
+
|
10
|
+
class Translator
|
11
|
+
|
12
|
+
PROGNAME = nil # progname for logger default class name
|
13
|
+
include Sbuilder::Ial::MyLogger # mix logger
|
14
|
+
|
15
|
+
|
16
|
+
# @attr [Hash] rules [rule->action]controlling translation
|
17
|
+
# @option rule [:Symbol] identify rule names
|
18
|
+
# @option action [Hash] actions
|
19
|
+
attr_accessor :rules
|
20
|
+
|
21
|
+
def initialize( rules, options={} )
|
22
|
+
self.rules = rules
|
23
|
+
@logger = getLogger( nil, options )
|
24
|
+
@logger.info "#{__method__}: starting options=#{options}"
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.start( elementGenarator, options={} )
|
29
|
+
# elementGenarator = Sbuilder::Ial::Action::Render::TlaElementGenerator.start if elementGenarator.nil?
|
30
|
+
Translator.new( TlaRules.rules(elementGenarator), options )
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def translate( node, rule=:start, ctx={} )
|
35
|
+
|
36
|
+
@logger.debug "#{__method__}: node=#{node}, rule=#{rule}, ctx.keys=#{ctx.keys.join(',')}" if @logger.debug?
|
37
|
+
# @logger.debug "#{__method__}: node=#{node}, ctx=#{ctx.to_yaml}" if @logger.debug?
|
38
|
+
# Lookup 'rule' from rules
|
39
|
+
raise TranslatorException, "Configuration error missing rule '#{rule}' - knonwn rules: #{rules.keys}" if rules[rule].nil?
|
40
|
+
raise TranslatorException, "Configuration error, node empty #{node.to_s}" if node.nil?
|
41
|
+
# raise TranslatorException, "Configuration error, node empty #{node.to_s}" if node.nil? or node == {}
|
42
|
+
|
43
|
+
if rules[rule][:debug]
|
44
|
+
puts <<-EOS.unindent
|
45
|
+
------------------------------------------------------------------
|
46
|
+
#{rule}:
|
47
|
+
|
48
|
+
node=#{node}
|
49
|
+
|
50
|
+
ctx keys=#{ctx.keys.join(',')}
|
51
|
+
|
52
|
+
ctx=#{ctx.to_yaml}
|
53
|
+
EOS
|
54
|
+
end
|
55
|
+
|
56
|
+
# rule -name property in ctx holds current node, restored later
|
57
|
+
prev_rule = ctx[rule]
|
58
|
+
ctx[rule] = node;
|
59
|
+
|
60
|
+
# Collect 'navigationResults' to hash with key as
|
61
|
+
# 'navigation[:rule] and values with the result of
|
62
|
+
# translating the nodes navigated to navigation[:navigate]
|
63
|
+
navigationResults = {}
|
64
|
+
|
65
|
+
# translate :navigations (before translating current node)
|
66
|
+
navigations = rules[rule][:navigations] ? rules[rule][:navigations] : []
|
67
|
+
navigations = [ navigations ] unless navigations.is_a?( Array )
|
68
|
+
navigations.each do |navigation|
|
69
|
+
|
70
|
+
# Validate rule configration
|
71
|
+
raise TranslatorException, "Error in rule #{navigation} " if navigation[:rule].nil?
|
72
|
+
|
73
|
+
if navigation[:navigate].nil? && navigation[:iterate].nil?
|
74
|
+
# no change in node - run a new rule on current node
|
75
|
+
nodesToNaviagate = [node]
|
76
|
+
elsif navigation[:navigate]
|
77
|
+
navigateSteps = navigation[:navigate].is_a?(Array ) ? navigation[:navigate] : [ navigation[:navigate] ]
|
78
|
+
# real navigation: nodesToNaviagate must exist
|
79
|
+
begin
|
80
|
+
# walk array of navigation[:navigate] -steps
|
81
|
+
currentNode = node
|
82
|
+
navigateSteps.each do |navigateStep|
|
83
|
+
# Hash, Model: access by ':navigate' key , Struct: send message ':navigate' message
|
84
|
+
currentNode = !currentNode.is_a?( Struct ) ? currentNode[navigateStep] : currentNode.send( navigateStep )
|
85
|
+
end
|
86
|
+
nodesToNaviagate = currentNode
|
87
|
+
# nodesToNaviagate = !node.is_a?( Struct ) ? currentNote on[:navigate]] : node.send( navigation[:navigate] )
|
88
|
+
# nodesToNaviagate = !node.is_a?( Struct ) ? node[navigation[:navigate]] : node.send( navigation[:navigate] )
|
89
|
+
|
90
|
+
rescue NameError => err
|
91
|
+
raise $!, <<-EOS,
|
92
|
+
#{$!}
|
93
|
+
|
94
|
+
Error navigating to '#{navigation[:navigate]}' in node #{node}.
|
95
|
+
|
96
|
+
EOS
|
97
|
+
$!.backtrace
|
98
|
+
end
|
99
|
+
raise TranslatorError, "Navigation '#{navigation[:navigate]}' in node '#{node}' failed" if nodesToNaviagate.nil?
|
100
|
+
nodesToNaviagate = [nodesToNaviagate] unless nodesToNaviagate.is_a?(Array)
|
101
|
+
elsif navigation[:iterate]
|
102
|
+
# NB {} -node --> no iteration
|
103
|
+
nodesToNaviagate = node.keys.map { |key| node[key] }
|
104
|
+
# raise TranslatorError, "Navigation iterator '#{navigation[:iterate]}' in node '#{node}' failed" unless nodesToNaviagate.any?
|
105
|
+
else
|
106
|
+
raise TranslatorException, "Error in rule #{navigation} " if navigation[:rule].nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# nextRule possibly defined using a lamdba
|
111
|
+
traslationKey, nextRule = navigation[:rule].respond_to?( :call ) ? navigation[:rule].call( node ).flatten : [ navigation[:rule], navigation[:rule] ]
|
112
|
+
navigationResults[ traslationKey ] =
|
113
|
+
nodesToNaviagate.map do |nodeToNaviagate|
|
114
|
+
begin
|
115
|
+
# run translation
|
116
|
+
nextTranslate = nextRule ? translate( nodeToNaviagate, nextRule, ctx ) : []
|
117
|
+
rescue TranslatorError => e
|
118
|
+
msg = <<-EOS
|
119
|
+
#{e.message}
|
120
|
+
|
121
|
+
within
|
122
|
+
|
123
|
+
node: #{node}
|
124
|
+
rule: #{rule}
|
125
|
+
ctx: #{ctx.to_yaml}
|
126
|
+
EOS
|
127
|
+
|
128
|
+
raise e.class.new, msg, e.backtrace
|
129
|
+
|
130
|
+
end
|
131
|
+
nextTranslate
|
132
|
+
end
|
133
|
+
# puts "navigationResults=#{navigationResults}"
|
134
|
+
|
135
|
+
end # navigations.each
|
136
|
+
|
137
|
+
# translate current node
|
138
|
+
if rules[rule][:translator]
|
139
|
+
ret = rules[rule][:translator].call( ctx.merge( { :navigationResults => navigationResults } ))
|
140
|
+
if rules[rule][:debug]
|
141
|
+
puts <<-EOS.unindent
|
142
|
+
|
143
|
+
-----> translation
|
144
|
+
|
145
|
+
#{ret}
|
146
|
+
EOS
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
# out of scope
|
153
|
+
# ctx.delete(ctx[rule])
|
154
|
+
ctx[rule] = prev_rule
|
155
|
+
ret
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/app/app.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Sbuilder
|
3
|
+
module Ial
|
4
|
+
module App
|
5
|
+
class App
|
6
|
+
|
7
|
+
PROGNAME = nil # progname for logger default class name
|
8
|
+
include Sbuilder::Ial::MyLogger # mix logger
|
9
|
+
attr_reader :logger
|
10
|
+
|
11
|
+
|
12
|
+
extend Forwardable # for easy delegation
|
13
|
+
|
14
|
+
|
15
|
+
TRANSLATION_TARGETS = [
|
16
|
+
:domains_defines
|
17
|
+
]
|
18
|
+
|
19
|
+
SNIPPET_TEMPLATE =
|
20
|
+
<<-EOS.unindent
|
21
|
+
{|# comment |}(* {|{ comment }|} *)
|
22
|
+
{|/ comment |}{|!
|
23
|
+
Output comment (with newline)
|
24
|
+
|}{|#useEval|}{|#EVAL|}template{|/EVAL|}{|/useEval|}{|^useEval|}{|{body}|}{|/useEval|}
|
25
|
+
EOS
|
26
|
+
|
27
|
+
# @attr [Sbuilder::Ial::Action::ModelBuilder] modelBuilder sexp-> model
|
28
|
+
attr_accessor :modelBuilder
|
29
|
+
|
30
|
+
# # @attr [Sbuilder::Ial::Action::Translator] translator model -> snippet
|
31
|
+
attr_accessor :translator
|
32
|
+
|
33
|
+
# @attr [object] applicationConfiguration to pass to Ruby IAL application modules
|
34
|
+
attr_accessor :applicationConfiguration
|
35
|
+
|
36
|
+
# @attr [Sbuilder::Ial::Action::Render::Producer]
|
37
|
+
attr_accessor :gen
|
38
|
+
|
39
|
+
# # @attr [Hash] partial
|
40
|
+
# attr_accessor :partials
|
41
|
+
|
42
|
+
# @attr [Sbuilder::Ial::Action::Translator] extender snippet -> sbuilder
|
43
|
+
attr_accessor :extender
|
44
|
+
|
45
|
+
# @attr [Sbuilder::Ial::Action::Render::Renderer] renderer
|
46
|
+
attr_accessor :renderer
|
47
|
+
|
48
|
+
def_delegators :extender, # access extension point
|
49
|
+
:defineDomain,
|
50
|
+
:defineSnippet
|
51
|
+
|
52
|
+
# ------------------------------------------------------------------
|
53
|
+
# @!group Contruct & configure
|
54
|
+
|
55
|
+
|
56
|
+
def initialize( options = {} )
|
57
|
+
@logger = getLogger( nil, options )
|
58
|
+
@logger.info "#{__method__}: starting options=#{options}"
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# @param [String] metatypes prefix to make specnames in TLA
|
63
|
+
# language unique
|
64
|
+
#
|
65
|
+
# @param [Object] applicationConfiguration passed to ial
|
66
|
+
# modules
|
67
|
+
#
|
68
|
+
# @return [App] app initilized with actions to implment steps
|
69
|
+
def self.start( options = {}, metatypes: nil, applicationConfiguration: nil )
|
70
|
+
|
71
|
+
app = App.new( options )
|
72
|
+
|
73
|
+
# remember configuration which will be passed to script-eval
|
74
|
+
app.applicationConfiguration = applicationConfiguration
|
75
|
+
app.logger.info "#{__method__}: applicationConfiguration=#{applicationConfiguration}"
|
76
|
+
|
77
|
+
# sexp -> model
|
78
|
+
app.modelBuilder = Sbuilder::Ial::Action::ModelBuilder.start
|
79
|
+
|
80
|
+
# produce snippets etc
|
81
|
+
app.gen = Sbuilder::Ial::Action::Render::ProducerEthereum.start( options, metatypes )
|
82
|
+
# # model -> translations
|
83
|
+
app.translator = Sbuilder::Ial::Action::Translator.start( app.gen, options )
|
84
|
+
|
85
|
+
# tempate -> data -> string
|
86
|
+
app.renderer = Sbuilder::Ial::Action::Render::Renderer.start( options )
|
87
|
+
|
88
|
+
# translation -> extension
|
89
|
+
app.extender = Sbuilder::Ial::Action::Extender.start
|
90
|
+
|
91
|
+
app
|
92
|
+
end
|
93
|
+
|
94
|
+
# @!endgroup
|
95
|
+
|
96
|
+
# ------------------------------------------------------------------
|
97
|
+
# @!group Workdflow
|
98
|
+
|
99
|
+
# Load IAL implemetations arrays from Ruby 'filenames'
|
100
|
+
#
|
101
|
+
# @return [Result|Error] Result holds an Array of Ruby IAL
|
102
|
+
# objects read, Error wraps an exception encounted when
|
103
|
+
# procesing 'filename'
|
104
|
+
def loadIalImplementation( filenames )
|
105
|
+
|
106
|
+
|
107
|
+
filenames = filenames.is_a?( Array ) ? filenames : [ filenames ]
|
108
|
+
|
109
|
+
errors = false
|
110
|
+
ret = Sequence( filenames ).
|
111
|
+
inject( [] ) do |memo,filename|
|
112
|
+
@logger.info "#{__method__}: evaluate script filename=#{filename}, applicationConfiguration=#{applicationConfiguration}"
|
113
|
+
evaluated = Sbuilder::Ial::Action::ScriptEval.script_eval( filename, applicationConfiguration )
|
114
|
+
errors ||= evaluated.isError
|
115
|
+
memo += evaluated.value.is_a?(Array) ? evaluated.value : [evaluated.value]
|
116
|
+
end
|
117
|
+
errors ? Error( ret ) : Result( ret )
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# @return [Result|Error] Result wraps
|
123
|
+
# Sbuilder::Ial::Model::Model, Error wraps 'Array' (with at
|
124
|
+
# least one 'Error' ialObjects)
|
125
|
+
|
126
|
+
def buildModel( ialObjects )
|
127
|
+
|
128
|
+
return Error( "No objects to buidl model ialObjects.nil?=#{ialObjects.nil?}") if ialObjects.nil?
|
129
|
+
|
130
|
+
ret =
|
131
|
+
Sbuilder::Fp::Sequence( ialObjects ).and_then do |vo|
|
132
|
+
# modelBuilder.updateVo(vo)
|
133
|
+
# end.and_then do |vo|
|
134
|
+
# # remap Result to Sequence
|
135
|
+
# Sequence( vo )
|
136
|
+
# end.and_then do |vo|
|
137
|
+
# modelBuilder.validateVo(vo)
|
138
|
+
# end.and_then do |vo|
|
139
|
+
# # remap Result to Sequence
|
140
|
+
# Sequence( vo )
|
141
|
+
# end.and_then do |vo|
|
142
|
+
modelBuilder.defineVo(vo)
|
143
|
+
end
|
144
|
+
|
145
|
+
# # Returns 'Result' (no Error objects in block), or 'Error'
|
146
|
+
# # if sequence block found some error.
|
147
|
+
|
148
|
+
ret
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
def getModel
|
153
|
+
modelBuilder.getModelBuilt
|
154
|
+
end
|
155
|
+
|
156
|
+
# @!endgroup
|
157
|
+
|
158
|
+
|
159
|
+
# ------------------------------------------------------------------
|
160
|
+
# @!group Walk model
|
161
|
+
|
162
|
+
# Run 'translateTargets' on 'model' to return array of
|
163
|
+
# translation ':results' for tranlation types :domain,
|
164
|
+
# :snippet, :interface.
|
165
|
+
#
|
166
|
+
# @param [Sbuilder::Ial::Model::Model] model
|
167
|
+
#
|
168
|
+
# @param [:Symbol:Array] array of tranlation targets to run
|
169
|
+
#
|
170
|
+
# @return [Hash:Sequence] translations
|
171
|
+
# @option translations [:Symbol] :translation values :domain, :snippet, :interface
|
172
|
+
# @option translations [:Symbol] :results array of translation types
|
173
|
+
|
174
|
+
def translateModel( model, translateTargets=nil )
|
175
|
+
|
176
|
+
# default targets can be overridden on command line
|
177
|
+
translateTargets = TRANSLATION_TARGETS if translateTargets.nil?
|
178
|
+
|
179
|
+
# Wrap targets to a sequence, and process target in block
|
180
|
+
ret = Sbuilder::Fp::Sequence( translateTargets ).and_then do |target|
|
181
|
+
|
182
|
+
# Translate 'target' in 'model' --> { :translation=>.. , :results => [] .. }
|
183
|
+
translationResults = translator.translate( model, target )
|
184
|
+
translationResults
|
185
|
+
end
|
186
|
+
|
187
|
+
# Return
|
188
|
+
ret
|
189
|
+
end
|
190
|
+
|
191
|
+
# @!endgroup
|
192
|
+
|
193
|
+
|
194
|
+
# Render 'snippetTemplate' only if 'snippetTemplate[:template]' or 'snippetTemplate[:body]' defined
|
195
|
+
def renderSnippet( snippetTemplate )
|
196
|
+
return nil if snippetTemplate.nil? || ( snippetTemplate[:template].nil? && snippetTemplate[:body].nil? )
|
197
|
+
snippetTemplate[:useEval] = snippetTemplate[:template] ? true : false
|
198
|
+
renderer.partials = gen.partials
|
199
|
+
snippetBody = renderer.to_str( SNIPPET_TEMPLATE, snippetTemplate )
|
200
|
+
snippetBody
|
201
|
+
end
|
202
|
+
|
203
|
+
# # @return [Hash] metatypes
|
204
|
+
# # @option metatypes [Symbol|String] key metatype
|
205
|
+
# # @option metatypes [Symbol] :name
|
206
|
+
# # @option metatypes [Symbol] :prefix
|
207
|
+
def appMetatypes
|
208
|
+
gen.rule_metatypes
|
209
|
+
end
|
210
|
+
|
211
|
+
# ------------------------------------------------------------------
|
212
|
+
# @!group Pass forward
|
213
|
+
|
214
|
+
#
|
215
|
+
# @param [Result] translation with value { :translation=>..., :results=> ... }
|
216
|
+
#
|
217
|
+
def extendWithTranslations( translation )
|
218
|
+
|
219
|
+
# Extract Has from
|
220
|
+
translation = translation.value
|
221
|
+
raise "Error in translation=#{translation}" if translation.nil? || translation[:translation].nil? || translation[:results].nil?
|
222
|
+
case translation[:translation]
|
223
|
+
when :domain
|
224
|
+
translation[:results].each{ |domainDefinition| defineDomain( domainDefinition ) }
|
225
|
+
ret = Result( "Domains defined" )
|
226
|
+
when :snippet
|
227
|
+
warn "TODO: snippeet =#{translation}"
|
228
|
+
# translation[:results].each{ |snippetDefinition| defineSnippet( snippetDefinition ) }
|
229
|
+
translation[:results].each{ |snippetDefinition|
|
230
|
+
warn "snippetDefinition=#{snippetDefinition}"
|
231
|
+
metatype = 'metatype to set'
|
232
|
+
appName = 'apppi'
|
233
|
+
renderData =
|
234
|
+
{
|
235
|
+
:metatype => metatype,
|
236
|
+
:appName => appName,
|
237
|
+
:comment => 'commenttit',
|
238
|
+
:snippet => snippetDefinition
|
239
|
+
}
|
240
|
+
renderer.partials = elementGenarator.partials
|
241
|
+
snippetBody = renderer.to_str( SNIPPET_TEMPLATE, renderData )
|
242
|
+
specName = nil
|
243
|
+
defineSnippet( metatype, appName, snippetBody, specName )
|
244
|
+
}
|
245
|
+
ret = Result( "Snippets defined #{translation}" )
|
246
|
+
else
|
247
|
+
raise "Error in translation=#{translation}"
|
248
|
+
end
|
249
|
+
ret
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
# @!endgroup
|
254
|
+
|
255
|
+
|
256
|
+
end # class App
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|