浏览代码

"Constant" procedure values for default values in structs

Ginger Bill 8 年之前
父节点
当前提交
1f24f105cc
共有 3 个文件被更改,包括 30 次插入7 次删除
  1. 17 2
      src/check_expr.cpp
  2. 3 3
      src/ir.cpp
  3. 10 2
      src/ir_print.cpp

+ 17 - 2
src/check_expr.cpp

@@ -58,6 +58,7 @@ void     check_expr_with_type_hint      (Checker *c, Operand *o, AstNode *e, Typ
 Type *   check_type                     (Checker *c, AstNode *expression, Type *named_type = nullptr);
 void     check_type_decl                (Checker *c, Entity *e, AstNode *type_expr, Type *def);
 Entity * check_selector                 (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
+Entity * check_ident                    (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name);
 void     check_not_tuple                (Checker *c, Operand *operand);
 void     convert_to_typed               (Checker *c, Operand *operand, Type *target_type, i32 level);
 gbString expr_to_string                 (AstNode *expression);
@@ -1037,9 +1038,23 @@ Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *>
 			} else if (o.mode != Addressing_Constant) {
 				if (default_value->kind == AstNode_ProcLit) {
 					value = exact_value_procedure(default_value);
-					// error(default_value, "A procedure literal as a default param is not yet supported");
 				} else {
-					error(default_value, "Default parameter must be a constant");
+					Entity *e = nullptr;
+					if (o.mode == Addressing_Value && is_type_proc(o.type)) {
+						Operand x = {};
+						if (default_value->kind == AstNode_Ident) {
+							e = check_ident(c, &x, default_value, nullptr, nullptr, false);
+						} else if (default_value->kind == AstNode_SelectorExpr) {
+							e = check_selector(c, &x, default_value, nullptr);
+						}
+					}
+
+					if (e != nullptr && e->kind == Entity_Procedure) {
+						value = exact_value_procedure(e->identifier);
+						add_entity_use(c, e->identifier, e);
+					} else {
+						error(default_value, "Default parameter must be a constant");
+					}
 				}
 			} else {
 				value = o.value;

+ 3 - 3
src/ir.cpp

@@ -3813,8 +3813,9 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
 					if (f->Variable.default_value.kind == ExactValue_Procedure) {
 						AstNode *expr = f->Variable.default_value.value_procedure;
 						GB_ASSERT(expr != nullptr);
-						GB_ASSERT(expr->kind == AstNode_ProcLit);
-						ir_gen_anonymous_proc_lit(m, e->token.string, expr);
+						if (expr->kind == AstNode_ProcLit) {
+							ir_gen_anonymous_proc_lit(m, e->token.string, expr);
+						}
 					}
 				}
 			}
@@ -8570,7 +8571,6 @@ void ir_gen_tree(irGen *s) {
 
 	for_array(i, m->procs_to_generate) {
 		irValue *p = m->procs_to_generate[i];
-		gb_printf_err("%.*s\n", LIT(p->Proc.name));
 		ir_build_proc(p, p->Proc.parent);
 	}
 

+ 10 - 2
src/ir_print.cpp

@@ -701,10 +701,18 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 	}
 
 	case ExactValue_Procedure: {
+		irValue **found = nullptr;
 		AstNode *expr = value.value_procedure;
 		GB_ASSERT(expr != nullptr);
-		GB_ASSERT(expr->kind == AstNode_ProcLit);
-		irValue **found = map_get(&m->anonymous_proc_lits, hash_pointer(expr));
+
+		if (expr->kind == AstNode_ProcLit) {
+			found = map_get(&m->anonymous_proc_lits, hash_pointer(expr));
+		} else {
+			GB_ASSERT(expr->kind == AstNode_Ident);
+			Entity *e = entity_of_ident(m->info, expr);
+			GB_ASSERT(e != nullptr);
+			found = map_get(&m->values, hash_entity(e));
+		}
 		GB_ASSERT(found != nullptr);
 		irValue *val = *found;
 		ir_print_value(f, m, val, type);