Map literals in ASH (potential feature)

Actually needs two little patches:

- One when you have just defined an aggregate
- One when you have a multiple layer map and are parsing an aggregate literal.

With revision 17658:

Code:
record rec1 { int a; string b; };

rec1 [int,int] rmap {4: {4: new rec1( 10, "abc" ) }, 10: {40: new rec1( 100, "xyz" ) } };

foreach key1, key2, val in rmap {
    print( "[ " + key1 + ", " + key2 + " ] -> ( " + val.a + ", " + val.b + " )" );
}
yields

Code:
[color=green]> test-map2[/color]

[ 4, 4 ] -> ( 10, abc )
[ 10, 40 ] -> ( 100, xyz )
I like it.
 
For Reference, I tried something I imagined would work, but didn't. I have this code:

Code:
// Far Future rewards
static item RIKER = $item[ Riker's Search History ];		// combat item: 900-1000 sleaze damage
static item KARDASHIAN = $item[ Shot of Kardashian Gin ];	// EPIC 1 drunk booze, +3 PVP fights
static item POINTY_EARS = $item[ Unstable Pointy Ears ];	// accessory disappears at rollover, +3 stats
static item MEMORY_DISK = $item[ Memory Disk, Alpha ];		// usable, allows access to The Far Future
static item EARL_GREY = $item[ Tea, Earl Grey, Hot ];		// EPIC 1 full food, 1000 MP and 1000 HP

// Keyword for Exandora's FarFuture script to replicate each item
static string [item] FAR_FUTURE_OPTION;
static
{
    FAR_FUTURE_OPTION[ RIKER ] = "riker";
    FAR_FUTURE_OPTION[ KARDASHIAN ] = "booze";
    FAR_FUTURE_OPTION[ POINTY_EARS ] = "ears";
    FAR_FUTURE_OPTION[ MEMORY_DISK ] = "memory";
    FAR_FUTURE_OPTION[ EARL_GREY ] = "food";
}
I tried to initialize using a map literal: { RIKER: "riker", ...} but it didn't work.
That's because although RIKER is (correctly) of type "item", it is not a constant. It is a Variable Reference. And, unfortunately, since static initialization happens at run time, not compile time, we can't even evaluate it at compile time.

The map literal however does happen at compile time. If we generated code to initialize the map at runtime, we'd presumably evaluate the lhs and rhs.

That is not how this works, though, so we should presumably require them to actually be constants and disallow variable references.
 
It doesn't work even if you remove static, if I'm not mistaken.

I agree that the two reasonable approaches are either to make the literal resolve during runtime, or to require keys to be const. I personally would prefer the former because it's less surprising to me, especially since values resolve as expected.
 
Looking back at r17654 -- we clearly evaluate the value.
Code:
 entry.setValue( entry.getValue().execute( interpreter ) );

I wonder if this would be as simple as just evaluating the key, as well.
 
Apparently setKey doesn't exist, so you'd have to construct a whole separate map. I guess you could cache that with an "isEvaluated" boolean private property.
 
On the other hand, if you wanted to require keys to be const, you could just throw an exception in Parser.parseAggregateLiteral if the lhs is a VariableReference.
 
Test program:

Code:
// Far Future rewards
static item RIKER = $item[ Riker's Search History ];		// combat item: 900-1000 sleaze damage
static item KARDASHIAN = $item[ Shot of Kardashian Gin ];	// EPIC 1 drunk booze, +3 PVP fights
static item POINTY_EARS = $item[ Unstable Pointy Ears ];	// accessory disappears at rollover, +3 stats
static item MEMORY_DISK = $item[ Memory Disk, Alpha ];		// usable, allows access to The Far Future
static item EARL_GREY = $item[ Tea, Earl Grey, Hot ];		// EPIC 1 full food, 1000 MP and 1000 HP

// Keyword to ask Exandora's FarFuture script to replicate each item
static string [item] FAR_FUTURE_OPTION;
static
{
    FAR_FUTURE_OPTION[ RIKER ] = "riker";
    FAR_FUTURE_OPTION[ KARDASHIAN ] = "booze";
    FAR_FUTURE_OPTION[ POINTY_EARS ] = "ears";
    FAR_FUTURE_OPTION[ MEMORY_DISK ] = "memory";
    FAR_FUTURE_OPTION[ EARL_GREY ] = "food";
}

foreach key, value in FAR_FUTURE_OPTION {
    print( key + " (" + key.to_int() + ") -> " + value );
}
yields:

Code:
Riker's Search History (9118) -> riker
Shot of Kardashian Gin (9119) -> booze
Unstable Pointy Ears (9120) -> ears
Memory Disk, Alpha (9121) -> memory
Tea, Earl Grey, Hot (9122) -> food
With literals, test program:

Code:
// Far Future rewards
static item RIKER = $item[ Riker's Search History ];		// combat item: 900-1000 sleaze damage
static item KARDASHIAN = $item[ Shot of Kardashian Gin ];	// EPIC 1 drunk booze, +3 PVP fights
static item POINTY_EARS = $item[ Unstable Pointy Ears ];	// accessory disappears at rollover, +3 stats
static item MEMORY_DISK = $item[ Memory Disk, Alpha ];		// usable, allows access to The Far Future
static item EARL_GREY = $item[ Tea, Earl Grey, Hot ];		// EPIC 1 full food, 1000 MP and 1000 HP

// Keyword to ask Exandora's FarFuture script to replicate each item
static string [item] FAR_FUTURE_OPTION {
     RIKER : "riker",
     KARDASHIAN : "booze",
     POINTY_EARS : "ears",
     MEMORY_DISK : "memory",
     EARL_GREY : "food"
};

foreach key, value in FAR_FUTURE_OPTION {
    print( key + " (" + key.to_int() + ") -> " + value );
}
yields:

Code:
EARL_GREY (0) -> food
KARDASHIAN (0) -> booze
MEMORY_DISK (0) -> memory
POINTY_EARS (0) -> ears
RIKER (0) -> riker
We cannot evaluate the key at compile time since, although it looks like a constant, it doesn't actually get initialized until run time.

I'll make the aggregate literal into something that evaluates at runtime. How hard can it be? :)
 
With revision 17878,

Code:
// Far Future rewards
static item RIKER = $item[ Riker's Search History ];		// combat item: 900-1000 sleaze damage
static item KARDASHIAN = $item[ Shot of Kardashian Gin ];	// EPIC 1 drunk booze, +3 PVP fights
static item POINTY_EARS = $item[ Unstable Pointy Ears ];	// accessory disappears at rollover, +3 stats
static item MEMORY_DISK = $item[ Memory Disk, Alpha ];		// usable, allows access to The Far Future
static item EARL_GREY = $item[ Tea, Earl Grey, Hot ];		// EPIC 1 full food, 1000 MP and 1000 HP

// Keyword to ask Exandora's FarFuture script to replicate each item
static string [item] FAR_FUTURE_OPTION {
     RIKER : "riker",
     KARDASHIAN : "booze",
     POINTY_EARS : "ears",
     MEMORY_DISK : "memory",
     EARL_GREY : "food"
};

foreach key, value in FAR_FUTURE_OPTION {
    print( key + " (" + key.to_int() + ") -> " + value );
}
yields:

Code:
Riker's Search History (9118) -> riker
Shot of Kardashian Gin (9119) -> booze
Unstable Pointy Ears (9120) -> ears
Memory Disk, Alpha (9121) -> memory
Tea, Earl Grey, Hot (9122) -> food
 
Certainly a different approach than I would have taken, but hey, works just as well (and probably a bit more efficient, too).
 
We probably no longer need the MapValue.execute override, correct?
Let me think about that. When we call initialValue() on an AggregateType(), we get back either a MapValue or an ArrayValue (each of which is an AggregateValue).

AggregateLiteral also is-a AggregateValue.

So, when do we call the execute() method of an AggregateValue? I'm not sure.

For an AggregateLiteral, it creates and fills in the MapValue or ArrayValue and subsequent calls to execute() will get the same thing.

For a MapValue, it calls execute to evaluate and bind the values of every key.
Ditto for an ArrayValue.

I am not sure why. I'm going to have to figure out/relearn when we call execute on these objects...
 
When we assign the AggregateLiteral to a Map, it calls the execute method and generates the MapValue.
I have been unable to find where/how the execute method of a MapValue or ArrayValue is called.
Looking at Assignment, you'd think that might do it, but no; if you have a map in one variable and copy it to another, the rhs is a VariableReference.
 
Except my experimentation has not yet found a case where we actually call execute on an AggregateValue, except for the new AggregateLiteral. So, yes - "we call it" because of what you said - but how can I trigger it?
 
IIRC, it's called when we try to access the value. I thought those changes were originally needed to handle nested literals?
 
Huh. You are right. Revision 17654.

I'll see if I can figure out what the issue was and determine if it is still necessary.
 
Ah. test-map2.ash. I still have that. And it still works after removing the execute functions from MapValue and ArrayValue.
 
Back
Top