# Language Syntax

### 1. Outputs Of Operations Are Of The Wrong Data Type¶

Description: The output type of an operation is determined by the first operand a*b. For example: 9*5.5 evaluates to 49 and not 49.5. However, the expression 5.5*9 gives the correct result.

Expected Behaviour: Both the expressions in the above example should yield the same result.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 8 void main() { int a = 7; float b = 1.1; // expected 7/1.1 = 6.363636 but actually // prints 7/1.1 = 6 xsChatData("7/1.1 = "+a/b); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, 6.363636 should have been chatted to the screen, but instead 6 is shown on the screen.

### 2. Modulo Operator Does Not Work Properly With Floating Point Values¶

Description: Using the modulo operator on floats does not return the fractional part of the answer.

Expected Behaviour: Using the modulo operator on a float value should correctly return the fractional part of the remainder.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 void main() { // expected 5.5 mod 1 = 0.500000 but actually // prints 5.5 mod 1 = 0.000000 xsChatData("5.5 mod 1 = "+(5.5%1)); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, 0.500000 should be chatted to the screen, but instaed 0.000000 is shown.

### 3. Function Parameters And Return Statements Do Not Implicitly Type Cast¶

Description: Passing an int to a function parameter that is supposed to take in a float value gets used as an int and is not type casted. Similarly, values returned from a function are not type casted to the function's return type. For example, if an int is returned in a function that is supposed to return a float, it will just return the int as is without type casting into float

Expected Behaviour: Values that are passed to/returned from a function should be correctly type casted.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 float test(float a = -1) { // keeping in mind the previous bug, // 5*5.5 evaluates to 27 (an int) // 27/2 then evaluates to 13 (an int) return (a*5.5/2); // expected to return 13.750000 } void main() { // expected test = 13.7500000 // prints test = 13 xsChatData("test = "+test(5)); // passed 5 for the argument which should // get type casted into a float but it // actually does not. // note that this function is supposed to return a float // but it actually returns an integer! } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, 13.750000 should be chatted to the screen, but 13 is shown instead

### 4. Limit On Number Of Params In A Function Call¶

Description: The number of parameters that can be used IN a function call are limited to 12. Attempting to call a function with more parameters results in an error from the game. Note that the error in the example shown below happens at the line the call is made, and not at the function definition itself. This suggests that defining a function with more than 12 parameters can be defined but they can't be called

Expected Behaviour: There should ideally be no limit on the amount of parameters for a function

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void test( int a1 = 1, int a2 = 1, int a3 = 1, int a4 = 1, int a5 = 1, int a6 = 1, int a7 = 1, int a8 = 1, int a9 = 1, int a10 = 1, int a11 = 1, int a12 = 1, int a13 = 1 ) { } void main() { test( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ); } 
3. Include the script in the scenario or RMS
4. When a game is played using this above script, an error at line 15 (the last line of the function call) is shown
5. If the lines with the function call are commented out, the error goes away

### 5. Cannot Use Variables Or Expressions In Vector Initialisation¶

Description: When initialising a vector, expressions or variables cannot be used in the initialisation. The code in question is shown below.

Expected Behaviour: Expressions and variables should be able to be used when initialising Vectors.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 void main() { float x = 2; float y = 4; float z = 6; // none of these declarations work: vector v1 = vector(5+5, 10, 4); vector v2 = vector(5, 10-1, 4); vector v3 = vector(5, 10, 4+5); vector v4 = vector(x, 5, 3); vector v5 = vector(3, y, 2); vector v6 = vector(4, 4, z); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the Could not parse the code for 'main' function error is shown

### 6. Unary Negative Does Not Work¶

Description: The unary negative operator does not work.

Expected Behaviour: Unary negative operator should return the negative of the number.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 void main() { int a = 5; float b = 3.4; // these do not work: int c = -a; float d = -a; int e = -b; float f = -b; int g = -a+b; float h = -a+b; } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the Could not parse the code for 'main' function error is shown

### 7. Explicit Type Casting Does Not Work¶

Description: Explicit type casting does not work on variables or at initialisation.

Expected Behaviour: Explicit type casting should be able to be used to convert one data type to another.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void main() { float a = 5.5; float b = (int)a; // will outwright assign 0 to b // expected b = 5.000000 but // prints b = 0.000000 xsChatData("b = "+b); b = 6.7; xsChatData("b (two) = "+b); b = (int)5.7; // this expression will do nothing // expected b = 5.000000 but // prints b = 6.700000 xsChatData("b (three) = "+b); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the effects described in the code using comments for each case are observed

### 8. Loop Variable Not Bounded To The Scope Of The Loop¶

Description: The loop variable from a for loop can be used anywhere outside the body of the loop

Expected Behaviour: The scope of the looping variable in for loop should be limited only to the body of the loop

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 8 void main() { for(j = 2; < 10) { xsChatData("j ="+j,); } // the scopr of the variable j is not limited to just the loop above xsChatData("j (out of loop scope) = "+j); // this will print "j (out of loop scope) = 10" } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, 'j = 10' will be printed last because of the chat data at the end.

### 9. Assigning Loop Variable To Itself Does Not Throw An Error¶

Description: Assigning the loop variable from a for loop to itself in the loop definition statement doesn't throw an error. The loop body is even run once

Expected Behaviour: This should throw an error in the editor

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 void main() { xsChatData("test before for lop for loop"); for(j = j; < 10) { xsChatData("test inside for loop"); } xsChatData("test after for loop"); } 
3. Include the script in the scenario or RMS
4. When a game is played all three chat data functions run and show on screen

### 10. Integers Softly Limited To 999_999_999¶

Description: An int cannot be directly initialised a value greater than 999_999_999. Attempting to do so causes a parsing error. They can still be given values higher than 999_999_999 by just adding/any other math operations

Expected Behaviour: Any value between the 32 bit signed int limits (-2147483648 and 2147483647 inclusive) should be a valid initial value for an integer

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 void main() { // this line will cause a parsing error: int a = 1000000000; } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, 'j = 10' will be printed last because of the chat data at the end.

### 11. Static Variables In Recursive Functions¶

Description: If a static variable is declared inside a recursive function, its value cannot be changed

Expected Behaviour: static variables inside recursive functions should behave normally like they do in C++

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 int prevent_infinite_recursion = 1; void test() { static int a = 1; xsChatData("a is "+a+" pri is "+prevent_infinite_recursion); a++; prevent_infinite_recursion++; if(a < 10 && prevent_infinite_recursion < 10) test(); } void main() { test(); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the values of the variable a are always the same

### 12. Static Variables In Global Scope¶

Description: If a static variable is declared in the global scope, XS execution fails silently

Expected Behaviour: This should be allowed (or throws an error) since static variables technically give variables internal linkage which they already have by default in XS. What should really not be allowed though is using extern static int a = 10;

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 static int a = 10; void main() { xsChatData("test "+a); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, nothing is chatted to the screen

### 13. Strings In Global Scope¶

Description: A string declared in the global scope doesn't retain its value

Expected Behaviour: When a string is declared in the global scope, it should be usable like other data type variables

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 string a = "test"; void main() { // prints random text to the screen or ??? or shows an // Error invalid encoding xsChatData("a = "+a); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the actual value that was assigned to the string is not chatted to the screen, but something random

### 14. Off By One Error With infiniteLoopLimit¶

Description: If infiniteLoopLimit = n; is used inside a function, it makes it so that ALL loops in that function run a maximum of n+1 times.

Expected Behaviour: It should make the loops run only n times, one is extra

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 void main() { infiniteLoopLimit = 10; int loopCount = 1; while(true) { xsChatData("loop count %d", loopCount); loopCount++; } // the last line printed is "loop count 11" off by one error here } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the last line chatted to the screen is "loop count 11".

### 15. Silent XS Crash with infiniteRecursionLimit¶

Description: If infiniteRecursionLimit = n; is used inside a function, the function may only be called n-1 times in one call stack. Attempting to call it for the n-th time will result in a silent XS crash

Expected Behaviour: The n-th function call should run normally, and further calls to the function in the same call stack should be prevented. The entirety of XS execution should not crash

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 int calls = 1; void recursionTest() { infiniteRecursionLimit = 10; xsChatData("recursion test %d", calls); // the last line chatted to screen is "recursion test 9" and no further XS execution takes place calls++; recursionTest(); } void main() { recursionTest(); xsChatData("further xs execution"); // this line isn't chatted to the screen } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the last line chatted to the screen is "recursion test 9". The last xsChatData in main() isn't run at all.

### 16. Return Statements Do Not Work As Documented¶

Description: Paranthesis are needed around return expressions for them to work.

Expected Behaviour: Return expressions should work with or without paranthesis.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 8 int test() { return 5+5; // instead, return (5+5); would work. } void main() { int a = test(); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the Could not parse the code for 'test' function error is shown

### 17. Scopes Cannot Be Explicitly Created¶

Description: {} cannot be used to explicitly create a scope

Expected Behaviour: Code within {} should define a scope and variable lifetime should properly be managed like in C++

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 void main() { { int a = 10; } xsChatData("test "+a); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, a parsing error is thrown

### 18. Cannot Declare Variables As A const In Function Parameters¶

Description: It is not possible to declare a function parameter as a const even though it is used in the xsChatData function in the official documentation.

Expected Behaviour: It should bee possible to declare function parameters as a const

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 float test(const float a = -1) { return (a*5); } void main() { xsChatData("test = "+test(5)); } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the 'const' is not a valid parameter type error is shown

### 19. Missing Data Types Which Are Documented¶

Description: The long, char and double data types do not exist, even though the official XS documentation references them.

Expected Behaviour: Variables of the long, char and double data types shoulld be able to be initialised.

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 void main() { // none of these declarations work: long a = 1000; double b = 10.34; char c = '8'; } 
3. Include the script in the scenario or RMS
4. When a game is played using the scenario or RMS, the Could not parse the code for 'main' function error is shown

### 20. Weird Behaviour With Return Statements¶

Description: This behaviour is not understood well

Expected Behaviour: An Error?

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
  1 2 3 4 5 6 7 8 9 10 11 float test(float a = -1) { // thisDoesNot... is not a function return thisDoesNotMatterWhatIsGoingOn(a)/55 + 2*2; // seems like this is completely ignoring the first term in the expression. } void main() { // prints test = 4 // once again, note that a float returning function is returning an int xsChatData("test = "+test(5)); //returns 4 } 
3. Include the script in the scenario or RMS
4. Run the main function of the script in the scenario

### 21. Using Single Quotes Causes The Could not emit quads Error¶

Description: Using single quotes (to construct strings) is not allowed and causes the could not emit quads error

Expected Behaviour: A more useful error along the lines of: "Could not parse function x" or "Single quotes not allowed"

Reproduction Steps:

1. Create a new scenario or RMS
2. Create a new XS script with the following code:
 1 2 3 4 5 6 7 void unrelatedFunc() { // ... } void main() { string x = 'my string'; } 
3. Include the script in the scenario or RMS
4. Run the main function of the script in the scenario