Skip to content

Commit 9646432

Browse files
authored
Merge pull request #1098 from Smit-create/strtolist2
Add String to List cast in LLVM
2 parents 28473bd + b510150 commit 9646432

File tree

65 files changed

+151
-129
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+151
-129
lines changed

integration_tests/str_to_list_cast.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,20 @@ def f():
1010
assert len(x) == 0
1111
x = list("L")
1212
assert len(x) == 1 and x[0] == 'L'
13+
x = list(s)
14+
assert len(x) == len(s)
15+
for i in range(len(x)):
16+
assert x[i] == s[i]
17+
s = "agowietg348203wk.smg.afejwp398273wd.a,23to0MEG.F,"
18+
x = list(s)
19+
assert len(x) == len(s)
20+
for i in range(len(x)):
21+
assert x[i] == s[i]
22+
s += str(i)
23+
x = list(s)
24+
assert len(x) == len(s)
25+
for i in range(len(x)):
26+
assert x[i] == s[i]
27+
1328

1429
f()

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,21 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
849849
AST::keyword_t* kwargs=nullptr, size_t n_kwargs=0) {
850850
if (intrinsic_node_handler.is_present(call_name)) {
851851
return intrinsic_node_handler.get_intrinsic_node(call_name, al, loc,
852-
args, ann_assign_target_type);
852+
args);
853853
}
854+
855+
if (call_name == "list" && (args.size() == 0 || args[0].m_value == nullptr)) {
856+
if (ann_assign_target_type) {
857+
ASR::ttype_t *type = ASRUtils::get_contained_type(ann_assign_target_type);
858+
ASR::ttype_t* list_type = ASRUtils::TYPE(ASR::make_List_t(al, loc, type));
859+
Vec<ASR::expr_t*> list;
860+
list.reserve(al, 1);
861+
return ASR::make_ListConstant_t(al, loc, list.p,
862+
list.size(), list_type);
863+
}
864+
return nullptr;
865+
}
866+
854867
ASR::symbol_t *s_generic = nullptr, *stemp = s;
855868
// Type map for generic functions
856869
std::map<std::string, ASR::ttype_t*> subs;
@@ -4861,7 +4874,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
48614874
return ;
48624875
} else if (intrinsic_node_handler.is_present(call_name)) {
48634876
tmp = intrinsic_node_handler.get_intrinsic_node(call_name, al,
4864-
x.base.base.loc, args, ann_assign_target_type);
4877+
x.base.base.loc, args);
48654878
return;
48664879
} else {
48674880
// The function was not found and it is not intrinsic

src/lpython/semantics/python_comptime_eval.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct PythonIntrinsicProcedures {
5757
{"bin", {m_builtin, &eval_bin}},
5858
{"hex", {m_builtin, &eval_hex}},
5959
{"oct", {m_builtin, &eval_oct}},
60+
{"list", {m_builtin, &eval_list}},
6061
{"complex", {m_builtin, &eval_complex}},
6162
{"_lpython_imag", {m_builtin, &eval__lpython_imag}},
6263
{"divmod", {m_builtin, &eval_divmod}},
@@ -371,6 +372,46 @@ struct PythonIntrinsicProcedures {
371372
}
372373
}
373374

375+
static ASR::expr_t *eval_list(Allocator &al, const Location &loc, Vec<ASR::expr_t*> &args) {
376+
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
377+
if (args.size() > 1) {
378+
throw SemanticError("list() takes 0 or 1 argument (" +
379+
std::to_string(args.size()) + " given)", loc);
380+
}
381+
LFORTRAN_ASSERT(args.size()==1);
382+
ASR::expr_t *arg = args[0];
383+
ASR::ttype_t *type = ASRUtils::expr_type(arg);
384+
ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al,
385+
loc, 1, 1, nullptr, nullptr, 0));
386+
if (ASRUtils::is_integer(*type) || ASRUtils::is_real(*type)
387+
|| ASRUtils::is_complex(*type) || ASRUtils::is_logical(*type)) {
388+
throw SemanticError("Integer, Real, Complex and Boolean are not iterable "
389+
"and cannot be converted to List", loc);
390+
} else if (ASR::is_a<ASR::List_t>(*type)) {
391+
return arg;
392+
} else if (ASRUtils::is_character(*type)) {
393+
ASR::ttype_t *list_type = ASRUtils::TYPE(ASR::make_List_t(al, loc, str_type));
394+
LFORTRAN_ASSERT(ASRUtils::expr_value(arg) != nullptr)
395+
std::string c = ASR::down_cast<ASR::StringConstant_t>(arg)->m_s;
396+
Vec<ASR::expr_t*> list;
397+
list.reserve(al, c.length());
398+
std::string r;
399+
for (size_t i=0; i<c.length(); i++) {
400+
r.push_back(char(c[i]));
401+
list.push_back(al, ASR::down_cast<ASR::expr_t>(
402+
ASR::make_StringConstant_t(al, loc, s2c(al, r),
403+
str_type)));
404+
r.pop_back();
405+
}
406+
return ASR::down_cast<ASR::expr_t>(ASR::make_ListConstant_t(al, loc, list.p,
407+
list.size(), list_type));
408+
} else {
409+
throw SemanticError("'" + ASRUtils::type_to_str_python(type) +
410+
"' object conversion to List is not implemented ",
411+
arg->base.loc);
412+
}
413+
}
414+
374415
static ASR::expr_t *eval_round(Allocator &al, const Location &loc, Vec<ASR::expr_t*> &args) {
375416
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
376417
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4, nullptr, 0));

