cauldron 0.1.0 → 0.1.1
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.
- data/Gemfile +2 -0
- data/Rakefile +7 -0
- data/VERSION +1 -1
- data/features/cauldron_generates_runtime_method.feature +3 -2
- data/features/step_definitions/cauldron_steps.rb +0 -1
- data/features/support/method_1.example +3 -0
- data/features/support/method_2.example +6 -0
- data/lib/Chain.rb +140 -264
- data/lib/CodeHandler.rb +0 -4
- data/lib/ScopeDependencies.rb +1 -0
- data/lib/Theory.rb +12 -15
- data/lib/UnifiedChain.rb +265 -8
- data/lib/cauldron.rb +1 -1
- data/lib/cauldron/demos.rb +280 -0
- data/lib/cauldron/pot.rb +56 -30
- data/lib/cauldron/sexp2cauldron.rb +109 -126
- data/lib/cauldron/terminal.rb +5 -74
- data/lib/core/ClassMethodCallContainer.rb +14 -0
- data/lib/core/Container.rb +12 -2
- data/lib/core/InstanceCallContainer.rb +30 -4
- data/lib/core/TheoryGenerator.rb +2 -9
- data/lib/core/assignment/Equal.rb +1 -1
- data/lib/core/assignment/Equivalent.rb +1 -1
- data/lib/core/assignment/NotEqual.rb +1 -1
- data/lib/core/call_container/CallContainer.rb +7 -1
- data/lib/core/instance_call/Chop.rb +0 -9
- data/lib/core/instance_call/instance_calls.rb +8 -0
- data/lib/core/instance_call/length_equal.rb +1 -1
- data/lib/core/requirement/Requirement.rb +1 -0
- data/lib/core/runtime_class/class_names.rb +12 -12
- data/lib/core/runtime_method/ActsAsRuntimeMethod.rb +0 -7
- data/lib/core/runtime_method/RuntimeMethod.rb +59 -45
- data/lib/core/statement/ActsAsStatement.rb +1 -1
- data/lib/core/statement/ArrayAccess.rb +28 -2
- data/lib/core/statement/OpenStatement.rb +7 -0
- data/lib/core/statement/Statement.rb +22 -18
- data/lib/core/statement/TheoryStatement.rb +8 -1
- data/lib/core/syntax/Addition.rb +3 -2
- data/lib/core/syntax/If.rb +8 -0
- data/lib/core/syntax/Return.rb +1 -1
- data/lib/core/variable/BaseVariable.rb +0 -2
- data/lib/core/variable/MethodParameter.rb +4 -31
- data/lib/core/variable/Unknown.rb +1 -5
- data/lib/implemented_chain.rb +3 -2
- data/lib/required.rb +0 -1
- data/lib/ruby_code/String.rb +0 -17
- data/lib/theories.rb +25 -1
- data/lib/theory/TheoryAction.rb +35 -5
- data/lib/theory/TheoryChainValidator.rb +10 -8
- data/lib/theory/TheoryComponent.rb +17 -0
- data/lib/theory/TheoryConnector.rb +76 -9
- data/lib/theory/TheoryDependent.rb +2 -2
- data/lib/theory/TheoryImplementation.rb +7 -7
- data/lib/util/ClassEvaluation.rb +2 -7
- data/lib/util/MethodValidation.rb +10 -6
- data/lib/util/Parser.rb +26 -20
- data/lib/util/StringToTheory.rb +27 -3
- data/spec/cauldron/chain_spec.rb +24 -0
- data/spec/cauldron/demos_spec.rb +30 -0
- data/spec/cauldron/pot_spec.rb +66 -0
- data/spec/cauldron/runtime_method_spec.rb +47 -5
- data/spec/cauldron/sexp_2_cauldron_spec.rb +92 -0
- data/spec/cauldron/terminal_spec.rb +1 -1
- data/spec/cauldron/theory_action_spec.rb +20 -0
- data/spec/cauldron/theory_connector_spec.rb +52 -0
- data/spec/cauldron/theory_spec.rb +59 -0
- data/spec/cauldron/unified_chain_spec.rb +102 -0
- data/spec/spec_helper.rb +10 -1
- data/tasks/theory_tasks.rake +274 -0
- data/test/fixtures/implementation_results/0/dump +0 -0
- data/test/fixtures/theories/0/dump +0 -0
- data/test/fixtures/theories/1/dump +0 -0
- data/test/fixtures/theories/10/dump +0 -0
- data/test/fixtures/theories/11/dump +0 -0
- data/test/fixtures/theories/12/dump +0 -0
- data/test/fixtures/theories/13/declaration.txt +1 -1
- data/test/fixtures/theories/13/desc +1 -1
- data/test/fixtures/theories/13/dump +0 -0
- data/test/fixtures/theories/14/dump +0 -0
- data/test/fixtures/theories/15/dump +0 -0
- data/test/fixtures/theories/16/dump +0 -0
- data/test/fixtures/theories/17/dump +0 -0
- data/test/fixtures/theories/18/dump +0 -0
- data/test/fixtures/theories/19/dump +0 -0
- data/test/fixtures/theories/2/dump +0 -0
- data/test/fixtures/theories/20/declaration.txt +1 -1
- data/test/fixtures/theories/20/desc +1 -1
- data/test/fixtures/theories/20/dump +0 -0
- data/test/fixtures/theories/3/dump +0 -0
- data/test/fixtures/theories/4/dump +0 -0
- data/test/fixtures/theories/5/dump +0 -0
- data/test/fixtures/theories/6/dump +0 -0
- data/test/fixtures/theories/7/dump +0 -0
- data/test/fixtures/theories/8/dump +0 -0
- data/test/fixtures/theories/9/dump +0 -0
- data/test/fixtures/theory_implementations/0/declaration.txt +1 -1
- data/test/fixtures/theory_implementations/0/dump +0 -0
- data/test/fixtures/theory_implementations/1/declaration.txt +11 -0
- data/test/fixtures/theory_implementations/1/dump +0 -0
- data/test/fixtures/theory_implementations/2/declaration.txt +11 -0
- data/test/fixtures/theory_implementations/2/dump +0 -0
- data/test/output/simple_method.txt +0 -1
- data/test/tc_contextual_variables.rb +2 -41
- data/test/tc_describe.rb +1 -2
- data/test/tc_method.rb +2 -5
- data/test/unit/core/runtime_method/tc_realised_runtime_method.rb +5 -3
- data/test/unit/core/runtime_method/tc_runtime_method.rb +34 -56
- data/test/unit/core/statement/tc_block_statement.rb +2 -0
- data/test/unit/core/statement/tc_open_statement.rb +15 -6
- data/test/unit/core/statement/tc_statement.rb +4 -5
- data/test/unit/core/statement/tc_statement_dependencies.rb +1 -0
- data/test/unit/core/statement/tc_theory_statement.rb +2 -0
- data/test/unit/core/syntax/tc_if_container.rb +5 -5
- data/test/unit/core/tc_theory_generator_heavy.rb +1 -1
- data/test/unit/core/tracking/tc_history.rb +3 -1
- data/test/unit/core/variable/tc_method_parameter_variable.rb +2 -2
- data/test/unit/tc_chain_with_case_1.rb +1 -1
- data/test/unit/tc_method_usage.rb +1 -1
- data/test/unit/tc_theory.rb +8 -2
- data/test/unit/theory/tc_theory_action.rb +37 -5
- data/test/unit/theory/tc_theory_chain_validator.rb +3 -3
- data/test/unit/theory/tc_theory_connector.rb +2 -37
- data/test/unit/theory/tc_theory_dependent.rb +2 -0
- data/test/unit/theory/tc_theory_implementation.rb +5 -1
- data/test/unit/theory/tc_theory_result.rb +3 -2
- data/test/unit/util/tc_method_validation.rb +4 -1
- data/test/unit/util/tc_parser.rb +2 -0
- data/test/unit/util/tc_string_to_theory.rb +3 -2
- data/tmp/runtime_method_evaluation.rb +7 -4
- metadata +59 -13
- data/lib/core/syntax/IfContainer.rb +0 -100
data/Gemfile
CHANGED
data/Rakefile
CHANGED
|
@@ -11,6 +11,12 @@ rescue Bundler::BundlerError => e
|
|
|
11
11
|
end
|
|
12
12
|
require 'rake'
|
|
13
13
|
|
|
14
|
+
$LOAD_PATH << File.expand_path('../lib',__FILE__)
|
|
15
|
+
|
|
16
|
+
require 'lib/cauldron'
|
|
17
|
+
|
|
18
|
+
load File.join(File.dirname(__FILE__), 'tasks', 'theory_tasks.rake')
|
|
19
|
+
|
|
14
20
|
require 'jeweler'
|
|
15
21
|
Jeweler::Tasks.new do |gem|
|
|
16
22
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
|
@@ -21,6 +27,7 @@ Jeweler::Tasks.new do |gem|
|
|
|
21
27
|
gem.description = %Q{Cauldron generates a methd from a number of examples that describe the input and the expected output. It is still at a very early stage of development right now so you're unlikely to get much practical use out of it.}
|
|
22
28
|
gem.email = "warrensangster@yahoo.com"
|
|
23
29
|
gem.authors = ["Warren Sangster"]
|
|
30
|
+
gem.required_ruby_version = '>= 1.6.8'
|
|
24
31
|
# dependencies defined in Gemfile
|
|
25
32
|
end
|
|
26
33
|
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.1
|
|
@@ -8,5 +8,6 @@ Feature: Cauldron generates a runtime method
|
|
|
8
8
|
Then I should receive a runtime method like this <runtime_method>
|
|
9
9
|
|
|
10
10
|
Scenarios: example with only one parameter
|
|
11
|
-
| cases
|
|
12
|
-
| "'sparky','sparky'*'kel','kel'"
|
|
11
|
+
| cases | runtime_method | demo_num |
|
|
12
|
+
| "'sparky','sparky'*'kel','kel'" | "def method_3(var_6)\n\treturn var_6\nend\n" | 1 |
|
|
13
|
+
| "'fish','animal'*'carrot','vegatable'" | "def method_3(var_0)\n\tif(var_0 == 'fish')\n\t\treturn 'animal'\n\tend\n\treturn 'vegetable'\nend\n" | 2 |
|
|
@@ -8,7 +8,6 @@ end
|
|
|
8
8
|
|
|
9
9
|
Then /^I should receive a runtime method like this "([^"]*)"$/ do |runtime_method_statement|
|
|
10
10
|
runtime_method_statement = runtime_method_statement.gsub('\\n',"\n").gsub('\\t',"\t")
|
|
11
|
-
#@terminal.submit('RUN').should == runtime_method_statement
|
|
12
11
|
@terminal.submit('RUN')
|
|
13
12
|
output.messages.should include(runtime_method_statement)
|
|
14
13
|
end
|
data/lib/Chain.rb
CHANGED
|
@@ -29,7 +29,8 @@ class Chain
|
|
|
29
29
|
real_method = Parser.run('runtime_method')
|
|
30
30
|
|
|
31
31
|
# Add the tail to the nodes list
|
|
32
|
-
add_link(@tail_theory,{1=>real_method,2=>tc})
|
|
32
|
+
#add_link(@tail_theory,{1=>real_method,2=>tc})
|
|
33
|
+
extension_permutaions(@tail_theory,{1=>real_method,2=>tc})
|
|
33
34
|
|
|
34
35
|
end
|
|
35
36
|
|
|
@@ -102,6 +103,14 @@ class Chain
|
|
|
102
103
|
end
|
|
103
104
|
end
|
|
104
105
|
|
|
106
|
+
def unmet_dependents_ids
|
|
107
|
+
collection = TheoryCollection.new(@nodes)
|
|
108
|
+
return collection.dependents.inject([]) do |total,dependent|
|
|
109
|
+
total << dependent.theory_component_id unless @chain_mapping.connected_component_ids.include?(dependent.theory_component_id)
|
|
110
|
+
total
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
105
114
|
# Returns a new chain where they are all using the same respective theory
|
|
106
115
|
# variables.
|
|
107
116
|
#
|
|
@@ -113,7 +122,8 @@ class Chain
|
|
|
113
122
|
end
|
|
114
123
|
unified_theories = @nodes.inject([]) do |total,theory|
|
|
115
124
|
mapping = generate_theory_mapping(theory.theory_instance_id)
|
|
116
|
-
|
|
125
|
+
mapped_theory = theory.map_to(mapping)
|
|
126
|
+
total.push(mapped_theory)
|
|
117
127
|
end
|
|
118
128
|
return UnifiedChain.new(unified_theories)
|
|
119
129
|
end
|
|
@@ -143,7 +153,6 @@ class Chain
|
|
|
143
153
|
|
|
144
154
|
# TODO Really need a method to highlight what is connected to what
|
|
145
155
|
|
|
146
|
-
# DEVELOPMENT
|
|
147
156
|
# Writes out the chain but highlights any of links in the chain weren't connected
|
|
148
157
|
# to a dependent.
|
|
149
158
|
#
|
|
@@ -161,12 +170,7 @@ class Chain
|
|
|
161
170
|
# Attempts to add a new link to form a complete chain between the head and tail. It starts
|
|
162
171
|
# by linking to the tail and then head.
|
|
163
172
|
#
|
|
164
|
-
|
|
165
|
-
# could be connected.
|
|
166
|
-
#
|
|
167
|
-
# TODO link_permutations mighht be a more appropriate name
|
|
168
|
-
#
|
|
169
|
-
def add_link(theory,value_mapping=nil)
|
|
173
|
+
def extension_permutaions(theory,value_mapping=nil)
|
|
170
174
|
|
|
171
175
|
# Give the theory an instance id
|
|
172
176
|
theory = theory.copy
|
|
@@ -247,6 +251,80 @@ class Chain
|
|
|
247
251
|
return res
|
|
248
252
|
end
|
|
249
253
|
|
|
254
|
+
# Returns any number of new chains after adding this link to the position
|
|
255
|
+
# specified.
|
|
256
|
+
#
|
|
257
|
+
# TODO SHould I raise an error if it doesn't connect to anything?
|
|
258
|
+
#
|
|
259
|
+
def add_link_to(theory,position,value_mapping)
|
|
260
|
+
# TODO Down and up are quite similar I should consider refactoring
|
|
261
|
+
|
|
262
|
+
# Do through each of the dependents and then find a result with the same structure
|
|
263
|
+
mappings = [@chain_mapping.copy]
|
|
264
|
+
upward_links = @nodes[0...position]
|
|
265
|
+
|
|
266
|
+
theory.copy.dependents.each do |dependent|
|
|
267
|
+
each_result(position,upward_links) do |index,link,result|
|
|
268
|
+
if result.same_structure?(dependent)
|
|
269
|
+
new_mappings = []
|
|
270
|
+
mappings.each do |x|
|
|
271
|
+
new_mappings << x.apply_mapping_update(theory,dependent.theory_component_id,link,result.theory_component_id)
|
|
272
|
+
end
|
|
273
|
+
mappings = new_mappings
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Go down the rest of the chain looking for exisitng links with unmet dependents
|
|
279
|
+
downward_links = @nodes[position...@nodes.length]
|
|
280
|
+
theory.copy.results.each do |result|
|
|
281
|
+
each_unmet(:dependents,position,downward_links) do |index,link,dependent|
|
|
282
|
+
if dependent.same_structure?(result)
|
|
283
|
+
new_mappings = []
|
|
284
|
+
mappings.each do |x|
|
|
285
|
+
new_mappings << x.apply_mapping_update(link,dependent.theory_component_id,theory,result.theory_component_id)
|
|
286
|
+
end
|
|
287
|
+
mappings = new_mappings
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Strip out any mappings that are identical to original they are
|
|
293
|
+
# links that haven't been connected with anything
|
|
294
|
+
# (don't include the head since it only has one thing to connect to)
|
|
295
|
+
# => TODO Do I like this? It means I'm including some forced connections
|
|
296
|
+
unless @nodes.length < 2
|
|
297
|
+
|
|
298
|
+
# Identify the mappings that are the same
|
|
299
|
+
mappings = mappings.select {|x| !@chain_mapping.same?(x) }
|
|
300
|
+
# => TODO Should inlcude error/warning and exit when there are no new mappings
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Identify any orphan variables in the action and give them uniq global ids
|
|
304
|
+
mappings.each do |mapping|
|
|
305
|
+
theory.orphan_action_variables.each do |x|
|
|
306
|
+
mapping.add_mapping(
|
|
307
|
+
mapping.next_free_global_id,
|
|
308
|
+
theory.theory_instance_id,
|
|
309
|
+
x.theory_variable_id
|
|
310
|
+
)
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Create a new nodes array with the new theory in place
|
|
315
|
+
updated_nodes = @nodes.copy
|
|
316
|
+
updated_nodes.insert(position,theory)
|
|
317
|
+
|
|
318
|
+
# Create a new chain for each of the possible mappings
|
|
319
|
+
extended_chains = []
|
|
320
|
+
mappings.each do |x|
|
|
321
|
+
c = self.copy
|
|
322
|
+
new_chain = c.create!(updated_nodes,x,@uniq_theory_instance_ids.copy,@values.copy)
|
|
323
|
+
extended_chains << new_chain
|
|
324
|
+
end
|
|
325
|
+
return extended_chains
|
|
326
|
+
end
|
|
327
|
+
|
|
250
328
|
# Implements a new the chain where all the theories are implemented. It can
|
|
251
329
|
# only be implemented if the chain is complete e.g. all the dependents and results
|
|
252
330
|
# are matched up.
|
|
@@ -335,6 +413,20 @@ class Chain
|
|
|
335
413
|
def theory_variables
|
|
336
414
|
return TheoryCollection.new(@nodes).theory_variables
|
|
337
415
|
end
|
|
416
|
+
|
|
417
|
+
# Returns an array of all the depdendents in the chain that haven't
|
|
418
|
+
# been met by the front of the chain.
|
|
419
|
+
#
|
|
420
|
+
def unmet_dependents
|
|
421
|
+
results = []
|
|
422
|
+
return results if self.empty?
|
|
423
|
+
duplicate_chain = self.copy
|
|
424
|
+
last_link = duplicate_chain.pop
|
|
425
|
+
last_link.dependents.each do |dependent|
|
|
426
|
+
results.push dependent unless dependent_met?(dependent,duplicate_chain.copy)
|
|
427
|
+
end
|
|
428
|
+
return results+duplicate_chain.unmet_dependents
|
|
429
|
+
end
|
|
338
430
|
|
|
339
431
|
# TODO Maybe just move this method to the UnfiedChain class
|
|
340
432
|
# Returns a set containing the intrinsic statements that created the variables. It should look
|
|
@@ -353,6 +445,7 @@ class Chain
|
|
|
353
445
|
raise StandardError.new('This should only be called on complete chains') unless complete?
|
|
354
446
|
res = []
|
|
355
447
|
unify_chain.theory_variables.each do |var|
|
|
448
|
+
|
|
356
449
|
intrinsic_value = global_id_intrinsic_value(var.theory_variable_id)
|
|
357
450
|
if intrinsic_value.kind_of?(IntrinsicRuntimeMethod)
|
|
358
451
|
res << {
|
|
@@ -380,10 +473,22 @@ class Chain
|
|
|
380
473
|
written_components = unified_components.collect {|x| x.write}
|
|
381
474
|
written_components = written_components.select {|x| x.include?('var'+var.theory_variable_id.to_s)}
|
|
382
475
|
|
|
476
|
+
# => DEV
|
|
477
|
+
temp_component = written_components.first
|
|
478
|
+
|
|
479
|
+
# => MATCH var0.params[var2] in runtime_method.add_statement_at(OpenStatement.new(TheoryStatement.new(If.new, Container.new(var0.params[var2], Equivalent.new, var1[var4][:params][var3]))),var0.statement_id)
|
|
480
|
+
reg = eval('/[\w\d\.\[\]:]*\['+var.write+'\]/')
|
|
481
|
+
|
|
383
482
|
# TODO Should use the Parser to find the statement with the varx in
|
|
483
|
+
#var_match = /\s.*\[var[\d]\]/
|
|
484
|
+
#var_match = /^[\s|\(]+(.*\[var[\d]\])/
|
|
485
|
+
var_match = reg
|
|
384
486
|
usage_statements = written_components.inject([]) do |total,x|
|
|
385
|
-
|
|
386
|
-
|
|
487
|
+
|
|
488
|
+
#unless x.write.match(/\s.*\[var[\d]\]/).nil?
|
|
489
|
+
unless x.write.match(var_match).nil?
|
|
490
|
+
match = x.write.match(var_match)[0]
|
|
491
|
+
total << TheoryStatement.new(StringToTheory.run(match))
|
|
387
492
|
end
|
|
388
493
|
total
|
|
389
494
|
end
|
|
@@ -405,6 +510,27 @@ class Chain
|
|
|
405
510
|
return res
|
|
406
511
|
end
|
|
407
512
|
|
|
513
|
+
# Returns a hash of all the unmet dependents down the chain (excluding the head)
|
|
514
|
+
# and the link/theory that it belongs to.
|
|
515
|
+
#
|
|
516
|
+
def unmet_dependents_and_link
|
|
517
|
+
results = []
|
|
518
|
+
return results if self.empty?
|
|
519
|
+
duplicate_chain = self.copy
|
|
520
|
+
|
|
521
|
+
# Remove the head link from the chain
|
|
522
|
+
duplicate_chain.shift
|
|
523
|
+
|
|
524
|
+
duplicate_chain.length.times do
|
|
525
|
+
last_link = duplicate_chain.pop
|
|
526
|
+
last_link.dependents.each do |d|
|
|
527
|
+
next if dependent_met?(d,duplicate_chain.copy)
|
|
528
|
+
results.push({:dependent=>d.copy,:theory=>last_link.copy})
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
return results
|
|
532
|
+
end
|
|
533
|
+
|
|
408
534
|
protected
|
|
409
535
|
|
|
410
536
|
# Returns the intrinsic mapping for the unified chain
|
|
@@ -449,7 +575,8 @@ protected
|
|
|
449
575
|
|
|
450
576
|
if potentential_values.length > 1
|
|
451
577
|
unless potentential_values.collect {|y| y.write}.uniq.length == 1
|
|
452
|
-
|
|
578
|
+
pp potentential_values
|
|
579
|
+
raise StandardError.new('There is more than one possible value for this('+global_id.to_s+') - it is ok if there the same')
|
|
453
580
|
end
|
|
454
581
|
end
|
|
455
582
|
return potentential_values[0]
|
|
@@ -468,223 +595,11 @@ protected
|
|
|
468
595
|
@nodes = obj
|
|
469
596
|
end
|
|
470
597
|
|
|
471
|
-
# Returns any number of new chains after adding this link to the position
|
|
472
|
-
# specified.
|
|
473
|
-
#
|
|
474
|
-
# TODO SHould I raise an error if it doesn't connect to anything?
|
|
475
|
-
#
|
|
476
|
-
def add_link_to(theory,position,value_mapping)
|
|
477
|
-
# TODO Down and up are quite similar I should consider refactoring
|
|
478
|
-
|
|
479
|
-
# Do through each of the dependents and then find a result with the same structure
|
|
480
|
-
mappings = [@chain_mapping.copy]
|
|
481
|
-
upward_links = @nodes[0...position]
|
|
482
|
-
# theory.copy.dependents.each do |dependent|
|
|
483
|
-
# if StandardLogger.instance.level == 0
|
|
484
|
-
# end
|
|
485
|
-
# each_unmet(:results,position,upward_links) do |index,link,result|
|
|
486
|
-
# if result.same_structure?(dependent)
|
|
487
|
-
# if StandardLogger.instance.level == 0
|
|
488
|
-
# end
|
|
489
|
-
# new_mappings = []
|
|
490
|
-
# mappings.each do |x|
|
|
491
|
-
# new_mappings << x.apply_mapping_update(theory,dependent.theory_component_id,link,result.theory_component_id)
|
|
492
|
-
# end
|
|
493
|
-
# mappings = new_mappings
|
|
494
|
-
# end
|
|
495
|
-
# end
|
|
496
|
-
# end
|
|
497
|
-
|
|
498
|
-
theory.copy.dependents.each do |dependent|
|
|
499
|
-
each_result(position,upward_links) do |index,link,result|
|
|
500
|
-
if result.same_structure?(dependent)
|
|
501
|
-
new_mappings = []
|
|
502
|
-
mappings.each do |x|
|
|
503
|
-
new_mappings << x.apply_mapping_update(theory,dependent.theory_component_id,link,result.theory_component_id)
|
|
504
|
-
end
|
|
505
|
-
mappings = new_mappings
|
|
506
|
-
end
|
|
507
|
-
end
|
|
508
|
-
end
|
|
509
|
-
|
|
510
|
-
# Go down the rest of the chain looking for exisitng links with unmet dependents
|
|
511
|
-
downward_links = @nodes[position...@nodes.length]
|
|
512
|
-
theory.copy.results.each do |result|
|
|
513
|
-
each_unmet(:dependents,position,downward_links) do |index,link,dependent|
|
|
514
|
-
if dependent.same_structure?(result)
|
|
515
|
-
new_mappings = []
|
|
516
|
-
mappings.each do |x|
|
|
517
|
-
new_mappings << x.apply_mapping_update(link,dependent.theory_component_id,theory,result.theory_component_id)
|
|
518
|
-
end
|
|
519
|
-
mappings = new_mappings
|
|
520
|
-
end
|
|
521
|
-
end
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
# Strip out any mappings that are identical to original they are
|
|
525
|
-
# links that haven't been connected with anything
|
|
526
|
-
# (don't include the head since it only has one thing to connect to)
|
|
527
|
-
unless @nodes.length < 2
|
|
528
|
-
mappings = mappings.select {|x| !@chain_mapping.same?(x) }
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
# Identify any orphan variables in the action and give them uniq global ids
|
|
532
|
-
mappings.each do |mapping|
|
|
533
|
-
theory.orphan_action_variables.each do |x|
|
|
534
|
-
mapping.add_mapping(mapping.next_free_global_id,theory.theory_instance_id,x.theory_variable_id)
|
|
535
|
-
end
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
# Create a new nodes array with the new theory in place
|
|
539
|
-
updated_nodes = @nodes.copy
|
|
540
|
-
updated_nodes.insert(position,theory)
|
|
541
|
-
|
|
542
|
-
# Create a new chain for each of the possible mappings
|
|
543
|
-
extended_chains = []
|
|
544
|
-
mappings.each do |x|
|
|
545
|
-
c = self.copy
|
|
546
|
-
new_chain = c.create!(updated_nodes,x,@uniq_theory_instance_ids.copy,@values.copy)
|
|
547
|
-
extended_chains << new_chain
|
|
548
|
-
end
|
|
549
|
-
return extended_chains
|
|
550
|
-
end
|
|
551
|
-
|
|
552
598
|
# TODO This could probably be replaced by the normal add_link_to method
|
|
553
599
|
def add_tail(theory,value_mapping={})
|
|
554
600
|
@nodes.push(theory.copy)
|
|
555
601
|
end
|
|
556
602
|
|
|
557
|
-
# # TODO I don't think this is used
|
|
558
|
-
# def update_unified_theory_variables(unified_theory_variables_mapping,chain_front,dependent,theory)
|
|
559
|
-
#
|
|
560
|
-
# # TODO Once the mapping is in place for all the theory vairables in the
|
|
561
|
-
# # in the dependent then the dependent should be mapped, written out
|
|
562
|
-
# # and compared to the result instead of the same_structure? method.
|
|
563
|
-
#
|
|
564
|
-
# # Find all the results that have the same structure as the dependent
|
|
565
|
-
# # TODO It should probably preference the earliest theories first.
|
|
566
|
-
# matching_theories = chain_front.select do |t|
|
|
567
|
-
# t.results.any? {|x| x.same_structure?(dependent)}
|
|
568
|
-
# end
|
|
569
|
-
#
|
|
570
|
-
# # Check that a matching theory was found in the chain
|
|
571
|
-
# if matching_theories.empty?
|
|
572
|
-
# # Couldn't find a theory that meets this theories depdenents - add the theory will
|
|
573
|
-
# # need to add a another link to the chain to connect this theory with the head.
|
|
574
|
-
# return unified_theory_variables_mapping
|
|
575
|
-
# end
|
|
576
|
-
#
|
|
577
|
-
# # Go through the matching thoeries and find the result that matched the dependent
|
|
578
|
-
# matching_results = matching_theories.inject([]) do |total,t|
|
|
579
|
-
# # TODO Presumes there is only one result
|
|
580
|
-
# res = t.results.select {|x| x.same_structure?(dependent)}.first
|
|
581
|
-
# total << {:theory_id=>t.theory_id,:result=>res,:theory=>t}
|
|
582
|
-
# end
|
|
583
|
-
#
|
|
584
|
-
# # Check how many results meet the dependents
|
|
585
|
-
# raise StandardError.new('Currently only handling one result to dependent match') unless matching_results.length == 1
|
|
586
|
-
# linking_result = matching_results.first
|
|
587
|
-
#
|
|
588
|
-
# # Link two theories so that the share the same global mapping
|
|
589
|
-
# @chain_mapping.connect(
|
|
590
|
-
# theory,
|
|
591
|
-
# dependent.theory_component_id,
|
|
592
|
-
# linking_result[:theory],
|
|
593
|
-
# linking_result[:result].theory_component_id
|
|
594
|
-
# )
|
|
595
|
-
# return unified_theory_variables_mapping
|
|
596
|
-
#
|
|
597
|
-
# end
|
|
598
|
-
|
|
599
|
-
# def map_to_tail(global_mapping,theory)
|
|
600
|
-
#
|
|
601
|
-
# # * Check whether there are any dependents from the back of the chain not met
|
|
602
|
-
#
|
|
603
|
-
# # Attempt to connect the theories results to the unmet dependents.
|
|
604
|
-
# # NOTE: The theories position is always one away from the head so
|
|
605
|
-
# # [:head]
|
|
606
|
-
# # [:x] <-----------this is where the new link will go.
|
|
607
|
-
# # [:linkB]
|
|
608
|
-
# # [:linkA]
|
|
609
|
-
# # [:tail]
|
|
610
|
-
#
|
|
611
|
-
# possible_mappings = [global_mapping.copy]
|
|
612
|
-
# valid_mappings = [global_mapping.copy]
|
|
613
|
-
#
|
|
614
|
-
# # 1. Find all the unmet dependents down the chain e.g. :tail, :linkA and :linkB
|
|
615
|
-
# # TODO Need to generate some nice diagrams for what's happing - very har to visualise
|
|
616
|
-
#
|
|
617
|
-
# # TEMP: This is the dependent for the tail of the chain - the head doesn't have any dependents
|
|
618
|
-
# unless unmet_dependents_and_link.empty?
|
|
619
|
-
# unmet_dependents_and_link.each do |dep_and_link|
|
|
620
|
-
#
|
|
621
|
-
# dependent = dep_and_link[:dependent]
|
|
622
|
-
# # TODO This is very similar to the code above - re-factor
|
|
623
|
-
# # Do any of the results have the same structure as the dependent?
|
|
624
|
-
# if theory.results.any? {|x| x.same_structure?(dep_and_link[:dependent])}
|
|
625
|
-
#
|
|
626
|
-
# valid_mappings = []
|
|
627
|
-
#
|
|
628
|
-
# results = theory.results.select {|x| x.same_structure?(dep_and_link[:dependent])}
|
|
629
|
-
# possible_mappings.each do |mapping|
|
|
630
|
-
# results.each do |res|
|
|
631
|
-
#
|
|
632
|
-
# begin
|
|
633
|
-
# new_mapping = potential_tail_mapping(mapping.copy,theory.copy,res.copy,dep_and_link[:dependent].copy,dep_and_link[:theory].copy)
|
|
634
|
-
# # TODO Create special MappingError
|
|
635
|
-
# rescue StandardError => e
|
|
636
|
-
# StandardLogger.instance.error e
|
|
637
|
-
# next
|
|
638
|
-
# end
|
|
639
|
-
# valid_mappings << new_mapping
|
|
640
|
-
# end
|
|
641
|
-
# end
|
|
642
|
-
#
|
|
643
|
-
# # Make the valid mappings the possible mappings for the next stage
|
|
644
|
-
# possible_mappings = valid_mappings
|
|
645
|
-
#
|
|
646
|
-
# end
|
|
647
|
-
#
|
|
648
|
-
# end
|
|
649
|
-
#
|
|
650
|
-
# end
|
|
651
|
-
#
|
|
652
|
-
# if valid_mappings.empty?
|
|
653
|
-
# raise StandardError.new('Unable to perform valid mapping')
|
|
654
|
-
# else
|
|
655
|
-
# # TODO Should be returning all the potential mapping
|
|
656
|
-
# return valid_mappings[0]
|
|
657
|
-
# end
|
|
658
|
-
#
|
|
659
|
-
# #return global_mapping
|
|
660
|
-
# end
|
|
661
|
-
|
|
662
|
-
# # Returns the updated mapping if a possible match is found otherwise it raises
|
|
663
|
-
# # an error.
|
|
664
|
-
# #
|
|
665
|
-
# def potential_tail_mapping(global_mapping,new_theory,new_result,existing_dependent,existing_theory)
|
|
666
|
-
#
|
|
667
|
-
# # Check that the result and dependent have the same number of theory variables
|
|
668
|
-
# if new_result.theory_variables.length != existing_dependent.theory_variables.length
|
|
669
|
-
# raise StandardError.new('The result and dependent that are being linked do not have the same number of theory_variables')
|
|
670
|
-
# end
|
|
671
|
-
#
|
|
672
|
-
# new_result.theory_variables.zip(existing_dependent.theory_variables) do |result_theory_variable,dependent_theory_variable|
|
|
673
|
-
# # Add the results of the theory to the global variables.
|
|
674
|
-
#
|
|
675
|
-
# # So these two variables need the same global variable
|
|
676
|
-
# # TODO This presumes that the same theory isn't being used in the chain
|
|
677
|
-
# global_mapping.connect(
|
|
678
|
-
# new_theory,
|
|
679
|
-
# new_result.theory_component_id,
|
|
680
|
-
# existing_theory,
|
|
681
|
-
# existing_dependent.theory_component_id
|
|
682
|
-
# )
|
|
683
|
-
# end
|
|
684
|
-
# return global_mapping
|
|
685
|
-
#
|
|
686
|
-
# end
|
|
687
|
-
|
|
688
603
|
# Returns the global id of the variable given the theory id and the variable
|
|
689
604
|
# id.
|
|
690
605
|
#
|
|
@@ -709,10 +624,6 @@ protected
|
|
|
709
624
|
linking_result = linking_results.first
|
|
710
625
|
end
|
|
711
626
|
|
|
712
|
-
# def front_of_chain
|
|
713
|
-
# return [@nodes.first.copy]
|
|
714
|
-
# end
|
|
715
|
-
|
|
716
627
|
# Returns a new theory mapping that replace the theories local ids with global
|
|
717
628
|
# ids.
|
|
718
629
|
#
|
|
@@ -752,23 +663,9 @@ protected
|
|
|
752
663
|
end
|
|
753
664
|
return false
|
|
754
665
|
end
|
|
755
|
-
|
|
756
|
-
# Returns an array of all the depdendents in the chain that haven't
|
|
757
|
-
# been met by the front of the chain.
|
|
758
|
-
#
|
|
759
|
-
def unmet_dependents
|
|
760
|
-
results = []
|
|
761
|
-
return results if self.empty?
|
|
762
|
-
duplicate_chain = self.copy
|
|
763
|
-
last_link = duplicate_chain.pop
|
|
764
|
-
last_link.dependents.each do |dependent|
|
|
765
|
-
results.push dependent unless dependent_met?(dependent,duplicate_chain.copy)
|
|
766
|
-
end
|
|
767
|
-
return results+duplicate_chain.unmet_dependents
|
|
768
|
-
end
|
|
769
666
|
|
|
770
667
|
# Goes up through each theory in the chain from the position
|
|
771
|
-
# specifies and yeilds any unment
|
|
668
|
+
# specifies and yeilds any unment dependents or results and the
|
|
772
669
|
# theory it belongs to.
|
|
773
670
|
#
|
|
774
671
|
# @param approach Either :depndents or :results
|
|
@@ -794,27 +691,6 @@ protected
|
|
|
794
691
|
end
|
|
795
692
|
end
|
|
796
693
|
|
|
797
|
-
# Returns a hash of all the unmet dependents down the chain (excluding the head)
|
|
798
|
-
# and the link/theory that it belongs to.
|
|
799
|
-
#
|
|
800
|
-
def unmet_dependents_and_link
|
|
801
|
-
results = []
|
|
802
|
-
return results if self.empty?
|
|
803
|
-
duplicate_chain = self.copy
|
|
804
|
-
|
|
805
|
-
# Remove the head link from the chain
|
|
806
|
-
duplicate_chain.shift
|
|
807
|
-
|
|
808
|
-
duplicate_chain.length.times do
|
|
809
|
-
last_link = duplicate_chain.pop
|
|
810
|
-
last_link.dependents.each do |d|
|
|
811
|
-
next if dependent_met?(d,duplicate_chain.copy)
|
|
812
|
-
results.push({:dependent=>d.copy,:theory=>last_link.copy})
|
|
813
|
-
end
|
|
814
|
-
end
|
|
815
|
-
return results
|
|
816
|
-
end
|
|
817
|
-
|
|
818
694
|
# Removes any results from the head that aren't needed to meet
|
|
819
695
|
# the dependents of the supplied theories.
|
|
820
696
|
#
|