do keyword for inline statements instead of blocks

This commit is contained in:
Ginger Bill
2017-07-01 11:38:44 +01:00
parent 33f4af2e19
commit ed089b44b9
11 changed files with 198 additions and 164 deletions
+40 -23
View File
@@ -1073,7 +1073,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
}
}
bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool compound) {
bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool compound, bool modify_type) {
Operand o = {Addressing_Value};
o.type = source;
switch (poly->kind) {
@@ -1085,40 +1085,42 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
return check_is_assignable_to(c, &o, poly);
case Type_Generic: {
Type *ds = default_type(source);
gb_memmove(poly, ds, gb_size_of(Type));
if (modify_type) {
Type *ds = default_type(source);
gb_memmove(poly, ds, gb_size_of(Type));
}
return true;
}
case Type_Pointer:
if (source->kind == Type_Pointer) {
return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Pointer.elem, true);
return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Pointer.elem, true, modify_type);
}
return false;
case Type_Atomic:
if (source->kind == Type_Atomic) {
return is_polymorphic_type_assignable(c, poly->Atomic.elem, source->Atomic.elem, true);
return is_polymorphic_type_assignable(c, poly->Atomic.elem, source->Atomic.elem, true, modify_type);
}
return false;
case Type_Array:
if (source->kind == Type_Array &&
poly->Array.count == source->Array.count) {
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true);
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
}
return false;
case Type_DynamicArray:
if (source->kind == Type_DynamicArray) {
return is_polymorphic_type_assignable(c, poly->DynamicArray.elem, source->DynamicArray.elem, true);
return is_polymorphic_type_assignable(c, poly->DynamicArray.elem, source->DynamicArray.elem, true, modify_type);
}
return false;
case Type_Vector:
if (source->kind == Type_Vector &&
poly->Vector.count == source->Vector.count) {
return is_polymorphic_type_assignable(c, poly->Vector.elem, source->Vector.elem, true);
return is_polymorphic_type_assignable(c, poly->Vector.elem, source->Vector.elem, true, modify_type);
}
return false;
case Type_Slice:
if (source->kind == Type_Slice) {
return is_polymorphic_type_assignable(c, poly->Slice.elem, source->Slice.elem, true);
return is_polymorphic_type_assignable(c, poly->Slice.elem, source->Slice.elem, true, modify_type);
}
return false;
@@ -1137,8 +1139,8 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
return false;
case Type_Map:
if (source->kind == Type_Map) {
bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true);
bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true);
bool key = is_polymorphic_type_assignable(c, poly->Map.key, source->Map.key, true, modify_type);
bool value = is_polymorphic_type_assignable(c, poly->Map.value, source->Map.value, true, modify_type);
return key || value;
}
return false;
@@ -1147,21 +1149,26 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
}
Type *determine_type_from_polymorphic(Checker *c, Type *poly_type, Operand operand) {
bool modify_type = !c->context.no_polymorphic_errors;
if (!is_operand_value(operand)) {
error(operand.expr, "Cannot determine polymorphic type from parameter");
if (modify_type) {
error(operand.expr, "Cannot determine polymorphic type from parameter");
}
return t_invalid;
}
if (is_polymorphic_type_assignable(c, poly_type, operand.type, false)) {
if (is_polymorphic_type_assignable(c, poly_type, operand.type, false, modify_type)) {
return poly_type;
}
gbString pts = type_to_string(poly_type);
gbString ots = type_to_string(operand.type);
defer (gb_string_free(pts));
defer (gb_string_free(ots));
error(operand.expr,
"Cannot determine polymorphic type from parameter: `%s` to `%s`\n"
"\tNote: Record and procedure types are not yet supported",
ots, pts);
if (modify_type) {
gbString pts = type_to_string(poly_type);
gbString ots = type_to_string(operand.type);
defer (gb_string_free(pts));
defer (gb_string_free(ots));
error(operand.expr,
"Cannot determine polymorphic type from parameter: `%s` to `%s`\n"
"\tNote: Record and procedure types are not yet supported",
ots, pts);
}
return t_invalid;
}
@@ -1332,7 +1339,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (o.mode == Addressing_Type) {
type = o.type;
} else {
error(o.expr, "Expected a type to assign to the type parameter");
if (!c->context.no_polymorphic_errors) {
error(o.expr, "Expected a type to assign to the type parameter");
}
success = false;
type = t_invalid;
}
}
@@ -5338,7 +5348,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
if (o.mode == Addressing_Invalid) {
continue;
} else if (o.mode != Addressing_Type) {
error(o.expr, "Expected a type for the argument `%.*s`", LIT(e->token.string));
if (show_error) {
error(o.expr, "Expected a type for the argument `%.*s`", LIT(e->token.string));
}
err = CallArgumentError_WrongTypes;
}
@@ -5641,6 +5653,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
for (isize i = 0; i < overload_count; i++) {
Entity *e = procs[i];
GB_ASSERT(e->token.string == name);
DeclInfo *d = decl_info_of_entity(&c->info, e);
GB_ASSERT(d != NULL);
check_entity_decl(c, e, d, NULL);
@@ -5651,7 +5664,11 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
Type *pt = base_type(p->type);
if (pt != NULL && is_type_proc(pt)) {
CallArgumentData data = {};
bool prev = c->context.no_polymorphic_errors;
defer (c->context.no_polymorphic_errors = prev);
c->context.no_polymorphic_errors = true;
CallArgumentError err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
if (err == CallArgumentError_None) {
valids[valid_count].index = i;
valids[valid_count].score = data.score;
+8 -1
View File
@@ -262,6 +262,7 @@ struct CheckerContext {
u32 stmt_state_flags;
bool in_defer; // TODO(bill): Actually handle correctly
bool allow_polymorphic_types;
bool no_polymorphic_errors;
String proc_name;
Type * type_hint;
DeclInfo * curr_proc_decl;
@@ -1474,8 +1475,10 @@ void check_procedure_overloading(Checker *c, Entity *e) {
is_invalid = true;
break;
case ProcOverload_Polymorphic:
#if 1
error(p->token, "Overloaded procedure `%.*s` has a polymorphic counterpart in this scope which is not allowed", LIT(name));
is_invalid = true;
#endif
break;
case ProcOverload_ParamCount:
case ProcOverload_ParamTypes:
@@ -1705,7 +1708,11 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
e->identifier = name;
if (fl != NULL && e->kind != Entity_Procedure) {
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[init->kind]));
AstNodeKind kind = init->kind;
error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_node_strings[kind]));
if (kind == AstNode_ProcType) {
gb_printf_err("\tDid you forget to append `---` to the procedure?\n");
}
// continue;
}
+1
View File
@@ -92,6 +92,7 @@ struct Entity {
bool is_foreign;
Entity * foreign_library;
AstNode * foreign_library_ident;
String link_name;
} Variable;
struct {
bool is_type_alias;
+36 -12
View File
@@ -882,9 +882,13 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
void error(AstNode *node, char *fmt, ...) {
Token token = {};
if (node != NULL) {
token = ast_node_token(node);
}
va_list va;
va_start(va, fmt);
error_va(ast_node_token(node), fmt, va);
error_va(token, fmt, va);
va_end(va);
}
@@ -2265,6 +2269,26 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
body = parse_body(f);
f->curr_proc = curr_proc;
return ast_proc_lit(f, type, body, tags, link_name);
} else if (allow_token(f, Token_do)) {
if ((tags & ProcTag_foreign) != 0) {
syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
}
AstNode *curr_proc = f->curr_proc;
AstNode *body = NULL;
f->curr_proc = type;
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
} else {
Token open = ast_node_token(body);
Token close = ast_node_token(body);
Array<AstNode *> stmts = make_ast_node_array(f, 1);
array_add(&stmts, body);
body = ast_block_stmt(f, stmts, open, close);
}
f->curr_proc = curr_proc;
return ast_proc_lit(f, type, body, tags, link_name);
}
@@ -3787,7 +3811,7 @@ AstNode *parse_if_stmt(AstFile *f) {
syntax_error(f->curr_token, "Expected condition for if statement");
}
if (allow_token(f, Token_ArrowRight)) {
if (allow_token(f, Token_do)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -3804,8 +3828,8 @@ AstNode *parse_if_stmt(AstFile *f) {
case Token_OpenBrace:
else_stmt = parse_block_stmt(f, false);
break;
case Token_ArrowRight: {
Token arrow = expect_token(f, Token_ArrowRight);
case Token_do: {
Token arrow = expect_token(f, Token_do);
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -3838,7 +3862,7 @@ AstNode *parse_when_stmt(AstFile *f) {
syntax_error(f->curr_token, "Expected condition for when statement");
}
if (allow_token(f, Token_ArrowRight)) {
if (allow_token(f, Token_do)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -3855,8 +3879,8 @@ AstNode *parse_when_stmt(AstFile *f) {
case Token_OpenBrace:
else_stmt = parse_block_stmt(f, true);
break;
case Token_ArrowRight: {
Token arrow = expect_token(f, Token_ArrowRight);
case Token_do: {
Token arrow = expect_token(f, Token_do);
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -3958,7 +3982,7 @@ AstNode *parse_for_stmt(AstFile *f) {
}
if (!is_range && (f->curr_token.kind == Token_Semicolon ||
f->curr_token.kind == Token_ArrowRight)) {
f->curr_token.kind == Token_do)) {
next_token(f);
init = cond;
cond = NULL;
@@ -3967,7 +3991,7 @@ AstNode *parse_for_stmt(AstFile *f) {
}
expect_semicolon(f, cond);
if (f->curr_token.kind != Token_OpenBrace &&
f->curr_token.kind != Token_ArrowRight) {
f->curr_token.kind != Token_do) {
post = parse_simple_stmt(f, StmtAllowFlag_None);
}
}
@@ -3975,7 +3999,7 @@ AstNode *parse_for_stmt(AstFile *f) {
f->expr_level = prev_level;
}
if (allow_token(f, Token_ArrowRight)) {
if (allow_token(f, Token_do)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -4236,7 +4260,7 @@ AstNode *parse_stmt(AstFile *f) {
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
if (allow_token(f, Token_ArrowRight)) {
if (allow_token(f, Token_do)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
@@ -4256,7 +4280,7 @@ AstNode *parse_stmt(AstFile *f) {
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
if (allow_token(f, Token_ArrowRight)) {
if (allow_token(f, Token_do)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
+30 -23
View File
@@ -36,27 +36,28 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
TOKEN_KIND(Token_CmpAnd, "&&"), \
TOKEN_KIND(Token_CmpOr, "||"), \
\
TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
TOKEN_KIND(Token_AddEq, "+="), \
TOKEN_KIND(Token_SubEq, "-="), \
TOKEN_KIND(Token_MulEq, "*="), \
TOKEN_KIND(Token_QuoEq, "/="), \
TOKEN_KIND(Token_ModEq, "%="), \
TOKEN_KIND(Token_ModModEq, "%%="), \
TOKEN_KIND(Token_AndEq, "&="), \
TOKEN_KIND(Token_OrEq, "|="), \
TOKEN_KIND(Token_XorEq, "~="), \
TOKEN_KIND(Token_AndNotEq, "&~="), \
TOKEN_KIND(Token_ShlEq, "<<="), \
TOKEN_KIND(Token_ShrEq, ">>="), \
TOKEN_KIND(Token_CmpAndEq, "&&="), \
TOKEN_KIND(Token_CmpOrEq, "||="), \
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
TOKEN_KIND(Token_ArrowRight, "->"), \
TOKEN_KIND(Token_ThickArrowRight, "=>"), \
TOKEN_KIND(Token_Inc, "++"), \
TOKEN_KIND(Token_Dec, "--"), \
TOKEN_KIND(Token_Undef, "---"), \
TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
TOKEN_KIND(Token_AddEq, "+="), \
TOKEN_KIND(Token_SubEq, "-="), \
TOKEN_KIND(Token_MulEq, "*="), \
TOKEN_KIND(Token_QuoEq, "/="), \
TOKEN_KIND(Token_ModEq, "%="), \
TOKEN_KIND(Token_ModModEq, "%%="), \
TOKEN_KIND(Token_AndEq, "&="), \
TOKEN_KIND(Token_OrEq, "|="), \
TOKEN_KIND(Token_XorEq, "~="), \
TOKEN_KIND(Token_AndNotEq, "&~="), \
TOKEN_KIND(Token_ShlEq, "<<="), \
TOKEN_KIND(Token_ShrEq, ">>="), \
TOKEN_KIND(Token_CmpAndEq, "&&="), \
TOKEN_KIND(Token_CmpOrEq, "||="), \
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
TOKEN_KIND(Token_ArrowRight, "->"), \
TOKEN_KIND(Token_ArrowLeft, "<-"), \
TOKEN_KIND(Token_DoubleArrowRight, "=>"), \
TOKEN_KIND(Token_Inc, "++"), \
TOKEN_KIND(Token_Dec, "--"), \
TOKEN_KIND(Token_Undef, "---"), \
\
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
TOKEN_KIND(Token_CmpEq, "=="), \
@@ -100,6 +101,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_continue, "continue"), \
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
TOKEN_KIND(Token_defer, "defer"), \
TOKEN_KIND(Token_do, "do"), \
TOKEN_KIND(Token_return, "return"), \
TOKEN_KIND(Token_proc, "proc"), \
TOKEN_KIND(Token_macro, "macro"), \
@@ -914,7 +916,7 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_Eq;
if (t->curr_rune == '>') {
advance_to_next_rune(t);
token.kind = Token_ThickArrowRight;
token.kind = Token_DoubleArrowRight;
} else if (t->curr_rune == '=') {
advance_to_next_rune(t);
token.kind = Token_CmpEq;
@@ -976,7 +978,12 @@ Token tokenizer_get_token(Tokenizer *t) {
} break;
case '<':
token.kind = token_kind_dub_eq(t, '<', Token_Lt, Token_LtEq, Token_Shl, Token_ShlEq);
if (t->curr_rune == '-') {
advance_to_next_rune(t);
token.kind = Token_ArrowLeft;
} else {
token.kind = token_kind_dub_eq(t, '<', Token_Lt, Token_LtEq, Token_Shl, Token_ShlEq);
}
break;
case '>': token.kind = token_kind_dub_eq(t, '>', Token_Gt, Token_GtEq, Token_Shr, Token_ShrEq); break;
+5 -3
View File
@@ -1353,14 +1353,16 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
TypeProc px = base_type(x)->Proc;
TypeProc py = base_type(y)->Proc;
// if (px.calling_convention != py.calling_convention) {
// return ProcOverload_CallingConvention;
// }
if (px.is_polymorphic != py.is_polymorphic) {
return ProcOverload_Polymorphic;
}
// if (px.calling_convention != py.calling_convention) {
// return ProcOverload_CallingConvention;
// }
if (px.param_count != py.param_count) {
return ProcOverload_ParamCount;
}