diff --git a/script/test.py b/script/test.py index e8542947..4c44bfdf 100755 --- a/script/test.py +++ b/script/test.py @@ -230,8 +230,10 @@ class Test: index += 1 - def fail(self, message, *args, **kwargs): - self.failures.append(message.format(*args, **kwargs)) + def fail(self, message, *args): + if args: + message = message.format(*args) + self.failures.append(message) def color_text(text, color): diff --git a/src/vm/wren_compiler.c b/src/vm/wren_compiler.c index c71dd7ec..ead059c8 100644 --- a/src/vm/wren_compiler.c +++ b/src/vm/wren_compiler.c @@ -1809,27 +1809,26 @@ static void list(Compiler* compiler, bool allowAssignment) // Instantiate a new list. callMethod(compiler, 0, "new()", 5); + ignoreNewlines(compiler); + // Compile the list elements. Each one compiles to a ".add()" call. - if (peek(compiler) != TOKEN_RIGHT_BRACKET) + do { - do - { - ignoreNewlines(compiler); + ignoreNewlines(compiler); - // List with trailing comma. - if (peek(compiler) == TOKEN_RIGHT_BRACKET) break; + // Stop if we hit the end of the list. + if (peek(compiler) == TOKEN_RIGHT_BRACKET) break; - // Push a copy of the list since the add() call will consume it. - emit(compiler, CODE_DUP); + // Push a copy of the list since the add() call will consume it. + emit(compiler, CODE_DUP); - // The element. - expression(compiler); - callMethod(compiler, 1, "add(_)", 6); + // The element. + expression(compiler); + callMethod(compiler, 1, "add(_)", 6); - // Discard the result of the add() call. - emit(compiler, CODE_POP); - } while (match(compiler, TOKEN_COMMA)); - } + // Discard the result of the add() call. + emit(compiler, CODE_POP); + } while (match(compiler, TOKEN_COMMA)); // Allow newlines before the closing ']'. ignoreNewlines(compiler); @@ -1850,31 +1849,28 @@ static void map(Compiler* compiler, bool allowAssignment) // Compile the map elements. Each one is compiled to just invoke the // subscript setter on the map. - if (peek(compiler) != TOKEN_RIGHT_BRACE) + do { - do - { - ignoreNewlines(compiler); + ignoreNewlines(compiler); - // Map with trailing comma. - if (peek(compiler) == TOKEN_RIGHT_BRACE) break; + // Stop if we hit the end of the map. + if (peek(compiler) == TOKEN_RIGHT_BRACE) break; - // Push a copy of the map since the subscript call will consume it. - emit(compiler, CODE_DUP); + // Push a copy of the map since the subscript call will consume it. + emit(compiler, CODE_DUP); - // The key. - parsePrecedence(compiler, false, PREC_PRIMARY); - consume(compiler, TOKEN_COLON, "Expect ':' after map key."); + // The key. + parsePrecedence(compiler, false, PREC_PRIMARY); + consume(compiler, TOKEN_COLON, "Expect ':' after map key."); + ignoreNewlines(compiler); - // The value. - expression(compiler); + // The value. + expression(compiler); + callMethod(compiler, 2, "[_]=(_)", 7); - callMethod(compiler, 2, "[_]=(_)", 7); - - // Discard the result of the setter call. - emit(compiler, CODE_POP); - } while (match(compiler, TOKEN_COMMA)); - } + // Discard the result of the setter call. + emit(compiler, CODE_POP); + } while (match(compiler, TOKEN_COMMA)); // Allow newlines before the closing '}'. ignoreNewlines(compiler); diff --git a/test/language/list/duplicate_comma.wren b/test/language/list/duplicate_comma.wren new file mode 100644 index 00000000..fd213a64 --- /dev/null +++ b/test/language/list/duplicate_comma.wren @@ -0,0 +1 @@ +[1,,2] // expect error diff --git a/test/language/list/duplicate_trailing_comma.wren b/test/language/list/duplicate_trailing_comma.wren new file mode 100644 index 00000000..a221ad7f --- /dev/null +++ b/test/language/list/duplicate_trailing_comma.wren @@ -0,0 +1 @@ +[1,,] // expect error diff --git a/test/language/list/empty_list_with_comma.wren b/test/language/list/empty_list_with_comma.wren new file mode 100644 index 00000000..e5bdec5d --- /dev/null +++ b/test/language/list/empty_list_with_comma.wren @@ -0,0 +1 @@ +[,] // expect error diff --git a/test/language/list/newlines.wren b/test/language/list/newlines.wren index 9e2b60a5..61296116 100644 --- a/test/language/list/newlines.wren +++ b/test/language/list/newlines.wren @@ -8,3 +8,17 @@ var list = [ IO.print(list[0]) // expect: a IO.print(list[1]) // expect: b + +// Newline after trailing comma. +list = ["c", + +] + +IO.print(list[0]) // expect: c + +// Newline in empty list. +list = [ + +] + +IO.print(list.count) // expect: 0 diff --git a/test/language/list/trailing_comma.wren b/test/language/list/trailing_comma.wren index 67fcdba7..e6f64348 100644 --- a/test/language/list/trailing_comma.wren +++ b/test/language/list/trailing_comma.wren @@ -1,12 +1,4 @@ -var list = [ - "a", - "b", -] +var list = ["a", "b",] IO.print(list[0]) // expect: a IO.print(list[1]) // expect: b - -// Invalid syntax -IO.print(new Fiber { Meta.eval("[,]") }.try()) // expect: Could not compile source code. -IO.print(new Fiber { Meta.eval("[1,,]") }.try()) // expect: Could not compile source code. -IO.print(new Fiber { Meta.eval("[1,,2]") }.try()) // expect: Could not compile source code. diff --git a/test/language/map/duplicate_comma.wren b/test/language/map/duplicate_comma.wren new file mode 100644 index 00000000..e891c43f --- /dev/null +++ b/test/language/map/duplicate_comma.wren @@ -0,0 +1 @@ +{1:1,,2:2} // expect error diff --git a/test/language/map/duplicate_trailing_comma.wren b/test/language/map/duplicate_trailing_comma.wren new file mode 100644 index 00000000..783745d3 --- /dev/null +++ b/test/language/map/duplicate_trailing_comma.wren @@ -0,0 +1 @@ +{1:1,,} // expect error diff --git a/test/language/map/empty_map_with_comma.wren b/test/language/map/empty_map_with_comma.wren new file mode 100644 index 00000000..1791adc7 --- /dev/null +++ b/test/language/map/empty_map_with_comma.wren @@ -0,0 +1 @@ +{,} // expect error diff --git a/test/language/map/newlines.wren b/test/language/map/newlines.wren new file mode 100644 index 00000000..c61e81b0 --- /dev/null +++ b/test/language/map/newlines.wren @@ -0,0 +1,27 @@ +// Allow after '{', ':', and ',', and before ']'. +var map = { + +"a": + +"a value", + +"b": "b value" + +} + +IO.print(map["a"]) // expect: a value +IO.print(map["b"]) // expect: b value + +// Newline after trailing comma. +map = {"c": "c value", + +} + +IO.print(map["c"]) // expect: c value + +// Newline in empty map. +map = { + +} + +IO.print(map.count) // expect: 0 diff --git a/test/language/map/trailing_comma.wren b/test/language/map/trailing_comma.wren index 6026d2c1..7dd0a69f 100644 --- a/test/language/map/trailing_comma.wren +++ b/test/language/map/trailing_comma.wren @@ -5,9 +5,3 @@ var map = { IO.print(map["a"]) // expect: 1 IO.print(map["b"]) // expect: 2 - -// Invalid syntax -// Parentheses are necessary to have these interpret as maps and not as blocks. -IO.print(new Fiber { Meta.eval("({,})") }.try()) // expect: Could not compile source code. -IO.print(new Fiber { Meta.eval("({1:1,,})") }.try()) // expect: Could not compile source code. -IO.print(new Fiber { Meta.eval("({1:1,,2:2})") }.try()) // expect: Could not compile source code.