nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 56b11fdd81db3c3b23cfc0e3074f98d74d6d5362
parent 9a7474c83432eee7c05a8436c44d2d1f2b1efd93
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Fri,  4 Feb 2022 18:47:46 -0600

add initial array member access syntax

We don't do typechecking yet, and only support single-dimensional
arrays with indexing by literals.

Diffstat:
Mir.c | 17+++++++++++++++++
Mnooc.h | 7+++++++
Mparse.c | 15+++++++++++++++
Atest/array_access.pass.nooc | 31+++++++++++++++++++++++++++++++
Mtype.c | 1+
5 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/ir.c b/ir.c @@ -325,6 +325,23 @@ genexpr(struct iproc *const out, const size_t expri, uint64_t *const val) stackpop(&loops); return VT_EMPTY; } + case EXPR_ACCESS: { + struct expr *expr2 = &exprs.data[expr->d.access.array]; + assert(expr2->kind == EXPR_IDENT); + struct decl *decl = finddecl(blocks, expr2->d.s); + struct type *type = &types.data[decl->type]; + assert(type->class == TYPE_ARRAY); + struct type *subtype = &types.data[type->d.arr.subtype]; + assert(subtype->size <= 8); + if (decl->toplevel) { + uint64_t addr = immediate(out, 8, decl->w.addr + expr->d.access.index * subtype->size); + *val = load(out, subtype->size, addr); + } else { + die("genexpr: EXPR_ACCESS: non-toplevel array access unhandled"); + } + return VT_TEMP; + break; + } default: die("genexpr: expr kind"); } diff --git a/nooc.h b/nooc.h @@ -186,6 +186,11 @@ struct proc { struct block block; }; +struct access { + uint64_t index; + size_t array; // struct exprs +}; + struct binop { enum { BOP_PLUS, @@ -222,6 +227,7 @@ enum exprkind { EXPR_COND, EXPR_LOOP, EXPR_PROC, + EXPR_ACCESS, }; enum class { @@ -244,6 +250,7 @@ struct expr { struct cond cond; struct loop loop; struct proc proc; + struct access access; } d; const struct token *start; }; diff --git a/parse.c b/parse.c @@ -185,6 +185,21 @@ binary_common: tok = tok->next; expr.d.uop.expr = parseexpr(block); break; + case TOK_LSQUARE: + expr.kind = EXPR_ACCESS; + tok = tok->next; + expect(TOK_NUM); + struct expr index = { 0 }; + parsenum(&index); + if (index.d.v.v.i64 < 0) + error(tok->line, tok->col, "expected non-negative integer for array index"); + expr.d.access.index = index.d.v.v.i64; + + expect(TOK_RSQUARE); + tok = tok->next; + expr.d.access.array = parseexpr(block); + expr.class = C_INT; //FIXME: determine from parent type + break; case TOK_NAME: // a procedure definition if (slice_cmplit(&tok->slice, "proc") == 0) { diff --git a/test/array_access.pass.nooc b/test/array_access.pass.nooc @@ -0,0 +1,31 @@ +let hello [5]i8 = "hello" + +let main proc() = proc() { + let char i8 = [0]hello + + if != char 104 { + syscall2(60, 1) + } + + char = [1]hello + if != char 101 { + syscall2(60, 2) + } + + char = [2]hello + if != char 108 { + syscall2(60, 3) + } + + char = [3]hello + if != char 108 { + syscall2(60, 4) + } + + char = [4]hello + if != char 111 { + syscall2(60, 5) + } + + syscall2(60, 0) +} diff --git a/type.c b/type.c @@ -253,6 +253,7 @@ typecheckexpr(const size_t expri) case EXPR_PROC: case EXPR_LOOP: case EXPR_IDENT: + case EXPR_ACCESS: break; case EXPR_FCALL: typecheckcall(expr);