|
|
|
|
|
In sac, you can [overload](../concepts/Overloading.md) functions.
|
|
|
In sac, you can [overload](../concepts/Overloading.md) functions.
|
|
|
This is great but the errors relating to this feature can be improved a lot.
|
|
|
|
|
|
## Show available options if no type match is found
|
|
|
## Show available options if no type match is found
|
|
|
|
|
|
If you have a program like this:
|
|
|
|
... | ... | @@ -21,6 +20,7 @@ int main() { |
|
|
```
|
|
|
|
|
|
The current error is:
|
|
|
|
|
|
```
|
|
|
All instances of "main" contain type errors
|
|
|
No matching definition found for the application of "_MAIN::foo" to arguments ( int[2]{2,3})
|
... | ... | @@ -41,9 +41,236 @@ int[3] -> void |
|
|
bool -> bool
|
|
|
```
|
|
|
|
|
|
Notice the formatting of the types.
|
|
|
The arrows are alligned to make it more readable.
|
|
|
Sijmen did an internship about this.
|
|
|
Notice the formatting of the types.
|
|
|
The arrows are alligned to make it more readable.
|
|
|
Sijmen did an internship about this.
|
|
|
|
|
|
Make sure to say and make clear if you assign the result of a function you can never call the version that returns void!
|
|
|
|
|
|
# Function not found
|
|
|
|
|
|
We should give a different error if no function with this name is available!
|
|
|
|
|
|
If we want to raise the error of no instance available we should look in the ast at the function names if it does exist.
|
|
|
Then we could also do a similarity thing based on types and names.
|
|
|
|
|
|
## Name based suggestions
|
|
|
|
|
|
If we do a suggestion based on the name we could try to look for an existing name that is similar up to some distance.
|
|
|
For instance edit distance of 2. We should first look in the _MAIN namespace, then the imported modules.
|
|
|
Let's make two suggestions.
|
|
|
|
|
|
Maybe you meant tho call %s or %s?
|
|
|
|
|
|
If we don't find anything we can say something like.
|
|
|
|
|
|
I looked for functions with names similar to %s, but I could not find any.
|
|
|
|
|
|
But only if there is no function available of this name at all!
|
|
|
Otherwise, we just assume you did the overload wrong.
|
|
|
|
|
|
Let's first just implement Levistein edit distance and after
|
|
|
that [keyboard or typing distance](https://github.com/MaxHalford/clavier?tab=readme-ov-file#distance-between-words).
|
|
|
|
|
|
How are we actually going to do this?
|
|
|
|
|
|
We know how many different functions there are in the program.
|
|
|
Well so we know how many function defs we so we know how much we have to malloc in the worst cost if they are all
|
|
|
different.
|
|
|
|
|
|
Lemma haha : To know how many different functions there are in the program we already need to have the data structure to
|
|
|
store them.
|
|
|
|
|
|
An iterable set of strings is a good data structure for this.
|
|
|
|
|
|
We could also just allocate the max we need.
|
|
|
|
|
|
We could then just loop over all the function names and calculate the distance.
|
|
|
|
|
|
## Number of arguments suggestion
|
|
|
|
|
|
At the create_wrappers stage of the compiler they make wrapper functions for functions with same name and same number of arguments and return values.
|
|
|
|
|
|
If you call a function for which a wrapper does not exist you get
|
|
|
|
|
|
```c
|
|
|
CTIabort (NODE_LOCATION (arg_node),
|
|
|
"No definition found for a function \"%s::%s\" that expects"
|
|
|
" %zu argument(s) and yields %zu return value(s)",
|
|
|
NSgetName (SPAP_NS (arg_node)), SPAP_NAME (arg_node), num_args,
|
|
|
INFO_EXPRETS (arg_info));
|
|
|
```
|
|
|
|
|
|
This can be a lot better.
|
|
|
|
|
|
This error often triggers when:
|
|
|
|
|
|
1. a: The programmer calls a function that just does not exist anywhere
|
|
|
1. The function is named sel
|
|
|
2. There exists a simiarly named function, e.g. detect typo
|
|
|
3. There does not exist a similarly named function.
|
|
|
2. b: The programmer calls a version of a function that does not exist
|
|
|
1. Not assigning the result of the function to a variable.
|
|
|
Calling the version that returns void, which often does not exist.
|
|
|
2. Only incorrect number of return values but more than 0.
|
|
|
3. Only incorrect number of arguments.
|
|
|
4. Incorrect number of arguments AND return values!
|
|
|
|
|
|
# a
|
|
|
|
|
|
## a1
|
|
|
In this case the programmer did arr[1] without having a sel function.
|
|
|
It is not intuitive that the arr[1] syntax requires the sel function.
|
|
|
We should give a special error message for this case.
|
|
|
|
|
|
```
|
|
|
The '%s' function is not defined anywhere.
|
|
|
sel is called when you do an array index like this: a[12]
|
|
|
You can get a working sel from the standard library by adding:
|
|
|
|
|
|
use Array: {sel};
|
|
|
|
|
|
to the top of the file.
|
|
|
```
|
|
|
|
|
|
## a2
|
|
|
|
|
|
In this case the whole function just doesn't exist.
|
|
|
We can assume that the programmer makes a typo.
|
|
|
With a typo there is probably a function that is named similarly.
|
|
|
Check all the function names edit distance and make a suggestion based on
|
|
|
if a function name has damerau_levenshtein_distance =< EDIT_DISTANCE_TRESHOLD
|
|
|
with the ap then we give a hint to use that function.
|
|
|
|
|
|
```
|
|
|
The '%s' function is not defined anywhere.
|
|
|
|
|
|
Hint: Did you mean call the '%s' function instead?
|
|
|
```
|
|
|
|
|
|
## a3
|
|
|
|
|
|
If there is no function defined with a name that is
|
|
|
damerau_levenshtein_distance =< EDIT_DISTANCE_TRESHOLD to the function name
|
|
|
being called give an error that there is no function with this name and also
|
|
|
not one that kind of has the same name.
|
|
|
|
|
|
```
|
|
|
The '%s' function is not defined anywhere.
|
|
|
I could not find another function with a similar names to recommend.
|
|
|
|
|
|
Hint:\n Check that you have:
|
|
|
• Imported/use the correct library
|
|
|
• Used the correct function name
|
|
|
• Defined the function
|
|
|
```
|
|
|
|
|
|
# b
|
|
|
|
|
|
## b1
|
|
|
|
|
|
I think that b1 is a special case for which we should make a specific error
|
|
|
message which explains that you have to assign the result to a variable or
|
|
|
define a version that returns void.
|
|
|
|
|
|
As soon as we find out this is the case we should tell them about that
|
|
|
not assining tries to call the void overload.
|
|
|
|
|
|
The error for this is now:
|
|
|
|
|
|
```
|
|
|
You are using the '%s' function without using or assigning its result but no void returning implementation of foo exists.
|
|
|
|
|
|
In SAC, if you do not use the result of a function application the
|
|
|
overloading mechanism expects an implementation which returns void.
|
|
|
None of the implementation of %s return void.
|
|
|
|
|
|
Hint:
|
|
|
• Assign the result to a variable e.g., 'var = %s(...)'
|
|
|
• Or define a void-returning version `void %s(...) {}`)
|
|
|
```
|
|
|
|
|
|
## Info gathering for b2 b3 and b4
|
|
|
|
|
|
How do we know if the arity is right?
|
|
|
We need to ask two questions in order to get 3 awnsers.
|
|
|
|
|
|
1. Does an instance exist with the right amount of args?
|
|
|
2. Does an instance exist with the right amount of returns?
|
|
|
|
|
|
- If 1 and 2 then you wouldn't have the error so that never happens,
|
|
|
- If 1 and not 2 you had the wrong number of returns (case b2)
|
|
|
- If not 1 and 2 you had the wrong number of arguments (case b3)
|
|
|
- If not 1 and not 2 you had the wrong number of arguments and returns (case b4)
|
|
|
|
|
|
## b2
|
|
|
|
|
|
In this case we can say that the number of return values are wrong.
|
|
|
We can list the different numbers of valid return values.
|
|
|
|
|
|
At least get the different cases of functions.
|
|
|
We can still make the function type printer :)
|
|
|
|
|
|
```
|
|
|
Invalid call to foo:
|
|
|
The number of return values does not match any existing implementation.
|
|
|
|
|
|
Available implementations of foo include:
|
|
|
a, b = foo(...) (2 returns)
|
|
|
a, b, c = foo(...) (3 returns)
|
|
|
a, b, c, d = foo(...) (4 returns)
|
|
|
|
|
|
The number of arguments is correct. There is an instance with 1 argument.
|
|
|
```
|
|
|
|
|
|
## b3
|
|
|
|
|
|
In this case the we can say that the number of arguments is wrong.
|
|
|
We can list the different numbers of valid arguments.
|
|
|
|
|
|
```
|
|
|
"Invalid call to foo: the number of arguments does not match any existing implementation.
|
|
|
Available implementations of foo:
|
|
|
|
|
|
foo(arg1) (1 argument)
|
|
|
foo(arg1, arg2) (2 arguments)
|
|
|
foo(arg1, arg2, arg3) (3 arguments)
|
|
|
|
|
|
The number of return values is correct."
|
|
|
```
|
|
|
|
|
|
Hopefully we can get the types in there maybe or the arg names
|
|
|
|
|
|
## b4
|
|
|
|
|
|
In this case we say you got both the
|
|
|
|
|
|
```
|
|
|
Invalid call to foo: the number of arguments and return values does not match any existing implementation.
|
|
|
Available implementations of foo:
|
|
|
|
|
|
a = foo(arg1) (1 argument, 1 return)
|
|
|
a, b = foo(arg1, arg2) (2 arguments, 2 returns)
|
|
|
a = foo(arg1, arg2, arg3) (3 arguments, 1 return)
|
|
|
```
|
|
|
|
|
|
Allign based on longest returns and longest arguments.
|
|
|
The tab at the start is nice!
|
|
|
|
|
|
## Type based suggestions
|
|
|
|
|
|
With the wrapper functions it only looks at number of arguments and return values not the types.
|
|
|
Later we can also look at the types!
|
|
|
|
|
|
I think that the name is more likely to be the right suggestion for a function call that does not exist.
|
|
|
Yeah. Because finding a function with the same type might do something complelty different as there are not so many
|
|
|
types.
|
|
|
Also doing suggestions based on passed in types would mean that this phase has to move down in the compiler.
|
|
|
Because mostly functions in sac only have 1 to 3 inputs really and there are not that many types so you might not get
|
|
|
the function you want.
|
|
|
|
|
|
But we should make it print all the versions of a function.
|
|
|
|
|
|
## Global objects are printed
|
|
|
|
|
|
If you have code like this:
|
... | ... | @@ -59,15 +286,17 @@ int main() { |
|
|
}
|
|
|
```
|
|
|
|
|
|
Currently, the compiler prints the global objects that are woven true in the overloading error message.
|
|
|
Currently, the compiler prints the global objects that are woven true in the overloading error message.
|
|
|
|
|
|
```
|
|
|
No definition found for a function "_MAIN::foo" that accepts an argument of type "bool{1}" as parameter no 3. Full argument types are "( Terminal::Terminal, TermFile::TermFile, bool{1})".
|
|
|
Compilation failed while Running type inference system, 1 warning(s).
|
|
|
```
|
|
|
|
|
|
I think that this can be very confusing for the programmer.
|
|
|
Especially because the parameter number does not match up with the parameter number in their source code.
|
|
|
I think that this can be very confusing for the programmer.
|
|
|
Especially because the parameter number does not match up with the parameter number in their source code.
|
|
|
|
|
|
We could perhaps try to hide the global objects.
|
|
|
|
|
|
## Not assigning a function to a result overloads to void return types is unclear
|
|
|
|
... | ... | @@ -95,7 +324,8 @@ Not assigned, got 3 |
|
|
Assigned!
|
|
|
```
|
|
|
|
|
|
If you call an overloaded function without assigning the result to a variable the compiler will pick the version that returns void.
|
|
|
If you call an overloaded function without assigning the result to a variable the compiler will pick the version that
|
|
|
returns void.
|
|
|
|
|
|
However, the error message about this is not very clear. Let's say you have:
|
|
|
|
... | ... | @@ -104,7 +334,7 @@ int ten() { return 10;} |
|
|
void main() { ten(); }
|
|
|
```
|
|
|
|
|
|
You get:
|
|
|
You get:
|
|
|
|
|
|
```
|
|
|
./test.sac:3:15: abort:
|
... | ... | @@ -112,8 +342,8 @@ You get: |
|
|
Compilation failed while Converting to static single assignment form, 1 warning(s).
|
|
|
```
|
|
|
|
|
|
I found this very unclear when I started out with sac.
|
|
|
I was used to programming languages just dropping the return value.
|
|
|
I found this very unclear when I started out with sac.
|
|
|
I was used to programming languages just dropping the return value.
|
|
|
We should say something about this in the error message:
|
|
|
|
|
|
```
|
... | ... | @@ -136,7 +366,7 @@ use StdIO: all; |
|
|
|
|
|
void foo() { printf("void\n"); return;}
|
|
|
// Works without the printf.
|
|
|
int foo() { printf("Bug"); return 137;}
|
|
|
int foo() { printf("Bug"); return 137;}
|
|
|
|
|
|
int main() {
|
|
|
foo();
|
... | ... | @@ -156,8 +386,10 @@ int foo() { return 137;} |
|
|
|
|
|
int main() { return 0; }
|
|
|
```
|
|
|
|
|
|
You get this error message.
|
|
|
`
|
|
|
|
|
|
```
|
|
|
Cannot overload functions of arity 0
|
|
|
```
|
... | ... | |