LCValueFetch undefined variables

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, LCMark

Locked
monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

LCValueFetch undefined variables

Post by monte » Mon Nov 04, 2013 5:30 am

I noticed this issue quite a while ago and I think I bug reported it but I can't find the report. If you declare a variable then don't assign a value to it and then use it in the call to the external the api throws an error. If the parameter was an optional one then I think it should handle the situation. So what I propose is in these cases the engine interface just returns kMCExternalErrorNone with no assignment to p_value unless it's the kMCExternalValueOptionAsVariable option. Our parameters will then be assigned default values. Giving these unassigned variables should be given a default empty value during the fetch is an option too but as we can't really do that for all types it might be better not to do it.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Mon Nov 04, 2013 10:35 am

I think that's a bug in the support code rather than something which should be utilized - variables are 'notionally' initialized with empty, indeed all the syntax evaluation code in the engine will ensure this is the case (by virtue of the fact MCExecPoint sees UNDEFINED as EMPTY).

There is potential scope for allowing unspecified parameters in an argument list for being passed as 'not present' so default values could be used. So, in things like:

Code: Select all

  myFunc a, b, , , c
Here the third and fourth parameters are not specified, and so would assume defaults in the external code.

When I looked at this before, I thought it would be better if the actual MCVariableRef at the non-specified location in the argument list was nil, rather than anything else (thus meaning if the external support code got a variableref with undefined, it could actually be treated as empty).

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Mon Nov 04, 2013 11:54 am

runrevmark wrote:I think that's a bug in the support code rather than something which should be utilized - variables are 'notionally' initialized with empty, indeed all the syntax evaluation code in the engine will ensure this is the case (by virtue of the fact MCExecPoint sees UNDEFINED as EMPTY).
So that's fine for strings. boolean=false? numbers=0? Would the fetch interface should return these standard empty values when an undefined variable is used?
runrevmark wrote: There is potential scope for allowing unspecified parameters in an argument list for being passed as 'not present' so default values could be used. So, in things like:

Code: Select all

  myFunc a, b, , , c
Here the third and fourth parameters are not specified, and so would assume defaults in the external code.
Hmm... isn't that how it works now?
runrevmark wrote:When I looked at this before, I thought it would be better if the actual MCVariableRef at the non-specified location in the argument list was nil, rather than anything else (thus meaning if the external support code got a variableref with undefined, it could actually be treated as empty).
Hmm... there could be backwards compatibility issues there though because the older support code might not like the nil variable refs...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Mon Nov 04, 2013 7:37 pm

So that's fine for strings. boolean=false? numbers=0? Would the fetch interface should return these standard empty values when an undefined variable is used?
Well, to be the same as the engine I think it should be: if fetching an 'undefined' value in string context, you get the empty string, in array context you get the empty array and in numeric context you get 0. In boolean context its an error though - as the only things that are considered to be booleans are 'true' and 'false'. (I need to double check this).
Hmm... isn't that how it works now?
I don't think so - it only does default processing tail parameters - i.e. if the number of arguments passed < the number of arguments declared.
Hmm... there could be backwards compatibility issues there though because the older support code might not like the nil variable refs...
The behavior could be keyed on the version of the external API the external expects so that shouldn't be a problem.

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Mon Nov 04, 2013 8:34 pm

I think it's false:

Code: Select all

on mouseUp
   if empty then
      put true
   else
      put false
   end if
end mouseUp
I'll test the default parameter handling because it seems weird I haven't noticed this yet...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Mon Nov 04, 2013 9:14 pm

'if' is a special case - it compares the value to "true"... All properties that accept booleans, and syntax which take booleans only accept "true" and "false" I think (those code paths use MCU_stob which is strict).

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Mon Nov 04, 2013 10:18 pm

Ah... ok, that's reasonable.

In the case of parameter 3 and 4 above when Handle does MCParameter -> get_value would it return an undefined variable or one with an empty string?
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Tue Nov 05, 2013 11:21 am

I had a further look at this...

The conversion of undefined/empty to 0 in the engine depends on what you are doing. Numeric properties tend to be strict - they use MCU_stoi* which doesn't see empty (undefined) as 0 - given that many properties accept empty as a valid value, this seems sensible. On the other hand, syntax that manipulates numbers (where ston() or ton() is called on the execpoint after eval'ing) does treat empty/undefined as 0. Of course, this latter observation does screw things up from a consistency point of view - and I'm not sure what I think about that, I fear it maybe a case of 'convenience' over 'correctness' in a situation where the latter would have been better. (Of course, one interpretation could see that *only* undefined gets translated to 0 in numeric context, and not empty - that would make the syntax manipulating numbers slightly more strict, and relax property setting slightly).

