Skip to content

Commit 2991c33

Browse files
support to print lists in REPL
1 parent a77c390 commit 2991c33

9 files changed

Lines changed: 270 additions & 88 deletions

File tree

src/bin/lpython.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,16 @@ int interactive_python_repl(
10071007
}
10081008
break;
10091009
}
1010+
case (LCompilers::PythonCompiler::EvalResult::structt) : {
1011+
if (verbose) {
1012+
std::cout << "Return type: "
1013+
<< LCompilers::ASRUtils::get_type_code(r.structure.ttype)
1014+
<< std::endl;
1015+
}
1016+
if (verbose) section("Result:");
1017+
std::cout << fe.string_aggregate_type(r) << std::endl;
1018+
break;
1019+
}
10101020
case (LCompilers::PythonCompiler::EvalResult::none) : {
10111021
if (verbose) {
10121022
std::cout << "Return type: none" << std::endl;

src/libasr/codegen/evaluator.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ std::string LLVMModule::str()
9090
return LLVMEvaluator::module_to_string(*m_m);
9191
}
9292

93+
llvm::Function *LLVMModule::get_function(const std::string &fn_name) {
94+
llvm::Module *m = m_m.get();
95+
return m->getFunction(fn_name);
96+
}
97+
9398
std::string LLVMModule::get_return_type(const std::string &fn_name)
9499
{
95100
llvm::Module *m = m_m.get();
@@ -121,12 +126,9 @@ std::string LLVMModule::get_return_type(const std::string &fn_name)
121126
return "complex4";
122127
} else if (startswith(std::string(st->getName()), "complex_8")) {
123128
return "complex8";
124-
} else {
125-
throw LCompilersException("LLVMModule::get_return_type(): Struct return type `" + std::string(st->getName()) + "` not supported");
126129
}
127-
} else {
128-
throw LCompilersException("LLVMModule::get_return_type(): Noname struct return type not supported");
129130
}
131+
return "struct";
130132
} else if (type->isVectorTy()) {
131133
// Used for passing complex_4 on some platforms
132134
return "complex4";
@@ -377,6 +379,10 @@ llvm::LLVMContext &LLVMEvaluator::get_context()
377379
return *context;
378380
}
379381

