code-ruby 1.4.0 → 1.5.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.node-version +1 -1
  3. data/.npm-version +1 -1
  4. data/.rubocop.yml +8 -7
  5. data/.ruby-version +1 -1
  6. data/.tool-versions +2 -2
  7. data/Gemfile +1 -1
  8. data/Gemfile.lock +15 -15
  9. data/VERSION +1 -1
  10. data/bin/code +12 -8
  11. data/code-ruby.gemspec +2 -2
  12. data/lib/code/concerns/shared.rb +10 -59
  13. data/lib/code/node/code.rb +10 -0
  14. data/lib/code/node/dictionary.rb +34 -15
  15. data/lib/code/node/function_parameter.rb +1 -1
  16. data/lib/code/object/boolean.rb +2 -2
  17. data/lib/code/object/class.rb +2 -2
  18. data/lib/code/object/code.rb +2 -2
  19. data/lib/code/object/context.rb +1 -1
  20. data/lib/code/object/date.rb +3 -3
  21. data/lib/code/object/decimal.rb +3 -3
  22. data/lib/code/object/dictionary.rb +23 -7
  23. data/lib/code/object/duration.rb +3 -3
  24. data/lib/code/object/function.rb +2 -2
  25. data/lib/code/object/global.rb +1 -5
  26. data/lib/code/object/html.rb +4 -5
  27. data/lib/code/object/http.rb +0 -2
  28. data/lib/code/object/integer.rb +3 -3
  29. data/lib/code/object/list.rb +9 -2
  30. data/lib/code/object/nothing.rb +2 -2
  31. data/lib/code/object/parameter.rb +2 -2
  32. data/lib/code/object/range.rb +2 -2
  33. data/lib/code/object/string.rb +2 -2
  34. data/lib/code/object/time.rb +2 -6
  35. data/lib/code/object.rb +5 -5
  36. data/lib/code/parser/call.rb +7 -6
  37. data/lib/code/parser/dictionary.rb +7 -5
  38. data/lib/code/parser/equal.rb +0 -4
  39. data/lib/code/parser/function.rb +8 -2
  40. data/lib/code/parser/group.rb +20 -4
  41. data/lib/code/parser/if.rb +8 -2
  42. data/lib/code/parser/name.rb +4 -8
  43. data/lib/code/parser/while.rb +8 -2
  44. data/lib/code/type/sig.rb +2 -2
  45. data/lib/code/type.rb +1 -1
  46. data/lib/code.rb +7 -7
  47. data/package-lock.json +2 -2
  48. data/package.json +2 -2
  49. data/spec/code/object/http_spec.rb +70 -66
  50. data/spec/code_spec.rb +4 -2
  51. metadata +4 -6
  52. data/TODO +0 -219
  53. data/bin/console +0 -6
@@ -3,8 +3,8 @@
3
3
  class Code
4
4
  class Object
5
5
  class List < Object
6
- def initialize(*args, **_kargs, &)
7
- @raw =
6
+ def initialize(*args, **_kargs, &_block)
7
+ self.raw =
8
8
  if args.first.is_a?(List)
9
9
  args.first.raw.map(&:to_code)
10
10
  elsif args.first.is_an?(::Array)
@@ -45,6 +45,9 @@ class Code
45
45
  when "sample"
46
46
  sig(args) { Integer.maybe }
47
47
  code_sample(code_value)
48
+ when "shuffle"
49
+ sig(args)
50
+ code_shuffle
48
51
  when "flatten"
49
52
  sig(args) { Integer.maybe }
50
53
  code_flatten
@@ -187,6 +190,10 @@ class Code
187
190
  end
188
191
  end
189
192
 
193
+ def code_shuffle
194
+ List.new(raw.shuffle)
195
+ end
196
+
190
197
  def code_flatten(level = nil)
191
198
  code_level = level.to_code
192
199
  code_level = Integer.new(-1) if code_level.nothing?
@@ -3,8 +3,8 @@
3
3
  class Code
4
4
  class Object
5
5
  class Nothing < Object
