sbuilder-ial 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|