aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-04-20 23:22:45 +0100
committerGinger Bill <bill@gingerbill.org>2017-04-20 23:22:45 +0100
commita713e3300786199510e525aa9f90ee8d91aa862a (patch)
treeb7fb9141d89e7a5ab673615cdfc0137630fc3260 /src
parentc5411a25a94650ec6370eea3572d3d60f6240482 (diff)
Change interval syntax: .. open range, ..< half-closed range
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c16
-rw-r--r--src/check_stmt.c3
-rw-r--r--src/ir.c14
-rw-r--r--src/parser.c20
-rw-r--r--src/tokenizer.c4
5 files changed, 48 insertions, 9 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 9038d8667..a631bf272 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -2819,6 +2819,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
return false;
}
+
return true;
}
}
@@ -5732,6 +5733,11 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
o->mode = Addressing_Value;
}
+ if (se->low == NULL && se->high != NULL) {
+ error(se->interval0, "1st index is required if a 2nd index is specified");
+ // It is okay to continue as it will assume the 1st index is zero
+ }
+
if (se->index3 && (se->high == NULL || se->max == NULL)) {
error(se->close, "2nd and 3rd indices are required in a 3-index slice");
o->mode = Addressing_Invalid;
@@ -5739,6 +5745,16 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
return kind;
}
+ if (se->index3 && se->interval0.kind != se->interval1.kind) {
+ error(se->close, "The interval separators for in a 3-index slice must be the same");
+ o->mode = Addressing_Invalid;
+ o->expr = node;
+ return kind;
+ }
+
+
+ TokenKind interval_kind = se->interval0.kind;
+
i64 indices[2] = {0};
AstNode *nodes[3] = {se->low, se->high, se->max};
for (isize i = 0; i < gb_count_of(nodes); i++) {
diff --git a/src/check_stmt.c b/src/check_stmt.c
index ca3bc9ac9..78d646302 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -771,7 +771,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
TokenKind op = Token_Lt;
switch (ie->op.kind) {
- case Token_Ellipsis: op = Token_Lt; break;
+ case Token_Ellipsis: op = Token_LtEq; break;
+ case Token_HalfClosed: op = Token_Lt; break;
default: error(ie->op, "Invalid range operator"); break;
}
bool ok = compare_exact_values(op, a, b);
diff --git a/src/ir.c b/src/ir.c
index 6fb03d7e0..aaddaf84a 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -4905,6 +4905,17 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
if (se->low != NULL) low = ir_build_expr(proc, se->low);
if (se->high != NULL) high = ir_build_expr(proc, se->high);
if (se->max != NULL) max = ir_build_expr(proc, se->max);
+
+
+ if (high != NULL && se->interval0.kind == Token_Ellipsis) {
+ high = ir_emit_arith(proc, Token_Add, high, v_one, t_int);
+ }
+
+ if (max != NULL && se->interval1.kind == Token_Ellipsis) {
+ GB_ASSERT(se->interval0.kind == se->interval1.kind);
+ max = ir_emit_arith(proc, Token_Add, max, v_one, t_int);
+ }
+
irValue *addr = ir_build_addr(proc, se->expr).addr;
irValue *base = ir_emit_load(proc, addr);
Type *type = base_type(ir_type(base));
@@ -5553,7 +5564,8 @@ void ir_build_range_interval(irProcedure *proc, AstNodeIntervalExpr *node, Type
TokenKind op = Token_Lt;
switch (node->op.kind) {
- case Token_Ellipsis: op = Token_Lt; break;
+ case Token_Ellipsis: op = Token_LtEq; break;
+ case Token_HalfClosed: op = Token_Lt; break;
default: GB_PANIC("Invalid interval operator"); break;
}
irValue *cond = ir_emit_comp(proc, op, ir_emit_load(proc, value), upper);
diff --git a/src/parser.c b/src/parser.c
index 31d14db78..d9b20fca6 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -105,6 +105,7 @@ typedef enum FieldFlag {
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_immutable,
} FieldListTag;
+
AstNodeArray make_ast_node_array(AstFile *f) {
AstNodeArray a;
// array_init(&a, gb_arena_allocator(&f->arena));
@@ -155,9 +156,11 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
- AST_NODE_KIND(SliceExpr, "slice expression", struct { \
+ AST_NODE_KIND(SliceExpr, "slice expression", struct { \
AstNode *expr; \
Token open, close; \
+ Token interval0; \
+ Token interval1; \
bool index3; \
AstNode *low, *high, *max; \
}) \
@@ -686,11 +689,13 @@ AstNode *ast_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, T
}
-AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, bool index3, AstNode *low, AstNode *high, AstNode *max) {
+AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval0, Token interval1, bool index3, AstNode *low, AstNode *high, AstNode *max) {
AstNode *result = make_ast_node(f, AstNode_SliceExpr);
result->SliceExpr.expr = expr;
result->SliceExpr.open = open;
result->SliceExpr.close = close;
+ result->SliceExpr.interval0 = interval0;
+ result->SliceExpr.interval1 = interval1;
result->SliceExpr.index3 = index3;
result->SliceExpr.low = low;
result->SliceExpr.high = high;
@@ -1980,15 +1985,19 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
f->expr_level++;
open = expect_token(f, Token_OpenBracket);
- if (f->curr_token.kind != Token_Ellipsis) {
+ if (f->curr_token.kind != Token_Ellipsis &&
+ f->curr_token.kind != Token_HalfClosed) {
indices[0] = parse_expr(f, false);
}
bool is_index = true;
- while (f->curr_token.kind == Token_Ellipsis && ellipsis_count < gb_count_of(ellipses)) {
+ while ((f->curr_token.kind == Token_Ellipsis ||
+ f->curr_token.kind == Token_HalfClosed)
+ && ellipsis_count < gb_count_of(ellipses)) {
ellipses[ellipsis_count++] = f->curr_token;
next_token(f);
if (f->curr_token.kind != Token_Ellipsis &&
+ f->curr_token.kind != Token_HalfClosed &&
f->curr_token.kind != Token_CloseBracket &&
f->curr_token.kind != Token_EOF) {
indices[ellipsis_count] = parse_expr(f, false);
@@ -2013,7 +2022,7 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
indices[2] = ast_bad_expr(f, ellipses[1], close);
}
}
- operand = ast_slice_expr(f, operand, open, close, index3, indices[0], indices[1], indices[2]);
+ operand = ast_slice_expr(f, operand, open, close, ellipses[0], ellipses[1], index3, indices[0], indices[1], indices[2]);
} else {
operand = ast_index_expr(f, operand, indices[0], open, close);
}
@@ -2301,6 +2310,7 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
allow_token(f, Token_in);
AstNode *expr = parse_expr(f, false);
switch (f->curr_token.kind) {
+ case Token_HalfClosed:
case Token_Ellipsis: {
Token op = f->curr_token;
next_token(f);
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 469620450..ba491e73c 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -75,7 +75,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token_Period, "."), \
TOKEN_KIND(Token_Comma, ","), \
TOKEN_KIND(Token_Ellipsis, ".."), \
- TOKEN_KIND(Token_HalfOpenRange, "..<"), \
+ TOKEN_KIND(Token_HalfClosed, "..<"), \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -872,7 +872,7 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_Ellipsis;
if (t->curr_rune == '<') {
advance_to_next_rune(t);
- token.kind = Token_HalfOpenRange;
+ token.kind = Token_HalfClosed;
}
}
break;