code-ruby 1.1.1 → 1.2.1
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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +13 -13
- data/.github/workflows/ci.yml +25 -24
- data/.npm-version +1 -0
- data/.rubocop.yml +14 -11
- data/Gemfile +5 -4
- data/Gemfile.lock +134 -28
- data/VERSION +1 -1
- data/bin/console +6 -0
- data/bin/dorian +31 -0
- data/code-ruby.gemspec +6 -1
- data/lib/code/error.rb +4 -25
- data/lib/code/node/code.rb +1 -1
- data/lib/code/node/function_parameter.rb +10 -8
- data/lib/code/node/while.rb +1 -1
- data/lib/code/object/boolean.rb +20 -16
- data/lib/code/object/class.rb +10 -4
- data/lib/code/object/code.rb +7 -3
- data/lib/code/object/context.rb +8 -8
- data/lib/code/object/date.rb +41 -7
- data/lib/code/object/decimal.rb +101 -56
- data/lib/code/object/dictionary.rb +245 -191
- data/lib/code/object/duration.rb +11 -7
- data/lib/code/object/function.rb +38 -25
- data/lib/code/object/global.rb +95 -42
- data/lib/code/object/html.rb +12 -14
- data/lib/code/object/http.rb +219 -0
- data/lib/code/object/identifier_list.rb +16 -16
- data/lib/code/object/integer.rb +129 -89
- data/lib/code/object/json.rb +18 -22
- data/lib/code/object/list.rb +141 -92
- data/lib/code/object/parameter.rb +9 -13
- data/lib/code/object/range.rb +77 -45
- data/lib/code/object/string.rb +15 -34
- data/lib/code/object/time.rb +17 -16
- data/lib/code/object.rb +126 -93
- data/lib/code/parser/string.rb +2 -1
- data/lib/code/type/sig.rb +3 -3
- data/lib/code-ruby.rb +119 -0
- data/package-lock.json +1 -1
- data/package.json +1 -1
- data/spec/code/object/http_spec.rb +91 -0
- data/spec/code/type_spec.rb +1 -1
- data/spec/code_spec.rb +10 -5
- data/spec/spec_helper.rb +18 -0
- metadata +50 -3
data/lib/code/object.rb
CHANGED
@@ -2,8 +2,20 @@
|
|
2
2
|
|
3
3
|
class Code
|
4
4
|
class Object
|
5
|
+
NUMBER_CLASSES = [
|
6
|
+
Integer,
|
7
|
+
Decimal,
|
8
|
+
String,
|
9
|
+
::Integer,
|
10
|
+
::Float,
|
11
|
+
::String,
|
12
|
+
::BigDecimal
|
13
|
+
].freeze
|
14
|
+
|
5
15
|
attr_reader :raw
|
6
16
|
|
17
|
+
delegate :to_s, :inspect, to: :raw
|
18
|
+
|
7
19
|
def initialize(...)
|
8
20
|
end
|
9
21
|
|
@@ -28,38 +40,38 @@ class Code
|
|
28
40
|
end
|
29
41
|
|
30
42
|
def self.call(**args)
|
31
|
-
|
32
|
-
|
33
|
-
|
43
|
+
code_operator = args.fetch(:operator, nil).to_code
|
44
|
+
code_arguments = args.fetch(:arguments, []).to_code
|
45
|
+
code_value = code_arguments.code_first
|
34
46
|
|
35
|
-
case
|
47
|
+
case code_operator.to_s
|
36
48
|
when "new"
|
37
49
|
sig(args) { Object.repeat }
|
38
|
-
code_new(*
|
50
|
+
code_new(*code_arguments.raw)
|
39
51
|
when "!", "not"
|
40
52
|
sig(args)
|
41
53
|
code_exclamation_point
|
42
54
|
when "!=", "different"
|
43
55
|
sig(args) { Object }
|
44
|
-
code_different(
|
56
|
+
code_different(code_value)
|
45
57
|
when "&&", "and"
|
46
58
|
sig(args) { Object }
|
47
|
-
code_and_operator(
|
59
|
+
code_and_operator(code_value)
|
48
60
|
when "+", "self"
|
49
61
|
sig(args)
|
50
62
|
code_self
|
51
63
|
when "..", "inclusive_range"
|
52
64
|
sig(args) { Object }
|
53
|
-
code_inclusive_range(
|
65
|
+
code_inclusive_range(code_value)
|
54
66
|
when "...", "exclusive_range"
|
55
67
|
sig(args) { Object }
|
56
|
-
code_exclusive_range(
|
68
|
+
code_exclusive_range(code_value)
|
57
69
|
when "==", "equal"
|
58
70
|
sig(args) { Object }
|
59
|
-
code_equal_equal(
|
71
|
+
code_equal_equal(code_value)
|
60
72
|
when "===", "strict_equal"
|
61
73
|
sig(args) { Object }
|
62
|
-
code_equal_equal_equal(
|
74
|
+
code_equal_equal_equal(code_value)
|
63
75
|
when "falsy?"
|
64
76
|
sig(args)
|
65
77
|
Boolean.new(falsy?)
|
@@ -68,7 +80,7 @@ class Code
|
|
68
80
|
Boolean.new(truthy?)
|
69
81
|
when "||", "or"
|
70
82
|
sig(args) { Object }
|
71
|
-
code_or_operator(
|
83
|
+
code_or_operator(code_value)
|
72
84
|
when "to_boolean"
|
73
85
|
sig(args)
|
74
86
|
Boolean.new(self)
|
@@ -104,58 +116,64 @@ class Code
|
|
104
116
|
String.new(self)
|
105
117
|
when "to_time"
|
106
118
|
sig(args)
|
107
|
-
Time.
|
119
|
+
Time.new(self)
|
108
120
|
when "as_json"
|
109
121
|
sig(args)
|
110
122
|
code_as_json
|
111
123
|
when "to_json"
|
112
124
|
sig(args) { { pretty: Boolean.maybe } }
|
113
|
-
|
114
|
-
|
125
|
+
|
126
|
+
if code_arguments.any?
|
127
|
+
code_to_json(pretty: code_value.code_get(:pretty))
|
115
128
|
else
|
116
129
|
code_to_json
|
117
130
|
end
|
118
131
|
when /=$/
|
119
132
|
sig(args) { Object }
|
120
133
|
|
121
|
-
if
|
122
|
-
|
123
|
-
|
134
|
+
if code_operator.to_s == "="
|
135
|
+
code_context = args.fetch(:context)
|
136
|
+
code_context.code_set(self, value)
|
124
137
|
else
|
125
|
-
|
126
|
-
|
138
|
+
code_context = args.fetch(:context).code_lookup!(self)
|
139
|
+
code_context.code_set(
|
127
140
|
self,
|
128
|
-
|
141
|
+
code_context.code_fetch(self).call(
|
129
142
|
**args,
|
130
|
-
operator: operator.chop,
|
131
|
-
arguments: List.new([
|
143
|
+
operator: operator.to_s.chop,
|
144
|
+
arguments: List.new([code_value])
|
132
145
|
)
|
133
146
|
)
|
134
147
|
end
|
135
148
|
|
136
149
|
context.code_fetch(self)
|
137
150
|
else
|
138
|
-
raise(
|
139
|
-
Error::Undefined,
|
140
|
-
"#{operator.inspect} not defined on #{inspect}:Class"
|
141
|
-
)
|
151
|
+
raise(Error, "#{code_operator.inspect} not defined on #{inspect}:Class")
|
142
152
|
end
|
143
153
|
end
|
144
154
|
|
145
|
-
def self.code_new(*)
|
146
|
-
|
155
|
+
def self.code_new(*arguments)
|
156
|
+
code_arguments = arguments.to_code
|
157
|
+
|
158
|
+
new(*code_arguments.raw)
|
147
159
|
end
|
148
160
|
|
149
161
|
def self.code_and_operator(other)
|
150
|
-
|
162
|
+
code_other = other.to_code
|
163
|
+
|
164
|
+
truthy? ? code_other : self
|
151
165
|
end
|
152
166
|
|
153
167
|
def self.code_different(other)
|
154
|
-
|
168
|
+
code_other = other.to_code
|
169
|
+
|
170
|
+
Boolean.new(self != code_other)
|
155
171
|
end
|
156
172
|
|
157
173
|
def self.code_equal_equal(other)
|
158
|
-
|
174
|
+
code_other = other.to_code
|
175
|
+
|
176
|
+
Boolean.new(self == code_other)
|
159
177
|
end
|
160
178
|
|
161
179
|
def self.code_exclamation_point
|
@@ -163,15 +181,21 @@ class Code
|
|
163
181
|
end
|
164
182
|
|
165
183
|
def self.code_exclusive_range(value)
|
166
|
-
|
184
|
+
code_value = value.to_code
|
185
|
+
|
186
|
+
Range.new(self, code_value, exclude_end: true)
|
167
187
|
end
|
168
188
|
|
169
189
|
def self.code_inclusive_range(value)
|
170
|
-
|
190
|
+
code_value = value.to_code
|
191
|
+
|
192
|
+
Range.new(self, code_value, exclude_end: false)
|
171
193
|
end
|
172
194
|
|
173
195
|
def self.code_or_operator(other)
|
174
|
-
|
196
|
+
code_other = other.to_code
|
197
|
+
|
198
|
+
truthy? ? self : code_other
|
175
199
|
end
|
176
200
|
|
177
201
|
def self.code_self
|
@@ -179,7 +203,9 @@ class Code
|
|
179
203
|
end
|
180
204
|
|
181
205
|
def self.code_equal_equal_equal(other)
|
182
|
-
|
206
|
+
code_other = other.to_code
|
207
|
+
|
208
|
+
Boolean.new(self === code_other)
|
183
209
|
end
|
184
210
|
|
185
211
|
def self.falsy?
|
@@ -192,7 +218,8 @@ class Code
|
|
192
218
|
|
193
219
|
def self.sig(args, &)
|
194
220
|
Type::Sig.sig(args, object: self, &)
|
195
|
-
|
221
|
+
|
222
|
+
Nothing.new
|
196
223
|
end
|
197
224
|
|
198
225
|
def self.to_s
|
@@ -224,56 +251,52 @@ class Code
|
|
224
251
|
end
|
225
252
|
|
226
253
|
def self.code_as_json
|
227
|
-
|
254
|
+
to_ruby.as_json.to_code
|
228
255
|
end
|
229
256
|
|
230
257
|
def <=>(other)
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
other <=> self
|
235
|
-
end
|
258
|
+
code_other = other.to_code
|
259
|
+
|
260
|
+
raw <=> code_other.raw
|
236
261
|
end
|
237
262
|
|
238
263
|
def ==(other)
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
other == self
|
243
|
-
end
|
264
|
+
code_other = other.to_code
|
265
|
+
|
266
|
+
raw == code_other.raw
|
244
267
|
end
|
245
268
|
alias eql? ==
|
246
269
|
|
247
270
|
def call(**args)
|
248
|
-
|
249
|
-
|
250
|
-
|
271
|
+
code_operator = args.fetch(:operator, nil).to_code
|
272
|
+
code_arguments = args.fetch(:arguments, []).to_code
|
273
|
+
code_value = code_arguments.code_first
|
251
274
|
|
252
|
-
case
|
275
|
+
case code_operator.to_s
|
253
276
|
when "!", "not"
|
254
277
|
sig(args)
|
255
278
|
code_exclamation_point
|
256
279
|
when "!=", "different"
|
257
280
|
sig(args) { Object }
|
258
|
-
code_different(
|
281
|
+
code_different(code_value)
|
259
282
|
when "&&", "and"
|
260
283
|
sig(args) { Object }
|
261
|
-
code_and_operator(
|
284
|
+
code_and_operator(code_value)
|
262
285
|
when "+", "self"
|
263
286
|
sig(args)
|
264
287
|
code_self
|
265
288
|
when "..", "inclusive_range"
|
266
289
|
sig(args) { Object }
|
267
|
-
code_inclusive_range(
|
290
|
+
code_inclusive_range(code_value)
|
268
291
|
when "...", "exclusive_range"
|
269
292
|
sig(args) { Object }
|
270
|
-
code_exclusive_range(
|
293
|
+
code_exclusive_range(code_value)
|
271
294
|
when "==", "equal"
|
272
295
|
sig(args) { Object }
|
273
|
-
code_equal_equal(
|
296
|
+
code_equal_equal(code_value)
|
274
297
|
when "===", "strict_equal"
|
275
298
|
sig(args) { Object }
|
276
|
-
code_equal_equal_equal(
|
299
|
+
code_equal_equal_equal(code_value)
|
277
300
|
when "falsy?"
|
278
301
|
sig(args)
|
279
302
|
Boolean.new(falsy?)
|
@@ -282,7 +305,7 @@ class Code
|
|
282
305
|
Boolean.new(truthy?)
|
283
306
|
when "||", "or"
|
284
307
|
sig(args) { Object }
|
285
|
-
code_or_operator(
|
308
|
+
code_or_operator(code_value)
|
286
309
|
when "to_boolean"
|
287
310
|
sig(args)
|
288
311
|
Boolean.new(self)
|
@@ -318,54 +341,61 @@ class Code
|
|
318
341
|
String.new(self)
|
319
342
|
when "to_time"
|
320
343
|
sig(args)
|
321
|
-
Time.
|
344
|
+
Time.new(self)
|
322
345
|
when "as_json"
|
323
346
|
sig(args)
|
324
347
|
code_as_json
|
325
348
|
when "to_json"
|
326
349
|
sig(args) { { pretty: Boolean.maybe } }
|
327
|
-
|
328
|
-
|
350
|
+
|
351
|
+
if code_arguments.any?
|
352
|
+
code_to_json(pretty: code_value.code_get(:pretty))
|
329
353
|
else
|
330
354
|
code_to_json
|
331
355
|
end
|
332
356
|
when /=$/
|
333
357
|
sig(args) { Object }
|
334
358
|
|
335
|
-
if
|
336
|
-
|
337
|
-
|
359
|
+
if code_operator.to_s == "="
|
360
|
+
code_context = args.fetch(:context)
|
361
|
+
code_context.code_set(self, code_value)
|
338
362
|
else
|
339
|
-
|
340
|
-
|
363
|
+
code_context = args.fetch(:context).code_lookup!(self)
|
364
|
+
code_context.code_set(
|
341
365
|
self,
|
342
|
-
|
366
|
+
code_context.code_fetch(self).call(
|
343
367
|
**args,
|
344
|
-
operator:
|
345
|
-
arguments: List.new([
|
368
|
+
operator: code_operator.to_s.chop,
|
369
|
+
arguments: List.new([code_value])
|
346
370
|
)
|
347
371
|
)
|
348
372
|
end
|
349
373
|
|
350
|
-
|
374
|
+
code_context.code_fetch(self)
|
351
375
|
else
|
352
376
|
raise(
|
353
|
-
Error
|
354
|
-
"#{
|
377
|
+
Error,
|
378
|
+
"#{code_operator.inspect} not defined on #{inspect}:#{self.class.name}"
|
355
379
|
)
|
356
380
|
end
|
357
381
|
end
|
358
382
|
|
359
383
|
def code_and_operator(other)
|
360
|
-
|
384
|
+
code_other = other.to_code
|
385
|
+
|
386
|
+
truthy? ? code_other : self
|
361
387
|
end
|
362
388
|
|
363
389
|
def code_different(other)
|
364
|
-
|
390
|
+
code_other = other.to_code
|
391
|
+
|
392
|
+
Boolean.new(self != code_other)
|
365
393
|
end
|
366
394
|
|
367
395
|
def code_equal_equal(other)
|
368
|
-
|
396
|
+
code_other = other.to_code
|
397
|
+
|
398
|
+
Boolean.new(self == code_other)
|
369
399
|
end
|
370
400
|
|
371
401
|
def code_exclamation_point
|
@@ -373,23 +403,21 @@ class Code
|
|
373
403
|
end
|
374
404
|
|
375
405
|
def code_exclusive_range(value)
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
Dictionary.new({ String.new(:exclude_end) => Boolean.new(true) })
|
380
|
-
)
|
406
|
+
code_value = value.to_code
|
407
|
+
|
408
|
+
Range.new(self, code_value, exclude_end: true)
|
381
409
|
end
|
382
410
|
|
383
411
|
def code_inclusive_range(value)
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
Dictionary.new({ String.new(:exclude_end) => Boolean.new(false) })
|
388
|
-
)
|
412
|
+
code_value = value.to_code
|
413
|
+
|
414
|
+
Range.new(self, code_value, exclude_end: false)
|
389
415
|
end
|
390
416
|
|
391
417
|
def code_or_operator(other)
|
392
|
-
|
418
|
+
code_other = other.to_code
|
419
|
+
|
420
|
+
truthy? ? self : code_other
|
393
421
|
end
|
394
422
|
|
395
423
|
def code_self
|
@@ -397,7 +425,9 @@ class Code
|
|
397
425
|
end
|
398
426
|
|
399
427
|
def code_equal_equal_equal(other)
|
400
|
-
|
428
|
+
code_other = other.to_code
|
429
|
+
|
430
|
+
Boolean.new(self === code_other)
|
401
431
|
end
|
402
432
|
|
403
433
|
def falsy?
|
@@ -414,10 +444,9 @@ class Code
|
|
414
444
|
|
415
445
|
def sig(args, &)
|
416
446
|
Type::Sig.sig(args, object: self, &)
|
417
|
-
nil
|
418
|
-
end
|
419
447
|
|
420
|
-
|
448
|
+
Nothing.new
|
449
|
+
end
|
421
450
|
|
422
451
|
def truthy?
|
423
452
|
true
|
@@ -440,11 +469,15 @@ class Code
|
|
440
469
|
end
|
441
470
|
|
442
471
|
def code_as_json
|
443
|
-
|
472
|
+
as_json.to_code
|
473
|
+
end
|
474
|
+
|
475
|
+
def to_code
|
476
|
+
self
|
444
477
|
end
|
445
478
|
|
446
479
|
def succ
|
447
|
-
|
480
|
+
self.class.new(raw.succ)
|
448
481
|
end
|
449
482
|
end
|
450
483
|
end
|
data/lib/code/parser/string.rb
CHANGED
data/lib/code/type/sig.rb
CHANGED
@@ -91,7 +91,7 @@ class Code
|
|
91
91
|
return if expected_range.include?(actual_arguments.size)
|
92
92
|
|
93
93
|
raise(
|
94
|
-
Error
|
94
|
+
Error,
|
95
95
|
"#{function}: Expected #{expected_count} but got #{actual_count}"
|
96
96
|
)
|
97
97
|
end
|
@@ -118,7 +118,7 @@ class Code
|
|
118
118
|
repeat_index = 0
|
119
119
|
else
|
120
120
|
raise(
|
121
|
-
Error
|
121
|
+
Error,
|
122
122
|
"#{function}: expected #{expected.name}, got #{actual.inspect}"
|
123
123
|
)
|
124
124
|
end
|
@@ -127,7 +127,7 @@ class Code
|
|
127
127
|
repeat_index = 0
|
128
128
|
else
|
129
129
|
raise(
|
130
|
-
Error
|
130
|
+
Error,
|
131
131
|
"#{function}: expected #{expected.name}, got #{actual.inspect}"
|
132
132
|
)
|
133
133
|
end
|
data/lib/code-ruby.rb
CHANGED
@@ -1,19 +1,138 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/all"
|
4
|
+
require "base64"
|
4
5
|
require "bigdecimal"
|
5
6
|
require "bigdecimal/util"
|
6
7
|
require "did_you_mean"
|
7
8
|
require "json"
|
8
9
|
require "language-ruby"
|
10
|
+
require "net/http"
|
9
11
|
require "stringio"
|
10
12
|
require "timeout"
|
13
|
+
require "uri"
|
11
14
|
require "zeitwerk"
|
12
15
|
|
13
16
|
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
14
17
|
loader.ignore("#{__dir__}/code-ruby.rb")
|
15
18
|
loader.setup
|
16
19
|
|
20
|
+
module WordNumberComparaisons
|
21
|
+
def zero?
|
22
|
+
zero?
|
23
|
+
end
|
24
|
+
|
25
|
+
def one?
|
26
|
+
self == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def two?
|
30
|
+
self == 2
|
31
|
+
end
|
32
|
+
|
33
|
+
def three?
|
34
|
+
self == 3
|
35
|
+
end
|
36
|
+
|
37
|
+
def four?
|
38
|
+
self == 4
|
39
|
+
end
|
40
|
+
|
41
|
+
def five?
|
42
|
+
self == 5
|
43
|
+
end
|
44
|
+
|
45
|
+
def six?
|
46
|
+
self == 6
|
47
|
+
end
|
48
|
+
|
49
|
+
def seven?
|
50
|
+
self == 7
|
51
|
+
end
|
52
|
+
|
53
|
+
def eight?
|
54
|
+
self == 8
|
55
|
+
end
|
56
|
+
|
57
|
+
def nine?
|
58
|
+
self == 9
|
59
|
+
end
|
60
|
+
|
61
|
+
def ten?
|
62
|
+
self == 10
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
17
66
|
class Object
|
18
67
|
alias is_an? is_a?
|
68
|
+
|
69
|
+
def to_code
|
70
|
+
raise NotImplementedError, "to_code not defined on #{self.class.name}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class NilClass
|
75
|
+
def to_code
|
76
|
+
Code::Object::Nothing.new(self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class TrueClass
|
81
|
+
def to_code
|
82
|
+
Code::Object::Boolean.new(self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class FalseClass
|
87
|
+
def to_code
|
88
|
+
Code::Object::Boolean.new(self)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class String
|
93
|
+
def to_code
|
94
|
+
Code::Object::String.new(self)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Symbol
|
99
|
+
def to_code
|
100
|
+
Code::Object::String.new(self)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Integer
|
105
|
+
include WordNumberComparaisons
|
106
|
+
|
107
|
+
def to_code
|
108
|
+
Code::Object::Integer.new(self)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Float
|
113
|
+
include WordNumberComparaisons
|
114
|
+
|
115
|
+
def to_code
|
116
|
+
Code::Object::Decimal.new(self)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class BigDecimal
|
121
|
+
include WordNumberComparaisons
|
122
|
+
|
123
|
+
def to_code
|
124
|
+
Code::Object::Decimal.new(self)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Array
|
129
|
+
def to_code
|
130
|
+
Code::Object::List.new(self)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class Hash
|
135
|
+
def to_code
|
136
|
+
Code::Object::Dictionary.new(self)
|
137
|
+
end
|
19
138
|
end
|
data/package-lock.json
CHANGED
data/package.json
CHANGED