Browse Source

Code clean up of call arguments

Ginger Bill 9 years ago
parent
commit
fee504636f
4 changed files with 100 additions and 140 deletions
  1. 1 8
      code/demo.odin
  2. 95 124
      src/checker/expr.cpp
  3. 1 4
      src/checker/stmt.cpp
  4. 3 4
      src/codegen/ssa.cpp

+ 1 - 8
code/demo.odin

@@ -5,12 +5,5 @@
 #import "game.odin"
 #import "game.odin"
 
 
 main :: proc() {
 main :: proc() {
-	Vector3 :: struct {
-		x, y, z: f32
-	}
-	Entity :: struct {
-		guid:     u64
-		position: Vector3
-	}
-
+	fmt.println("Hellope")
 }
 }

+ 95 - 124
src/checker/expr.cpp

@@ -85,10 +85,13 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 		return true;
 		return true;
 	}
 	}
 
 
-	if (is_type_pointer(dst) && is_type_rawptr(src)) {
-	    return true;
-	}
+	// ^T <- rawptr
+	// TODO(bill): Should C-style (not C++) pointer cast be allowed?
+	// if (is_type_pointer(dst) && is_type_rawptr(src)) {
+	    // return true;
+	// }
 
 
+	// rawptr <- ^T
 	if (is_type_rawptr(dst) && is_type_pointer(src)) {
 	if (is_type_rawptr(dst) && is_type_pointer(src)) {
 	    return true;
 	    return true;
 	}
 	}
@@ -121,7 +124,7 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 		return true;
 		return true;
 	}
 	}
 
 
-	if (is_argument) {
+	if (true || is_argument) {
 		// NOTE(bill): Polymorphism for subtyping
 		// NOTE(bill): Polymorphism for subtyping
 		if (check_is_assignable_to_using_subtype(type, src)) {
 		if (check_is_assignable_to_using_subtype(type, src)) {
 			return true;
 			return true;
@@ -224,16 +227,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 	defer (map_destroy(&entity_map));
 	defer (map_destroy(&entity_map));
 
 
 	isize other_field_index = 0;
 	isize other_field_index = 0;
-
 	Entity *using_index_expr = NULL;
 	Entity *using_index_expr = NULL;
 
 
+	struct Delay {
+		Entity *e;
+		AstNode *t;
+	};
+	gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
+	gbArray(Delay) delayed_type;  gb_array_init(delayed_type,  gb_heap_allocator());
+	defer (gb_array_free(delayed_const));
+	defer (gb_array_free(delayed_type));
 
 
-	// TODO(bill): Random declarations with DeclInfo
-#if 0
-	Entity *e;
-	DeclInfo *d;d
-	check_entity_decl(c, e, d, NULL);
-#endif
 	gb_for_array(decl_index, decls) {
 	gb_for_array(decl_index, decls) {
 		AstNode *decl = decls[decl_index];
 		AstNode *decl = decls[decl_index];
 		if (decl->kind == AstNode_ConstDecl) {
 		if (decl->kind == AstNode_ConstDecl) {
@@ -252,7 +256,9 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 				Token name_token = name->Ident;
 				Token name_token = name->Ident;
 				Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, NULL, v);
 				Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, NULL, v);
 				entities[entity_index++] = e;
 				entities[entity_index++] = e;
-				check_const_decl(c, e, cd->type, value);
+
+				Delay delay = {e, cd->type};
+				gb_array_append(delayed_const, delay);
 			}
 			}
 
 
 			isize lhs_count = gb_array_count(cd->names);
 			isize lhs_count = gb_array_count(cd->names);
@@ -288,8 +294,8 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 			Token name_token = td->name->Ident;
 			Token name_token = td->name->Ident;
 
 
 			Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
 			Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL);
-			add_entity(c, c->context.scope, td->name, e);
-			check_type_decl(c, e, td->type, NULL, NULL);
+			Delay delay = {e, td->type};
+			gb_array_append(delayed_type, delay);
 
 
 			if (name_token.string == "_") {
 			if (name_token.string == "_") {
 				other_fields[other_field_index++] = e;
 				other_fields[other_field_index++] = e;
@@ -302,10 +308,17 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 					map_set(&entity_map, key, e);
 					map_set(&entity_map, key, e);
 					other_fields[other_field_index++] = e;
 					other_fields[other_field_index++] = e;
 				}
 				}
+				add_entity(c, c->context.scope, td->name, e);
 				add_entity_use(c, td->name, e);
 				add_entity_use(c, td->name, e);
 			}
 			}
 		}
 		}