src/lpython/semantics/python_intrinsic_eval.h

Lines changed: 11 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace LFortran {
1212
struct IntrinsicNodeHandler {
1313

1414
typedef ASR::asr_t* (*intrinsic_eval_callback)(Allocator &, Vec<ASR::call_arg_t>,
15-
const Location &, ASR::ttype_t *);
15+
const Location &);
1616

1717
std::map<std::string, intrinsic_eval_callback> intrinsic_map;
1818

@@ -26,7 +26,6 @@ struct IntrinsicNodeHandler {
2626
{"reshape", &handle_reshape},
2727
{"ord", &handle_intrinsic_ord},
2828
{"chr", &handle_intrinsic_chr},
29-
{"list", &handle_intrinsic_list}
3029
};
3130
}
3231

@@ -35,20 +34,19 @@ struct IntrinsicNodeHandler {
3534
}
3635

3736
ASR::asr_t* get_intrinsic_node(std::string call_name,
38-
Allocator &al, const Location &loc, Vec<ASR::call_arg_t> args,
39-
ASR::ttype_t *ann_assign_target_type) {
37+
Allocator &al, const Location &loc, Vec<ASR::call_arg_t> args) {
4038
auto search = intrinsic_map.find(call_name);
4139
if (search != intrinsic_map.end()) {
4240
intrinsic_eval_callback cb = search->second;
43-
return cb(al, args, loc, ann_assign_target_type);
41+
return cb(al, args, loc);
4442
} else {
4543
throw SemanticError(call_name + " is not implemented yet",
4644
loc);
4745
}
4846
}
4947

