code-ruby 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d84bcfcb9ae6cbd546334c89b2aefd5a0b70bf4da537d0fe646c5f2a8030c4a3
4
- data.tar.gz: d9894a0ee1a9c80fa1744b4b29c3b8065c6dedd310558d0f4210f252f5f330a2
3
+ metadata.gz: efd32092c4583410121731e5e6a0300001ef215812e690b0a3fe3c280f0cf84e
4
+ data.tar.gz: b7a88bce4d570b5c9156e79fe5a684f8e945a18faca8a3ecfb242b8ca720d96f
5
5
  SHA512:
6
- metadata.gz: f18605e6c94eccb892d45d09dddb06cf4f5fba5f2f1f30df077687812424ea97c0fde6c3c53f80bc075dfc362864307d17ef354ed5f45997c9ccc42faeb44658
7
- data.tar.gz: 1333842f223896c4bff55a2359034420631680bfe6d2563458b1dc6546e95e7c1d50b42b577396866f3770592bc574b616aaf48d32acda843d80997a4179bb09
6
+ metadata.gz: 2d047f84b6ddb2ac77b8154692089eea38f02a6e4d8b7a46b2e2334594d9a00178dcdfa4b649c82267178c7a681ccd3874685b19c5a8c531c7fb72b7ce5e3189
7
+ data.tar.gz: df9dd8a546339658b3efa419685559981b20aba4b3e7a48e52a580cae0dabc7e19e5691efabdd4591f89ed0525358b557947cf0a744eee52d59297722ef059a2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- code-ruby (0.7.6)
4
+ code-ruby (0.7.8)
5
5
  activesupport (~> 7)
6
6
  bigdecimal (~> 3)
7
7
  language-ruby (~> 0)
@@ -9,6 +9,18 @@ class Code
9
9
  @raw = raw
10
10
  end
11
11
 
12
+ def call(...)
13
+ raw.call(...)
14
+ end
15
+
16
+ def to_s
17
+ raw.name
18
+ end
19
+
20
+ def inspect
21
+ to_s
22
+ end
23
+
12
24
  def self.name
13
25
  "Class"
14
26
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ class Object
5
+ class Date < Object
6
+ attr_reader :raw
7
+
8
+ def initialize(date)
9
+ @raw = date
10
+ end
11
+
12
+ def self.name
13
+ "Date"
14
+ end
15
+
16
+ def self.call(**args)
17
+ operator = args.fetch(:operator, nil)
18
+
19
+ case operator.to_s
20
+ when "tomorrow"
21
+ sig(args)
22
+ code_tomorrow
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def self.code_tomorrow
29
+ ::Time.zone ||= Time::DEFAULT_ZONE
30
+ new(::Time.zone.tomorrow)
31
+ end
32
+
33
+ def inspect
34
+ to_s
35
+ end
36
+
37
+ def to_s
38
+ raw.to_s
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/numeric/time"
4
-
5
3
  class Code
6
4
  class Object
7
5
  class Duration < Object
@@ -22,6 +22,9 @@ class Code
22
22
  when "Class"
23
23
  sig(args) { Object.maybe }
24
24
  value ? value.code_to_class : Class.new(Class)
25
+ when "Date"
26
+ sig(args) { Object.maybe }
27
+ value ? value.code_to_date : Class.new(Date)
25
28
  when "Decimal"
26
29
  sig(args) { Object.maybe }
27
30
  value ? value.code_to_decimal : Class.new(Decimal)
@@ -55,6 +58,9 @@ class Code
55
58
  when "String"
56
59
  sig(args) { Object.maybe }
57
60
  value ? value.code_to_string : Class.new(String)
61
+ when "Time"
62
+ sig(args) { Object.maybe }
63
+ value ? value.code_to_time : Class.new(Time)
58
64
  when "context"
59
65
  sig(args) { String.maybe }
60
66
  value ? context.code_get(value) || Nothing.new : context
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/numeric/time"
4
-
5
3
  class Code
6
4
  class Object
7
5
  class Integer < Number
@@ -3,6 +3,8 @@
3
3
  class Code
4
4
  class Object
5
5
  class Time < Object
6
+ DEFAULT_ZONE = "Etc/UTC"
7
+
6
8
  attr_reader :raw
7
9
 
8
10
  def initialize(time)
@@ -13,6 +15,23 @@ class Code
13
15
  "Time"
14
16
  end
15
17
 
18
+ def self.call(**args)
19
+ operator = args.fetch(:operator, nil)
20
+
21
+ case operator.to_s
22
+ when "tomorrow"
23
+ sig(args)
24
+ code_tomorrow
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ def self.code_tomorrow
31
+ ::Time.zone ||= DEFAULT_ZONE
32
+ new(::Time.zone.tomorrow.beginning_of_day)
33
+ end
34
+
16
35
  def inspect
17
36
  to_s
18
37
  end
data/lib/code/object.rb CHANGED
@@ -18,6 +18,151 @@ class Code
18
18
  Type::Or.new(self, other)
19
19
  end
20
20
 