+	}
 
 
+	gb_for_array(i, delayed_type) {
+		check_const_decl(c, delayed_type[i].e, delayed_type[i].t, NULL);
+	}
+	gb_for_array(i, delayed_const) {
+		check_type_decl(c, delayed_const[i].e, delayed_const[i].t, NULL, NULL);
 	}
 	}
 
 
 	if (node->kind == AstNode_UnionType) {
 	if (node->kind == AstNode_UnionType) {
@@ -1536,18 +1549,15 @@ b32 check_is_castable_to(Checker *c, Operand *operand, Type *y) {
 	}
 	}
 
 
 	// Cast between pointers
 	// Cast between pointers
-	if (is_type_pointer(xb)) {
-		if (is_type_pointer(yb))
+	if (is_type_pointer(xb) && is_type_pointer(yb)) {
 			return true;
 			return true;
 	}
 	}
 
 
 	// (u)int <-> pointer
 	// (u)int <-> pointer
-	if (is_type_int_or_uint(xb) && !is_type_untyped(xb)) {
-		if (is_type_pointer(yb))
+	if (is_type_int_or_uint(xb) && is_type_rawptr(yb)) {
 			return true;
 			return true;
 	}
 	}
-	if (is_type_pointer(xb)) {
-		if (is_type_int_or_uint(yb) && !is_type_untyped(yb))
+	if (is_type_rawptr(xb) && is_type_int_or_uint(yb)) {
 			return true;
 			return true;
 	}
 	}
 
 
@@ -2961,137 +2971,98 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 	GB_ASSERT(proc_type->kind == Type_Proc);
 	GB_ASSERT(proc_type->kind == Type_Proc);
 	ast_node(ce, CallExpr, call);
 	ast_node(ce, CallExpr, call);
 
 
-
-	isize error_code = 0;
-	isize param_index = 0;
 	isize param_count = 0;
 	isize param_count = 0;
 	b32 variadic = proc_type->Proc.variadic;
 	b32 variadic = proc_type->Proc.variadic;
 	b32 vari_expand = (ce->ellipsis.pos.line != 0);
 	b32 vari_expand = (ce->ellipsis.pos.line != 0);
 
 
-	if (proc_type->Proc.params) {
+	if (proc_type->Proc.params != NULL) {
 		param_count = proc_type->Proc.params->Tuple.variable_count;
 		param_count = proc_type->Proc.params->Tuple.variable_count;
+		if (variadic) {
+			param_count--;
+		}
 	}
 	}
 
 
-	if (ce->ellipsis.pos.line != 0) {
-		if (!variadic) {
-			error(ce->ellipsis,
-			      "Cannot use `..` in call to a non-variadic procedure: `%.*s`",
-			      LIT(ce->proc->Ident.string));
-			return;
-		}
+	if (vari_expand && !variadic) {
+		error(ce->ellipsis,
+		      "Cannot use `..` in call to a non-variadic procedure: `%.*s`",
+		      LIT(ce->proc->Ident.string));
+		return;
 	}
 	}
 
 
-	if (gb_array_count(ce->args) == 0) {
-		if (variadic && param_count-1 == 0)
-			return;
-		if (param_count == 0)
-			return;
+	if (gb_array_count(ce->args) == 0 && param_count == 0) {
+		return;
 	}
 	}
 
 
-	// TODO(bill): Completely redo this entire code.
-	// It's from when I used linked lists instead of arrays in the parser
+	isize operand_count = 0;
+	gbArray(Operand) operands;
+	gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count);
+	defer (gb_array_free(operands));
 
 
-	if (gb_array_count(ce->args) > param_count && !variadic) {
-		error_code = +1;
-	} else {
-		Entity **sig_params = proc_type->Proc.params->Tuple.variables;
-		gb_for_array(arg_index, ce->args) {
-			check_multi_expr(c, operand, ce->args[arg_index]);
-			if (operand->mode == Addressing_Invalid) {
-				param_index++;
-				continue;
+	gb_for_array(i, ce->args) {
+		Operand o = {};
+		check_multi_expr(c, &o, ce->args[i]);
+		if (o.type->kind != Type_Tuple) {
+			gb_array_append(operands, o);
+		} else {
+			auto *tuple = &o.type->Tuple;
+			if (variadic && i >= param_count) {
+				error(ast_node_token(ce->args[i]),
+				      "`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
+				operand->mode = Addressing_Invalid;
+				return;
 			}
 			}
-			if (operand->type->kind != Type_Tuple) {
-				check_not_tuple(c, operand);
-				isize index = param_index;
-				b32 end_variadic = false;
-				b32 variadic_expand = false;
-				if (variadic && param_index >= param_count-1) {
-					index = param_count-1;
-					end_variadic = true;
-					if (vari_expand) {
-						variadic_expand = true;
-						if (param_index != param_count-1) {
-							error(ast_node_token(operand->expr),
-							      "`..` in a variadic procedure can only have one variadic argument at the end");
-							break;
-						}
-					}
-				}
-				Type *arg_type = sig_params[index]->type;
-				if (end_variadic && is_type_slice(arg_type)) {
-					if (variadic_expand) {
-						check_assignment(c, operand, arg_type, make_string("argument"), true);
-					} else {
-						arg_type = base_type(arg_type)->Slice.elem;
-						check_assignment(c, operand, arg_type, make_string("argument"), true);
-					}
-				} else {
-					check_assignment(c, operand, arg_type, make_string("argument"), true);
-				}
-				param_index++;
-			} else {
-				auto *tuple = &operand->type->Tuple;
-				isize i = 0;
-				for (;
-				     i < tuple->variable_count && (param_index < param_count && !variadic);
-				     i++) {
-					Entity *e = tuple->variables[i];
-					operand->type = e->type;
-					operand->mode = Addressing_Value;
-					check_not_tuple(c, operand);
-					isize index = param_index;
-					b32 end_variadic = false;
-					if (variadic && param_index >= param_count-1) {
-						index = param_count-1;
-						end_variadic = true;
-						if (vari_expand) {
-							error(ast_node_token(operand->expr),
-							      "`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
-							goto end;
-						}
-					}
-					Type *arg_type = sig_params[index]->type;
-					if (end_variadic && is_type_slice(arg_type)) {
-						arg_type = base_type(arg_type)->Slice.elem;
-					}
-					check_assignment(c, operand, arg_type, make_string("argument"), true);
-					param_index++;
-				}
-
-			end:
-
-				if (i < tuple->variable_count && param_index == param_count) {
-					error_code = +1;
-					break;
-				}
+			for (isize j = 0; j < tuple->variable_count; j++) {
+				o.type = tuple->variables[j]->type;
+				gb_array_append(operands, o);
 			}
 			}
-
-			if (!variadic && param_index >= param_count)
-				break;
-		}
-
-
-		if ((!variadic && param_index < param_count) ||
-		    (variadic  && param_index < param_count-1)) {
-			error_code = -1;
 		}
 		}
 	}
 	}
 
 
+	operand_count = gb_array_count(operands);
+	i32 error_code = 0;
+	if (operand_count < param_count) {
+		error_code = -1;
+	} else if (!variadic && operand_count > param_count) {
+		error_code = +1;
+	}
 	if (error_code != 0) {
 	if (error_code != 0) {
-		char *err_fmt = "";
+		char *err_fmt = "Too many arguments for `%s`, expected %td arguments";
 		if (error_code < 0) {
 		if (error_code < 0) {
 			err_fmt = "Too few arguments for `%s`, expected %td arguments";
 			err_fmt = "Too few arguments for `%s`, expected %td arguments";
-		} else {
-			err_fmt = "Too many arguments for `%s`, expected %td arguments";
 		}
 		}
 
 
 		gbString proc_str = expr_to_string(ce->proc);
 		gbString proc_str = expr_to_string(ce->proc);
 		error(ast_node_token(call), err_fmt, proc_str, param_count);
 		error(ast_node_token(call), err_fmt, proc_str, param_count);
 		gb_string_free(proc_str);
 		gb_string_free(proc_str);
-
 		operand->mode = Addressing_Invalid;
 		operand->mode = Addressing_Invalid;
 	}
 	}
+
+	GB_ASSERT(proc_type->Proc.params != NULL);
+	Entity **sig_params = proc_type->Proc.params->Tuple.variables;
+	for (isize i = 0; i < param_count; i++) {
+		Type *arg_type = sig_params[i]->type;
+		check_assignment(c, &operands[i], arg_type, make_string("argument"), true);
+	}
+
+	if (variadic) {
+		b32 variadic_expand = false;
+		Type *slice = sig_params[param_count]->type;
+		Type *elem = base_type(slice)->Slice.elem;
+		Type *t = elem;
+		for (isize i = param_count; i < operand_count; i++) {
+			Operand *o = &operands[i];
+			if (vari_expand) {
+				variadic_expand = true;
+				t = slice;
+				if (i != param_count) {
+					error(ast_node_token(o->expr),
+					      "`..` in a variadic procedure can only have one variadic argument at the end");
+					break;
+				}
+			}
+			check_assignment(c, o, t, make_string("argument"), true);
+		}
+	}
 }
 }
 
 
 
 

