code-ruby 3.1.2 → 4.0.0

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/code +97 -20
  4. data/lib/code/concerns/shared.rb +331 -15
  5. data/lib/code/format.rb +15 -1
  6. data/lib/code/network.rb +87 -0
  7. data/lib/code/node/call.rb +79 -2
  8. data/lib/code/node/call_argument.rb +14 -0
  9. data/lib/code/node/code.rb +5 -4
  10. data/lib/code/node/function_parameter.rb +7 -4
  11. data/lib/code/node/list.rb +29 -1
  12. data/lib/code/object/base_64.rb +132 -6
  13. data/lib/code/object/boolean.rb +60 -0
  14. data/lib/code/object/class.rb +138 -2
  15. data/lib/code/object/code.rb +111 -3
  16. data/lib/code/object/context.rb +57 -1
  17. data/lib/code/object/cryptography.rb +63 -0
  18. data/lib/code/object/date.rb +13339 -462
  19. data/lib/code/object/decimal.rb +1725 -0
  20. data/lib/code/object/dictionary.rb +1790 -11
  21. data/lib/code/object/duration.rb +28 -0
  22. data/lib/code/object/function.rb +261 -23
  23. data/lib/code/object/global.rb +534 -1
  24. data/lib/code/object/html.rb +179 -7
  25. data/lib/code/object/http.rb +244 -14
  26. data/lib/code/object/ics.rb +75 -13
  27. data/lib/code/object/identifier_list.rb +17 -2
  28. data/lib/code/object/integer.rb +1937 -2
  29. data/lib/code/object/json.rb +75 -1
  30. data/lib/code/object/list.rb +3383 -10
  31. data/lib/code/object/nothing.rb +53 -0
  32. data/lib/code/object/number.rb +110 -0
  33. data/lib/code/object/parameter.rb +140 -0
  34. data/lib/code/object/range.rb +576 -14
  35. data/lib/code/object/smtp.rb +95 -12
  36. data/lib/code/object/string.rb +944 -3
  37. data/lib/code/object/super.rb +10 -1
  38. data/lib/code/object/time.rb +13358 -498
  39. data/lib/code/object/url.rb +65 -0
  40. data/lib/code/object.rb +543 -0
  41. data/lib/code/parser.rb +161 -24
  42. data/lib/code-ruby.rb +3 -0
  43. data/lib/code.rb +30 -3
  44. metadata +135 -84
  45. data/.github/dependabot.yml +0 -15
  46. data/.github/workflows/ci.yml +0 -38
  47. data/.gitignore +0 -30
  48. data/.node-version +0 -1
  49. data/.npm-version +0 -1
  50. data/.prettierignore +0 -2
  51. data/.rspec +0 -1
  52. data/.rubocop.yml +0 -140
  53. data/.ruby-version +0 -1
  54. data/.tool-versions +0 -3
  55. data/AGENTS.md +0 -43
  56. data/Gemfile +0 -22
  57. data/Gemfile.lock +0 -292
  58. data/Rakefile +0 -5
  59. data/bin/bundle +0 -123
  60. data/bin/bundle-audit +0 -31
  61. data/bin/bundler-audit +0 -31
  62. data/bin/dorian +0 -31
  63. data/bin/rspec +0 -31
  64. data/bin/rubocop +0 -31
  65. data/bin/test +0 -5
  66. data/code-ruby.gemspec +0 -34
  67. data/docs/precedence.txt +0 -36
  68. data/package-lock.json +0 -14
  69. data/package.json +0 -7
  70. data/spec/bin/code_spec.rb +0 -48
  71. data/spec/code/format_spec.rb +0 -153
  72. data/spec/code/node/call_spec.rb +0 -11
  73. data/spec/code/object/boolean_spec.rb +0 -18
  74. data/spec/code/object/cryptography_spec.rb +0 -25
  75. data/spec/code/object/decimal_spec.rb +0 -50
  76. data/spec/code/object/dictionary_spec.rb +0 -98
  77. data/spec/code/object/function_spec.rb +0 -268
  78. data/spec/code/object/http_spec.rb +0 -33
  79. data/spec/code/object/ics_spec.rb +0 -50
  80. data/spec/code/object/integer_spec.rb +0 -42
  81. data/spec/code/object/list_spec.rb +0 -22
  82. data/spec/code/object/nothing_spec.rb +0 -14
  83. data/spec/code/object/range_spec.rb +0 -23
  84. data/spec/code/object/string_spec.rb +0 -26
  85. data/spec/code/parser/boolean_spec.rb +0 -11
  86. data/spec/code/parser/chained_call_spec.rb +0 -16
  87. data/spec/code/parser/dictionary_spec.rb +0 -18
  88. data/spec/code/parser/function_spec.rb +0 -16
  89. data/spec/code/parser/group_spec.rb +0 -11
  90. data/spec/code/parser/if_modifier_spec.rb +0 -18
  91. data/spec/code/parser/list_spec.rb +0 -17
  92. data/spec/code/parser/number_spec.rb +0 -11
  93. data/spec/code/parser/string_spec.rb +0 -20
  94. data/spec/code/parser_spec.rb +0 -52
  95. data/spec/code/type_spec.rb +0 -21
  96. data/spec/code_spec.rb +0 -717
  97. data/spec/spec_helper.rb +0 -21
  98. data/spec/zeitwerk/loader_spec.rb +0 -7
