commit b7c6dd96f53181bfca00d127c148f859a6c169c9
parent c7f7d297f83c885d47d0e0cad1b4579b7933a732
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 21 Dec 2020 14:42:37 -0500
check: access expressions
Diffstat:
5 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -5,6 +5,7 @@
#include "types.h"
struct scope;
+struct scope_object;
enum expr_type {
EXPR_ACCESS,
@@ -32,6 +33,10 @@ enum expr_type {
EXPR_WHILE,
};
+struct expression_access {
+ const struct scope_object *object;
+};
+
// TODO: Stretchy constants
union expression_constant {
bool bval;
@@ -65,6 +70,7 @@ struct expression {
enum expr_type type;
bool terminates;
union {
+ struct expression_access access;
union expression_constant constant;
struct expression_list list;
struct expression_return _return;
diff --git a/include/identifier.h b/include/identifier.h
@@ -1,6 +1,7 @@
#ifndef HARE_IDENTIFIER_H
#define HARE_IDENTIFIER_H
#include <stddef.h>
+#include <stdbool.h>
struct identifier {
char *name;
@@ -8,8 +9,9 @@ struct identifier {
};
char *identifier_unparse(const struct identifier *ident);
-int identifier_unparse_static(const struct identifier *ident,
- char *buf, size_t len);
+int identifier_unparse_static(
+ const struct identifier *ident, char *buf, size_t len);
void identifier_dup(struct identifier *new, const struct identifier *ident);
+bool identifier_eq(const struct identifier *a, const struct identifier *b);
#endif
diff --git a/src/check.c b/src/check.c
@@ -27,6 +27,7 @@ expect(bool constraint, char *fmt, ...)
fprintf(stderr, "Error: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
+ abort();
}
}
@@ -34,6 +35,24 @@ static void check_expression(struct context *ctx,
const struct ast_expression *aexpr, struct expression *expr);
static void
+check_expr_access(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr)
+{
+ trace(TR_CHECK, "access");
+ expr->type = EXPR_ACCESS;
+
+ const struct scope_object *obj = scope_lookup(
+ ctx->scope, &aexpr->access.ident);
+ char buf[1024];
+ identifier_unparse_static(&aexpr->access.ident, buf, sizeof(buf));
+ expect(obj, "Unknown object %s", buf);
+
+ expr->result = obj->type;
+ expr->access.object = obj;
+}
+
+static void
check_expr_constant(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -140,6 +159,8 @@ check_expression(struct context *ctx,
switch (aexpr->type) {
case EXPR_ACCESS:
+ check_expr_access(ctx, aexpr, expr);
+ break;
case EXPR_ASSERT:
case EXPR_ASSIGN:
case EXPR_BINARITHM:
diff --git a/src/identifier.c b/src/identifier.c
@@ -73,3 +73,17 @@ identifier_dup(struct identifier *new, const struct identifier *ident)
identifier_dup(new->ns, ident->ns);
}
}
+
+bool
+identifier_eq(const struct identifier *a, const struct identifier *b)
+{
+ if (!a && !b) {
+ return true;
+ } else if ((!a && b) || (a && !b)) {
+ return false;
+ }
+ if (strcmp(a->name, b->name) != 0) {
+ return false;
+ }
+ return identifier_eq(a->ns, b->ns);
+}
diff --git a/src/scope.c b/src/scope.c
@@ -74,5 +74,15 @@ scope_insert(struct scope *scope,
const struct scope_object *
scope_lookup(struct scope *scope, const struct identifier *ident)
{
- assert(0); // TODO
+ struct scope_object *o = scope->objects;
+ while (o) {
+ if (identifier_eq(&o->ident, ident)) {
+ return o;
+ }
+ o = o->next;
+ }
+ if (scope->parent) {
+ return scope_lookup(scope->parent, ident);
+ }
+ return NULL;
}