gingerBill 5 years ago
parent
commit
57b09b2ffb
3 changed files with 45 additions and 7 deletions
  1. 16 3
      src/check_expr.cpp
  2. 27 2
      src/ir.cpp
  3. 2 2
      src/ir_print.cpp

+ 16 - 3
src/check_expr.cpp

@@ -7760,6 +7760,20 @@ bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *y, ExactValu
 	return true;
 	return true;
 }
 }
 
 
+bool check_is_operand_compound_lit_constant(CheckerContext *c, Operand *o) {
+	Ast *expr = unparen_expr(o->expr);
+	if (expr != nullptr) {
+		Entity *e = strip_entity_wrapping(entity_from_expr(expr));
+		if (e != nullptr && e->kind == Entity_Procedure) {
+			return true;
+		}
+		if (expr->kind == Ast_ProcLit) {
+			add_type_and_value(c->info, expr, Addressing_Constant, type_of_expr(expr), exact_value_procedure(expr));
+			return true;
+		}
+	}
+	return o->mode == Addressing_Constant;
+}
 
 
 
 
 ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
 ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
@@ -7780,7 +7794,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		c->state_flags = out;
 		c->state_flags = out;
 	}
 	}
 
 
-
 	ExprKind kind = Expr_Stmt;
 	ExprKind kind = Expr_Stmt;
 
 
 	o->mode = Addressing_Invalid;
 	o->mode = Addressing_Invalid;
@@ -8242,7 +8255,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 						is_constant = false;
 						is_constant = false;
 					}
 					}
 					if (is_constant) {
 					if (is_constant) {
-						is_constant = o.mode == Addressing_Constant;
+						is_constant = check_is_operand_compound_lit_constant(c, &o);
 					}
 					}
 
 
 					check_assignment(c, &o, field->type, str_lit("structure literal"));
 					check_assignment(c, &o, field->type, str_lit("structure literal"));
@@ -8277,7 +8290,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 						is_constant = false;
 						is_constant = false;
 					}
 					}
 					if (is_constant) {
 					if (is_constant) {
-						is_constant = o.mode == Addressing_Constant;
+						is_constant = check_is_operand_compound_lit_constant(c, &o);
 					}
 					}
 
 
 					check_assignment(c, &o, field->type, str_lit("structure literal"));
 					check_assignment(c, &o, field->type, str_lit("structure literal"));

+ 27 - 2
src/ir.cpp

@@ -523,6 +523,7 @@ struct irAddr {
 };
 };
 
 
 Type *ir_type(irValue *value);
 Type *ir_type(irValue *value);
+irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, irProcedure *proc = nullptr);
 
 
 irAddr ir_addr(irValue *addr) {
 irAddr ir_addr(irValue *addr) {
 	irAddr v = {irAddr_Default, addr};
 	irAddr v = {irAddr_Default, addr};
@@ -1614,7 +1615,27 @@ irDefer ir_add_defer_proc(irProcedure *proc, isize scope_index, irValue *deferre
 }
 }
 
 
 
 
-
+void ir_check_compound_lit_constant(irModule *m, Ast *expr) {
+	expr = unparen_expr(expr);
+	if (expr == nullptr) {
+		return;
+	}
+	if (expr->kind == Ast_CompoundLit) {
+		ast_node(cl, CompoundLit, expr);
+		for_array(i, cl->elems) {
+			Ast *elem = cl->elems[i];
+			if (elem->kind == Ast_FieldValue) {
+				ast_node(fv, FieldValue, elem);
+				ir_check_compound_lit_constant(m, fv->value);
+			} else {
+				ir_check_compound_lit_constant(m, elem);
+			}
+		}
+	}
+	if (expr->kind == Ast_ProcLit) {
+		ir_gen_anonymous_proc_lit(m, str_lit("_proclit"), expr);
+	}
+}
 
 
 irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) {
 irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) {
 	gbAllocator a = ir_allocator();
 	gbAllocator a = ir_allocator();
@@ -1652,6 +1673,10 @@ irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) {
 		}
 		}
 	}
 	}
 
 
+	if (value.kind == ExactValue_Compound) {
+		ir_check_compound_lit_constant(m, value.value_compound);
+	}
+
 	return ir_value_constant(type, value);
 	return ir_value_constant(type, value);
 }
 }
 
 
@@ -6504,7 +6529,7 @@ void ir_pop_target_list(irProcedure *proc) {
 
 
 
 
 
 
-irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, irProcedure *proc = nullptr) {
+irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, Ast *expr, irProcedure *proc) {
 	ast_node(pl, ProcLit, expr);
 	ast_node(pl, ProcLit, expr);
 
 
 	// NOTE(bill): Generate a new name
 	// NOTE(bill): Generate a new name

+ 2 - 2
src/ir_print.cpp

@@ -1294,7 +1294,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 	}
 	}
 	case ExactValue_Procedure: {
 	case ExactValue_Procedure: {
 		irValue **found = nullptr;
 		irValue **found = nullptr;
-		Ast *expr = value.value_procedure;
+		Ast *expr = unparen_expr(value.value_procedure);
 		GB_ASSERT(expr != nullptr);
 		GB_ASSERT(expr != nullptr);
 
 
 		if (expr->kind == Ast_ProcLit) {
 		if (expr->kind == Ast_ProcLit) {
@@ -1304,7 +1304,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			GB_ASSERT(e != nullptr);
 			GB_ASSERT(e != nullptr);
 			found = map_get(&m->values, hash_entity(e));
 			found = map_get(&m->values, hash_entity(e));
 		}
 		}
-		GB_ASSERT(found != nullptr);
+		GB_ASSERT_MSG(found != nullptr, "%s", expr_to_string(expr));
 		irValue *val = *found;
 		irValue *val = *found;
 		ir_print_value(f, m, val, type);
 		ir_print_value(f, m, val, type);
 		break;
 		break;