[Groonga-commit] groonga/groonga at 6ba0c0c [master] Introduce context object

Zurück zum Archiv-Index

Kouhei Sutou null+****@clear*****
Thu Feb 16 10:26:41 JST 2017


Kouhei Sutou	2017-02-16 10:26:41 +0900 (Thu, 16 Feb 2017)

  New Revision: 6ba0c0c13dc1173c96bb8ceac23d76de26cf08cf
  https://github.com/groonga/groonga/commit/6ba0c0c13dc1173c96bb8ceac23d76de26cf08cf

  Message:
    Introduce context object

  Modified files:
    lib/mrb/scripts/scan_info_builder.rb

  Modified: lib/mrb/scripts/scan_info_builder.rb (+129 -86)
===================================================================
--- lib/mrb/scripts/scan_info_builder.rb    2017-02-15 13:17:23 +0900 (27d0f5f)
+++ lib/mrb/scripts/scan_info_builder.rb    2017-02-16 10:26:41 +0900 (b29bf39)
@@ -2,14 +2,6 @@ require "scan_info_data"
 
 module Groonga
   class ScanInfoBuilder
-    module Status
-      START = 0
-      VAR = 1
-      COL1 = 2
-      COL2 = 3
-      CONST = 4
-    end
-
     def initialize(expression, operator, record_exist)
       @data_list = []
       @expression = expression
@@ -61,94 +53,106 @@ module Groonga
     def build
       return nil unless valid?
 
-      status = Status::START
-      variable = @expression[0]
-      data = nil
-      codes =****@expre*****
-      n_codes = codes.size
-      next_code_op = nil
-      codes.each_with_index do |code, i|
-        code_op = (next_code_op || code.op)
-        next_code_op = nil
+      context = BuildContext.new(@expression)
+      codes = context.codes
+      variable = context.variable
+      while context.have_next?
+        code = context.code
+        code_op = context.code_op
+        i = context.i
+        context.next
+
         case code_op
         when *RELATION_OPERATORS
-          status = Status::START
+          context.status = :start
+          data = context.data
           data.op = code_op
           data.end = i
           data.match_resolve_index
           @data_list << data
-          data = nil
+          context.data = nil
         when *LOGICAL_OPERATORS
-          if status == Status::CONST
+          if context.status == :const
+            data = context.data
             data.op = Operator::PUSH
             data.end = data.start
             @data_list << data
-            data = nil
+            context.data = nil
           end
           put_logical_op(code_op, i)
           # TODO: rescue and return nil
-          status = Status::START
+          context.status = :start
         when Operator::PUSH
-          data ||= ScanInfoData.new(i)
+          context.data ||= ScanInfoData.new(i)
+          data = context.data
           if code.value == variable
-            status = Status::VAR
+            context.status = :var
           else
             data.args << code.value
-            if status == Status::START
+            if context.status == :start
               data.flags |= ScanInfo::Flags::PRE_CONST
             end
-            status = Status::CONST
+            context.status = :const
           end
           if code.modify > 0 and
               LOGICAL_OPERATORS.include?(codes[i + code.modify].op)
             data.op = Operator::PUSH
             data.end = data.start
             @data_list << data
-            data = nil
-            status = Status::START
+            context.data = nil
+            context.status = :start
           end
         when Operator::GET_VALUE
-          case status
-          when Status::START
-            data ||= ScanInfoData.new(i)
-            status = Status::COL1
+          case context.status
+          when :start
+            context.data ||= ScanInfoData.new(i)
+            data = context.data
+            context.status = :column1
             data.args << code.value
-          when Status::CONST, Status::VAR
-            status = Status::COL1
+          when :const, :var
+            context.status = :column1
             data.args << code.value
-          when Status::COL1
-            raise ErrorMessage, "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>"
-            status = Status::COL2
-          when Status::COL2
+          when :column1
+            message = "invalid expression: can't use column as a value: "
+            message << "<#{code.value.name}>: <#{@expression.grn_inspect}>"
+            raise ErrorMessage, message
+          when :column2
             # Do nothing
+          else
+            message = "internal expression parsing error: unknown status: "
+            message << "<#{context.status.inspect}>: "
+            message << "<#{@expression.grn_inspect}>"
+            raise ErrorMessage, message
           end
         when Operator::CALL
-          data ||= ScanInfoData.new(i)
+          context.data ||= ScanInfoData.new(i)
+          data = context.data
           if (code.flags & ExpressionCode::Flags::RELATIONAL_EXPRESSION) != 0 or
-              (i + 1) == n_codes
-            status = Status::START
+              (not context.have_next?)
+            context.status = :start
             data.op = code_op
             data.end = i
             data.call_relational_resolve_indexes
             @data_list << data
-            data = nil
+            context.data = nil
           else
-            status = Status::COL2
+            context.status = :column2
           end
         when Operator::GET_REF
-          data ||= ScanInfoData.new(i)
-          case status
-          when Status::START
-            data ||= ScanInfoData.new(i)
-            status = Status::COL1
+          context.data ||= ScanInfoData.new(i)
+          case context.status
+          when :start
+            data = context.data
+            context.status = :column1
             data.args << code.value
           end
         when Operator::GET_MEMBER
+          data = context.data
           index = data.args.pop
           data.start_position = index.value
-          status = Status::COL1
+          context.status = :column1
         when Operator::NOT
