Skip to content

[WIP] Support ListExpression '@[]' in PowerShell - #5762

Closed
Dongbo Wang (daxian-dbw) wants to merge 3 commits into
PowerShell:masterfrom
daxian-dbw:list
Closed

Dongbo Wang (daxian-dbw) wants to merge 3 commits into
PowerShell:masterfrom
daxian-dbw:list

Conversation

@daxian-dbw

@daxian-dbw Dongbo Wang (daxian-dbw) commented Dec 29, 2017 •

Copy link
Copy Markdown
Member

PR Summary

Another attempt to address #5643

This design is to add the ListExpression '@[]' to PowerShell, which is similar to ArrayExpression '@()' but always returns a List<object>.

Please review with #5761 as a comparison, where list is supported as a ListLiteralExpression, similar to ArrayLiteralExpression.

A blocking issue

@[] has a SubExpression like '@()' and '$()'. However, unlike the closing parenthesis character ')', the closing bracket character ']' doesn't always force to start a new token, and it can be included in a generic token, meaning that ']' can appear in a command name, argument, or function name. This makes it impossible for @[dir] to determine the ending of the list expression because dir] will be treated as a single generic token.

This PR adds the property InListSubExpression to Tokenizer, and makes ']' a force-to-start-new-token character when _tokenizer.InListSubExpression is set. This approach solves the most common UX problem but is by no way perfect, for example, comparing to @(funcHas[]inName) or @(dir has[]inpath), @[funcHas[]inName] and @[dir has[]inpath] won't work because the first ']' will force the command name to end.

I couldn't find a less hacky solution without breaking changes (make '[' and ']' always not included by GenericToken). So I started to think what if we support list in PowerShell like the ArrayLiteralExpression instead of @(). In that case, a list can only contain Expression elements and hence command name, arguments, and function names won't be a problem for the ending bracket. #5761 was also submitted to support list as a ListLiteralExpression.

Example

# an empty list
> $l = @[]
> $l.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     List`1                                   System.Object
# one element list, the element is a type
> $l = @[[string]]
> $l.Count
1
> $l[0]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
# multi-element list
> $l = @[$pid,2,$home,4]
> $l.Count
4
> $l.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     List`1                                   System.Object
# arbitrary statements in @[], like @()
> $l = @[dir]
> $l.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     List`1                                   System.Object

> $l.Count
30

PR Checklist

Note: Please mark anything not applicable to this PR NA.

@lzybkr

Copy link
Copy Markdown
Contributor

You could consider 2 character tokens.

For example, F# uses this syntax for an array literal:

[| 1; 2 |]

There are other possibilities that probably aren't breaking changes, e.g. [< 1, 2 >].

The key here is to use a second character that can't be in a command name.

@daxian-dbw

Copy link
Copy Markdown
Member Author

Jason Shirk (@lzybkr) that's a good idea! I didn't think in that way. It would be great if we can have @[] because it resembles the existing @() and $(), but I'm fine to have new token pairs for List support.
I will start prototype with [<>], and wait for more discussion at the same time.

@daxian-dbw

Copy link
Copy Markdown
Member Author

The proposal now is to use a type accelerator [list] for List<object>, so that users can easily create a list using $list = [list]@(...). This way, we can avoid the issue we have here, but still provide an easy way to create a list. Given that, I will close this PR. Please see #5643 for more discussions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants