Skip to content

Commit e10392c

Browse files
gh-181: Replace - with : in slices indexes.
1 parent 5f3773f commit e10392c

8 files changed

Lines changed: 30 additions & 40 deletions

File tree

docs/SPECIFICATION.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
Keywords and built-in names MUST be matched case-sensitively and MUST be written in their canonical uppercase forms. If a reserved word is written in any other case, it MUST be tokenized as an identifier instead.
5656

57-
The character `-` MUST be interpreted only as the leading sign of a numeric literal or as the dash used by slice syntax `lo-hi`. Any unsupported use of `-` MUST raise a syntax error.
57+
The character `-` MUST be interpreted only as the leading sign of a numeric literal. Any unsupported use of `-` MUST raise a syntax error.
5858

5959
The character `~` MUST be reserved for coerced function parameters and MUST NOT appear inside identifiers.
6060

@@ -104,7 +104,7 @@
104104

105105
Indexed assignment to a map MUST use the same form as ordinary map access, such as `map<k1, k2> = expression`. Intermediate nested maps MUST be created on demand when assigning to deeper keys. Reassigning an existing key to a value of a different static type MUST raise a runtime error.
106106

107-
If a tensor target uses slice indices such as `lo-hi` or `*`, the right-hand side MUST evaluate to a `TNS` whose shape exactly matches the selected slice, and every written element MUST satisfy the target's static type constraints.
107+
If a tensor target uses slice indices such as `lo:hi` or `*`, the right-hand side MUST evaluate to a `TNS` whose shape exactly matches the selected slice, and every written element MUST satisfy the target's static type constraints.
108108

109109
---
110110

@@ -328,7 +328,7 @@
328328
329329
`TNS` indexing MUST use square brackets (`[` and `]`) with a comma-separated list of indices. Indexing MUST be one-based. Negative indices MUST count backwards from the end of the dimension.
330330
331-
Slice indexing MUST be supported in any index position using a range of the form `lo-hi`. The selected slice MUST be inclusive of both endpoints. The symbol `*` MAY be used in an index position to denote a full-dimension slice, selecting every element along that axis.
331+
Slice indexing MUST be supported in any index position using a range of the form `lo:hi`. The selected slice MUST be inclusive of both endpoints. The symbol `*` MAY be used in an index position to denote a full-dimension slice, selecting every element along that axis.
332332
333333
---
334334

lib/std/image/init.pre

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ FUNC TNS CROP(TNS img, TNS corners){
120120
IF(NEQ(SHAPE(corners), [0d4, 0d2])){
121121
THROW("CROP corners must be a 0d4 by 0d2 tensor: [[tl_x, tl_y], [tr_x, tr_y], [bl_x, bl_y], [br_x, br_y]]")
122122
}
123-
RETURN(img[MIN(corners[*, 0d1])-MAX(corners[*, 0d1]), MIN(corners[*, 0d2])-MAX(corners[*, 0d2]), *])
123+
RETURN(img[MIN(corners[*, 0d1]):MAX(corners[*, 0d1]), MIN(corners[*, 0d2]):MAX(corners[*, 0d2]), *])
124124
}
125125

126126
FUNC BOOL SHOW(TNS img){

src/parser.c

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -718,16 +718,9 @@ static Expr* parse_call(Parser* parser) {
718718
// parse an expression for index or possibly a range
719719
Expr* start = parse_expression(parser);
720720
if (!start) return NULL;
721-
// Accept either an explicit DASH token or a negative-number token as the range separator
722-
bool is_range = false;
723-
if (parser->current_token.type == TOKEN_DASH) {
724-
is_range = true;
725-
} else if (parser->current_token.type == TOKEN_NUMBER && parser->current_token.literal && parser->current_token.literal[0] == '-') {
726-
is_range = true;
727-
}
728-
if (is_range) {
729-
// If it's a DASH token, consume it; otherwise leave the negative-number token for parse_expression
730-
if (parser->current_token.type == TOKEN_DASH) advance(parser);
721+
// Range separator is ':' inside index expressions
722+
if (parser->current_token.type == TOKEN_COLON) {
723+
advance(parser); // consume ':'
731724
Expr* end = parse_expression(parser);
732725
if (!end) return NULL;
733726
Expr* range = expr_range(start, end, start->line, start->column);
@@ -950,7 +943,7 @@ static Stmt* parse_statement(Parser* parser) {
950943
}
951944
char* name = parser->current_token.literal;
952945
advance(parser);
953-
// Support typed declaration with indexed-assignment target, e.g. `TNS: t[1-10] = ...`
946+
// Support typed declaration with indexed-assignment target, e.g. `TNS: t[1:10] = ...`
954947
if (parser->current_token.type == TOKEN_LBRACKET || parser->current_token.type == TOKEN_LANGLE) {
955948
// construct base identifier expr and parse trailing indexers
956949
Expr* base = expr_ident(name, type_tok.line, type_tok.column);
@@ -969,20 +962,17 @@ static Stmt* parse_statement(Parser* parser) {
969962
Expr* wc = expr_wildcard(parser->previous_token.line, parser->previous_token.column);
970963
expr_list_add(&idx->as.index.indices, wc);
971964
} else {
972-
Expr* start = parse_expression(parser);
973-
if (!start) return NULL;
974-
bool is_range = false;
975-
if (parser->current_token.type == TOKEN_DASH) is_range = true;
976-
else if (parser->current_token.type == TOKEN_NUMBER && parser->current_token.literal && parser->current_token.literal[0] == '-') is_range = true;
977-
if (is_range) {
978-
if (parser->current_token.type == TOKEN_DASH) advance(parser);
979-
Expr* end = parse_expression(parser);
980-
if (!end) return NULL;
981-
Expr* range = expr_range(start, end, start->line, start->column);
982-
expr_list_add(&idx->as.index.indices, range);
983-
} else {
984-
expr_list_add(&idx->as.index.indices, start);
985-
}
965+
Expr* start = parse_expression(parser);
966+
if (!start) return NULL;
967+
if (parser->current_token.type == TOKEN_COLON) {
968+
advance(parser); // consume ':'
969+
Expr* end = parse_expression(parser);
970+
if (!end) return NULL;
971+
Expr* range = expr_range(start, end, start->line, start->column);
972+
expr_list_add(&idx->as.index.indices, range);
973+
} else {
974+
expr_list_add(&idx->as.index.indices, start);
975+
}
986976
}
987977

988978
if (parser->current_token.type == TOKEN_COMMA) { advance(parser); continue; }

src/token.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ typedef enum {
3131
TOKEN_TILDE, // ~
3232
TOKEN_STAR, // *
3333
TOKEN_DOT, // .
34-
TOKEN_DASH, // - (when used as slice range separator)
34+
TOKEN_DASH, // - (reserved; negative numeric literals are part of NUMBER/FLOAT; standalone '-' is a syntax error)
3535

3636
// Keywords
3737
TOKEN_TRY,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
TNS vec = [0d1, 0d2]
2-
ASSIGN(vec[0d1-0d2], [0d1.5, 0d2.5])
2+
ASSIGN(vec[0d1:0d2], [0d1.5, 0d2.5])
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
TNS vec = [0d1, 0d2]
2-
ASSIGN(vec[0d1-0d2], 0d9)
2+
ASSIGN(vec[0d1:0d2], 0d9)

tests/cases/passing/tns-indexing.pre

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ ASSERT(EQ(cube[0d2, 0d2, 0d1], 0d7))
1515
ASSERT(EQ(cube[0d1], [[0d1, 0d2], [0d3, 0d4]]))
1616
ASSERT(EQ(cube[0d1, *], [[0d1, 0d2], [0d3, 0d4]]))
1717

18-
ASSERT(EQ(vec[0d1-0d2], [0d1, 0d2]))
19-
ASSERT(EQ(vec[0d2-0d2], 0d2))
20-
ASSERT(EQ(vec[0d1--0d1], [0d1, 0d2, 0d3]))
21-
ASSERT(EQ(vec[0d0-0d4], [0d1, 0d2, 0d3]))
18+
ASSERT(EQ(vec[0d1:0d2], [0d1, 0d2]))
19+
ASSERT(EQ(vec[0d2:0d2], 0d2))
20+
ASSERT(EQ(vec[0d1:-0d1], [0d1, 0d2, 0d3]))
21+
ASSERT(EQ(vec[0d0:0d4], [0d1, 0d2, 0d3]))
2222

2323
ASSERT(EQ(matrix[*, *], matrix))
2424
ASSERT(EQ(matrix[*, 0d1], [0d1, 0d3]))
2525
ASSERT(EQ(matrix[0d1, *], [0d1, 0d2]))
26-
ASSERT(EQ(matrix[0d1-0d2, 0d1-0d2], matrix))
27-
ASSERT(EQ(matrix[0d1--0d1, 0d1], [0d1, 0d3]))
26+
ASSERT(EQ(matrix[0d1:0d2, 0d1:0d2], matrix))
27+
ASSERT(EQ(matrix[0d1:-0d1, 0d1], [0d1, 0d3]))
2828
ASSERT(EQ(cube[*, 0d2, 0d1], [0d3, 0d7]))
2929

3030
INT errors_caught = 0d0
@@ -44,7 +44,7 @@ TRY {
4444
}
4545

4646
TRY {
47-
vec[TRUE-0d1]
47+
vec[TRUE:0d1]
4848
} CATCH(err) {
4949
ASSERT(EQ(err, 'Range bounds must be INT'))
5050
ADD(@errors_caught, 0d1)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
TNS vec = [0d1, 0d2, 0d3]
22

3-
ASSERT(EQ(ASSIGN(vec[0d1-0d2], [0d9, 0d10]), [0d9, 0d10]))
3+
ASSERT(EQ(ASSIGN(vec[0d1:0d2], [0d9, 0d10]), [0d9, 0d10]))
44
ASSERT(EQ(vec, [0d9, 0d10, 0d3]))

0 commit comments

Comments
 (0)