@@ -1,268 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Function do
6
- [
7
- ["even? = (i) => { i.even? } even?(2)", "true"],
8
- ["even? = (i:) => { i.even? } even?(i: 2)", "true"],
9
- ["add = (a, b) => { a + b } add(1, 2)", "3"],
10
- ["minus = (a:, b:) => { a - b } minus(b: 1, a: 2)", "1"]
11
- ].each do |input, expected|
12
- it "#{input} == #{expected}" do
13
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
14
- end
15
- end
16
-
17
- context "valid" do
18
- [
19
- "f = () => {} f",
20
- "f = (x) => {} f(1)",
21
- "f = (x:) => {} f(x: 1)"
22
- ].each do |input|
23
- it "#{input} is valid" do
24
- Code.evaluate(input)
25
- end
26
- end
27
- end
28
-
29
- context "invalid" do
30
- [
31
- "f = (x) => {} f()",
32
- "f = (x:) => {} f(1)",
33
- "f = (x:) => {} f(y: 1)"
34
- ].each do |input|
35
- it "#{input} is invalid" do
36
- expect { Code.evaluate(input) }.to raise_error(Code::Error)
37
- end
38
- end
39
- end
40
-
41
- it "evaluates omitted keyword argument defaults" do
42
- result = Code.evaluate(<<~CODE)
43
- f = (number: 1, text: "fallback", missing: nothing, headers: {}) => {
44
- [
45
- number,
46
- text,
47
- missing.nothing?,
48
- headers.merge({ authorization: "Bearer x" })
49
- ]
50
- }
51
-
52
- f()
53
- CODE
54
-
55
- expect(result).to eq(
56
- Code.evaluate('[1, "fallback", true, { authorization: "Bearer x" }]')
57
- )
58
- end
59
-
60
- it "evaluates keyword defaults in the call context" do
61
- expect(Code.evaluate("f = (a:, b: a + 1) => { b } f(a: 2)")).to eq(
62
- Code.evaluate("3")
63
- )
64
- end
65
-
66
- it "binds self when calling a function stored on a dictionary" do
67
- result = Code.evaluate(<<~CODE)
68
- object = {}
69
- object.value = 1
70
- object.fetch = () => {
71
- self.value
72
- }
73
- object.fetch()
74
- CODE
75
-
76
- expect(result).to eq(
77
- Code.evaluate("1")
78
- )
79
- end
80
-
81
- it "captures self for constructor-like functions that return self" do
82
- result = Code.evaluate(<<~CODE)
83
- User = (given_name:, family_name:, birth_date:) => {
84
- self.given_name = given_name.to_string.presence
85
- self.family_name = family_name.to_string.presence
86
- self.birth_date = birth_date.presence&.to_date
87
- self.full_name = () => {
88
- [self.given_name, self.family_name].compact.join(" ")
89
- }
90
- self.age = () => {
91
- return unless(self.birth_date)
92
-
93
- self.birth_date.year
94
- }
95
-
96
- return(self)
97
- }
98
-
99
- user = User(given_name: "Dorian", family_name: "Marie", birth_date: "1992-08-11")
100
- [user.given_name, user.family_name, user.full_name, user.age]
101
- CODE
102
-
103
- expect(result).to eq(
104
- Code::Object::List.new(
105
- [
106
- Code::Object::String.new("Dorian"),
107
- Code::Object::String.new("Marie"),
108
- Code::Object::String.new("Dorian Marie"),
109
- Code::Object::Integer.new(1992)
110
- ]
111
- )
112
- )
113
- end
114
-
115
- it "binds parent to the enclosing self for nested constructor functions" do
116
- result = Code.evaluate(<<~CODE)
117
- Account = (name:) => {
118
- self.name = name
119
-
120
- self.Project = (name:) => {
121
- self.name = name
122
-
123
- self.Task = (name:) => {
124
- self.name = name
125
-
126
- [
127
- self.name,
128
- parent.name,
129
- parent.parent.name
130
- ]
131
- }
132
-
133
- return(self)
134
- }
135
-
136
- return(self)
137
- }
138
-
139
- account = Account(name: "Acme")
140
- Project = account.get(:Project)
141
- project = Project(name: "Migration")
142
- Task = project.get(:Task)
143
- Task(name: "Import")
144
- CODE
145
-
146
- expect(result).to eq(
147
- Code.evaluate('["Import", "Migration", "Acme"]')
148
- )
149
- end
150
-
151
- it "allows parent chains deeper than two levels" do
152
- result = Code.evaluate(<<~CODE)
153
- A = (name:) => {
154
- self.name = name
155
- self.B = (name:) => {
156
- self.name = name
157
- self.C = (name:) => {
158
- self.name = name
159
- self.D = (name:) => {
160
- self.name = name
161
- parent.parent.parent.name
162
- }
163
- return(self)
164
- }
165
- return(self)
166
- }
167
- return(self)
168
- }
169
-
170
- a = A(name: "a")
171
- B = a.get(:B)
172
- b = B(name: "b")
173
- C = b.get(:C)
174
- c = C(name: "c")
175
- D = c.get(:D)
176
- D(name: "d")
177
- CODE
178
-
179
- expect(result).to eq(Code::Object::String.new("a"))
180
- end
181
-
182
- it "supports constructor methods on functions" do
183
- result = Code.evaluate(<<~CODE)
184
- User = (given_name:, family_name:) => {
185
- self.given_name = given_name
186
- self.family_name = family_name
187
- self.full_name = () => {
188
- [self.given_name, self.family_name].join(" ")
189
- }
190
- return(self)
191
- }
192
-
193
- User.all = () => {
194
- [
195
- User(given_name: "Dorian", family_name: "Marie"),
196
- User(given_name: "Ada", family_name: "Lovelace")
197
- ]
198
- }
199
-
200
- User.first = () => {
201
- User.all.first
202
- }
203
-
204
- User.first.full_name
205
- CODE
206
-
207
- expect(result).to eq(Code::Object::String.new("Dorian Marie"))
208
- end
209
-
210
- it "supports extending constructors and forwarding super arguments" do
211
- result = Code.evaluate(<<~CODE)
212
- Person = (given_name:, family_name:) => {
213
- self.given_name = given_name
214
- self.family_name = family_name
215
- self.full_name = () => {
216
- [self.given_name, self.family_name].join(" ")
217
- }
218
- return(self)
219
- }
220
-
221
- Employee = Person.extend((employee_id:, given_name:, family_name:) => {
222
- super
223
- self.employee_id = employee_id
224
- return(self)
225
- })
226
-
227
- employee = Employee(employee_id: "EMP-001", given_name: "Dorian", family_name: "Marie")
228
- [employee.employee_id, employee.full_name]
229
- CODE
230
-
231
- expect(result).to eq(
232
- Code::Object::List.new(
233
- [
234
- Code::Object::String.new("EMP-001"),
235
- Code::Object::String.new("Dorian Marie")
236
- ]
237
- )
238
- )
239
- end
240
-
241
- it "distinguishes super from super()" do
242
- result = Code.evaluate(<<~CODE)
243
- Person = (given_name:, family_name:) => {
244
- self.full_name = () => {
245
- [given_name, family_name].join(" ")
246
- }
247
- return(self)
248
- }
249
-
250
- Anonymous = Person.extend(() => {
251
- super()
252
- self.full_name = () => { "anonymous" }
253
- return(self)
254
- })
255
-
256
- [Anonymous().full_name, Person(given_name: "Ada", family_name: "Lovelace").full_name]
257
- CODE
258
-
259
- expect(result).to eq(
260
- Code::Object::List.new(
261
- [
262
- Code::Object::String.new("anonymous"),
263
- Code::Object::String.new("Ada Lovelace")
264
- ]
265
- )
266
- )
267
- end
268
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Http do
6
- describe ".code_get" do
7
- it "wraps connection reset errors as Code::Error" do
8
- allow_any_instance_of(Net::HTTP).to receive(:request).and_raise(
9
- Errno::ECONNRESET,
10
- "Connection reset by peer - SSL_connect"
11
- )
12
-
13
- expect do
14
- described_class.code_get(
15
- Code::Object::String.new("https://httpbin.org/status/200")
16
- )
17
- end.to raise_error(Code::Error, "http error")
18
- end
19
-
20
- it "wraps name resolution errors as Code::Error" do
21
- allow_any_instance_of(Net::HTTP).to receive(:request).and_raise(
22
- Socket::ResolutionError,
23
- "getaddrinfo(3): Temporary failure in name resolution"
24
- )
25
-
26
- expect do
27
- described_class.code_get(
28
- Code::Object::String.new("https://api.github.com")
29
- )
30
- end.to raise_error(Code::Error, "http error")
31
- end
32
- end
33
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Ics do
6
- it "normalizes binary event strings before json serialization" do
7
- source = <<~ICS
8
- BEGIN:VCALENDAR
9
- VERSION:2.0
10
- PRODID:-//code-ruby//EN
11
- BEGIN:VEVENT
12
- UID:event-1
13
- DTSTART:20260327T120000Z
14
- DTEND:20260327T133000Z
15
- SUMMARY:Joséphine
16
- DESCRIPTION:https://luma.com/opv3owre
17
- END:VEVENT
18
- END:VCALENDAR
19
- ICS
20
-
21
- events = described_class.code_parse(Code::Object::String.new(source.b))
22
-
23
- expect do
24
- expect(events.to_json).to include("Joséphine")
25
- end.not_to output.to_stderr
26
- end
27
-
28
- it "serializes comma-separated descriptions as strings" do
29
- source = <<~ICS
30
- BEGIN:VCALENDAR
31
- VERSION:2.0
32
- PRODID:-//code-ruby//EN
33
- BEGIN:VEVENT
34
- UID:event-2
35
- DTSTART:20260401T170000Z
36
- DTEND:20260401T190000Z
37
- SUMMARY:Le Cirque du Donut
38
- DESCRIPTION:Bonjour Paris !\\nLe 1er avril, Kate Raworth vous donne rendez-vous, pour une soirée inédite.
39
- END:VEVENT
40
- END:VCALENDAR
41
- ICS
42
-
43
- events = described_class.code_parse(Code::Object::String.new(source))
44
- description = events.raw.first.code_get("description").raw
45
-
46
- expect(description).to be_a(String)
47
- expect(description).to include("Le 1er avril, Kate Raworth")
48
- expect(description).to include("rendez-vous, pour")
49
- end
50
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Integer do
6
- [
7
- ["10 % 5", "0"],
8
- ["5 * 2", "10"],
9
- ["2 ** 2", "4"],
10
- ["1 + 1", "2"],
11
- ["1 - 0", "1"],
12
- ["-1", "1 - 2"],
13
- ["1 / 2", "0.5"],
14
- ["1 < 2", "true"],
15
- ["1 <= 1", "true"],
16
- ["1 <=> 2", "-1"],
17
- ["1 > 0", "true"],
18
- ["1 >= 1", "true"],
19
- ["1 === 1", "true"],
20
- %w[-1.abs 1],
21
- %w[-1.ceil -1],
22
- %w[1234.ceil(-2) 1300],
23
- %w[-1.floor -1],
24
- %w[1234.floor(-2) 1200],
25
- %w[1.round 1],
26
- %w[1234.round(-2) 1200],
27
- %w[0.zero? true],
28
- %w[1.truncate 1],
29
- %w[1234.truncate(-2) 1200],
30
- %w[1.to_string :1],
31
- %w[1.to_integer 1],
32
- %w[1.to_decimal 1.0],
33
- %w[4.sqrt 2.0],
34
- ["1 + 2", "3"],
35
- ["2 - 1", "1"],
36
- ["a = 2 - 1 a", "1"]
37
- ].each do |input, expected|
38
- it "#{input} == #{expected}" do
39
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
40
- end
41
- end
42
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::List do
6
- [
7
- ["[] == []", "true"],
8
- ["[nothing, 1, false, \"\"].compact", '[1, false, ""]'],
9
- ["[nothing, 1, false, \"\"].compact(&:blank?)", "[1]"],
10
- ["[1, 2, 3].sum", "6"],
11
- ["[1, 2] + [3, 4]", "[1, 2, 3, 4]"],
12
- ["[] + []", "[]"],
13
- ["[1, 2, 3].second", "2"],
14
- ["[1, 2, 3].third", "3"],
15
- %w[(1..100).to_list.one_hundredth 100],
16
- ["[1, 2, 3].one_hundredth", "nothing"]
17
- ].each do |input, expected|
18
- it "#{input} == #{expected}" do
19
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
20
- end
21
- end
22
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Nothing do
6
- [
7
- %w[nothing nothing],
8
- ["nothing nothing", "nothing"]
9
- ].each do |input, expected|
10
- it "#{input} == #{expected}" do
11
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
12
- end
13
- end
14
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::Range do
6
- [
7
- %w[(0..1).any?(&:even?) true],
8
- %w[(0..1).all?(&:even?) false],
9
- ["a = 0 (0..1).each { a += 1 } a", "2"],
10
- ["(0..1).select(&:even?)", "[0]"],
11
- ["(0..1).map(&:increment)", "[1, 2]"],
12
- ["(0..10).step(3)", "[0, 3, 6, 9]"],
13
- ["(0...9).step(3)", "[0, 3, 6]"],
14
- ["(0..1).to_list", "[0, 1]"],
15
- ["(0...1).to_list", "[0]"],
16
- %w[(0..1).first 0],
17
- %w[(0..1).last 1]
18
- ].each do |input, expected|
19
- it "#{input} == #{expected}" do
20
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
21
- end
22
- end
23
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Object::String do
6
- [
7
- %w[:a a],
8
- %w[:a_b_c_0123 a_b_c_0123],
9
- %w[:Hello Hello],
10
- %w[:Hello Hello],
11
- ['"Hello\nWorld"', "Hello\nWorld"],
12
- ["'Hello\\nWorld'", "Hello\nWorld"]
13
- ].each do |input, expected|
14
- it "(#{input}).to_s == #{expected.inspect}" do
15
- expect(Code.evaluate(input).to_s).to eq(expected)
16
- end
17
- end
18
-
19
- describe "#code_strip" do
20
- it "replaces invalid utf-8 bytes instead of raising" do
21
- string = described_class.new("\xC3 ".b.force_encoding(Encoding::UTF_8))
22
-
23
- expect(string.code_strip.to_s).to eq("\uFFFD")
24
- end
25
- end
26
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser boolean" do
6
- [%w[true !false], %w[false !true]].each do |input, expected|
7
- it "#{input} == #{expected}" do
8
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
9
- end
10
- end
11
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser chained call" do
6
- [
7
- "a.b",
8
- "user.first_name",
9
- "user.admin?",
10
- 'user.update!(name: "Dorian")'
11
- ].each do |input|
12
- it "parses #{input}" do
13
- Code::Parser.parse(input)
14
- end
15
- end
16
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser dictionary" do
6
- [
7
- "{}",
8
- "{ }",
9
- "{/* comment */}",
10
- "{ a: 1, b: 2, c: 3 }",
11
- '{ "first_name": "Dorian" }',
12
- "{ end: 2 }"
13
- ].each do |input|
14
- it "parses #{input}" do
15
- Code::Parser.parse(input)
16
- end
17
- end
18
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser function" do
6
- [
7
- "() => {}",
8
- "(a, b) => { add(a, b) }",
9
- "(a:, b:) => { add(a, b) }",
10
- "(end:) => { nothing }"
11
- ].each do |input|
12
- it "parses #{input}" do
13
- Code::Parser.parse(input)
14
- end
15
- end
16
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser group" do
6
- ["(true (nothing))"].each do |input|
7
- it "parses #{input}" do
8
- Code::Parser.parse(input)
9
- end
10
- end
11
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser if modifier" do
6
- [
7
- ["1 if true", "1"],
8
- ["1 if false", "nothing"],
9
- ["1 unless true", "nothing"],
10
- ["1 unless false", "1"],
11
- ["a = 0 (a += 1) while a < 10 a", "10"],
12
- ["a = 0 (a += 1) until a > 10 a", "11"]
13
- ].each do |input, expected|
14
- it "#{input} == #{expected}" do
15
- expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
16
- end
17
- end
18
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser list" do
6
- [
7
- "[]",
8
- "[ ]",
9
- "[/* comment */]",
10
- "[1, 2, 3]",
11
- "['hello', 1, true, [false, nothing]]"
12
- ].each do |input|
13
- it "parses #{input}" do
14
- Code::Parser.parse(input)
15
- end
16
- end
17
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser number" do
6
- %w[0 1 1.1 123.123 1_000.12_244 0xf0 0o70 0b10].each do |input|
7
- it "parses #{input}" do
8
- Code::Parser.parse(input)
9
- end
10
- end
11
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "parser string" do
6
- [
7
- "''",
8
- '""',
9
- "'Hello Dorian'",
10
- '"Hello Dorian"',
11
- "'Hello \\{name}'",
12
- '"Hello \\{name}"',
13
- "'Hello {name}'",
14
- '"Hello {name}"'
15
- ].each do |input|
16
- it "parses #{input}" do
17
- Code::Parser.parse(input)
18
- end
19
- end
20
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Code::Parser do
6
- [
7
- "",
8
- " ",
9
- "\n",
10
- "# comment",
11
- "dorian = 1 dorian#.to_something",
12
- "/* comment",
13
- "/* comment */",
14
- "// comment",
15
- "/* first comment */ # second comment",
16
- "nothing",
17
- " nothing ",
18
- "nothing nothing nothing"
19
- ].each do |input, _output|
20
- it input.inspect do
21
- described_class.parse(input)
22
- end
23
- end
24
-
25
- Dir["spec/fixtures/code/parser/**/*.code"].each do |filename|
26
- it "parses #{filename}" do
27
- described_class.parse(File.read(filename))
28
- end
29
- end
30
-
31
- it "raises instead of hanging when lexing makes no progress" do
32
- parser = described_class.new('"hello"')
33
-
34
- allow(parser).to receive(:scan_string).and_return({ parts: [], index: 0 })
35
-
36
- expect { parser.send(:lex, '"hello"') }.to raise_error(
37
- Code::Parser::Error,
38
- /lexer made no progress/
39
- )
40
- end
41
-
42
- it "raises instead of hanging when parsing makes no progress" do
43
- parser = described_class.new("a\n.b")
44
-
45
- allow(parser).to receive(:skip_newlines)
46
-
47
- expect { parser.parse }.to raise_error(
48
- Code::Parser::Error,
49
- /parser made no progress/
50
- )
51
- end
52
- end