Skip to content

Implement real and imag for complex #256

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

Merged
merged 10 commits into from
Mar 24, 2022
Merged
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
1 change: 1 addition & 0 deletions integration_tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"test_c_interop_01.py",
"test_generics_01.py",
"test_cmath.py",
"test_complex.py"
]

# CPython tests only
Expand Down
16 changes: 16 additions & 0 deletions integration_tests/test_complex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from ltypes import f64, c64

def test_real_imag():
x: c64
x = 2 + 3j
a: f64
b: f64
eps: f64
eps = 1e-12
a = x.real
b = x.imag
assert abs(a - 2) < eps
# TODO: below test should work
# assert abs(b - 3) < eps

test_real_imag()
4 changes: 2 additions & 2 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4032,6 +4032,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
throw CodeGenError("Function LFortran interfaces not implemented yet");
} else if (s->m_abi == ASR::abiType::Interactive) {
h = get_hash((ASR::asr_t*)s);
} else if (s->m_abi == ASR::abiType::BindC) {
h = get_hash((ASR::asr_t*)s);
} else if (s->m_abi == ASR::abiType::Intrinsic || intrinsic_function) {
std::string func_name = s->m_name;
if( fname2arg_type.find(func_name) != fname2arg_type.end() ) {
Expand All @@ -4049,8 +4051,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
h = get_hash((ASR::asr_t*)s);
}
}
} else if (s->m_abi == ASR::abiType::BindC) {
h = get_hash((ASR::asr_t*)s);
} else {
throw CodeGenError("ABI type not implemented yet.");
}
Expand Down
60 changes: 58 additions & 2 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab,
for (auto &item : mod2->m_symtab->scope) {
if (ASR::is_a<ASR::Subroutine_t>(*item.second)) {
ASR::Subroutine_t *s = ASR::down_cast<ASR::Subroutine_t>(item.second);
s->m_abi = ASR::abiType::Intrinsic;
if (s->m_abi == ASR::abiType::Source) {
s->m_abi = ASR::abiType::Intrinsic;
}
if (s->n_body == 0) {
std::string name = s->m_name;
if (name == "ubound" || name == "lbound") {
Expand All @@ -164,7 +166,9 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab,
}
if (ASR::is_a<ASR::Function_t>(*item.second)) {
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(item.second);
s->m_abi = ASR::abiType::Intrinsic;
if (s->m_abi == ASR::abiType::Source) {
s->m_abi = ASR::abiType::Intrinsic;
}
if (s->n_body == 0) {
std::string name = s->m_name;
if (name == "ubound" || name == "lbound") {
Expand Down Expand Up @@ -1837,6 +1841,58 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {

}

void visit_Attribute(const AST::Attribute_t &x) {
if (AST::is_a<AST::Name_t>(*x.m_value)) {
std::string value = AST::down_cast<AST::Name_t>(x.m_value)->m_id;
ASR::symbol_t *t = current_scope->scope[value];
if (!t) {
throw SemanticError("'" + value + "' is not defined in the scope",
x.base.base.loc);
}
if (ASR::is_a<ASR::Variable_t>(*t)) {
ASR::Variable_t *var = ASR::down_cast<ASR::Variable_t>(t);
if (ASRUtils::is_complex(*var->m_type)) {
std::string attr = x.m_attr;
if (attr == "imag") {
ASR::expr_t *val = ASR::down_cast<ASR::expr_t>(ASR::make_Var_t(al, x.base.base.loc, t));
ASR::symbol_t *fn_imag = resolve_intrinsic_function(x.base.base.loc, "_lpython_imag");
Vec<ASR::call_arg_t> args;
args.reserve(al, 1);
ASR::call_arg_t arg;
arg.loc = val->base.loc;
arg.m_value = val;
args.push_back(al, arg);
make_call_helper(al, fn_imag, current_scope, args, "_lpython_imag", x.base.base.loc);
return;
} else if (attr == "real") {
ASR::expr_t *val = ASR::down_cast<ASR::expr_t>(ASR::make_Var_t(al, x.base.base.loc, t));
int kind = ASRUtils::extract_kind_from_ttype_t(var->m_type);
ASR::ttype_t *dest_type = ASR::down_cast<ASR::ttype_t>(ASR::make_Real_t(al, x.base.base.loc,
kind, nullptr, 0));
tmp = (ASR::asr_t*)ASR::down_cast<ASR::expr_t>(ASR::make_ImplicitCast_t(
al, val->base.loc, val, ASR::cast_kindType::ComplexToReal, dest_type,
nullptr));
return;
} else {
throw SemanticError("'" + attr + "' is not implemented for Complex type",
x.base.base.loc);
}

} else {
throw SemanticError("Only Complex type supported for now in Attribute",
x.base.base.loc);
}
} else {
throw SemanticError("Only Variable type is supported for now in Attribute",
x.base.base.loc);
}

} else {
throw SemanticError("Only Name is supported for now in Attribute",
x.base.base.loc);
}
}

void visit_If(const AST::If_t &x) {
visit_expr(*x.m_test);
ASR::expr_t *test = ASRUtils::EXPR(tmp);
Expand Down
19 changes: 19 additions & 0 deletions src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct PythonIntrinsicProcedures {
{"hex", {m_builtin, &eval_hex}},
{"oct", {m_builtin, &eval_oct}},
{"complex", {m_builtin, &eval_complex}},
{"_lpython_imag", {m_builtin, &eval__lpython_imag}},
{"divmod", {m_builtin, &eval_divmod}},
};
}
Expand Down Expand Up @@ -503,6 +504,24 @@ struct PythonIntrinsicProcedures {
return ASR::down_cast<ASR::expr_t>(make_ConstantComplex_t(al, loc, c1, c2, type));
}

static ASR::expr_t *eval__lpython_imag(Allocator &al, const Location &loc,
Vec<ASR::expr_t*> &args
) {
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
if (args.size() != 1) {
throw SemanticError("Intrinsic _lpython_imag function accepts exactly 1 argument", loc);
}
ASR::expr_t* imag_arg = args[0];
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Real_t(al, loc, 8, nullptr, 0));
if (ASR::is_a<ASR::Complex_t>(*ASRUtils::expr_type(imag_arg))) {
double im = ASR::down_cast<ASR::ConstantComplex_t>(imag_arg)->m_im;
double result = im;
return ASR::down_cast<ASR::expr_t>(ASR::make_ConstantReal_t(al, loc, result, type));
} else {
throw SemanticError("Argument of the _lpython_imag() function must be Complex", loc);
}
}

static ASR::expr_t *eval_divmod(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &args) {
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
if (args.size() != 2) {
Expand Down
16 changes: 16 additions & 0 deletions src/runtime/lpython_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,19 @@ def lbound(x: i32[:], dim: i32) -> i32:

def ubound(x: i32[:], dim: i32) -> i32:
pass

@ccall
def _lfortran_caimag(x: c32) -> f32:
pass

@ccall
def _lfortran_zaimag(x: c64) -> f64:
pass

@overload
def _lpython_imag(x: c64) -> f64:
return _lfortran_zaimag(x)

@overload
def _lpython_imag(x: c32) -> f32:
return _lfortran_caimag(x)
2 changes: 1 addition & 1 deletion tests/reference/asr-complex1-f26c460.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-complex1-f26c460.stdout",
"stdout_hash": "6b4a5f8939ee7531165bc085d06704c624004418ee7b4a7896d4c72e",
"stdout_hash": "e0dbbef3bb6240c45acbfb64be1004e16ee9e9d3477097022be1c92a",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/asr-complex1-f26c460.stdout
Original file line number Diff line number Diff line change
@@ -1 +1 @@
(TranslationUnit (SymbolTable 1 {lpython_builtin: (IntrinsicModule lpython_builtin), main_program: (Program (SymbolTable 40 {}) main_program [] []), test: (Subroutine (SymbolTable 3 {x: (Variable 3 x Local () () Default (Complex 8 []) Source Public Required .false.), y: (Variable 3 y Local () () Default (Complex 8 []) Source Public Required .false.), z: (Variable 3 z Local () () Default (Complex 4 []) Source Public Required .false.)}) test [] [(= (Var 3 x) (BinOp (ImplicitCast (ConstantInteger 2 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Add (ConstantComplex 0.000000 3.000000 (Complex 8 [])) (Complex 8 []) () ()) ()) (= (Var 3 y) (BinOp (ImplicitCast (ConstantInteger 5 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Add (ConstantComplex 0.000000 5.000000 (Complex 8 [])) (Complex 8 []) () ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (Var 3 x) Add (Var 3 y) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (Var 3 x) Sub (Var 3 y) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (ImplicitCast (ConstantInteger 2 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Mul (Var 3 x) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ())] Source Public Implementation () .false. .false.), test_complex: (Subroutine (SymbolTable 2 {b: (Variable 2 b Local () () Default (Logical 1 []) Source Public Required .false.), c: (Variable 2 c Local () () Default (Complex 4 []) Source Public Required .false.), c1: (Variable 2 c1 Local () () Default (Complex 4 []) Source Public Required .false.), c2: (Variable 2 c2 Local () () Default (Complex 4 []) Source Public Required .false.), c3: (Variable 2 c3 Local () () Default (Complex 8 []) Source Public Required .false.), complex: (ExternalSymbol 2 complex 5 complex lpython_builtin [] complex Private)}) test_complex [] [(= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [] (Complex 8 []) (ConstantComplex 0.000000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantReal 3.400000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.400000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantReal 5.000000 (Real 8 []))) ((ConstantReal 4.300000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 5.000000 4.300000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c1) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c2) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 2 (Integer 4 []))) ((ConstantReal 4.500000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 2.000000 4.500000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c3) (FunctionCall 2 complex () [((ConstantReal 3.000000 (Real 8 []))) ((ConstantReal 4.000000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) ()) (= (Var 2 b) (Compare (Var 2 c1) NotEq (Var 2 c2) (Logical 4 []) () ()) ()) (= (Var 2 b) (Compare (ImplicitCast (Var 2 c1) ComplexToComplex (Complex 8 []) ()) Eq (Var 2 c3) (Logical 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c1) Add (Var 2 c2) (Complex 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c2) Sub (Var 2 c1) (Complex 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c1) Mul (Var 2 c2) (Complex 4 []) () ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 []))) ((ConstantInteger 2 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 2.000000 (Complex 8 [])) ()) Pow (FunctionCall 2 complex () [((ConstantReal 3.345340 (Real 8 []))) ((ConstantReal 4.867868 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.345340 4.867868 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex 0.015553 0.065561 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 []))) ((ConstantInteger 2 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 2.000000 (Complex 8 [])) ()) Mul (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex -5.000000 10.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 4 (Integer 4 []))) ((ConstantInteger 5 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 4.000000 5.000000 (Complex 8 [])) ()) Sub (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex 1.000000 1.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ())] Source Public Implementation () .false. .false.)}) [])
(TranslationUnit (SymbolTable 1 {lpython_builtin: (IntrinsicModule lpython_builtin), main_program: (Program (SymbolTable 44 {}) main_program [] []), test: (Subroutine (SymbolTable 3 {x: (Variable 3 x Local () () Default (Complex 8 []) Source Public Required .false.), y: (Variable 3 y Local () () Default (Complex 8 []) Source Public Required .false.), z: (Variable 3 z Local () () Default (Complex 4 []) Source Public Required .false.)}) test [] [(= (Var 3 x) (BinOp (ImplicitCast (ConstantInteger 2 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Add (ConstantComplex 0.000000 3.000000 (Complex 8 [])) (Complex 8 []) () ()) ()) (= (Var 3 y) (BinOp (ImplicitCast (ConstantInteger 5 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Add (ConstantComplex 0.000000 5.000000 (Complex 8 [])) (Complex 8 []) () ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (Var 3 x) Add (Var 3 y) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (Var 3 x) Sub (Var 3 y) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 3 z) (ImplicitCast (BinOp (ImplicitCast (ConstantInteger 2 (Integer 4 [])) IntegerToComplex (Complex 8 []) ()) Mul (Var 3 x) (Complex 8 []) () ()) ComplexToComplex (Complex 4 []) ()) ())] Source Public Implementation () .false. .false.), test_complex: (Subroutine (SymbolTable 2 {b: (Variable 2 b Local () () Default (Logical 1 []) Source Public Required .false.), c: (Variable 2 c Local () () Default (Complex 4 []) Source Public Required .false.), c1: (Variable 2 c1 Local () () Default (Complex 4 []) Source Public Required .false.), c2: (Variable 2 c2 Local () () Default (Complex 4 []) Source Public Required .false.), c3: (Variable 2 c3 Local () () Default (Complex 8 []) Source Public Required .false.), complex: (ExternalSymbol 2 complex 5 complex lpython_builtin [] complex Private)}) test_complex [] [(= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [] (Complex 8 []) (ConstantComplex 0.000000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantReal 3.400000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.400000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantReal 5.000000 (Real 8 []))) ((ConstantReal 4.300000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 5.000000 4.300000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 0.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c1) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c2) (ImplicitCast (FunctionCall 2 complex () [((ConstantInteger 2 (Integer 4 []))) ((ConstantReal 4.500000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 2.000000 4.500000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c3) (FunctionCall 2 complex () [((ConstantReal 3.000000 (Real 8 []))) ((ConstantReal 4.000000 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) ()) (= (Var 2 b) (Compare (Var 2 c1) NotEq (Var 2 c2) (Logical 4 []) () ()) ()) (= (Var 2 b) (Compare (ImplicitCast (Var 2 c1) ComplexToComplex (Complex 8 []) ()) Eq (Var 2 c3) (Logical 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c1) Add (Var 2 c2) (Complex 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c2) Sub (Var 2 c1) (Complex 4 []) () ()) ()) (= (Var 2 c) (BinOp (Var 2 c1) Mul (Var 2 c2) (Complex 4 []) () ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 []))) ((ConstantInteger 2 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 2.000000 (Complex 8 [])) ()) Pow (FunctionCall 2 complex () [((ConstantReal 3.345340 (Real 8 []))) ((ConstantReal 4.867868 (Real 8 [])))] (Complex 8 []) (ConstantComplex 3.345340 4.867868 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex 0.015553 0.065561 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 1 (Integer 4 []))) ((ConstantInteger 2 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 1.000000 2.000000 (Complex 8 [])) ()) Mul (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex -5.000000 10.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ()) (= (Var 2 c) (ImplicitCast (BinOp (FunctionCall 2 complex () [((ConstantInteger 4 (Integer 4 []))) ((ConstantInteger 5 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 4.000000 5.000000 (Complex 8 [])) ()) Sub (FunctionCall 2 complex () [((ConstantInteger 3 (Integer 4 []))) ((ConstantInteger 4 (Integer 4 [])))] (Complex 8 []) (ConstantComplex 3.000000 4.000000 (Complex 8 [])) ()) (Complex 8 []) (ConstantComplex 1.000000 1.000000 (Complex 8 [])) ()) ComplexToComplex (Complex 4 []) ()) ())] Source Public Implementation () .false. .false.)}) [])
2 changes: 1 addition & 1 deletion tests/reference/asr-constants1-5828e8a.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-constants1-5828e8a.stdout",
"stdout_hash": "b1312682ec61a28f1368c5a4382aa6f98c1c1023aed1be56c9608d5a",
"stdout_hash": "e19e1e08674cdb1ce0690b9e58003c0c620a559384550649d774ad32",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
Loading