Răsfoiți Sursa

Allow `$` in polymorphic record parameter fields (but disallow mixing)

gingerBill 4 ani în urmă
părinte
comite
08f7d3edbe
3 a modificat fișierele cu 23 adăugiri și 7 ștergeri
  1. 1 0
      core/odin/ast/ast.odin
  2. 12 4
      src/check_type.cpp
  3. 10 3
      src/parser.cpp

+ 1 - 0
core/odin/ast/ast.odin

@@ -562,6 +562,7 @@ Field_Flags_Struct :: Field_Flags{
 };
 Field_Flags_Record_Poly_Params :: Field_Flags{
 	.Typeid_Token,
+	.Default_Parameters,
 };
 Field_Flags_Signature :: Field_Flags{
 	.Ellipsis,

+ 12 - 4
src/check_type.cpp

@@ -152,10 +152,12 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array<Entity *> *fields
 
 		for_array(j, p->names) {
 			Ast *name = p->names[j];
-			if (!ast_node_expect(name, Ast_Ident)) {
+			if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) {
 				continue;
 			}
-
+			if (name->kind == Ast_PolyType) {
+				name = name->PolyType.type;
+			}
 			Token name_token = name->Ident.token;
 
 			Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index);
@@ -464,9 +466,12 @@ void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *node, Array<
 				Scope *scope = ctx->scope;
 				for_array(j, p->names) {
 					Ast *name = p->names[j];
-					if (!ast_node_expect(name, Ast_Ident)) {
+					if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) {
 						continue;
 					}
+					if (name->kind == Ast_PolyType) {
+						name = name->PolyType.type;
+					}
 					Entity *e = nullptr;
 
 					Token token = name->Ident.token;
@@ -680,9 +685,12 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
 				Scope *scope = ctx->scope;
 				for_array(j, p->names) {
 					Ast *name = p->names[j];
-					if (!ast_node_expect(name, Ast_Ident)) {
+					if (!ast_node_expect2(name, Ast_Ident, Ast_PolyType)) {
 						continue;
 					}
+					if (name->kind == Ast_PolyType) {
+						name = name->PolyType.type;
+					}
 					Entity *e = nullptr;
 
 					Token token = name->Ident.token;

+ 10 - 3
src/parser.cpp

@@ -490,6 +490,13 @@ bool ast_node_expect(Ast *node, AstKind kind) {
 	}
 	return true;
 }
+bool ast_node_expect2(Ast *node, AstKind kind0, AstKind kind1) {
+	if (node->kind != kind0 && node->kind != kind1) {
+		syntax_error(node, "Expected %.*s or %.*s, got %.*s", LIT(ast_strings[kind0]), LIT(ast_strings[kind1]), LIT(ast_strings[node->kind]));
+		return false;
+	}
+	return true;
+}
 
 Ast *ast_bad_expr(AstFile *f, Token begin, Token end) {
 	Ast *result = alloc_ast_node(f, Ast_BadExpr);
@@ -1863,9 +1870,9 @@ void check_polymorphic_params_for_type(AstFile *f, Ast *polymorphic_params, Toke
 		}
 		for_array(i, field->Field.names) {
 			Ast *name = field->Field.names[i];
-			if (name->kind == Ast_PolyType) {
-				syntax_error(name, "Polymorphic names are not needed for %.*s parameters", LIT(token.string));
-				return; // TODO(bill): Err multiple times or just the once?
+			if (name->kind != field->Field.names[0]->kind) {
+				syntax_error(name, "Mixture of polymorphic names using both $ and not for %.*s parameters", LIT(token.string));
+				return;
 			}
 		}
 	}