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,210 @@
1
+ require 'yaml'
2
+ module Sbuilder
3
+ module Al
4
+ module Translator
5
+
6
+ # not catched
7
+ class TranslatorException < Sbuilder::Al::Util::AlException; end
8
+ # to be catched
9
+ class TranslatorError < Sbuilder::Al::Util::AlError; end
10
+
11
+
12
+ # Visitor implementation
13
+ # {Sbuilder::Al::Translator::Translator#translate} using
14
+ # configuration {Sbuilder::Al::Translator::Translator#rules}
15
+ class Translator
16
+
17
+ # Include common meta services e.g. 'attribute_accessor'
18
+ include Sbuilder::Al::Meta
19
+
20
+ # @!attribute rules controlling visitor and translation
21
+ # * key [Symbol] rule name
22
+ #
23
+ # * value [Hash] rule definition
24
+ # * :debug [Boolean] true if debug rule, optional
25
+ # * :navigations [Array<Hash>] collect ctx[:navigationResults]
26
+ # * :iterate [Boolean] iterate current node keys
27
+ # to apply :rule, if true
28
+ # * :navigate [Symbol] if given lookup :navigate key
29
+ # in current model node to appply :rule
30
+ # * :rule [Symbol|lambda] rule to apply on model node
31
+ # found using :iterate or :navigate, apply to current
32
+ # node if both :itarate and :navigate missing,
33
+ # - symbol: result in ctx[:navigationResults][rule]
34
+ # - lambda: returns Array [key,rule] to produce result
35
+ # in ctx[:navigationResults][key] using rule
36
+ # * :translator [Lambda(ctx)] lambda function producing Array
37
+ # result into ctx[:navigationResults]
38
+ attribute_accessor :rules
39
+
40
+ # @!group Constructors
41
+
42
+ def initialize( rules={} )
43
+ self.rules = rules
44
+ end
45
+
46
+ # Default constructor to initialize functional object with
47
+ # default values
48
+ #
49
+ # @return [Sbuilder::Al::Translator::Translator] translator
50
+ # object
51
+ def self.start( rules )
52
+ Translator.new( rules )
53
+ end
54
+
55
+ # @!endgroup
56
+
57
+
58
+ # Vistit and traslate 'node' starting with 'rules[rule]'
59
+ # (default rule = 'node.type').
60
+ #
61
+ # @see #rules for tranlate rules
62
+ #
63
+ # @param rule [Symbol] apply 'rules[rule]' on 'node'
64
+ #
65
+ # @param node [Array<Hash>] node to transform
66
+ # Sbuilder::Al::Model::Root objects to translate
67
+ #
68
+ # @param ctx [Hash] context collected so far before visiting
69
+ # current 'node', default {}
70
+ #
71
+ #
72
+ # @return [String] result of visiting/translating 'node' and
73
+ # using 'rule'
74
+ #
75
+ def translate( node, rule=node.type, ctx={} )
76
+
77
+ # @logger.debug "#{__method__}: node=#{node}, rule=#{rule}, ctx.keys=#{ctx.keys.join(',')}" if @logger.debug?
78
+ # @logger.debug "#{__method__}: node=#{node}, ctx=#{ctx.to_yaml}" if @logger.debug?
79
+ # Lookup 'rule' from rules
80
+ raise TranslatorException, "Configuration error, missing rule '#{rule}' - knonwn rules: #{rules.keys}" if rules[rule].nil?
81
+ raise TranslatorException, "Configuration error, node empty #{node.to_s}" if node.nil?
82
+ # raise TranslatorException, "Configuration error, node empty #{node.to_s}" if node.nil? or node == {}
83
+
84
+ if rules[rule][:debug]
85
+ puts <<-EOS.unindent
86
+ ------------------------------------------------------------------
87
+ #{rule}:
88
+
89
+ node=#{node}
90
+
91
+ ctx keys=#{ctx.keys.join(',')}
92
+
93
+ ctx=#{ctx.to_yaml}
94
+ EOS
95
+ end
96
+
97
+ # rule -name property in ctx holds current node, restored later
98
+ prev_rule = ctx[rule]
99
+ ctx[rule] = node;
100
+
101
+ # Collect 'navigationResults' to hash with key as
102
+ # 'navigation[:rule] and values with the result of
103
+ # translating the nodes navigated to navigation[:navigate]
104
+ navigationResults = {}
105
+
106
+ # translate :navigations (before translating current node)
107
+ navigations = rules[rule][:navigations] ? rules[rule][:navigations] : []
108
+ navigations = [ navigations ] unless navigations.is_a?( Array )
109
+ navigations.each do |navigation|
110
+
111
+ # Validate rule configration
112
+ raise TranslatorException, "Error in rule #{navigation} -missing rule " if navigation[:rule].nil?
113
+
114
+ if navigation[:navigate].nil? && navigation[:iterate].nil?
115
+ # no change in node - run a new rule on current node
116
+ nodesToNaviagate = [node]
117
+ elsif navigation[:navigate]
118
+ navigateSteps = navigation[:navigate].is_a?(Array ) ? navigation[:navigate] : [ navigation[:navigate] ]
119
+ # real navigation: nodesToNaviagate must exist
120
+ begin
121
+ # walk array of navigation[:navigate] -steps
122
+ currentNode = node
123
+ navigateSteps.each do |navigateStep|
124
+ # Hash, Model: access by ':navigate' key , Struct: send message ':navigate' message
125
+ # puts( "currentNode==#{currentNode}")
126
+ if currentNode.respond_to?( :"[]" ) && !currentNode.is_a?( String )
127
+ currentNode = currentNode[navigateStep]
128
+ elsif currentNode.respond_to?( navigateStep )
129
+ currentNode = currentNode.send( navigateStep )
130
+ else
131
+ raise TranslatorError, "Navigation '#{navigateStep}' in node '#{currentNode}' failed"
132
+ end
133
+ #currentNode = !currentNode.is_a?( Struct ) ? currentNode[navigateStep] : currentNode.send( navigateStep )
134
+ end
135
+ nodesToNaviagate = currentNode
136
+
137
+ rescue NameError => err
138
+ raise $!, <<-EOS,
139
+ #{$!}
140
+
141
+ Error navigating to '#{navigation[:navigate]}' in node #{node}.
142
+
143
+ EOS
144
+ $!.backtrace
145
+ end
146
+ raise TranslatorError, "Navigation '#{navigation[:navigate]}' in node '#{node}' failed" if nodesToNaviagate.nil?
147
+ nodesToNaviagate = [nodesToNaviagate] unless nodesToNaviagate.is_a?(Array)
148
+ elsif navigation[:iterate]
149
+ # NB {} -node --> no iteration
150
+ nodesToNaviagate = node.keys.map { |key| node[key] }
151
+ # raise TranslatorError, "Navigation iterator '#{navigation[:iterate]}' in node '#{node}' failed" unless nodesToNaviagate.any?
152
+ else
153
+ raise TranslatorException, "Error in rule #{navigation} " if navigation[:rule].nil?
154
+ end
155
+
156
+
157
+ # nextRule possibly defined using a lamdba
158
+ traslationKey, nextRule = navigation[:rule].respond_to?( :call ) ? navigation[:rule].call( node ).flatten : [ navigation[:rule], navigation[:rule] ]
159
+ navigationResults[ traslationKey ] =
160
+ nodesToNaviagate.map do |nodeToNaviagate|
161
+ begin
162
+ # run translation
163
+ nextTranslate = nextRule ? translate( nodeToNaviagate, nextRule, ctx ) : []
164
+ rescue TranslatorError => e
165
+ msg = <<-EOS
166
+ #{e.message}
167
+
168
+ within
169
+
170
+ node: #{node}
171
+ rule: #{rule}
172
+ ctx: #{ctx.to_yaml}
173
+ EOS
174
+
175
+ raise e.class.new, msg, e.backtrace
176
+
177
+ end
178
+ nextTranslate
179
+ end
180
+ # puts "navigationResults=#{navigationResults}"
181
+
182
+ end # navigations.each
183
+
184
+ # translate current node
185
+ if rules[rule][:translator]
186
+ ret = rules[rule][:translator].call( ctx.merge( { :navigationResults => navigationResults } ))
187
+ if rules[rule][:debug]
188
+ puts <<-EOS.unindent
189
+
190
+ -----> translation
191
+
192
+ #{ret}
193
+ EOS
194
+
195
+ end
196
+
197
+ end
198
+
199
+ # out of scope
200
+ # ctx.delete(ctx[rule])
201
+ ctx[rule] = prev_rule
202
+ ret
203
+
204
+ end
205
+
206
+ end
207
+
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,16 @@
1
+ module Sbuilder
2
+ module Al
3
+ module Util
4
+
5
+ # Exception class not catched
6
+ class AlException < Exception;
7
+ include Sbuilder::Al::Meta
8
+ end
9
+
10
+ # Application error, should be catched
11
+ class AlError < AlException; end
12
+
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,90 @@
1
+ module Sbuilder
2
+ module Al
3
+ module Util
4
+
5
+ require 'logger'
6
+
7
+ # see http://hawkins.io/2013/08/using-the-ruby-logger/
8
+
9
+ module MyLogger
10
+
11
+ include Sbuilder::Al::Meta
12
+ addService( :hello ) do |what|
13
+ "Hello #{:what}"
14
+ end
15
+
16
+
17
+ # no logging done
18
+
19
+ class NullLoger < Logger
20
+ def initialize(*args)
21
+ end
22
+
23
+ def add(*args, &block)
24
+ end
25
+
26
+ def debug?
27
+ false
28
+ end
29
+ end
30
+
31
+ @@logfile = nil # absolute path to log file
32
+ LOGFILE="sbuilder-al.log"
33
+
34
+ def logfile( options )
35
+ return @@logfile if @@logfile
36
+ @@logfile = options[:logfile] || File.join( Dir.getwd, LOGFILE )
37
+ @@logfile
38
+ end
39
+
40
+ def getLogger( progname=nil, options={} )
41
+
42
+
43
+ progname = self.class.name.split('::').last if progname.nil?
44
+ level = get_level( options )
45
+
46
+ if level.nil?
47
+
48
+ return NullLoger.new
49
+
50
+ else
51
+
52
+ logger = Logger.new( logfile(options) )
53
+ logger.level=level
54
+ logger.progname = progname
55
+ return logger
56
+
57
+ end
58
+
59
+ end # getLogger
60
+
61
+
62
+ # ------------------------------------------------------------------
63
+ private
64
+
65
+ def get_level( options )
66
+
67
+ level_name = options && options[:log] ? options[:log] : ENV['LOG_LEVEL']
68
+
69
+ level = case level_name
70
+ when 'warn', 'WARN'
71
+ Logger::WARN
72
+ when 'info', 'INFO'
73
+ Logger::INFO
74
+ when 'debug', 'DEBUG'
75
+ Logger::DEBUG
76
+ when 'error', 'ERROR'
77
+ Logger::ERROR
78
+ else
79
+ nil
80
+ end
81
+
82
+ return level
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,16 @@
1
+ module Sbuilder
2
+ module Al
3
+
4
+ ##
5
+ # Generic helpers and utilities for Sbuilder::Al
6
+ #
7
+ # Exception: {Sbuilder::Al::Exception} Exception hierarchy
8
+ # starting point to {Sbuilder::Al}
9
+ module Util
10
+ end
11
+ end
12
+ end
13
+
14
+ require_relative( "exception" )
15
+ require_relative( "logger" )
16
+ require_relative( "script_eval" )
@@ -0,0 +1,41 @@
1
+ module Sbuilder
2
+ module Al
3
+ module Util
4
+
5
+ class ScriptException < Sbuilder::Al::Util::AlException; end
6
+ class ScriptError < Sbuilder::Al::Util::AlException; end
7
+ # Evaluate Ruby script
8
+ #
9
+ class ScriptEval
10
+
11
+ # @param filename [String] ruby script to evaluate
12
+ #
13
+ # @param context [Object] available for the Ruby scripts being
14
+ # evaluated
15
+ #
16
+ # @return [Object] return from ruby script
17
+ def self.script_eval( filename, context=nil )
18
+ begin
19
+ # applicationConfiguration can be accessed in 'filename' in variable 'context'
20
+ # context = appContext
21
+ proc = Proc.new {}
22
+ ret = eval( File.read(filename), proc.binding, filename )
23
+ return( ret )
24
+ rescue Errno::ENOENT => err
25
+ msg = <<-HERE
26
+ #{err}: when trying to evaluate Ruby script in file #{filename}
27
+ HERE
28
+ raise ScriptError, msg, err.backtrace
29
+ rescue SyntaxError => err
30
+ msg = <<~HERE
31
+ #{err}: when evaluating Ruby script in file #{filename}
32
+ #{File.read(filename)}
33
+ HERE
34
+ raise ScriptError, msg, err.backtrace
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8; mode: ruby -*-
2
+
3
+ lib = File.expand_path('../lib/', __FILE__)
4
+ $:.unshift lib unless $:.include?(lib)
5
+
6
+
7
+ # http://guides.rubygems.org/make-your-own-gem/
8
+
9
+ Gem::Specification.new do |s|
10
+
11
+ # version = "0.0.1.pre"
12
+ version = File.open( "VERSION", "r" ) { |f| f.read }.strip.gsub( "-SNAPSHOT", ".pre" )
13
+
14
+ s.name = 'sbuilder-al'
15
+ s.version = version
16
+ s.date = Time.now.strftime( "%Y-%m-%d" ) #'2014-09-10'
17
+ s.summary = "API language interface to tla-sbuilder"
18
+ s.description = <<EOF
19
+
20
+ API language interface to tla-sbuilder. Uses API Loader Extension
21
+ Point and Snippet Loader Extension Point in tla-sbuilder tool.
22
+
23
+ tla-sbuilder is a tool to generate runnable formal models in TLA+ language
24
+ http://research.microsoft.com/en-us/um/people/lamport/tla/book.html
25
+ Generated formal models can be verified using TLA+ Tools
26
+ http://research.microsoft.com/en-us/um/people/lamport/tla/tools.html.
27
+
28
+ EOF
29
+ s.authors = ["jarjuk"]
30
+ s.files = ["README.org", "VERSION", "#{s.name}.gemspec", "design/al-language-bnf.org" ] | Dir.glob("lib/**/*")
31
+ s.require_paths = [ "lib" ]
32
+ s.executables = [ ]
33
+ s.license = 'MIT'
34
+
35
+ s.homepage = "https://github.com/jarjuk/sbuilder-al"
36
+
37
+ s.required_ruby_version = '~> 2'
38
+
39
+ s.add_runtime_dependency "docile", '~>1.1', ">=1.1.5"
40
+ s.add_runtime_dependency 'mustache', '~>1.0', ">=1.0.3"
41
+ s.add_runtime_dependency "tla-sbuilder", '~>0.3', ">=0.3.5"
42
+ s.add_runtime_dependency "tla-parser-s", '~>0.2', ">=0.2.5"
43
+
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sbuilder-al
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ platform: ruby
6
+ authors:
7
+ - jarjuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.5
33
+ - !ruby/object:Gem::Dependency
34
+ name: mustache
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.0.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: tla-sbuilder
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.3'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.3.5
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.3'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 0.3.5
73
+ - !ruby/object:Gem::Dependency
74
+ name: tla-parser-s
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '0.2'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.5
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.2'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.2.5
93
+ description: "\n API language interface to tla-sbuilder. Uses API Loader Extension\n
94
+ \ Point and Snippet Loader Extension Point in tla-sbuilder tool.\n\n tla-sbuilder
95
+ is a tool to generate runnable formal models in TLA+ language\n http://research.microsoft.com/en-us/um/people/lamport/tla/book.html\n
96
+ \ Generated formal models can be verified using TLA+ Tools\n http://research.microsoft.com/en-us/um/people/lamport/tla/tools.html.\n
97
+ \ \n"
98
+ email:
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - README.org
104
+ - VERSION
105
+ - design/al-language-bnf.org
106
+ - lib/meta/etc.rb
107
+ - lib/meta/meta.rb
108
+ - lib/model/api.rb
109
+ - lib/model/builders.rb
110
+ - lib/model/constants.rb
111
+ - lib/model/model.rb
112
+ - lib/model/module.rb
113
+ - lib/plugin/controller.rb
114
+ - lib/plugin/module.rb
115
+ - lib/plugin/plugin.rb
116
+ - lib/sbuilder-al.rb
117
+ - lib/translator/alrules.rb
118
+ - lib/translator/module.rb
119
+ - lib/translator/producer.rb
120
+ - lib/translator/renderer.rb
121
+ - lib/translator/sexp.rb
122
+ - lib/translator/tlagenerator.rb
123
+ - lib/translator/translator.rb
124
+ - lib/util/exception.rb
125
+ - lib/util/logger.rb
126
+ - lib/util/module.rb
127
+ - lib/util/script_eval.rb
128
+ - sbuilder-al.gemspec
129
+ homepage: https://github.com/jarjuk/sbuilder-al
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '2'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.6.14
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: API language interface to tla-sbuilder
153
+ test_files: []