Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Move visit_Call in Common Visitor #2013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions integration_tests/structs_10.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ class Vec:

@dataclass
class MatVec:
mat: Mat = Mat([f64(0.0), f64(0.0)])
vec: Vec = Vec([f64(0.0), f64(0.0)])
# TODO: this should ideally be the following:
# mat: Mat = Mat(empty((2, 2), dtype=float64))
# vec: Vec = Vec(empty(2, dtype=float64))
# But since lpython ignores empty, the following is just a workaround.
# Follow the discussions here: https://github.com/lcompilers/lpython/issues/1809
mat: Mat = Mat(2.0)
vec: Vec = Vec(2.0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is forced by moving visit_Call and visit_List into the common visitor. Both the original mat: Mat = Mat([f64(0.0), f64(0.0)]) and the new mat: Mat = Mat(2.0) is incorrect so I think it's fine for now. The proper fix is to use mat: Mat = Mat(empty((2, 2), dtype=float64)).


def rotate(mat_vec: MatVec) -> f64[2]:
rotated_vec: f64[2] = empty(2, dtype=float64)
Expand Down
21 changes: 20 additions & 1 deletion integration_tests/structs_27.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lpython import dataclass, i32
from lpython import dataclass, i32, u16, f32


@dataclass
Expand All @@ -7,6 +7,14 @@ class StringIO:
_0cursor : i32 = 10
_len : i32 = 1

@dataclass
class StringIONew:
_buf : str
_0cursor : i32 = i32(142)
_len : i32 = i32(2439)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR assigns this to the "value" member of Variable. I am not sure if our code assumes that this is a constant, so the backend doesn't even visit this variable and uses the value instead. If so, then this won't work, since any modifications to _len will be lost.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a test for modifying _len.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is documentation for Variable:

`symbolic_value` the optional symbolic expression to initialize the variable
(e.g. `2+3+4+x`), this value must be compile time, but it is not necessarily a
constant (e.g., can contain binary operations, other variables, etc.)

`value` the optional constant expression holding the compile time value
(e.g. `5`, or `5.5`), it is a compile time constant.

So value and symbolic_value must be compile time constants. So let's require that for now as well in LPython.

A separate question is if they are set, if the Variable itself has to be a constant or not. I would say if it has to be a constant, then it should have a type Const. Otherwise it can change, which means value is the initial value, but the runtime value can change.

Copy link
Collaborator Author

@Smit-create Smit-create Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: This does work on an assignment but makes things more complex as it requires more methods to be moved to CommonVisitor.

Now, this problem gets trickier as Structs don't have a body, and, so AnnAssign which is an Assignment to the struct variables isn't possible with the current design.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that we may do is add a field in the Struct to contain initializers for all it's variable members like the following:

     | StructType(symbol_table symtab, identifier name, identifier* dependencies,
         identifier* members, abi abi, access access, bool is_packed, bool is_abstract,
-        expr? alignment, symbol? parent)
+        expr* initializers, expr? alignment, symbol? parent)

_var1 : u16 = u16(23)
_var2 : f32 = f32(30.24)


def test_issue_1928():
integer_asr : str = '(Integer 4 [])'
Expand Down Expand Up @@ -47,4 +55,15 @@ def test_issue_1928():
assert test_dude4._0cursor == 31


def test_issue_1981():
integer_asr : str = '(Integer 4 [])'
test_dude : StringIONew = StringIONew(integer_asr)
assert test_dude._buf == integer_asr
assert test_dude._len == 2439
assert test_dude._0cursor == 142
assert test_dude._var1 == u16(23)
assert abs(test_dude._var2 - f32(30.24)) < f32(1e-5)


test_issue_1981()
test_issue_1928()
7 changes: 4 additions & 3 deletions src/libasr/codegen/asr_to_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,12 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
void allocate_array_members_of_struct(ASR::StructType_t* der_type_t, std::string& sub,
std::string indent, std::string name) {
for( auto itr: der_type_t->m_symtab->get_scope() ) {
if( ASR::is_a<ASR::UnionType_t>(*itr.second) ||
ASR::is_a<ASR::StructType_t>(*itr.second) ) {
ASR::symbol_t *sym_type = ASRUtils::symbol_get_past_external(itr.second);
if( ASR::is_a<ASR::UnionType_t>(*sym_type) ||
ASR::is_a<ASR::StructType_t>(*sym_type) ) {
continue ;
}
ASR::ttype_t* mem_type = ASRUtils::symbol_type(itr.second);
ASR::ttype_t* mem_type = ASRUtils::symbol_type(sym_type);
if( ASRUtils::is_character(*mem_type) ) {
sub += indent + name + "->" + itr.first + " = NULL;\n";
} else if( ASRUtils::is_array(mem_type) &&
Expand Down
5 changes: 5 additions & 0 deletions src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,11 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) {
last_expr_precedence = 2;
}

void visit_UnsignedIntegerConstant(const ASR::UnsignedIntegerConstant_t &x) {
src = std::to_string(x.m_n);
last_expr_precedence = 2;
}

void visit_RealConstant(const ASR::RealConstant_t &x) {
// TODO: remove extra spaces from the front of double_to_scientific result
src = double_to_scientific(x.m_r);
Expand Down
13 changes: 7 additions & 6 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3308,14 +3308,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
ASRUtils::symbol_get_past_external(struct_t->m_derived_type));
std::string struct_type_name = struct_type_t->m_name;
for( auto item: struct_type_t->m_symtab->get_scope() ) {
if( ASR::is_a<ASR::ClassProcedure_t>(*item.second) ||
ASR::is_a<ASR::GenericProcedure_t>(*item.second) ||
ASR::is_a<ASR::UnionType_t>(*item.second) ||
ASR::is_a<ASR::StructType_t>(*item.second) ||
ASR::is_a<ASR::CustomOperator_t>(*item.second) ) {
ASR::symbol_t *sym_type = ASRUtils::symbol_get_past_external(item.second);
if( ASR::is_a<ASR::ClassProcedure_t>(*sym_type) ||
ASR::is_a<ASR::GenericProcedure_t>(*sym_type) ||
ASR::is_a<ASR::UnionType_t>(*sym_type) ||
ASR::is_a<ASR::StructType_t>(*sym_type) ||
ASR::is_a<ASR::CustomOperator_t>(*sym_type) ) {
continue ;
}
ASR::ttype_t* symbol_type = ASRUtils::symbol_type(item.second);
ASR::ttype_t* symbol_type = ASRUtils::symbol_type(sym_type);
int idx = name2memidx[struct_type_name][item.first];
llvm::Value* ptr_member = llvm_utils->create_gep(ptr, idx);
ASR::Variable_t* v = nullptr;
Expand Down
Loading