Skip to content

Commit

Permalink
Merge pull request lcompilers#754 from namannimmo10/stringtoint
Browse files Browse the repository at this point in the history
Make `int()` work for non-constant strings
  • Loading branch information
certik committed Jul 19, 2022
2 parents b76b9db + f12c03b commit 0cb0f83
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 6 deletions.
15 changes: 14 additions & 1 deletion integration_tests/test_str_to_int.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,18 @@ def f():
assert i == 314
i = int("-314")
assert i == -314
s: str
s = "123"
i = int(s)
assert i == 123
s = "-123"
i = int(s)
assert i == -123
s = " 1234"
i = int(s)
assert i == 1234
s = " -1234 "
i = int(s)
assert i == -1234

f()
f()
1 change: 1 addition & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ cast_kind
| IntegerToLogical
| RealToLogical
| CharacterToLogical
| CharacterToInteger
| ComplexToLogical
| ComplexToComplex
| ComplexToReal
Expand Down
21 changes: 21 additions & 0 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
return builder->CreateCall(fn, {str});
}

llvm::Value* lfortran_str_to_int(llvm::Value* str)
{
std::string runtime_func_name = "_lfortran_str_to_int";
llvm::Function *fn = module->getFunction(runtime_func_name);
if (!fn) {
llvm::FunctionType *function_type = llvm::FunctionType::get(
llvm::Type::getInt32Ty(context), {
character_type->getPointerTo()
}, false);
fn = llvm::Function::Create(function_type,
llvm::Function::ExternalLinkage, runtime_func_name, *module);
}
return builder->CreateCall(fn, {str});
}

llvm::Value* lfortran_str_copy(llvm::Value* str, llvm::Value* idx1, llvm::Value* idx2)
{
std::string runtime_func_name = "_lfortran_str_copy";
Expand Down Expand Up @@ -4103,6 +4118,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
tmp = builder->CreateICmpNE(lfortran_str_len(parg), builder->getInt32(0));
break;
}
case (ASR::cast_kindType::CharacterToInteger) : {
llvm::AllocaInst *parg = builder->CreateAlloca(character_type, nullptr);
builder->CreateStore(tmp, parg);
tmp = lfortran_str_to_int(parg);
break;
}
case (ASR::cast_kindType::ComplexToLogical) : {
// !(c.real == 0.0 && c.imag == 0.0)
llvm::Value *zero;
Expand Down
12 changes: 7 additions & 5 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3423,8 +3423,8 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
loc, ival, to_type));
}
return (ASR::asr_t *)ASR::down_cast<ASR::expr_t>(ASR::make_Cast_t(
al, loc, arg, ASR::cast_kindType::RealToInteger,
to_type, value));
al, loc, arg, ASR::cast_kindType::RealToInteger,
to_type, value));
} else if (ASRUtils::is_character(*type)) {
if (ASRUtils::expr_value(arg) != nullptr) {
char *c = ASR::down_cast<ASR::StringConstant_t>(
Expand All @@ -3447,7 +3447,9 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
return (ASR::asr_t *)ASR::down_cast<ASR::expr_t>(ASR::make_IntegerConstant_t(al,
loc, ival, to_type));
}
// TODO: make int() work for non-constant strings
return (ASR::asr_t *)ASR::down_cast<ASR::expr_t>(ASR::make_Cast_t(
al, loc, arg, ASR::cast_kindType::CharacterToInteger,
to_type, value));
} else if (ASRUtils::is_logical(*type)) {
if (ASRUtils::expr_value(arg) != nullptr) {
int32_t ival = ASR::down_cast<ASR::LogicalConstant_t>(
Expand All @@ -3456,8 +3458,8 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
loc, ival, to_type));
}
return (ASR::asr_t *)ASR::down_cast<ASR::expr_t>(ASR::make_Cast_t(
al, loc, arg, ASR::cast_kindType::LogicalToInteger,
to_type, value));
al, loc, arg, ASR::cast_kindType::LogicalToInteger,
to_type, value));
} else if (!ASRUtils::is_integer(*type)) {
std::string stype = ASRUtils::type_to_str_python(type);
throw SemanticError(
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/impure/lfortran_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,12 @@ LFORTRAN_API int _lfortran_str_len(char** s)
return strlen(*s);
}

LFORTRAN_API int _lfortran_str_to_int(char** s)
{
char *ptr;
return strtol(*s, &ptr, 10);
}

LFORTRAN_API char* _lfortran_malloc(int size) {
return (char*)malloc(size);
}
Expand Down
1 change: 1 addition & 0 deletions src/runtime/impure/lfortran_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ LFORTRAN_API bool _lpython_str_compare_gte(char** s1, char** s2);
LFORTRAN_API void _lfortran_strrepeat(char** s, int32_t n, char** dest);
LFORTRAN_API void _lfortran_strcat(char** s1, char** s2, char** dest);
LFORTRAN_API int _lfortran_str_len(char** s);
LFORTRAN_API int _lfortran_str_to_int(char** s);
LFORTRAN_API char* _lfortran_malloc(int size);
LFORTRAN_API void _lfortran_free(char* ptr);
LFORTRAN_API void _lfortran_string_init(int size_plus_one, char *s);
Expand Down

0 comments on commit 0cb0f83

Please sign in to comment.