382+
const llvm::DataLayout &LLVMEvaluator::get_jit_data_layout() {
383+
return jit->getDataLayout();
384+
}
385+
380386
void LLVMEvaluator::print_targets()
381387
{
382388
llvm::InitializeNativeTarget();

src/libasr/codegen/evaluator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace llvm {
1919
class Module;
2020
class Function;
2121
class TargetMachine;
22+
class DataLayout;
2223
namespace orc {
2324
class KaleidoscopeJIT;
2425
}
@@ -35,6 +36,7 @@ class LLVMModule
3536
std::string str();
3637
// Return a function return type as a string (real / integer)
3738
std::string get_return_type(const std::string &fn_name);
39+
llvm::Function *get_function(const std::string &fn_name);
3840
};
3941

4042
class LLVMEvaluator
@@ -60,6 +62,7 @@ class LLVMEvaluator
6062
static std::string module_to_string(llvm::Module &m);
6163
static void print_version_message();
6264
llvm::LLVMContext &get_context();
65+
const llvm::DataLayout &get_jit_data_layout();
6366
static void print_targets();
6467
static std::string get_default_target_triple();
6568

src/libasr/pass/global_stmts.cpp

Lines changed: 46 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -45,58 +45,14 @@ void pass_wrap_global_stmts(Allocator &al,
4545
ASR::expr_t *target;
4646
ASR::expr_t *value = EXPR(unit.m_items[i]);
4747
// Create a new variable with the right type
48-
if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Integer) {
49-
s.from_str(al, fn_name_s + std::to_string(idx));
50-
var_name = s.c_str(al);
51-
52-
int a_kind = down_cast<ASR::Integer_t>(ASRUtils::expr_type(value))->m_kind;
53-
54-
type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, a_kind));
55-
return_var = ASR::make_Variable_t(al, loc,
56-
fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
57-
ASR::storage_typeType::Default, type,
58-
nullptr, ASR::abiType::BindC,
59-
ASR::Public, ASR::presenceType::Required, false);
60-
return_var_ref = EXPR(ASR::make_Var_t(al, loc,
61-
down_cast<ASR::symbol_t>(return_var)));
62-
fn_scope->add_symbol(std::string(var_name), down_cast<ASR::symbol_t>(return_var));
63-
target = return_var_ref;
64-
idx++;
65-
} else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::UnsignedInteger) {
66-
s.from_str(al, fn_name_s + std::to_string(idx));
67-
var_name = s.c_str(al);
68-
69-
int a_kind = down_cast<ASR::UnsignedInteger_t>(ASRUtils::expr_type(value))->m_kind;
70-
71-
type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, a_kind));
72-
return_var = ASR::make_Variable_t(al, loc,
73-
fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
74-
ASR::storage_typeType::Default, type,
75-
nullptr, ASR::abiType::BindC,
76-
ASR::Public, ASR::presenceType::Required, false);
77-
return_var_ref = EXPR(ASR::make_Var_t(al, loc,
78-
down_cast<ASR::symbol_t>(return_var)));
79-
fn_scope->add_symbol(std::string(var_name), down_cast<ASR::symbol_t>(return_var));
80-
target = return_var_ref;
81-
idx++;
82-
} else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Logical) {
83-
s.from_str(al, fn_name_s + std::to_string(idx));
84-
var_name = s.c_str(al);
85-
86-
int a_kind = down_cast<ASR::Logical_t>(ASRUtils::expr_type(value))->m_kind;
87-
88-
type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, a_kind));
89-
return_var = ASR::make_Variable_t(al, loc,
90-
fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
91-
ASR::storage_typeType::Default, type,
92-
nullptr, ASR::abiType::BindC,
93-
ASR::Public, ASR::presenceType::Required, false);
94-
return_var_ref = EXPR(ASR::make_Var_t(al, loc,
95-
down_cast<ASR::symbol_t>(return_var)));
96-
fn_scope->add_symbol(std::string(var_name), down_cast<ASR::symbol_t>(return_var));
97-
target = return_var_ref;
98-
idx++;
99-
} else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Real) {
48+
if ((ASRUtils::expr_type(value)->type == ASR::ttypeType::Integer) ||
49+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::UnsignedInteger) ||
50+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Logical) ||
51+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Real) ||
52+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Complex) ||
53+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Character) ||
54+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::List) ||
55+
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Tuple)) {
10056
s.from_str(al, fn_name_s + std::to_string(idx));
10157
var_name = s.c_str(al);
10258
type = ASRUtils::expr_type(value);
@@ -110,22 +66,7 @@ void pass_wrap_global_stmts(Allocator &al,
11066
fn_scope->add_symbol(std::string(var_name), down_cast<ASR::symbol_t>(return_var));
11167
target = return_var_ref;
11268
idx++;
113-
} else if ((ASRUtils::expr_type(value)->type == ASR::ttypeType::Complex) ||
114-
(ASRUtils::expr_type(value)->type == ASR::ttypeType::Character)) {
115-
s.from_str(al, fn_name_s + std::to_string(idx));
116-
var_name = s.c_str(al);
117-
type = ASRUtils::expr_type(value);
118-
return_var = ASR::make_Variable_t(al, loc,
119-
fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
120-
ASR::storage_typeType::Default, type,
121-
nullptr, ASR::abiType::BindC,
122-
ASR::Public, ASR::presenceType::Required, false);
123-
return_var_ref = EXPR(ASR::make_Var_t(al, loc,
124-
down_cast<ASR::symbol_t>(return_var)));
125-
fn_scope->add_symbol(std::string(var_name), down_cast<ASR::symbol_t>(return_var));
126-
target = return_var_ref;
127-
idx++;
128-
} else {
69+
} else {
12970
throw LCompilersException("Return type not supported in interactive mode");
13071
}
13172
ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target, value, nullptr));
@@ -142,6 +83,43 @@ void pass_wrap_global_stmts(Allocator &al,
14283
if (return_var) {
14384
// The last defined `return_var` is the actual return value
14485
ASR::down_cast2<ASR::Variable_t>(return_var)->m_intent = ASRUtils::intent_return_var;
86+
std::string global_underscore_name = "_" + fn_name_s;
87+
s.from_str(al, global_underscore_name);
88+
89+
ASR::asr_t *global_underscore = ASR::make_Variable_t(al, loc,
90+
unit.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
91+
ASR::storage_typeType::Default, type,
92+
nullptr, ASR::abiType::Source,
93+
ASR::Public, ASR::presenceType::Required, false);
94+
ASR::expr_t * global_underscore_ref = EXPR(ASR::make_Var_t(al, loc, down_cast<ASR::symbol_t>(global_underscore)));
95+
96+
if (fn_scope->parent->get_symbol(global_underscore_name) != nullptr) {
97+
throw LCompilersException("Global variable already defined");
98+
}
99+
unit.m_symtab->add_symbol(global_underscore_name, down_cast<ASR::symbol_t>(global_underscore));
100+
ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, global_underscore_ref, return_var_ref, nullptr));
101+
body.push_back(al, asr_stmt);
102+
103+
// if ((type->type == ASR::ttypeType::Tuple) ||
104+
// (type->type == ASR::ttypeType::List)) {
105+
// s.from_str(al, fn_name_s + std::to_string(idx));
106+
// var_name = s.c_str(al);
107+
108+
// ASR::ttype_t *type_pointer = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, type));
109+
// ASR::expr_t *value = EXPR(ASR::make_GetPointer_t(al, loc, global_underscore_ref, type_pointer, nullptr));
110+
111+
// return_var = ASR::make_Variable_t(al, loc,
112+
// fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr,
113+
// ASR::storage_typeType::Default, type_pointer,
114+
// nullptr, ASR::abiType::BindC,
115+
// ASR::Public, ASR::presenceType::Required, false);
116+
// return_var_ref = EXPR(ASR::make_Var_t(al, loc, down_cast<ASR::symbol_t>(return_var)));
117+
// ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, return_var_ref, value, nullptr));
118+
// body.push_back(al, asr_stmt);
119+
// idx++;
120+
// return_var_ref = nullptr;
121+
// return_var = nullptr;
122+
// }
145123
}
146124

