Browse Source

Fix ||= and &&=

gingerBill 6 years ago
parent
commit
ab0afa548b
4 changed files with 75 additions and 37 deletions
  1. 8 0
      core/sort/sort.odin
  2. 52 28
      src/check_expr.cpp
  3. 13 6
      src/ir.cpp
  4. 2 3
      src/tokenizer.cpp

+ 8 - 0
core/sort/sort.odin

@@ -189,6 +189,14 @@ merge_sort :: proc(array: $A/[]$T) {
 }
 
 
+compare_bools :: proc(a, b: bool) -> int {
+	switch {
+	case !a && b: return -1;
+	case a && !b: return +1;
+	}
+	return 0;
+}
+
 
 compare_ints :: proc(a, b: int) -> int {
 	switch delta := a - b; {

+ 52 - 28
src/check_expr.cpp

@@ -4440,8 +4440,8 @@ bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
 			// NOTE(bill): override DeclInfo for dependency
 			Entity *e = lhs[tuple_index];
 			if (e != nullptr) {
-				DeclInfo *decl = decl_info_of_entity(e);
-				if (decl) c->decl = decl;
+				// DeclInfo *decl = decl_info_of_entity(e);
+				// if (decl) c->decl = decl;
 				type_hint = e->type;
 				if (e->flags & EntityFlag_Ellipsis) {
 					GB_ASSERT(is_type_slice(e->type));
@@ -4449,13 +4449,12 @@ bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
 					type_hint = e->type->Slice.elem;
 				}
 			}
-		}
-		if (lhs != nullptr && tuple_index >= lhs_count && is_variadic) {
+		} else if (lhs != nullptr && tuple_index >= lhs_count && is_variadic) {
 			// NOTE(bill): override DeclInfo for dependency
 			Entity *e = lhs[lhs_count-1];
 			if (e != nullptr) {
-				DeclInfo *decl = decl_info_of_entity(e);
-				if (decl) c->decl = decl;
+				// DeclInfo *decl = decl_info_of_entity(e);
+				// if (decl) c->decl = decl;
 				type_hint = e->type;
 				if (e->flags & EntityFlag_Ellipsis) {
 					GB_ASSERT(is_type_slice(e->type));
@@ -4930,6 +4929,40 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 	return err;
 }
 
+Entity **populate_proc_parameter_list(CheckerContext *c, Type *proc_type, isize *lhs_count_, bool *is_variadic) {
+	Entity **lhs = nullptr;
+	isize lhs_count = -1;
+
+	if (proc_type == nullptr) {
+		return nullptr;
+	}
+
+	GB_ASSERT(is_type_proc(proc_type));
+	TypeProc *pt = &base_type(proc_type)->Proc;
+	*is_variadic = pt->variadic;
+
+	if (!pt->is_polymorphic || pt->is_poly_specialized) {
+		if (pt->params != nullptr) {
+			lhs = pt->params->Tuple.variables.data;
+			lhs_count = pt->params->Tuple.variables.count;
+		}
+	} else {
+		// NOTE(bill): Create 'lhs' list in order to ignore parameters which are polymorphic
+		lhs_count = pt->params->Tuple.variables.count;
+		lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count);
+		for_array(i, pt->params->Tuple.variables) {
+			Entity *e = pt->params->Tuple.variables[i];
+			if (!is_type_polymorphic(e->type)) {
+				lhs[i] = e;
+			}
+		}
+	}
+
+	if (lhs_count_) *lhs_count_ = lhs_count;
+
+	return lhs;
+}
+
 CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type *proc_type, Ast *call) {
 	ast_node(ce, CallExpr, call);
 
@@ -4960,28 +4993,11 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 		isize lhs_count = -1;
 		bool is_variadic = false;
 		if (proc_type != nullptr && is_type_proc(proc_type)) {
-			TypeProc *pt = &base_type(proc_type)->Proc;
-			is_variadic = pt->variadic;
-
-			if (!pt->is_polymorphic || pt->is_poly_specialized) {
-				if (pt->params != nullptr) {
-					lhs = pt->params->Tuple.variables.data;
-					lhs_count = pt->params->Tuple.variables.count;
-				}
-			} else {
-				// NOTE(bill): Create 'lhs' list in order to ignore parameters which are polymorphic
-				lhs_count = pt->params->Tuple.variables.count;
-				lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count);
-				for_array(i, pt->params->Tuple.variables) {
-					Entity *e = pt->params->Tuple.variables[i];
-					if (!is_type_polymorphic(e->type)) {
-						lhs[i] = e;
-					}
-				}
-			}
+			lhs = populate_proc_parameter_list(c, proc_type, &lhs_count, &is_variadic);
+		}
+		if (operand->mode != Addressing_ProcGroup) {
+			check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, is_variadic);
 		}
