adsl 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -20
- data/README.md +14 -21
- data/bin/adsl-verify +8 -8
- data/lib/adsl.rb +3 -0
- data/lib/adsl/adsl.rb +3 -0
- data/lib/adsl/ds/data_store_spec.rb +339 -0
- data/lib/adsl/extract/instrumenter.rb +206 -0
- data/lib/adsl/extract/meta.rb +33 -0
- data/lib/adsl/extract/rails/action_block_builder.rb +233 -0
- data/lib/adsl/extract/rails/action_instrumenter.rb +400 -0
- data/lib/adsl/extract/rails/action_runner.rb +57 -0
- data/lib/adsl/extract/rails/active_record_metaclass_generator.rb +555 -0
- data/lib/adsl/extract/rails/callback_chain_simulator.rb +135 -0
- data/lib/adsl/extract/rails/invariant_extractor.rb +48 -0
- data/lib/adsl/extract/rails/invariant_instrumenter.rb +70 -0
- data/lib/adsl/extract/rails/other_meta.rb +57 -0
- data/lib/adsl/extract/rails/rails_extractor.rb +211 -0
- data/lib/adsl/extract/rails/rails_instrumentation_test_case.rb +34 -0
- data/lib/adsl/extract/rails/rails_special_gem_instrumentation.rb +120 -0
- data/lib/adsl/extract/rails/rails_test_helper.rb +140 -0
- data/lib/adsl/extract/sexp_utils.rb +54 -0
- data/lib/adsl/fol/first_order_logic.rb +261 -0
- data/lib/adsl/parser/adsl_parser.racc +159 -0
- data/lib/{parser → adsl/parser}/adsl_parser.rex +4 -4
- data/lib/{parser → adsl/parser}/adsl_parser.rex.rb +6 -6
- data/lib/adsl/parser/adsl_parser.tab.rb +1031 -0
- data/lib/adsl/parser/ast_nodes.rb +1410 -0
- data/lib/adsl/railtie.rb +67 -0
- data/lib/adsl/spass/bin.rb +230 -0
- data/lib/{spass → adsl/spass}/ruby_extensions.rb +0 -0
- data/lib/adsl/spass/spass_ds_extensions.rb +931 -0
- data/lib/adsl/spass/spass_translator.rb +393 -0
- data/lib/adsl/spass/util.rb +13 -0
- data/lib/adsl/util/csv_hash_formatter.rb +94 -0
- data/lib/adsl/util/general.rb +228 -0
- data/lib/adsl/util/test_helper.rb +71 -0
- data/lib/adsl/verification/formula_generators.rb +231 -0
- data/lib/adsl/verification/instrumentation_filter.rb +50 -0
- data/lib/adsl/verification/invariant.rb +19 -0
- data/lib/adsl/verification/rails_verification.rb +33 -0
- data/lib/adsl/verification/utils.rb +20 -0
- data/lib/adsl/verification/verification_case.rb +13 -0
- data/test/integration/rails/rails_branch_verification_test.rb +112 -0
- data/test/integration/rails/rails_verification_test.rb +253 -0
- data/test/integration/spass/basic_translation_test.rb +563 -0
- data/test/integration/spass/control_flow_translation_test.rb +421 -0
- data/test/unit/adsl/ds/data_store_spec_test.rb +54 -0
- data/test/unit/adsl/extract/instrumenter_test.rb +103 -0
- data/test/unit/adsl/extract/meta_test.rb +142 -0
- data/test/unit/adsl/extract/rails/action_block_builder_test.rb +178 -0
- data/test/unit/adsl/extract/rails/action_instrumenter_test.rb +68 -0
- data/test/unit/adsl/extract/rails/active_record_metaclass_generator_test.rb +336 -0
- data/test/unit/adsl/extract/rails/callback_chain_simulator_test.rb +76 -0
- data/test/unit/adsl/extract/rails/invariant_extractor_test.rb +92 -0
- data/test/unit/adsl/extract/rails/rails_extractor_test.rb +1380 -0
- data/test/unit/adsl/extract/rails/rails_test_helper_test.rb +25 -0
- data/test/unit/adsl/extract/sexp_utils_test.rb +100 -0
- data/test/unit/adsl/fol/first_order_logic_test.rb +227 -0
- data/test/unit/adsl/parser/action_parser_test.rb +1040 -0
- data/test/unit/adsl/parser/ast_nodes_test.rb +359 -0
- data/test/unit/adsl/parser/class_parser_test.rb +288 -0
- data/test/unit/adsl/parser/general_parser_test.rb +67 -0
- data/test/unit/adsl/parser/invariant_parser_test.rb +432 -0
- data/test/unit/adsl/parser/parser_util_test.rb +126 -0
- data/test/unit/adsl/spass/bin_test.rb +65 -0
- data/test/unit/adsl/spass/ruby_extensions_test.rb +39 -0
- data/test/unit/adsl/spass/spass_ds_extensions_test.rb +7 -0
- data/test/unit/adsl/spass/spass_translator_test.rb +342 -0
- data/test/unit/adsl/util/csv_hash_formatter_test.rb +68 -0
- data/test/unit/adsl/util/general_test.rb +303 -0
- data/test/unit/adsl/util/test_helper_test.rb +120 -0
- data/test/unit/adsl/verification/formula_generators_test.rb +200 -0
- data/test/unit/adsl/verification/instrumentation_filter_test.rb +39 -0
- data/test/unit/adsl/verification/utils_test.rb +39 -0
- data/test/unit/adsl/verification/verification_case_test.rb +8 -0
- metadata +229 -29
- data/lib/ds/data_store_spec.rb +0 -292
- data/lib/fol/first_order_logic.rb +0 -260
- data/lib/parser/adsl_ast.rb +0 -779
- data/lib/parser/adsl_parser.racc +0 -151
- data/lib/parser/adsl_parser.tab.rb +0 -976
- data/lib/parser/dsdl_parser.rex.rb +0 -196
- data/lib/parser/dsdl_parser.tab.rb +0 -976
- data/lib/spass/bin.rb +0 -164
- data/lib/spass/spass_ds_extensions.rb +0 -870
- data/lib/spass/spass_translator.rb +0 -388
- data/lib/spass/util.rb +0 -11
- data/lib/util/csv_hash_formatter.rb +0 -47
- data/lib/util/test_helper.rb +0 -33
- data/lib/util/util.rb +0 -114
data/lib/ds/data_store_spec.rb
DELETED
@@ -1,292 +0,0 @@
|
|
1
|
-
require 'util/util'
|
2
|
-
|
3
|
-
module DS
|
4
|
-
class DSNode
|
5
|
-
def list_entity_classes_written_to
|
6
|
-
recursively_gather :entity_class_writes
|
7
|
-
end
|
8
|
-
|
9
|
-
def list_entity_classes_read
|
10
|
-
recursively_gather :entity_class_reads
|
11
|
-
end
|
12
|
-
|
13
|
-
def replace(what, with)
|
14
|
-
to_inspect = [self]
|
15
|
-
inspected = Set.new
|
16
|
-
replaced = false
|
17
|
-
while not to_inspect.empty?
|
18
|
-
elem = to_inspect.pop
|
19
|
-
if elem.kind_of? Array
|
20
|
-
elem.length.times do |i|
|
21
|
-
if elem[i] == what
|
22
|
-
elem[i] = with
|
23
|
-
replaced = true
|
24
|
-
else
|
25
|
-
to_inspect << elem[i] unless inspected.include? elem[i]
|
26
|
-
end
|
27
|
-
inspected << elem[i]
|
28
|
-
end
|
29
|
-
elsif elem.class.methods.include? 'container_for_fields' or elem.class.methods.include? :container_for_fields
|
30
|
-
elem.class.container_for_fields.each do |field_name|
|
31
|
-
field_val = elem.send field_name
|
32
|
-
if field_val == what
|
33
|
-
elem.send "#{field_name}=", with
|
34
|
-
replaced = true
|
35
|
-
elsif field_val.kind_of?(Array) or field_val.class.methods.include?('container_for_fields')
|
36
|
-
to_inspect << field_val unless inspected.include? field_val
|
37
|
-
end
|
38
|
-
inspected << field_val
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
replaced
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class DSSpec < DSNode
|
47
|
-
container_for :classes, :actions, :invariants
|
48
|
-
end
|
49
|
-
|
50
|
-
class DSClass < DSNode
|
51
|
-
container_for :name, :parent, :relations, :inverse_relations do
|
52
|
-
@relations = [] if @relations.nil?
|
53
|
-
@inverse_relations = [] if @inverse_relations.nil?
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_s
|
57
|
-
@name
|
58
|
-
end
|
59
|
-
|
60
|
-
def superclass_of?(other_class)
|
61
|
-
until other_class.nil?
|
62
|
-
return true if other_class == self
|
63
|
-
other_class = other_class.parent
|
64
|
-
end
|
65
|
-
return false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class DSRelation < DSNode
|
70
|
-
container_for :cardinality, :from_class, :to_class, :name, :inverse_of
|
71
|
-
|
72
|
-
def to_s
|
73
|
-
"#{from}.#{name}"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class DSAction < DSNode
|
78
|
-
container_for :name, :args, :cardinalities, :block
|
79
|
-
|
80
|
-
def statements
|
81
|
-
@block.statements
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class DSBlock < DSNode
|
86
|
-
container_for :statements
|
87
|
-
end
|
88
|
-
|
89
|
-
class DSAssignment < DSNode
|
90
|
-
container_for :var, :objset
|
91
|
-
end
|
92
|
-
|
93
|
-
class DSCreateObj < DSNode
|
94
|
-
container_for :klass
|
95
|
-
|
96
|
-
def entity_class_writes
|
97
|
-
Set[@klass]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class DSCreateObjset < DSNode
|
102
|
-
container_for :createobj
|
103
|
-
end
|
104
|
-
|
105
|
-
class DSCreateTup < DSNode
|
106
|
-
container_for :objset1, :relation, :objset2
|
107
|
-
end
|
108
|
-
|
109
|
-
class DSDeleteObj < DSNode
|
110
|
-
container_for :objset
|
111
|
-
|
112
|
-
def entity_class_writes
|
113
|
-
Set[@objset.type]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
class DSDeleteTup < DSNode
|
118
|
-
container_for :objset1, :relation, :objset2
|
119
|
-
end
|
120
|
-
|
121
|
-
class DSEither < DSNode
|
122
|
-
container_for :blocks, :lambdas
|
123
|
-
end
|
124
|
-
|
125
|
-
class DSEitherLambdaObjset < DSNode
|
126
|
-
container_for :either, :vars
|
127
|
-
end
|
128
|
-
|
129
|
-
class DSForEachCommon < DSNode
|
130
|
-
container_for :objset, :block
|
131
|
-
end
|
132
|
-
|
133
|
-
class DSForEach < DSForEachCommon
|
134
|
-
end
|
135
|
-
|
136
|
-
class DSFlatForEach < DSForEachCommon
|
137
|
-
end
|
138
|
-
|
139
|
-
class DSForEachIteratorObjset < DSNode
|
140
|
-
container_for :for_each
|
141
|
-
|
142
|
-
def typecheck_and_resolve(context)
|
143
|
-
self
|
144
|
-
end
|
145
|
-
|
146
|
-
def type
|
147
|
-
@for_each.objset.type
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
class DSForEachPreLambdaObjset < DSNode
|
152
|
-
container_for :for_each, :before_var, :inside_var
|
153
|
-
end
|
154
|
-
|
155
|
-
class DSForEachPostLambdaObjset < DSNode
|
156
|
-
container_for :for_each, :before_var, :inside_var
|
157
|
-
end
|
158
|
-
|
159
|
-
class DSVariable < DSNode
|
160
|
-
container_for :name, :type
|
161
|
-
end
|
162
|
-
|
163
|
-
class DSAllOf < DSNode
|
164
|
-
container_for :klass
|
165
|
-
|
166
|
-
def type
|
167
|
-
@klass
|
168
|
-
end
|
169
|
-
|
170
|
-
def entity_class_reads
|
171
|
-
@klass
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
class DSSubset < DSNode
|
176
|
-
container_for :objset
|
177
|
-
|
178
|
-
def type
|
179
|
-
@objset.type
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
class DSOneOf < DSNode
|
184
|
-
container_for :objset
|
185
|
-
def type
|
186
|
-
@objset.type
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
class DSDereference < DSNode
|
191
|
-
container_for :objset, :relation
|
192
|
-
|
193
|
-
def type
|
194
|
-
@relation.to_class
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class DSInvariant < DSNode
|
199
|
-
container_for :name, :formula
|
200
|
-
end
|
201
|
-
|
202
|
-
class DSBoolean < DSNode
|
203
|
-
container_for :bool_value
|
204
|
-
|
205
|
-
TRUE = DSBoolean.new :bool_value => true
|
206
|
-
FALSE = DSBoolean.new :bool_value => false
|
207
|
-
|
208
|
-
def type
|
209
|
-
:formula
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
class DSForAll < DSNode
|
214
|
-
container_for :vars, :objsets, :subformula
|
215
|
-
|
216
|
-
def type
|
217
|
-
:formula
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
class DSExists < DSNode
|
222
|
-
container_for :vars, :objsets, :subformula
|
223
|
-
|
224
|
-
def type
|
225
|
-
:formula
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
class DSIn < DSNode
|
230
|
-
container_for :objset1, :objset2
|
231
|
-
|
232
|
-
def type
|
233
|
-
:formula
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
class DSEmpty < DSNode
|
238
|
-
container_for :objset
|
239
|
-
|
240
|
-
def type
|
241
|
-
:formula
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
class DSNot < DSNode
|
246
|
-
container_for :subformula
|
247
|
-
|
248
|
-
def type
|
249
|
-
:formula
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
class DSAnd < DSNode
|
254
|
-
container_for :subformulae
|
255
|
-
|
256
|
-
def type
|
257
|
-
:formula
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
class DSOr < DSNode
|
262
|
-
container_for :subformulae
|
263
|
-
|
264
|
-
def type
|
265
|
-
:formula
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
class DSImplies < DSNode
|
270
|
-
container_for :subformula1, :subformula2
|
271
|
-
|
272
|
-
def type
|
273
|
-
:formula
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
class DSEquiv < DSNode
|
278
|
-
container_for :subformulae
|
279
|
-
|
280
|
-
def type
|
281
|
-
:formula
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
class DSEqual < DSNode
|
286
|
-
container_for :objsets
|
287
|
-
|
288
|
-
def type
|
289
|
-
:formula
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
@@ -1,260 +0,0 @@
|
|
1
|
-
require 'active_support/all'
|
2
|
-
require 'util/util'
|
3
|
-
|
4
|
-
class String
|
5
|
-
def resolve_spass
|
6
|
-
self
|
7
|
-
end
|
8
|
-
|
9
|
-
def split_by_zero_level_comma
|
10
|
-
parts = []
|
11
|
-
sequence_beginning_index = 0
|
12
|
-
index = 0
|
13
|
-
paren_level = 0
|
14
|
-
while index < length
|
15
|
-
if self[index, 1] == '('
|
16
|
-
paren_level += 1
|
17
|
-
elsif self[index, 1] == ')'
|
18
|
-
paren_level -= 1
|
19
|
-
raise ArgumentError, 'Unmatching parenthesis' if paren_level < 0
|
20
|
-
elsif self[index, 1] == ',' and paren_level == 0
|
21
|
-
parts << self[sequence_beginning_index, index - sequence_beginning_index].strip
|
22
|
-
sequence_beginning_index = index + 1
|
23
|
-
end
|
24
|
-
index += 1
|
25
|
-
end
|
26
|
-
parts << self[sequence_beginning_index, length - sequence_beginning_index].strip
|
27
|
-
parts
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Symbol
|
32
|
-
def resolve_spass
|
33
|
-
to_s
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class TrueClass
|
38
|
-
def resolve_spass
|
39
|
-
"true"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class FalseClass
|
44
|
-
def resolve_spass
|
45
|
-
"false"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
module FOL
|
50
|
-
class Not
|
51
|
-
def initialize(*formulae)
|
52
|
-
@formulae = formulae.flatten
|
53
|
-
raise ArgumentError, "At least one subformula required" if @formulae.empty?
|
54
|
-
end
|
55
|
-
|
56
|
-
def resolve_spass
|
57
|
-
children = @formulae.map{ |obj| obj.resolve_spass }
|
58
|
-
children.delete_if{ |a| a == 'false' }
|
59
|
-
return 'false' if children.include? 'true'
|
60
|
-
return And.new(children.map{ |child| child.match('\Anot\((.*)\)\z') ? $1 : "not(#{child})" }).resolve_spass
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
class And
|
66
|
-
attr_reader :objs
|
67
|
-
|
68
|
-
def initialize(*objs)
|
69
|
-
@objs = objs.flatten
|
70
|
-
end
|
71
|
-
|
72
|
-
def resolve_spass
|
73
|
-
children = @objs.map{ |child| child.resolve_spass }
|
74
|
-
children = children.map{ |child| child.match('\Aand\((.*)\)\z') ? $1.split_by_zero_level_comma : child }.flatten
|
75
|
-
children.delete_if{ |a| a == 'true' }
|
76
|
-
return 'false' if children.include? 'false'
|
77
|
-
return 'true' if children.empty?
|
78
|
-
return children.first if children.length == 1
|
79
|
-
return "and(#{children.join(', ')})"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
class Or
|
84
|
-
attr_reader :objs
|
85
|
-
|
86
|
-
def initialize(*objs)
|
87
|
-
@objs = objs.flatten
|
88
|
-
end
|
89
|
-
|
90
|
-
def resolve_spass
|
91
|
-
children = @objs.map{ |child| child.resolve_spass }
|
92
|
-
children = children.map{ |child| child.match('\Aor\((.*)\)\z') ? $1.split_by_zero_level_comma : child }.flatten
|
93
|
-
children.delete_if{ |a| a == 'false' }
|
94
|
-
return 'true' if children.include? 'true'
|
95
|
-
return 'false' if children.empty?
|
96
|
-
return children.first if children.length == 1
|
97
|
-
return "or(#{children.join(', ')})"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class ForAll
|
102
|
-
def initialize(*params)
|
103
|
-
params = params.flatten
|
104
|
-
raise ArgumentError, "At least a formula required" if params.length < 1
|
105
|
-
@args = params.first(params.length - 1)
|
106
|
-
@formula = params.last
|
107
|
-
end
|
108
|
-
|
109
|
-
def resolve_spass
|
110
|
-
args = @args.map{ |obj| obj.resolve_spass }
|
111
|
-
formula = @formula.resolve_spass
|
112
|
-
return formula if args.empty?
|
113
|
-
return 'true' if formula == 'true'
|
114
|
-
return 'false' if formula == 'false'
|
115
|
-
"forall( [#{args.join(', ')}], #{formula})"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
class Exists
|
120
|
-
def initialize(*params)
|
121
|
-
params = params.flatten
|
122
|
-
raise ArgumentError, "At least a formula required" if params.length < 1
|
123
|
-
@args = params.first(params.length - 1)
|
124
|
-
@formula = params.last
|
125
|
-
end
|
126
|
-
|
127
|
-
def resolve_spass
|
128
|
-
args = @args.map{ |obj| obj.resolve_spass }
|
129
|
-
formula = @formula.resolve_spass
|
130
|
-
return formula if args.empty?
|
131
|
-
return 'true' if formula == 'true'
|
132
|
-
return 'false' if formula == 'false'
|
133
|
-
"exists( [#{args.join(', ')}], #{formula})"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
class Equal
|
138
|
-
def initialize(*subformulae)
|
139
|
-
@subformulae = subformulae.flatten
|
140
|
-
raise ArgumentError, "At least two subformulae required" if @subformulae.length < 2
|
141
|
-
end
|
142
|
-
|
143
|
-
def resolve_spass
|
144
|
-
return @subformulae.first.resolve_spass if @subformulae.length == 1
|
145
|
-
combinations = []
|
146
|
-
(@subformulae.length-1).times do |index|
|
147
|
-
combinations << "equal(#{@subformulae[index].resolve_spass}, #{@subformulae[index+1].resolve_spass})"
|
148
|
-
end
|
149
|
-
return And.new(combinations).resolve_spass
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
class Equiv
|
154
|
-
def initialize(*subformulae)
|
155
|
-
@subformulae = subformulae.flatten
|
156
|
-
raise ArgumentError, "At least two subformulae required" if @subformulae.length < 2
|
157
|
-
end
|
158
|
-
|
159
|
-
def resolve_spass
|
160
|
-
subformulae = @subformulae.map{ |sub| sub.resolve_spass }
|
161
|
-
return subformulae.first if subformulae.length == 1
|
162
|
-
return And.new(subformulae).resolve_spass if subformulae.include? 'true'
|
163
|
-
return Not.new(subformulae).resolve_spass if subformulae.include? 'false'
|
164
|
-
combinations = []
|
165
|
-
(subformulae.length-1).times do |index|
|
166
|
-
combinations << "equiv(#{subformulae[index]}, #{subformulae[index+1]})"
|
167
|
-
end
|
168
|
-
return And.new(combinations).resolve_spass
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
class Implies
|
173
|
-
def initialize(from, to)
|
174
|
-
@from = from
|
175
|
-
@to = to
|
176
|
-
end
|
177
|
-
|
178
|
-
def resolve_spass
|
179
|
-
from = @from.resolve_spass
|
180
|
-
to = @to.resolve_spass
|
181
|
-
return to if from == 'true'
|
182
|
-
return 'true' if from == 'false'
|
183
|
-
return Not.new(from).resolve_spass if to == 'false'
|
184
|
-
return 'true' if to == 'true'
|
185
|
-
return "implies(#{from}, #{to})"
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
class OneOf
|
190
|
-
def initialize(*formulae)
|
191
|
-
@formulae = formulae.flatten
|
192
|
-
end
|
193
|
-
|
194
|
-
def resolve_spass
|
195
|
-
return 'false' if @formulae.empty?
|
196
|
-
return @formulae.first.resolve_spass if @formulae.length == 1
|
197
|
-
return Equiv.new(Not.new(@formulae.first), @formulae.last).resolve_spass if @formulae.length == 2
|
198
|
-
|
199
|
-
substatements = []
|
200
|
-
@formulae.length.times do |i|
|
201
|
-
formulae_without_i = @formulae.first(i) + @formulae.last(@formulae.length - 1 - i)
|
202
|
-
substatements << Implies.new(@formulae[i], Not.new(formulae_without_i))
|
203
|
-
end
|
204
|
-
And.new(Or.new(@formulae), substatements).resolve_spass
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
class IfThenElse
|
209
|
-
def initialize(iif, tthen, eelse)
|
210
|
-
@iif = iif
|
211
|
-
@tthen = tthen
|
212
|
-
@eelse = eelse
|
213
|
-
end
|
214
|
-
|
215
|
-
def resolve_spass
|
216
|
-
And.new(Implies.new(@iif, @tthen), Implies.new(Not.new(@iif), @eelse)).resolve_spass
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
class IfThenElseEq
|
221
|
-
def initialize(iif, tthen, eelse)
|
222
|
-
@iif = iif
|
223
|
-
@tthen = tthen
|
224
|
-
@eelse = eelse
|
225
|
-
end
|
226
|
-
|
227
|
-
def resolve_spass
|
228
|
-
And.new(Equiv.new(@iif, @tthen), Equiv.new(Not.new(@iif), @eelse)).resolve_spass
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
class PairwiseEqual
|
233
|
-
def initialize(*list)
|
234
|
-
list = list.flatten
|
235
|
-
@list1 = list.first((list.length/2.0).ceil)
|
236
|
-
@list2 = list.last((list.length/2.0).floor)
|
237
|
-
raise ArgumentError, "Lists not of equal length: [#{@list1.join(", ")}], [#{@list2.join(", ")}]" if @list1.length != @list2.length
|
238
|
-
end
|
239
|
-
|
240
|
-
def resolve_spass
|
241
|
-
equalities = []
|
242
|
-
@list1.length.times do |i|
|
243
|
-
equalities << Equal.new(@list1[i], @list2[i])
|
244
|
-
end
|
245
|
-
return And.new(equalities).resolve_spass
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
# define a method for each of the above classes, starting with underscore and underscored* afterwards
|
250
|
-
# *see: http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/String/Inflections.html
|
251
|
-
self.constants.each do |klass_name|
|
252
|
-
instance_eval do
|
253
|
-
klass = FOL.const_get klass_name
|
254
|
-
send :define_method, "_#{klass_name.to_s.underscore}".to_sym do |*args|
|
255
|
-
klass.new(*args).resolve_spass
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|