Class: ActiveFacts::CQL::Compiler::Operation

Inherits:
Object
  • Object
show all
Defined in:
lib/activefacts/cql/compiler/expression.rb

Overview

An Operation is a binary or ternary fact type involving an operator, a result, and one or two operands. Viewed as a result, it behaves like a Reference with a nested Clause. Viewed as a fact type, it behaves like a Clause.

The only exception here is an equality comparison, where it may turn out that the equality is merely a projection. In this case the Operation is dropped from the clauses and is replaced by the projected operand.

Each operand may be a Literal, a Reference, or another Operation, so we need to recurse down the tree to build the query.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeOperation

Returns a new instance of Operation.



51
52
53
# File 'lib/activefacts/cql/compiler/expression.rb', line 51

def initialize
  @certainty = true       # Assume it's definite
end

Instance Attribute Details

#bindingObject

What Binding for that ObjectType



33
34
35
# File 'lib/activefacts/cql/compiler/expression.rb', line 33

def binding
  @binding
end

#certaintyObject

nil, true, false -> maybe, definitely, not



37
38
39
# File 'lib/activefacts/cql/compiler/expression.rb', line 37

def certainty
  @certainty
end

#clauseObject

What clause does the result participate in?



34
35
36
# File 'lib/activefacts/cql/compiler/expression.rb', line 34

def clause
  @clause
end

#fact_typeObject (readonly)

Returns the value of attribute fact_type.



48
49
50
# File 'lib/activefacts/cql/compiler/expression.rb', line 48

def fact_type
  @fact_type
end

#playerObject

What ObjectType does the Binding denote



32
33
34
# File 'lib/activefacts/cql/compiler/expression.rb', line 32

def player
  @player
end

#roleObject

Which Role of this ObjectType



35
36
37
# File 'lib/activefacts/cql/compiler/expression.rb', line 35

def role
  @role
end

#role_refObject

Which RoleRef to that Role



36
37
38
# File 'lib/activefacts/cql/compiler/expression.rb', line 36

def role_ref
  @role_ref
end

Instance Method Details

#bind(context) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/activefacts/cql/compiler/expression.rb', line 76

def bind context
  refs.each do |o|
    o.bind context
  end
  name = result_type_name(context)
  @player = result_value_type(context, name)
  key = "#{name} #{object_id}"  # Every Operation result is a unique Binding
  @binding = (context.bindings[key] ||= Binding.new(@player))
  @binding.refs << self
  @binding
end

#conjunctionObject



47
# File 'lib/activefacts/cql/compiler/expression.rb', line 47

def conjunction; nil; end

#identify_other_players(context) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/activefacts/cql/compiler/expression.rb', line 68

def identify_other_players context
  # Just recurse, there's no way (yet: REVISIT?) to add a role name to the result of an expression
  refs.each { |o|
    o.identify_other_players(context)
  }
  identify_player context
end

#identify_players_with_role_name(context) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/activefacts/cql/compiler/expression.rb', line 59

def identify_players_with_role_name context
  # Just recurse, there's no way (yet: REVISIT?) to add a role name to the result of an expression
  refs.each { |o|
    o.identify_players_with_role_name(context)
  }
  # As yet, an operation cannot have a role name:
  # identify_player context if role_name
end

#is_equality_comparisonObject



140
141
142
# File 'lib/activefacts/cql/compiler/expression.rb', line 140

def is_equality_comparison
  false
end

#is_naked_object_typeObject



99
100
101
# File 'lib/activefacts/cql/compiler/expression.rb', line 99

def is_naked_object_type
  false # All Operations are non-naked
end

#leading_adjectiveObject



27
# File 'lib/activefacts/cql/compiler/expression.rb', line 27

def leading_adjective; nil; end

#literalObject



30
# File 'lib/activefacts/cql/compiler/expression.rb', line 30

def literal; nil; end

#match_existing_fact_type(context) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/activefacts/cql/compiler/expression.rb', line 103

def match_existing_fact_type context
  opnds = refs
  result_ref = Reference.new(@binding.player.name)
  result_ref.player = @binding.player
  result_ref.binding = @binding
  @binding.refs << result_ref
  clause_ast = Clause.new(
    [result_ref, '='] +
      (opnds.size > 1 ? [opnds[0]] : []) +
      [operator, opnds[-1]]
  )

  # REVISIT: All operands must be value-types or simply-identified Entity Types.

  # REVISIT: We should auto-create steps from Entity Types to an identifying ValueType
  # REVISIT: We should traverse up the supertype of ValueTypes to find a DataType
  @fact_type = clause_ast.match_existing_fact_type(context, :exact_type => true)
  if clause.certainty == false
    raise "Negated fact types in expressions are not yet supported: #{clause.inspect}"
  end
  return @fact_type if @fact_type

  @fact_type = clause_ast.make_fact_type context.vocabulary
  reading = clause_ast.make_reading context.vocabulary, @fact_type
  rrs = reading.role_sequence.all_role_ref_in_order
  opnds[0].role_ref = rrs[0]
  opnds[-1].role_ref = rrs[-1]
  opnds.each do |opnd|
    next unless opnd.is_a?(Operation)
    opnd.match_existing_fact_type context
    if opnd.certainty == false
      raise "Negated fact types in expressions are not yet supported: #{opnd.inspect}"
    end
  end
  @fact_type
end

#nested_clausesObject



38
# File 'lib/activefacts/cql/compiler/expression.rb', line 38

def nested_clauses; @nested_clauses ||= [self]; end

#objectification_ofObject



40
# File 'lib/activefacts/cql/compiler/expression.rb', line 40

def objectification_of; @fact_type; end

#objectified_asObject

The Reference which objectified this fact type



49
# File 'lib/activefacts/cql/compiler/expression.rb', line 49

def objectified_as; self; end

#operands(context = nil) ⇒ Object



55
56
57
# File 'lib/activefacts/cql/compiler/expression.rb', line 55

def operands context = nil
  raise "REVISIT: Implement operand enumeration in the operator subclass #{self.class.name}"
end

#operatorObject



144
145
146
# File 'lib/activefacts/cql/compiler/expression.rb', line 144

def operator
  raise "REVISIT: Implement operator access in the operator subclass #{self.class.name}"
end

#result_type_name(context) ⇒ Object



88
89
90
# File 'lib/activefacts/cql/compiler/expression.rb', line 88

def result_type_name(context)
  raise "REVISIT: Implement result_type_name in the #{self.class.name} subclass"
end

#result_value_type(context, name) ⇒ Object



92
93
94
95
96
97
# File 'lib/activefacts/cql/compiler/expression.rb', line 92

def result_value_type(context, name)
  vocabulary = context.vocabulary
  constellation = vocabulary.constellation
  vocabulary.valid_value_type_name(name) ||
    constellation.ValueType(vocabulary, name, :concept => :new)
end

#role_nameObject



26
# File 'lib/activefacts/cql/compiler/expression.rb', line 26

def role_name; nil; end

#side_effectsObject



31
# File 'lib/activefacts/cql/compiler/expression.rb', line 31

def side_effects; nil; end

#trailing_adjectiveObject



28
# File 'lib/activefacts/cql/compiler/expression.rb', line 28

def trailing_adjective; nil; end

#value_constraintObject



29
# File 'lib/activefacts/cql/compiler/expression.rb', line 29

def value_constraint; nil; end