xls_function 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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