From e1868ce284dc17d3654a7f0ac4b94a674a21dcc6 Mon Sep 17 00:00:00 2001 From: Herwin Date: Fri, 14 Feb 2025 17:36:42 +0100 Subject: [PATCH] Support polar form in String to Complex coercion --- spec/shared/kernel/complex.rb | 8 +++----- src/kernel_module.cpp | 31 ++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/spec/shared/kernel/complex.rb b/spec/shared/kernel/complex.rb index 65a29e1e3..98ee0b2b3 100644 --- a/spec/shared/kernel/complex.rb +++ b/spec/shared/kernel/complex.rb @@ -114,11 +114,9 @@ end it "understands 'm@a' to mean a complex number in polar form with 'm' as the modulus, 'a' as the argument" do - NATFIXME "understands 'm@a' to mean a complex number in polar form with 'm' as the modulus, 'a' as the argument", exception: SpecFailedException do - @object.send(@method, '79@4').should == Complex.polar(79, 4) - @object.send(@method, '-79@4').should == Complex.polar(-79, 4) - @object.send(@method, '79@-4').should == Complex.polar(79, -4) - end + @object.send(@method, '79@4').should == Complex.polar(79, 4) + @object.send(@method, '-79@4').should == Complex.polar(-79, 4) + @object.send(@method, '79@-4').should == Complex.polar(79, -4) end it "ignores leading whitespaces" do diff --git a/src/kernel_module.cpp b/src/kernel_module.cpp index 33082c97f..1fa753335 100644 --- a/src/kernel_module.cpp +++ b/src/kernel_module.cpp @@ -196,6 +196,7 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool auto state = State::Start; auto real_type = Type::Undefined; auto imag_type = Type::Undefined; + bool polar = false; const char *real_start = nullptr; const char *real_end = nullptr; const char *imag_start = nullptr; @@ -263,19 +264,33 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool *curr_type = Type::Scientific; *curr_end = c; } else if (*c == '@') { - // TODO: Parse polar form - return NilObject::the(); - } else if (*c == '+' || *c == '-') { - if (*curr_start && *curr_start == *curr_end && (**curr_end == '-' || **curr_end == '+')) + if (polar) return error(); - if (state == State::Imag) + if (state != State::Real) return error(); + if (!c[1]) + return error(); + polar = true; curr_start = &imag_start; curr_end = &imag_end; *curr_start = *curr_end = c; curr_type = &imag_type; *curr_type = Type::Integer; state = State::Imag; + } else if (*c == '+' || *c == '-') { + if (*curr_start && *curr_start == *curr_end && (**curr_end == '-' || **curr_end == '+')) + return error(); + if (state == State::Imag) { + if (!polar && (!*curr_start || *curr_start != *curr_end)) + return error(); + } else { + curr_start = &imag_start; + curr_end = &imag_end; + *curr_start = *curr_end = c; + curr_type = &imag_type; + *curr_type = Type::Integer; + state = State::Imag; + } } else if (*c == 'i' || *c == 'I' || *c == 'j' || *c == 'J') { if (*curr_start && *curr_start == *curr_end && (**curr_end == '-' || **curr_end == '+')) { // Corner case: '-i' or '+i' @@ -326,6 +341,8 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool } } if (imag_start != nullptr && imag_end != nullptr) { + if (polar) + imag_start++; // skip '@' auto tmp = new StringObject { imag_start, static_cast(imag_end - imag_start + 1) }; switch (imag_type) { case Type::Integer: @@ -342,6 +359,10 @@ Value KernelModule::Complex(Env *env, StringObject *input, bool exception, bool return error(); } } + if (polar) { + auto Complex = GlobalEnv::the()->Object()->const_get(env, "Complex"_s); + return Complex.send(env, "polar"_s, { new_real, new_imag }); + } return new ComplexObject { new_real, new_imag }; } }