One thing that should definitely be the case is that in fetch_as_string, if the value is undefined it should return the empty string - that is at least consistent throughout the engine. (This change would also mean you get empty for unspecified arguments in the list, when evaluated as a string that is).

In terms of the optional parameter thing, then this is probably best handled by not creating MCVariableRef's (as I mentioned before) for unspecified parameters - although this will require a few changes in both lcidlc, the engine and the support code.

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Tue Nov 05, 2013 11:14 pm

Hmm.... I definitely agree that parameters 3 and 4 here if optional should end up with the default value if there is one. There's a question in my mind about how an undefined variable should be treated though... if it were an optional parameter then perhaps the default value should be used? If not then, yes, we need to return an equivalent value to the way the engine treats an undefined variable. It occurs to me that it might be better if undefined variables were always defined as something the first time they are used to ensure the engine treats them consistently throughout...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Wed Nov 06, 2013 9:19 pm

I think my previous post was a little misleading - well, not so much that but I had forgotten one important distinction between things like 'the textSize' and things like '+'... The types they require are different.

'the textSize' expects either empty or an integer - essentially its type is union(empty, integer).

'+' expects numbers - its signature is (number, number)->(number).

So, in the case of + when you give it empty, the engine attempts to convert to number - with the rule that empty can convert to 0 - and you get 0. In the case of 'the textSize', it expects empty or integer so when you give it empty the engine is happy with that and doesn't try to convert.

From this point of view, 'uninitialized' variables are not uninitialized, they are empty (which is, I think, how I always tend to think of them on a day to day basis - because that is the effect they have in all current situations in the engine).
There's a question in my mind about how an undefined variable should be treated though... if it were an optional parameter then perhaps the default value should be used?
I'm still on the fence about this one - I need to ponder more :)

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Wed Nov 06, 2013 10:44 pm

I've thought about this some more and I think as LiveCoders we come to expect undefined variables to be empty so in all cases an undefined variable should be treated as closely as we can to how the engine treats them. So booleans should throw errors, numbers should be 0 and strings should be "", arrays and dictionaries should throw errors if not an array.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Fri Nov 08, 2013 9:30 pm

This is what I always come back to when I've pondered the notion of an 'undefined' value before - it ends up needing to be almost identical to 'empty' to be consistent with everything now, and as such places where it aren't (like passing a variable you haven't initialized into a piece of syntax / argument list causing a default value) is likely to be slightly jarring.

(By the way, this case is distinct from having a missing parameter - i.e. a, ,b - since that is syntactic - there is no expression there; for example, this is the same as not having the 'at size ...' clause in import snapshot).

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: LCValueFetch undefined variables

Post by monte » Fri Nov 08, 2013 10:39 pm

Yep... so to handle undefined vars we just need to change fetch to check for undefined and then apply the defaults... Numbers should probably use get_as_real.

For missing parameters I'm not sure where to look to see if there's a way to identify them in MCExternalV1::Handle as missing... I see the stuff about temp vars but I can't see anything in MCParameter to identify that the param was missing...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1208
Joined: Thu Apr 11, 2013 11:27 am

Re: LCValueFetch undefined variables

Post by LCMark » Sun Nov 10, 2013 2:41 pm

Yep... so to handle undefined vars we just need to change fetch to check for undefined and then apply the defaults... Numbers should probably use get_as_real.
I think the correct behavior here is to (in MCExternalVariableFetch) change it so:
  • If AsInteger/AsCardinal - if (var -> is_empty()), return 0.
  • If AsReal - if (var -> is_empty()), return 0.0.
Then in fetch_as_string (in externalv1.cpp) change it so that 'if (p_var -> is_undefined())' return empty.

In terms of missing parameters then this might be a little more subtle. If you look at MCParameter, then it holds an 'exp' which is the expression that is used to evaluate the parameter. If this is 'nil', then it means no argument was specified. Therefore, it should be enough to add an accessor for 'ispresent()' to MCParameter, and then process that in MCExternalV1::Handle to not create / pass an MCVariableRef to the external handler (i.e. so not present arguments are passed as nil.

Locked

Return to “Engine Contributors”