6
- def initialize(*_args, **_kargs, &)
7
- @raw = nil
6
+ def initialize(*_args, **_kargs, &_block)
7
+ self.raw = nil
8
8
  end
9
9
 
10
10
  def truthy?
@@ -3,8 +3,8 @@
3
3
  class Code
4
4
  class Object
5
5
  class Parameter < Object
6
- def initialize(*args, **_kargs, &)
7
- @raw = Dictionary.new(args.first)
6
+ def initialize(*args, **_kargs, &_block)
7
+ self.raw = Dictionary.new(args.first)
8
8
  end
9
9
 
10
10
  def code_name
@@ -5,7 +5,7 @@ class Code
5
5
  class Range < Object
6
6
  attr_reader :code_left, :code_right, :code_options, :code_exclude_end
7
7
 
8
- def initialize(*args, **kargs, &)
8
+ def initialize(*args, **kargs, &_block)
9
9
  if args.first.is_a?(Range)
10
10
  @code_left = args.first.code_left
11
11
  @code_right = args.first.code_right
@@ -26,7 +26,7 @@ class Code
26
26
  @code_exclude_end = Boolean.new(code_options.code_get(:exclude_end))
27
27
  end
28
28
 
29
- @raw = ::Range.new(code_left, code_right, exclude_end?)
29
+ self.raw = ::Range.new(code_left, code_right, exclude_end?)
30
30
  end
31
31
 
32
32
  def call(**args)
@@ -3,8 +3,8 @@
3
3
  class Code
4
4
  class Object
5
5
  class String < Object
6
- def initialize(*args, **_kargs, &)
7
- @raw =
6
+ def initialize(*args, **_kargs, &_block)
7
+ self.raw =
8
8
  if args.first.is_an?(Class)
9
9
  args.first.raw.name
10
10
  elsif args.first.is_an?(Object)
@@ -5,9 +5,9 @@ class Code
5
5
  class Time < Object
6
6
  DEFAULT_ZONE = "Etc/UTC"
7
7
 
8
- def initialize(*args, **_kargs, &)
8
+ def initialize(*args, **_kargs, &_block)
9
9
  ::Time.zone ||= DEFAULT_ZONE
10
- @raw = ::Time.zone.parse(args.first.to_s) || ::Time.zone.now
10
+ self.raw = ::Time.zone.parse(args.first.to_s) || ::Time.zone.now
11
11
  end
12
12
 
13
13
  def self.call(**args)
@@ -79,10 +79,6 @@ class Code
79
79
  end
80
80
  end
81
81
 
82
- def self.code_hour
83
- code_now.code_hour
84
- end
85
-
86
82
  def self.code_tomorrow
87
83
  ::Time.zone ||= DEFAULT_ZONE
88
84
  new(::Time.zone.tomorrow)
data/lib/code/object.rb CHANGED
@@ -23,23 +23,23 @@ class Code
23
23
  end
24
24
 
25
25
  def self.repeat(minimum = 0, maximum = nil)
26
- Type::Repeat.new(self, minimum:, maximum:)
26
+ Type::Repeat.new(self, minimum: minimum, maximum: maximum)
27
27
  end
28
28
 
29
29
  def self.|(other)
30
30
  Type::Or.new(self, other)
31
31
  end
32
32
 
33
- def self.code_new(*)
34
- new(*)
33
+ def self.code_new(*args)
34
+ new(*args)
35
35
  end
36
36
 
37
37
  def name
38
38
  self.class.name
39
39
  end
40
40
 
41
- def code_new(*)
42
- self.class.code_new(*)
41
+ def code_new(*args)
42
+ self.class.code_new(*args)
43
43
  end
44
44
  end
45
45
  end
@@ -111,14 +111,15 @@ class Code
111
111
 
112
112
  def block
113
113
  (
114
- (do_keyword | begin_keyword) << whitespace? <<
115
- parameters.aka(:parameters).maybe << code.aka(:body) <<
116
- end_keyword.maybe
114
+ (do_keyword | begin_keyword).ignore << whitespace <<
115
+ parameters.aka(:parameters).maybe << whitespace? <<
116
+ code.aka(:body) << (whitespace? << end_keyword).maybe.ignore
117
117
  ) |
