Skip to content

Commit

Permalink
Wrap args inside stringFormat in write + remove write visitor in `pri…
Browse files Browse the repository at this point in the history
…nt_arr` pass (lfortran#4669)
  • Loading branch information
assem2002 authored Aug 19, 2024
1 parent a290f51 commit b1d809a
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 100 deletions.
3 changes: 3 additions & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@ RUN(NAME format_11 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_12 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_13 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_14 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_15 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_16 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)
RUN(NAME format_17 LABELS gfortran llvm llvm_wasm llvm_wasm_emcc)

RUN(NAME submodule_01 LABELS gfortran)
RUN(NAME submodule_02 LABELS gfortran)
Expand Down
5 changes: 5 additions & 0 deletions integration_tests/format_15.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
program format_15
integer ::i
10 FORMAT (5A,I100)
write (*,10) ('*',i=1,5), 12345678
end program format_15
5 changes: 5 additions & 0 deletions integration_tests/format_16.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
program format_16
integer ::i
write(*,201) ('*',i=1,10)
201 FORMAT( 10X, 'whatever', /, 10A )
end program format_16
5 changes: 5 additions & 0 deletions integration_tests/format_17.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
program format_17
integer ::i
201 FORMAT( 3I1 )
write(*,201) (1,i=1,3)
end program format_17
14 changes: 10 additions & 4 deletions src/lfortran/semantics/ast_body_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,16 +707,22 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
a_fmt_constant = ASRUtils::EXPR(ASR::make_StringConstant_t(
al, a_fmt->base.loc, s2c(al, format_statements[label]), a_fmt_type));
}
if (a_fmt_constant) {
// Don't use stringFormat with single character argument
if (!a_fmt
&& _type == AST::stmtType::Write
&& a_values_vec.size() == 1
&& ASR::is_a<ASR::Character_t>(*ASRUtils::expr_type(a_values_vec[0]))){
tmp = ASR::make_FileWrite_t(al, loc, m_label, a_unit,
a_iomsg, a_iostat, a_id, a_values_vec.p,
a_values_vec.size(), a_separator, a_end, overloaded_stmt);
} else if ( _type == AST::stmtType::Write ) { // If not the previous case, Wrap everything in stringFormat.
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(
al, loc, -1, 0, nullptr));
ASR::expr_t* string_format = ASRUtils::EXPR(ASRUtils::make_StringFormat_t_util(al, a_fmt->base.loc,
ASR::expr_t* string_format = ASRUtils::EXPR(ASRUtils::make_StringFormat_t_util(al, a_fmt? a_fmt->base.loc : read_write_stmt.base.loc,
a_fmt_constant, a_values_vec.p, a_values_vec.size(), ASR::string_format_kindType::FormatFortran,
type, nullptr));
a_values_vec.reserve(al, 1);
a_values_vec.push_back(al, string_format);
}
if( _type == AST::stmtType::Write ) {
tmp = ASR::make_FileWrite_t(al, loc, m_label, a_unit,
a_iomsg, a_iostat, a_id, a_values_vec.p,
a_values_vec.size(), a_separator, a_end, overloaded_stmt);
Expand Down
12 changes: 10 additions & 2 deletions src/libasr/codegen/asr_to_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,16 @@ Kokkos::View<T*> from_std_vector(const std::vector<T> &v)
void visit_FileWrite(const ASR::FileWrite_t &x) {
std::string indent(indentation_level*indentation_spaces, ' ');
std::string out = indent + "std::cout ";
for (size_t i=0; i<x.n_values; i++) {
this->visit_expr(*x.m_values[i]);
//HACKISH way to handle print refactoring (always using stringformat).
// TODO : Implement stringformat visitor.
ASR::StringFormat_t* str_fmt = nullptr;
size_t n_values = x.n_values;
if(x.m_values[0] && ASR::is_a<ASR::StringFormat_t>(*x.m_values[0])) {
str_fmt = ASR::down_cast<ASR::StringFormat_t>(x.m_values[0]);
n_values = str_fmt->n_args;
}
for (size_t i=0; i<n_values; i++) {
str_fmt? this->visit_expr(*(str_fmt->m_args[i])): this->visit_expr(*x.m_values[i]);
out += "<< " + src + " ";
}
out += "<< std::endl;\n";
Expand Down
14 changes: 9 additions & 5 deletions src/libasr/codegen/asr_to_fortran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,12 +1057,16 @@ class ASRToFortranVisitor : public ASR::BaseVisitor<ASRToFortranVisitor>
}
if (x.n_values > 0 && is_a<ASR::StringFormat_t>(*x.m_values[0])) {
ASR::StringFormat_t *sf = down_cast<ASR::StringFormat_t>(x.m_values[0]);
visit_expr(*sf->m_fmt);
if (is_a<ASR::StringConstant_t>(*sf->m_fmt)
&& (!startswith(src, "\"(") || !endswith(src, ")\""))) {
src = "\"(" + src.substr(1, src.size()-2) + ")\"";
if(sf->m_fmt){
visit_expr(*sf->m_fmt);
if (is_a<ASR::StringConstant_t>(*sf->m_fmt)
&& (!startswith(src, "\"(") || !endswith(src, ")\""))) {
src = "\"(" + src.substr(1, src.size()-2) + ")\"";
}
r += src;
} else {
r += "*";
}
r += src;
} else {
r += "*";
}
Expand Down
7 changes: 6 additions & 1 deletion src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8292,8 +8292,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
//Create ArrayPhysicalCast to get the array pointer.
ASR::ttype_t* array_type = ASRUtils::TYPE(ASR::make_Array_t(al, v->base.loc,arr->m_type, arr->m_dims,
arr->n_dims,ASR::array_physical_typeType::FixedSizeArray));
ASR::expr_t* array_casted_to_pointer = ASRUtils::EXPR(ASR::make_ArrayPhysicalCast_t(al, v->base.loc, v,arr->m_physical_type,
ASR::expr_t* array_casted_to_pointer;
if(arr->m_physical_type == ASR::array_physical_typeType::PointerToDataArray){
array_casted_to_pointer = v; //Don't cast, It's already casted.
} else {
array_casted_to_pointer = ASRUtils::EXPR(ASR::make_ArrayPhysicalCast_t(al, v->base.loc, v,arr->m_physical_type,
ASR::array_physical_typeType::PointerToDataArray, array_type, nullptr));
}

// Create size argument.
int array_size;
Expand Down
119 changes: 61 additions & 58 deletions src/libasr/pass/print_arr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,64 +316,67 @@ class PrintArrVisitor : public PassUtils::PassVisitor<PrintArrVisitor>
write_body.clear();
}

void visit_FileWrite(const ASR::FileWrite_t& x) {
if (x.m_unit && ASRUtils::is_character(*ASRUtils::expr_type(x.m_unit))) {
// Skip for character write
return;
}
std::vector<ASR::expr_t*> write_body;
ASR::stmt_t* write_stmt;
ASR::stmt_t* empty_file_write_endl = ASRUtils::STMT(ASR::make_FileWrite_t(al, x.base.base.loc,
x.m_label, x.m_unit, nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr));
if(x.m_values && x.m_values[0] != nullptr && ASR::is_a<ASR::StringFormat_t>(*x.m_values[0])){
ASR::StringFormat_t* format = ASR::down_cast<ASR::StringFormat_t>(x.m_values[0]);
for (size_t i=0; i<format->n_args; i++) {
if (PassUtils::is_array(format->m_args[i])) {
if (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(format->m_args[i]))) {
print_fixed_sized_array(format->m_args[i], write_body, x.base.base.loc);
} else {
if (write_body.size() > 0) {
write_stmt = create_formatstmt(write_body, format,
x.base.base.loc, ASR::stmtType::FileWrite, x.m_unit, x.m_separator,
x.m_end, x.m_overloaded);
pass_result.push_back(al, write_stmt);
}
write_stmt = write_array_using_doloop(format->m_args[i], format, x.m_unit, x.base.base.loc);
pass_result.push_back(al, write_stmt);
pass_result.push_back(al, empty_file_write_endl);
}
} else {
write_body.push_back(format->m_args[i]);
}
}
if (write_body.size() > 0) {
write_stmt = create_formatstmt(write_body, format, x.base.base.loc,
ASR::stmtType::FileWrite, x.m_unit, x.m_separator,
x.m_end, x.m_overloaded);
pass_result.push_back(al, write_stmt);
}
return;
}
for (size_t i=0; i<x.n_values; i++) {
// DIVERGENCE between LFortran and LPython
// If a pointer array variable is provided
// then it will be printed as a normal array.
if (PassUtils::is_array(x.m_values[i])) {
if (write_body.size() > 0) {
print_args_apart_from_arrays(write_body, x);
pass_result.push_back(al, empty_file_write_endl);
}
write_stmt = write_array_using_doloop(x.m_values[i], nullptr, x.m_unit, x.base.base.loc);
pass_result.push_back(al, write_stmt);
pass_result.push_back(al, empty_file_write_endl);
} else {
write_body.push_back(x.m_values[i]);
}
}
if (write_body.size() > 0) {
print_args_apart_from_arrays(write_body, x);
}
}
// TODO :: CREATE write visitor to loop on arrays of type `structType` only,
// otherwise arrays are handled by backend.

// void visit_FileWrite(const ASR::FileWrite_t& x) {
// if (x.m_unit && ASRUtils::is_character(*ASRUtils::expr_type(x.m_unit))) {
// // Skip for character write
// return;
// }
// std::vector<ASR::expr_t*> write_body;
// ASR::stmt_t* write_stmt;
// ASR::stmt_t* empty_file_write_endl = ASRUtils::STMT(ASR::make_FileWrite_t(al, x.base.base.loc,
// x.m_label, x.m_unit, nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr));
// if(x.m_values && x.m_values[0] != nullptr && ASR::is_a<ASR::StringFormat_t>(*x.m_values[0])){
// ASR::StringFormat_t* format = ASR::down_cast<ASR::StringFormat_t>(x.m_values[0]);
// for (size_t i=0; i<format->n_args; i++) {
// if (PassUtils::is_array(format->m_args[i])) {
// if (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(format->m_args[i]))) {
// print_fixed_sized_array(format->m_args[i], write_body, x.base.base.loc);
// } else {
// if (write_body.size() > 0) {
// write_stmt = create_formatstmt(write_body, format,
// x.base.base.loc, ASR::stmtType::FileWrite, x.m_unit, x.m_separator,
// x.m_end, x.m_overloaded);
// pass_result.push_back(al, write_stmt);
// }
// write_stmt = write_array_using_doloop(format->m_args[i], format, x.m_unit, x.base.base.loc);
// pass_result.push_back(al, write_stmt);
// pass_result.push_back(al, empty_file_write_endl);
// }
// } else {
// write_body.push_back(format->m_args[i]);
// }
// }
// if (write_body.size() > 0) {
// write_stmt = create_formatstmt(write_body, format, x.base.base.loc,
// ASR::stmtType::FileWrite, x.m_unit, x.m_separator,
// x.m_end, x.m_overloaded);
// pass_result.push_back(al, write_stmt);
// }
// return;
// }
// for (size_t i=0; i<x.n_values; i++) {
// // DIVERGENCE between LFortran and LPython
// // If a pointer array variable is provided
// // then it will be printed as a normal array.
// if (PassUtils::is_array(x.m_values[i])) {
// if (write_body.size() > 0) {
// print_args_apart_from_arrays(write_body, x);
// pass_result.push_back(al, empty_file_write_endl);
// }
// write_stmt = write_array_using_doloop(x.m_values[i], nullptr, x.m_unit, x.base.base.loc);
// pass_result.push_back(al, write_stmt);
// pass_result.push_back(al, empty_file_write_endl);
// } else {
// write_body.push_back(x.m_values[i]);
// }
// }
// if (write_body.size() > 0) {
// print_args_apart_from_arrays(write_body, x);
// }
// }

};

Expand Down
2 changes: 1 addition & 1 deletion src/libasr/runtime/lfortran_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,9 +952,9 @@ LFORTRAN_API char* _lcompilers_string_format_fortran(int count, const char* form
struct array_iteration_state array_state;
array_state.array_size = -1;
array_state.current_arr_index = -1;
int32_t current_arg_type_int = -1; // holds int that represents type of argument.
while (1) {
int scale = 0;
int32_t current_arg_type_int = -1; // holds int that represents type of argument.
bool is_array = false;
bool array_looping = false;
for (int i = item_start; i < format_values_count; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-intrinsics_open_close_read_write-a696eca.stdout",
"stdout_hash": "e57c139379d37e9e2669c3860b9e53706b6cf4c3ff0e949d7ec49d0a",
"stdout_hash": "47aaf5efcb6e4d3287dd4a7ee1820ac5cca05be8883597c7e2f724b5",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
36 changes: 21 additions & 15 deletions tests/reference/asr-intrinsics_open_close_read_write-a696eca.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -414,22 +414,28 @@
()
()
()
[(ArrayItem
(Var 2 p)
[(()
(Var 2 i)
())]
(Real 4)
ColMajor
[(StringFormat
()
)
(ArrayItem
(Var 2 q)
[(()
(Var 2 i)
())]
(Real 4)
ColMajor
[(ArrayItem
(Var 2 p)
[(()
(Var 2 i)
())]
(Real 4)
ColMajor
()
)
(ArrayItem
(Var 2 q)
[(()
(Var 2 i)
())]
(Real 4)
ColMajor
()
)]
FormatFortran
(Character -1 0 ())
()
)]
()
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/asr-print3-5f4fc26.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-print3-5f4fc26.stdout",
"stdout_hash": "ec9ac9af5097e844c8f19f225064fa542ec859f3a5b14131a35d4a14",
"stdout_hash": "9a4448373ec29e4be8ac99c62a815333b84230c1354c23c6eb5aad58",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
16 changes: 11 additions & 5 deletions tests/reference/asr-print3-5f4fc26.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,17 @@
()
()
()
[(StringConstant
"x is "
(Character 1 5 ())
)
(Var 2 x)]
[(StringFormat
()
[(StringConstant
"x is "
(Character 1 5 ())
)
(Var 2 x)]
FormatFortran
(Character -1 0 ())
()
)]
()
()
()
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/llvm-print_01-63a0480.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "llvm-print_01-63a0480.stdout",
"stdout_hash": "1f0c2755fe64a9536e9652fe73f55a11f392a1a6d7751ffef890ff01",
"stdout_hash": "d8fc72b67635a05b631f8ee83733598b3c28f9ca4edefbc9b4c9432c",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
12 changes: 8 additions & 4 deletions tests/reference/llvm-print_01-63a0480.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ source_filename = "LFortran"
@2 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1
@3 = private unnamed_addr constant [2 x i8] c" \00", align 1
@4 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1
@5 = private unnamed_addr constant [21 x i8] c"%d%s%d%s%d%s%d%s%d%s\00", align 1
@5 = private unnamed_addr constant [5 x i8] c"%s%s\00", align 1

define i32 @main(i32 %0, i8** %1) {
.entry:
Expand All @@ -24,10 +24,14 @@ define i32 @main(i32 %0, i8** %1) {
%9 = call i8* (i32, i8*, ...) @_lcompilers_string_format_fortran(i32 10, i8* null, i32 2, i64 %3, i32 2, i64 1, i32 2, i64 3, i32 2, i64 %5, i32 2, i64 %8)
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @2, i32 0, i32 0), i8* %9, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @1, i32 0, i32 0))
%10 = load i32, i32* %x1, align 4
%11 = load i32, i32* %x1, align 4
%11 = sext i32 %10 to i64
%12 = load i32, i32* %x1, align 4
%13 = add i32 25, %12
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @5, i32 0, i32 0), i32 %10, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @3, i32 0, i32 0), i32 1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @3, i32 0, i32 0), i32 3, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @3, i32 0, i32 0), i32 %11, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @3, i32 0, i32 0), i32 %13, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @4, i32 0, i32 0))
%13 = sext i32 %12 to i64
%14 = load i32, i32* %x1, align 4
%15 = add i32 25, %14
%16 = sext i32 %15 to i64
%17 = call i8* (i32, i8*, ...) @_lcompilers_string_format_fortran(i32 10, i8* null, i32 2, i64 %11, i32 2, i64 1, i32 2, i64 3, i32 2, i64 %13, i32 2, i64 %16)
call void (i8*, ...) @_lfortran_printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @5, i32 0, i32 0), i8* %17, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @4, i32 0, i32 0))
br label %return

return: ; preds = %.entry
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/run-print3-b6beca0.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "run-print3-b6beca0.stdout",
"stdout_hash": "7c21b856c7d57d23e4c5b7e5b7b5dd37d8cf077a8a5fe5826558f4e1",
"stdout_hash": "b7a8e92f3ad654f0db00b67a50310de56893a8ef6bcf296f40cdece5",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/run-print3-b6beca0.stdout
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
x is 24
x is 24
x is 24
ok
ok

0 comments on commit b1d809a

Please sign in to comment.