-          success, next_code_op = build_not(code, codes, i)
+          success = build_not(context, code)
           return nil unless success
         end
       end
@@ -163,7 +167,7 @@ module Groonga
           first_data.logical_op = @operator
         end
       else
-        put_logical_op(@operator, n_codes)
+        put_logical_op(@operator, @context.n_codes)
       end
 
       optimize
@@ -173,31 +177,33 @@ module Groonga
     def valid?
       n_relation_expressions = 0
       n_logical_expressions = 0
-      status = Status::START
+      status = :start
       variable = @expression[0]
       codes =****@expre*****
       codes.each_with_index do |code, i|
         case code.op
         when *RELATION_OPERATORS
-          return false if status < Status::COL1
-          return false if status > Status::CONST
-          status = Status::START
+          if status == :start || status == :var
+            return false
+          end
+          status = :start
           n_relation_expressions += 1
         when *ARITHMETIC_OPERATORS
-          return false if status < Status::COL1
-          return false if status > Status::CONST
-          status = Status::START
+          if status == :start || status == :var
+            return false
+          end
+          status = :start
           return false if n_relation_expressions != (n_logical_expressions + 1)
         when *LOGICAL_OPERATORS
           case status
-          when Status::START
+          when :start
             n_logical_expressions += 1
             return false if n_logical_expressions >= n_relation_expressions
-          when Status::CONST
+          when :const
             n_logical_expressions += 1
             n_relation_expressions += 1
             return false if n_logical_expressions >= n_relation_expressions
-            status = Status::START
+            status = :start
           else
             return false
           end
@@ -205,21 +211,21 @@ module Groonga
           if code.modify > 0 and
               LOGICAL_OPERATORS.include?(codes[i + code.modify].op)
             n_relation_expressions += 1
-            status = Status::START
+            status = :start
           else
             if code.value == variable
-              status = Status::VAR
+              status = :var
             else
-              status = Status::CONST
+              status = :const
             end
           end
         when Operator::GET_VALUE
           case status
-          when Status::START, Status::CONST, Status::VAR
-            status = Status::COL1
-          when Status::COL1
-            status = Status::COL2
-          when Status::COL2
+          when :start, :const, :var
+            status = :column1
+          when :column1
+            status = :column2
+          when :column2
             # Do nothing
           else
             return false
@@ -227,23 +233,23 @@ module Groonga
         when Operator::CALL
           if (code.flags & ExpressionCode::Flags::RELATIONAL_EXPRESSION) != 0 or
               code == codes.last
-            status = Status::START
+            status = :start
             n_relation_expressions += 1
           else
-            status = Status::COL2
+            status = :column2
           end
         when Operator::GET_REF
           case status
-          when Status::START
-            status = Status::COL1
+          when :start
+            status = :column1
           else
             return false
           end
         when Operator::GET_MEMBER
           case status
-          when Status::CONST
+          when :const
             return false unless codes[i - 1].value.value.is_a?(Integer)
-            status = Status::COL1
+            status = :column1
           else
             return false
           end
@@ -254,7 +260,7 @@ module Groonga
         end
       end
 
-      return false if status != Status::START
+      return false if status != :start
       return false if n_relation_expressions != (n_logical_expressions + 1)
 
       true
@@ -323,11 +329,10 @@ module Groonga
       end
     end
 
-    def build_not(code, codes, i)
+    def build_not(context, code)
       last_data = @data_list.last
-      return [false, nil] if last_data.nil?
+      return false if last_data.nil?
 
-      next_code_op = nil
       case last_data.op
       when Operator::LESS
         last_data.op = Operator::GREATER_EQUAL
@@ -351,7 +356,7 @@ module Groonga
               last_data.op = Operator::NOT_EQUAL
               last_data.end += 1
             else
-              return [false, nil]
+              return false
             end
           else
             last_data.logical_op = Operator::AND_NOT
@@ -359,21 +364,21 @@ module Groonga
             @data_list.unshift(create_all_match_data)
           end
         else
-          next_code = codes[i + 1]
-          return [false, nil] if next_code.nil?
+          next_code = context.code
+          return false if next_code.nil?
 
           case next_code.op
           when Operator::AND
-            next_code_op = Operator::AND_NOT
+            context.code_op = Operator::AND_NOT
           when Operator::AND_NOT
-            next_code_op = Operator::AND
+            context.code_op = Operator::AND
           else
-            return [false, nil]
+            return false
           end
         end
       end
 
-      [true, next_code_op]
+      true
     end
 
     def optimize
@@ -490,5 +495,43 @@ module Groonga
         @expression.allocate_constant(max_border),
       ]
     end
+
+    class BuildContext
+      attr_accessor :status
+      attr_reader :variable
+      attr_reader :codes
+      attr_reader :n_codes
+      attr_reader :i
+      attr_writer :code_op
+      attr_accessor :data
+      def initialize(expression)
+        @expression = expression
+        @status = :start
+        @variable = @expression[0]
+        @current_data = nil
+        @codes =****@expre*****
+        @n_codes =****@codes*****
+        @i = 0
+        @code_op = nil
+        @data = nil
+      end
+
+      def have_next?
+        @i < @n_codes
+      end
+
+      def next
+        @i += 1
+        @code_op = nil
+      end
+
+      def code
+        @codes[@i]
+      end
+
+      def code_op
+        @code_op || code.op
+      end
+    end
   end
 end
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Zurück zum Archiv-Index