Skip to content

Commit 18e1379

Browse files
committed
Merge pull request #2601 from herwinw/kernel_complex
More coercion of string into complex
2 parents c65cf0e + 683a3cd commit 18e1379

File tree

5 files changed

+33
-42
lines changed

5 files changed

+33
-42
lines changed

spec/core/kernel/Complex_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565

6666
context "invalid argument" do
6767
it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
68-
NATFIXME 'raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding', exception: SpecFailedException do
68+
NATFIXME 'Add encoder to to UTF-16', exception: SpecFailedException, message: /code converter not found \(UTF-8 to UTF-16\)/ do
6969
-> {
7070
Complex("79+4i".encode("UTF-16"))
7171
}.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
@@ -117,7 +117,7 @@
117117

118118
context "invalid argument and exception: false passed" do
119119
it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
120-
NATFIXME 'raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding', exception: SpecFailedException do
120+
NATFIXME 'Add encoder to to UTF-16', exception: SpecFailedException, message: /code converter not found \(UTF-8 to UTF-16\)/ do
121121
-> {
122122
Complex("79+4i".encode("UTF-16"), exception: false)
123123
}.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")

spec/core/string/to_c_spec.rb

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
it "allows null-byte" do
3131
"1-2i\0".to_c.should == Complex(1, -2)
3232
"1\0-2i".to_c.should == Complex(1, 0)
33-
NATFIXME 'it allows null-byte', exception: SpecFailedException do
33+
NATFIXME 'This is not a null-byte, but 0x01', exception: SpecFailedException do
3434
"\01-2i".to_c.should == Complex(0, 0)
3535
end
3636
end
3737

3838
it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
39-
NATFIXME 'Raise Encoding::CompatibilityError', exception: SpecFailedException, message: /should have raised Encoding::CompatibilityError/ do
39+
NATFIXME 'Add encoder to to UTF-16', exception: SpecFailedException, message: /code converter not found \(UTF-8 to UTF-16\)/ do
4040
-> {
4141
'79+4i'.encode("UTF-16").to_c
4242
}.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
@@ -45,15 +45,11 @@
4545

4646
ruby_version_is "3.2" do
4747
it "treats a sequence of underscores as an end of Complex string" do
48-
NATFIXME 'Handle single underscore', exception: SpecFailedException do
49-
"5+3_1i".to_c.should == Complex(5, 31)
50-
end
48+
"5+3_1i".to_c.should == Complex(5, 31)
5149
"5+3__1i".to_c.should == Complex(5)
5250
"5+3___1i".to_c.should == Complex(5)
5351

54-
NATFIXME 'Handle single underscore', exception: SpecFailedException do
55-
"12_3".to_c.should == Complex(123)
56-
end
52+
"12_3".to_c.should == Complex(123)
5753
"12__3".to_c.should == Complex(12)
5854
"12___3".to_c.should == Complex(12)
5955
end

spec/shared/kernel/complex.rb

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -93,46 +93,32 @@
9393
end
9494

9595
it "understands scientific notation for the real part" do
96-
NATFIXME 'understands scientific notation for the real part', exception: SpecFailedException do
97-
@object.send(@method, '2e3+4i').should == Complex(2e3,4)
98-
end
96+
@object.send(@method, '2e3+4i').should == Complex(2e3,4)
9997
end
10098

10199
it "understands negative scientific notation for the real part" do
102-
NATFIXME 'understands negative scientific notation for the real part', exception: SpecFailedException do
103-
@object.send(@method, '-2e3+4i').should == Complex(-2e3,4)
104-
end
100+
@object.send(@method, '-2e3+4i').should == Complex(-2e3,4)
105101
end
106102

107103
it "understands scientific notation for the imaginary part" do
108-
NATFIXME 'understands scientific notation for the imaginary part', exception: SpecFailedException do
109-
@object.send(@method, '4+2e3i').should == Complex(4, 2e3)
110-
end
104+
@object.send(@method, '4+2e3i').should == Complex(4, 2e3)
111105
end
112106

113107
it "understands negative scientific notation for the imaginary part" do
114-
NATFIXME 'understands negative scientific notation for the imaginary part', exception: SpecFailedException do
115-
@object.send(@method, '4-2e3i').should == Complex(4, -2e3)
116-
end
108+
@object.send(@method, '4-2e3i').should == Complex(4, -2e3)
117109
end
118110

119111
it "understands scientific notation for the real and imaginary part in the same String" do
120-
NATFIXME 'understands scientific notation for the real and imaginary part in the same String', exception: SpecFailedException do
121-
@object.send(@method, '2e3+2e4i').should == Complex(2e3,2e4)
122-
end
112+
@object.send(@method, '2e3+2e4i').should == Complex(2e3,2e4)
123113
end
124114

