From 32c1736d9bee8dec0bb70b5b4bc87a31fdc47627 Mon Sep 17 00:00:00 2001 From: Anurag Bhat <90216905+faze-geek@users.noreply.github.com> Date: Mon, 20 Jun 2022 11:16:18 +0530 Subject: [PATCH] Fix integer casting of strings (#591) * fix str to int casting * add test file and integration test --- integration_tests/CMakeLists.txt | 1 + integration_tests/test_str_to_int.py | 10 ++++++++++ src/lpython/semantics/python_ast_to_asr.cpp | 17 ++++++++++++++++- tests/errors/test_str_to_int.py | 4 ++++ .../reference/asr-test_str_to_int-61553e7.json | 13 +++++++++++++ .../asr-test_str_to_int-61553e7.stderr | 5 +++++ tests/tests.toml | 4 ++++ 7 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 integration_tests/test_str_to_int.py create mode 100644 tests/errors/test_str_to_int.py create mode 100644 tests/reference/asr-test_str_to_int-61553e7.json create mode 100644 tests/reference/asr-test_str_to_int-61553e7.stderr diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 6c884d6381..3ae359e113 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -175,6 +175,7 @@ RUN(NAME test_issue_518 LABELS cpython llvm) RUN(NAME structs_01 LABELS cpython llvm c) RUN(NAME structs_02 LABELS llvm c) RUN(NAME structs_03 LABELS llvm c) +RUN(NAME test_str_to_int LABELS cpython llvm) # Just CPython RUN(NAME test_builtin_bin LABELS cpython) diff --git a/integration_tests/test_str_to_int.py b/integration_tests/test_str_to_int.py new file mode 100644 index 0000000000..81bd75c34d --- /dev/null +++ b/integration_tests/test_str_to_int.py @@ -0,0 +1,10 @@ +from ltypes import i32 + +def f(): + i: i32 + i = int("314") + assert i == 314 + i = int("-314") + assert i == -314 + +f() \ No newline at end of file diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 5b83e3291f..0d6d441222 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3184,8 +3184,23 @@ class BodyVisitor : public CommonVisitor { if (ASRUtils::expr_value(arg) != nullptr) { char *c = ASR::down_cast( ASRUtils::expr_value(arg))->m_s; + int ival = 0; + char *ch = c; + if (*ch == '-') { + ch++; + } + while (*ch) { + if (*ch == '.') { + throw SemanticError("invalid literal for int() with base 10: '"+ std::string(c) + "'", arg->base.loc); + } + if (*ch < '0' || *ch > '9') { + throw SemanticError("invalid literal for int() with base 10: '"+ std::string(c) + "'", arg->base.loc); + } + ch++; + } + ival = std::stoi(c); return (ASR::asr_t *)ASR::down_cast(ASR::make_IntegerConstant_t(al, - loc, std::atoi(c), to_type)); + loc, ival, to_type)); } // TODO: make int() work for non-constant strings } else if (ASRUtils::is_logical(*type)) { diff --git a/tests/errors/test_str_to_int.py b/tests/errors/test_str_to_int.py new file mode 100644 index 0000000000..f6f847df22 --- /dev/null +++ b/tests/errors/test_str_to_int.py @@ -0,0 +1,4 @@ +def test_e1(): + print(int('3abc')) + +test_e1() diff --git a/tests/reference/asr-test_str_to_int-61553e7.json b/tests/reference/asr-test_str_to_int-61553e7.json new file mode 100644 index 0000000000..ac1093b9c8 --- /dev/null +++ b/tests/reference/asr-test_str_to_int-61553e7.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_str_to_int-61553e7", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_str_to_int.py", + "infile_hash": "da0ed82ada98ef2757178c4997af53abc82f4761a0e683a613216c64", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_str_to_int-61553e7.stderr", + "stderr_hash": "1998e37d9abe044f164c73ea1e000ce748ed43af5ea14c2eb4715f11", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_str_to_int-61553e7.stderr b/tests/reference/asr-test_str_to_int-61553e7.stderr new file mode 100644 index 0000000000..785d95ba7f --- /dev/null +++ b/tests/reference/asr-test_str_to_int-61553e7.stderr @@ -0,0 +1,5 @@ +semantic error: invalid literal for int() with base 10: '3abc' + --> tests/errors/test_str_to_int.py:2:15 + | +2 | print(int('3abc')) + | ^^^^^^ diff --git a/tests/tests.toml b/tests/tests.toml index daf6b172f2..280c645e7b 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -534,6 +534,10 @@ asr = true filename = "errors/test_func_args.py" asr = true +[[test]] +filename = "errors/test_str_to_int.py" +asr = true + # tests/tokens/errors [[test]]