activefacts 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/cql +137 -91
- data/css/style.css +3 -3
- data/examples/CQL/Insurance.cql +1 -1
- data/examples/CQL/SeparateSubtype.cql +2 -2
- data/lib/activefacts/cql/Language/English.treetop +9 -0
- data/lib/activefacts/cql/ObjectTypes.treetop +1 -1
- data/lib/activefacts/cql/Terms.treetop +3 -1
- data/lib/activefacts/cql/ValueTypes.treetop +10 -4
- data/lib/activefacts/cql/compiler.rb +1 -0
- data/lib/activefacts/cql/compiler/clause.rb +53 -23
- data/lib/activefacts/cql/compiler/entity_type.rb +0 -4
- data/lib/activefacts/cql/compiler/expression.rb +9 -13
- data/lib/activefacts/cql/compiler/fact.rb +49 -48
- data/lib/activefacts/cql/compiler/fact_type.rb +23 -20
- data/lib/activefacts/cql/compiler/query.rb +49 -121
- data/lib/activefacts/cql/compiler/shared.rb +5 -1
- data/lib/activefacts/cql/compiler/value_type.rb +4 -2
- data/lib/activefacts/generate/rails/schema.rb +138 -108
- data/lib/activefacts/generate/transform/surrogate.rb +1 -2
- data/lib/activefacts/mapping/rails.rb +52 -45
- data/lib/activefacts/persistence/columns.rb +5 -5
- data/lib/activefacts/persistence/tables.rb +6 -4
- data/lib/activefacts/support.rb +0 -2
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +64 -42
- data/lib/activefacts/vocabulary/metamodel.rb +14 -12
- data/lib/activefacts/vocabulary/verbaliser.rb +98 -92
- data/spec/cql/expressions_spec.rb +8 -3
- data/spec/cql/parser/entity_types_spec.rb +1 -1
- data/spec/cql/parser/expressions_spec.rb +66 -52
- data/spec/cql/parser/fact_types_spec.rb +1 -1
- data/spec/cql/parser/literals_spec.rb +10 -10
- data/spec/cql/parser/pragmas_spec.rb +3 -3
- data/spec/cql/parser/value_types_spec.rb +1 -1
- metadata +2 -2
@@ -37,8 +37,8 @@ module ActiveFacts
|
|
37
37
|
to_s
|
38
38
|
end
|
39
39
|
|
40
|
-
def inspect
|
41
|
-
to_s
|
40
|
+
def inspect
|
41
|
+
to_s
|
42
42
|
end
|
43
43
|
|
44
44
|
def to_s phrases = nil
|
@@ -52,21 +52,34 @@ module ActiveFacts
|
|
52
52
|
# else 'definitely '
|
53
53
|
end
|
54
54
|
}#{
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
55
|
+
(
|
56
|
+
phrases.map do |phrase|
|
57
|
+
case phrase
|
58
|
+
when String
|
59
|
+
'"' + phrase.to_s + '"'
|
60
|
+
when Reference
|
61
|
+
phrase.to_s +
|
62
|
+
if phrase.nested_clauses
|
63
|
+
' (in which ' +
|
64
|
+
phrase.nested_clauses.map do |c|
|
65
|
+
((j = c.conjunction) ? j+' ' : '') +
|
66
|
+
c.to_s
|
67
|
+
end*' ' +
|
68
|
+
')'
|
69
|
+
else
|
70
|
+
''
|
71
|
+
end
|
72
|
+
when Operation
|
73
|
+
phrase.inspect
|
74
|
+
when Literal
|
75
|
+
phrase.inspect
|
76
|
+
#when FunctionCallChain # REVISIT: Add something here when I re-add functions
|
77
|
+
# phrase.inspect
|
78
|
+
else
|
79
|
+
raise "Unexpected phrase type in clause: #{phrase.class}"
|
80
|
+
end
|
81
|
+
end * ' '
|
82
|
+
).gsub(/" "/, ' ')
|
70
83
|
}#{
|
71
84
|
@context_note && ' ' + @context_note.inspect
|
72
85
|
}"
|
@@ -131,6 +144,22 @@ module ActiveFacts
|
|
131
144
|
def match_existing_fact_type context, options = {}
|
132
145
|
raise "Cannot match a clause that contains no object types" if refs.size == 0
|
133
146
|
raise "Internal error, clause already matched, should not match again" if @fact_type
|
147
|
+
|
148
|
+
if is_naked_object_type
|
149
|
+
ref = refs[0] # "There can be only one"
|
150
|
+
return true unless ref.nested_clauses
|
151
|
+
ref.nested_clauses.each do |nested|
|
152
|
+
ft = nested.match_existing_fact_type(context)
|
153
|
+
raise "Unrecognised fact type #{nested.display} nested under #{inspect}" unless ft
|
154
|
+
if (ft.entity_type == ref.player)
|
155
|
+
ref.objectification_of = ft
|
156
|
+
nested.objectified_as = ref
|
157
|
+
end
|
158
|
+
end
|
159
|
+
raise "#{ref.inspect} contains objectification steps that do not objectify it" unless ref.objectification_of
|
160
|
+
return true
|
161
|
+
end
|
162
|
+
|
134
163
|
# If we fail to match, try a left contraction (or save this for a subsequent left contraction):
|
135
164
|
left_contract_this_onto = context.left_contractable_clause
|
136
165
|
new_conjunction = (conjunction == nil || conjunction == ',')
|
@@ -195,7 +224,7 @@ module ActiveFacts
|
|
195
224
|
|
196
225
|
player_names = players.map{|p| p.name}
|
197
226
|
|
198
|
-
trace :matching, "Looking for existing #{players.size}-ary fact types matching '#{inspect
|
227
|
+
trace :matching, "Looking for existing #{players.size}-ary fact types matching '#{inspect}'" do
|
199
228
|
trace :matching, "Players are '#{player_names.inspect}'"
|
200
229
|
|
201
230
|
# Match existing fact types in nested clauses first:
|
@@ -204,12 +233,12 @@ module ActiveFacts
|
|
204
233
|
vrs.each do |ref|
|
205
234
|
next if ref.is_a?(Operation)
|
206
235
|
next unless steps = ref.nested_clauses and !steps.empty?
|
207
|
-
ref.nested_clauses.each do |
|
208
|
-
ft =
|
209
|
-
raise "Unrecognised fact type #{
|
236
|
+
ref.nested_clauses.each do |nested|
|
237
|
+
ft = nested.match_existing_fact_type(context)
|
238
|
+
raise "Unrecognised fact type #{nested.display}" unless ft
|
210
239
|
if (ft && ft.entity_type == ref.player)
|
211
240
|
ref.objectification_of = ft
|
212
|
-
|
241
|
+
nested.objectified_as = ref
|
213
242
|
end
|
214
243
|
end
|
215
244
|
raise "#{ref.inspect} contains objectification steps that do not objectify it" unless ref.objectification_of
|
@@ -883,7 +912,7 @@ module ActiveFacts
|
|
883
912
|
end
|
884
913
|
|
885
914
|
def includes_literals
|
886
|
-
@nested_clauses && @nested_clauses.detect{|
|
915
|
+
@nested_clauses && @nested_clauses.detect{|nested| nested.includes_literals}
|
887
916
|
end
|
888
917
|
|
889
918
|
# We create value types for the results of arithmetic expressions, and they get assigned here:
|
@@ -1064,6 +1093,7 @@ module ActiveFacts
|
|
1064
1093
|
end
|
1065
1094
|
end
|
1066
1095
|
|
1096
|
+
# REVISIT: This needs to handle annotations for some/that/which, etc.
|
1067
1097
|
class Quantifier
|
1068
1098
|
attr_accessor :enforcement
|
1069
1099
|
attr_accessor :context_note
|
@@ -170,10 +170,6 @@ module ActiveFacts
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def create_identifying_fact_type context, clauses
|
173
|
-
# Remove uninteresting assertions:
|
174
|
-
clauses.reject!{|clause| clause.is_existential_type }
|
175
|
-
return nil unless clauses.size > 0 # Nothing interesting was said.
|
176
|
-
|
177
173
|
# See if any fact type already exists (this ET cannot be a player, but might objectify it)
|
178
174
|
existing_clauses = clauses.select{ |clause| clause.match_existing_fact_type context }
|
179
175
|
if negation = existing_clauses.detect{|c| c.certainty == false }
|
@@ -137,10 +137,6 @@ module ActiveFacts
|
|
137
137
|
@fact_type
|
138
138
|
end
|
139
139
|
|
140
|
-
def is_existential_type
|
141
|
-
false
|
142
|
-
end
|
143
|
-
|
144
140
|
def is_equality_comparison
|
145
141
|
false
|
146
142
|
end
|
@@ -179,7 +175,7 @@ module ActiveFacts
|
|
179
175
|
end
|
180
176
|
|
181
177
|
def result_type_name(context)
|
182
|
-
"
|
178
|
+
"COMPARE#{operator}<#{[@e1,@e2].map{|e| e.player.name}*' WITH '})>"
|
183
179
|
end
|
184
180
|
|
185
181
|
def is_equality_comparison
|
@@ -210,7 +206,7 @@ module ActiveFacts
|
|
210
206
|
def inspect; to_s; end
|
211
207
|
|
212
208
|
def to_s
|
213
|
-
"
|
209
|
+
"COMPARE#{
|
214
210
|
operator
|
215
211
|
}(#{
|
216
212
|
case @certainty
|
@@ -220,7 +216,7 @@ module ActiveFacts
|
|
220
216
|
end
|
221
217
|
}#{
|
222
218
|
e1.to_s
|
223
|
-
} #{
|
219
|
+
} WITH #{
|
224
220
|
e2.to_s
|
225
221
|
}#{
|
226
222
|
@qualifiers.empty? ? '' : ', ['+@qualifiers*', '+']'
|
@@ -255,7 +251,7 @@ module ActiveFacts
|
|
255
251
|
end
|
256
252
|
|
257
253
|
def result_type_name(context)
|
258
|
-
"
|
254
|
+
"SUM_OF<#{ @terms.map{|f| f.player.name}*', ' }>"
|
259
255
|
end
|
260
256
|
|
261
257
|
=begin
|
@@ -269,7 +265,7 @@ module ActiveFacts
|
|
269
265
|
def inspect; to_s; end
|
270
266
|
|
271
267
|
def to_s
|
272
|
-
'
|
268
|
+
'SUM(' + @terms.map{|term| "#{term.to_s}" } * ' PLUS ' + ')'
|
273
269
|
end
|
274
270
|
end
|
275
271
|
|
@@ -299,7 +295,7 @@ module ActiveFacts
|
|
299
295
|
end
|
300
296
|
|
301
297
|
def result_type_name(context)
|
302
|
-
"
|
298
|
+
"PRODUCT_OF<#{ @factors.map{|f| f.player.name}*' ' }>"
|
303
299
|
end
|
304
300
|
|
305
301
|
=begin
|
@@ -313,7 +309,7 @@ module ActiveFacts
|
|
313
309
|
def inspect; to_s; end
|
314
310
|
|
315
311
|
def to_s
|
316
|
-
'
|
312
|
+
'PRODUCT(' + @factors.map{|factor| "#{factor.to_s}" } * ' TIMES ' + ')'
|
317
313
|
end
|
318
314
|
end
|
319
315
|
|
@@ -350,7 +346,7 @@ module ActiveFacts
|
|
350
346
|
def inspect; to_s; end
|
351
347
|
|
352
348
|
def to_s
|
353
|
-
"
|
349
|
+
"RECIPROCAL(#{factor.to_s})"
|
354
350
|
end
|
355
351
|
end
|
356
352
|
|
@@ -381,7 +377,7 @@ module ActiveFacts
|
|
381
377
|
def inspect; to_s; end
|
382
378
|
|
383
379
|
def to_s
|
384
|
-
"
|
380
|
+
"NEGATIVE(#{term.to_s})"
|
385
381
|
end
|
386
382
|
end
|
387
383
|
|
@@ -24,7 +24,7 @@ module ActiveFacts
|
|
24
24
|
|
25
25
|
# Figure out the simple existential facts and find fact types:
|
26
26
|
@bound_facts = []
|
27
|
-
@unbound_clauses = all_clauses.
|
27
|
+
@unbound_clauses = all_clauses(@clauses).
|
28
28
|
map do |clause|
|
29
29
|
bind_literal_or_fact_type clause
|
30
30
|
end.
|
@@ -53,7 +53,7 @@ module ActiveFacts
|
|
53
53
|
player = ref.binding.player
|
54
54
|
# raise "A literal may not be an objectification" if ref.role_ref.nested_clauses
|
55
55
|
# raise "Not processing facts involving nested clauses yet" if ref.role_ref
|
56
|
-
trace :
|
56
|
+
trace :instance_detail, "Making #{player.class.basename} #{player.name} using #{l.inspect}" do
|
57
57
|
ref.binding.instance = instance_identified_by_literal(player, l)
|
58
58
|
end
|
59
59
|
ref
|
@@ -92,8 +92,8 @@ module ActiveFacts
|
|
92
92
|
true
|
93
93
|
end
|
94
94
|
|
95
|
-
|
96
|
-
|
95
|
+
trace :instance_detail, "Considering '#{clause.display}' with "+
|
96
|
+
(bare_roles.empty? ? "no bare roles" : "bare roles: #{bare_roles.map{|ref| ref.player.name}*", "}") do
|
97
97
|
|
98
98
|
# If all the roles are in place, we can bind the rest of this clause:
|
99
99
|
return true if bare_roles.size == 0 && bind_complete_fact(clause)
|
@@ -109,7 +109,7 @@ module ActiveFacts
|
|
109
109
|
end
|
110
110
|
|
111
111
|
return true if progress
|
112
|
-
trace :
|
112
|
+
trace :instance_detail, "Delaying until all role players are asserted: #{clause.fact_type.default_reading.inspect}"
|
113
113
|
nil
|
114
114
|
end
|
115
115
|
end
|
@@ -120,37 +120,36 @@ module ActiveFacts
|
|
120
120
|
@pass += 1
|
121
121
|
|
122
122
|
progress = false
|
123
|
-
trace :
|
123
|
+
trace :instance_detail, "Pass #{@pass} with #{@unbound_clauses.size} clauses to consider" do
|
124
124
|
@unbound_clauses =
|
125
125
|
@unbound_clauses.select do |clause|
|
126
126
|
action = bind_clause(clause)
|
127
127
|
progress = true if action
|
128
128
|
!action
|
129
129
|
end
|
130
|
-
trace :
|
130
|
+
trace :instance_detail, "end of pass, unbound clauses are #{@unbound_clauses.map(&:display)*', '}"
|
131
131
|
end # debug
|
132
132
|
progress
|
133
133
|
end
|
134
134
|
|
135
|
-
# Occasionally we need to search through all the clauses
|
136
|
-
def all_clauses
|
137
|
-
|
138
|
-
[clause] + clause.refs.map{|vr| vr.nested_clauses}
|
135
|
+
# Occasionally we need to search through all the clauses. This builds a flat list
|
136
|
+
def all_clauses clauses
|
137
|
+
clauses.map do |clause|
|
138
|
+
[clause] + clause.refs.map{|vr| vr.nested_clauses ? all_clauses(vr.nested_clauses) : []}
|
139
139
|
end.flatten.compact
|
140
140
|
end
|
141
141
|
|
142
142
|
def bind_complete_fact clause
|
143
143
|
return true unless clause.fact_type # An bare objectification
|
144
|
-
trace :instance, "All bindings in '#{clause.display}' contain instances; assert the fact type"
|
145
144
|
instances = clause.refs.map{|vr| vr.binding.instance }
|
146
|
-
trace :
|
145
|
+
trace :instance_detail, "All role players exist for #{clause.display.inspect} exist: #{instances.map{|i| "#{i.verbalise}"}*", "}"
|
147
146
|
|
148
147
|
if e = clause.fact_type.entity_type and
|
149
148
|
clause.refs[0].binding.instance.object_type == e
|
150
149
|
fact = clause.refs[0].binding.instance.fact
|
151
150
|
else
|
152
151
|
# Check that this fact doesn't already exist
|
153
|
-
trace :
|
152
|
+
trace :instance_detail, "Searching for existing fact instance"
|
154
153
|
|
155
154
|
fact = clause.fact_type.all_fact.detect do |f|
|
156
155
|
|
@@ -165,26 +164,27 @@ module ActiveFacts
|
|
165
164
|
end
|
166
165
|
if fact
|
167
166
|
clause.fact = fact
|
168
|
-
trace :instance, "
|
167
|
+
trace :instance, "Already known: #{fact.verbalise.inspect}"
|
169
168
|
else
|
170
|
-
trace :
|
169
|
+
trace :instance_detail, "Asserting fact of type #{clause.fact_type.default_reading.inspect}"
|
171
170
|
fact =
|
172
171
|
clause.fact =
|
173
172
|
@constellation.Fact(:new, :fact_type => clause.fact_type, :population => @population)
|
174
173
|
@bound_facts << fact
|
175
174
|
clause.reading.role_sequence.all_role_ref_in_order.zip(instances).each do |rr, instance|
|
176
|
-
trace :
|
175
|
+
trace :instance_detail, "Assigning fact role #{instance.object_type.name} to #{instance.value ? instance.value.inspect : instance.verbalise}"
|
177
176
|
# REVISIT: Any residual adjectives after the fact type matching are lost here.
|
178
177
|
@constellation.RoleValue(:fact => fact, :instance => instance, :role => rr.role, :population => @population)
|
179
178
|
end
|
179
|
+
trace :instance, "Assert #{fact.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}" unless clause.fact_type.entity_type
|
180
180
|
end
|
181
181
|
|
182
182
|
if !fact.instance && clause.fact_type.entity_type
|
183
183
|
# Objectified fact type; create the instance
|
184
184
|
# Create the instance that objectifies this fact. We don't have the binding to assign it to though; that'll happen in our caller
|
185
|
-
trace :instance, "Objectifying fact as #{clause.fact_type.entity_type.name}"
|
186
185
|
instance =
|
187
186
|
@constellation.Instance(:new, :object_type => clause.fact_type.entity_type, :fact => fact, :population => @population)
|
187
|
+
trace :instance, "Assert #{instance.verbalise.inspect}"
|
188
188
|
@bound_facts << instance
|
189
189
|
end
|
190
190
|
|
@@ -207,23 +207,24 @@ module ActiveFacts
|
|
207
207
|
return false unless identifying_binding # This happens when we have a bare objectification
|
208
208
|
identifying_instance = identifying_binding.instance
|
209
209
|
preferred_identifier = entity_type.preferred_identifier
|
210
|
+
role_count = preferred_identifier.role_sequence.all_role_ref.size
|
210
211
|
|
211
|
-
trace :instance, "
|
212
|
+
trace :instance, "A #{binding.player.name} is #{role_count > 1 ? 'partly ':''}identified in #{clause.inspect}"
|
212
213
|
|
213
214
|
identifying_role_ref = preferred_identifier.role_sequence.all_role_ref.detect { |rr|
|
214
215
|
rr.role.fact_type == clause.fact_type && rr.role.object_type == identifying_binding.player
|
215
216
|
}
|
216
217
|
unless identifying_role_ref
|
217
|
-
# This
|
218
|
+
# This should never happen; we already bound all refs
|
218
219
|
trace :instance, "Failed to find a #{identifying_instance.object_type.name}"
|
219
220
|
return false # We can't do this yet
|
220
221
|
end
|
221
222
|
role_value = identifying_instance.all_role_value.detect do |rv|
|
222
223
|
rv.fact.fact_type == identifying_role_ref.role.fact_type
|
223
224
|
end
|
224
|
-
if role_value
|
225
|
+
if role_value && role_count == 1
|
225
226
|
instance = (role_value.fact.all_role_value.to_a-[role_value])[0].instance
|
226
|
-
trace :instance, "
|
227
|
+
trace :instance, "Existential fact already known: #{instance.verbalise.inspect}"
|
227
228
|
binding.instance = instance
|
228
229
|
return true # Done with this clause
|
229
230
|
end
|
@@ -234,7 +235,7 @@ module ActiveFacts
|
|
234
235
|
identifiers =
|
235
236
|
pi_role_refs.map do |rr|
|
236
237
|
# Find a clause that provides the identifying_ref for this player:
|
237
|
-
identifying_clause = all_clauses.detect do |clause|
|
238
|
+
identifying_clause = all_clauses(@clauses).detect do |clause|
|
238
239
|
rr.role.fact_type == clause.fact_type &&
|
239
240
|
clause.refs.detect{|vr| vr.binding == binding}
|
240
241
|
end
|
@@ -250,22 +251,21 @@ module ActiveFacts
|
|
250
251
|
return false
|
251
252
|
end
|
252
253
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
end
|
254
|
+
instance = @constellation.Instance(:new, :object_type => entity_type, :population => @population)
|
255
|
+
binding.instance = instance
|
256
|
+
@bound_facts << instance
|
257
|
+
identifiers.each do |rr, identifying_clause, identifying_binding, identifying_instance|
|
258
|
+
# This clause provides the identifying literal for the entity_type
|
259
|
+
id_fact =
|
260
|
+
identifying_clause.fact =
|
261
|
+
@constellation.Fact(:new, :fact_type => rr.role.fact_type, :population => @population)
|
262
|
+
@bound_facts << id_fact
|
263
|
+
role = (rr.role.fact_type.all_role.to_a-[rr.role])[0]
|
264
|
+
@constellation.RoleValue(:instance => instance, :fact => id_fact, :population => @population, :role => role)
|
265
|
+
@constellation.RoleValue(:instance => identifying_instance, :fact => id_fact, :role => rr.role, :population => @population)
|
266
|
+
trace :instance, "Assert #{id_fact.verbalise.inspect} (existential) #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
267
|
+
end
|
268
|
+
trace :instance, "Assert #{instance.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
269
269
|
|
270
270
|
true # Done with this clause
|
271
271
|
end
|
@@ -274,29 +274,29 @@ module ActiveFacts
|
|
274
274
|
if object_type.is_a?(ActiveFacts::Metamodel::EntityType)
|
275
275
|
entity_identified_by_literal object_type, literal
|
276
276
|
else
|
277
|
-
trace :
|
277
|
+
trace :instance_detail, "Assert Value #{object_type.name} #{literal.inspect}" do
|
278
278
|
is_literal_string = literal.literal.is_a?(String)
|
279
279
|
# REVISIT: Check for subtypes and supertypes also, and promote type if necessary
|
280
280
|
instance = object_type.all_instance.detect do |i|
|
281
281
|
#instance = @constellation.Instance.detect do |key, i|
|
282
282
|
# REVISIT: And same unit
|
283
|
-
trace :
|
283
|
+
trace :instance_detail2, "Comparing #{i.value.literal.inspect} to #{literal.literal.to_s.inspect}"
|
284
284
|
i.population == @population &&
|
285
285
|
i.value &&
|
286
|
-
i.value.literal.inspect == literal.literal.inspect &&
|
286
|
+
i.value.literal.inspect == literal.literal.to_s.inspect &&
|
287
287
|
i.value.is_literal_string == is_literal_string
|
288
288
|
end
|
289
289
|
#instance = object_type.all_instance.detect { |instance|
|
290
290
|
# instance.population == @population && instance.value == literal
|
291
291
|
#}
|
292
292
|
if instance
|
293
|
-
trace :instance, "
|
293
|
+
trace :instance, "Instance already known: #{instance.verbalise.inspect}"
|
294
294
|
else
|
295
|
-
trace :instance, "Creating Value #{object_type.name} #{literal.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
296
295
|
instance = @constellation.Instance(:new)
|
297
296
|
instance.object_type = object_type
|
298
297
|
instance.population = @population
|
299
298
|
instance.value = [literal.to_s, is_literal_string, nil]
|
299
|
+
trace :instance, "Assert #{instance.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
300
300
|
@bound_facts << instance
|
301
301
|
end
|
302
302
|
instance
|
@@ -307,7 +307,7 @@ module ActiveFacts
|
|
307
307
|
def entity_identified_by_literal object_type, literal
|
308
308
|
# A literal that identifies an entity type means the entity type has only one identifying role
|
309
309
|
# That role is played either by a value type, or by another similarly single-identified entity type
|
310
|
-
trace :
|
310
|
+
trace :instance_detail, "Assert Entity #{object_type.name} identified by '#{literal}'" do
|
311
311
|
identifying_role_refs = object_type.preferred_identifier.role_sequence.all_role_ref
|
312
312
|
raise "Single literal cannot satisfy multiple identifying roles for #{object_type.name}" if identifying_role_refs.size > 1
|
313
313
|
role = identifying_role_refs.single.role
|
@@ -323,19 +323,20 @@ module ActiveFacts
|
|
323
323
|
}
|
324
324
|
if instance_rv
|
325
325
|
instance = existing_instance
|
326
|
-
|
326
|
+
trace :instance, "Already known: #{instance.verbalise.inspect}"
|
327
327
|
else
|
328
328
|
# This fact has no clause.
|
329
|
-
trace :
|
329
|
+
trace :instance_detail, "Creating implicit existential fact #{role.fact_type.default_reading}"
|
330
330
|
fact = @constellation.Fact(:new, :fact_type => role.fact_type, :population => @population)
|
331
331
|
@bound_facts << fact
|
332
332
|
# This instance will be associated with its binding by our caller
|
333
333
|
instance = @constellation.Instance(:new, :object_type => object_type, :population => @population)
|
334
|
-
trace :
|
334
|
+
trace :instance_detail, "Creating Entity #{object_type.name} identified by '#{literal}' #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
335
335
|
@bound_facts << instance
|
336
336
|
# The identifying fact type has two roles; create both role instances:
|
337
337
|
@constellation.RoleValue(:instance => identifying_instance, :fact => fact, :population => @population, :role => role)
|
338
338
|
@constellation.RoleValue(:instance => instance, :fact => fact, :population => @population, :role => (role.fact_type.all_role-[role])[0])
|
339
|
+
trace :instance, "Assert #{instance.verbalise.inspect}"
|
339
340
|
end
|
340
341
|
instance
|
341
342
|
end
|