Skip to content

Commit

Permalink
Renamed Compiler::RoleRef to ::VarRef
Browse files Browse the repository at this point in the history
  • Loading branch information
cjheath committed Feb 10, 2011
1 parent 2052b51 commit be0767d
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 214 deletions.
12 changes: 6 additions & 6 deletions lib/activefacts/cql/FactTypes.treetop
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module ActiveFacts
elsif (clauses_ast.size == 1 &&
clauses_ast[0].phrases.size == 1 &&
(popname = clauses_ast[0].phrases[0]) &&
!popname.is_a?(Compiler::RoleRef) &&
!popname.is_a?(Compiler::VarRef) &&
conditions.detect{|r| r.includes_literals}
)
Compiler::Fact.new conditions, popname
Expand Down Expand Up @@ -83,7 +83,7 @@ module ActiveFacts
end

rule return
ordering_prefix? clause_word+
ordering_prefix? phrase+
end

rule qualified_clauses
Expand Down Expand Up @@ -146,7 +146,7 @@ module ActiveFacts
(
contraction # A contraction will terminate this repetition by eating to the end
/
clause_word
phrase
)+
{
def ast
Expand Down Expand Up @@ -193,7 +193,7 @@ module ActiveFacts

rule condition_contraction
role p:post_qualifiers? q:qualifier? s comparator s e2:expression
!clause_word # The contracted_clauses must not continue here!
!phrase # The contracted_clauses must not continue here!
{
def ast
c = Compiler::Comparison.new(comparator.text_value, role.ast, e2.ast, q.empty? ? [] : [q.text_value])
Expand Down Expand Up @@ -228,7 +228,7 @@ module ActiveFacts
'<=' / '<>' / '<' / '=' / '>=' / '>' / '!='
end

rule clause_word
rule phrase
role # A role reference containing a term, perhaps with attached paraphernalia
/ # A hyphenated non-term. Important: no embedded spaces
id tail:('-' !term id)+ s
Expand All @@ -239,7 +239,7 @@ module ActiveFacts
def node_type; :linking; end
}
/ # A normal non-term
!non_role_word id s
!non_phrase id s
{
def ast
id.value
Expand Down
14 changes: 7 additions & 7 deletions lib/activefacts/cql/ObjectTypes.treetop
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ module ActiveFacts
&{|s|
role_list = s[-1]
forwards = role_list.ast.
map do |role_ref|
next nil if role_ref.is_a?(Compiler::Clause) # Can't forward-reference unaries
next nil if role_ref.leading_adjective or role_ref.trailing_adjective
role_ref.term
map do |role|
next nil if role.is_a?(Compiler::Clause) # Can't forward-reference unaries
next nil if role.leading_adjective or role.trailing_adjective
role.term
end.
compact
input.context.allowed_forward_terms(forwards)
Expand Down Expand Up @@ -124,7 +124,7 @@ module ActiveFacts
end

rule unary_text
(s !non_role_word !term id)*
(s !non_phrase !term id)*
{
def node_type; :linking; end
}
Expand All @@ -146,11 +146,11 @@ module ActiveFacts
end
}
/
s !non_role_word id s &non_role_word s ss:subscript
s !non_phrase id s &non_phrase s ss:subscript
{ # A forward-referenced entity type
# REVISIT: A change in this rule might allow forward-referencing a multi-word term
def ast
Compiler::RoleRef.new(id.text_value, nil, nil, nil, ss.empty? ? nil : ss.value)
Compiler::VarRef.new(id.text_value, nil, nil, nil, ss.empty? ? nil : ss.value)
end
}
end
Expand Down
8 changes: 4 additions & 4 deletions lib/activefacts/cql/Terms.treetop
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module ActiveFacts
mapping_pragmas entity_prefix
/ mapping_pragmas written_as # Value type
/ mapping_pragmas is_where # Objectified type
/ non_role_word
/ non_phrase
/ identified_by # as in: "a kind of X identified by..."
/ unit
end
Expand Down Expand Up @@ -142,7 +142,7 @@ module ActiveFacts
gt = x.context[:global_term]
leading_adjective = t[0...-gt.size-1] if t.size > gt.size and t[-gt.size..-1] == gt
trailing_adjective = t[gt.size+1..-1] if t.size > gt.size and t[0...gt.size] == gt
Compiler::RoleRef.new(gt, leading_adjective, trailing_adjective, quantifier, function_call, role_name, value_constraint, literal, objectification_join)
Compiler::VarRef.new(gt, leading_adjective, trailing_adjective, quantifier, function_call, role_name, value_constraint, literal, objectification_join)
end

def value # Sometimes we just want the full term name
Expand Down Expand Up @@ -176,8 +176,8 @@ module ActiveFacts
}
end

rule non_role_word
# These words are illegal in (but maybe ok following) a clause where a clause_word is expected:
rule non_phrase
# These words are illegal in (but maybe ok following) a clause where a phrase is expected:
and
/ but
/ if
Expand Down
100 changes: 50 additions & 50 deletions lib/activefacts/cql/compiler/clause.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ class Clause
attr_reader :side_effects
attr_writer :fact_type # Assigned for a bare (existential) objectification fact
attr_accessor :fact # When binding fact instances the fact goes here
attr_accessor :objectified_as # The Reading::RoleRef which objectified this fact type
attr_accessor :objectified_as # The VarRef which objectified this fact type

def initialize role_refs_and_words, qualifiers = [], context_note = nil
@phrases = role_refs_and_words
role_refs.each { |role_ref| role_ref.clause = self }
def initialize phrases, qualifiers = [], context_note = nil
@phrases = phrases
var_refs.each { |var_ref| var_ref.clause = self }
@qualifiers = qualifiers
@context_note = context_note
end

def role_refs
@phrases.select{|r| r.is_a?(RoleRef)}
def var_refs
@phrases.select{|r| r.is_a?(VarRef)}
end

# A clause that contains only the name of a ObjectType and no literal or reading text
# refers only to the existence of that ObjectType (as opposed to an instance of the object_type).
def is_existential_type
@phrases.size == 1 and
@phrases[0].is_a?(RoleRef) and
@phrases[0].is_a?(VarRef) and
!@phrases[0].literal
end

Expand All @@ -45,7 +45,7 @@ def to_s
}#{
quotes = false
@phrases.inject(""){|s, p|
if RoleRef === p
if VarRef === p
s[0..-2] + (quotes ? (quotes = false; '" ') : '') + p.to_s +
((oj = p.objectification_join) ? ' ('+ oj.map{|c| ((j=c.conjunction) ? j+' ' : '') + c.to_s}*' ' + ')' : '') +
' '
Expand All @@ -63,49 +63,49 @@ def to_s
end

def identify_players_with_role_name context
role_refs.each do |role_ref|
role_ref.identify_player(context) if role_ref.role_name
var_refs.each do |var_ref|
var_ref.identify_player(context) if var_ref.role_name
# Include players in an objectification join, if any
role_ref.objectification_join.each{|clause| clause.identify_players_with_role_name(context)} if role_ref.objectification_join
var_ref.objectification_join.each{|clause| clause.identify_players_with_role_name(context)} if var_ref.objectification_join
end
end

def identify_other_players context
role_refs.each do |role_ref|
role_ref.identify_player(context) unless role_ref.player
var_refs.each do |var_ref|
var_ref.identify_player(context) unless var_ref.player
# Include players in an objectification join, if any
role_ref.objectification_join.each{|clause| clause.identify_other_players(context)} if role_ref.objectification_join
var_ref.objectification_join.each{|clause| clause.identify_other_players(context)} if var_ref.objectification_join
end
end

def includes_literals
role_refs.detect{|role_ref| role_ref.literal || (ja = role_ref.objectification_join and ja.detect{|jr| jr.includes_literals })}
var_refs.detect{|var_ref| var_ref.literal || (ja = var_ref.objectification_join and ja.detect{|jr| jr.includes_literals })}
end

def is_equality_comparison
false
end

def bind_roles context
role_names = role_refs.map{ |role_ref| role_ref.role_name }.compact
role_names = var_refs.map{ |var_ref| var_ref.role_name }.compact

# Check uniqueness of role names and subscripts within this clause:
role_names.each do |rn|
next if role_names.select{|rn2| rn2 == rn}.size == 1
raise "Duplicate role #{rn.is_a?(Integer) ? "subscript" : "name"} '#{rn}' in clause"
end

role_refs.each do |role_ref|
role_ref.bind context
var_refs.each do |var_ref|
var_ref.bind context
# Include players in an objectification join, if any
role_ref.objectification_join.each{|clause| clause.bind_roles(context)} if role_ref.objectification_join
var_ref.objectification_join.each{|clause| clause.bind_roles(context)} if var_ref.objectification_join
end
end

def phrases_match(phrases)
@phrases.zip(phrases).each do |mine, theirs|
return false if mine.is_a?(RoleRef) != theirs.is_a?(RoleRef)
if mine.is_a?(RoleRef)
return false if mine.is_a?(VarRef) != theirs.is_a?(VarRef)
if mine.is_a?(VarRef)
return false unless mine.key == theirs.key
else
return false unless mine == theirs
Expand Down Expand Up @@ -136,7 +136,7 @@ def match_existing_fact_type context, options = {}

contracted_role = nil

rrs = []+role_refs
rrs = []+var_refs
begin
players = rrs.map{|rr| rr.player}
raise "Must identify players before matching fact types" if players.include? nil
Expand All @@ -149,25 +149,25 @@ def match_existing_fact_type context, options = {}

# Match existing fact types in objectification joins first (not for contractions):
if !contracted_role
rrs.each do |role_ref|
next unless joins = role_ref.objectification_join and !joins.empty?
role_ref.objectification_join.each do |oj|
rrs.each do |var_ref|
next unless joins = var_ref.objectification_join and !joins.empty?
var_ref.objectification_join.each do |oj|
ft = oj.match_existing_fact_type(context)
raise "Unrecognised fact type #{oj.display}" unless ft
if (ft && ft.entity_type == role_ref.player)
role_ref.objectification_of = ft
oj.objectified_as = role_ref
if (ft && ft.entity_type == var_ref.player)
var_ref.objectification_of = ft
oj.objectified_as = var_ref
end
end
raise "#{role_ref.inspect} contains objectification joins that do not objectify it" unless role_ref.objectification_of
raise "#{var_ref.inspect} contains objectification joins that do not objectify it" unless var_ref.objectification_of
end
end

# For each role player, find the compatible types (the set of all subtypes and supertypes).
# For a player that's an objectification, we don't allow implicit supertype joins
player_related_types =
rrs.zip(players).map do |role_ref, player|
disallow_subtyping = role_ref && role_ref.objectification_of || options[:exact_type]
rrs.zip(players).map do |var_ref, player|
disallow_subtyping = var_ref && var_ref.objectification_of || options[:exact_type]
((disallow_subtyping ? [] : player.supertypes_transitive) +
player.subtypes_transitive).uniq
end
Expand Down Expand Up @@ -254,9 +254,9 @@ def match_existing_fact_type context, options = {}
debug :matching, "No fact type matched, candidates were '#{candidate_fact_types.map{|ft| ft.default_reading}*"', '"}'"
end
if left_contract_this_onto && !contracted_role
contracted_from = left_contract_this_onto.role_refs[0]
contracted_from = left_contract_this_onto.var_refs[0]
contraction_player = contracted_from.player
contracted_role = RoleRef.new(contraction_player.name)
contracted_role = VarRef.new(contraction_player.name)
contracted_role.player = contracted_from.player
contracted_role.role_name = contracted_from.role_name
contracted_role.bind(context)
Expand All @@ -277,7 +277,7 @@ def match_existing_fact_type context, options = {}
# Find whether the phrases of this clause match the fact type reading,
# which may require absorbing unmarked adjectives.
#
# If it does match, make the required changes and set @role_ref to the matching role.
# If it does match, make the required changes and set @var_ref to the matching role ref.
# Adjectives that were used to match are removed (and leaving any additional adjectives intact).
#
# Approach:
Expand Down Expand Up @@ -318,7 +318,7 @@ def clause_matches(fact_type, reading, contracted_role = nil)
intervening_words = []
while (phrase = phrases[phrase_num])
phrase_num += 1
if phrase.is_a?(RoleRef)
if phrase.is_a?(VarRef)
next_player_phrase = phrase
next_player_phrase_num = phrase_num-1
break
Expand Down Expand Up @@ -519,7 +519,7 @@ def make_fact_type vocabulary
fact_type = vocabulary.constellation.FactType(:new)
debug :matching, "Making new fact type for #{@phrases.inspect}" do
@phrases.each do |phrase|
next unless phrase.is_a?(RoleRef)
next unless phrase.is_a?(VarRef)
phrase.role = vocabulary.constellation.Role(fact_type, fact_type.all_role.size, :object_type => phrase.player)
phrase.role.role_name = phrase.role_name if phrase.role_name && phrase.role_name.is_a?(String)
end
Expand All @@ -535,7 +535,7 @@ def make_reading vocabulary, fact_type
index = 0
debug :matching, "Making new reading for #{@phrases.inspect}" do
reading_words.map! do |phrase|
if phrase.is_a?(RoleRef)
if phrase.is_a?(VarRef)
# phrase.role will be set if this reading was used to make_fact_type.
# Otherwise we have to find the existing role via the Binding. This is pretty ugly.
unless phrase.role
Expand Down Expand Up @@ -590,7 +590,7 @@ def adjust_for_match
reading_words = []
new_role_sequence_needed = false
@phrases.each do |phrase|
if phrase.is_a?(RoleRef)
if phrase.is_a?(VarRef)
role_phrases << phrase
reading_words << "{#{phrase.role_ref.ordinal}}"
if phrase.role_name != phrase.role_ref.role.role_name ||
Expand Down Expand Up @@ -652,10 +652,10 @@ def adjust_for_match
end

def make_embedded_constraints vocabulary
role_refs.each do |role_ref|
next unless role_ref.quantifier
# puts "Quantifier #{role_ref.inspect} not implemented as a presence constraint"
role_ref.make_embedded_presence_constraint vocabulary
var_refs.each do |var_ref|
next unless var_ref.quantifier
# puts "Quantifier #{var_ref.inspect} not implemented as a presence constraint"
var_ref.make_embedded_presence_constraint vocabulary
end

if @qualifiers && @qualifiers.size > 0
Expand All @@ -677,7 +677,7 @@ def make_embedded_constraints vocabulary
end

def is_naked_object_type
@phrases.size == 1 && role_refs.size == 1
@phrases.size == 1 && var_refs.size == 1
end

end
Expand Down Expand Up @@ -710,7 +710,7 @@ def to_s
class ClauseMatchSideEffects
attr_reader :residual_adjectives
attr_reader :fact_type
attr_reader :role_side_effects # One array of values per RoleRef matched, in order
attr_reader :role_side_effects # One array of values per VarRef matched, in order

def initialize fact_type, clause, residual_adjectives, role_side_effects
@fact_type = fact_type
Expand Down Expand Up @@ -750,12 +750,12 @@ def describe
end
end

class RoleRef
class VarRef
attr_reader :term, :trailing_adjective, :quantifier, :function_call, :role_name, :value_constraint, :literal, :objectification_join
attr_accessor :leading_adjective, :trailing_adjective
attr_accessor :player
attr_accessor :binding
attr_accessor :clause # The clause that this RoleRef is part of
attr_accessor :clause # The clause that this VarRef is part of
attr_accessor :role # This refers to the ActiveFacts::Metamodel::Role
attr_accessor :role_ref # This refers to the ActiveFacts::Metamodel::RoleRef
attr_accessor :objectification_of # If objectification_join is set, this is the fact type it objectifies
Expand Down Expand Up @@ -866,13 +866,13 @@ def rebind(context)
bind context
end

def rebind_to(context, other_role_ref)
debug :binding, "Rebinding #{inspect} to #{other_role_ref.inspect}"
def rebind_to(context, other_var_ref)
debug :binding, "Rebinding #{inspect} to #{other_var_ref.inspect}"

old_binding = binding # Remember to move all refs across
unbind(context)

new_binding = other_role_ref.binding
new_binding = other_var_ref.binding
[self, *old_binding.refs].each do |ref|
ref.binding = new_binding
new_binding.refs << ref
Expand Down Expand Up @@ -907,7 +907,7 @@ def make_embedded_presence_constraint vocabulary

debug :constraint, "Processing embedded constraint #{@quantifier.inspect} on #{@role_ref.role.object_type.name} in #{fact_type.describe}" do
# Preserve the role order of the clause, excluding this role:
constrained_roles = (@clause.role_refs-[self]).map{|rr| rr.role_ref.role}
constrained_roles = (@clause.var_refs-[self]).map{|rr| rr.role_ref.role}
if constrained_roles.empty?
debug :constraint, "Quantifier over unary role has no effect"
return
Expand Down
Loading

0 comments on commit be0767d

Please sign in to comment.