Skip to content

tagof operator as default argument does not evaluate properly if default arguments are used #268

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
YashasSamaga opened this issue Jan 19, 2018 · 2 comments

Comments

@YashasSamaga
Copy link
Member

#include <a_samp>
f({Tag1, Tag2}:a = Tag1:123, b = tagof(a)) {
	printf("b: %d", _:b);
}

main () {
	new Tag21:x;
	printf("Tag21: %d, Tag1: %d, Tag2: %d", tagof(Tag21:), tagof(Tag1:), tagof(Tag2:));
	f();
}

gives

Tag21: -1073741807, Tag1: -1073741809, Tag2: -1073741808
b: 0

The value of b shouldn't be zero. As the default argument is Tag1:123, b should have had the tag identifier of Tag1.

If f is called with an argument, it works fine.

With f() replaced with f(x):

Tag21: -1073741807, Tag1: -1073741809, Tag2: -1073741808
b: -1073741807
@YashasSamaga
Copy link
Member Author

YashasSamaga commented Jan 28, 2018

f({Tag1, Tag2}:a[] = {Tag2: 5, Tag1:10}, b = tagof(a)) { }

What should be the default tag of a?

@YashasSamaga
Copy link
Member Author

YashasSamaga commented Jan 28, 2018

beta commit: YashasSamaga@42c18c2

Commit description:

Previously, if the tagof operator was used on an argument with default value, the tag identifier recorded would be 0 in case the default value was used.

f({Tag1, Tag2}:a = Tag2:123, b = tagof(a)) { }
main () { f(); }

In the above code, the argument a would have the value 123 but b would have 0.

This commit patches the bug. The value of b will be the tag identifier of the default argument.

This commit patches for two cases: default argument is a reference and default argument is a variable.

The case of reference arrays is not handled correctly as the tag of the default reference array is not well defined.

Implementation details:
The compiler first processes arguments which are not taking default values (including tagof and sizeof parameters). The compiler does a second pass on the list of all formal parameters and processes the default values. The compiler then does a final pass on the list of formal parameters and processes sizeof and tagof parameters.

The compiler maintains a list of tags of all the arguments in a constvalue list called taglst as it processes the arguments.

The name field of the members of the tag list is the argument name and the tag field stores the tag identifier of that argument (tag identifier of the actual parameter).

In the first pass where the expclit arguments are being processed, the compiler checks the argument's tag and adds the tag along with the formal parameter name (can be thought of as "formal-paramter-name : tag" pair) to the tag list if the tag identifier is NOT zero.

In the second pass where the default values are being handled, the compiler does not modify the tag list (source of the bug).

After all the arguments other than sizeof and tagof have been handled othe, the compiler iterates through the list of arguments and takes care of sizeof and tagof arguments.

Here it checks to which formal parameter (say F) the tagof parameter (say T) points to. It then checks the tag list for that symbol F, if an entry is found, it uses the tag identifier associated with that argument. If not found, it defaults to 0.

Since the tags of default arguments along with it's formal name is not added to the tag list, the third pass won't be aware of any tag associated with the default values and assumes 0.

This commit adds code to add the tags of the default values to the tag list so that the compiler is aware of the tag of the default values in the final pass.

Basic tests:

#include <a_samp>
f1({Tag1, Tag2}:a = Tag2:123, b = tagof(a)) {
	printf("[VARIABLE] Expected Tag: %d, Found Tag: %d", tagof(Tag2:), _:b);
}
f2(&{Tag3, Tag4}:a = Tag4:123, b = tagof(a)) {
	printf("[REFERENCE] Expected Tag: %d, Found Tag: %d", tagof(Tag4:), _:b);
}
f3({Tag5, Tag6}:a[] = {Tag6:1, Tag6:2}, b = tagof(a)) {
	printf("[REFARRAY] Expected Tag: %d, Found Tag: %d", tagof(Tag6:), _:b);
}
main () {
	f1();
	f2();
	f3();
}

Output:

[VARIABLE] Expected Tag: -1073741808, Found Tag: -1073741808
[REFERENCE] Expected Tag: -1073741806, Found Tag: -1073741806
[REFARRAY] Expected Tag: -1073741804, Found Tag: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants