ID:119260
 
Not Feasible
Applies to:DM Language
Status: Not Feasible

Implementing this feature is not possible now or in the foreseeable future
I'm sure someone has suggested this before, I wasn't able to find the thread tho.

I, and several other developers on my team, would absolutely love it if it was possible to set visibility for procs, which are tied to datums and vars which are tied to datums.

I suggest the same concept as any other object based language has: public, (restricted), private.

public: can be accessed from anywhere
restricted: can only be accessed by objects of this type and subtypes
private: can only be accessed within the same object

no var or proc would demand this to be set and the default would be 'public', to ensure compatibility with existing code.

The above is becoming ever more vital for development in non-professional and non-structured teams which don't have everything planed out. (so most teams, really).

A second thing I'd request however is the addition of a non-inherited variable to all atom objects called 'abstract'. It would default to 0.

so having:
/obj/item
--abstract = 1
/obj/item/axe
/obj/item/bow

would be interpreted as only /obj/item being abstract. (due the non-inherited part) The reason for it being non-inherited is because the vast majority of atoms in a typical project aren't abstract and having to set a custom defined variable to 1 for each one of them can be tedious. The effect of abstract objects is that it would not be possible to place those specific objects on the map.

Addendum: To make it easier to implement into the actual language I suggest that the first tier of implementation is just an update to the compiler. In other words that everything works exactly the same in the actual compiled code, but the compiler giving you error messages when trying to compile code that inappropriately references protected variables.
I don't see this being feasible on the compiler end, inasmuch as the compiler is a dark and scary place and an overhaul of this magnitude would be impractical. But it's even less feasible at runtime, because all var and proc references would have to be checked for permission, slowing execution.

Essentially member access controls are language features that exist strictly to protect the programmer from themselves. So in a broad sense this is only sensible from the compiler side anyway, but its helpfulness is relatively questionable.
Shame.

"strictly to protect the programmer from themselves." is actually the reason why I requested it.

I'm guessing that during compiling, the variables and procs are mapped into some sort of table or equivalent. Would it not be possible to simply also include visibility information to such a table.

As for compiling I don't know if syntax and such is checked by going through all lines of code and performing all check on each line at once or if it works in stages, iterating through code several times. But in either case, it should be possible to simply add an additional check, which after checking that a variable or proc actually exists, also checks in the var/proc map for it's visibility. If it's public it's good, if it's private it does an equivalent of "if source.type == varowner.type" and if it's restricted, it does an equivalent of "if istype(source, varowner.type)"
I was just thinking of a possible way to implement this:

mob/var/private/myvariable
mob/var/protected/myvariable

Variables defined in this way would have additional compile-time checks performed on their use.

If the private flag is set, any attempt to read or write to the variable from a src object which is not of the same type fails.

protected is like private, except if src is set to a child of the main type it's still allowed.

Examples of how it would work in code:
/obj/weapon/var/protected/strength
/obj/weapon/var/protected/double_handed
/obj/weapon/sword/strength = 5
/obj/weapon/sword/double_handed = 1 //compile error: variable may not be accessed in this scope
/obj/weapon/knife/strength = 3

/proc/test()
var/obj/weapon/W = new/obj/weapon/sword()
world.log << W.strength //compile error: variable may not be accessed in this scope
world.log << W.double_handed //compile error: variable may not be accessed in this scope

/obj/weapon/proc/test()
var/obj/weapon/W = new/obj/weapon/sword()
world.log << W.strength //5
world.log << W.double_handed //1

/obj/weapon/sword/proc/test2()
var/obj/weapon/W = new/obj/weapon/sword()
world.log << W.strength //5
world.log << W.double_handed //compile error: variable may not be accessed in this scope


The check would be purely compile time, and it would only encompass changes that you make to the variable by directly accessing it or redefining it (so you can still change the value with W.vars["double_handed"] = 1 if you wanted).

You can only define variables as private or protected on object-level; you can't do this on a global scale.

Variables that have been marked as private cannot be re-declared in another object. Instead, it should give a compile error that the variable name is a duplicate though inaccessible one.

Would this make it more feasible to implement?