cel 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cel/checker.rb CHANGED
@@ -31,10 +31,9 @@ module Cel
31
31
  Checker.new(@declarations ? @declarations.merge(declarations) : declarations)
32
32
  end
33
33
 
34
- # TODO: add protobuf timestamp and duration
35
- LOGICAL_EXPECTED_TYPES = %i[bool int uint double string bytes].freeze
36
- ADD_EXPECTED_TYPES = %i[int uint double string bytes list].freeze
37
- SUB_EXPECTED_TYPES = %i[int uint double].freeze
34
+ LOGICAL_EXPECTED_TYPES = %i[bool int uint double string bytes timestamp duration].freeze
35
+ ADD_EXPECTED_TYPES = %i[int uint double string bytes list duration].freeze
36
+ SUB_EXPECTED_TYPES = %i[int uint double duration].freeze
38
37
  MULTIDIV_EXPECTED_TYPES = %i[int uint double].freeze
39
38
  REMAINDER_EXPECTED_TYPES = %i[int uint].freeze
40
39
 
@@ -73,26 +72,48 @@ module Cel
73
72
  else
74
73
 
75
74
  case op
76
- when "&&", "||", "==", "!=", "<", "<=", ">=", ">"
77
- return TYPES[:bool]
75
+ when "&&", "||", "<", "<=", ">=", ">"
76
+ return TYPES[:bool] if find_match_all_types(LOGICAL_EXPECTED_TYPES, values) || values.include?(:any)
77
+ when "!=", "=="
78
+ return TYPES[:bool] if values.uniq.size == 1 ||
79
+ values.all? { |v| v == :list } ||
80
+ values.all? { |v| v == :map } ||
81
+ values.include?(:any)
78
82
  when "in"
79
- return TYPES[:bool] if find_match_all_types(%i[list map], values.last)
83
+ return TYPES[:bool] if find_match_all_types(%i[list map any], values.last)
80
84
  when "+"
81
- if (type = find_match_all_types(ADD_EXPECTED_TYPES, values))
82
- return type
83
- end
85
+ return type if (type = find_match_all_types(ADD_EXPECTED_TYPES, values))
86
+
87
+ return TYPES[:timestamp] if %i[timestamp duration].any? { |typ| values.first == typ }
88
+
89
+ return values.last if values.first == :any
90
+
84
91
  when "-"
85
- if (type = find_match_all_types(SUB_EXPECTED_TYPES, values))
86
- return type
92
+ return type if (type = find_match_all_types(SUB_EXPECTED_TYPES, values))
93
+
94
+ case values.first
95
+ when TYPES[:timestamp]
96
+ return TYPES[:duration] if values.last == :timestamp
97
+
98
+ return TYPES[:timestamp] if values.last == :duration
99
+
100
+ return TYPES[:any] if values.last == :any
101
+
102
+ when TYPES[:any]
103
+ return values.last
87
104
  end
88
105
  when "*", "/"
89
- if (type = find_match_all_types(MULTIDIV_EXPECTED_TYPES, values))
90
- return type
91
- end
106
+ return type if (type = find_match_all_types(MULTIDIV_EXPECTED_TYPES, values))
107
+
108
+ values.include?(:any)
109
+ values.find { |typ| typ != :any } || TYPES[:any]
110
+
92
111
  when "%"
93
- if (type = find_match_all_types(REMAINDER_EXPECTED_TYPES, values))
94
- return type
95
- end
112
+ return type if (type = find_match_all_types(REMAINDER_EXPECTED_TYPES, values))
113
+
114
+ values.include?(:any)
115
+ values.find { |typ| typ != :any } || TYPES[:any]
116
+
96
117
  else
97
118
  unsupported_type(operation)
98
119
  end
@@ -100,6 +121,17 @@ module Cel
100
121
  unsupported_type(operation)
101
122
  end
102
123
 
124
+ def infer_variable_type(var)
125
+ case var
126
+ when Identifier
127
+ check_identifier(var)
128
+ when Invoke
129
+ check_invoke(var)
130
+ else
131
+ var.type
132
+ end
133
+ end
134
+
103
135
  def check_invoke(funcall, var_type = nil)
