Map literals in ASH (potential feature)

heeheehee

Developer
Staff member
I assume that user defined types - typedefs and record names - are not precluded from being variable or function names. By analogy with the built-in types, presumably they should be.

I imagine this would create problems, due to ASH's single-pass, top-down parsing style -- for instance, suppose you defined both a record and a function with the same type. Depending on which one is defined first, an error could (but would not always) be thrown. Unless establishing a type with the same name as an existing function/variable also threw an error, the ASH interpreter would need to be changed to take a double-pass approach. At least, I think this is the case, judging from what little I've read of the ASH interpreter.

That change broke way more scripts than I expected...
Ayup.
 

Bale

Minion
Thanks. I have a habit of not promptly reading threads for scripts I do not use. The problem is much more widespread than I had realized.
 

heeheehee

Developer
Staff member
Updated first post with a copy of the map-literals patch, in a perhaps futile attempt to re-rail this thread.
 

fronobulax

Developer
Staff member
Updated first post with a copy of the map-literals patch, in a perhaps futile attempt to re-rail this thread.

So I confess that I see neither the utility nor the support for the proposed patch, but I am willing to look for both if they appear in the thread.
 

heeheehee

Developer
Staff member
Utility is in the ability to do something like calling a function without having to create a variable just for this express purpose, or for initializing a variable with preset values without requiring an external datafile. I see at least as much utility for this feature as, say, typedefs or ArrayLists in the form of plural typed constants (note: I refer to something of the form $ints[1,1,2,3], not $items[]).

As for support, the only reason most of the prominent scripters have posted in this thread is because of the bug that this patch uncovered (does this count as secondary utility?). None of them commented initially, which is why I didn't actually start looking into implementing this until a few weeks after the first post.
 

zarqon

Well-known member
As an example to illustrate heeheehee's first point:

PHP:
import <zlib.ash>
kmail("Zarqon", "Here is 10 meat and some bat crap!", 10, int[item] { $item[bat guano] : 3 } );

(or whatever the syntax will look like)

Oooh, handy. This as opposed to:

PHP:
import <zlib.ash>
int[item] temporaryitemlist;
temporaryitemlist[$item[bat guano]] = 3;
kmail("Zarqon", "Here is 10 meat and some bat crap!", 10, temporaryitemlist);

To my memory at least, this is not the first thread to discuss the possibility of ASH constructors for maps.
 

fronobulax

Developer
Staff member
I applied the patch from the first post. zarqon's example just netted him 10 meat and some bat crap, but my DCQuest which calls datelib had "Internal error (datelib.ash, line 28)" which suggests something changed for the worse. Not ready for prime time since my time to diagnose is momentarily limited.
 

heeheehee

Developer
Staff member
Not sure, haven't tried out datelib with this patch. I'll look into it (since that is evidently my script :p).

edit: ooh, that was quick. As I discovered earlier in the thread (which led to the massive derailing), any variables with the name of an existing type will cause the interpreter to throw an error (because of the change to control flow -- said patch causes Mafia to try to parse map literals before variable references, and I wasn't sure how to put tokens back onto the stack).

Said patch still needs cleanup, naturally (for instance, standalone expressions like "ash int[int] {1: 2};" will throw a different error).

double edit: fixed both issues; new patch attached here. Will also add to first post.
 

Attachments

  • mapliterals.patch
    4.2 KB · Views: 41
Last edited:

heeheehee

Developer
Staff member
Bumpity bump bump. Funny story, actually. Someone pinged me about map literals in ASH a few weeks ago, citing this thread (which I'd totally forgotten about). I checked out this patch, and other than trailing whitespace, it applied and compiled without any complaints. Good job, self from 2012!

I never did fix the issue with array literals, but I'm still not sure that anyone might care about it (as I mentioned, plural typed constants are superior if you can use them). I'm thinking I'll commit this once I take a look at what I did and see if there's anything I can improve, unless there are any reservations.
 

heeheehee

Developer
Staff member
r16866 commits this; docs can be found in the commit notes. One outstanding issue I noticed:

Code:
int [int]
{
    4 : 3,
    5 : 6
};
throws a script parsing error, while
Code:
(int [int]
{
    4 : 3,
    5 : 6
});
does not. I personally think this is a non-issue, since there's no reason to use a map literal without using its value anywhere.
 

Veracity

Developer
Staff member
We can do this:

Code:
item [int,int] imap = item[int, int] {4: item[int] {4: $item[eyepatch]} };

record rec1 { int a; string b; };

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

Code:
item [int,int] imap = {4: item[int] {4: $item[eyepatch]} };

record rec1 { int a; string b; };

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

heeheehee

Developer
Staff member
Looks like it -- well, once you add the type information to the literals, as follows:
Code:
item [int,int] imap = item[int,int]{4: item[int] {4: $item[eyepatch]} };

record rec1 { int a; string b; };

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

edit: I see, you're referring to omitting type specification entirely.
 

heeheehee

Developer
Staff member
It certainly would be simpler to infer type from the lhs of the assignment. But this would primarily be useful in initializing variables. In the case of passing in literals as arguments to functions (which I always saw as the main use case of this feature), the current syntax might be the best we can do -- otherwise, overload resolution seems... potentially difficult. Not impossible, but probably more effort than it's worth.
 

Veracity

Developer
Staff member
Well, yes. I am interested (at the moment) in initializing maps from literals. So, the type definition is redundant.
For parsing arguments, the type definition is necessary, to disamiguate overloaded functions, at least.

They don't have to have the same syntax requirements.
 

heeheehee

Developer
Staff member
Certainly. The current implementation was just simpler (and in practice, a neat side effect), since we got code reuse without any extra effort.

Other than that one point, I don't see any other immediate issues. Given the structure of parseAggregateLiteral, you probably will be able to reuse that code (I imagine you could add an else-if around Parser.java:861, if you wanted to implement the notation without '=', which might even be marginally easier).
 
Last edited:
Top