diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-04-16 22:30:48 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-04-16 22:30:48 +0100 |
| commit | 187b186112f88b883a6366f7cd1b4a1ef32d3232 (patch) | |
| tree | c10f1d8af8a0bdfa22941aac7bf67fa168a83f0b /src | |
| parent | 5041a35b95e4e911697b464d6f20f99aef7a598b (diff) | |
Add `#require_results` for procedures
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_decl.c | 22 | ||||
| -rw-r--r-- | src/check_expr.c | 2 | ||||
| -rw-r--r-- | src/check_stmt.c | 17 | ||||
| -rw-r--r-- | src/parser.c | 3 | ||||
| -rw-r--r-- | src/types.c | 1 |
5 files changed, 36 insertions, 9 deletions
diff --git a/src/check_decl.c b/src/check_decl.c index 4522fb85e..5586cb904 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -242,11 +242,13 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) { check_open_scope(c, pd->type); check_procedure_type(c, proc_type, pd->type); - bool is_foreign = (pd->tags & ProcTag_foreign) != 0; - bool is_link_name = (pd->tags & ProcTag_link_name) != 0; - bool is_export = (pd->tags & ProcTag_export) != 0; - bool is_inline = (pd->tags & ProcTag_inline) != 0; - bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; + bool is_foreign = (pd->tags & ProcTag_foreign) != 0; + bool is_link_name = (pd->tags & ProcTag_link_name) != 0; + bool is_export = (pd->tags & ProcTag_export) != 0; + bool is_inline = (pd->tags & ProcTag_inline) != 0; + bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; + bool is_require_results = (pd->tags & ProcTag_require_results) != 0; + if (d->scope->is_file && str_eq(e->token.string, str_lit("main"))) { if (proc_type != NULL) { @@ -282,6 +284,16 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) { check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags); } + + if (proc_type != NULL && is_type_proc(proc_type)) { + TypeProc *tp = &proc_type->Proc; + if (tp->result_count == 0 && is_require_results) { + error_node(pd->type, "`#require_results` is not needed on a procedure with no results"); + } else { + tp->require_results = is_require_results; + } + } + if (is_foreign) { MapEntity *fp = &c->info.foreigns; String name = e->token.string; diff --git a/src/check_expr.c b/src/check_expr.c index ab8611e52..abdc21820 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -4796,7 +4796,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { } operand->expr = call; - return Expr_Stmt; + return Expr_Expr; } diff --git a/src/check_stmt.c b/src/check_stmt.c index c66729005..ca3bc9ac9 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -442,9 +442,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { Operand operand = {Addressing_Invalid}; ExprKind kind = check_expr_base(c, &operand, es->expr, NULL); switch (operand.mode) { - case Addressing_Type: - error_node(node, "Is not an expression"); - break; + case Addressing_Type: { + gbString str = type_to_string(operand.type); + error_node(node, "`%s` is not an expression", str); + gb_string_free(str); + } break; case Addressing_NoValue: return; default: { @@ -452,6 +454,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { return; } if (operand.expr->kind == AstNode_CallExpr) { + AstNodeCallExpr *ce = &operand.expr->CallExpr; + Type *t = type_of_expr(&c->info, ce->proc); + if (is_type_proc(t)) { + if (t->Proc.require_results) { + gbString expr_str = expr_to_string(ce->proc); + error_node(node, "`%s` requires that its results must be handled", expr_str); + gb_string_free(expr_str); + } + } return; } gbString expr_str = expr_to_string(operand.expr); diff --git a/src/parser.c b/src/parser.c index c3005ddb7..31d14db78 100644 --- a/src/parser.c +++ b/src/parser.c @@ -65,6 +65,8 @@ typedef enum ProcTag { ProcTag_bounds_check = 1<<0, ProcTag_no_bounds_check = 1<<1, + ProcTag_require_results = 1<<4, + ProcTag_foreign = 1<<10, ProcTag_export = 1<<11, ProcTag_link_name = 1<<12, @@ -1570,6 +1572,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str expect_token(f, Token_String); } } + ELSE_IF_ADD_TAG(require_results) ELSE_IF_ADD_TAG(export) ELSE_IF_ADD_TAG(bounds_check) ELSE_IF_ADD_TAG(no_bounds_check) diff --git a/src/types.c b/src/types.c index 0dc91f246..a806b13a2 100644 --- a/src/types.c +++ b/src/types.c @@ -135,6 +135,7 @@ typedef struct TypeRecord { Type **abi_compat_params; \ Type **abi_compat_results; \ bool variadic; \ + bool require_results; \ ProcCallingConvention calling_convention; \ }) \ TYPE_KIND(Map, struct { \ |