adsl 0.0.2 → 0.0.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6b26fde19cd7f72d505d12b67a37e9eb7c76aba2
4
+ data.tar.gz: 425182f63a8d718786e63dc9f21439c764f9332a
5
+ SHA512:
6
+ metadata.gz: a15fbddc4618acafd6cfe069195656f11ac0ec58ac3d22b36341fa90b0c5a690d15e3ad5c687a0a1c3af134e82093428a93a07737d19f09fcd7241dca437c1a6
7
+ data.tar.gz: 6f84daa5917019dbf27dc523e693d7eee093329de27826777b85c9ce173a09268751e396cbba04d55984e3bdc48c7363b66c12492b3a74428da06ea75facc5f9
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ source "http://rubygems.org"
7
7
  gem "i18n"
8
8
 
9
9
  # lexer/parser
10
- gem "rex"
10
+ gem "rexical"
11
11
  gem "racc"
12
12
 
13
13
  # used all over the place
@@ -15,3 +15,6 @@ gem "active_support"
15
15
 
16
16
  # terminal color output
17
17
  gem "colorize"
18
+
19
+ # extraction tools
20
+ gem "ruby_parser"
data/README.md CHANGED
@@ -1,11 +1,32 @@
1
1
  ADSL - Abstract Data Store Language Parser and Translator
2
2
  =========================================================
3
3
 
4
- This package contains adsl, a Ruby gem for verifying ADSL specifications.
4
+ This tool an Abstract Data Store Language (ADSL) specification verification tool.
5
+
6
+ ADSL is a language for specifying Abstract Data Stores using a syntax familiar to anyone that has experience
7
+ with ORM tools such as Hibernate and ActiveRecord. A specification contains the model classes, actions executed
8
+ using a RESTful interface, and a set of invariants to be verified.
9
+
10
+ This tool verifies a specification by translating it into a first order logic theorem verifiable by [Spass] [1],
11
+ a theorem prover. It provides detailed information on the actions and invariants verified in human-readable or
12
+ CSV format.
13
+
14
+ This tool is distributed as a Ruby gem and is uploaded to [RubyGems.org] [2]. Install it and give it a try!
15
+
5
16
 
6
17
  Installation
7
18
  ------------
8
19
 
