ID:2091430
 
BYOND Version:510.1345
Operating System:Linux
Web Browser:Chrome 50.0.2661.102
Applies to:Dream Maker
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary:
initial() on a const variable does not compile, saying "cannot change constant value".

Numbered Steps to Reproduce Problem:
Use initial() on a const variable

Code Snippet (if applicable) to Reproduce Problem:
/datum/var/const/some_const_var = 1

/world/New()
var/datum/D = /datum
var/thing = initial(D.some_const_var)
world.log << "thing is [thing]"


Expected Results:
"thing is 1"

Actual Results:
error: D.some_const_var: cannot change constant value

Does the problem occur:
Every time? Or how often? Every time
In other games? Yes
In other user accounts? Unknown
On other computers? Unknown

When does the problem NOT occur? When the var is not const.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? Unknown

Workarounds: None known
Tested a little more; this is AFAIAA entirely undocumented, but the following works (!!!):

/datum/var/const/some_const_var = 2

/world/New()
var/datum/D = /datum
var/thing = D.some_const_var
world.log << "thing is [thing]"


It does not, however, work for parent_type, which is the 'const' var I initially tested before genericising it for this bug report.
I found this in the compiler code for initial():

//use save idx even though we are getting value because that handles lists correctly
//TODO: should make this work for consts and other non-writable values
PreEvalSaveIdx(n);
Add(PUSHIDX_INST);

var_info_idx = initial_valIdx;
AddSaveIdx(n);

Apparently that's a very long-awaited todo. What this code is saying is that the node within is being treated like a variable index that will be written to, and AddSaveIdx() is where the message about const is coming from.

I'm really puzzled by this note, because initial() doesn't handle lists correctly at all; I think the thing it's meant to handle here is a case like initial(list[1]) or something, but even that I don't get.

PreEvalSaveIdx() checks to see if you're using the [] operator and does some stack work if so, and AddSaveIdx() also does something differently when lists are in play. Presumably, I think all I need to do here is make another function similar to AddSaveIdx() that does the same legwork but does not set the saving flag. (Or, I can just add an argument with a default value, but I prefer another function because it's clearer and also I think faster.)
I just poked initial() with lists, and found... well. Something a bit more broken.

var/x = 3
var/y = null
var/z = list()

/world/New()
x = list()
y = "hello"
z = 5
world.log << "x: [initial(x)]"
world.log << "y: [initial(y)]"
world.log << "z: [initial(z)]"
del(src)


Expected output is:

x: 3
y:
z:


Actual output is:

x: /list
y: hello
z: 5


Should I make a separate bug report for initial() not working on globals, or?
In response to GinjaNinja32
Have you tried checking this in a place other than world/New()?
How's this? Same output as when it was in /world/New().
var/x = 3
var/y = null
var/z = list()

/client/verb/test()
x = list()
y = "hello"
z = 5
world.log << "x: [initial(x)]"
world.log << "y: [initial(y)]"
world.log << "z: [initial(z)]"
This is quite annoying when trying to create debug tools and some optimization code.

initial(datum.type), initial(datum.parent_type), and initial(datum.vars) all don't work
well initial(datum.vars) would never work, as that's a list.
You can't get initial values of objects like that.
The ability to get a ref to (likely a copy of) the type's compile time value list, would be handy.

It wouldn't work normally yes, but a snowflake for it would be handy. the vars list isn't even a real list, its generated at access time