5048
static ASR::asr_t* handle_intrinsic_int(Allocator &al, Vec<ASR::call_arg_t> args,
51-
const Location &loc, ASR::ttype_t * /*ann_assign_target_type*/) {
49+
const Location &loc) {
5250
ASR::expr_t *arg = nullptr, *value = nullptr;
5351
ASR::ttype_t *type = nullptr;
5452
if (args.size() > 1) {
@@ -129,7 +127,7 @@ struct IntrinsicNodeHandler {
129127

130128

131129
static ASR::asr_t* handle_intrinsic_float(Allocator &al, Vec<ASR::call_arg_t> args,
132-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
130+
const Location &loc) {
133131
ASR::expr_t *arg = nullptr, *value = nullptr;
134132
ASR::ttype_t *type = nullptr;
135133
if (args.size() > 1) {
@@ -184,7 +182,7 @@ struct IntrinsicNodeHandler {
184182
}
185183

186184
static ASR::asr_t* handle_intrinsic_bool(Allocator &al, Vec<ASR::call_arg_t> args,
187-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
185+
const Location &loc) {
188186
if (args.size() > 1) {
189187
throw SemanticError("Either 0 or 1 argument is expected in 'bool()'",
190188
loc);
@@ -255,7 +253,7 @@ struct IntrinsicNodeHandler {
255253

256254

257255
static ASR::asr_t* handle_intrinsic_str(Allocator &al, Vec<ASR::call_arg_t> args,
258-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
256+
const Location &loc) {
259257
if (args.size() > 1) {
260258
throw SemanticError("Either 0 or 1 argument is expected in 'str()'",
261259
loc);
@@ -316,7 +314,7 @@ struct IntrinsicNodeHandler {
316314
}
317315

318316
static ASR::asr_t* handle_intrinsic_len(Allocator &al, Vec<ASR::call_arg_t> args,
319-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
317+
const Location &loc) {
320318
if (args.size() != 1) {
321319
throw SemanticError("len() takes exactly one argument (" +
322320
std::to_string(args.size()) + " given)", loc);
@@ -372,7 +370,7 @@ struct IntrinsicNodeHandler {
372370
}
373371

374372
static ASR::asr_t* handle_reshape(Allocator &al, Vec<ASR::call_arg_t> args,
375-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
373+
const Location &loc) {
376374
if( args.size() != 2 ) {
377375
throw SemanticError("reshape accepts only 2 arguments, got " +
378376
std::to_string(args.size()) + " arguments instead.",
@@ -398,7 +396,7 @@ struct IntrinsicNodeHandler {
398396
}
399397

400398
static ASR::asr_t* handle_intrinsic_ord(Allocator &al, Vec<ASR::call_arg_t> args,
401-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
399+
const Location &loc) {
402400
if (args.size() != 1) {
403401
throw SemanticError("ord() takes exactly one argument (" +
404402
std::to_string(args.size()) + " given)", loc);
@@ -425,7 +423,7 @@ struct IntrinsicNodeHandler {
425423
}
426424

427425
static ASR::asr_t* handle_intrinsic_chr(Allocator &al, Vec<ASR::call_arg_t> args,
428-
const Location &loc, ASR::ttype_t */*ann_assign_target_type*/) {
426+
const Location &loc) {
429427
if (args.size() != 1) {
430428
throw SemanticError("chr() takes exactly one argument (" +
431429
std::to_string(args.size()) + " given)", loc);
@@ -454,60 +452,6 @@ struct IntrinsicNodeHandler {
454452
}
455453
}
456454

457-
static ASR::asr_t* handle_intrinsic_list(Allocator &al, Vec<ASR::call_arg_t> args,
458-
const Location &loc, ASR::ttype_t *ann_assign_target_type) {
459-
if (args.size() > 1) {
460-
throw SemanticError("list() takes 0 or 1 argument (" +
461-
std::to_string(args.size()) + " given)", loc);
462-
}
463-
ASR::expr_t *arg = args[0].m_value;
464-
if (args.size() == 0 || arg == nullptr) {
465-
if (ann_assign_target_type) {
466-
ASR::ttype_t *type = ASRUtils::get_contained_type(ann_assign_target_type);
467-
ASR::ttype_t* list_type = ASRUtils::TYPE(ASR::make_List_t(al, loc, type));
468-
Vec<ASR::expr_t*> list;
469-
list.reserve(al, 1);
470-
return ASR::make_ListConstant_t(al, loc, list.p,
471-
list.size(), list_type);
472-
}
473-
return nullptr;
474-
}
475-
ASR::ttype_t *type = ASRUtils::expr_type(arg);
476-
ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al,
477-
loc, 1, 1, nullptr, nullptr, 0));
478-
if (ASRUtils::is_integer(*type) || ASRUtils::is_real(*type)
479-
|| ASRUtils::is_complex(*type) || ASRUtils::is_logical(*type)) {
480-
throw SemanticError("Integer, Real, Complex and Boolean are not iterable "
481-
"and cannot be converted to List", loc);
482-
} else if (ASR::is_a<ASR::List_t>(*type)) {
483-
return (ASR::asr_t*) arg;
484-
} else if (ASRUtils::is_character(*type)) {
485-
ASR::ttype_t *list_type = ASRUtils::TYPE(ASR::make_List_t(al, loc, str_type));
486-
if (ASRUtils::expr_value(arg) != nullptr) {
487-
std::string c = ASR::down_cast<ASR::StringConstant_t>(arg)->m_s;
488-
Vec<ASR::expr_t*> list;
489-
list.reserve(al, c.length());
490-
std::string r;
491-
for (size_t i=0; i<c.length(); i++) {
492-
r.push_back(char(c[i]));
493-
list.push_back(al, ASR::down_cast<ASR::expr_t>(
494-
ASR::make_StringConstant_t(al, loc, s2c(al, r),
495-
str_type)));
496-
r.pop_back();
497-
}
498-
return ASR::make_ListConstant_t(al, loc, list.p,
499-
list.size(), list_type);
500-
}
501-
return ASR::make_Cast_t(
502-
al, loc, arg, ASR::cast_kindType::CharacterToList,
503-
list_type, nullptr);
504-
} else {
505-
throw SemanticError("'" + ASRUtils::type_to_str_python(type) +
506-
"' object conversion to List is not implemented ",
507-
arg->base.loc);
508-
}
509-
}
510-
511455
}; // IntrinsicNodeHandler
512456

513457
} // namespace LFortran

src/runtime/lpython_builtin.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,12 @@ def _lpython_str_startswith(s: str ,sub: str) -> bool:
732732
if res:
733733
res = res and (j == len(sub))
734734
return res
735+
736+
737+
def list(s: str) -> list[str]:
738+
l: list[str]
739+
l = []
740+
i: i32
741+
for i in range(len(s)):
742+
l.append(s[i])
743+
return l

tests/reference/asr-array_01_decl-39cf894.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-array_01_decl-39cf894.stdout",
9-
"stdout_hash": "8f3b88c700b2de8d8e8c2073f7b7ec6547357b98bd713ec454a413d9",
9+
"stdout_hash": "d1f77e5bef8795bf92a5c4c165376a842450b6ea54080d3c3cb79a4c",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-array_01_decl-39cf894.stdout

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/reference/asr-array_02_decl-e8f6874.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-array_02_decl-e8f6874.stdout",
9-
"stdout_hash": "57f80f9b84b5cce7826aef397b357c66dde7a6abe54664f0fb811354",
9+
"stdout_hash": "583481e0d85588a96f414b6e9dc04533305b8a5500eb0338e9793aac",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-array_02_decl-e8f6874.stdout

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

tests/reference/asr-cast-435c233.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-cast-435c233.stdout",
9-
"stdout_hash": "ca113f84d1d0ab5b9ff36ea064d4f82396f50ca8e8f34b5039c604d3",
9+
"stdout_hash": "afa219c8482c6ed824aaad5fa2292f636c6ef2dc1b8ad8a9f3248076",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(TranslationUnit (SymbolTable 1 {_lpython_main_program: (Function (SymbolTable 4 {}) _lpython_main_program [] [(SubroutineCall 1 f () [] ())] () Source Public Implementation () .false. .false. .false. .false. [] [] .false.), f: (Function (SymbolTable 2 {s: (Variable 2 s Local () () Default (Character 1 -2 () []) Source Public Required .false.), x: (Variable 2 x Local () () Default (List (Character 1 -2 () [])) Source Public Required .false.), y: (Variable 2 y Local () () Default (List (Character 1 -2 () [])) Source Public Required .false.)}) f [] [(= (Var 2 s) (StringConstant "lpython" (Character 1 7 () [])) ()) (= (Var 2 x) (Cast (Var 2 s) CharacterToList (List (Character 1 1 () [])) ()) ()) (= (Var 2 y) (ListConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () [])) (StringConstant "c" (Character 1 1 () []))] (List (Character 1 1 () []))) ()) (= (Var 2 x) (Var 2 y) ()) (= (Var 2 x) (ListConstant [(StringConstant "l" (Character 1 1 () [])) (StringConstant "p" (Character 1 1 () [])) (StringConstant "y" (Character 1 1 () [])) (StringConstant "t" (Character 1 1 () [])) (StringConstant "h" (Character 1 1 () [])) (StringConstant "o" (Character 1 1 () [])) (StringConstant "n" (Character 1 1 () []))] (List (Character 1 1 () []))) ())] () Source Public Implementation () .false. .false. .false. .false. [] [] .false.), main_program: (Program (SymbolTable 3 {}) main_program [] [(SubroutineCall 1 _lpython_main_program () [] ())])}) [])
1+
(TranslationUnit (SymbolTable 1 {_lpython_main_program: (Function (SymbolTable 96 {}) _lpython_main_program [] [(SubroutineCall 1 f () [] ())] () Source Public Implementation () .false. .false. .false. .false. [] [] .false.), f: (Function (SymbolTable 2 {list: (ExternalSymbol 2 list 4 list lpython_builtin [] list Private), s: (Variable 2 s Local () () Default (Character 1 -2 () []) Source Public Required .false.), x: (Variable 2 x Local () () Default (List (Character 1 -2 () [])) Source Public Required .false.), y: (Variable 2 y Local () () Default (List (Character 1 -2 () [])) Source Public Required .false.)}) f [] [(= (Var 2 s) (StringConstant "lpython" (Character 1 7 () [])) ()) (= (Var 2 x) (FunctionCall 2 list () [((Var 2 s))] (List (Character 1 -2 () [])) () ()) ()) (= (Var 2 y) (ListConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () [])) (StringConstant "c" (Character 1 1 () []))] (List (Character 1 1 () []))) ()) (= (Var 2 x) (FunctionCall 2 list () [((Var 2 y))] (List (Character 1 -2 () [])) () ()) ()) (= (Var 2 x) (FunctionCall 2 list () [((StringConstant "lpython" (Character 1 7 () [])))] (List (Character 1 -2 () [])) (ListConstant [(StringConstant "l" (Character 1 1 () [])) (StringConstant "p" (Character 1 1 () [])) (StringConstant "y" (Character 1 1 () [])) (StringConstant "t" (Character 1 1 () [])) (StringConstant "h" (Character 1 1 () [])) (StringConstant "o" (Character 1 1 () [])) (StringConstant "n" (Character 1 1 () []))] (List (Character 1 1 () []))) ()) ())] () Source Public Implementation () .false. .false. .false. .false. [] [] .false.), lpython_builtin: (IntrinsicModule lpython_builtin), main_program: (Program (SymbolTable 95 {}) main_program [] [(SubroutineCall 1 _lpython_main_program () [] ())])}) [])

tests/reference/asr-complex1-f26c460.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-complex1-f26c460.stdout",
9-
"stdout_hash": "fe7b6c186770420affb4691913b788c5c7e35c8fa09b2556cebff310",
9+
"stdout_hash": "db664f20fd0cca3c4119f9edb6fceffd57b98ecb7fcc82aba0f81dff",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

0 commit comments

Comments
 (0)