20
+ This gem is tested on 32 and 64 bit Linux. OS-X compatibility not tested, give it a try
21
+ and tell us if it works! Windows is not supported at this moment.
22
+
23
+ - Ruby 1.8.7 or later required. We suggest using the [Ruby Version Manager](https://rvm.io/rvm/install/) to manage this installation.
24
+ - [Download and install Spass](http://www.spass-prover.org/download/index.html) and make sure its executable (`bin/SPASS`) on your $PATH
25
+ - Install the ADSL gem by running `gem install adsl`.
26
+
27
+ If you receive an error while generating documentation for 'activesupport' run `gem install rdoc adsl` instead.
28
+ - Test the installation by verifying [the example specification](https://raw.github.com/Bocete/adsl/master/example/running-example.adsl)
29
+
9
30
  Usage
10
31
  -----
11
32
 
@@ -14,28 +35,31 @@ Usage
14
35
  For options and other modes of operation, run
15
36
 
16
37
  adsl-verify --help
17
-
38
+
39
+ You can download sample ADSL specifications
40
+
41
+
18
42
  Development
19
43
  -----------
20
44
 
21
45
  ### Source Repository
22
46
 
23
- The ADSL gem is currently hosted at github. The github web page is
24
- http://github.com/Bocete/adsl. The public git clone URL is
47
+ The ADSL gem is currently hosted at github. The github web page is http://github.com/Bocete/adsl.
48
+ You can download the source using our public git clone URL:
25
49
 
26
50
  git://github.com/Bocete/adsl.git
27
51
 
28
52
  ### Issues and Bug Reports
29
53
 
30
- Feature requests and bug reports can be made here
54
+ Feature requests and bug reports can be made at https://github.com/Bocete/adsl/issues
31
55
 
32
- https://github.com/Bocete/adsl/issues
33
56
 
34
57
  License
35
58
  -------
36
59
 
37
60
  Rake is available under a [Lesser GPL (LGPL) license](LICENSE).
38
61
 
62
+
39
63
  Warranty
40
64
  --------
41
65
 
@@ -43,3 +67,6 @@ This software is provided "as is" and without any express or
43
67
  implied warranties, including, without limitation, the implied
44
68
  warranties of merchantibility and fitness for a particular
45
69
  purpose.
70
+
71
+ [1]: http://www.spass-prover.org/ "Spass"
72
+ [2]: https://rubygems.org/gems/adsl "RubyGems.org"
@@ -12,7 +12,7 @@ module DS
12
12
 
13
13
  def replace(what, with)
14
14
  to_inspect = [self]
15
- inspected = Set[]
15
+ inspected = Set.new
16
16
  replaced = false
17
17
  while not to_inspect.empty?
18
18
  elem = to_inspect.pop
@@ -26,7 +26,7 @@ module DS
26
26
  end
27
27
  inspected << elem[i]
28
28
  end
29
- elsif elem.class.methods.include? 'container_for_fields'
29
+ elsif elem.class.methods.include? 'container_for_fields' or elem.class.methods.include? :container_for_fields
30
30
  elem.class.container_for_fields.each do |field_name|
31
31
  field_val = elem.send field_name
32
32
  if field_val == what
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'active_support/all'
3
2
  require 'util/util'
4
3
 
@@ -247,12 +246,12 @@ module FOL
247
246
  end
248
247
  end
249
248
 
250
- # define a function for each of the above classes, starting with underscore and underscored* afterwards
249
+ # define a method for each of the above classes, starting with underscore and underscored* afterwards
251
250
  # *see: http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/String/Inflections.html
252
251
  self.constants.each do |klass_name|
253
252
  instance_eval do
254
- klass = FOL.const_get(klass_name)
255
- self.send :define_method, "_#{klass_name.underscore}".to_sym do |*args|
253
+ klass = FOL.const_get klass_name
254
+ send :define_method, "_#{klass_name.to_s.underscore}".to_sym do |*args|
256
255
  klass.new(*args).resolve_spass
257
256
  end
258
257
  end
@@ -214,7 +214,7 @@ module ADSL
214
214
  # name => [astnode, dsobj]
215
215
  @classes = ActiveSupport::OrderedHash.new
216
216
  # classname => name => [astnode, dsobj]
217
- @relations = ActiveSupport::OrderedHash.new { |hash, key| hash[key] = ActiveSupport::OrderedHash.new }
217
+ @relations = ActiveSupport::OrderedHash.new{ |hash, key| hash[key] = ActiveSupport::OrderedHash.new }
218
218
  # stack of name => [astnode, dsobj]
219
219
  @actions = ActiveSupport::OrderedHash.new
220
220
  @invariants = []
@@ -234,10 +234,7 @@ module ADSL
234
234
  end
235
235
  @actions = source.actions.dup
236
236
  @invariants = source.invariants.dup
237
- @var_stack = []
238
- source.var_stack.each do |frame|
239
- @var_stack << frame.dup
240
- end
237
+ @var_stack = source.var_stack.map{ |frame| frame.dup }
241
238
  end
242
239
 
243
240
  def on_var_write(&block)
@@ -312,10 +309,10 @@ module ADSL
312
309
  def self.context_vars_that_differ(*contexts)
313
310
  vars_per_context = []
314
311
  contexts.each do |context|
315
- vars_per_context << context.var_stack.inject({}) { |so_far, frame| so_far.merge! frame }
312
+ vars_per_context << context.var_stack.inject(ActiveSupport::OrderedHash.new) { |so_far, frame| so_far.merge! frame }
316
313
  end
317
314
  all_vars = vars_per_context.map{ |c| c.keys }.flatten.uniq
318
- packed = {}
315
+ packed = ActiveSupport::OrderedHash.new
319
316
  all_vars.each do |v|
320
317
  packed[v] = vars_per_context.map{ |vpc| vpc[v][1] }
321
318
  end
@@ -466,23 +463,25 @@ module ADSL
466
463
 
467
464
  def typecheck_and_resolve(context)
468
465
  context.push_frame
466
+
469
467
  contexts = [context]
470
- (1..@blocks.length-1).each do |i|
468
+ (@blocks.length-1).times do
471
469
  contexts << context.dup
472
470
  end
473
-
471
+
474
472
  blocks = []
475
473
  @blocks.length.times do |i|
476
474
  blocks << @blocks[i].typecheck_and_resolve(contexts[i])
477
475
  end
478
476
 
479
- contexts.each do |context|
480
- context.pop_frame
477
+ contexts.each do |c|
478
+ c.pop_frame
481
479
  end
482
480
 
483
481
  either = DS::DSEither.new :blocks => blocks
484
482
 
485
483
  lambdas = []
484
+
486
485
  ADSLTypecheckResolveContext::context_vars_that_differ(*contexts).each do |var_name, vars|
487
486
  var = DS::DSVariable.new :name => var_name, :type => vars.first.type
488
487
  objset = DS::DSEitherLambdaObjset.new :either => either, :vars => vars
@@ -138,8 +138,8 @@ module ADSL
138
138
 
139
139
  # generated by racc
140
140
  def generate_ast(str)
141
- scan_evaluate str
142
- do_parse
141
+ scan str
142
+ # do_parse
143
143
  end
144
144
 
145
145
  def parse(str)
@@ -42,7 +42,7 @@ rule
42
42
  = { [text, lineno] }
43
43
  \+ { [text, lineno] }
44
44
  [01] { [text, lineno] }
45
- \w+ { [:IDENT, ADSLIdent.new(:lineno => lineno, :text => text)] }
45
+ \w+ { [:IDENT, ADSL::ADSLIdent.new(:lineno => lineno, :text => text)] }
46
46
  \s # blank, no action
47
47
  . { [:unknown_symbol, [text, lineno]] }
48
48
  end
@@ -1,196 +1,199 @@
1
1
  #--
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by rex 1.0.2
3
+ # This file is automatically generated by rex 1.0.5
4
4
  # from lexical definition file "./lib/parser/adsl_parser.rex".
5
5
  #++
6
6
 
7
7
  require 'racc/parser'
8
8
  require 'parser/adsl_ast'
9
9
 
10
- module ADSL
11
- class ADSLParser < Racc::Parser
10
+ class ADSL::ADSLParser < Racc::Parser
12
11
  require 'strscan'
13
12
 
14
13
  class ScanError < StandardError ; end
15
14
 
16
- attr_reader :lineno
17
- attr_reader :filename
15
+ attr_reader :lineno
16
+ attr_reader :filename
17
+ attr_accessor :state
18
18
 
19
- def scan_setup ; end
19
+ def scan_setup(str)
20
+ @ss = StringScanner.new(str)
21
+ @lineno = 1
22
+ @state = nil
23
+ end
20
24
 
21
- def action &block
25
+ def action
22
26
  yield
23
27
  end
24
28
 
25
- def scan_str( str )
26
- scan_evaluate str
29
+ def scan_str(str)
30
+ scan_setup(str)
27
31
  do_parse
28
32
  end
33
+ alias :scan :scan_str
29
34
 
30
35
  def load_file( filename )
31
36
  @filename = filename
32
37
  open(filename, "r") do |f|
33
- scan_evaluate f.read
38
+ scan_setup(f.read)
34
39
  end
35
40
  end
36
41
 
37
42
  def scan_file( filename )
38
- load_file filename
43
+ load_file(filename)
39
44
  do_parse
40
45
  end
41
46
 
47
+
42
48
  def next_token
43
- @rex_tokens.shift
49
+ return if @ss.eos?
50
+
51
+ # skips empty actions
52
+ until token = _next_token or @ss.eos?; end
53
+ token
44
54
  end
45
55
 
46
- def scan_evaluate( str )
47
- scan_setup
48
- @rex_tokens = []
49
- @lineno = 1
50
- ss = StringScanner.new(str)
51
- state = nil
52
- until ss.eos?
53
- text = ss.peek(1)
54
- @lineno += 1 if text == "\n"
55
- case state
56
- when nil
57
- case
58
- when (text = ss.scan(/\/\/[^\n\z]*/))
59
- ;
56
+ def _next_token
57
+ text = @ss.peek(1)
58
+ @lineno += 1 if text == "\n"
59
+ token = case @state
60
+ when nil
61
+ case
62
+ when (text = @ss.scan(/\/\/[^\n\z]*/))
63
+ ;
60
64
 
61
- when (text = ss.scan(/\#[^\n\z]*/))
62
- ;
65
+ when (text = @ss.scan(/\#[^\n\z]*/))
66
+ ;
63
67
 
64
- when (text = ss.scan(/\/\*(?:[^\*]*(?:\*+[^\/]+)?)*\*\//))
65
- ;
68
+ when (text = @ss.scan(/\/\*(?:[^\*]*(?:\*+[^\/]+)?)*\*\//))
69
+ ;
66
70
 
67
- when (text = ss.scan(/class\b/))
68
- @rex_tokens.push action { [:class, lineno] }
71
+ when (text = @ss.scan(/class\b/))
72
+ action { [:class, lineno] }
69
73
 
70
- when (text = ss.scan(/extends\b/))
71
- @rex_tokens.push action { [:extends, lineno] }
74
+ when (text = @ss.scan(/extends\b/))
75
+ action { [:extends, lineno] }
72
76
 
73
- when (text = ss.scan(/inverseof\b/))
74
- @rex_tokens.push action { [:inverseof, lineno] }
77
+ when (text = @ss.scan(/inverseof\b/))
78
+ action { [:inverseof, lineno] }
75
79
 
76
- when (text = ss.scan(/create\b/))
77
- @rex_tokens.push action { [:create, lineno] }
80
+ when (text = @ss.scan(/create\b/))
81
+ action { [:create, lineno] }
78
82
 
79
- when (text = ss.scan(/delete\b/))
80
- @rex_tokens.push action { [:delete, lineno] }
83
+ when (text = @ss.scan(/delete\b/))
84
+ action { [:delete, lineno] }
81
85
 
82
- when (text = ss.scan(/foreach\b/))
83
- @rex_tokens.push action { [:foreach, lineno] }
86
+ when (text = @ss.scan(/foreach\b/))
87
+ action { [:foreach, lineno] }
84
88
 
85
- when (text = ss.scan(/either\b/))
86
- @rex_tokens.push action { [:either, lineno] }
89
+ when (text = @ss.scan(/either\b/))
90
+ action { [:either, lineno] }
87
91
 
88
- when (text = ss.scan(/action\b/))
89
- @rex_tokens.push action { [:action, lineno] }
92
+ when (text = @ss.scan(/action\b/))
93
+ action { [:action, lineno] }
90
94
 
91
- when (text = ss.scan(/or\b/))
92
- @rex_tokens.push action { [:or, lineno] }
95
+ when (text = @ss.scan(/or\b/))
96
+ action { [:or, lineno] }
93
97
 
94
- when (text = ss.scan(/subset\b/))
95
- @rex_tokens.push action { [:subset, lineno] }
98
+ when (text = @ss.scan(/subset\b/))
99
+ action { [:subset, lineno] }
96
100
 
97
- when (text = ss.scan(/oneof\b/))
98
- @rex_tokens.push action { [:oneof, lineno] }
101
+ when (text = @ss.scan(/oneof\b/))
102
+ action { [:oneof, lineno] }
99
103
 
100
- when (text = ss.scan(/\.\s*all\b/))
101
- @rex_tokens.push action { [:dotall, lineno] }
104
+ when (text = @ss.scan(/\.\s*all\b/))
105
+ action { [:dotall, lineno] }
102
106
 
103
- when (text = ss.scan(/forall\b/))
104
- @rex_tokens.push action { [:forall, lineno] }
107
+ when (text = @ss.scan(/forall\b/))
108
+ action { [:forall, lineno] }
105
109
 
106
- when (text = ss.scan(/exists\b/))
107
- @rex_tokens.push action { [:exists, lineno] }
110
+ when (text = @ss.scan(/exists\b/))
111
+ action { [:exists, lineno] }
108
112
 
109
- when (text = ss.scan(/in\b/))
110
- @rex_tokens.push action { [:in, lineno] }
113
+ when (text = @ss.scan(/in\b/))
114
+ action { [:in, lineno] }
111
115
 
112
- when (text = ss.scan(/invariant\b/))
113
- @rex_tokens.push action { [:invariant, lineno] }
116
+ when (text = @ss.scan(/invariant\b/))
117
+ action { [:invariant, lineno] }
114
118
 
115
- when (text = ss.scan(/true\b/))
116
- @rex_tokens.push action { [:true, lineno] }
119
+ when (text = @ss.scan(/true\b/))
120
+ action { [:true, lineno] }
117
121
 
118
- when (text = ss.scan(/false\b/))
119
- @rex_tokens.push action { [:false, lineno] }
122
+ when (text = @ss.scan(/false\b/))
123
+ action { [:false, lineno] }
120
124
 
121
- when (text = ss.scan(/!=/))
122
- @rex_tokens.push action { [text, lineno] }
125
+ when (text = @ss.scan(/!=/))
126
+ action { [text, lineno] }
123
127
 
124
- when (text = ss.scan(/!|not\b/))
125
- @rex_tokens.push action { [:not, lineno] }
128
+ when (text = @ss.scan(/!|not\b/))
129
+ action { [:not, lineno] }
126
130
 
127
- when (text = ss.scan(/and\b/))
128
- @rex_tokens.push action { [:and, lineno] }
131
+ when (text = @ss.scan(/and\b/))
132
+ action { [:and, lineno] }
129
133
 
130
- when (text = ss.scan(/equal\b/))
131
- @rex_tokens.push action { [:equal, lineno] }
134
+ when (text = @ss.scan(/equal\b/))
135
+ action { [:equal, lineno] }
132
136
 
133
- when (text = ss.scan(/equiv\b/))
134
- @rex_tokens.push action { [:equiv, lineno] }
137
+ when (text = @ss.scan(/equiv\b/))
138
+ action { [:equiv, lineno] }
135
139
 
136
- when (text = ss.scan(/empty\b/))
137
- @rex_tokens.push action { [:empty, lineno] }
140
+ when (text = @ss.scan(/empty\b/))
141
+ action { [:empty, lineno] }
138
142
 
139
- when (text = ss.scan(/implies\b/))
140
- @rex_tokens.push action { [:implies, lineno] }
143
+ when (text = @ss.scan(/implies\b/))
144
+ action { [:implies, lineno] }
141
145
 
142
- when (text = ss.scan(/\.\./))
143
- @rex_tokens.push action { [text, lineno] }
146
+ when (text = @ss.scan(/\.\./))
147
+ action { [text, lineno] }
144
148
 
145
- when (text = ss.scan(/[{}:\(\)\.,]/))
146
- @rex_tokens.push action { [text, lineno] }
149
+ when (text = @ss.scan(/[{}:\(\)\.,]/))
150
+ action { [text, lineno] }
147
151
 
148
- when (text = ss.scan(/\+=/))
149
- @rex_tokens.push action { [text, lineno] }
152
+ when (text = @ss.scan(/\+=/))
153
+ action { [text, lineno] }
150
154
 
151
- when (text = ss.scan(/\-=/))
152
- @rex_tokens.push action { [text, lineno] }
155
+ when (text = @ss.scan(/\-=/))
156
+ action { [text, lineno] }
153
157
 
154
- when (text = ss.scan(/==/))
155
- @rex_tokens.push action { [text, lineno] }
158
+ when (text = @ss.scan(/==/))
159
+ action { [text, lineno] }
156
160
 
157
- when (text = ss.scan(/<=>/))
158
- @rex_tokens.push action { [text, lineno] }
161
+ when (text = @ss.scan(/<=>/))
162
+ action { [text, lineno] }
159
163
 
160
- when (text = ss.scan(/<=/))
161
- @rex_tokens.push action { [text, lineno] }
164
+ when (text = @ss.scan(/<=/))
165
+ action { [text, lineno] }
162
166
 
163
- when (text = ss.scan(/=>/))
164
- @rex_tokens.push action { [text, lineno] }
167
+ when (text = @ss.scan(/=>/))
168
+ action { [text, lineno] }
165
169
 
166
- when (text = ss.scan(/=/))
167
- @rex_tokens.push action { [text, lineno] }
170
+ when (text = @ss.scan(/=/))
171
+ action { [text, lineno] }
168
172
 
169
- when (text = ss.scan(/\+/))
170
- @rex_tokens.push action { [text, lineno] }
173
+ when (text = @ss.scan(/\+/))
174
+ action { [text, lineno] }
171
175
 
172
- when (text = ss.scan(/[01]/))
173
- @rex_tokens.push action { [text, lineno] }
176
+ when (text = @ss.scan(/[01]/))
177
+ action { [text, lineno] }
174
178
 
175
- when (text = ss.scan(/\w+/))
176
- @rex_tokens.push action { [:IDENT, ADSLIdent.new(:lineno => lineno, :text => text)] }
179
+ when (text = @ss.scan(/\w+/))
180
+ action { [:IDENT, ADSL::ADSLIdent.new(:lineno => lineno, :text => text)] }
177
181
 
178
- when (text = ss.scan(/\s/))
179
- ;
182
+ when (text = @ss.scan(/\s/))
183
+ ;
180
184
 
181
- when (text = ss.scan(/./))
182
- @rex_tokens.push action { [:unknown_symbol, [text, lineno]] }
183
-
184
- else
185
- text = ss.string[ss.pos .. -1]
186
- raise ScanError, "can not match: '" + text + "'"
187
- end # if
185
+ when (text = @ss.scan(/./))
186
+ action { [:unknown_symbol, [text, lineno]] }
188
187
 
189
188
  else
190
- raise ScanError, "undefined state: '" + state.to_s + "'"
191
- end # case state
192
- end # until ss
193
- end # def scan_evaluate
189
+ text = @ss.string[@ss.pos .. -1]
190
+ raise ScanError, "can not match: '" + text + "'"
191
+ end # if
192
+
193
+ else
194
+ raise ScanError, "undefined state: '" + state.to_s + "'"
195
+ end # case state
196
+ token
197
+ end # def _next_token
194
198
 
195
199
  end # class
196
- end # module