<commit_before>module ActiveFacts
  module CQL
    class Compiler < ActiveFacts::CQL::Parser
      class Definition
        # Make a Variable for every binding present in these clauses
        def build_variables(clauses_list)
          trace :query, "Building variables" do
            query = @constellation.Query(:new)
            all_bindings_in_clauses(clauses_list).
              each do |binding|
                var_name = (r = binding.refs.select{|r| r.is_a?(Reference)}.first) ? r.var_name : nil
                trace :query, "Creating variable #{query.all_variable.size} for #{binding.inspect} with role_name #{var_name}"
                binding.variable = @constellation.Variable(
                  query, query.all_variable.size, :object_type => binding.player, role_name: var_name
                )
                if literal = binding.refs.detect{|r| r.literal}
                  if literal.kind_of?(ActiveFacts::CQL::Compiler::Reference)
                    # REVISIT: Fix this crappy ad-hoc polymorphism hack
                    literal = literal.literal
                  end
                  unit = @constellation.Unit.detect{|k, v| [v.name, v.plural_name].include? literal.unit} if literal.unit
                  binding.variable.value = [literal.literal.to_s, literal.literal.is_a?(String), unit]
                end
              end
            query
          end
        end

        def build_all_steps(query, clauses_list)
          roles_by_binding = {}
          trace :query, "Building steps" do
            clauses_list.each do |clause|
              build_step(query, clause, roles_by_binding)
            end
          end
          roles_by_binding
        end

        def build_step query, clause, roles_by_binding = {}, parent_variable = nil
          return unless clause.refs.size > 0  # Empty clause... really?

          step = @constellation.Step(
              query, query.all_step.size,
              :fact_type => clause.fact_type,
              :alternative_set => nil,
              :is_disallowed => clause.certainty == false,
              :is_optional => clause.certainty == nil
            )

          trace :query, "Creating Plays for #{clause.inspect} with #{clause.refs.size} refs" do
            is_input = true
            clause.refs.each do |ref|
              # These refs are the Compiler::References, which have associated Metamodel::RoleRefs,
              # but we need to create Plays for those roles.
              # REVISIT: Plays may need to save residual_adjectives
              binding = ref.binding
              role = (ref && ref.role) || (ref.role_ref && ref.role_ref.role)

              objectification_step = nil
              if ref.nested_clauses
                ref.nested_clauses.each do |nested_clause|
                  objectification_step = build_step(query, nested_clause, roles_by_binding)
                  if ref.binding.player.is_a?(ActiveFacts::Metamodel::EntityType) and
                      ref.binding.player.fact_type == nested_clause.fact_type
                    objectification_step.objectification_variable = binding.variable
                  end
                end<commit_msg>A bare object type is a valid clause, but it contains no fact type hence no step<commit_after>module ActiveFacts
  module CQL
    class Compiler < ActiveFacts::CQL::Parser
      class Definition
        # Make a Variable for every binding present in these clauses
        def build_variables(clauses_list)
          trace :query, "Building variables" do
            query = @constellation.Query(:new)
            all_bindings_in_clauses(clauses_list).
              each do |binding|
                var_name = (r = binding.refs.select{|r| r.is_a?(Reference)}.first) ? r.var_name : nil
                trace :query, "Creating variable #{query.all_variable.size} for #{binding.inspect} with role_name #{var_name}"
                binding.variable = @constellation.Variable(
                  query, query.all_variable.size, :object_type => binding.player, role_name: var_name
                )
                if literal = binding.refs.detect{|r| r.literal}
                  if literal.kind_of?(ActiveFacts::CQL::Compiler::Reference)
                    # REVISIT: Fix this crappy ad-hoc polymorphism hack
                    literal = literal.literal
                  end
                  unit = @constellation.Unit.detect{|k, v| [v.name, v.plural_name].include? literal.unit} if literal.unit
                  binding.variable.value = [literal.literal.to_s, literal.literal.is_a?(String), unit]
                end
              end
            query
          end
        end

        def build_all_steps(query, clauses_list)
          roles_by_binding = {}
          trace :query, "Building steps" do
            clauses_list.each do |clause|
              build_step(query, clause, roles_by_binding)
            end
          end
          roles_by_binding
        end

        def build_step query, clause, roles_by_binding = {}, parent_variable = nil
          return unless clause.refs.size > 0  # Empty clause... really?

          # A bare object type is a valid clause, but it contains no fact type hence no step
          if clause.fact_type
            step = @constellation.Step(
                query, query.all_step.size,
                :fact_type => clause.fact_type,
                :alternative_set => nil,
                :is_disallowed => clause.certainty == false,
                :is_optional => clause.certainty == nil
              )
          end

          trace :query, "Creating Plays for #{clause.inspect} with #{clause.refs.size} refs" do
            is_input = true
            clause.refs.each do |ref|
              # These refs are the Compiler::References, which have associated Metamodel::RoleRefs,
              # but we need to create Plays for those roles.
              # REVISIT: Plays may need to save residual_adjectives
              binding = ref.binding
              role = (ref && ref.role) || (ref.role_ref && ref.role_ref.role)

              objectification_step = nil
              if ref.nested_clauses
                ref.nested_clauses.each do |nested_clause|
                  objectification_step = build_step(query, nested_clause, roles_by_binding)
                  if ref.binding.player.is_a?(ActiveFacts::Metamodel::EntityType) and
                      ref.binding.player.fact_type == nested_clause.fact_type
                    objectification_step.objectification_variable = binding.variable
                  end
                end
{'fraction_non_alphanumeric': 0.08262454434993925, 'fraction_numerical': 0.00030376670716889426, 'mean_word_length': 1.8104993597951344, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7232989', 'n_tokens_mistral': 1815, 'n_tokens_neox': 1711, 'n_words': 441}