commit 4db3a7129372f4a13421fb70c50fa244b3a1813e
parent 04988d5245f29f669d7f4909e00ecd07d8957ebc
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 26 Dec 2020 10:37:21 -0500
Initial riggings for eval
Diffstat:
9 files changed, 79 insertions(+), 6 deletions(-)
diff --git a/configure b/configure
@@ -6,6 +6,7 @@ harec() {
genrules harec \
src/check.c \
src/emit.c \
+ src/eval.c \
src/gen.c \
src/identifier.c \
src/lex.c \
diff --git a/include/check.h b/include/check.h
@@ -4,6 +4,7 @@
#include "identifier.h"
#include "types.h"
+struct context;
struct expression;
struct scope;
@@ -47,8 +48,12 @@ struct unit {
struct declarations *declarations;
};
+struct ast_expression;
struct ast_unit;
void check(const struct ast_unit *aunit, struct unit *unit);
+void check_expression(struct context *ctx,
+ const struct ast_expression *aexpr, struct expression *expr);
+
#endif
diff --git a/include/eval.h b/include/eval.h
@@ -0,0 +1,25 @@
+#ifndef HAREC_EVAL_H
+#define HAREC_EVAL_H
+#include <stdbool.h>
+
+struct expression;
+struct context;
+
+enum eval_result {
+ // Evaluation succeeded.
+ EVAL_OK,
+
+ // Insufficient context, such as references to unknown types or
+ // objects. Defer this expression until later and re-try when more of
+ // the type & object graph are populated.
+ EVAL_NEED_CONTEXT,
+
+ // This expression cannot be evaluated at compile time (user error).
+ EVAL_INVALID,
+};
+
+// Evaluates an expression at compile time.
+enum eval_result eval_expr(struct context *ctx,
+ struct expression *in, struct expression *out);
+
+#endif
diff --git a/include/expr.h b/include/expr.h
@@ -19,7 +19,6 @@ enum expr_type {
EXPR_CONSTANT,
EXPR_CONTINUE,
EXPR_FOR,
- EXPR_FREE,
EXPR_IF,
EXPR_LIST,
EXPR_MATCH,
diff --git a/include/type_store.h b/include/type_store.h
@@ -10,8 +10,11 @@ struct type_bucket {
struct type_bucket *next;
};
+struct context;
+
struct type_store {
struct type_bucket *buckets[TYPE_STORE_BUCKETS];
+ struct context *check_context;
};
bool type_is_assignable(struct type_store *store,
diff --git a/src/check.c b/src/check.c
@@ -33,7 +33,7 @@ expect(bool constraint, char *fmt, ...)
}
}
-static void check_expression(struct context *ctx,
+void check_expression(struct context *ctx,
const struct ast_expression *aexpr, struct expression *expr);
static void
@@ -425,7 +425,7 @@ check_expr_unarithm(struct context *ctx,
trleave(TR_CHECK, NULL);
}
-static void
+void
check_expression(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -459,7 +459,6 @@ check_expression(struct context *ctx,
break;
case EXPR_CONTINUE:
case EXPR_FOR:
- case EXPR_FREE:
case EXPR_IF:
assert(0); // TODO
case EXPR_LIST:
@@ -635,6 +634,7 @@ void
check(const struct ast_unit *aunit, struct unit *unit)
{
struct context ctx = {0};
+ ctx.store.check_context = &ctx;
// Top-level scope management involves:
//
diff --git a/src/eval.c b/src/eval.c
@@ -0,0 +1,39 @@
+#include <assert.h>
+#include <stdbool.h>
+#include "eval.h"
+#include "expr.h"
+#include "scope.h"
+#include "type_store.h"
+#include "types.h"
+
+enum eval_result
+eval_expr(struct context *ctx, struct expression *in, struct expression *out)
+{
+ switch (in->type) {
+ case EXPR_ACCESS:
+ case EXPR_BINARITHM:
+ case EXPR_CAST:
+ case EXPR_CONSTANT:
+ case EXPR_CONTINUE:
+ case EXPR_FOR:
+ case EXPR_MEASURE:
+ case EXPR_SLICE:
+ case EXPR_STRUCT:
+ case EXPR_UNARITHM:
+ assert(0); // TODO
+ case EXPR_ASSERT:
+ case EXPR_ASSIGN:
+ case EXPR_BINDING:
+ case EXPR_BREAK:
+ case EXPR_CALL:
+ case EXPR_IF:
+ case EXPR_LIST:
+ case EXPR_MATCH:
+ case EXPR_RETURN:
+ case EXPR_SWITCH:
+ case EXPR_WHILE:
+ // Excluded from translation-compatible subset
+ return EVAL_INVALID;
+ }
+ assert(0); // Unreachable
+}
diff --git a/src/gen.c b/src/gen.c
@@ -519,7 +519,6 @@ gen_expression(struct gen_context *ctx,
break;
case EXPR_CONTINUE:
case EXPR_FOR:
- case EXPR_FREE:
case EXPR_IF:
assert(0); // TODO
case EXPR_LIST:
diff --git a/src/type_store.c b/src/type_store.c
@@ -1,8 +1,8 @@
#include <assert.h>
#include <stdlib.h>
+#include "check.h"
#include "type_store.h"
#include "util.h"
-#include <stdio.h>
bool
type_is_assignable(struct type_store *store,
@@ -177,6 +177,7 @@ atype_hash(struct type_store *store, const struct ast_type *type)
break; // built-ins
case TYPE_STORAGE_ALIAS:
case TYPE_STORAGE_ARRAY:
+ assert(0); // TODO
case TYPE_STORAGE_FUNCTION:
hash = djb2(hash, atype_hash(store, type->func.result));
hash = djb2(hash, type->func.variadism);
@@ -231,6 +232,7 @@ type_hash(struct type_store *store, const struct type *type)
break; // built-ins
case TYPE_STORAGE_ALIAS:
case TYPE_STORAGE_ARRAY:
+ assert(0); // TODO
case TYPE_STORAGE_FUNCTION:
hash = djb2(hash, type_hash(store, type->func.result));
hash = djb2(hash, type->func.variadism);