Browse Source

Fix demo and improve type hinting

gingerBill 7 years ago
parent
commit
e1e4a916a5
3 changed files with 83 additions and 53 deletions
  1. 24 52
      examples/demo/demo.odin
  2. 58 0
      src/check_expr.cpp
  3. 1 1
      src/check_stmt.cpp

+ 24 - 52
examples/demo/demo.odin

@@ -713,58 +713,30 @@ deprecated_attribute :: proc() {
 }
 
 bit_set_type :: proc() {
-	{
-		using Day :: enum {
-			Sunday,
-			Monday,
-			Tuesday,
-			Wednesday,
-			Thursday,
-			Friday,
-			Saturday,
-		}
-
-		Days :: distinct bit_set[Day];
-		WEEKEND :: Days{Sunday, Saturday};
-
-		d: Days;
-		d = Days{Sunday} | Days{Monday};
-		x := Tuesday;
-		e := d | WEEKEND;
-		e |= {Monday};
-		fmt.println(d, e);
-
-		ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
-		fmt.println(ok);
-		if Saturday in e {
-			fmt.println("Saturday in", e);
-		}
-	}
-	{
-		using Days :: bit_set {
-			Sunday,
-			Monday,
-			Tuesday,
-			Wednesday,
-			Thursday,
-			Friday,
-			Saturday,
-		}
-
-		WEEKEND :: Days{Sunday, Saturday};
-
-		d: Days;
-		d = Days{Sunday} | Days{Monday};
-		x := Tuesday;
-		e := d | WEEKEND;
-		e |= {Monday};
-		fmt.println(d, e);
-
-		ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
-		fmt.println(ok);
-		if Saturday in e {
-			fmt.println("Saturday in", e);
-		}
+	using Day :: enum {
+		Sunday,
+		Monday,
+		Tuesday,
+		Wednesday,
+		Thursday,
+		Friday,
+		Saturday,
+	}
+
+	Days :: distinct bit_set[Day];
+	WEEKEND :: Days{Sunday, Saturday};
+
+	d: Days;
+	d = Days{Sunday} | Days{Monday};
+	x := Tuesday;
+	e := d | WEEKEND;
+	e |= {Monday};
+	fmt.println(d, e);
+
+	ok := Saturday in e; // `in` is only allowed for `map` and `bit_set` types
+	fmt.println(ok);
+	if Saturday in e {
+		fmt.println("Saturday in", e);
 	}
 }
 

+ 58 - 0
src/check_expr.cpp

@@ -3711,6 +3711,64 @@ isize add_dependencies_from_unpacking(CheckerContext *c, Entity **lhs, isize lhs
 }
 
 
+void check_assignment_arguments(CheckerContext *ctx, Array<Operand> const &lhs, Array<Operand> *operands, Array<Ast *> const &rhs, bool allow_ok, bool *optional_ok_ = nullptr) {
+	bool optional_ok = false;
+	isize tuple_index = 0;
+	for_array(i, rhs) {
+		CheckerContext c_ = *ctx;
+		CheckerContext *c = &c_;
+
+		Operand o = {};
+
+		Type *type_hint = nullptr;
+
+		if (tuple_index < lhs.count) {
+			type_hint = lhs[tuple_index].type;
+		}
+
+		check_expr_base(c, &o, rhs[i], type_hint);
+		if (o.mode == Addressing_NoValue) {
+			error_operand_no_value(&o);
+			o.mode = Addressing_Invalid;
+		}
+
+		if (o.type == nullptr || o.type->kind != Type_Tuple) {
+			if (allow_ok && lhs.count == 2 && rhs.count == 1 &&
+			    (o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
+				Type *tuple = make_optional_ok_type(o.type);
+				add_type_and_value(&c->checker->info, o.expr, o.mode, tuple, o.value);
+
+				Operand val = o;
+				Operand ok = o;
+				val.mode = Addressing_Value;
+				ok.mode  = Addressing_Value;
+				ok.type  = t_bool;
+				array_add(operands, val);
+				array_add(operands, ok);
+
+				optional_ok = true;
+				tuple_index += 2;
+			} else {
+				array_add(operands, o);
+				tuple_index += 1;
+			}
+		} else {
+			TypeTuple *tuple = &o.type->Tuple;
+			for_array(j, tuple->variables) {
+				o.type = tuple->variables[j]->type;
+				array_add(operands, o);
+			}
+
+			isize count = tuple->variables.count;
+			tuple_index += 2;
+		}
+	}
+
+	if (optional_ok_) *optional_ok_ = optional_ok;
+}
+
+
+
 void check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Array<Ast *> const &rhs, bool allow_ok, bool *optional_ok_ = nullptr) {
 	bool optional_ok = false;
 	isize tuple_index = 0;

+ 1 - 1
src/check_stmt.cpp

@@ -1122,7 +1122,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 				}
 			}
 
-			check_unpack_arguments(ctx, nullptr, lhs_operands.count, &rhs_operands, as->rhs, true);
+			check_assignment_arguments(ctx, lhs_operands, &rhs_operands, as->rhs, true);
 
 			isize rhs_count = rhs_operands.count;
 			for_array(i, rhs_operands) {