harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2474bf28a6b828c08062b5e2ad211c2d9748ba45
parent 6c40c6cb64fb78f7f9c1a19bc1ecb441d3500fb6
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 13 Jan 2021 13:42:22 -0500

gen: finish implementation of slicing expressions

Diffstat:
Msrc/gen.c | 32+++++++++++++++++++++++++++-----
Msrc/parse.c | 2++
Mtests/08-slices.ha | 7++++++-
3 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -1089,6 +1089,10 @@ gen_expr_slice(struct gen_context *ctx, gen_temp(ctx, &start, &qbe_long, "start.%d"); gen_temp(ctx, &end, &qbe_long, "end.%d"); + struct qbe_value src = {0}, dest = {0}, temp = {0}, offset = {0}; + gen_temp(ctx, &dest, &qbe_long, "dest.%d"); + gen_temp(ctx, &offset, &qbe_long, "offset.%d"); + if (expr->slice.start) { gen_expression(ctx, expr->slice.start, &start); } else { @@ -1100,16 +1104,34 @@ gen_expr_slice(struct gen_context *ctx, } else if (otype->storage == TYPE_STORAGE_ARRAY) { constl(&end, otype->array.length); } else { - assert(0); // TODO: Read slice length into &end + pushc(ctx->current, "load length"); + constl(&temp, 8); // XXX: ARCH + pushi(ctx->current, &offset, Q_ADD, &object, &temp, NULL); + pushi(ctx->current, &end, Q_LOADL, &offset, NULL); } // TODO: Bounds check - struct qbe_value src = {0}, dest = {0}, temp = {0}, offset = {0}; - gen_temp(ctx, &dest, &qbe_long, "dest.%d"); - gen_temp(ctx, &offset, &qbe_long, "offset.%d"); pushi(ctx->current, &dest, Q_COPY, out, NULL); if (otype->storage == TYPE_STORAGE_SLICE) { - assert(0); // TODO + pushc(ctx->current, "load array"); + + gen_temp(ctx, &src, &qbe_long, "src.%d"); + pushi(ctx->current, &src, Q_LOADL, &object, NULL); + + pushc(ctx->current, "add offset"); + constl(&temp, otype->array.members->size); + pushi(ctx->current, &offset, Q_MUL, &start, &temp, NULL); + pushi(ctx->current, &offset, Q_ADD, &src, &offset, NULL); + pushi(ctx->current, NULL, Q_STOREL, &offset, &dest, NULL); + + pushc(ctx->current, "store length & capacity"); + constl(&temp, 8); // XXX: ARCH + pushi(ctx->current, &offset, Q_SUB, &end, &start, NULL); + constl(&temp, 8); // XXX: ARCH + pushi(ctx->current, &dest, Q_ADD, &dest, &temp, NULL); + pushi(ctx->current, NULL, Q_STOREL, &offset, &dest, NULL); + pushi(ctx->current, &dest, Q_ADD, &dest, &temp, NULL); + pushi(ctx->current, NULL, Q_STOREL, &offset, &dest, NULL); } else { gen_temp(ctx, &src, &qbe_long, "length.%d"); diff --git a/src/parse.c b/src/parse.c @@ -1118,6 +1118,8 @@ parse_index_slice_expression(struct lexer *lexer, struct ast_expression *lvalue) exp->access.index = start; trleave(TR_PARSE, "slice-index (index)"); return exp; + } else if (tok.token == T_RBRACKET) { + unlex(lexer, &tok); } switch (lex(lexer, &tok)) { diff --git a/tests/08-slices.ha b/tests/08-slices.ha @@ -73,11 +73,16 @@ fn assert_slice_eq(actual: []int, expected: []int) void = { fn slicing() void = { let a = [1, 2, 3, 4, 5]; + assert_slice_eq(a[..], [1, 2, 3, 4, 5]); assert_slice_eq(a[..3], [1, 2, 3]); assert_slice_eq(a[1..3], [2, 3]); assert_slice_eq(a[1..], [2, 3, 4, 5]); - // TODO: Test slicing other slices + let b: []int = [1, 2, 3, 4, 5]; + assert_slice_eq(b[..], [1, 2, 3, 4, 5]); + assert_slice_eq(b[..3], [1, 2, 3]); + assert_slice_eq(b[1..3], [2, 3]); + assert_slice_eq(b[1..], [2, 3, 4, 5]); assert(rt::compile( "fn test() void = { let x = \"test\"; x[1..3]; };"