Skip to content

Commit

Permalink
Fix integer casting of strings (lcompilers#591)
Browse files Browse the repository at this point in the history
* fix str to int casting
* add test file and integration test
  • Loading branch information
faze-geek committed Jun 20, 2022
1 parent ecead95 commit 32c1736
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
10 changes: 10 additions & 0 deletions integration_tests/test_str_to_int.py
Original file line number Diff line number Diff line change
@@ -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()
17 changes: 16 additions & 1 deletion src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3184,8 +3184,23 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
if (ASRUtils::expr_value(arg) != nullptr) {
char *c = ASR::down_cast<ASR::StringConstant_t>(
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::expr_t>(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)) {
Expand Down
4 changes: 4 additions & 0 deletions tests/errors/test_str_to_int.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def test_e1():
print(int('3abc'))

test_e1()
13 changes: 13 additions & 0 deletions tests/reference/asr-test_str_to_int-61553e7.json
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 5 additions & 0 deletions tests/reference/asr-test_str_to_int-61553e7.stderr
Original file line number Diff line number Diff line change
@@ -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'))
| ^^^^^^
4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand Down

0 comments on commit 32c1736

Please sign in to comment.