harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Minclude/types.h | 2++
Msrc/check.c | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/types.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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) {