Browse Source

Refactor default parameter values

gingerBill 7 years ago
parent
commit
60711dd355
4 changed files with 110 additions and 48 deletions
  1. 6 17
      src/check_expr.cpp
  2. 27 10
      src/check_type.cpp
  3. 18 4
      src/entity.cpp
  4. 59 17
      src/ir.cpp

+ 6 - 17
src/check_expr.cpp

@@ -4168,9 +4168,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 				}
 
 				if (e->kind == Entity_Variable) {
-					if (e->Variable.default_value.kind != ExactValue_Invalid ||
-					    e->Variable.default_is_nil ||
-					    e->Variable.default_is_location) {
+					if (e->Variable.param_value.kind != ParameterValue_Invalid) {
 						param_count--;
 						continue;
 					}
@@ -4190,9 +4188,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 			}
 
 			if (e->kind == Entity_Variable) {
-				if (e->Variable.default_value.kind != ExactValue_Invalid ||
-				    e->Variable.default_is_nil ||
-				    e->Variable.default_is_location) {
+				if (e->Variable.param_value.kind != ParameterValue_Invalid) {
 					param_count_excluding_defaults--;
 					continue;
 				}
@@ -4442,10 +4438,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 				continue;
 			}
 			if (e->kind == Entity_Variable) {
-				if (e->Variable.default_value.kind != ExactValue_Invalid) {
-					score += assign_score_function(1);
-					continue;
-				} else if (e->Variable.default_is_nil) {
+				if (e->Variable.param_value.kind != ParameterValue_Invalid) {
 					score += assign_score_function(1);
 					continue;
 				}
@@ -5218,8 +5211,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 	case_ast_node(i, Implicit, node)
 		switch (i->kind) {
 		case Token_context:
-			if (c->proc_name.len == 0) {
-				error(node, "'context' is only allowed within procedures");
+			if (c->proc_name.len == 0 && c->curr_proc_sig == nullptr) {
+				error(node, "'context' is only allowed within procedures %p", c->curr_proc_decl);
 				return kind;
 			}
 
@@ -5500,11 +5493,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 				for (isize i = min_field_count-1; i >= 0; i--) {
 					Entity *e = t->Struct.fields[i];
 					GB_ASSERT(e->kind == Entity_Variable);
-					if (e->Variable.default_is_nil) {
-						min_field_count--;
-					} else if (e->Variable.default_is_undef) {
-						min_field_count--;
-					} else if (e->Variable.default_value.kind != ExactValue_Invalid) {
+					if (e->Variable.param_value.kind != ParameterValue_Invalid) {
 						min_field_count--;
 					} else {
 						break;

+ 27 - 10
src/check_type.cpp

@@ -1065,9 +1065,14 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is
 				}
 
 				param = alloc_entity_param(scope, name->Ident.token, type, is_using, is_in);
-				param->Variable.default_value = value;
-				param->Variable.default_is_nil = default_is_nil;
-				param->Variable.default_is_location = default_is_location;
+				if (default_is_nil) {
+					param->Variable.param_value.kind = ParameterValue_Nil;
+				} else if (default_is_location) {
+					param->Variable.param_value.kind = ParameterValue_Location;
+				} else if (value.kind != ExactValue_Invalid) {
+					param->Variable.param_value.kind = ParameterValue_Constant;
+					param->Variable.param_value.value = value;
+				}
 			}
 			if (p->flags&FieldFlag_no_alias) {
 				param->flags |= EntityFlag_NoAlias;
@@ -1194,8 +1199,12 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
 			Token token = ast_token(field->type);
 			token.string = str_lit("");
 			Entity *param = alloc_entity_param(scope, token, type, false, false);
-			param->Variable.default_value = value;
-			param->Variable.default_is_nil = default_is_nil;
+			if (default_is_nil) {
+				param->Variable.param_value.kind = ParameterValue_Nil;
+			} else if (value.kind != ExactValue_Invalid) {
+				param->Variable.param_value.kind = ParameterValue_Constant;
+				param->Variable.param_value.value = value;
+			}
 			array_add(&variables, param);
 		} else {
 			for_array(j, field->names) {
@@ -1218,8 +1227,12 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
 
 				Entity *param = alloc_entity_param(scope, token, type, false, false);
 				param->flags |= EntityFlag_Result;
-				param->Variable.default_value = value;
-				param->Variable.default_is_nil = default_is_nil;
+				if (default_is_nil) {
+					param->Variable.param_value.kind = ParameterValue_Nil;
+				} else if (value.kind != ExactValue_Invalid) {
+					param->Variable.param_value.kind = ParameterValue_Constant;
+					param->Variable.param_value.value = value;
+				}
 				array_add(&variables, param);
 				add_entity(ctx->checker, scope, name, param);
 			}
@@ -1465,9 +1478,13 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 	if (param_count > 0) {
 		for_array(i, params->Tuple.variables) {
 			Entity *param = params->Tuple.variables[i];
-			if (param->kind == Entity_Variable && param->Variable.default_value.kind == ExactValue_Procedure) {
-				type->Proc.has_proc_default_values = true;
-				break;
+			if (param->kind == Entity_Variable) {
+				ParameterValue pv = param->Variable.param_value;
+				if (pv.kind == ParameterValue_Constant &&
+				    pv.value.kind == ExactValue_Procedure) {
+					type->Proc.has_proc_default_values = true;
+					break;
+				}
 			}
 		}
 	}

+ 18 - 4
src/entity.cpp

@@ -56,6 +56,19 @@ enum EntityState {
 };
 
 
+enum ParameterValueKind {
+	ParameterValue_Invalid,
+	ParameterValue_Constant,
+	ParameterValue_Nil,
+	ParameterValue_Location,
+};
+
+struct ParameterValue {
+	ParameterValueKind kind;
+	ExactValue value;
+};
+
+
 // An Entity is a named "thing" in the language
 struct Entity {
 	EntityKind  kind;
@@ -84,7 +97,9 @@ struct Entity {
 		struct {
 			i32        field_index;
 			i32        field_src_index;
-			ExactValue default_value;
+
+			ParameterValue param_value;
+
 			String     thread_local_model;
 			Entity *   foreign_library;
 			Ast *  foreign_library_ident;
@@ -93,9 +108,8 @@ struct Entity {
 			bool       is_foreign;
 			bool       is_export;
 
-			bool       default_is_nil;
-			bool       default_is_undef;
-			bool       default_is_location;
+			// bool       default_is_nil;
+			// bool       default_is_location;
 			bool       is_immutable;
 		} Variable;
 		struct {

+ 59 - 17
src/ir.cpp

@@ -5348,10 +5348,17 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 				} else {
 					GB_ASSERT(e->kind == Entity_Variable);
 					if (args[i] == nullptr) {
-						if (e->Variable.default_value.kind != ExactValue_Invalid) {
-							args[i] = ir_value_constant(e->type, e->Variable.default_value);
-						} else {
+						switch (e->Variable.param_value.kind) {
+						case ParameterValue_Constant:
+							args[i] = ir_value_constant(e->type, e->Variable.param_value.value);
+							break;
+						case ParameterValue_Nil:
 							args[i] = ir_value_nil(e->type);
+							break;
+						case ParameterValue_Location:
+							// args[i] =
+							GB_PANIC("TODO ParameterValue_Location");
+							break;
 						}
 					} else {
 						args[i] = ir_emit_conv(proc, args[i], e->type);
@@ -5434,12 +5441,17 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 				while (arg_index < end) {
 					Entity *e = param_tuple->variables[arg_index];
 					GB_ASSERT(e->kind == Entity_Variable);
-					if (e->Variable.default_value.kind != ExactValue_Invalid) {
-						args[arg_index++] = ir_value_constant(e->type, e->Variable.default_value);
-					} else if (e->Variable.default_is_location) {
-						args[arg_index++] = ir_emit_source_code_location(proc, proc_name, pos);
-					} else {
+
+					switch (e->Variable.param_value.kind) {
+					case ParameterValue_Constant:
+						args[arg_index++] = ir_value_constant(e->type, e->Variable.param_value.value);
+						break;
+					case ParameterValue_Nil:
 						args[arg_index++] = ir_value_nil(e->type);
+						break;
+					case ParameterValue_Location:
+						args[arg_index++] = ir_emit_source_code_location(proc, proc_name, pos);
+						break;
 					}
 				}
 			}
@@ -5521,12 +5533,16 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 		if (variadic && variadic_index+1 < param_count) {
 			for (isize i = variadic_index+1; i < param_count; i++) {
 				Entity *e = param_tuple->variables[i];
-				if (e->Variable.default_value.kind != ExactValue_Invalid) {
-					args[i] = ir_value_constant(e->type, e->Variable.default_value);
-				} else if (e->Variable.default_is_location) {
-					args[i] = ir_emit_source_code_location(proc, proc_name, pos);
-				} else {
+				switch (e->Variable.param_value.kind) {
+				case ParameterValue_Constant:
+					args[i] = ir_value_constant(e->type, e->Variable.param_value.value);
+					break;
+				case ParameterValue_Nil:
 					args[i] = ir_value_nil(e->type);
+					break;
+				case ParameterValue_Location:
+					args[i] = ir_emit_source_code_location(proc, proc_name, pos);
+					break;
 				}
 			}
 		}
@@ -7602,8 +7618,20 @@ void ir_begin_procedure_body(irProcedure *proc) {
 			if (e->token.string != "") {
 				GB_ASSERT(!is_blank_ident(e->token));
 				irValue *res = ir_add_local(proc, e, e->identifier, true);
-				if (e->Variable.default_value.kind != ExactValue_Invalid) {
-					irValue *c = ir_value_constant(e->type, e->Variable.default_value);
+
+				irValue *c = nullptr;
+				switch (e->Variable.param_value.kind) {
+				case ParameterValue_Constant:
+					c = ir_value_constant(e->type, e->Variable.param_value.value);
+					break;
+				case ParameterValue_Nil:
+					c = ir_value_nil(e->type);
+					break;
+				case ParameterValue_Location:
+					GB_PANIC("ParameterValue_Location");
+					break;
+				}
+				if (c != nullptr) {
 					ir_emit_store(proc, res, c);
 				}
 			}
@@ -7704,8 +7732,22 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
 		for_array(i, p->params->Tuple.variables) {
 			Entity *f = p->params->Tuple.variables[i];
 			if (f->kind == Entity_Variable) {
-				if (f->Variable.default_value.kind == ExactValue_Procedure) {
-					Ast *expr = f->Variable.default_value.value_procedure;
+				ParameterValue pv = f->Variable.param_value;
+				if (pv.kind ==  ParameterValue_Constant && pv.value.kind == ExactValue_Procedure) {
+					Ast *expr = f->Variable.param_value.value.value_procedure;
+					GB_ASSERT(expr != nullptr);
+					if (expr->kind == Ast_ProcLit) {
+						ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
+					}
+				}
+			}
+		}
+		for_array(i, p->results->Tuple.variables) {
+			Entity *f = p->results->Tuple.variables[i];
+			if (f->kind == Entity_Variable) {
+				ParameterValue pv = f->Variable.param_value;
+				if (pv.kind ==  ParameterValue_Constant && pv.value.kind == ExactValue_Procedure) {
+					Ast *expr = f->Variable.param_value.value.value_procedure;
 					GB_ASSERT(expr != nullptr);
 					if (expr->kind == Ast_ProcLit) {
 						ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);