-
Notifications
You must be signed in to change notification settings - Fork 171
Function Default Arguments #2618
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
Changes from all commits
1a2e739
1adbddc
9fbd33e
0e14c0a
abcd34a
d7869b1
fa18fa7
7f85dc2
649b079
2902eea
d3734db
f8b7c97
c4ac4f3
1f3d26f
2cf7f4f
35b5faa
a4d4d9c
8ec5b38
3bb336c
c7ff531
3423d9b
8748b42
be236f8
c286d39
b34a32b
11d1015
ee07640
fe4f162
ae0f7a0
233eddd
b86819a
d912b71
4860230
7ca1987
0fee905
fc1d61c
262041a
b8a14b1
a474734
2549f0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from lpython import i32,i64 | ||
|
||
def factorial_1(x: i32, y:i32 =1) ->i32 : | ||
if x <= 1: | ||
return y | ||
return x * factorial_1(x-1) | ||
|
||
def factorial_2(x: i32, y:i32=3 ,z:i32 =2) ->i32: | ||
if x ==4: | ||
return x * y * z | ||
return x * factorial_2(x-1) | ||
|
||
def default_func(x : str ="Hello", y : str = " ", z : str = "World") ->str: | ||
return x + y + z | ||
|
||
|
||
def even_positions(iterator : i32, to_add : str = "?")-> str: | ||
if (iterator == 10): return "" | ||
if iterator%2 == 0 : | ||
return to_add + even_positions(iterator+1,"X") | ||
return to_add +even_positions(iterator+1) | ||
|
||
|
||
|
||
def test_factorial_1(): | ||
test_00 : i32 = factorial_1(1) | ||
print("test_00 is =>", test_00) | ||
assert test_00 == 1 | ||
|
||
test_01 : i32 = factorial_1(5,0) | ||
print("test_01 is =>", test_01) | ||
assert test_01 == 120 | ||
|
||
test_02 : i32 = factorial_1(1,5555) | ||
print("test_02 is =>", test_02) | ||
assert test_02 == 5555 | ||
assem2002 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def test_factorial_2(): | ||
test_03 : i32 =factorial_2(5,99999,99999) | ||
print("test_03 is =>", test_03) | ||
assert test_03 == 120 | ||
|
||
test_04 : i32 = factorial_2(4,-1,100) | ||
print("test_04 is =>", test_04) | ||
assert test_04 == -400 | ||
|
||
def test_default_func(): | ||
test_05 :str = default_func() | ||
print("test_05 is =>", test_05) | ||
assert test_05 == "Hello World" | ||
|
||
test_06 :str = default_func(y = "|||",x="Hi") | ||
print("test_06 is =>", test_06) | ||
assert test_06 == "Hi|||World" | ||
|
||
test_07 :str = default_func(y = "++",z = "LPython") | ||
print("test_07 is =>", test_07) | ||
assert test_07 == "Hello++LPython" | ||
|
||
test_8 :str = default_func("Welcome",z = "LPython") | ||
print("test_8 is =>", test_8) | ||
assert test_8 == "Welcome LPython" | ||
|
||
def test_even_positions(): | ||
test_09 : str = even_positions(0) | ||
print("test_09 is =>", test_09) | ||
assert test_09 == "?X?X?X?X?X" | ||
|
||
test_10 : str = even_positions(0,"W") | ||
print("test_10 is =>", test_10) | ||
assert test_10 == "WX?X?X?X?X" | ||
|
||
assem2002 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
test_factorial_1() | ||
test_factorial_2() | ||
test_default_func() | ||
test_even_positions() |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -659,7 +659,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> { | |||||||||||||||||||
|
||||||||||||||||||||
// Fill the whole call_args_vec with nullptr | ||||||||||||||||||||
// This is for error handling later on. | ||||||||||||||||||||
for( size_t i = 0; i < n_pos_args + n_kwargs; i++ ) { | ||||||||||||||||||||
for( size_t i = 0; i < orig_func->n_args; i++ ) { | ||||||||||||||||||||
ASR::call_arg_t call_arg; | ||||||||||||||||||||
Location loc; | ||||||||||||||||||||
loc.first = loc.last = 1; | ||||||||||||||||||||
|
@@ -704,6 +704,31 @@ class CommonVisitor : public AST::BaseVisitor<Struct> { | |||||||||||||||||||
call_args_vec.p[arg_pos].loc = expr->base.loc; | ||||||||||||||||||||
call_args_vec.p[arg_pos].m_value = expr; | ||||||||||||||||||||
} | ||||||||||||||||||||
// Filling missing arguments with their defaults passed in function definition (if present). | ||||||||||||||||||||
std::string missed_args_names; | ||||||||||||||||||||
size_t missed_args_count =0; | ||||||||||||||||||||
for(size_t i = 0; i < orig_func->n_args; i++ ){ | ||||||||||||||||||||
if(call_args_vec.p[i].m_value == nullptr){ | ||||||||||||||||||||
ASR::Variable_t* var = ASRUtils::EXPR2VAR(orig_func->m_args[i]); | ||||||||||||||||||||
if (var->m_symbolic_value == nullptr){ | ||||||||||||||||||||
missed_args_names+="'" + (std::string) var->m_name + "' and "; | ||||||||||||||||||||
missed_args_count++; | ||||||||||||||||||||
} else { | ||||||||||||||||||||
call_args_vec.p[i].m_value = var->m_symbolic_value; | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
if(missed_args_count > 0){ | ||||||||||||||||||||
missed_args_names = missed_args_names.substr(0,missed_args_names.length() - 5); | ||||||||||||||||||||
diag.add(diag::Diagnostic( | ||||||||||||||||||||
"Number of arguments does not match in the function call", | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
diag::Level::Error, diag::Stage::Semantic, { | ||||||||||||||||||||
diag::Label("missing " + std::to_string(missed_args_count) + " required arguments :" + missed_args_names, | ||||||||||||||||||||
{call_loc}) | ||||||||||||||||||||
}) | ||||||||||||||||||||
); | ||||||||||||||||||||
throw SemanticAbort(); | ||||||||||||||||||||
} | ||||||||||||||||||||
return true; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
|
@@ -1139,9 +1164,35 @@ class CommonVisitor : public AST::BaseVisitor<Struct> { | |||||||||||||||||||
if (ASR::is_a<ASR::Function_t>(*s)) { | ||||||||||||||||||||
ASR::Function_t *func = ASR::down_cast<ASR::Function_t>(s); | ||||||||||||||||||||
if( n_kwargs > 0 && !is_generic_procedure ) { | ||||||||||||||||||||
args.reserve(al, n_pos_args + n_kwargs); | ||||||||||||||||||||
args.reserve(al, func->n_args); | ||||||||||||||||||||
visit_expr_list(pos_args, n_pos_args, kwargs, n_kwargs, | ||||||||||||||||||||
args, rt_subs, func, loc); | ||||||||||||||||||||
} else if (args.size() < func->n_args) { | ||||||||||||||||||||
assem2002 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||
std::string missed_args_names =" "; | ||||||||||||||||||||
size_t missed_args_count =0; | ||||||||||||||||||||
for (size_t def_arg = args.size(); def_arg < func->n_args; def_arg++){ | ||||||||||||||||||||
ASR::Variable_t* var = ASRUtils::EXPR2VAR(func->m_args[def_arg]); | ||||||||||||||||||||
if(var->m_symbolic_value == nullptr) { | ||||||||||||||||||||
missed_args_names+= "'" + std::string(var->m_name) + "' and "; | ||||||||||||||||||||
missed_args_count++; | ||||||||||||||||||||
} else { | ||||||||||||||||||||
ASR::call_arg_t call_arg; | ||||||||||||||||||||
call_arg.m_value = var->m_symbolic_value; | ||||||||||||||||||||
call_arg.loc = (var->m_symbolic_value->base).loc; | ||||||||||||||||||||
args.push_back(al,call_arg); | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
if(missed_args_count > 0){ | ||||||||||||||||||||
missed_args_names = missed_args_names.substr(0,missed_args_names.length() - 5); | ||||||||||||||||||||
diag.add(diag::Diagnostic( | ||||||||||||||||||||
"Number of arguments does not match in the function call", | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @assem2002 Do you mind adding an error reference test for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
diag::Level::Error, diag::Stage::Semantic, { | ||||||||||||||||||||
diag::Label("missing " + std::to_string(missed_args_count) + " required arguments :" + missed_args_names, | ||||||||||||||||||||
{loc}) | ||||||||||||||||||||
}) | ||||||||||||||||||||
); | ||||||||||||||||||||
throw SemanticAbort(); | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
if (ASRUtils::get_FunctionType(func)->m_is_restriction) { | ||||||||||||||||||||
rt_vec.push_back(s); | ||||||||||||||||||||
|
@@ -4269,6 +4320,7 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { | |||||||||||||||||||
throw SemanticError("Function " + std::string(x.m_name) + " is already defined", x.base.base.loc); | ||||||||||||||||||||
} | ||||||||||||||||||||
bool is_allocatable = false, is_const = false; | ||||||||||||||||||||
size_t default_arg_index_start = x.m_args.n_args - x.m_args.n_defaults; | ||||||||||||||||||||
for (size_t i=0; i<x.m_args.n_args; i++) { | ||||||||||||||||||||
char *arg=x.m_args.m_args[i].m_arg; | ||||||||||||||||||||
Location loc = x.m_args.m_args[i].loc; | ||||||||||||||||||||
|
@@ -4290,6 +4342,11 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { | |||||||||||||||||||
std::string arg_s = arg; | ||||||||||||||||||||
ASR::expr_t *value = nullptr; | ||||||||||||||||||||
ASR::expr_t *init_expr = nullptr; | ||||||||||||||||||||
if (i >= default_arg_index_start){ | ||||||||||||||||||||
size_t default_arg_index = i - default_arg_index_start; | ||||||||||||||||||||
this->visit_expr(*(x.m_args.m_defaults[default_arg_index])); | ||||||||||||||||||||
Comment on lines
+4345
to
+4347
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We can be a little readable here. |
||||||||||||||||||||
init_expr = ASRUtils::EXPR(tmp); | ||||||||||||||||||||
} | ||||||||||||||||||||
if (s_intent == ASRUtils::intent_unspecified) { | ||||||||||||||||||||
s_intent = ASRUtils::intent_in; | ||||||||||||||||||||
if (ASRUtils::is_array(arg_type)) { | ||||||||||||||||||||
|
@@ -4308,6 +4365,9 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { | |||||||||||||||||||
} | ||||||||||||||||||||
ASR::accessType s_access = ASR::accessType::Public; | ||||||||||||||||||||
ASR::presenceType s_presence = ASR::presenceType::Required; | ||||||||||||||||||||
if (i >= default_arg_index_start){ | ||||||||||||||||||||
s_presence = ASR::presenceType::Optional; | ||||||||||||||||||||
} | ||||||||||||||||||||
bool value_attr = false; | ||||||||||||||||||||
if (current_procedure_abi_type == ASR::abiType::BindC) { | ||||||||||||||||||||
value_attr = true; | ||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_01(x : str) -> str: | ||
print(x) | ||
|
||
func_01() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_02(x : i32 ,y : i32) -> i32 : | ||
print(x,y) | ||
|
||
func_02() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_03(x : i32 ,y : i32) -> i32 : | ||
print(x,y) | ||
|
||
func_03(1) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_04(x : i32 ,y : i32) -> i32 : | ||
print(x,y) | ||
|
||
func_04(y=3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_05(x : i32 ,y : i32,z : i32) -> i32 : | ||
print(x,y,z) | ||
|
||
func_05(1,2) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from lpython import i32 | ||
def func_05(x : i32 ,y : i32,z : i32) -> i32 : | ||
print(x,y,z) | ||
|
||
func_05(z=3) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_01-1c7f4cd", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_01.py", | ||
"infile_hash": "fda645ec7920824250cc2b5c28663061fe629b1dc341fc70ba3a691c", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_01-1c7f4cd.stderr", | ||
"stderr_hash": "e96fc67b26c68ef0954595fb87bf261a1bfe6e9f55d83baf28e73032", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_01.py:5:1 | ||
| | ||
5 | func_01() | ||
| ^^^^^^^^^ missing 1 required arguments : 'x' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_02-8bf7092", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_02.py", | ||
"infile_hash": "fe3a3789ece86f790691ead17887dfebb8d60b882f58e06d333c9bb2", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_02-8bf7092.stderr", | ||
"stderr_hash": "61aea2e70bfee634a40291abc98afa838c6ca173201d9d16f9dfb428", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_02.py:5:1 | ||
| | ||
5 | func_02() | ||
| ^^^^^^^^^ missing 2 required arguments : 'x' and 'y' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_03-58ad7c5", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_03.py", | ||
"infile_hash": "e69f130e474a8757368e7ad3e9afcd3553eaff1e819173febb66fd06", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_03-58ad7c5.stderr", | ||
"stderr_hash": "5ac45e87ffbe795b9ca06dc4a82d3743c762f4f0a1f6bbfdc3e14ca2", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_03.py:5:1 | ||
| | ||
5 | func_03(1) | ||
| ^^^^^^^^^^ missing 1 required arguments : 'y' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_04-4af8c0d", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_04.py", | ||
"infile_hash": "522166d0c6c1a0cb273d67ce577ec42330f02822c75b1b317c97608c", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_04-4af8c0d.stderr", | ||
"stderr_hash": "11bd3ae2f41227fd383927fa2f9fc4feff50c19784df51b56f50d3e9", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_04.py:5:1 | ||
| | ||
5 | func_04(y=3) | ||
| ^^^^^^^^^^^^ missing 1 required arguments :'x' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_05-6c33b29", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_05.py", | ||
"infile_hash": "bc8d5377ec564a4d5758653dea39d5c6237992a54ec33fdef88f63f2", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_05-6c33b29.stderr", | ||
"stderr_hash": "9dad35128e5da8dcc73f9c96bdb43ce15e3309d590bb794b14e3133c", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_05.py:5:1 | ||
| | ||
5 | func_05(1,2) | ||
| ^^^^^^^^^^^^ missing 1 required arguments : 'z' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"basename": "asr-def_func_06-9a3ebfc", | ||
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}", | ||
"infile": "tests/errors/def_func_06.py", | ||
"infile_hash": "5ad73c3f18ab4d9fe82108e65e0013687a70acc3eff495a402d4297e", | ||
"outfile": null, | ||
"outfile_hash": null, | ||
"stdout": null, | ||
"stdout_hash": null, | ||
"stderr": "asr-def_func_06-9a3ebfc.stderr", | ||
"stderr_hash": "f9c79e62d7ef7f411870195bfeb99615cb7da9216af328fda2fb0cd2", | ||
"returncode": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
semantic error: Number of arguments does not match in the function call | ||
--> tests/errors/def_func_06.py:5:1 | ||
| | ||
5 | func_05(z=3) | ||
| ^^^^^^^^^^^^ missing 2 required arguments :'x' and 'y' |
Uh oh!
There was an error while loading. Please reload this page.