104
136
  var = funcall.var
105
137
  func = funcall.func
@@ -107,14 +139,7 @@ module Cel
107
139
 
108
140
  return check_standard_func(funcall) unless var
109
141
 
110
- var_type ||= case var
111
- when Identifier
112
- check_identifier(var)
113
- when Invoke
114
- check_invoke(var)
115
- else
116
- var.type
117
- end
142
+ var_type ||= infer_variable_type(var)
118
143
 
119
144
  case var_type
120
145
  when MapType
@@ -153,6 +178,8 @@ module Cel
153
178
 
154
179
  unsupported_type(funcall) unless identifier.is_a?(Identifier)
155
180
 
181
+ identifier.type = var_type.element_type
182
+
156
183
  element_checker = merge(identifier.to_sym => var_type.element_type)
157
184
 
158
185
  unsupported_type(funcall) if element_checker.check(predicate) != :bool
@@ -195,17 +222,38 @@ module Cel
195
222
  unsupported_type(funcall)
196
223
  end
197
224
  unsupported_operation(funcall)
225
+ when TYPES[:timestamp]
226
+ case func
227
+ when :getDate, :getDayOfMonth, :getDayOfWeek, :getDayOfYear, :getFullYear, :getHours,
228
+ :getMilliseconds, :getMinutes, :getMonth, :getSeconds
229
+ check_arity(func, args, 0..1)
230
+ return TYPES[:int] if args.empty? || (args.size.positive? && args[0] == :string)
231
+ else
232
+ unsupported_type(funcall)
233
+ end
234
+ unsupported_operation(funcall)
235
+ when TYPES[:duration]
236
+ case func
237
+ when :getMilliseconds, :getMinutes, :getHours, :getSeconds
238
+ check_arity(func, args, 0)
239
+ return TYPES[:int]
240
+ else
241
+ unsupported_type(funcall)
242
+ end
243
+ unsupported_operation(funcall)
198
244
  else
199
245
  TYPES[:any]
200
246
  end
201
247
  end
202
248
 
203
249
  CAST_ALLOWED_TYPES = {
204
- int: %i[uint double string], # TODO: enum, timestamp
250
+ int: %i[uint double string timestamp], # TODO: enum
205
251
  uint: %i[int double string],
206
- string: %i[int uint double bytes], # TODO: timestamp, duration
252
+ string: %i[int uint double bytes timestamp duration],
207
253
  double: %i[int uint string],
208
254
  bytes: %i[string],
255
+ duration: %i[string],
256
+ timestamp: %i[string],
209
257
  }.freeze
210
258
 
211
259
  def check_standard_func(funcall)
@@ -223,15 +271,18 @@ module Cel
223
271
  return TYPES[:bool]
224
272
  when :size
225
273
  check_arity(func, args, 1)
226
- return TYPES[:int] if find_match_all_types(%i[string bytes list map], call(args.first))
227
- when :int, :uint, :string, :double, :bytes # :duration, :timestamp
274
+
275
+ arg = call(args.first)
276
+ return TYPES[:int] if find_match_all_types(%i[string bytes list map], arg)
277
+ when *CAST_ALLOWED_TYPES.keys
228
278
  check_arity(func, args, 1)
229
279
  allowed_types = CAST_ALLOWED_TYPES[func]
230
280
 
231
- return TYPES[func] if find_match_all_types(allowed_types, call(args.first))
281
+ arg = call(args.first)
282
+ return TYPES[func] if find_match_all_types(allowed_types, arg)
232
283
  when :matches
233
284
  check_arity(func, args, 2)
234
- return TYPES[:bool] if find_match_all_types(%i[string], args.map { |arg| call(arg) })
285
+ return TYPES[:bool] if find_match_all_types(%i[string], args.map(&method(:call)))
235
286
  when :dyn
236
287
  check_arity(func, args, 1)
237
288
  arg_type = call(args.first)
@@ -241,14 +292,37 @@ module Cel
241
292
  end
242
293
  return arg_type
243
294
  else
