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:
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);