125115
it "understands negative scientific notation for the real and imaginary part in the same String" do
126-
NATFIXME 'understands negative scientific notation for the real and imaginary part in the same String', exception: SpecFailedException do
127-
@object.send(@method, '-2e3-2e4i').should == Complex(-2e3,-2e4)
128-
end
116+
@object.send(@method, '-2e3-2e4i').should == Complex(-2e3,-2e4)
129117
end
130118

131119
it "understands scientific notation with e and E" do
132-
NATFIXME 'understands scientific notation with e and E', exception: SpecFailedException do
133-
@object.send(@method, '2e3+2e4i').should == Complex(2e3, 2e4)
134-
@object.send(@method, '2E3+2E4i').should == Complex(2e3, 2e4)
135-
end
120+
@object.send(@method, '2e3+2e4i').should == Complex(2e3, 2e4)
121+
@object.send(@method, '2E3+2E4i').should == Complex(2e3, 2e4)
136122
end
137123

138124
it "understands 'm@a' to mean a complex number in polar form with 'm' as the modulus, 'a' as the argument" do
@@ -152,8 +138,6 @@
152138
end
153139

154140
it "understands _" do
155-
NATFIXME 'understands _', exception: SpecFailedException do
156-
@object.send(@method, '7_9+4_0i').should == Complex(79, 40)
157-
end
141+
@object.send(@method, '7_9+4_0i').should == Complex(79, 40)
158142
end
159143
end

src/kernel_module.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
190190
Undefined,
191191
Integer,
192192
Float,
193+
Scientific,
193194
};
194195
auto state = State::Start;
195196
auto real_type = Type::Undefined;
@@ -206,8 +207,7 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
206207
for (const char *c = input->c_str(); c < input->c_str() + input->bytesize(); c++) {
207208
if (*c == 0) {
208209
if (string_to_c) {
209-
if (state != State::Start)
210-
state = State::Finished;
210+
state = State::Finished;
211211
continue;
212212
} else {
213213
if (exception)
@@ -233,8 +233,9 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
233233
if (*c >= '0' && *c <= '9') {
234234
*curr_end = c;
235235
} else if (*c == '_') {
236-
// TODO: Skip single underscore
237-
if (string_to_c) {
236+
if (c[1] && c[1] >= '0' && c[1] <= '9') {
237+
continue; // Skip single underscore, only if it is part of a number
238+
} else if (string_to_c) {
238239
imag_start = imag_end = nullptr;
239240
state = State::Finished;
240241
} else {
@@ -252,9 +253,11 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
252253
} else if (*c == '/') {
253254
// TODO: Parse fraction
254255
return NilObject::the();
255-
} else if (*c == 'e') {
256-
// TODO: Parse scientific notation
257-
return NilObject::the();
256+
} else if (*c == 'e' || *c == 'E') {
257+
if (*curr_type == Type::Scientific)
258+
return error();
259+
*curr_type = Type::Scientific;
260+
*curr_end = c;
258261
} else if (*c == '@') {
259262
// TODO: Parse polar form
260263
return NilObject::the();
@@ -308,6 +311,7 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
308311
new_real = Integer(env, tmp);
309312
break;
310313
case Type::Float:
314+
case Type::Scientific:
311315
new_real = Float(env, tmp);
312316
break;
313317
case Type::Undefined:
@@ -321,6 +325,7 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool
321325
new_imag = Integer(env, tmp);
322326
break;
323327
case Type::Float:
328+
case Type::Scientific:
324329
new_imag = Float(env, tmp);
325330
break;
326331
case Type::Undefined:

test/natalie/kernel_complex_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,10 @@
2626
-> { Complex('1.0.') }.should raise_error(ArgumentError, 'invalid value for convert(): "1.0."')
2727
-> { Complex('1..0') }.should raise_error(ArgumentError, 'invalid value for convert(): "1..0"')
2828
end
29+
30+
it "accepts an 'e' only once per numeric part" do
31+
-> { Complex('1e2e3') }.should raise_error(ArgumentError, 'invalid value for convert(): "1e2e3"')
32+
-> { Complex('1e2e3+1i') }.should raise_error(ArgumentError, 'invalid value for convert(): "1e2e3+1i"')
33+
-> { Complex('1+1e2e3i') }.should raise_error(ArgumentError, 'invalid value for convert(): "1+1e2e3i"')
34+
end
2935
end

0 commit comments

Comments
 (0)