Skip to content
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

Script compiler: support implicit int-float type casts in script #2590

Closed
ivan-mogilko opened this issue Nov 25, 2024 · 9 comments
Closed

Script compiler: support implicit int-float type casts in script #2590

ivan-mogilko opened this issue Nov 25, 2024 · 9 comments

Comments

@ivan-mogilko
Copy link
Contributor

ivan-mogilko commented Nov 25, 2024

The lack of implicit cast between ints and floats has been an endless annoyance to both beginners and advanced users, and idk why there's no ticket made about this.

The proposal is to support such cast without a requirement to use IntToFloat and FloatToInt.
NOTE: If this is implemented, then IntToFloat should probably be deprecated, but FloatToInt kept, as it lets choose different sorts of rounding (see also #1983)

To be honest, I don't know how C-like languages implement this, but suppose that we would need 2 new opcodes for this, e.g. something that reads a T1 from register1 and write T2 into register2, where T1 and T2 and int/float and float/int respectively.
These opcodes likely should have an argument that tells integer type's size (1,2 or 4 bytes).
Alternatively, we may use N pairs of opcodes, for each integer size.

Compiler would generate this operation whenever int or float are assigned to each other in expressions, and engine will implement the opcodes.

EDIT: for example, curiously, in Java there are only opcodes for converting between int32 and other integer and float types, so when you need to convert from float to char, it has to first convert from float to int32 and then from int32 to char as a 2-step operation. (https://javaalmanac.io/bytecode/mnemonics/)

OTHER NOTES:
For the reference, C and C++ allow to implicitly convert both ways, although they may print value truncation warnings. C# only allows to implicitly convert from int32 to float, but opposite conversion requires an explicit cast (because it may change the number).

@ivan-mogilko ivan-mogilko added type: enhancement a suggestion or necessity to have something improved context: script compiler context: script vm labels Nov 25, 2024
@messengerbag
Copy link

Should there be implicit casts? I'm not convinced. (Though the AGS cast functions are far too verbose.)

@ivan-mogilko
Copy link
Contributor Author

Should there be implicit casts? I'm not convinced. (Though the AGS cast functions are far too verbose.)

What's you propose then?

@messengerbag
Copy link

My proposal is to not do this. At most, replace IntToFloat() and FloatToInt() with the more conventional (float) and Round().

BTW, even if you add implicit cast you're still going to need IntToFloat (or equivalent) for cases like ratio = a/b (where a and b are integers but you want the ratio as a float)... Or alternatively you'd need to add different operators for integer division and float division.

@fernewelten
Copy link
Contributor

We don't necessarily need opcodes for this. The compiler could generate the respective function calls in the background.

This would only need to be efficient when we envisage programmers to have lots of int-to-float, float-to-int conversions in tight loops with lots of iterations. Do we?

@ivan-mogilko
Copy link
Contributor Author

ivan-mogilko commented Nov 29, 2024

We don't necessarily need opcodes for this. The compiler could generate the respective function calls in the background.

This would only need to be efficient when we envisage programmers to have lots of int-to-float, float-to-int conversions in tight loops with lots of iterations. Do we?

After closing this ticket, I opened an alternative suggestion here: #2593

But today I even wonder if it was a mistake to suggest implementing Array.Length as a function (attribute), and not a opcode.
Because AGS compiler cannot optimize things, for example, by knowing that certain value or result of condition will be constant for the whole duration of some piece of code. So when you do a "for" loop iterating over an array, it will call Array.Length every time to check the end of iteration.

I don't know if that's important for AGS or not. There have to be written a good performance test for such experiment, in order to compare if such change would make any difference.

@ericoporto
Copy link
Member

I don't understand why being a function instead of opcode prevents optimization for the case of length. You can just as well create a rule to store the length in a variable and use such variable and prevent additional calls in theory.

@ivan-mogilko
Copy link
Contributor Author

ivan-mogilko commented Nov 29, 2024

I don't understand why being a function instead of opcode prevents optimization for the case of length. You can just as well create a rule to store the length in a variable and use such variable and prevent additional calls in theory.

It does not prevent optimization, but right now that would require a manual code rewrite from the user, who should be aware of the issue in the first place. Not to mention that this will make the code uglier.
I am not sure what do you imply by "create a rule".

@ericoporto
Copy link
Member

Right, I don't understand how the compiler works to come up with the bytecode. In operations research we use heuristics to describe like an approach of solving a problem when you have knowledge of the problem domain - English is failing me right now....

But what I mean by a rule is like a logic that if such code is met - a for clause that contains length in it's "header" - then you instead would do a different code. Other approach is to do this after the bytecode is in place somehow - but I don't know if there is already a machinery to be able to run through the generated bytecode and replace things. Since the length call is put in place by the compiler it should be possible to rely on it's name/meaning relationship.

@ivan-mogilko
Copy link
Contributor Author

ivan-mogilko commented Nov 30, 2024

But what I mean by a rule is like a logic that if such code is met - a for clause that contains length in it's "header" - then you instead would do a different code.

I suppose that's theoretically possible, but that would require to implement optimization in compiler, that's a huge thing on its own, which, i imagine, is going to be a lot of work.

In practice compiler would need to be able to detect that parts of the expression in "for condition" do not change during the course of the loop. In the given example it would have to parse the whole code in loop, and record what happens to the array.

EDIT:
Another way to achieve this perhaps is to introduce iterator mechanics and "foreach" kind of loops, which assume that the range stays constant in the duration of the loop.

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

4 participants