-
-		check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, is_variadic);
 	}
 
 	if (operand->mode == Addressing_ProcGroup) {
@@ -4998,6 +5014,13 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 
 			Entity *e = procs[0];
 
+			Entity **lhs = nullptr;
+			isize lhs_count = -1;
+			bool is_variadic = false;
+			lhs = populate_proc_parameter_list(c, e->type, &lhs_count, &is_variadic);
+			check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, is_variadic);
+
+
 			CallArgumentData data = {};
 			CallArgumentError err = call_checker(c, call, e->type, e, operands, CallArgumentMode_ShowErrors, &data);
 			Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
@@ -5006,6 +5029,8 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 			return data;
 		}
 
+		check_unpack_arguments(c, nullptr, -1, &operands, ce->args, false, false);
+
 		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
 		isize               valid_count    = 0;
 		defer (gb_free(heap_allocator(), valids));
@@ -5015,7 +5040,6 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 
 		for_array(i, procs) {
 			Entity *p = procs[i];
-			check_entity_decl(c, p, nullptr, nullptr);
 			Type *pt = base_type(p->type);
 			if (pt != nullptr && is_type_proc(pt)) {
 				CallArgumentError err = CallArgumentError_None;

+ 13 - 6
src/ir.cpp

@@ -7687,6 +7687,7 @@ void ir_build_assign_op(irProcedure *proc, irAddr const &lhs, irValue *value, To
 	} else {
 		change = ir_emit_conv(proc, value, type);
 	}
+
 	irValue *new_value = ir_emit_arith(proc, op, old_value, change, type);
 	ir_addr_store(proc, lhs, new_value);
 }
@@ -8394,14 +8395,20 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 			// +=, -=, etc
 			i32 op = cast(i32)as->op.kind;
 			op += Token_Add - Token_AddEq; // Convert += to +
-			irAddr lhs = ir_build_addr(proc, as->lhs[0]);
-			irValue *value = ir_build_expr(proc, as->rhs[0]);
-			ir_build_assign_op(proc, lhs, value, cast(TokenKind)op);
-			break;
+			if (op == Token_CmpAnd || op == Token_CmpOr) {
+				Type *type = as->lhs[0]->tav.type;
+				irValue *new_value = ir_emit_logical_binary_expr(proc, cast(TokenKind)op, as->lhs[0], as->rhs[0], type);
+
+				irAddr lhs = ir_build_addr(proc, as->lhs[0]);
+				ir_addr_store(proc, lhs, new_value);
+			} else {
+				irAddr lhs = ir_build_addr(proc, as->lhs[0]);
+				irValue *value = ir_build_expr(proc, as->rhs[0]);
+				ir_build_assign_op(proc, lhs, value, cast(TokenKind)op);
+			}
+			return;
 		}
 		}
-
-		gb_temp_arena_memory_end(tmp);
 	case_end;
 
 	case_ast_node(es, ExprStmt, node);

+ 2 - 3
src/tokenizer.cpp

@@ -32,9 +32,8 @@ TOKEN_KIND(Token__OperatorBegin, ""), \
 	TOKEN_KIND(Token_AndNot,   "&~"), \
 	TOKEN_KIND(Token_Shl,      "<<"), \
 	TOKEN_KIND(Token_Shr,      ">>"), \
-\
-	TOKEN_KIND(Token_CmpAnd, "&&"), \
-	TOKEN_KIND(Token_CmpOr,  "||"), \
+	TOKEN_KIND(Token_CmpAnd,   "&&"), \
+	TOKEN_KIND(Token_CmpOr,    "||"), \
 \
 TOKEN_KIND(Token__AssignOpBegin, ""), \
 	TOKEN_KIND(Token_AddEq,    "+="), \