aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-04-16 22:30:48 +0100
committerGinger Bill <bill@gingerbill.org>2017-04-16 22:30:48 +0100
commit187b186112f88b883a6366f7cd1b4a1ef32d3232 (patch)
treec10f1d8af8a0bdfa22941aac7bf67fa168a83f0b /src
parent5041a35b95e4e911697b464d6f20f99aef7a598b (diff)
Add `#require_results` for procedures
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.c22
-rw-r--r--src/check_expr.c2
-rw-r--r--src/check_stmt.c17
-rw-r--r--src/parser.c3
-rw-r--r--src/types.c1
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 { \