activefacts 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cql +137 -91
  3. data/css/style.css +3 -3
  4. data/examples/CQL/Insurance.cql +1 -1
  5. data/examples/CQL/SeparateSubtype.cql +2 -2
  6. data/lib/activefacts/cql/Language/English.treetop +9 -0
  7. data/lib/activefacts/cql/ObjectTypes.treetop +1 -1
  8. data/lib/activefacts/cql/Terms.treetop +3 -1
  9. data/lib/activefacts/cql/ValueTypes.treetop +10 -4
  10. data/lib/activefacts/cql/compiler.rb +1 -0
  11. data/lib/activefacts/cql/compiler/clause.rb +53 -23
  12. data/lib/activefacts/cql/compiler/entity_type.rb +0 -4
  13. data/lib/activefacts/cql/compiler/expression.rb +9 -13
  14. data/lib/activefacts/cql/compiler/fact.rb +49 -48
  15. data/lib/activefacts/cql/compiler/fact_type.rb +23 -20
  16. data/lib/activefacts/cql/compiler/query.rb +49 -121
  17. data/lib/activefacts/cql/compiler/shared.rb +5 -1
  18. data/lib/activefacts/cql/compiler/value_type.rb +4 -2
  19. data/lib/activefacts/generate/rails/schema.rb +138 -108
  20. data/lib/activefacts/generate/transform/surrogate.rb +1 -2
  21. data/lib/activefacts/mapping/rails.rb +52 -45
  22. data/lib/activefacts/persistence/columns.rb +5 -5
  23. data/lib/activefacts/persistence/tables.rb +6 -4
  24. data/lib/activefacts/support.rb +0 -2
  25. data/lib/activefacts/version.rb +1 -1
  26. data/lib/activefacts/vocabulary/extensions.rb +64 -42
  27. data/lib/activefacts/vocabulary/metamodel.rb +14 -12
  28. data/lib/activefacts/vocabulary/verbaliser.rb +98 -92
  29. data/spec/cql/expressions_spec.rb +8 -3
  30. data/spec/cql/parser/entity_types_spec.rb +1 -1
  31. data/spec/cql/parser/expressions_spec.rb +66 -52
  32. data/spec/cql/parser/fact_types_spec.rb +1 -1
  33. data/spec/cql/parser/literals_spec.rb +10 -10
  34. data/spec/cql/parser/pragmas_spec.rb +3 -3
  35. data/spec/cql/parser/value_types_spec.rb +1 -1
  36. metadata +2 -2
@@ -37,8 +37,8 @@ module ActiveFacts
37
37
  to_s
38
38
  end
39
39
 
40
- def inspect phrases = nil
41
- to_s(phrases||@phrases)
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
- quotes = false
56
- phrases.inject(""){|s, p|
57
- if String === p
58
- s + (quotes ? '' : (quotes = true; '"')) + p.to_s + ' '
59
- # REVISIT: Add something here when I re-add functions
60
- # elsif FunctionCallChain === p
61
- # s[0..-2] + (quotes ? (quotes = false; '" ') : '') + p.to_s
62
- else # if Reference === p
63
- s[0..-2] + (quotes ? (quotes = false; '" ') : '') + p.to_s +
64
- ((oj = p.nested_clauses) ? ' ('+ oj.map{|c| ((j=c.conjunction) ? j+' ' : '') + c.to_s}*' ' + ')' : '') +
65
- ' '
66
- # else
67
- # raise "Unexpected phrase type in clause: #{p.to_s}"
68
- end
69
- }.sub(/ $/,'') + (quotes ? '"' : '')
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(phrases)}'" do
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 |oj|
208
- ft = oj.match_existing_fact_type(context)
209
- raise "Unrecognised fact type #{oj.display}" unless ft
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
- oj.objectified_as = ref
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{|oj| oj.includes_literals}
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
- "compare#{operator}(#{[@e1,@e2].map{|e| e.player.name}*', '}))"
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
- "compare#{
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
- "sum(#{ @terms.map{|f| f.player.name}*', ' })"
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
- 'sum(' + @terms.map{|term| "#{term.to_s}" } * ' ' + ')'
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
- "product(#{ @factors.map{|f| f.player.name}*', ' })"
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
- 'product(' + @factors.map{|factor| "#{factor.to_s}" } * ' ' + ')'
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
- "reciprocal(#{factor.to_s})"
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
- "negate(#{term.to_s})"
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 :instance, "Making #{player.class.basename} #{player.name} using #{l.inspect}" do
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
- trace :instance, "Considering '#{clause.display}' with "+
96
- (bare_roles.empty? ? "no bare roles" : "bare roles: #{bare_roles.map{|ref| ref.player.name}*", "}") do
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 :instance, "Can't make progress on '#{clause.display}'"
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 :instance, "Pass #{@pass} with #{@unbound_clauses.size} clauses to consider" do
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 :instance, "end of pass, unbound clauses are #{@unbound_clauses.map(&:display)*', '}"
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
- @clauses.map do |clause|
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 :instance, "Instances are #{instances.map{|i| "#{i.verbalise}"}*", "}"
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 :instance, "Searching for existing fact instance"
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, "Found existing fact"
167
+ trace :instance, "Already known: #{fact.verbalise.inspect}"
169
168
  else
170
- trace :instance, "Creating new fact of type #{clause.fact_type.default_reading}"
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 :instance, "Assigning fact role #{instance.object_type.name} to #{instance.value ? instance.value.inspect : instance.verbalise}"
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, "This clause associates a new #{binding.player.name} with a #{identifying_binding.player.name}#{identifying_instance ? " which exists" : ""}"
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 shold never happen; we already bound all refs
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, "Found an existing instance (of #{instance.object_type.name}) from a previous definition"
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
- trace :instance, "Creating Entity #{binding.player.name} using #{identifiers.size} roles" do
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
- trace :instance, "Creating existential fact #{rr.role.fact_type.default_reading} for value #{identifying_instance.value.inspect}"
260
- id_fact =
261
- identifying_clause.fact =
262
- @constellation.Fact(:new, :fact_type => rr.role.fact_type, :population => @population)
263
- @bound_facts << id_fact
264
- role = (rr.role.fact_type.all_role.to_a-[rr.role])[0]
265
- @constellation.RoleValue(:instance => instance, :fact => id_fact, :population => @population, :role => role)
266
- @constellation.RoleValue(:instance => identifying_instance, :fact => id_fact, :role => rr.role, :population => @population)
267
- end
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 :instance, "Assert Value #{object_type.name} #{literal.inspect}" do
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 :instance, "Comparing #{i.value.literal.inspect} to #{literal.literal.inspect}"
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, "This #{object_type.name} value already exists"
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 :instance, "Assert Entity #{object_type.name} identified by '#{literal}'" do
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
- trace :instance, "This #{object_type.name} entity already exists"
326
+ trace :instance, "Already known: #{instance.verbalise.inspect}"
327
327
  else
328
328
  # This fact has no clause.
329
- trace :instance, "Creating implicit existential fact #{role.fact_type.default_reading}"
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 :instance, "Creating Entity #{object_type.name} identified by '#{literal}' #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
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