295
+ return check_custom_func(@declarations[func], funcall) if @declarations.key?(func)
296
+
244
297
  unsupported_type(funcall)
245
298
  end
246
299
 
247
300
  unsupported_operation(funcall)
248
301
  end
249
302
 
303
+ def check_custom_func(func, funcall)
304
+ args = funcall.args
305
+
306
+ unless func.is_a?(Cel::Function)
307
+ raise CheckError, "#{func} must respond to #call" unless func.respond_to?(:call)
308
+
309
+ func = Cel::Function(&func)
310
+ end
311
+
312
+ unless func.types.empty?
313
+ unsupported_type(funcall) unless func.types.zip(args.map(&method(:call)))
314
+ .all? do |expected_type, type|
315
+ expected_type == :any || expected_type == type
316
+ end
317
+
318
+ return func.type
319
+ end
320
+
321
+ unsupported_operation(funcall)
322
+ end
323
+
250
324
  def check_identifier(identifier)
251
- return unless identifier.type == :any
325
+ return identifier.type unless identifier.type == :any
252
326
 
253
327
  return TYPES[:type] if Cel::PRIMITIVE_TYPES.include?(identifier.to_sym)
254
328
 
@@ -262,6 +336,10 @@ module Cel
262
336
  end
263
337
 
264
338
  def check_condition(condition)
339
+ if_type = call(condition.if)
340
+
341
+ raise CheckError, "`#{condition.if}` must evaluate to a bool" unless if_type == :bool
342
+
265
343
  then_type = call(condition.then)
266
344
  else_type = call(condition.else)
267
345
 
@@ -286,7 +364,7 @@ module Cel
286
364
  case typ
287
365
  when Symbol
288
366
  TYPES[typ] or
289
- raise CheckError, "#{typ} is not aa valid type"
367
+ raise CheckError, "#{typ} is not a valid type"
290
368
  else
291
369
  typ
292
370
  end
@@ -307,7 +385,7 @@ module Cel
307
385
  end
308
386
 
309
387
  def check_arity(func, args, arity)
310
- return if args.size == arity
388
+ return if arity === args.size # rubocop:disable Style/CaseEquality
311
389
 
312
390
  raise CheckError, "`#{func}` invoked with wrong number of arguments (should be #{arity})"
313
391
  end
data/lib/cel/context.rb CHANGED
@@ -2,13 +2,18 @@
2
2
 
3
3
  module Cel
4
4
  class Context
5
- def initialize(bindings)
5
+ attr_reader :declarations
6
+
7
+ def initialize(declarations, bindings)
8
+ @declarations = declarations
6
9
  @bindings = bindings.dup
7
10
 
8
11
  return unless @bindings
9
12
 
10
13
  @bindings.each do |k, v|
11
- @bindings[k] = to_cel_type(v)
14
+ val = to_cel_type(v)
15
+ val = TYPES[@declarations[k]].cast(val) if @declarations && @declarations.key?(k)
16
+ @bindings[k] = val
12
17
  end
13
18
  end
14
19
 
@@ -24,7 +29,7 @@ module Cel
24
29
  end
25
30
 
26
31
  def merge(bindings)
27
- Context.new(@bindings ? @bindings.merge(bindings) : bindings)
32
+ Context.new(@declarations, @bindings ? @bindings.merge(bindings) : bindings)
28
33
  end
29
34
 
