xls_function 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/publish_gem.yml +25 -0
  3. data/.github/workflows/rspec.yml +30 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +41 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +8 -0
  9. data/LICENSE +201 -0
  10. data/README.md +48 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/lib/xls_function/class_dictionary.rb +7 -0
  15. data/lib/xls_function/converter.rb +24 -0
  16. data/lib/xls_function/converters/date_converter.rb +30 -0
  17. data/lib/xls_function/converters/date_serial_converter.rb +17 -0
  18. data/lib/xls_function/converters/number_converter.rb +28 -0
  19. data/lib/xls_function/converters/time_converter.rb +158 -0
  20. data/lib/xls_function/converters/time_serial_converter.rb +97 -0
  21. data/lib/xls_function/default_logger.rb +7 -0
  22. data/lib/xls_function/error.rb +49 -0
  23. data/lib/xls_function/evaluators/arguments_definable.rb +39 -0
  24. data/lib/xls_function/evaluators/binary_operation_evaluator.rb +20 -0
  25. data/lib/xls_function/evaluators/binary_operations/add.rb +13 -0
  26. data/lib/xls_function/evaluators/binary_operations/concat.rb +13 -0
  27. data/lib/xls_function/evaluators/binary_operations/divide.rb +13 -0
  28. data/lib/xls_function/evaluators/binary_operations/equal.rb +13 -0
  29. data/lib/xls_function/evaluators/binary_operations/greater_than.rb +13 -0
  30. data/lib/xls_function/evaluators/binary_operations/greater_than_or_equal_to.rb +13 -0
  31. data/lib/xls_function/evaluators/binary_operations/less_than.rb +13 -0
  32. data/lib/xls_function/evaluators/binary_operations/less_than_or_equal_to.rb +13 -0
  33. data/lib/xls_function/evaluators/binary_operations/multiple.rb +13 -0
  34. data/lib/xls_function/evaluators/binary_operations/not_equal.rb +13 -0
  35. data/lib/xls_function/evaluators/binary_operations/power.rb +13 -0
  36. data/lib/xls_function/evaluators/binary_operations/subtract.rb +13 -0
  37. data/lib/xls_function/evaluators/class_dictionary.rb +30 -0
  38. data/lib/xls_function/evaluators/error_detector.rb +29 -0
  39. data/lib/xls_function/evaluators/evaluable.rb +37 -0
  40. data/lib/xls_function/evaluators/false_evaluator.rb +19 -0
  41. data/lib/xls_function/evaluators/function_evaluator.rb +133 -0
  42. data/lib/xls_function/evaluators/functions/and.rb +21 -0
  43. data/lib/xls_function/evaluators/functions/asc.rb +17 -0
  44. data/lib/xls_function/evaluators/functions/char.rb +19 -0
  45. data/lib/xls_function/evaluators/functions/clean.rb +22 -0
  46. data/lib/xls_function/evaluators/functions/code.rb +18 -0
  47. data/lib/xls_function/evaluators/functions/concat.rb +27 -0
  48. data/lib/xls_function/evaluators/functions/date.rb +57 -0
  49. data/lib/xls_function/evaluators/functions/date_value.rb +17 -0
  50. data/lib/xls_function/evaluators/functions/day.rb +15 -0
  51. data/lib/xls_function/evaluators/functions/dbcs.rb +18 -0
  52. data/lib/xls_function/evaluators/functions/e_date.rb +19 -0
  53. data/lib/xls_function/evaluators/functions/e_o_month.rb +20 -0
  54. data/lib/xls_function/evaluators/functions/exact.rb +16 -0
  55. data/lib/xls_function/evaluators/functions/find.rb +28 -0
  56. data/lib/xls_function/evaluators/functions/fixed.rb +46 -0
  57. data/lib/xls_function/evaluators/functions/hour.rb +15 -0
  58. data/lib/xls_function/evaluators/functions/if.rb +24 -0
  59. data/lib/xls_function/evaluators/functions/ifs.rb +20 -0
  60. data/lib/xls_function/evaluators/functions/int.rb +15 -0
  61. data/lib/xls_function/evaluators/functions/iserror.rb +20 -0
  62. data/lib/xls_function/evaluators/functions/isnumber.rb +15 -0
  63. data/lib/xls_function/evaluators/functions/lambda.rb +57 -0
  64. data/lib/xls_function/evaluators/functions/left.rb +16 -0
  65. data/lib/xls_function/evaluators/functions/len.rb +15 -0
  66. data/lib/xls_function/evaluators/functions/let.rb +24 -0
  67. data/lib/xls_function/evaluators/functions/lower.rb +15 -0
  68. data/lib/xls_function/evaluators/functions/mid.rb +23 -0
  69. data/lib/xls_function/evaluators/functions/minute.rb +15 -0
  70. data/lib/xls_function/evaluators/functions/month.rb +15 -0
  71. data/lib/xls_function/evaluators/functions/not.rb +15 -0
  72. data/lib/xls_function/evaluators/functions/now.rb +19 -0
  73. data/lib/xls_function/evaluators/functions/or.rb +21 -0
  74. data/lib/xls_function/evaluators/functions/power.rb +16 -0
  75. data/lib/xls_function/evaluators/functions/proper.rb +17 -0
  76. data/lib/xls_function/evaluators/functions/replace.rb +19 -0
  77. data/lib/xls_function/evaluators/functions/rept.rb +25 -0
  78. data/lib/xls_function/evaluators/functions/right.rb +16 -0
  79. data/lib/xls_function/evaluators/functions/round.rb +16 -0
  80. data/lib/xls_function/evaluators/functions/round_down.rb +16 -0
  81. data/lib/xls_function/evaluators/functions/round_up.rb +16 -0
  82. data/lib/xls_function/evaluators/functions/second.rb +15 -0
  83. data/lib/xls_function/evaluators/functions/sqrt.rb +17 -0
  84. data/lib/xls_function/evaluators/functions/substitute.rb +44 -0
  85. data/lib/xls_function/evaluators/functions/text.rb +17 -0
  86. data/lib/xls_function/evaluators/functions/time.rb +54 -0
  87. data/lib/xls_function/evaluators/functions/timevalue.rb +17 -0
  88. data/lib/xls_function/evaluators/functions/today.rb +19 -0
  89. data/lib/xls_function/evaluators/functions/trim.rb +16 -0
  90. data/lib/xls_function/evaluators/functions/trunc.rb +16 -0
  91. data/lib/xls_function/evaluators/functions/unichar.rb +19 -0
  92. data/lib/xls_function/evaluators/functions/unicode.rb +18 -0
  93. data/lib/xls_function/evaluators/functions/upper.rb +15 -0
  94. data/lib/xls_function/evaluators/functions/value.rb +26 -0
  95. data/lib/xls_function/evaluators/functions/year.rb +15 -0
  96. data/lib/xls_function/evaluators/number_evaluator.rb +18 -0
  97. data/lib/xls_function/evaluators/string_evaluator.rb +18 -0
  98. data/lib/xls_function/evaluators/true_evaluator.rb +19 -0
  99. data/lib/xls_function/evaluators/variant_evaluator.rb +24 -0
  100. data/lib/xls_function/extensions/array_extension.rb +22 -0
  101. data/lib/xls_function/extensions/big_decimal_extension.rb +15 -0
  102. data/lib/xls_function/extensions/date_extension.rb +11 -0
  103. data/lib/xls_function/extensions/hash_extension.rb +24 -0
  104. data/lib/xls_function/extensions/time_extension.rb +11 -0
  105. data/lib/xls_function/format_string/evaluators/elapsed_time_evaluator.rb +42 -0
  106. data/lib/xls_function/format_string/evaluators/number_evaluator.rb +243 -0
  107. data/lib/xls_function/format_string/evaluators/time_evaluator.rb +103 -0
  108. data/lib/xls_function/format_string/parse_rules/dates.rb +53 -0
  109. data/lib/xls_function/format_string/parse_rules/numbers.rb +31 -0
  110. data/lib/xls_function/format_string/parse_rules/texts.rb +25 -0
  111. data/lib/xls_function/format_string/parse_rules/times.rb +55 -0
  112. data/lib/xls_function/format_string/parser.rb +27 -0
  113. data/lib/xls_function/format_string/transform.rb +87 -0
  114. data/lib/xls_function/format_string/transform_rules/dates.rb +98 -0
  115. data/lib/xls_function/format_string/transform_rules/numbers.rb +59 -0
  116. data/lib/xls_function/format_string/transform_rules/texts.rb +25 -0
  117. data/lib/xls_function/format_string/transform_rules/times.rb +97 -0
  118. data/lib/xls_function/format_string.rb +24 -0
  119. data/lib/xls_function/i18n.rb +4 -0
  120. data/lib/xls_function/locales/en.yml +65 -0
  121. data/lib/xls_function/locales/ja.yml +65 -0
  122. data/lib/xls_function/parse_rules/binary_operation.rb +28 -0
  123. data/lib/xls_function/parse_rules/common.rb +34 -0
  124. data/lib/xls_function/parser.rb +12 -0
  125. data/lib/xls_function/transform.rb +58 -0
  126. data/lib/xls_function/transform_rules/binary_operation_transform.rb +16 -0
  127. data/lib/xls_function/transform_rules/boolean_transform.rb +12 -0
  128. data/lib/xls_function/transform_rules/function_call_transform.rb +16 -0
  129. data/lib/xls_function/transform_rules/number_transform.rb +11 -0
  130. data/lib/xls_function/transform_rules/string_transform.rb +17 -0
  131. data/lib/xls_function/transform_rules/variant_transform.rb +13 -0
  132. data/lib/xls_function/user_defined_function_factory.rb +59 -0
  133. data/lib/xls_function/version.rb +3 -0
  134. data/lib/xls_function.rb +82 -0
  135. data/xls_function.gemspec +30 -0
  136. metadata +221 -0
