Rename $(etc) to [etc]
diff --git a/cmd/wuffs-c/internal/cgen/cgen.go b/cmd/wuffs-c/internal/cgen/cgen.go
index 17ee47c..8248f3f 100644
--- a/cmd/wuffs-c/internal/cgen/cgen.go
+++ b/cmd/wuffs-c/internal/cgen/cgen.go
@@ -595,7 +595,7 @@
 }
 
 func (g *gen) writeConstList(b *buffer, n *a.Expr) error {
-	if n.Operator() == t.IDDollar {
+	if n.Operator() == t.IDComma {
 		b.writeb('{')
 		for _, o := range n.Args() {
 			if err := g.writeConstList(b, o.AsExpr()); err != nil {
diff --git a/doc/changelog.md b/doc/changelog.md
index 8c7e0c8..2157555 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -19,6 +19,7 @@
 - Renamed `std/flate` to `std/deflate`.
 - Renamed `~+` to `~mod+`; added `~mod-`, `~sat+` and `~sat-`.
 - Removed `&^`.
+- Renamed `$(etc)` to `[etc]`.
 - Renamed `[N] T` and `[] T` types to `array[N] T` and `slice T`.
 - Renamed `buf1`, `reader1`, etc to `io_buffer`, `io_reader`, etc.
 - Renamed `u32`, `io_reader`, etc to `base.u32`, `base.io_reader`, etc.
diff --git a/lang/ast/ast.go b/lang/ast/ast.go
index 42a9a02..755f1f2 100644
--- a/lang/ast/ast.go
+++ b/lang/ast/ast.go
@@ -328,7 +328,7 @@
 //
 // For selectors, like "LHS.ID2", ID0 is IDDot.
 //
-// For lists, like "$(0, 1, 2)", ID0 is IDDollar.
+// For lists, like "[0, 1, 2]", ID0 is IDComma.
 //
 // For statuses like "?foo" and bar."$baz", ID0 is IDStatus, ID1 is the package
 // and ID2 is the message.
diff --git a/lang/ast/string.go b/lang/ast/string.go
index 1718dec..cb3c249 100644
--- a/lang/ast/string.go
+++ b/lang/ast/string.go
@@ -126,15 +126,15 @@
 			buf = append(buf, '.')
 			buf = append(buf, tm.ByID(n.id2)...)
 
-		case t.IDDollar:
-			buf = append(buf, "$("...)
+		case t.IDComma:
+			buf = append(buf, '[')
 			for i, o := range n.list0 {
 				if i != 0 {
 					buf = append(buf, ", "...)
 				}
 				buf = o.AsExpr().appendStr(buf, tm, false, depth)
 			}
-			buf = append(buf, ')')
+			buf = append(buf, ']')
 		}
 	}
 
diff --git a/lang/check/bounds.go b/lang/check/bounds.go
index bfd8425..638ee11 100644
--- a/lang/check/bounds.go
+++ b/lang/check/bounds.go
@@ -869,7 +869,7 @@
 	case t.IDStatus:
 		// No-op.
 
-	case t.IDDollar:
+	case t.IDComma:
 		for _, o := range n.Args() {
 			if _, err := q.bcheckExpr(o.AsExpr(), depth); err != nil {
 				return a.Bounds{}, err
diff --git a/lang/check/check.go b/lang/check/check.go
index 47931ea..5198888 100644
--- a/lang/check/check.go
+++ b/lang/check/check.go
@@ -306,7 +306,7 @@
 func (c *Checker) checkConstElement(n *a.Expr, nb a.Bounds, nLists int) error {
 	if nLists > 0 {
 		nLists--
-		if n.Operator() != t.IDDollar {
+		if n.Operator() != t.IDComma {
 			return fmt.Errorf("invalid const value %q", n.Str(c.tm))
 		}
 		for _, o := range n.Args() {
diff --git a/lang/check/resolve.go b/lang/check/resolve.go
index d606d45..9fa89c3 100644
--- a/lang/check/resolve.go
+++ b/lang/check/resolve.go
@@ -36,7 +36,7 @@
 	typeExprGeneric1    = a.NewTypeExpr(0, t.IDBase, t.IDDagger1, nil, nil, nil)
 	typeExprGeneric2    = a.NewTypeExpr(0, t.IDBase, t.IDDagger2, nil, nil, nil)
 	typeExprIdeal       = a.NewTypeExpr(0, t.IDBase, t.IDQIdeal, nil, nil, nil)
-	typeExprList        = a.NewTypeExpr(0, t.IDBase, t.IDDollar, nil, nil, nil)
+	typeExprList        = a.NewTypeExpr(0, t.IDBase, t.IDComma, nil, nil, nil)
 	typeExprNullptr     = a.NewTypeExpr(0, t.IDBase, t.IDQNullptr, nil, nil, nil)
 	typeExprPlaceholder = a.NewTypeExpr(0, t.IDBase, t.IDQPlaceholder, nil, nil, nil)
 	typeExprTypeExpr    = a.NewTypeExpr(0, t.IDBase, t.IDQTypeExpr, nil, nil, nil)
diff --git a/lang/check/type.go b/lang/check/type.go
index 972bbf1..8f8d62b 100644
--- a/lang/check/type.go
+++ b/lang/check/type.go
@@ -499,7 +499,7 @@
 		n.SetMType(typeExprStatus)
 		return nil
 
-	case t.IDDollar:
+	case t.IDComma:
 		for _, o := range n.Args() {
 			o := o.AsExpr()
 			if err := q.tcheckExpr(o, depth); err != nil {
diff --git a/lang/parse/parse.go b/lang/parse/parse.go
index 23bc30c..a3f4fc6 100644
--- a/lang/parse/parse.go
+++ b/lang/parse/parse.go
@@ -138,7 +138,7 @@
 					p.tm.ByID(id), p.filename, p.line())
 			}
 			p.src = p.src[1:]
-			value, err := p.parsePossibleDollarExpr()
+			value, err := p.parsePossibleListExpr()
 			if err != nil {
 				return nil, err
 			}
@@ -301,7 +301,7 @@
 	ret := []*a.Node(nil)
 	for len(p.src) > 0 {
 		if p.src[0].ID == stop {
-			if stop == t.IDCloseParen {
+			if stop == t.IDCloseParen || stop == t.IDCloseBracket {
 				p.src = p.src[1:]
 			}
 			return ret, nil
@@ -315,7 +315,7 @@
 
 		switch x := p.peek1(); x {
 		case stop:
-			if stop == t.IDCloseParen {
+			if stop == t.IDCloseParen || stop == t.IDCloseBracket {
 				p.src = p.src[1:]
 			}
 			return ret, nil
@@ -885,24 +885,25 @@
 	return a.NewVar(op, id, typ, value).AsNode(), nil
 }
 
-func (p *parser) parsePossibleDollarExprNode() (*a.Node, error) {
-	n, err := p.parsePossibleDollarExpr()
+func (p *parser) parsePossibleListExprNode() (*a.Node, error) {
+	n, err := p.parsePossibleListExpr()
 	if err != nil {
 		return nil, err
 	}
 	return n.AsNode(), err
 }
 
-func (p *parser) parsePossibleDollarExpr() (*a.Expr, error) {
-	if x := p.peek1(); x != t.IDDollar {
+func (p *parser) parsePossibleListExpr() (*a.Expr, error) {
+	// TODO: put the [ and ] parsing into parseExpr.
+	if x := p.peek1(); x != t.IDOpenBracket {
 		return p.parseExpr()
 	}
 	p.src = p.src[1:]
-	args, err := p.parseList(t.IDCloseParen, (*parser).parsePossibleDollarExprNode)
+	args, err := p.parseList(t.IDCloseBracket, (*parser).parsePossibleListExprNode)
 	if err != nil {
 		return nil, err
 	}
-	return a.NewExpr(0, t.IDDollar, 0, 0, nil, nil, nil, args), nil
+	return a.NewExpr(0, t.IDComma, 0, 0, nil, nil, nil, args), nil
 }
 
 func (p *parser) parseExprNode() (*a.Node, error) {
diff --git a/lang/render/render.go b/lang/render/render.go
index 244c4a5..0425515 100644
--- a/lang/render/render.go
+++ b/lang/render/render.go
@@ -107,7 +107,7 @@
 		// Render the lineTokens.
 		prevID, prevIsTightRight := t.ID(0), false
 		for _, tok := range lineTokens {
-			if prevID != 0 && !prevIsTightRight && !tok.ID.IsTightLeft() {
+			if prevID == t.IDEq || (prevID != 0 && !prevIsTightRight && !tok.ID.IsTightLeft()) {
 				// The "(" token's tight-left-ness is context dependent. For
 				// "f(x)", the "(" is tight-left. For "a * (b + c)", it is not.
 				if tok.ID != t.IDOpenParen || !isCloseIdentStrLiteral(tm, prevID) {
diff --git a/std/crc32/common_crc32.wuffs b/std/crc32/common_crc32.wuffs
index e7af0ec..cbde228 100644
--- a/std/crc32/common_crc32.wuffs
+++ b/std/crc32/common_crc32.wuffs
@@ -47,7 +47,7 @@
 
 // The table below was created by script/print-crc32-magic-numbers.go.
 
-pri const ieee_table array[8] array[256] base.u32 = $($(
+pri const ieee_table array[8] array[256] base.u32 = [[
 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
 	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
 	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
@@ -80,7 +80,7 @@
 	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
 	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
-), $(
+],[
 	0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7,
 	0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF,
 	0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496,
@@ -113,7 +113,7 @@
 	0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23,
 	0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A,
 	0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72,
-), $(
+],[
 	0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685,
 	0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D,
 	0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5,
@@ -146,7 +146,7 @@
 	0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D,
 	0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555,
 	0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED,
-), $(
+],[
 	0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9,
 	0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056,
 	0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26,
@@ -179,7 +179,7 @@
 	0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E,
 	0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E,
 	0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1,
-), $(
+],[
 	0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10,
 	0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1,
 	0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92,
@@ -212,7 +212,7 @@
 	0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E,
 	0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D,
 	0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C, 0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C,
-), $(
+],[
 	0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8,
 	0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5,
 	0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223,
@@ -245,7 +245,7 @@
 	0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957,
 	0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1,
 	0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA, 0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC,
-), $(
+],[
 	0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E,
 	0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9,
 	0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240,
@@ -278,7 +278,7 @@
 	0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE,
 	0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457,
 	0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23, 0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30,
-), $(
+],[
 	0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919,
 	0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC,
 	0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832,
@@ -311,4 +311,4 @@
 	0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD,
 	0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53,
 	0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C, 0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6,
-))
+]]
diff --git a/std/deflate/common_consts.wuffs b/std/deflate/common_consts.wuffs
index 12223c6..f67d3b7 100644
--- a/std/deflate/common_consts.wuffs
+++ b/std/deflate/common_consts.wuffs
@@ -13,12 +13,12 @@
 // limitations under the License.
 
 // code_order is defined in the RFC section 3.2.7.
-pri const code_order array[19] base.u8[..18] = $(
+pri const code_order array[19] base.u8[..18] = [
 	16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
-)
+]
 
 // reverse8 reverses the bits in a byte.
-pri const reverse8 array[256] base.u8 = $(
+pri const reverse8 array[256] base.u8 = [
 	0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,  // 0x00 - 0x07
 	0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,  // 0x08 - 0x0F
 	0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,  // 0x10 - 0x17
@@ -51,4 +51,4 @@
 	0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,  // 0xE8 - 0xEF
 	0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,  // 0xF0 - 0xF7
 	0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,  // 0xF8 - 0xFF
-)
+]
diff --git a/std/deflate/decode_deflate.wuffs b/std/deflate/decode_deflate.wuffs
index 7194c08..31ed2c5 100644
--- a/std/deflate/decode_deflate.wuffs
+++ b/std/deflate/decode_deflate.wuffs
@@ -40,19 +40,19 @@
 //
 // Some trailing elements are 0x08000000. Bit 27 indicates an invalid value.
 
-pri const lcode_magic_numbers array[32] base.u32 = $(
+pri const lcode_magic_numbers array[32] base.u32 = [
 	0x40000300, 0x40000400, 0x40000500, 0x40000600, 0x40000700, 0x40000800, 0x40000900, 0x40000A00,
 	0x40000B10, 0x40000D10, 0x40000F10, 0x40001110, 0x40001320, 0x40001720, 0x40001B20, 0x40001F20,
 	0x40002330, 0x40002B30, 0x40003330, 0x40003B30, 0x40004340, 0x40005340, 0x40006340, 0x40007340,
 	0x40008350, 0x4000A350, 0x4000C350, 0x4000E350, 0x40010200, 0x08000000, 0x08000000, 0x08000000,
-)
+]
 
-pri const dcode_magic_numbers array[32] base.u32 = $(
+pri const dcode_magic_numbers array[32] base.u32 = [
 	0x40000000, 0x40000100, 0x40000200, 0x40000300, 0x40000410, 0x40000610, 0x40000820, 0x40000C20,
 	0x40001030, 0x40001830, 0x40002040, 0x40003040, 0x40004050, 0x40006050, 0x40008060, 0x4000C060,
 	0x40010070, 0x40018070, 0x40020080, 0x40030080, 0x40040090, 0x40060090, 0x400800A0, 0x400C00A0,
 	0x401000B0, 0x401800B0, 0x402000C0, 0x403000C0, 0x404000D0, 0x406000D0, 0x08000000, 0x08000000,
-)
+]
 
 pub struct decoder?(
 	// These fields yield src's bits in Least Significant Bits order.
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 50544a0..5a4c9d3 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -37,8 +37,8 @@
 // accessed after all interlace stages are complete. Being the maximum base.u32
 // value means that, after all interlace stages are complete, dst_y will be set
 // to that maximum value (and therefore outside the frame rect).
-pri const interlace_start array[5] base.u32 = $(0xFFFFFFFF, 1, 2, 4, 0)
-pri const interlace_delta array[5] base.u8 = $(1, 2, 4, 8, 8)
+pri const interlace_start array[5] base.u32 = [0xFFFFFFFF, 1, 2, 4, 0]
+pri const interlace_delta array[5] base.u8 = [1, 2, 4, 8, 8]
 
 pub struct decoder?(
 	width base.u32,
@@ -352,14 +352,14 @@
 }
 
 // animexts1dot0 is "ANIMEXTS1.0" as bytes.
-pri const animexts1dot0 array[11] base.u8 = $(
+pri const animexts1dot0 array[11] base.u8 = [
 	0x41, 0x4E, 0x49, 0x4D, 0x45, 0x58, 0x54, 0x53, 0x31, 0x2E, 0x30,
-)
+]
 
 // netscape2dot0 is "NETSCAPE2.0" as bytes.
-pri const netscape2dot0 array[11] base.u8 = $(
+pri const netscape2dot0 array[11] base.u8 = [
 	0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30,
-)
+]
 
 // decode_ae reads an Application Extension.
 pri func decoder.decode_ae!??(src base.io_reader) {