118
118
  (
119
- opening_curly_bracket << whitespace? <<
120
- parameters.aka(:parameters).maybe << code.aka(:body) <<
121
- closing_curly_bracket.maybe
119
+ opening_curly_bracket.ignore << whitespace? <<
120
+ parameters.aka(:parameters).maybe << whitespace? <<
121
+ code.aka(:body) <<
122
+ (whitespace? << closing_curly_bracket).maybe.ignore
122
123
  )
123
124
  end
124
125
 
@@ -48,14 +48,16 @@ class Code
48
48
  end
49
49
 
50
50
  def key_value
51
- (name.aka(:name) << colon << code_present.aka(:value).maybe) |
51
+ (name.aka(:name) << colon << code_present.aka(:code).maybe).aka(
52
+ :name_code
53
+ ) |
52
54
  (
53
- statement.aka(:statement) << colon << code_present.aka(:value).maybe
54
- ) |
55
+ statement.aka(:statement) << colon << code_present.aka(:code).maybe
56
+ ).aka(:statement_code) |
55
57
  (
56
58
  statement.aka(:statement) << whitespace? << equal << greater <<
57
- code_present.aka(:value).maybe
58
- ) | statement.aka(:statement)
59
+ code_present.aka(:code).maybe
60
+ ).aka(:statement_code) | code_present.aka(:code)
59
61
  end
60
62
 
61
63
  def root
@@ -51,10 +51,6 @@ class Code
51
51
  str("^")
52
52
  end
53
53
 
54
- def dot
55
- str(".")
56
- end
57
-
58
54
  def right_statement
59
55
  OrKeyword
60
56
  end
@@ -101,8 +101,14 @@ class Code
101
101
  end
102
102
 
103
103
  def body
104
- ((begin_keyword | do_keyword) << code << end_keyword.maybe) |
105
- (opening_curly_bracket << code << closing_curly_bracket.maybe) | code
104
+ (
105
+ (begin_keyword | do_keyword).ignore << whitespace << code <<
106
+ (whitespace? << end_keyword).maybe.ignore
107
+ ) |
108
+ (
109
+ opening_curly_bracket.ignore << whitespace? << code <<
110
+ (whitespace? << closing_curly_bracket).maybe.ignore
111
+ ) | (code << (whitespace? << end_keyword).maybe.ignore)
106
112
  end
107
113
 
108
114
  def root
@@ -7,6 +7,14 @@ class Code
7
7
  Code
8
8
  end
9
9
 
10
+ def whitespace
11
+ Whitespace
12
+ end
13
+
14
+ def whitespace?
15
+ whitespace.maybe
16
+ end
17
+
10
18
  def opening_parenthesis
11
19
  str("(")
12
20
  end
@@ -28,10 +36,18 @@ class Code
28
36
  end
29
37
 
30
38
  def root
31
- (opening_parenthesis << code << closing_parenthesis.maybe).aka(:group) |
32
- (begin_keyword << code << end_keyword.maybe).aka(:group) |
33
- (do_keyword << code << end_keyword.maybe).aka(:group) |
34
- Call
39
+ (
40
+ opening_parenthesis.ignore << whitespace? << code <<
41
+ (whitespace? << closing_parenthesis).maybe.ignore
42
+ ).aka(:group) |
43
+ (
44
+ begin_keyword.ignore << whitespace << code <<
45
+ (whitespace? << end_keyword).maybe.ignore
46
+ ).aka(:group) |
47
+ (
48
+ do_keyword.ignore << whitespace << code <<
49
+ (whitespace? << end_keyword).maybe.ignore
50
+ ).aka(:group) | Call
35
51
  end
36
52
  end
37
53
  end
@@ -60,8 +60,14 @@ class Code
60
60
  end
61
61
 
62
62
  def body
63
- ((begin_keyword | do_keyword) << code << end_keyword.maybe) |
64
- (opening_curly_bracket << code << closing_curly_bracket.maybe) | code
63
+ (
64
+ (begin_keyword | do_keyword).ignore << whitespace << code <<
65
+ (whitespace? << end_keyword).maybe.ignore
66
+ ) |
67
+ (
68
+ opening_curly_bracket.ignore << whitespace? << code <<
69
+ (whitespace? << closing_curly_bracket).maybe.ignore
70
+ ) | (code << (whitespace? << end_keyword).maybe.ignore)
65
71
  end
66
72
 
67
73
  def root
@@ -83,6 +83,10 @@ class Code
83
83
  str("do")
84
84
  end
85
85
 
86
+ def begin_keyword
87
+ str("begin")
88
+ end
89
+
86
90
  def end_keyword
87
91
  str("end")
88
92
  end
@@ -91,18 +95,10 @@ class Code
91
95
  str("elsif")
92
96
  end
93
97
 
94
- def begin_keyword
95
- str("begin")
96
- end
97
-
98
98
  def else_keyword
99
99
  str("else")
100
100
  end
101
101
 
102
- def begin_keyword
103
- str("begin")
104
- end
105
-
106
102
  def special_character
107
103
  ampersand | equal | pipe | dot | colon | comma | space | newline |
108
104
  opening_curly_bracket | closing_curly_bracket | opening_parenthesis |
@@ -52,8 +52,14 @@ class Code
52
52
  end
53
53
 
54
54
  def body
55
- ((do_keyword | begin_keyword) << code << end_keyword.maybe) |
56
- (opening_curly_bracket << code << closing_curly_bracket) | code
55
+ (
56
+ (begin_keyword | do_keyword).ignore << whitespace << code <<
57
+ (whitespace? << end_keyword).maybe.ignore
58
+ ) |
59
+ (
60
+ opening_curly_bracket.ignore << whitespace? << code <<
61
+ (whitespace? << closing_curly_bracket).maybe.ignore
62
+ ) | (code << (whitespace? << end_keyword).maybe.ignore)
57
63
  end
58
64
 
59
65
  def root
data/lib/code/type/sig.rb CHANGED
@@ -111,7 +111,7 @@ class Code
111
111
  actual_arguments.each do |actual|
112
112
  expected = expected_arguments[expected_index]
113
113
  if expected.is_a?(Repeat)
114
- if valid_for?(expected:, actual:)
114
+ if valid_for?(expected: expected, actual: actual)
115
115
  repeat_index += 1
116
116
  elsif repeat_index >= expected.min_arguments
117
117
  expected_index += 1
@@ -122,7 +122,7 @@ class Code
122
122
  "#{function}: expected #{expected.name}, got #{actual.inspect}"
123
123
  )
124
124
  end
125
- elsif valid_for?(expected:, actual:)
125
+ elsif valid_for?(expected: expected, actual: actual)
126
126
  expected_index += 1
127
127
  repeat_index = 0
128
128
  else
data/lib/code/type.rb CHANGED
@@ -7,7 +7,7 @@ class Code
7
7
  end
8
8
 
9
9
  def repeat(minimum = 0, maximum = nil)
10
- Repeat.new(self, minimum:, maximum:)
10
+ Repeat.new(self, minimum: minimum, maximum: maximum)
11
11
  end
12
12
 
13
13
  def |(other)
data/lib/code.rb CHANGED
@@ -33,13 +33,13 @@ class Code
33
33
  def evaluate
34
34
  Timeout.timeout(timeout) do
35
35
  Node::Code.new(Code.parse(source)).evaluate(
36
- context:,
37
- error:,
38
- input:,
39
- object:,
40
- output:,
41
- source:,
42
- timeout:
36
+ context: context,
37
+ error: error,
38
+ input: input,
39
+ object: object,
40
+ output: output,
41
+ source: source,
42
+ timeout: timeout
43
43
  )
44
44
  end
45
45
  end
data/package-lock.json CHANGED
@@ -6,8 +6,8 @@
6
6
  "": {
7
7
  "license": "MIT",
8
8
  "engines": {
9
- "node": "22.5.1",
10
- "npm": "10.8.2"
9
+ "node": "23.11.0",
10
+ "npm": "11.2.0"
11
11
  }
12
12
  }