30
35
  private
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cel
4
+ module Encoder
5
+ module_function
6
+
7
+ def encode(expr)
8
+ case expr
9
+ when Group
10
+ ["group", encode(expr.value)]
11
+ when Invoke
12
+ enc = [
13
+ "inv",
14
+ (encode(expr.var) if expr.var),
15
+ expr.func.to_s,
16
+ *(if expr.args
17
+ expr.func == :[] ? [encode(expr.args)] : expr.args.map(&method(:encode))
18
+ end),
19
+ ]
20
+ enc.compact!
21
+ enc
22
+ when Operation
23
+ [
24
+ "op",
25
+ expr.op.to_s,
26
+ *expr.operands.map(&method(:encode)),
27
+ ]
28
+ when Condition
29
+ [
30
+ "cond",
31
+ encode(expr.if),
32
+ encode(expr.then),
33
+ encode(expr.else),
34
+ ]
35
+ when Identifier
36
+ [
37
+ "id",
38
+ expr.type.to_s,
39
+ expr.id.to_s,
40
+ ]
41
+ when List
42
+ ["lit",
43
+ expr.type.to_s,
44
+ *expr.value.map(&method(:encode))]
45
+ when Map
46
+ ["lit",
47
+ expr.type.to_s,
48
+ *expr.value.map { |kv| kv.map(&method(:encode)) }]
49
+ when Number, Bool, String, Bytes
50
+ ["lit", expr.type.to_s, expr.value]
51
+ when Null
52
+ %w[lit null]
53
+ when Type
54
+ ["lit", "type", expr.to_s]
55
+ end
56
+ end
57
+
58
+ def decode(enc)
59
+ case enc
60
+ in ["group", stmt]
61
+ Group.new(decode(stmt))
62
+ in ["inv", var, ::String => func, *args]
63
+ args = if func == "[]" && args.size == 1
64
+ decode(args.first)
65
+ elsif args.empty?
66
+ nil
67
+ else
68
+ args.map(&method(:decode))
69
+ end
70
+ Invoke.new(func: func, var: decode(var), args: args)
71
+ in ["inv", ::String => func, *args]
72
+ args = nil if args.empty?
73
+ Invoke.new(func: func, args: args.map(&method(:decode)))
74
+ in ["op", ::String => op, *args]
75
+ Operation.new(op, args.map(&method(:decode)))
76
+ in ["cond", f, th, el]
77
+ Condition.new(decode(f), decode(th), decode(el))
78
+ in ["id", ::String => type, ::String => val]
79
+ id = Identifier.new(val)
80
+ id.type = TYPES[type.to_sym]
81
+ id
82
+ in ["lit", "list", *items]
83
+ list = List.new(items.map(&method(:decode)))
84
+ list
85
+ in ["lit", "map", items]
86
+ Map.new(items.map(&method(:decode)).each_slice(2))
87
+ in ["lit", /\Aint|uint|double\z/ => type, Integer => val]
88
+ Number.new(type.to_sym, val)
89
+ in ["lit", "bool", val]
90
+ Bool.new(val)
91
+ in ["lit", "string", val]
92
+ String.new(val)
93
+ in ["lit", "bytes", val]
94
+ Bytes.new(val)
95
+ in ["lit", "null"]
96
+ Null.new
97
+ in ["lit", "type", type]
98
+ TYPES[type.to_sym]
99
+ end
100
+ end
101
+ end
102
+ end
@@ -14,19 +14,31 @@ module Cel
14
14
  ast
15
15
  end
16
16
 
17
+ def encode(expr)
18
+ Encoder.encode(compile(expr))
19
+ end
20
+
21
+ def decode(encoded_expr)
22
+ ast = Encoder.decode(encoded_expr)
23
+ @checker.check(ast)
24
+ ast
25
+ end
26
+
17
27
  def check(expr)
18
28
  ast = @parser.parse(expr)
19
29
  @checker.check(ast)
20
30
  end
21
31
 
22
32
  def program(expr)
23
- expr = compile(expr) if expr.is_a?(::String)
24
- Runner.new(expr)
33
+ expr = @parser.parse(expr) if expr.is_a?(::String)
34
+ @checker.check(expr)
35
+ Runner.new(@declarations, expr)
25
36
  end
26
37
 
27
38
  def evaluate(expr, bindings = nil)
28
- context = Context.new(bindings)
29
- expr = compile(expr) if expr.is_a?(::String)
39
+ context = Context.new(@declarations, bindings)
40
+ expr = @parser.parse(expr) if expr.is_a?(::String)
41
+ @checker.check(expr)
30
42
  Program.new(context).evaluate(expr)
31
43
  end
32
44
 
@@ -36,12 +48,13 @@ module Cel
36
48
  end
37
49
 
38
50
  class Runner