@@ -0,0 +1,158 @@
1
+ module XlsFunction
2
+ module Converters
3
+ module TimeConverter
4
+ class << self
5
+ def try_convert(time_value)
6
+ [true, convert(time_value)]
7
+ rescue ArgumentError
8
+ [false, invalid_time(time_value)]
9
+ end
10
+
11
+ def invalid_time(time_value)
12
+ I18n.t('xls_function.errors.cannot_convert_to_time', source: time_value)
13
+ end
14
+
15
+ def convert(input)
16
+ case input
17
+ when Time
18
+ input
19
+ when Date
20
+ input.to_time
21
+ when BigDecimal
22
+ NumberConverter.decimal_to_time(input)
23
+ when Numeric
24
+ Time.at(input)
25
+ else
26
+ parse(input)
27
+ end
28
+ end
29
+
30
+ # @param [object] input
31
+ # @param [Hash] cache context
32
+ def convert_with_cache(input, cache)
33
+ cache[:cache_convert_time] ||= {}
34
+ cache[:cache_convert_time][input] ||= convert(input)
35
+ end
36
+
37
+ FORMAT_MAP = {
38
+ 'yyyy' => '%Y',
39
+ 'yy' => '%y',
40
+ 'm' => '%m',
41
+ 'mm' => '%m',
42
+ 'mmm' => '%b',
43
+ 'mmmm' => '%B',
44
+ 'mmmmm' => '%B',
45
+ 'd' => '%d',
46
+ 'dd' => '%d',
47
+ 'aaa' => '%w',
48
+ 'aaaa' => '%w',
49
+ 'ddd' => '%a',
50
+ 'dddd' => '%A',
51
+ 'e' => '%Jg',
52
+ 'ee' => '%Jg',
53
+ 'r' => '%Jg',
54
+ 'g' => '%Je',
55
+ 'gg' => '%Je',
56
+ 'ggg' => '%Je',
57
+ 'hh' => '%H',
58
+ 'h' => '%H',
59
+ 'M' => '%M',
60
+ 'MM' => '%M',
61
+ 's' => '%S',
62
+ 'ss' => '%S',
63
+ '.0' => '%1N',
64
+ '.00' => '%2N',
65
+ '.000' => '%3N'
66
+ }.freeze
67
+
68
+ def convert_format(format, ampm_mode: false)
69
+ mapped = FORMAT_MAP[format]
70
+ mapped = '%I' if mapped == '%H' && ampm_mode
71
+ raise NotImplementedError, "#{format} is not supported" unless mapped
72
+
73
+ mapped
74
+ end
75
+
76
+ WEEKDAYS_JP = %w[日 月 火 水 木 金 土].freeze
77
+
78
+ def convert_weekday_jp(week_index)
79
+ WEEKDAYS_JP[week_index]
80
+ end
81
+
82
+ WAREKI_ALPHABETS = {
83
+ '明治' => 'M',
84
+ '大正' => 'T',
85
+ '昭和' => 'S',
86
+ '平成' => 'H',
87
+ '令和' => 'R'
88
+ }.freeze
89
+
90
+ def convert_wareki_to_alphabet(gengo)
91
+ WAREKI_ALPHABETS[gengo] || ''
92
+ end
93
+
94
+ # Accepts elapsed time expression that Time.parse cannot parse.
95
+ def parse(date, now = Time.now, &block)
96
+ Time.parse(date, now, &block)
97
+ rescue ArgumentError
98
+ result = fix_elapsed_time(date, now)
99
+ raise if result == :throw
100
+
101
+ Time.parse(result, now, &block)
102
+ end
103
+
104
+ def fix_elapsed_time(time_value, now)
105
+ h = Date._parse(time_value)
106
+ return :throw if h.key?(:yday) # give up when yday exists.
107
+ return :throw if !h.key?(:sec) && !h.key?(:min) && !h.key?(:hour) # give up when not elapsed time expression.
108
+
109
+ time_str, elapsed_day = fixed_time_str(h)
110
+ date_str = fixed_date_str(h, now, elapsed_day)
111
+ "#{date_str} #{time_str}"
112
+ end
113
+
114
+ def fixed_time_str(parsed)
115
+ sec = parsed.fetch(:sec, 0)
116
+ min = parsed.fetch(:min, 0)
117
+ hour = parsed.fetch(:hour, 0)
118
+
119
+ adjusted = adjust_elapsed_time(hour, min, sec)
120
+
121
+ [
122
+ "#{adjusted[:hour]}:#{adjusted[:minute]}:#{adjusted[:second]}#{sec_fraction_str(parsed)}#{zone_str(parsed)}",
123
+ adjusted[:day]
124
+ ]
125
+ end
126
+
127
+ def fixed_date_str(parsed, now, elapsed_day)
128
+ year = parsed.fetch(:year, now.year)
129
+ month = parsed.fetch(:mon, now.month)
130
+ day = parsed.fetch(:mday, now.day)
131
+ date = Date.new(year, month, day) + elapsed_day
132
+
133
+ "#{date.year}-#{date.month}-#{date.day}"
134
+ end
135
+
136
+ def sec_fraction_str(parsed)
137
+ return '' unless parsed.key?(:sec_fraction)
138
+
139
+ ".#{(parsed[:sec_fraction] * 1000).to_i.to_s.rjust(3, '0')}"
140
+ end
141
+
142
+ def zone_str(parsed)
143
+ return '' unless parsed.key?(:zone)
144
+
145
+ " #{parsed[:zone]}"
146
+ end
147
+
148
+ def adjust_elapsed_time(hour, minute, second)
149
+ elapsed_minute, s = second.divmod(60)
150
+ elapsed_hour, m = (minute + elapsed_minute).divmod(60)
151
+ elapsed_day, h = (hour + elapsed_hour).divmod(24)
152
+
153
+ { day: elapsed_day, hour: h, minute: m, second: s }
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,97 @@
1
+ module XlsFunction
2
+ module Converters
3
+ module TimeSerialConverter
4
+ H_UNIT = (BigDecimal('1') / 24)
5
+ M_UNIT = (H_UNIT / 60)
6
+ S_UNIT = (M_UNIT / 60)
7
+ MS_UNIT = (S_UNIT / 1000)
8
+
9
+ ORIGIN_TIME = Time.new(1899, 12, 31, 0, 0, 0).freeze
10
+
11
+ class << self
12
+ def time_to_serial(time, except_date: false)
13
+ (except_date ? 0 : DateSerialConverter.date_to_serial(time.to_date)) +
14
+ (
15
+ hour_value_of(time) +
16
+ minute_value_of(time) +
17
+ second_value_of(time) +
18
+ millisecond_value_of(time)
19
+ ).round(15)
20
+ end
21
+
22
+ # @param [BigDecimal] time_serial
23
+ def serial_to_time(time_serial, now = ORIGIN_TIME)
24
+ Time.parse(TimeSerial.new(time_serial).to_s, now.to_time)
25
+ end
26
+
27
+ private
28
+
29
+ def hour_value_of(time)
30
+ time.hour * H_UNIT
31
+ end
32
+
33
+ def minute_value_of(time)
34
+ time.min * M_UNIT
35
+ end
36
+
37
+ def second_value_of(time)
38
+ time.sec * S_UNIT
39
+ end
40
+
41
+ def millisecond_value_of(time)
42
+ time.usec.to_s.rjust(6, '0')[0, 3].to_i * MS_UNIT
43
+ end
44
+ end
45
+
46
+ class TimeSerial
47
+ attr_reader :serial
48
+
49
+ def initialize(serial)
50
+ @serial = serial.frac
51
+ end
52
+
53
+ def hour
54
+ @hour ||= (serial / H_UNIT).round(15).to_i
55
+ end
56
+
57
+ def minute
58
+ @minute ||= (without_hour / M_UNIT).round(15).to_i
59
+ end
60
+
61
+ def second
62
+ @second ||= (without_hour_and_minute / S_UNIT).round(15).to_i
63
+ end
64
+
65
+ def millisecond
66
+ @millisecond ||= (without_hour_and_minute_and_second / MS_UNIT).round(15).to_i
67
+ end
68
+
69
+ def to_s
70
+ "#{pad_zero(&:hour)}:#{pad_zero(&:minute)}:#{pad_zero(&:second)}#{millisecond_suffix}"
71
+ end
72
+
73
+ private
74
+
75
+ def without_hour
76
+ serial - (H_UNIT * hour)
77
+ end
78
+
79
+ def without_hour_and_minute
80
+ without_hour - (M_UNIT * minute)
81
+ end
82
+
83
+ def without_hour_and_minute_and_second
84
+ without_hour_and_minute - (S_UNIT * second)
85
+ end
86
+
87
+ def pad_zero(count = 2, &block)
88
+ block.call(self).to_s.rjust(count, '0')
89
+ end
90
+
91
+ def millisecond_suffix
92
+ millisecond.zero? ? '' : ".#{pad_zero(3, &:millisecond)}"
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,7 @@
1
+ module XlsFunction
2
+ class DefaultLogger
3
+ def write(log)
4
+ pp log
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ module XlsFunction
2
+ # Default Error
3
+ class EvaluationError < StandardError
4
+ end
5
+
6
+ class ErrorValue < String
7
+ attr_reader :error_info
8
+
9
+ def initialize(string = '', error_info = '')
10
+ @error_info = error_info
11
+ super(string)
12
+ end
13
+
14
+ def to_s
15
+ super + error_info
16
+ end
17
+
18
+ def error?
19
+ true
20
+ end
21
+
22
+ class << self
23
+ # @return #VALUE!
24
+ def value!(error_info = '')
25
+ new(ERROR_VALUE, error_info)
26
+ end
27
+
28
+ # @return #NUM!
29
+ def num!(error_info = '')
30
+ new(ERROR_NUM, error_info)
31
+ end
32
+
33
+ # @return #N/A
34
+ def na(error_info = '')
35
+ new(ERROR_NA, error_info)
36
+ end
37
+ end
38
+ end
39
+
40
+ ERROR_VALUE = '#VALUE!'.freeze
41
+ ERROR_NUM = '#NUM!'.freeze
42
+ ERROR_NA = '#N/A'.freeze
43
+
44
+ ERRORS = [
45
+ ERROR_VALUE,
46
+ ERROR_NUM,
47
+ ERROR_NA
48
+ ].freeze
49
+ end
@@ -0,0 +1,39 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module ArgumentsDefinable
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ class << self
7
+ def arg_definitions
8
+ @arg_definitions || []
9
+ end
10
+
11
+ def inherited(subclass)
12
+ super
13
+ subclass.instance_variable_set(:@arg_definitions, arg_definitions.dup)
14
+ end
15
+ end
16
+ end
17
+
18
+ klass.extend(ClassMethods)
19
+ end
20
+
21
+ private
22
+
23
+ def defined_args
24
+ self.class.arg_definitions.map do |name, _default, _type|
25
+ instance_variable_get("@#{name}")
26
+ end
27
+ end
28
+
29
+ module ClassMethods
30
+ def define_arg(name, default: nil, type: nil)
31
+ @arg_definitions ||= []
32
+
33
+ @arg_definitions << [name, default, type]
34
+ attr_reader(name)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ class BinaryOperationEvaluator < FunctionEvaluator
4
+ define_arg :left
5
+ define_arg :right
6
+
7
+ class << self
8
+ alias operator_as register_dictionary
9
+
10
+ def create(left, right, context)
11
+ new(context.merge(arglist: [left, right]))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ Dir[File.expand_path('binary_operations', __dir__) << '/*.rb'].sort.each do |file|
19
+ require file
20
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Add < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '+'
6
+
7
+ def eval
8
+ left + right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Concat < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '&'
6
+
7
+ def eval
8
+ "#{left}#{right}"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Divide < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '/'
6
+
7
+ def eval
8
+ left / right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Equal < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '='
6
+
7
+ def eval
8
+ left == right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class GreaterThan < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '>'
6
+
7
+ def eval
8
+ left > right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class GreaterThanOrEqualTo < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '>='
6
+
7
+ def eval
8
+ left >= right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class LessThan < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '<'
6
+
7
+ def eval
8
+ left < right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class LessThanOrEqualTo < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '<='
6
+
7
+ def eval
8
+ left <= right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Multiple < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '*'
6
+
7
+ def eval
8
+ left * right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class NotEqual < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '<>'
6
+
7
+ def eval
8
+ left != right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Power < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '^'
6
+
7
+ def eval
8
+ left**right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module BinaryOperations
4
+ class Subtract < ::XlsFunction::Evaluators::BinaryOperationEvaluator
5
+ operator_as '-'
6
+
7
+ def eval
8
+ left - right
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module ClassDictionary
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ class << self
7
+ def register_dictionary(key, value = self)
8
+ @register_key = key
9
+ dictionary[key] = value
10
+ end
11
+
12
+ def from_dictionary(key)
13
+ dictionary[key]
14
+ end
15
+
16
+ def description(text)
17
+ @description = text
18
+ end
19
+
20
+ private
21
+
22
+ def dictionary
23
+ XlsFunction.class_dictionary
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module ErrorDetector
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ attr_reader :error_value
7
+ end
8
+ end
9
+
10
+ def rescue_with(error_class)
11
+ yield
12
+ rescue error_class => e
13
+ if XlsFunction.verbose
14
+ XlsFunction.logger.write(e.inspect)
15
+ XlsFunction.logger.write(e.backtrace)
16
+ end
17
+ ::XlsFunction::ErrorValue.value!(class_info(e.message))
18
+ end
19
+
20
+ def class_info(message = '')
21
+ "#{class_name.upcase}:#{message}"
22
+ end
23
+
24
+ def class_name
25
+ self.class.name&.split('::')&.last || 'Class'
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ module Evaluable
4
+ using ::XlsFunction::Extensions::HashExtension
5
+
6
+ def self.included(klass)
7
+ klass.class_eval do
8
+ attr_reader :context
9
+ end
10
+ end
11
+
12
+ def evaluate(runtime_context = nil)
13
+ merge_context(runtime_context) do
14
+ before_eval
15
+ eval
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def merge_context(runtime_context = nil)
22
+ origin_context = context
23
+ @context = runtime_context.deep_merge(context) if runtime_context && runtime_context != context
24
+
25
+ yield
26
+ ensure
27
+ @context = origin_context
28
+ end
29
+
30
+ def before_eval; end
31
+
32
+ def eval
33
+ raise NotImplementedError, "You must implement #{self.class}##{__method__}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module XlsFunction
2
+ module Evaluators
3
+ class FalseEvaluator
4
+ include Evaluable
5
+
6
+ # unused, but hold for future logging...
7
+ attr_reader :source
8
+
9
+ def initialize(source, context)
10
+ @source = source
11
+ @context = context
12
+ end
13
+
14
+ def eval
15
+ false
16
+ end
17
+ end
18
+ end
19
+ end