Browse Source

Constant polymorphic names

gingerBill 7 years ago
parent
commit
46b1868185
2 changed files with 46 additions and 5 deletions
  1. 17 1
      examples/demo/demo.odin
  2. 29 4
      src/check_type.cpp

+ 17 - 1
examples/demo/demo.odin

@@ -489,6 +489,23 @@ parametric_polymorphism :: proc() {
 		r = Error.Foo0;
 		fmt.println(r);
 	}
+
+	{ // Polymorphic names
+		foo :: proc($N: $I, $T: typeid) -> (res: [N]T) {
+			fmt.printf("Generating an array of type %v from the value %v of type %v\n",
+			           typeid_of(type_of(res)), N, typeid_of(I));
+			for i in 0..N-1 {
+				res[i] = i*i;
+			}
+			return;
+		}
+
+		T :: int;
+		array := foo(4, T);
+		for v, i in array {
+			assert(v == T(i*i));
+		}
+	}
 }
 
 
@@ -794,7 +811,6 @@ diverging_procedures :: proc() {
 	foo();
 }
 
-
 main :: proc() {
 	when true {
 		general_stuff();

+ 29 - 4
src/check_type.cpp

@@ -1467,7 +1467,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 				if (type != nullptr && type_expr->kind == Ast_TypeidType) {
 					is_type_param = true;
 				} else {
-					error(name, "Polymorphic names are not yet supported for non-typeid parameters");
+					if (param_value.kind != ParameterValue_Invalid)  {
+						error(default_value, "Constant parameters cannot have a default value");
+						param_value.kind = ParameterValue_Invalid;
+					}
 				}
 			}
 
@@ -1514,9 +1517,12 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 				param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved);
 				param->TypeName.is_type_alias = true;
 			} else {
+				ExactValue poly_const = {};
+
 				if (operands != nullptr && variables.count < operands->count) {
+
+					Operand op = (*operands)[variables.count];
 					if (is_type_polymorphic_type) {
-						Operand op = (*operands)[variables.count];
 						type = determine_type_from_polymorphic(ctx, type, op);
 						if (type == t_invalid) {
 							success = false;
@@ -1525,6 +1531,13 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 							is_type_polymorphic_type = false;
 						}
 					}
+					if (is_poly_name) {
+						if (op.mode == Addressing_Constant) {
+							poly_const = op.value;
+						} else {
+							success = false;
+						}
+					}
 				}
 
 				if (p->flags&FieldFlag_no_alias) {
@@ -1533,9 +1546,21 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 						p->flags &= ~FieldFlag_no_alias; // Remove the flag
 					}
 				}
+				if (is_poly_name) {
+					if (p->flags&FieldFlag_no_alias) {
+						error(name, "'#no_alias' can only be applied to non constant values");
+						p->flags &= ~FieldFlag_no_alias; // Remove the flag
+					}
+					if (p->flags&FieldFlag_auto_cast) {
+						error(name, "'auto_cast' can only be applied to variable fields");
+						p->flags &= ~FieldFlag_auto_cast;
+					}
 
-				param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
-				param->Variable.param_value = param_value;
+					param = alloc_entity_const_param(scope, name->Ident.token, type, poly_const, is_type_polymorphic(type));
+				} else {
+					param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
+					param->Variable.param_value = param_value;
+				}
 			}
 			if (p->flags&FieldFlag_no_alias) {
 				param->flags |= EntityFlag_NoAlias;