sbuilder-al 0.0.8

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.
@@ -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: []