commit 105d0970e78eee965a56e96e5e77e39cbec821d3
parent 4fd9a0bca3e9cb1801e07f717f235b644becc429
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 23 Dec 2020 15:53:49 -0500
check: (mostly) implement unary arithmetic
Diffstat:
3 files changed, 120 insertions(+), 0 deletions(-)
diff --git a/include/types.h b/include/types.h
@@ -88,6 +88,8 @@ struct type {
const char *type_storage_unparse(enum type_storage storage);
bool type_is_signed(const struct type *type);
+bool type_is_integer(const struct type *type);
+bool type_is_numeric(const struct type *type);
// Built-in type singletons
extern const struct type
diff --git a/src/check.c b/src/check.c
@@ -278,6 +278,45 @@ check_expr_return(struct context *ctx,
}
static void
+check_expr_unarithm(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr)
+{
+ trenter(TR_CHECK, "unarithm");
+ expr->type = EXPR_UNARITHM;
+
+ struct expression *operand = calloc(1, sizeof(struct expression));
+ check_expression(ctx, aexpr->unarithm.operand, operand);
+ expr->unarithm.operand = operand;
+ expr->unarithm.op = aexpr->unarithm.op;
+
+ switch (expr->unarithm.op) {
+ case UN_LNOT:
+ expect(operand->result->storage == TYPE_STORAGE_BOOL,
+ "Cannot perform logical NOT (!) on non-boolean type");
+ expr->result = &builtin_type_bool;
+ break;
+ case UN_BNOT:
+ expect(type_is_integer(operand->result),
+ "Cannot perform binary NOT (~) on non-integer type");
+ expect(!type_is_signed(operand->result),
+ "Cannot perform binary NOT (~) on signed type");
+ // Fallthrough
+ case UN_MINUS:
+ case UN_PLUS:
+ expect(type_is_numeric(operand->result),
+ "Cannot perform operation on non-numeric type");
+ expr->result = operand->result;
+ break;
+ case UN_ADDRESS:
+ case UN_DEREF:
+ assert(0); // TODO
+ }
+
+ trleave(TR_CHECK, NULL);
+}
+
+static void
check_expression(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -322,7 +361,10 @@ check_expression(struct context *ctx,
case EXPR_SLICE:
case EXPR_STRUCT:
case EXPR_SWITCH:
+ assert(0); // TODO
case EXPR_UNARITHM:
+ check_expr_unarithm(ctx, aexpr, expr);
+ break;
case EXPR_WHILE:
assert(0); // TODO
}
diff --git a/src/types.c b/src/types.c
@@ -67,6 +67,82 @@ type_storage_unparse(enum type_storage storage)
}
bool
+type_is_integer(const struct type *type)
+{
+ switch (type->storage) {
+ case TYPE_STORAGE_VOID:
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ return false;
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ return true;
+ }
+ assert(0); // Unreachable
+}
+
+bool
+type_is_numeric(const struct type *type)
+{
+ switch (type->storage) {
+ case TYPE_STORAGE_VOID:
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_FUNCTION:
+ case TYPE_STORAGE_POINTER:
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_ENUM:
+ return false;
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ return true;
+ }
+ assert(0); // Unreachable
+}
+
+bool
type_is_signed(const struct type *type)
{
switch (type->storage) {