39
- def initialize(ast)
51
+ def initialize(declarations, ast)
52
+ @declarations = declarations
40
53
  @ast = ast
41
54
  end
42
55
 
43
56
  def evaluate(bindings = nil)
44
- context = Context.new(bindings)
57
+ context = Context.new(@declarations, bindings)
45
58
  Program.new(context).evaluate(@ast)
46
59
  end
47
60
  end
data/lib/cel/parser.rb CHANGED
@@ -63,9 +63,18 @@ def parse(str)
63
63
  tokenize(str)
64
64
  do_parse
65
65
  rescue Racc::ParseError => err
66
- ex = Cel::ParseError.new(err.message)
67
- ex.set_backtrace(err.backtrace)
68
- raise ex
66
+ raise parse_error(err)
67
+ end
68
+
69
+ def parse_error(error)
70
+ parse_error = case error.message
71
+ when /parse error on value "([^"]+)" \(tRESERVED\)/
72
+ Cel::ParseError.new("invalid usage of the reserved word \"#{$1}\"")
73
+ else
74
+ Cel::ParseError.new(error.message)
75
+ end
76
+ parse_error.set_backtrace(error.backtrace)
77
+ parse_error
69
78
  end
70
79
 
71
80
  def tokenize(str)
@@ -83,10 +92,6 @@ def tokenize(str)
83
92
  # skip comment lines
84
93
  when scanner.scan(NUMBER_REGEX)
85
94
  @q << convert_to_number(scanner)