13
13
  }
data/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "license": "MIT",
3
3
  "engines": {
4
- "node": "22.5.1",
5
- "npm": "10.8.2"
4
+ "node": "23.11.0",
5
+ "npm": "11.2.0"
6
6
  }
7
7
  }
@@ -3,73 +3,77 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe Code::Object::Http do
6
- %w[get head post put delete options trace patch].each do |verb|
6
+ VERBS = %w[get head post put delete options trace patch].freeze
7
+
8
+ RESPONSE_CODES = {
9
+ continue: 100,
10
+ switching_protocols: 101,
11
+ processing: 102,
12
+ early_hints: 103,
13
+ ok: 200,
14
+ created: 201,
15
+ accepted: 202,
16
+ non_authoritative_information: 203,
17
+ no_content: 204,
18
+ reset_content: 205,
19
+ partial_content: 206,
20
+ multi_status: 207,
21
+ already_reported: 208,
22
+ im_used: 226,
23
+ multiple_choices: 300,
24
+ moved_permanently: 301,
25
+ found: 302,
26
+ see_other: 303,
27
+ not_modified: 304,
28
+ use_proxy: 305,
29
+ reserved: 306,
30
+ temporary_redirect: 307,
31
+ permanent_redirect: 308,
32
+ bad_request: 400,
33
+ unauthorized: 401,
34
+ payment_required: 402,
35
+ forbidden: 403,
36
+ not_found: 404,
37
+ method_not_allowed: 405,
38
+ not_acceptable: 406,
39
+ proxy_authentication_required: 407,
40
+ request_timeout: 408,
41
+ conflict: 409,
42
+ gone: 410,
43
+ length_required: 411,
44
+ precondition_failed: 412,
45
+ request_entity_too_large: 413,
46
+ request_uri_too_long: 414,
47
+ unsupported_media_type: 415,
48
+ requested_range_not_satisfiable: 416,
49
+ expectation_failed: 417,
50
+ misdirected_request: 421,
51
+ unprocessable_entity: 422,
52
+ locked: 423,
53
+ failed_dependency: 424,
54
+ too_early: 425,
55
+ upgrade_required: 426,
56
+ precondition_required: 428,
57
+ too_many_requests: 429,
58
+ request_header_fields_too_large: 431,
59
+ unavailable_for_legal_reasons: 451,
60
+ internal_server_error: 500,
61
+ not_implemented: 501,
62
+ bad_gateway: 502,
63
+ service_unavailable: 503,
64
+ gateway_timeout: 504,
65
+ http_version_not_supported: 505,
66
+ variant_also_negotiates: 506,
67
+ insufficient_storage: 507,
68
+ loop_detected: 508,
69
+ bandwidth_limit_exceeded: 509,
70
+ not_extended: 510,
71
+ network_authentication_required: 511
72
+ }.freeze
73
+
74
+ VERBS.each do |verb|
7
75
  describe ".#{verb}" do
