aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-05-29 23:17:06 +0100
committergingerBill <bill@gingerbill.org>2023-05-29 23:17:06 +0100
commit97490c6445cb3ba85f470e64e6ed6d24394c421a (patch)
tree0830f019734c96afd14faf81a7f05ee88021c66f /src
parent1247d36a12b9a0043fda0f73f164bd7fa5dc3897 (diff)
Basic support for `#reverse for in` on normal arrays
Diffstat (limited to 'src')
-rw-r--r--src/check_stmt.cpp21
-rw-r--r--src/llvm_backend_stmt.cpp64
-rw-r--r--src/parser.cpp11
-rw-r--r--src/parser.hpp1
4 files changed, 79 insertions, 18 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 6c69ad59f..c64de40c7 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1461,6 +1461,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
bool is_map = false;
bool use_by_reference_for_value = false;
bool is_soa = false;
+ bool is_reverse = rs->reverse;
Ast *expr = unparen_expr(rs->expr);
@@ -1476,6 +1477,10 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
}
array_add(&vals, x.type);
array_add(&vals, t_int);
+
+ if (is_reverse) {
+ error(node, "#reverse for is not yet supported with ranges");
+ }
} else {
Operand operand = {Addressing_Invalid};
check_expr_base(ctx, &operand, expr, nullptr);
@@ -1488,6 +1493,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
gb_string_free(t);
goto skip_expr_range_stmt;
} else {
+ if (is_reverse) {
+ error(node, "#reverse for is not supported for enum types");
+ }
array_add(&vals, operand.type);
array_add(&vals, t_int);
add_type_info_type(ctx, operand.type);
@@ -1503,6 +1511,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
array_add(&vals, t_int);
add_package_dependency(ctx, "runtime", "string_decode_rune");
}
+ if (is_reverse) {
+ error(node, "#reverse for is not supported for string types");
+ }
break;
case Type_EnumeratedArray:
@@ -1534,6 +1545,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
is_map = true;
array_add(&vals, t->Map.key);
array_add(&vals, t->Map.value);
+ if (is_reverse) {
+ error(node, "#reverse for is not supported for map types");
+ }
break;
case Type_Tuple:
@@ -1570,6 +1584,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
break;
}
+ if (is_reverse) {
+ error(node, "#reverse for is not supported for multiple return valued parameters");
+ }
}
break;
@@ -1579,6 +1596,10 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
if (is_ptr) use_by_reference_for_value = true;
array_add(&vals, t->Struct.soa_elem);
array_add(&vals, t_int);
+
+ if (is_reverse) {
+ error(node, "#reverse for is not yet supported for #soa types");
+ }
}
break;
}
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 125913ac5..60468c7f0 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -249,7 +249,8 @@ gb_internal void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) {
gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr,
- lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) {
+ lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_,
+ bool is_reverse) {
lbModule *m = p->module;
lbValue count = {};
@@ -267,23 +268,50 @@ gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_
lbBlock *body = nullptr;
- lbAddr index = lb_add_local_generated(p, t_int, false);
- lb_addr_store(p, index, lb_const_int(m, t_int, cast(u64)-1));
+ lbAddr index = {};
+ lbValue incr = {};
+ lbValue cond = {};
- loop = lb_create_block(p, "for.index.loop");
- lb_emit_jump(p, loop);
- lb_start_block(p, loop);
+ index = lb_add_local_generated(p, t_int, false);
- lbValue incr = lb_emit_arith(p, Token_Add, lb_addr_load(p, index), lb_const_int(m, t_int, 1), t_int);
- lb_addr_store(p, index, incr);
+ if (!is_reverse) {
+ lb_addr_store(p, index, lb_const_int(m, t_int, cast(u64)-1));
- body = lb_create_block(p, "for.index.body");
- done = lb_create_block(p, "for.index.done");
- if (count.value == nullptr) {
- GB_ASSERT(count_ptr.value != nullptr);
- count = lb_emit_load(p, count_ptr);
+ loop = lb_create_block(p, "for.index.loop");
+ lb_emit_jump(p, loop);
+ lb_start_block(p, loop);
+
+ incr = lb_emit_arith(p, Token_Add, lb_addr_load(p, index), lb_const_int(m, t_int, 1), t_int);
+ lb_addr_store(p, index, incr);
+
+ body = lb_create_block(p, "for.index.body");
+ done = lb_create_block(p, "for.index.done");
+ if (count.value == nullptr) {
+ GB_ASSERT(count_ptr.value != nullptr);
+ count = lb_emit_load(p, count_ptr);
+ }
+ cond = lb_emit_comp(p, Token_Lt, incr, count);
+ } else {
+ // NOTE(bill): REVERSED LOGIC
+ if (count.value == nullptr) {
+ GB_ASSERT(count_ptr.value != nullptr);
+ count = lb_emit_load(p, count_ptr);
+ }
+ count = lb_emit_conv(p, count, t_int);
+ lb_addr_store(p, index, count);
+
+ loop = lb_create_block(p, "for.index.loop");
+ lb_emit_jump(p, loop);
+ lb_start_block(p, loop);
+
+ incr = lb_emit_arith(p, Token_Sub, lb_addr_load(p, index), lb_const_int(m, t_int, 1), t_int);
+ lb_addr_store(p, index, incr);
+
+ body = lb_create_block(p, "for.index.body");
+ done = lb_create_block(p, "for.index.done");
+ cond = lb_emit_comp(p, Token_GtEq, incr, lb_const_int(m, t_int, 0));
}
- lbValue cond = lb_emit_comp(p, Token_Lt, incr, count);
+
lb_emit_if(p, cond, body, done);
lb_start_block(p, body);
@@ -820,7 +848,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
}
lbAddr count_ptr = lb_add_local_generated(p, t_int, false);
lb_addr_store(p, count_ptr, lb_const_int(p->module, t_int, et->Array.count));
- lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done);
+ lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse);
break;
}
case Type_EnumeratedArray: {
@@ -830,7 +858,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
}
lbAddr count_ptr = lb_add_local_generated(p, t_int, false);
lb_addr_store(p, count_ptr, lb_const_int(p->module, t_int, et->EnumeratedArray.count));
- lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done);
+ lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done, rs->reverse);
break;
}
case Type_DynamicArray: {
@@ -840,7 +868,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
array = lb_emit_load(p, array);
}
count_ptr = lb_emit_struct_ep(p, array, 1);
- lb_build_range_indexed(p, array, val0_type, count_ptr, &val, &key, &loop, &done);
+ lb_build_range_indexed(p, array, val0_type, count_ptr, &val, &key, &loop, &done, rs->reverse);
break;
}
case Type_Slice: {
@@ -853,7 +881,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
count_ptr = lb_add_local_generated(p, t_int, false).addr;
lb_emit_store(p, count_ptr, lb_slice_len(p, slice));
}
- lb_build_range_indexed(p, slice, val0_type, count_ptr, &val, &key, &loop, &done);
+ lb_build_range_indexed(p, slice, val0_type, count_ptr, &val, &key, &loop, &done, rs->reverse);
break;
}
case Type_Basic: {
diff --git a/src/parser.cpp b/src/parser.cpp
index 1b48dce87..afdb1078d 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -4759,6 +4759,17 @@ gb_internal Ast *parse_stmt(AstFile *f) {
return stmt;
} else if (tag == "unroll") {
return parse_unrolled_for_loop(f, name);
+ } else if (tag == "reverse") {
+ Ast *for_stmt = parse_for_stmt(f);
+ if (for_stmt->kind == Ast_RangeStmt) {
+ if (for_stmt->RangeStmt.reverse) {
+ syntax_error(token, "#reverse already applied to a 'for in' statement");
+ }
+ for_stmt->RangeStmt.reverse = true;
+ } else {
+ syntax_error(token, "#reverse can only be applied to a 'for in' statement");
+ }
+ return for_stmt;
} else if (tag == "include") {
syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?");
s = ast_bad_stmt(f, token, f->curr_token);
diff --git a/src/parser.hpp b/src/parser.hpp
index d4883f287..6ba4ef6d6 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -529,6 +529,7 @@ AST_KIND(_ComplexStmtBegin, "", bool) \
Token in_token; \
Ast *expr; \
Ast *body; \
+ bool reverse; \
}) \
AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \
Scope *scope; \