21
+ def self.sig(args, &block)
22
+ Type::Sig.sig(args, object: self, &block)
23
+ end
24
+
25
+ def self.call(**args)
26
+ operator = args.fetch(:operator, nil)
27
+ arguments = args.fetch(:arguments, [])
28
+ value = arguments.first&.value
29
+
30
+ case operator.to_s
31
+ when "!", "not"
32
+ sig(args)
33
+ code_exclamation_point
34
+ when "!=", "different"
35
+ sig(args) { Object }
36
+ code_different(value)
37
+ when "&&", "and"
38
+ sig(args) { Object }
39
+ code_and_operator(value)
40
+ when "+", "self"
41
+ sig(args)
42
+ code_self
43
+ when "..", "inclusive_range"
44
+ sig(args) { Object }
45
+ code_inclusive_range(value)
46
+ when "...", "exclusive_range"
47
+ sig(args) { Object }
48
+ code_exclusive_range(value)
49
+ when "==", "equal"
50
+ sig(args) { Object }
51
+ code_equal_equal(value)
52
+ when "===", "strict_equal"
53
+ sig(args) { Object }
54
+ code_equal_equal_equal(value)
55
+ when "falsy?"
56
+ sig(args)
57
+ Boolean.new(falsy?)
58
+ when "to_string"
59
+ sig(args)
60
+ code_to_string
61
+ when "truthy?"
62
+ sig(args)
63
+ Boolean.new(truthy?)
64
+ when "||", "or"
65
+ sig(args) { Object }
66
+ code_or_operator(value)
67
+ when /=$/
68
+ sig(args) { Object }
69
+
70
+ if operator == "="
71
+ context = args[:context]
72
+ context.code_set(self, value)
73
+ else
74
+ context = args[:context].lookup!(self)
75
+ context.code_set(
76
+ self,
77
+ context.code_fetch(self).call(
78
+ **args,
79
+ operator: operator[..-2],
80
+ arguments: [Argument.new(value)]
81
+ )
82
+ )
83
+ end
84
+
85
+ context.code_fetch(self)
86
+ else
87
+ raise(
88
+ Code::Error::Undefined,
89
+ "#{operator} not defined on #{inspect}:#{name}"
90
+ )
91
+ end
92
+ end
93
+
94
+ def self.code_and_operator(other)
95
+ truthy? ? other : self
96
+ end
97
+
98
+ def self.code_different(other)
99
+ Boolean.new(self != other)
100
+ end
101
+
102
+ def self.code_equal_equal(other)
103
+ Boolean.new(self == other)
104
+ end
105
+
106
+ def self.code_exclamation_point
107
+ Boolean.new(falsy?)
108
+ end
109
+
110
+ def self.code_exclusive_range(value)
111
+ Range.new(self, value, exclude_end: true)
112
+ end
113
+
114
+ def self.code_inclusive_range(value)
115
+ Range.new(self, value, exclude_end: false)
116
+ end
117
+
118
+ def self.code_or_operator(other)
119
+ truthy? ? self : other
120
+ end
121
+
122
+ def self.code_self
123
+ self
124
+ end
125
+
126
+ def self.code_equal_equal_equal(other)
127
+ Boolean.new(self === other)
128
+ end
129
+
130
+ def self.code_to_string
131
+ String.new(to_s)
132
+ end
133
+
134
+ def self.falsy?
135
+ !truthy?
136
+ end
137
+
138
+ def self.hash
139
+ unless respond_to?(:raw)
140
+ raise NotImplementedError, "#{self.class.name}#hash"
141
+ end
142
+
143
+ [self.class, raw].hash
144
+ end
145
+
146
+ def self.multi_fetch(hash, *keys)
147
+ keys.map { |key| [key, hash.fetch(key)] }.to_h
148
+ end
149
+
150
+ def self.sig(args, &block)
151
+ Type::Sig.sig(args, object: self, &block)
152
+ end
153
+
154
+ def self.name
155
+ raise NotImplementedError, "name"
156
+ end
157
+
158
+ def self.to_s
159
+ name
160
+ end
161
+
162
+ def self.truthy?
163
+ true
164
+ end
165
+
21
166
  def <=>(other)
22
167
  if respond_to?(:raw)
23
168
  raw <=> (other.respond_to?(:raw) ? other.raw : other)
@@ -117,7 +262,7 @@ class Code
117
262
  end
118
263
 
119
264
  def code_exclamation_point
120
- truthy? ? Object::Boolean.new(false) : Object::Boolean.new(true)
265
+ Boolean.new(falsy?)
121
266
  end
122
267
 
123
268
  def code_exclusive_range(value)
data/lib/code/version.rb CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require_relative "../code"
4
4
 
5
- Code::Version = Gem::Version.new("0.7.7")
5
+ Code::Version = Gem::Version.new("0.8.0")
data/lib/code-ruby.rb CHANGED
@@ -6,6 +6,8 @@ require "timeout"
6
6
  require "zeitwerk"
7
7
  require "language-ruby"
8
8
  require "active_support"
9
+ require "active_support/core_ext/numeric/time"
10
+ require "active_support/core_ext/date/conversions"
9
11
 
10
12
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
11
13
  loader.ignore("#{__dir__}/code-ruby.rb")
data/spec/code_spec.rb CHANGED
@@ -190,7 +190,11 @@ RSpec.describe Code do
190
190
  ).to eq(Code.evaluate("[:Hello]"))
191
191
  end
192
192
 
193
- it "works with time" do
194
- Code.evaluate("1.hour.from_now")
193
+ [
194
+ "1.hour.from_now",
195
+ "Time.tomorrow",
196
+ "Date.tomorrow"
197
+ ].each do |input|
198
+ it(input) { Code.evaluate(input) }
195
199
  end
196
200
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.7
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-12 00:00:00.000000000 Z
11
+ date: 2024-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -118,6 +118,7 @@ files:
118
118
  - lib/code/object/boolean.rb
119
119
  - lib/code/object/class.rb
120
120
  - lib/code/object/context.rb
121
+ - lib/code/object/date.rb
121
122
  - lib/code/object/decimal.rb
122
123
  - lib/code/object/dictionary.rb
123
124
  - lib/code/object/duration.rb