147125
ASR::asr_t *fn = ASRUtils::make_Function_t_util(

src/lpython/python_evaluator.cpp

Lines changed: 141 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#ifdef HAVE_LFORTRAN_LLVM
1717
#include <libasr/codegen/evaluator.h>
1818
#include <libasr/codegen/asr_to_llvm.h>
19+
#include <llvm/IR/Function.h>
20+
#include <llvm/IR/Type.h>
21+
#include <llvm/IR/DataLayout.h>
1922
#else
2023
namespace LCompilers {
2124
class LLVMEvaluator {};
@@ -120,10 +123,35 @@ Result<PythonCompiler::EvalResult> PythonCompiler::evaluate(
120123
}
121124

122125
bool call_run_fn = false;
123-
std::string return_type;
124-
if (m->get_return_type(run_fn) != "none") {
125-
call_run_fn = true;
126-
return_type = m->get_return_type(run_fn);
126+
std::string return_type = m->get_return_type(run_fn);
127+
if (return_type != "none") {
128+
call_run_fn = true;
129+
}
130+
131+
llvm::Type *type = nullptr;
132+
ASR::symbol_t *f = symbol_table->get_symbol("_" + run_fn);
133+
if ((return_type == "struct") && (f)) {
134+
llvm::Function *fn = m->get_function(run_fn);
135+
type = fn->getReturnType();
136+
LCOMPILERS_ASSERT(type->isStructTy())
137+
138+
const llvm::DataLayout &dl = e->get_jit_data_layout();
139+
size_t elements_count = type->getStructNumElements();
140+
LCompilers::Vec<size_t> offsets;
141+
offsets.reserve(al, elements_count);
142+
for (size_t i = 0; i < elements_count; i++) {
143+
size_t offset = dl.getStructLayout((llvm::StructType*)type)->getElementOffset(i);
144+
offsets.push_back(al, offset);
145+
}
146+
result.structure.offsets = offsets.p;
147+
148+
result.structure.ttype = ASR::down_cast<ASR::Variable_t>(f)->m_type;
149+
if (result.structure.ttype->type == ASR::ttypeType::List) {
150+
type = type->getStructElementType(2);
151+
LCOMPILERS_ASSERT(type->isPointerTy())
152+
result.structure.element_size = e->get_jit_data_layout().getTypeAllocSize(
153+
type->getNonOpaquePointerElementType());
154+
}
127155
}
128156

129157
e->add_module(std::move(m));
@@ -213,6 +241,14 @@ Result<PythonCompiler::EvalResult> PythonCompiler::evaluate(
213241
bool r = e->execfn<bool>(run_fn);
214242
result.type = EvalResult::boolean;
215243
result.b = r;
244+
} else if (return_type == "struct") {
245+
e->execfn<void>(run_fn);
246+
if (f) {
247+
void *r = (void*)e->get_symbol_address("_" + run_fn);
248+
LCOMPILERS_ASSERT(r)
249+
result.structure.structure = r;
250+
result.type = EvalResult::structt;
251+
}
216252
} else if (return_type == "void") {
217253
e->execfn<void>(run_fn);
218254
result.type = EvalResult::statement;
@@ -449,4 +485,105 @@ Result<std::string> PythonCompiler::get_asm(
449485
}
450486

451487

488+
void print_type(ASR::ttype_t *t, void *data, std::string &result);
489+
490+
std::string PythonCompiler::string_aggregate_type(const struct EvalResult &r) {
491+
ASR::ttype_t *asr_type = r.structure.ttype;
492+
void *data = r.structure.structure;
493+
size_t *offsets = r.structure.offsets;
494+
size_t element_size = r.structure.element_size;
495+
496+
std::string result;
497+
498+
if (asr_type->type == ASR::ttypeType::List) {
499+
int32_t size = *(int32_t*)(((char*)data)+offsets[0]);
500+
void *array = *(void**)(((char*)data)+offsets[2]);
501+
// int32_t capacity = *(int32_t*)(((char*)data)+offsets[1]);
502+
// std::cout << "size: " << size << " capacity: " << capacity << " array: " << array << std::endl;
503+
ASR::ttype_t *element_ttype = ASR::down_cast<ASR::List_t>(asr_type)->m_type;
504+
505+
result += "[";
506+
for (int32_t i = 0; i < size - 1; i++) {
507+
print_type(element_ttype, ((char*)array)+(i*element_size), result);
508+
result += ", ";
509+
}
510+
print_type(element_ttype, ((char*)array)+((size - 1)*element_size), result);
511+
result += "]";
512+
513+
} else {
514+
throw LCompilersException("PythonCompiler::evaluate(): Return type not supported");
515+
}
516+
517+
return result;
518+
}
519+
520+
void print_type(ASR::ttype_t *t, void *data, std::string &result) {
521+
switch (t->type) {
522+
case ASR::ttypeType::Logical:
523+
result += (*(bool*)data ? "True" : "False");
524+
break;
525+
case ASR::ttypeType::Integer: {
526+
int64_t a_kind = ASR::down_cast<ASR::Integer_t>(t)->m_kind;
527+
switch (a_kind) {
528+
case 1:
529+
result += std::to_string(int(*(int8_t*)data));
530+
break;
531+
case 2:
532+
result += std::to_string(*(int16_t*)data);
533+
break;
534+
case 4:
535+
result += std::to_string(*(int32_t*)data);
536+
break;
537+
case 8:
538+
result += std::to_string(*(int64_t*)data);
539+
break;
540+
default:
541+
throw LCompilersException("Unaccepted int size");
542+
}
543+
break;
544+
}
545+
case ASR::ttypeType::UnsignedInteger: {
546+
int64_t a_kind = ASR::down_cast<ASR::UnsignedInteger_t>(t)->m_kind;
547+
switch (a_kind) {
548+
case 1:
549+
result += std::to_string(int(*(uint8_t*)data));
550+
break;
551+
case 2:
552+
result += std::to_string(*(uint16_t*)data);
553+
break;
554+
case 4:
555+
result += std::to_string(*(uint32_t*)data);
556+
break;
557+
case 8:
558+
result += std::to_string(*(uint64_t*)data);
559+
break;
560+
default:
561+
throw LCompilersException("Unaccepted int size");
562+
}
563+
break;
564+
}
565+
case ASR::ttypeType::Real: {
566+
int64_t a_kind = ASR::down_cast<ASR::Real_t>(t)->m_kind;
567+
switch (a_kind) {
568+
case 4:
569+
result += std::to_string(*(float*)data);
570+
break;
571+
case 8:
572+
result += std::to_string(*(double*)data);
573+
break;
574+
default:
575+
throw LCompilersException("Unaccepted real size");
576+
}
577+
break;
578+
}
579+
case ASR::ttypeType::Character:
580+
result += '"';
581+
result += std::string(*(char**)data); // TODO: replace \n with \\n
582+
result += '"';
583+
break;
584+
default:
585+
throw LCompilersException("PythonCompiler::print_type(): type not supported");
586+
}
587+
}
588+
452589
} // namespace LCompilers::LPython

0 commit comments

Comments
 (0)