8
- {
9
- continue: 100,
10
- switching_protocols: 101,
11
- processing: 102,
12
- early_hints: 103,
13
- ok: 200,
14
- created: 201,
15
- accepted: 202,
16
- non_authoritative_information: 203,
17
- no_content: 204,
18
- reset_content: 205,
19
- partial_content: 206,
20
- multi_status: 207,
21
- already_reported: 208,
22
- im_used: 226,
23
- multiple_choices: 300,
24
- moved_permanently: 301,
25
- found: 302,
26
- see_other: 303,
27
- not_modified: 304,
28
- use_proxy: 305,
29
- reserved: 306,
30
- temporary_redirect: 307,
31
- permanent_redirect: 308,
32
- bad_request: 400,
33
- unauthorized: 401,
34
- payment_required: 402,
35
- forbidden: 403,
36
- not_found: 404,
37
- method_not_allowed: 405,
38
- not_acceptable: 406,
39
- proxy_authentication_required: 407,
40
- request_timeout: 408,
41
- conflict: 409,
42
- gone: 410,
43
- length_required: 411,
44
- precondition_failed: 412,
45
- request_entity_too_large: 413,
46
- request_uri_too_long: 414,
47
- unsupported_media_type: 415,
48
- requested_range_not_satisfiable: 416,
49
- expectation_failed: 417,
50
- misdirected_request: 421,
51
- unprocessable_entity: 422,
52
- locked: 423,
53
- failed_dependency: 424,
54
- too_early: 425,
55
- upgrade_required: 426,
56
- precondition_required: 428,
57
- too_many_requests: 429,
58
- request_header_fields_too_large: 431,
59
- unavailable_for_legal_reasons: 451,
60
- internal_server_error: 500,
61
- not_implemented: 501,
62
- bad_gateway: 502,
63
- service_unavailable: 503,
64
- gateway_timeout: 504,
65
- http_version_not_supported: 505,
66
- variant_also_negotiates: 506,
67
- insufficient_storage: 507,
68
- loop_detected: 508,
69
- bandwidth_limit_exceeded: 509,
70
- not_extended: 510,
71
- network_authentication_required: 511
72
- }.each do |status, code|
76
+ RESPONSE_CODES.each do |status, code|
73
77
  it "returns #{code} as code and #{status} as status" do
74
78
  expect(Code.evaluate(<<~INPUT)).to eq(Code.evaluate(<<~OUTPUT))
75
79
  response = Http.#{verb}("https://httpbin.org/status/#{code}")
data/spec/code_spec.rb CHANGED
@@ -339,6 +339,8 @@ RSpec.describe Code do
339
339
  ["[1, 2, 3].any?(&:even?)", "true"],
340
340
  ["[1, 2, 3].none?", "false"],
341
341
  ["[1, 2, 3].none?(&:even?)", "false"],
342
+ ["subject = 1 { subject }", "{ subject: 1 }"],
343
+ ["subject = 1 { subject: }", "{ subject: 1 }"],
342
344
  ["'{1} {2}'", "'1 2'"],
343
345
  %w[Json.parse("1") 1],
344
346
  %w[{a:1}.to_query "a=1"],
@@ -346,7 +348,7 @@ RSpec.describe Code do
346
348
  ].each do |input, expected|
347
349
  it "#{input} == #{expected}" do
348
350
  output = StringIO.new
349
- code_input = described_class.evaluate(input, output:)
351
+ code_input = described_class.evaluate(input, output: output)
350
352
  code_expected = described_class.evaluate(expected)
351
353
  expect(code_input).to eq(code_expected)
352
354
  expect(output.string).to eq("")
@@ -361,7 +363,7 @@ RSpec.describe Code do
361
363
  [["puts(true)", "true\n"], %w[print(false) false]].each do |input, expected|
362
364
  it "#{input} prints #{expected}" do
363
365
  output = StringIO.new
364
- described_class.evaluate(input, output:)
366
+ described_class.evaluate(input, output: output)
365
367
  expect(output.string).to eq(expected)
366
368
  end
367
369
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-04 00:00:00.000000000 Z
10
+ date: 2025-05-16 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport
@@ -164,7 +164,7 @@ dependencies:
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  description: a programming language for the internet
167
- email: dorian@dorianmarie.fr
167
+ email: dorian@dorianmarie.com
168
168
  executables:
169
169
  - code
170
170
  extensions: []
@@ -185,13 +185,11 @@ files:
185
185
  - LICENSE
186
186
  - README.md
187
187
  - Rakefile
188
- - TODO
189
188
  - VERSION
190
189
  - bin/bundle
191
190
  - bin/bundle-audit
192
191
  - bin/bundler-audit
193
192
  - bin/code
194
- - bin/console
195
193
  - bin/dorian
196
194
  - bin/rspec
197
195
  - bin/rubocop
@@ -338,7 +336,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
338
336
  requirements:
339
337
  - - ">="
340
338
  - !ruby/object:Gem::Version
341
- version: '3.1'
339
+ version: '3.0'
342
340
  required_rubygems_version: !ruby/object:Gem::Requirement
343
341
  requirements:
344
342
  - - ">="