-
Notifications
You must be signed in to change notification settings - Fork 241
Description
It has been asked for many times before to make it so that lexicons can use the syntax of suffixes, like so:
set my_var to lexicon(
"key0", 0, // key looks like an identifier
"key1", 100, // key looks like an identifier
"key2", 200, // key looks like an identifier
"key with spaces", 300, // key cannot be an identifier
List("key that isn't even a string", 0), 400 // key cannot be an identifier
).
print my_var:key0. // prints 0.
print my_var:key1. // prints 100.
print my_var:key2. // prints 200.
print my_var:key with spaces. // doesn't parse - not do-able
print my_var:List("key that isn't even a string",0). // doesn't parse - not do-able
(I kept examples of keys that wouldn't work in the example to show what would and would not be supported by this proposed change. This proposed change still wouldn't allow those last two examples to work, but would allow the first 3 to work.).
The inability to make identifiers become lexicon keys in this way was the main reason for this long thread from before asking us to keep deprecated syntax around: #2288.
I had pushed back on it because I thought it required special parser and compiler support for just one type of class, and that felt wrong. (Like the way the C# keyword "yield" and the .Net type IEnumerable are intertwined in a way which never sat well with me.)
But I hit on a possible way to do it that has nothing to do with the compiling and lives entirely inside the class Lexicon itself, and that might work better.
When the compiler sees the colon-syntax, that causes it to call Structure.GetSuffix() or Structure.SetSuffix() on the result. Well we already have a few instances where classes derived from Structure override GetSuffix() - BodyTarget does, as does Config, StageValues, and VesselTarget. (They cook the value a little bit, then call base.GetSuffix().)
So we could put the logic entirely inside Lexicon instead of touching the compiler at all. We could have Lexicon override GetSuffix() by having it first try base.GetSuffix() and if that fails then instead look inside itself for keys that match.
This way the logic lives entirely inside the class definitions and NOT in the compiler.
The compiler's rule would thus remain unchanged: "When I see AAA:BBB, then I will eval AAA, and whatever object that ends up being, I will call that object's GetSuffix("BBB") and put its result on the stack. That would be the same for lexicons or anything else. It's the lexicon that would define that it does something unusual when asked to GetSufffix.
A similar logic would work for SetSuffix, I presume.