harec

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

commit 6961bfd6431a3a8c1b776d998c8fdd35094c6112
parent 76ca5aba26366d1417a4f5e05d38c17a1cd25381
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 24 Dec 2020 14:56:35 -0500

check: implement call expressions

Diffstat:
Minclude/expr.h | 12++++++++++++
Minclude/types.h | 2++
Msrc/check.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/types.c | 9+++++++++
4 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -82,6 +82,17 @@ struct expression_binding { struct expression_binding *next; }; +struct call_argument { + bool variadic; + struct expression *value; + struct call_argument *next; +}; + +struct expression_call { + struct expression *lvalue; + struct call_argument *args; +}; + union expression_constant { bool bval; struct { @@ -147,6 +158,7 @@ struct expression { struct expression_assign assign; struct expression_binarithm binarithm; struct expression_binding binding; + struct expression_call call; union expression_constant constant; struct expression_list list; struct expression_measure measure; diff --git a/include/types.h b/include/types.h @@ -91,6 +91,8 @@ bool type_is_signed(const struct type *type); bool type_is_integer(const struct type *type); bool type_is_numeric(const struct type *type); +const struct type *type_dereference(const struct type *type); + // Built-in type singletons extern const struct type // Primitive diff --git a/src/check.c b/src/check.c @@ -182,6 +182,48 @@ check_expr_binding(struct context *ctx, } static void +check_expr_call(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "call"); + expr->type = EXPR_CALL; + + struct expression *lvalue = calloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->call.lvalue, lvalue); + expr->call.lvalue = lvalue; + + const struct type *fntype = type_dereference(lvalue->result); + expect(fntype->storage == TYPE_STORAGE_FUNCTION, + "Cannot call non-function type"); + expr->result = fntype->func.result; + assert(fntype->func.variadism == VARIADISM_NONE); // TODO + + struct call_argument *arg, **next = &expr->call.args; + struct ast_call_argument *aarg = aexpr->call.args; + struct type_func_param *param = fntype->func.params; + while (param && aarg) { + assert(!aarg->variadic); // TODO + arg = *next = calloc(1, sizeof(struct call_argument)); + arg->value = calloc(1, sizeof(struct expression)); + check_expression(ctx, aarg->value, arg->value); + + // TODO: Test for assignability + expect(arg->value->result->storage == param->type->storage, + "Invalid type for parameter"); + + aarg = aarg->next; + param = param->next; + next = &arg->next; + } + + expect(!aarg, "Too many parameters for function call"); + expect(!param, "Not enough parameters for function call"); + + trleave(TR_CHECK, NULL); +} + +static void check_expr_constant(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -385,7 +427,10 @@ check_expression(struct context *ctx, check_expr_binding(ctx, aexpr, expr); break; case EXPR_BREAK: + assert(0); // TODO case EXPR_CALL: + check_expr_call(ctx, aexpr, expr); + break; case EXPR_CAST: assert(0); // TODO case EXPR_CONSTANT: diff --git a/src/types.c b/src/types.c @@ -181,6 +181,15 @@ type_is_signed(const struct type *type) assert(0); // Unreachable } +const struct type * +type_dereference(const struct type *type) +{ + if (type->storage != TYPE_STORAGE_POINTER) { + return type; + } + return type_dereference(type->pointer.referent); +} + // Built-in type singletons const struct type builtin_type_bool = { .storage = TYPE_STORAGE_BOOL,