Jump to content

Sign in to follow this  
igneous01

Why is there no type safety in .sqf?

Recommended Posts

Just something I've been thinking about lately, but why does .sqf not include defining data types for variables?

A majority of errors are caused by calling functions or commands on variables that are of the wrong type. The errors are also not so straight forward either (ie. 0 Elements, 3 expected, Generic Error in Expression, Error select: Type Object, expected Array) this particular example is fairly clear that wrong data type is given, but it shows the error in the wrong spot (like inside a function). Not all commands will error when wrong data type is given either, some commands simply return undefined or 0 or null when the type they encounter is wrong.

Other examples include assigning a variable another variable that is undefined, engine determine if an undefined variable is nil or null when assigning that var to an object that doesnt exist, arrays that can be mixed data types. calling BIS functions with wrong data type in parameters will display an error in the functions themselves, rather than the source (invalid type in arguments given). This can happen alot as well when you have a lot of functions you are using that are calling other functions etc. Overwriting a variable to a new type (ie shared variable in multiple scripts where you forget what type it should be)

Another thing that is missing is the ability to overload functions (because there is no type declaration for vars) the only way to do this now is to do:

if (typename _var == "OBJECT" then {....
if (typename _var == "STRING" then {...
if (typename _var == "ARRAY" then {...

and change the command you are using to handle data from this variable, while this works, in some cases you are having to compile strings into code to do proper calculations, which is not necessary.

While it is convenient for flexible arguments for scripts/functions, arguments should not be done using traditional arrays in sqf, but with each index having its type set to avoid passing in wrong parameters.

This might seem trivial to some people, but whenever Im designing a mission or scripts of fair complexity (ie scripts calling other scripts) this is the number one thing that frustrates me in trying to debug something.

I hope they consider this for sqf in arma 3, or atleast allow us to use java to define types in sqf.

/Rant

Edited by Igneous01

Share this post


Link to post
Share on other sites

Seems to me like you want better error reporting and not a type system which is a means to achieve this. Have you tried to use squint?

Share this post


Link to post
Share on other sites
  Muzzleflash said:
Seems to me like you want better error reporting and not a type system which is a means to achieve this. Have you tried to use squint?

yes I have, and its really good for those little things like missing quotes/brackets and when a variable thats clearly defined in that script is not working with a command (bad type) however, it wont tell me if I use the wrong datatype in an argument, nor will it say anything if the variable is declared outside of the script.

And no, I think type system which is standard across any programming language should be implemented. Its there to help keep the coder organized and tell him when he is doing something he shouldnt be doing (like passing the wrong variable into a script). Its not apparent with 2 or 3 scripts, but when you have a collection of scripts with variables everywhere being passed into functions and other scripts, as well as variables being shared with multiple scripts, it really helps the coder (like moi) from making obvious and trivial mistakes like this, which are sometimes very hard to debug.

Share this post


Link to post
Share on other sites

I'm going to assume when you mean a type system you mean that the code is checked before it is run 8(e.g at compile time). Please let me know if I am wrong - runtime type checking is what we already have now.

Whilst almost any language have types, that does not mean that code is analysed before it is run. For example Python.

Firstly - I don't disagree that better error reporting would be nice.

But to answer your question:

Typically static scoped languages have type checking whilst dynamic languages do not. And there are good reasons for that. Here are some considerations for why it may not be feasible to implement type system:

- You would always have to write types which means more to write and in some cases does not add to readability. Also you will not be able to "overload" at all!.

- Even with static checking you would have to compile, you get error and you fix it. Much like it is now - but perhaps you will get slightly better error messages with type checking.

- You would no longer be able to nillify (Var = nil) since that would mean no type. So scripts that use that will not work anymore.

- AFAIK it is not actually possible to pass multiple arguments to a function - what you are passing is an array containing the "arguments", and the array is the real argument. How would that be type checked? Specify the entire type of the entire array? - look at next point.

- How would you declare an array? MyArray = [int, float, string, array]?. What happens if I in some parallel code does MyArray resize 2;. Is that legal? What is the type of MyArray now? So any script that use resize would no longer work.

- Would you type check this? MySum = MyNumber + (call compile "MyString");

- Ton of other situations.

- You would lose the ability to dynamically change variables.

- Basically you would lose the dynamic properties of the language, meaning instead of a crappy language that is dynamic we are left with a crappy language with bolted on types.

Why don't we just make specifying types optionally?

- Any code that runs non-type specified with type-specified would be like if no we did not specify types at all. Otherwise it would fail because of type mismatch.

- They would have to change the parser drastically. Not a trivial task to perform without causing other issues (e.g. ensuring that all existing code is still valid and parses correctly).

Hopefully Java would do what you need. Although from what I've seen it involves a lot of casting of values from the engine.

Edited by Muzzleflash

Share this post


Link to post
Share on other sites

I think .sqf would be harder to debug if it was strongly typed.

Now if there is a problem it compiles the .sqf anyways and you get the error when you call the code.

If it was strongly typed it would have to stop compiling and would likey result in ctd. Just like now if there is a problem in an addon or in the description.ext , it would be a pita to have to restart for each error.

Its not like c# or c++ where we compile before we run the code.

Share this post


Link to post
Share on other sites
  Riouken said:
If it was strongly typed it would have to stop compiling and would likey result in ctd. It would be a pita to have to restart for each error.

OMG :eek: -- thanks, now I'm going to have nightmares about trying to test a script and having to re-launch bc of ctd every time it had an error!

Share this post


Link to post
Share on other sites
  Muzzleflash said:

Typically static scoped languages have type checking whilst dynamic languages do not. And there are good reasons for that. Here are some considerations for why it may not be feasible to implement type system:

- You would always have to write types which means more to write and in some cases does not add to readability. Also you will not be able to "overload" at all!.

- Even with static checking you would have to compile, you get error and you fix it. Much like it is now - but perhaps you will get slightly better error messages with type checking.

- You would no longer be able to nillify (Var = nil) since that would mean no type. So scripts that use that will not work anymore.

- AFAIK it is not actually possible to pass multiple arguments to a function - what you are passing is an array containing the "arguments", and the array is the real argument. How would that be type checked? Specify the entire type of the entire array? - look at next point.

- How would you declare an array? MyArray = [int, float, string, array]?. What happens if I in some parallel code does MyArray resize 2;. Is that legal? What is the type of MyArray now? So any script that use resize would no longer work.

- Would you type check this? MySum = MyNumber + (call compile "MyString");

- Ton of other situations.

- You would lose the ability to dynamically change variables.

- Basically you would lose the dynamic properties of the language, meaning instead of a crappy language that is dynamic we are left with a crappy language with bolted on types.

Why don't we just make specifying types optionally?

- Any code that runs non-type specified with type-specified would be like if no we did not specify types at all. Otherwise it would fail because of type mismatch.

- They would have to change the parser drastically. Not a trivial task to perform without causing other issues (e.g. ensuring that all existing code is still valid and parses correctly).

Hopefully Java would do what you need. Although from what I've seen it involves a lot of casting of values from the engine.

- I dont see how you would be unable to overload, you can overload in C++ and Java++ just fine so long as the signature is different

- Since we dont have any sort of IDE or debug console to work with (which is fine, since its not that serious for sqf) it doesnt really matter. What does matter is that the correct error is reported.

- this really depends on the strictness of types, doing ie string myvar = "cat" and then doing myvar = nil could be just a macro to mean something like release myvar or destroy myvar. that is doable. Heres an example:

#define destroy(var) var = nil
string myvar = "lalala";
destroy(myvar);

- How does this work in other languages? its a special array specifically for arguments that check proper data types are passed (double param1, string param 2). having an argument array that is different from an array in sqf as is now would work.

- this should be either declared as:

 array <int> myArray 

or

int myArray[] 

there should also be a way to do a mixed type like now where the compiler doesnt care whats inside the array by doing this:

 array <> myArray

this way you can specify the strictness in the array and what it can hold

resize would still work in this case

- you are calling to compile MyString into code, so the script will halt until call returns a value from the compiling of that string, if it fails to compile the string (ie error) then call compile would return nil or false, and this is what happens already, no issue here

- Is it a good thing to change variables dynamically on the spot? Sure its fast, but its prone to producing alot of errors, this is a lazy approach to a problem in my opinion, this can be solved with casting data types (ie (string) (myObject)) casts object type into a string

- The major dynamic features of the language is the ability to compile and run code while at the same time compiling and running a script, not so much with assigning a variable to another type. How does the compiler know the difference between an int and a double? if I do _i = 0, does the compiler interprete that as 0 (int) or double (0.0)

Optional specifying of types would be welcome too, something like

var setTypeName "DOUBLE"

and allow changing of type later on by calling this command. Assuming the compiler is smart enough to determine what data type the coder is declaring (ie not using such a command as this) it can still do type check to see that its correct.

And yes, the parser would need alot of changes, I would be happy with a command like above that does this.

---------- Post added at 05:33 AM ---------- Previous post was at 05:28 AM ----------

  Riouken said:
I think .sqf would be harder to debug if it was strongly typed.

Now if there is a problem it compiles the .sqf anyways and you get the error when you call the code.

If it was strongly typed it would have to stop compiling and would likey result in ctd. Just like now if there is a problem in an addon or in the description.ext , it would be a pita to have to restart for each error.

Its not like c# or c++ where we compile before we run the code.

thats not entirely true, when you do something like:

call compile preprocessfile "functions.sqf"

the engine will attempt to compile the code, if any errors are found it will simply stop compiling it and log an error (where as preprocessfilelinenumbers simply stops compiling doesn't tell you something is wrong) execVM is compiled the same way (otherwise like you said, we would ctd each time we had an error) if sqf were strongly typed, the compiler would quit and log the error rather than ctd.

Edited by Igneous01

Share this post


Link to post
Share on other sites

preProcessFile is the one that gives you very vague information on the error, from my experience.

Share this post


Link to post
Share on other sites
  cuel said:
preProcessFile is the one that gives you very vague information on the error, from my experience.

It does, sometimes its very misleading, but atleast it tries to, preProcessFileLineNumbers doesnt error, or log any warning at all. You'll know it failed to compile when your functions are undefined (which is not always the case either)

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×