adsl 0.0.2 → 0.0.3

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