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) {