aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-27 15:58:53 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-27 15:58:53 +0100
commit5df854fcef6d3c37f3703ed5568ef7de8ca6719e (patch)
treee48482df30b417f06cd819ffc722ad5bc2ea03e8 /src
parent260089431e069d2ce21ce74ff17c56c45fa7785e (diff)
Fixed demov0.5.0
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp62
-rw-r--r--src/checker.cpp15
-rw-r--r--src/types.cpp11
3 files changed, 54 insertions, 34 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 2f3b1630a..97bd33c88 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1077,14 +1077,17 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
-Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, Array<Operand> *operands) {
+Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, bool *success_, Array<Operand> *operands) {
if (_params == NULL) {
return NULL;
}
+
+ bool success = true;
ast_node(field_list, FieldList, _params);
Array<AstNode *> params = field_list->list;
if (params.count == 0) {
+ if (success_) *success_ = success;
return NULL;
}
@@ -1120,6 +1123,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
ExactValue value = {};
bool default_is_nil = false;
bool default_is_location = false;
+ bool is_type_param = false;
+
if (type_expr == NULL) {
if (default_value->kind == AstNode_BasicDirective &&
@@ -1147,15 +1152,19 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
is_variadic = true;
} else {
error(param, "Invalid AST: Invalid variadic parameter");
+ success = false;
}
}
if (type_expr->kind == AstNode_HelperType) {
+ is_type_param = true;
if (operands != NULL) {
Operand o = (*operands)[variable_index];
if (o.mode == Addressing_Type) {
type = o.type;
} else {
- error(o.expr, "Expected a type to assign to a type parameter");
+ error(o.expr, "Expected a type to assign to the type parameter");
+ type = t_invalid;
+ success = false;
}
} else {
type = make_type_generic(c->allocator, 0);
@@ -1197,7 +1206,11 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
type = t_invalid;
}
if (is_type_untyped(type)) {
- error(params[i], "Cannot determine parameter type from a nil");
+ if (is_type_untyped_undef(type)) {
+ error(params[i], "Cannot determine parameter type from ---");
+ } else {
+ error(params[i], "Cannot determine parameter type from a nil");
+ }
type = t_invalid;
}
@@ -1221,16 +1234,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
AstNode *name = p->names[j];
if (ast_node_expect(name, AstNode_Ident)) {
Entity *param = NULL;
- bool is_generic = type->kind == Type_Generic;
- Type *gen_type = type;
- if (operands != NULL) {
- Operand o = (*operands)[variable_index];
- is_generic = o.mode == Addressing_Type && o.type == type;
- if (is_generic) gen_type = o.type;
- }
-
- if (is_generic) {
- param = make_entity_type_name(c->allocator, scope, name->Ident, gen_type);
+ if (is_type_param) {
+ param = make_entity_type_name(c->allocator, scope, name->Ident, type);
param->TypeName.is_type_alias = true;
} else {
param = make_entity_param(c->allocator, scope, name->Ident, type,
@@ -1267,6 +1272,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
tuple->Tuple.variables = variables;
tuple->Tuple.variable_count = variable_count;
+ if (success_) *success_ = success;
if (is_variadic_) *is_variadic_ = is_variadic;
return tuple;
@@ -1574,11 +1580,12 @@ bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *a
}
// NOTE(bill): `operands` is for generating non generic procedure type
-void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array<Operand> *operands = NULL) {
+bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array<Operand> *operands = NULL) {
ast_node(pt, ProcType, proc_type_node);
bool variadic = false;
- Type *params = check_get_params(c, c->context.scope, pt->params, &variadic, operands);
+ bool success = true;
+ Type *params = check_get_params(c, c->context.scope, pt->params, &variadic, &success, operands);
Type *results = check_get_results(c, c->context.scope, pt->results);
isize param_count = 0;
@@ -1637,6 +1644,8 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
// NOTE(bill): The types are the same
type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
type->Proc.return_by_pointer = abi_compat_return_by_value(c->allocator, pt->calling_convention, type->Proc.abi_compat_result_type);
+
+ return success;
}
@@ -5002,15 +5011,18 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
// NOTE(bill): This is slightly memory leaking if the type already exists
// Maybe it's better to check with the previous types first?
Type *final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
- check_procedure_type(c, final_proc_type, pt->node, operands);
+ bool success = check_procedure_type(c, final_proc_type, pt->node, operands);
+ // if (!success) {
+ // return NULL;
+ // }
auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
if (found_gen_procs) {
for_array(i, *found_gen_procs) {
Entity *other = (*found_gen_procs)[i];
if (are_types_identical(other->type, final_proc_type)) {
- // NOTE(bill): This scope is not needed any more, destroy it
- destroy_scope(scope);
+ // NOTE(bill): This scope is not needed any more, destroy it
+ // destroy_scope(scope);
return other;
}
}
@@ -5039,12 +5051,14 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
entity->scope = base_entity->scope;
ProcedureInfo proc_info = {};
- proc_info.file = c->curr_ast_file;
- proc_info.token = token;
- proc_info.decl = d;
- proc_info.type = final_proc_type;
- proc_info.body = pd->body;
- proc_info.tags = tags;
+ if (success) {
+ proc_info.file = c->curr_ast_file;
+ proc_info.token = token;
+ proc_info.decl = d;
+ proc_info.type = final_proc_type;
+ proc_info.body = pd->body;
+ proc_info.tags = tags;
+ }
if (found_gen_procs) {
array_add(found_gen_procs, entity);
diff --git a/src/checker.cpp b/src/checker.cpp
index 051020ae6..f490a2a23 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -1448,19 +1448,10 @@ void check_procedure_overloading(Checker *c, Entity *e) {
TokenPos pos = q->token.pos;
- if (q->type == NULL) {
+ if (q->type == NULL || q->type == t_invalid) {
continue;
}
- if (is_type_proc(q->type)) {
- TypeProc *ptq = &base_type(q->type)->Proc;
- if (ptq->is_generic) {
- q->type = t_invalid;
- error(q->token, "Polymorphic procedure `%.*s` cannot be overloaded", LIT(name));
- continue;
- }
- }
-
ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type);
switch (kind) {
case ProcOverload_Identical:
@@ -1480,6 +1471,10 @@ void check_procedure_overloading(Checker *c, Entity *e) {
error(p->token, "Overloaded procedure `%.*s` as the same parameters but different results in this scope", LIT(name));
is_invalid = true;
break;
+ case ProcOverload_Polymorphic:
+ error(p->token, "Overloaded procedure `%.*s` has a polymorphic counterpart in this scope which is not allowed", LIT(name));
+ is_invalid = true;
+ break;
case ProcOverload_ParamCount:
case ProcOverload_ParamTypes:
// This is okay :)
diff --git a/src/types.cpp b/src/types.cpp
index 465f69048..ab6408b12 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1083,6 +1083,12 @@ bool are_types_identical(Type *x, Type *y) {
}
switch (x->kind) {
+ case Type_Generic:
+ if (y->kind == Type_Generic) {
+ return true; // TODO(bill): Is this correct?
+ }
+ break;
+
case Type_Basic:
if (y->kind == Type_Basic) {
return x->Basic.kind == y->Basic.kind;
@@ -1321,6 +1327,7 @@ enum ProcTypeOverloadKind {
ProcOverload_ParamTypes,
ProcOverload_ResultCount,
ProcOverload_ResultTypes,
+ ProcOverload_Polymorphic,
ProcOverload_NotProcedure,
@@ -1340,6 +1347,10 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
// return ProcOverload_CallingConvention;
// }
+ if (px.is_generic != py.is_generic) {
+ return ProcOverload_Polymorphic;
+ }
+
if (px.param_count != py.param_count) {
return ProcOverload_ParamCount;
}