+ 1 - 4
src/checker/stmt.cpp

@@ -11,8 +11,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags);
 void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
 void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
 
 
 void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
-	// TODO(bill): Allow declaration (expect variable) in any order
-	// even within a procedure
 	struct Delay {
 	struct Delay {
 		Entity *e;
 		Entity *e;
 		DeclInfo *d;
 		DeclInfo *d;
@@ -57,7 +55,6 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 		case_ast_node(td, TypeDecl, node);
 		case_ast_node(td, TypeDecl, node);
 			Entity *e = make_entity_type_name(c->allocator, c->context.scope, td->name->Ident, NULL);
 			Entity *e = make_entity_type_name(c->allocator, c->context.scope, td->name->Ident, NULL);
 			e->identifier = td->name;
 			e->identifier = td->name;
-			add_entity(c, c->context.scope, td->name, e);
 
 
 			DeclInfo *d = make_declaration_info(c->allocator, e->scope);
 			DeclInfo *d = make_declaration_info(c->allocator, e->scope);
 			d->type_expr = td->type;
 			d->type_expr = td->type;
@@ -339,7 +336,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 
 
 	// TODO(bill): Do not use heap allocation here if I can help it
 	// TODO(bill): Do not use heap allocation here if I can help it
 	gbArray(Operand) operands;
 	gbArray(Operand) operands;
-	gb_array_init(operands, gb_heap_allocator());
+	gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count);
 	defer (gb_array_free(operands));
 	defer (gb_array_free(operands));
 
 
 	gb_for_array(i, inits) {
 	gb_for_array(i, inits) {

+ 3 - 4
src/codegen/ssa.cpp

@@ -1799,7 +1799,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 
 
 	// NOTE(bill): This has to be done beofre `Pointer <-> Pointer` as it's
 	// NOTE(bill): This has to be done beofre `Pointer <-> Pointer` as it's
 	// subtype polymorphism casting
 	// subtype polymorphism casting
-	if (is_argument) {
+	if (true || is_argument) {
 		Type *sb = base_type(type_deref(src));
 		Type *sb = base_type(type_deref(src));
 		b32 src_is_ptr = src != sb;
 		b32 src_is_ptr = src != sb;
 		if (is_type_struct(sb)) {
 		if (is_type_struct(sb)) {
@@ -1924,8 +1924,9 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
 
 
 	Type *src = base_type(src_type);
 	Type *src = base_type(src_type);
 	Type *dst = base_type(t);
 	Type *dst = base_type(t);
-	if (are_types_identical(t, src_type))
+	if (are_types_identical(t, src_type)) {
 		return value;
 		return value;
+	}
 
 
 	i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
 	i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
 	i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
 	i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
@@ -1950,8 +1951,6 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
 	Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
 	Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
 	ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
 	ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
 
 
-	// IMPORTANT TODO(bill): THIS ONLY DOES ONE LAYER DEEP!!! FUCKING HELL THIS IS NOT WHAT I SIGNED UP FOR!
-
 	i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
 	i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
 	ssaValue *offset = ssa_make_const_int(allocator, -offset_);
 	ssaValue *offset = ssa_make_const_int(allocator, -offset_);
 	ssaValue *head = ssa_emit_ptr_offset(proc, bytes, offset);
 	ssaValue *head = ssa_emit_ptr_offset(proc, bytes, offset);