86
- when scanner.scan(/true|false/)
87
- @q << [:tBOOL, scanner.matched == "true"]
88
- when scanner.scan(/null/)
89
- @q << [:tNULL, nil]
90
95
  when scanner.scan(/[bB]?[rR]?#{STRING_LIT_REGEX}/) # string
91
96
  # s = scanner.matched.yield_self {|s| s[1, s.length - 2] }
92
97
  # .gsub(DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE) do |match|
@@ -115,7 +120,13 @@ def tokenize(str)
115
120
  end
116
121
  when scanner.scan(IDENTIFIER_REGEX)
117
122
  word = scanner.matched
118
- if RESERVED.include?(word)
123
+ if word == "null"
124
+ @q << [:tNULL, nil]
125
+ elsif word == "true"
126
+ @q << [:tBOOL, true]
127
+ elsif word == "false"
128
+ @q << [:tBOOL, false]
129
+ elsif RESERVED.include?(word)
119
130
  @q << [:tRESERVED, scanner.matched]
120
131
  elsif word == "in"
121
132
  @q << [OPERATORS[scanner.matched], scanner.matched]
@@ -470,7 +481,7 @@ racc_reduce_table = [
470
481
  1, 49, :_reduce_42,
471
482
  0, 45, :_reduce_43,
472
483
  1, 45, :_reduce_none,
473
- 5, 51, :_reduce_none,
484
+ 5, 51, :_reduce_45,
474
485
  3, 51, :_reduce_46,
475
486
  5, 50, :_reduce_47,
476
487
  3, 50, :_reduce_48,
@@ -738,7 +749,7 @@ module_eval(<<'.,.,', 'parser.ry', 54)
738
749
 
739
750
  module_eval(<<'.,.,', 'parser.ry', 55)
740
751
  def _reduce_30(val, _values, result)
741
- result = Cel::Invoke.new(func: val[0], args: [val[2]].flatten(1))
752
+ result = Cel::Invoke.new(func: val[0], args: [val[2]].flatten(1))
742
753
  result
743
754
  end
744
755
  .,.,
@@ -774,7 +785,7 @@ module_eval(<<'.,.,', 'parser.ry', 58)
774
785
 
775
786
  module_eval(<<'.,.,', 'parser.ry', 65)
776
787
  def _reduce_38(val, _values, result)
777
- result = nil
788
+ result = []
778
789
  result
779
790
  end
780
791
  .,.,
@@ -811,7 +822,12 @@ module_eval(<<'.,.,', 'parser.ry', 73)
811
822
 
812
823
  # reduce 44 omitted
813
824
 
814
- # reduce 45 omitted
825
+ module_eval(<<'.,.,', 'parser.ry', 76)
826
+ def _reduce_45(val, _values, result)
827
+ result = val[0].merge(Cel::Identifier.new(val[2]) => val[4])
828
+ result
829
+ end
830
+ .,.,
815
831
 
816
832
  module_eval(<<'.,.,', 'parser.ry', 77)
817
833
  def _reduce_46(val, _values, result)
data/lib/cel/program.rb CHANGED
@@ -40,7 +40,7 @@ module Cel
40
40
  def evaluate_literal(val)
41
41
  case val
42
42
  when List
43
- List.new(val.value.map { |y| call(y) })
43
+ List.new(val.value.map(&method(:call)))
44
44
  else
45
45
  val
46
46
  end
@@ -110,6 +110,10 @@ module Cel
110
110
  args ?
111
111
  var.public_send(func, *args) :
112
112
  var.public_send(func)
113
+ when Timestamp, Duration
114
+ raise EvaluateError, "#{invoke} is not supported" unless var.class.method_defined?(func, false)
115
+
116
+ var.public_send(func, *args)
113
117
  else
114
118
  raise EvaluateError, "#{invoke} is not supported"
115
119
  end
@@ -133,15 +137,23 @@ module Cel
133
137
  when :has, :size
134
138
  Macro.__send__(func, *args)
135
139
  when :matches
136
- Macro.__send__(func, *args.map { |arg| call(arg) })
137
- when :int, :uint, :string, :double, :bytes # :duration, :timestamp
140
+ Macro.__send__(func, *args.map(&method(:call)))
141
+ when :int, :uint, :string, :double, :bytes, :duration, :timestamp
138
142
  type = TYPES[func]
139
143
  type.cast(call(args.first))
140
144
  when :dyn
141
145
  call(args.first)
142
146
  else
147
+ return evaluate_custom_func(@context.declarations[func], funcall) if @context.declarations.key?(func)
148
+
143
149
  raise EvaluateError, "#{funcall} is not supported"
144
150
  end
145
151
  end
152
+
153
+ def evaluate_custom_func(func, funcall)
154
+ args = funcall.args
155
+
156
+ func.call(*args.map(&method(:call)))
157
+ end
146
158
  end
147
159
  end
data/lib/cel/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cel
4
4
  module Ruby
5
- VERSION = "0.1.2"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
data/lib/cel.rb CHANGED
@@ -7,16 +7,11 @@ require "cel/ast/types"
7
7
  require "cel/parser"
8
8
  require "cel/macro"
9
9
  require "cel/context"
10
+ require "cel/encoder" if RUBY_VERSION >= "3.1.0"
10
11
  require "cel/checker"
11
12
  require "cel/program"
12
13
  require "cel/environment"
13
14
 
14
- begin
15
- require "google/protobuf/well_known_types"
16
- require "cel/protobuf"
17
- rescue LoadError # rubocop:disable Lint/SuppressedException
18
- end
19
-
20
15
  module Cel
21
16
  def self.to_numeric(anything)
22
17
  num = BigDecimal(anything.to_s)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-10 00:00:00.000000000 Z
11
+ date: 2023-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tzinfo
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: Pure Ruby implementation of Google Common Expression Language, https://opensource.google/projects/cel.
28
42
  email:
29
43
  - cardoso_tiago@hotmail.com
@@ -39,15 +53,16 @@ files:
39
53
  - README.md
40
54
  - lib/cel.rb
41
55
  - lib/cel/ast/elements.rb
56
+ - lib/cel/ast/elements/protobuf.rb
42
57
  - lib/cel/ast/types.rb
43
58
  - lib/cel/checker.rb
44
59
  - lib/cel/context.rb
60
+ - lib/cel/encoder.rb
45
61
  - lib/cel/environment.rb
46
62
  - lib/cel/errors.rb
47
63
  - lib/cel/macro.rb
48
64
  - lib/cel/parser.rb
49
65
  - lib/cel/program.rb
50
- - lib/cel/protobuf.rb
51
66
  - lib/cel/version.rb
52
67
  homepage:
53
68
  licenses: