aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-04-13 15:48:56 +0100
committergingerBill <bill@gingerbill.org>2020-04-13 15:48:56 +0100
commitf229084baa383ebd81c5d04db1ede5dc71017904 (patch)
treeb2f5f4ace82547fd96e1e6bf3279dd300272c928 /src
parentf09b6a4c90805a562b2252430f844e85d06f1ee1 (diff)
Basic polymorphic named procedure parameters for procedures and records
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.cpp3
-rw-r--r--src/check_expr.cpp67
-rw-r--r--src/check_type.cpp22
-rw-r--r--src/checker.cpp3
-rw-r--r--src/entity.cpp20
-rw-r--r--src/exact_value.cpp22
-rw-r--r--src/ir.cpp31
-rw-r--r--src/llvm_backend.cpp38
-rw-r--r--src/types.cpp3
9 files changed, 165 insertions, 44 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 04c754649..dd2432eb9 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -1193,7 +1193,6 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
ProcUsingVar puv = {e, uvar};
array_add(&using_entities, puv);
-
}
}
} else {
@@ -1221,7 +1220,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
// NOTE(bill, 2019-08-31): Don't check the body as the where clauses failed
return;
}
-
+
check_open_scope(ctx, body);
{
for_array(i, using_entities) {
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index e446752a1..f401c993f 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1117,6 +1117,9 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
e->flags |= EntityFlag_Used;
Type *type = e->type;
+
+ o->type = type;
+
switch (e->kind) {
case Entity_Constant:
if (type == t_invalid) {
@@ -1127,6 +1130,14 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
if (o->value.kind == ExactValue_Invalid) {
return e;
}
+ if (o->value.kind == ExactValue_Procedure) {
+ Entity *proc = strip_entity_wrapping(o->value.value_procedure);
+ if (proc != nullptr) {
+ o->mode = Addressing_Value;
+ o->type = proc->type;
+ return proc;
+ }
+ }
o->mode = Addressing_Constant;
break;
@@ -1144,6 +1155,7 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
case Entity_Procedure:
o->mode = Addressing_Value;
+ o->value = exact_value_procedure(n);
break;
case Entity_Builtin:
@@ -1180,7 +1192,6 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
break;
}
- o->type = type;
return e;
}
@@ -3602,10 +3613,20 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
add_entity_use(c, selector, entity);
+ operand->type = entity->type;
+ operand->expr = node;
+
switch (entity->kind) {
case Entity_Constant:
- operand->mode = Addressing_Constant;
operand->value = entity->Constant.value;
+ operand->mode = Addressing_Constant;
+ if (operand->value.kind == ExactValue_Procedure) {
+ Entity *proc = strip_entity_wrapping(operand->value.value_procedure);
+ if (proc != nullptr) {
+ operand->mode = Addressing_Value;
+ operand->type = proc->type;
+ }
+ }
break;
case Entity_Variable:
// TODO(bill): Is this the rule I need?
@@ -3628,6 +3649,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
break;
case Entity_Procedure:
operand->mode = Addressing_Value;
+ operand->value = exact_value_procedure(node);
break;
case Entity_Builtin:
operand->mode = Addressing_Builtin;
@@ -3645,8 +3667,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
break;
}
- operand->type = entity->type;
- operand->expr = node;
+ add_type_and_value(c->info, operand->expr, operand->mode, operand->type, operand->value);
return entity;
}
@@ -7044,10 +7065,17 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
}
o->type = e->type;
if (o->mode != Addressing_Constant) {
- if (show_error) {
- error(o->expr, "Expected a constant value for this polymorphic type argument");
+ bool valid = false;
+ if (is_type_proc(o->type)) {
+ Entity *proc_entity = entity_from_expr(o->expr);
+ valid = proc_entity != nullptr;
+ }
+ if (!valid) {
+ if (show_error) {
+ error(o->expr, "Expected a constant value for this polymorphic type argument");
+ }
+ err = CallArgumentError_NoneConstantParameter;
}
- err = CallArgumentError_NoneConstantParameter;
}
score += s;
}
@@ -9257,29 +9285,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = check_expr_base_internal(c, o, node, type_hint);
- Type *type = nullptr;
- ExactValue value = {ExactValue_Invalid};
- switch (o->mode) {
- case Addressing_Invalid:
- type = t_invalid;
- break;
- case Addressing_NoValue:
- type = nullptr;
- break;
- case Addressing_Constant:
- value = o->value;
- type = o->type;
- break;
- default:
- type = o->type;
- break;
+ if (o->type != nullptr && is_type_untyped(o->type)) {
+ add_untyped(&c->checker->info, node, false, o->mode, o->type, o->value);
}
-
- if (type != nullptr && is_type_untyped(type)) {
- add_untyped(&c->checker->info, node, false, o->mode, type, value);
- }
- add_type_and_value(&c->checker->info, node, o->mode, type, value);
-
+ add_type_and_value(&c->checker->info, node, o->mode, o->type, o->value);
return kind;
}
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 089e66c4d..6df824ec1 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -469,7 +469,9 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
is_polymorphic = true;
can_check_fields = false;
}
- e = alloc_entity_constant(scope, token, operand.type, operand.value);
+ if (e == nullptr) {
+ e = alloc_entity_constant(scope, token, operand.type, operand.value);
+ }
}
} else {
if (is_type_param) {
@@ -1672,11 +1674,19 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
}
}
if (is_poly_name) {
- if (op.mode == Addressing_Constant) {
- poly_const = op.value;
- } else {
- error(op.expr, "Expected a constant value for this polymorphic name parameter");
- success = false;
+ bool valid = false;
+ if (is_type_proc(op.type)) {
+ Entity *proc_entity = entity_from_expr(op.expr);
+ valid = proc_entity != nullptr;
+ poly_const = exact_value_procedure(proc_entity->identifier ? proc_entity->identifier : op.expr);
+ }
+ if (!valid) {
+ if (op.mode == Addressing_Constant) {
+ poly_const = op.value;
+ } else {
+ error(op.expr, "Expected a constant value for this polymorphic name parameter");
+ success = false;
+ }
}
}
if (is_type_untyped(default_type(type))) {
diff --git a/src/checker.cpp b/src/checker.cpp
index 517a63506..026b1e7c1 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -885,6 +885,7 @@ void destroy_checker(Checker *c) {
Entity *entity_of_ident(Ast *identifier) {
+ identifier = unparen_expr(identifier);
if (identifier->kind == Ast_Ident) {
return identifier->Ident.entity;
}
@@ -1042,6 +1043,8 @@ void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mode, Type *ty
expr->tav.value = value;
} else if (mode == Addressing_Value && is_type_typeid(type)) {
expr->tav.value = value;
+ } else if (mode == Addressing_Value && is_type_proc(type)) {
+ expr->tav.value = value;
}
prev_expr = expr;
diff --git a/src/entity.cpp b/src/entity.cpp
index a64e767d6..f4888d072 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -357,3 +357,23 @@ Entity *alloc_entity_dummy_variable(Scope *scope, Token token) {
return alloc_entity_variable(scope, token, nullptr);
}
+
+Entity *entity_from_expr(Ast *expr);
+
+Entity *strip_entity_wrapping(Entity *e) {
+ if (e == nullptr) {
+ return nullptr;
+ }
+ if (e->kind != Entity_Constant) {
+ return e;
+ }
+ if (e->Constant.value.kind == ExactValue_Procedure) {
+ return strip_entity_wrapping(e->Constant.value.value_procedure);
+ }
+ return e;
+}
+
+Entity *strip_entity_wrapping(Ast *expr) {
+ Entity *e = entity_from_expr(expr);
+ return strip_entity_wrapping(e);
+}
diff --git a/src/exact_value.cpp b/src/exact_value.cpp
index 1473319cc..2e33d1786 100644
--- a/src/exact_value.cpp
+++ b/src/exact_value.cpp
@@ -592,6 +592,10 @@ i32 exact_value_order(ExactValue const &v) {
return 5;
case ExactValue_Pointer:
return 6;
+ case ExactValue_Procedure:
+ return 7;
+ // case ExactValue_Compound:
+ // return 8;
default:
GB_PANIC("How'd you get here? Invalid Value.kind");
@@ -652,6 +656,9 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
return;
}
break;
+
+ case ExactValue_Procedure:
+ return;
}
compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
@@ -915,12 +922,23 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
case Token_NotEq: return !are_types_identical(x.value_typeid, y.value_typeid);
}
break;
+
+ case ExactValue_Procedure:
+ switch (op) {
+ case Token_CmpEq: return are_types_identical(x.value_typeid, y.value_typeid);
+ case Token_NotEq: return !are_types_identical(x.value_typeid, y.value_typeid);
+ }
+ break;
}
GB_PANIC("Invalid comparison");
return false;
}
+Entity *strip_entity_wrapping(Ast *expr);
+Entity *strip_entity_wrapping(Entity *e);
+
+gbString write_expr_to_string(gbString str, Ast *node);
gbString write_exact_value_to_string(gbString str, ExactValue const &v, isize string_limit=36) {
switch (v.kind) {
@@ -956,9 +974,9 @@ gbString write_exact_value_to_string(gbString str, ExactValue const &v, isize st
case ExactValue_Pointer:
return str;
case ExactValue_Compound:
- return str;
+ return write_expr_to_string(str, v.value_compound);
case ExactValue_Procedure:
- return str;
+ return write_expr_to_string(str, v.value_procedure);
}
return str;
};
diff --git a/src/ir.cpp b/src/ir.cpp
index e8ab09ea5..a5d532b97 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1984,7 +1984,11 @@ irDebugEncoding ir_debug_encoding_for_basic(BasicKind kind) {
// case Basic_f16:
case Basic_f32:
case Basic_f64:
- return irDebugBasicEncoding_float;
+ case Basic_f32le:
+ case Basic_f64le:
+ case Basic_f32be:
+ case Basic_f64be:
+ return irDebugBasicEncoding_float;
// case Basic_complex32:
case Basic_complex64:
@@ -7104,6 +7108,29 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
return ir_emit_conv(proc, v, tv.type);
}
+ if (tv.value.kind == ExactValue_Procedure) {
+ Ast *expr = tv.value.value_procedure;
+ if (expr->kind == Ast_ProcLit) {
+ return ir_gen_anonymous_proc_lit(proc->module, str_lit("_proclit"), expr);
+ }
+ Entity *e = entity_from_expr(expr);
+ e = strip_entity_wrapping(e);
+ GB_ASSERT(e != nullptr);
+ auto *found = map_get(&proc->module->values, hash_entity(e));
+ if (found) {
+ auto v = *found;
+ // NOTE(bill): This is because pointers are already pointers in LLVM
+ if (is_type_proc(ir_type(v))) {
+ return v;
+ }
+ return ir_emit_load(proc, v);
+ } else if (e != nullptr && e->kind == Entity_Variable) {
+ return ir_addr_load(proc, ir_build_addr(proc, expr));
+ }
+
+ GB_PANIC("Error in: %.*s(%td:%td) %s\n", LIT(proc->name), e->token.pos.line, e->token.pos.column);
+ }
+
return ir_add_module_constant(proc->module, tv.type, tv.value);
}
@@ -7139,6 +7166,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
case_ast_node(i, Ident, expr);
Entity *e = entity_of_ident(expr);
+ e = strip_entity_wrapping(e);
+
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
if (e->kind == Entity_Builtin) {
Token token = ast_token(expr);
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 954e6368d..b296a7df7 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -8565,6 +8565,30 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
GB_ASSERT(tv.mode != Addressing_Type);
if (tv.value.kind != ExactValue_Invalid) {
+ if (tv.value.kind == ExactValue_Procedure) {
+ Ast *expr = tv.value.value_procedure;
+ if (expr->kind == Ast_ProcLit) {
+ return lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr);
+ }
+ Entity *e = entity_from_expr(expr);
+ e = strip_entity_wrapping(e);
+ GB_ASSERT(e != nullptr);
+ auto *found = map_get(&p->module->values, hash_entity(e));
+ if (found) {
+ auto v = *found;
+ // NOTE(bill): This is because pointers are already pointers in LLVM
+ if (is_type_proc(v.type)) {
+ return v;
+ }
+ return lb_emit_load(p, v);
+ } else if (e != nullptr && e->kind == Entity_Variable) {
+ return lb_addr_load(p, lb_build_addr(p, expr));
+ }
+
+ GB_PANIC("Error in: %.*s(%td:%td) %s\n", LIT(p->name), e->token.pos.line, e->token.pos.column);
+ // GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(e->pkg->name), LIT(e->token.string), e, type_to_string(e->type), expr);
+ }
+
// NOTE(bill): Short on constant values
return lb_const_value(p->module, tv.type, tv.value);
}
@@ -8599,7 +8623,9 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
case_end;
case_ast_node(i, Ident, expr);
- Entity *e = entity_of_ident(expr);
+ Entity *e = entity_from_expr(expr);
+ e = strip_entity_wrapping(e);
+
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
if (e->kind == Entity_Builtin) {
Token token = ast_token(expr);
@@ -8626,8 +8652,12 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
} else if (e != nullptr && e->kind == Entity_Variable) {
return lb_addr_load(p, lb_build_addr(p, expr));
}
- gb_printf_err("Error in: %.*s(%td:%td)\n", LIT(p->name), i->token.pos.line, i->token.pos.column);
- GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(e->pkg->name), LIT(e->token.string), e, type_to_string(e->type), expr);
+ gb_printf_err("Error in: %.*s(%td:%td) %s\n", LIT(p->name), i->token.pos.line, i->token.pos.column);
+ String pkg = {};
+ if (e->pkg) {
+ pkg = e->pkg->name;
+ }
+ GB_PANIC("nullptr value for expression from identifier: %.*s.%.*s (%p) : %s @ %p", LIT(pkg), LIT(e->token.string), e, type_to_string(e->type), expr);
return {};
case_end;
@@ -9085,7 +9115,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
if (tav.mode == Addressing_Type) { // Addressing_Type
Selection sel = lookup_field(type, selector, true);
Entity *e = sel.entity;
- GB_ASSERT(e->kind == Entity_Variable);
+ GB_ASSERT_MSG(e->kind == Entity_Variable, "Entity_%.*s", LIT(entity_strings[e->kind]));
GB_ASSERT(e->flags & EntityFlag_TypeField);
String name = e->token.string;
/*if (name == "names") {
diff --git a/src/types.cpp b/src/types.cpp
index bf5a12e9b..530a02df7 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1039,6 +1039,9 @@ bool is_type_constant_type(Type *t) {
if (t->kind == Type_BitSet) {
return true;
}
+ if (t->kind == Type_Proc) {
+ return true;
+ }
return false;
}
bool is_type_float(Type *t) {