Bläddra i källkod

Ternary expression (removed if and block expression)

Ginger Bill 8 år sedan
förälder
incheckning
71100ed427
7 ändrade filer med 197 tillägg och 435 borttagningar
  1. 6 9
      code/demo.odin
  2. 10 2
      core/fmt.odin
  3. 25 205
      src/check_expr.c
  4. 0 11
      src/check_stmt.c
  5. 1 3
      src/checker.c
  6. 28 56
      src/ir.c
  7. 127 149
      src/parser.c

+ 6 - 9
code/demo.odin

@@ -9,18 +9,14 @@
 
 
 
 
 main :: proc() {
 main :: proc() {
-	x := type_info(int);
-	t1, ok := union_cast(^Type_Info.Integer)x;
-	_, ok = union_cast(^Type_Info.Integer)x;
-	t2 := union_cast(^Type_Info.Integer)x;
-
-
+	x: f32 = false ? 123 : 55;
+	fmt.println("Ternary:", x);
 /*
 /*
 /*
 /*
 	Version 0.1.1
 	Version 0.1.1
 
 
 	Added:
 	Added:
-	 * Dynamic Arrays `[...]Type`
+	 * Dynamic Arrays [dynamic]Type`
 	 * Dynamic Maps   `map[Key]Value`
 	 * Dynamic Maps   `map[Key]Value`
 	 * Dynamic array and map literals
 	 * Dynamic array and map literals
 	 * Custom struct alignemnt `struct #align 8 { bar: i8 }`
 	 * Custom struct alignemnt `struct #align 8 { bar: i8 }`
@@ -32,6 +28,7 @@ main :: proc() {
 	 * enum types have an implict `names` field, a []string of all the names in that enum
 	 * enum types have an implict `names` field, a []string of all the names in that enum
 	 * immutable variables are "completely immutable" - rules need a full explanation
 	 * immutable variables are "completely immutable" - rules need a full explanation
 	 * `slice_to_bytes` - convert any slice to a slice of bytes
 	 * `slice_to_bytes` - convert any slice to a slice of bytes
+	 * `union_cast` allows for optional ok check
 
 
 	Removed:
 	Removed:
 	 * Maybe/option types
 	 * Maybe/option types
@@ -101,7 +98,7 @@ main :: proc() {
 	}
 	}
 
 
 	{
 	{
-		x: [...]f64;
+		x: [dynamic]f64;
 		reserve(x, 16);
 		reserve(x, 16);
 		defer free(x);
 		defer free(x);
 		append(x, 2_000_000.500_000, 3, 5, 7);
 		append(x, 2_000_000.500_000, 3, 5, 7);
@@ -114,7 +111,7 @@ main :: proc() {
 	}
 	}
 
 
 	{
 	{
-		x := [...]f64{2_000_000.500_000, 3, 5, 7};
+		x := [dynamic]f64{2_000_000.500_000, 3, 5, 7};
 		defer free(x);
 		defer free(x);
 		fmt.println(x);
 		fmt.println(x);
 	}
 	}

+ 10 - 2
core/fmt.odin

@@ -116,7 +116,11 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
 		case ti == type_info(int):  buffer_write_string(buf, "int");
 		case ti == type_info(int):  buffer_write_string(buf, "int");
 		case ti == type_info(uint): buffer_write_string(buf, "uint");
 		case ti == type_info(uint): buffer_write_string(buf, "uint");
 		default:
 		default:
-			buffer_write_string(buf, if info.signed { give "i" } else { give "u"});
+			if info.signed {
+				buffer_write_string(buf, "i");
+			} else {
+				buffer_write_string(buf, "u");
+			}
 			fi := Fmt_Info{buf = buf};
 			fi := Fmt_Info{buf = buf};
 			fmt_int(^fi, cast(u64)(8*info.size), false, 'd');
 			fmt_int(^fi, cast(u64)(8*info.size), false, 'd');
 		}
 		}
@@ -392,7 +396,11 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
 fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 	match verb {
 	match verb {
 	case 't', 'v':
 	case 't', 'v':
-		buffer_write_string(buf, if b { give "true" } else { give "false" });
+		if b {
+			buffer_write_string(buf, "true");
+		} else {
+			buffer_write_string(buf, "false");
+		}
 	default:
 	default:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 	}
 	}

+ 25 - 205
src/check_expr.c

@@ -1114,11 +1114,12 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
 }
 }
 
 
 Type *make_optional_ok_type(gbAllocator a, Type *value) {
 Type *make_optional_ok_type(gbAllocator a, Type *value) {
+	bool typed = true;
 	Type *t = make_type_tuple(a);
 	Type *t = make_type_tuple(a);
 	t->Tuple.variables = gb_alloc_array(a, Entity *, 2);
 	t->Tuple.variables = gb_alloc_array(a, Entity *, 2);
 	t->Tuple.variable_count = 2;
 	t->Tuple.variable_count = 2;
 	t->Tuple.variables[0] = make_entity_field(a, NULL, blank_token, value,  false, 0);
 	t->Tuple.variables[0] = make_entity_field(a, NULL, blank_token, value,  false, 0);
-	t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, t_bool, false, 1);
+	t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, typed ? t_bool : t_untyped_bool, false, 1);
 	return t;
 	return t;
 }
 }
 
 
@@ -2113,6 +2114,7 @@ void check_cast(Checker *c, Operand *x, Type *type) {
 		gb_string_free(from_type);
 		gb_string_free(from_type);
 		gb_string_free(to_type);
 		gb_string_free(to_type);
 		gb_string_free(expr_str);
 		gb_string_free(expr_str);
+
 		x->mode = Addressing_Invalid;
 		x->mode = Addressing_Invalid;
 		return;
 		return;
 	}
 	}
@@ -3831,7 +3833,8 @@ int valid_proc_and_score_cmp(void const *a, void const *b) {
 
 
 typedef Array(Operand) ArrayOperand;
 typedef Array(Operand) ArrayOperand;
 
 
-void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) {
+bool check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) {
+	bool optional_ok = false;
 	for_array(i, rhs) {
 	for_array(i, rhs) {
 		Operand o = {0};
 		Operand o = {0};
 		check_multi_expr(c, &o, rhs.e[i]);
 		check_multi_expr(c, &o, rhs.e[i]);
@@ -3849,6 +3852,8 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands,
 				ok.type  = t_bool;
 				ok.type  = t_bool;
 				array_add(operands, val);
 				array_add(operands, val);
 				array_add(operands, ok);
 				array_add(operands, ok);
+
+				optional_ok = true;
 			} else {
 			} else {
 				array_add(operands, o);
 				array_add(operands, o);
 			}
 			}
@@ -3860,6 +3865,8 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands,
 			}
 			}
 		}
 		}
 	}
 	}
+
+	return optional_ok;
 }
 }
 
 
 Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
 Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
@@ -4162,40 +4169,6 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
 	return false;
 	return false;
 }
 }
 
 
-
-bool check_is_giving(AstNode *node, AstNode **give_expr) {
-	switch (node->kind) {
-	case_ast_node(es, ExprStmt, node);
-		if (es->expr->kind == AstNode_GiveExpr) {
-			if (give_expr) *give_expr = es->expr;
-			return true;
-		}
-	case_end;
-
-	case_ast_node(ge, GiveExpr, node);
-		if (give_expr) *give_expr = node;
-		return true;
-	case_end;
-
-	case_ast_node(be, BlockExpr, node);
-		// Iterate backwards
-		for (isize n = be->stmts.count-1; n >= 0; n--) {
-			AstNode *stmt = be->stmts.e[n];
-			if (stmt->kind == AstNode_EmptyStmt) {
-				continue;
-			}
-			if (stmt->kind == AstNode_ExprStmt && stmt->ExprStmt.expr->kind == AstNode_GiveExpr) {
-				if (give_expr) *give_expr = stmt->ExprStmt.expr;
-				return true;
-			}
-		}
-	case_end;
-	}
-
-	if (give_expr) *give_expr = NULL;
-	return false;
-}
-
 ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
 ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
 	ExprKind kind = Expr_Stmt;
 	ExprKind kind = Expr_Stmt;
 
 
@@ -4297,177 +4270,30 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 		o->type = type;
 		o->type = type;
 	case_end;
 	case_end;
 
 
-	case_ast_node(ge, GiveExpr, node);
+	case_ast_node(te, TernaryExpr, node);
 		if (c->proc_stack.count == 0) {
 		if (c->proc_stack.count == 0) {
-			error_node(node, "A give expression is only allowed within a procedure");
+			error_node(node, "A ternary expression is only allowed within a procedure");
 			goto error;
 			goto error;
 		}
 		}
-
-		if (ge->results.count == 0) {
-			error_node(node, "`give` has no results");
-			goto error;
-		}
-
-		gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
-		Array(Operand) operands;
-		array_init_reserve(&operands, c->tmp_allocator, 2*ge->results.count);
-
-		for_array(i, ge->results) {
-			AstNode *rhs = ge->results.e[i];
-			Operand o = {0};
-			check_multi_expr(c, &o, rhs);
-			if (!is_operand_value(o)) {
-				error_node(rhs, "Expected a value for a `give`");
-				continue;
-			}
-			if (o.type->kind != Type_Tuple) {
-				array_add(&operands, o);
-			} else {
-				TypeTuple *tuple = &o.type->Tuple;
-				for (isize j = 0; j < tuple->variable_count; j++) {
-					o.type = tuple->variables[j]->type;
-					array_add(&operands, o);
-				}
-			}
-		}
-
-		if (operands.count == 0) {
-			error_node(node, "`give` has no value");
-			gb_temp_arena_memory_end(tmp);
-			goto error;
-		} else if (operands.count == 1) {
-			Operand operand = operands.e[0];
-			Type *th = type_hint != NULL ? type_hint : c->context.type_hint;
-			if (th != NULL) {
-				convert_to_typed(c, &operand, th, 0);
-			}
-			// IMPORTANT NOTE(bill): This type could be untyped!!!
-			o->type = default_type(operand.type);
-			o->mode = Addressing_Value;
-		} else {
-			Type *tuple = make_type_tuple(c->allocator);
-
-			Entity **variables = gb_alloc_array(c->allocator, Entity *, operands.count);
-			isize variable_index = 0;
-			for_array(i, operands) {
-				Operand operand = operands.e[i];
-				// Type *type = default_type(operand.type);
-				Type *type = operand.type;
-				switch (operand.mode) {
-				case Addressing_Constant:
-					variables[variable_index++] = make_entity_constant(c->allocator, NULL, empty_token, type, operand.value);
-					break;
-				default:
-					variables[variable_index++] = make_entity_param(c->allocator, NULL, empty_token, type, false, true);
-					break;
-				}
-			}
-			tuple->Tuple.variables = variables;
-			tuple->Tuple.variable_count = operands.count;
-
-			o->type = tuple;
-			o->mode = Addressing_Value;
-		}
-		gb_temp_arena_memory_end(tmp);
-	case_end;
-
-	case_ast_node(be, BlockExpr, node);
-		if (c->proc_stack.count == 0) {
-			error_node(node, "A block expression is only allowed within a procedure");
-			goto error;
-		}
-
-		for (isize i = be->stmts.count-1; i >= 0; i--) {
-			if (be->stmts.e[i]->kind != AstNode_EmptyStmt) {
-				break;
-			}
-			be->stmts.count--;
-		}
-
-		if (be->stmts.count == 0) {
-			error_node(node, "Empty block expression");
-			goto error;
-		}
-
-		CheckerContext prev_context = c->context;
-		c->context.type_hint = type_hint;
-		check_open_scope(c, node);
-		check_stmt_list(c, be->stmts, Stmt_GiveAllowed);
-		check_close_scope(c);
-
-		c->context = prev_context;
-
-		AstNode *give_node = NULL;
-		if (!check_is_giving(node, &give_node) || give_node == NULL) {
-			error_node(node, "Missing give statement at end of block expression");
-			goto error;
-		}
-
-		GB_ASSERT(give_node != NULL && give_node->kind == AstNode_GiveExpr);
-		be->give_node = give_node;
-
-		Type *type = type_of_expr(&c->info, give_node);
-		if (type == NULL) {
-			goto error;
-		} else if (type == t_invalid) {
-			o->type = t_invalid;
-			o->mode = Addressing_Invalid;
-		} else {
-			o->type = type;
-			o->mode = Addressing_Value;
-		}
-	case_end;
-
-	case_ast_node(ie, IfExpr, node);
-		if (c->proc_stack.count == 0) {
-			error_node(node, "An if expression is only allowed within a procedure");
-			goto error;
-		}
-
-		check_open_scope(c, node);
-
-		if (ie->init != NULL) {
-			check_stmt(c, ie->init, 0);
-		}
-
 		Operand operand = {Addressing_Invalid};
 		Operand operand = {Addressing_Invalid};
-		check_expr(c, &operand, ie->cond);
+		check_expr(c, &operand, te->cond);
 		if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
 		if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
-			error_node(ie->cond, "Non-boolean condition in if expression");
+			error_node(te->cond, "Non-boolean condition in if expression");
 		}
 		}
 
 
 		Operand x = {Addressing_Invalid};
 		Operand x = {Addressing_Invalid};
 		Operand y = {Addressing_Invalid};
 		Operand y = {Addressing_Invalid};
-		Type *if_type = NULL;
-		Type *else_type = NULL;
-		if (type_hint) {
-			gb_printf_err("here\n");
-		}
-		check_expr_with_type_hint(c, &x, ie->body, type_hint);
-		if_type = x.type;
-
-		if (ie->else_expr != NULL) {
-			switch (ie->else_expr->kind) {
-			case AstNode_IfExpr:
-			case AstNode_BlockExpr:
-				check_expr_with_type_hint(c, &y, ie->else_expr, if_type);
-				else_type = y.type;
-				break;
-			default:
-				error_node(ie->else_expr, "Invalid else expression in if expression");
-				break;
-			}
+		check_expr_with_type_hint(c, &x, te->x, type_hint);
+
+		if (te->y != NULL) {
+			check_expr_with_type_hint(c, &y, te->y, type_hint);
 		} else {
 		} else {
-			error_node(ie->else_expr, "An if expression must have an else expression");
-			check_close_scope(c);
+			error_node(node, "A ternary expression must have an else clause");
 			goto error;
 			goto error;
 		}
 		}
 
 
-		check_close_scope(c);
-
-		if (if_type == NULL || if_type == t_invalid ||
-		    else_type == NULL || else_type == t_invalid) {
+		if (x.type == NULL || x.type == t_invalid ||
+		    y.type == NULL || y.type == t_invalid) {
 			goto error;
 			goto error;
 		}
 		}
 
 
@@ -4482,16 +4308,16 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 		}
 		}
 
 
 
 
-		if (!are_types_identical(if_type, else_type)) {
-			gbString its = type_to_string(if_type);
-			gbString ets = type_to_string(else_type);
-			error_node(node, "Mismatched types in if expression, %s vs %s", its, ets);
+		if (!are_types_identical(x.type, y.type)) {
+			gbString its = type_to_string(x.type);
+			gbString ets = type_to_string(y.type);
+			error_node(node, "Mismatched types in ternary expression, %s vs %s", its, ets);
 			gb_string_free(ets);
 			gb_string_free(ets);
 			gb_string_free(its);
 			gb_string_free(its);
 			goto error;
 			goto error;
 		}
 		}
 
 
-		o->type = if_type;
+		o->type = x.type;
 		o->mode = Addressing_Value;
 		o->mode = Addressing_Value;
 	case_end;
 	case_end;
 
 
@@ -5371,12 +5197,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = gb_string_appendc(str, "}");
 		str = gb_string_appendc(str, "}");
 	case_end;
 	case_end;
 
 
-	case_ast_node(be, BlockExpr, node);
-		str = gb_string_appendc(str, "block expression");
-	case_end;
-	case_ast_node(ie, IfExpr, node);
-		str = gb_string_appendc(str, "if expression");
-	case_end;
 
 
 	case_ast_node(te, TagExpr, node);
 	case_ast_node(te, TagExpr, node);
 		str = gb_string_appendc(str, "#");
 		str = gb_string_appendc(str, "#");

+ 0 - 11
src/check_stmt.c

@@ -30,11 +30,6 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 			case AstNode_ReturnStmt:
 			case AstNode_ReturnStmt:
 				error_node(n, "Statements after this `return` are never executed");
 				error_node(n, "Statements after this `return` are never executed");
 				break;
 				break;
-			case AstNode_ExprStmt:
-				if (n->ExprStmt.expr->kind == AstNode_GiveExpr) {
-					error_node(n, "A `give` must be the last statement in a block");
-				}
-				break;
 			}
 			}
 		}
 		}
 
 
@@ -413,12 +408,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			if (operand.expr->kind == AstNode_CallExpr) {
 			if (operand.expr->kind == AstNode_CallExpr) {
 				return;
 				return;
 			}
 			}
-			if (operand.expr->kind == AstNode_GiveExpr) {
-				if ((flags&Stmt_GiveAllowed) != 0) {
-					return;
-				}
-				error_node(node, "Illegal use of `give`");
-			}
 			gbString expr_str = expr_to_string(operand.expr);
 			gbString expr_str = expr_to_string(operand.expr);
 			error_node(node, "Expression is not used: `%s`", expr_str);
 			error_node(node, "Expression is not used: `%s`", expr_str);
 			gb_string_free(expr_str);
 			gb_string_free(expr_str);

+ 1 - 3
src/checker.c

@@ -400,9 +400,7 @@ void check_open_scope(Checker *c, AstNode *node) {
 	node = unparen_expr(node);
 	node = unparen_expr(node);
 	GB_ASSERT(node->kind == AstNode_Invalid ||
 	GB_ASSERT(node->kind == AstNode_Invalid ||
 	          is_ast_node_stmt(node) ||
 	          is_ast_node_stmt(node) ||
-	          is_ast_node_type(node) ||
-	          node->kind == AstNode_BlockExpr ||
-	          node->kind == AstNode_IfExpr );
+	          is_ast_node_type(node));
 	Scope *scope = make_scope(c->context.scope, c->allocator);
 	Scope *scope = make_scope(c->context.scope, c->allocator);
 	add_scope(c, node, scope);
 	add_scope(c, node, scope);
 	if (node->kind == AstNode_ProcType) {
 	if (node->kind == AstNode_ProcType) {

+ 28 - 56
src/ir.c

@@ -2851,25 +2851,40 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 	case_end;
 	case_end;
 
 
-	case_ast_node(be, BlockExpr, expr);
-		ir_emit_comment(proc, str_lit("BlockExpr"));
-		ir_open_scope(proc);
+	case_ast_node(te, TernaryExpr, expr);
+		ir_emit_comment(proc, str_lit("TernaryExpr"));
 
 
-		AstNodeArray stmts = be->stmts;
-		stmts.count--;
-		ir_build_stmt_list(proc, stmts);
+		irValueArray edges = {0};
+		array_init_reserve(&edges, proc->module->allocator, 2);
 
 
-		AstNode *give_stmt = be->stmts.e[be->stmts.count-1];
-		GB_ASSERT(give_stmt->kind == AstNode_ExprStmt);
-		AstNode *give_expr = give_stmt->ExprStmt.expr;
-		GB_ASSERT(give_expr->kind == AstNode_GiveExpr);
-		irValue *value = ir_build_expr(proc, give_expr);
+		GB_ASSERT(te->y != NULL);
+		irBlock *then  = ir_new_block(proc, NULL, "if.then");
+		irBlock *done  = ir_new_block(proc, NULL, "if.done"); // NOTE(bill): Append later
+		irBlock *else_ = ir_new_block(proc, NULL, "if.else");
 
 
+		irValue *cond = ir_build_cond(proc, te->cond, then, else_);
+		ir_start_block(proc, then);
+
+		ir_open_scope(proc);
+		array_add(&edges, ir_build_expr(proc, te->x));
 		ir_close_scope(proc, irDeferExit_Default, NULL);
 		ir_close_scope(proc, irDeferExit_Default, NULL);
 
 
-		return value;
+		ir_emit_jump(proc, done);
+		ir_start_block(proc, else_);
+
+		ir_open_scope(proc);
+		array_add(&edges, ir_build_expr(proc, te->y));
+		ir_close_scope(proc, irDeferExit_Default, NULL);
+
+		ir_emit_jump(proc, done);
+		ir_start_block(proc, done);
+
+		Type *type = type_of_expr(proc->module->info, expr);
+
+		return ir_emit(proc, ir_make_instr_phi(proc, edges, type));
 	case_end;
 	case_end;
 
 
+#if 0
 	case_ast_node(ie, IfExpr, expr);
 	case_ast_node(ie, IfExpr, expr);
 		ir_emit_comment(proc, str_lit("IfExpr"));
 		ir_emit_comment(proc, str_lit("IfExpr"));
 		if (ie->init != NULL) {
 		if (ie->init != NULL) {
@@ -2908,50 +2923,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 
 
 		return ir_emit(proc, ir_make_instr_phi(proc, edges, type));
 		return ir_emit(proc, ir_make_instr_phi(proc, edges, type));
 	case_end;
 	case_end;
-
-	case_ast_node(ge, GiveExpr, expr);
-		ir_emit_comment(proc, str_lit("GiveExpr"));
-
-		irValue *v = NULL;
-		Type *give_type = type_of_expr(proc->module->info, expr);
-		GB_ASSERT(give_type != NULL);
-		if (give_type->kind != Type_Tuple) {
-			v = ir_emit_conv(proc, ir_build_expr(proc, ge->results.e[0]), give_type);
-		} else {
-			TypeTuple *tuple = &give_type->Tuple;
-			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
-
-			irValueArray results;
-			array_init_reserve(&results, proc->module->tmp_allocator, tuple->variable_count);
-
-			for_array(res_index, ge->results) {
-				irValue *res = ir_build_expr(proc, ge->results.e[res_index]);
-				Type *t = ir_type(res);
-				if (t->kind == Type_Tuple) {
-					for (isize i = 0; i < t->Tuple.variable_count; i++) {
-						Entity *e = t->Tuple.variables[i];
-						irValue *v = ir_emit_struct_ev(proc, res, i);
-						array_add(&results, v);
-					}
-				} else {
-					array_add(&results, res);
-				}
-			}
-
-			v = ir_add_local_generated(proc, give_type);
-			for_array(i, results) {
-				Entity *e = tuple->variables[i];
-				irValue *res = ir_emit_conv(proc, results.e[i], e->type);
-				irValue *field = ir_emit_struct_ep(proc, v, i);
-				ir_emit_store(proc, field, res);
-			}
-			v = ir_emit_load(proc, v);
-
-			gb_temp_arena_memory_end(tmp);
-		}
-
-		return v;
-	case_end;
+#endif
 
 
 	case_ast_node(ce, CastExpr, expr);
 	case_ast_node(ce, CastExpr, expr);
 		Type *type = tv->type;
 		Type *type = tv->type;

+ 127 - 149
src/parser.c

@@ -168,24 +168,9 @@ AST_NODE_KIND(_ExprBegin,  "",  i32) \
 		Token        open; \
 		Token        open; \
 		Token        close; \
 		Token        close; \
 	}) \
 	}) \
-	AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \
-	AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
-	AST_NODE_KIND(BlockExpr, "block expr", struct { \
-		AstNodeArray stmts; \
-		Token open, close; \
-		AstNode *give_node; \
-	}) \
-	AST_NODE_KIND(GiveExpr, "give expression", struct { \
-		Token token; \
-		AstNodeArray results; \
-	}) \
-	AST_NODE_KIND(IfExpr, "if expression", struct { \
-		Token token; \
-		AstNode *init; \
-		AstNode *cond; \
-		AstNode *body; \
-		AstNode *else_expr; \
-	}) \
+	AST_NODE_KIND(CastExpr,     "cast expression",     struct { Token token; AstNode *type, *expr; Token open, close; }) \
+	AST_NODE_KIND(FieldValue,   "field value",         struct { Token eq; AstNode *field, *value; }) \
+	AST_NODE_KIND(TernaryExpr,  "ternary expression",  struct { AstNode *cond, *x, *y; }) \
 	AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \
 	AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \
 AST_NODE_KIND(_ExprEnd,       "", i32) \
 AST_NODE_KIND(_ExprEnd,       "", i32) \
 AST_NODE_KIND(_StmtBegin,     "", i32) \
 AST_NODE_KIND(_StmtBegin,     "", i32) \
@@ -465,9 +450,7 @@ Token ast_node_token(AstNode *node) {
 	case AstNode_CastExpr:     return node->CastExpr.token;
 	case AstNode_CastExpr:     return node->CastExpr.token;
 	case AstNode_FieldValue:   return node->FieldValue.eq;
 	case AstNode_FieldValue:   return node->FieldValue.eq;
 	case AstNode_DerefExpr:    return node->DerefExpr.op;
 	case AstNode_DerefExpr:    return node->DerefExpr.op;
-	case AstNode_BlockExpr:    return node->BlockExpr.open;
-	case AstNode_GiveExpr:     return node->GiveExpr.token;
-	case AstNode_IfExpr:       return node->IfExpr.token;
+	case AstNode_TernaryExpr:  return ast_node_token(node->TernaryExpr.cond);
 	case AstNode_IntervalExpr: return ast_node_token(node->IntervalExpr.left);
 	case AstNode_IntervalExpr: return ast_node_token(node->IntervalExpr.left);
 
 
 	case AstNode_BadStmt:       return node->BadStmt.begin;
 	case AstNode_BadStmt:       return node->BadStmt.begin;
@@ -768,29 +751,11 @@ AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token o
 	return result;
 	return result;
 }
 }
 
 
-
-AstNode *ast_block_expr(AstFile *f, AstNodeArray stmts, Token open, Token close) {
-	AstNode *result = make_ast_node(f, AstNode_BlockExpr);
-	result->BlockExpr.stmts = stmts;
-	result->BlockExpr.open = open;
-	result->BlockExpr.close = close;
-	return result;
-}
-
-AstNode *ast_give_expr(AstFile *f, Token token, AstNodeArray results) {
-	AstNode *result = make_ast_node(f, AstNode_GiveExpr);
-	result->GiveExpr.token = token;
-	result->GiveExpr.results = results;
-	return result;
-}
-
-AstNode *ast_if_expr(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_expr) {
-	AstNode *result = make_ast_node(f, AstNode_IfExpr);
-	result->IfExpr.token = token;
-	result->IfExpr.init = init;
-	result->IfExpr.cond = cond;
-	result->IfExpr.body = body;
-	result->IfExpr.else_expr = else_expr;
+AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) {
+	AstNode *result = make_ast_node(f, AstNode_TernaryExpr);
+	result->TernaryExpr.cond = cond;
+	result->TernaryExpr.x = x;
+	result->TernaryExpr.y = y;
 	return result;
 	return result;
 }
 }
 
 
@@ -1321,13 +1286,13 @@ void expect_semicolon(AstFile *f, AstNode *s) {
 				return;
 				return;
 			}
 			}
 		} else {
 		} else {
-			switch (s->kind) {
-			case AstNode_GiveExpr:
-				if (f->curr_token.kind == Token_CloseBrace) {
-					return;
-				}
-				break;
-			}
+			// switch (s->kind) {
+			// case AstNode_GiveExpr:
+			// 	if (f->curr_token.kind == Token_CloseBrace) {
+			// 		return;
+			// 	}
+			// 	break;
+			// }
 		}
 		}
 		syntax_error(prev_token, "Expected `;` after %.*s, got %.*s",
 		syntax_error(prev_token, "Expected `;` after %.*s, got %.*s",
 		             LIT(ast_node_strings[s->kind]), LIT(token_strings[prev_token.kind]));
 		             LIT(ast_node_strings[s->kind]), LIT(token_strings[prev_token.kind]));
@@ -1612,72 +1577,72 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
 
 
 
 
 
 
-AstNode *parse_block_expr(AstFile *f) {
-	AstNodeArray stmts = {0};
-	Token open, close;
-	open = expect_token(f, Token_OpenBrace);
-	f->expr_level++;
-	stmts = parse_stmt_list(f);
-	f->expr_level--;
-	close = expect_token(f, Token_CloseBrace);
-	return ast_block_expr(f, stmts, open, close);
-}
-
-AstNode *parse_if_expr(AstFile *f) {
-	if (f->curr_proc == NULL) {
-		syntax_error(f->curr_token, "You cannot use an if expression in the file scope");
-		return ast_bad_stmt(f, f->curr_token, f->curr_token);
-	}
-
-	Token token = expect_token(f, Token_if);
-	AstNode *init = NULL;
-	AstNode *cond = NULL;
-	AstNode *body = NULL;
-	AstNode *else_expr = NULL;
-
-	isize prev_level = f->expr_level;
-	f->expr_level = -1;
-
-	if (allow_token(f, Token_Semicolon)) {
-		cond = parse_expr(f, false);
-	} else {
-		init = parse_simple_stmt(f, false);
-		if (allow_token(f, Token_Semicolon)) {
-			cond = parse_expr(f, false);
-		} else {
-			cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
-			init = NULL;
-		}
-	}
-
-	f->expr_level = prev_level;
-
-	if (cond == NULL) {
-		syntax_error(f->curr_token, "Expected condition for if statement");
-	}
-
-	body = parse_block_expr(f);
-
-	if (allow_token(f, Token_else)) {
-		switch (f->curr_token.kind) {
-		case Token_if:
-			else_expr = parse_if_expr(f);
-			break;
-		case Token_OpenBrace:
-			else_expr = parse_block_expr(f);
-			break;
-		default:
-			syntax_error(f->curr_token, "Expected if expression block statement");
-			else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
-			break;
-		}
-	} else {
-		syntax_error(f->curr_token, "An if expression must have an else clause");
-		return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
-	}
-
-	return ast_if_expr(f, token, init, cond, body, else_expr);
-}
+// AstNode *parse_block_expr(AstFile *f) {
+// 	AstNodeArray stmts = {0};
+// 	Token open, close;
+// 	open = expect_token(f, Token_OpenBrace);
+// 	f->expr_level++;
+// 	stmts = parse_stmt_list(f);
+// 	f->expr_level--;
+// 	close = expect_token(f, Token_CloseBrace);
+// 	return ast_block_expr(f, stmts, open, close);
+// }
+
+// AstNode *parse_if_expr(AstFile *f) {
+// 	if (f->curr_proc == NULL) {
+// 		syntax_error(f->curr_token, "You cannot use an if expression in the file scope");
+// 		return ast_bad_stmt(f, f->curr_token, f->curr_token);
+// 	}
+
+// 	Token token = expect_token(f, Token_if);
+// 	AstNode *init = NULL;
+// 	AstNode *cond = NULL;
+// 	AstNode *body = NULL;
+// 	AstNode *else_expr = NULL;
+
+// 	isize prev_level = f->expr_level;
+// 	f->expr_level = -1;
+
+// 	if (allow_token(f, Token_Semicolon)) {
+// 		cond = parse_expr(f, false);
+// 	} else {
+// 		init = parse_simple_stmt(f, false);
+// 		if (allow_token(f, Token_Semicolon)) {
+// 			cond = parse_expr(f, false);
+// 		} else {
+// 			cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
+// 			init = NULL;
+// 		}
+// 	}
+
+// 	f->expr_level = prev_level;
+
+// 	if (cond == NULL) {
+// 		syntax_error(f->curr_token, "Expected condition for if statement");
+// 	}
+
+// 	body = parse_block_expr(f);
+
+// 	if (allow_token(f, Token_else)) {
+// 		switch (f->curr_token.kind) {
+// 		case Token_if:
+// 			else_expr = parse_if_expr(f);
+// 			break;
+// 		case Token_OpenBrace:
+// 			else_expr = parse_block_expr(f);
+// 			break;
+// 		default:
+// 			syntax_error(f->curr_token, "Expected if expression block statement");
+// 			else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
+// 			break;
+// 		}
+// 	} else {
+// 		syntax_error(f->curr_token, "An if expression must have an else clause");
+// 		return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]);
+// 	}
+
+// 	return ast_if_expr(f, token, init, cond, body, else_expr);
+// }
 
 
 AstNode *parse_operand(AstFile *f, bool lhs) {
 AstNode *parse_operand(AstFile *f, bool lhs) {
 	AstNode *operand = NULL; // Operand
 	AstNode *operand = NULL; // Operand
@@ -1791,16 +1756,16 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		return type;
 		return type;
 	}
 	}
 
 
-	case Token_if:
-		if (!lhs && f->expr_level >= 0) {
-			return parse_if_expr(f);
-		}
-		break;
-	case Token_OpenBrace:
-		if (!lhs && f->expr_level >= 0) {
-			return parse_block_expr(f);
-		}
-		break;
+	// case Token_if:
+	// 	if (!lhs && f->expr_level >= 0) {
+	// 		return parse_if_expr(f);
+	// 	}
+	// 	break;
+	// case Token_OpenBrace:
+	// 	if (!lhs && f->expr_level >= 0) {
+	// 		return parse_block_expr(f);
+	// 	}
+	// 	break;
 
 
 	default: {
 	default: {
 		AstNode *type = parse_type_or_ident(f);
 		AstNode *type = parse_type_or_ident(f);
@@ -1984,6 +1949,19 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
 			}
 			}
 			break;
 			break;
 
 
+		case Token_Question:
+			if (!lhs && operand != NULL && f->expr_level >= 0) {
+				AstNode *cond = operand;
+				Token token_q = expect_token(f, Token_Question);
+				AstNode *x = parse_expr(f, false);
+				Token token_c = expect_token(f, Token_Colon);
+				AstNode *y = parse_expr(f, false);
+				operand = ast_ternary_expr(f, cond, x, y);
+			} else {
+				loop = false;
+			}
+			break;
+
 		default:
 		default:
 			loop = false;
 			loop = false;
 			break;
 			break;
@@ -2925,27 +2903,27 @@ AstNode *parse_return_stmt(AstFile *f) {
 }
 }
 
 
 
 
-AstNode *parse_give_stmt(AstFile *f) {
-	if (f->curr_proc == NULL) {
-		syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
-		return ast_bad_stmt(f, f->curr_token, f->curr_token);
-	}
-	if (f->expr_level == 0) {
-		syntax_error(f->curr_token, "A give statement must be used within an expression");
-		return ast_bad_stmt(f, f->curr_token, f->curr_token);
-	}
-
-	Token token = expect_token(f, Token_give);
-	AstNodeArray results;
-	if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
-		results = parse_rhs_expr_list(f);
-	} else {
-		results = make_ast_node_array(f);
-	}
-	AstNode *ge = ast_give_expr(f, token, results);
-	expect_semicolon(f, ge);
-	return ast_expr_stmt(f, ge);
-}
+// AstNode *parse_give_stmt(AstFile *f) {
+// 	if (f->curr_proc == NULL) {
+// 		syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
+// 		return ast_bad_stmt(f, f->curr_token, f->curr_token);
+// 	}
+// 	if (f->expr_level == 0) {
+// 		syntax_error(f->curr_token, "A give statement must be used within an expression");
+// 		return ast_bad_stmt(f, f->curr_token, f->curr_token);
+// 	}
+
+// 	Token token = expect_token(f, Token_give);
+// 	AstNodeArray results;
+// 	if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
+// 		results = parse_rhs_expr_list(f);
+// 	} else {
+// 		results = make_ast_node_array(f);
+// 	}
+// 	AstNode *ge = ast_give_expr(f, token, results);
+// 	expect_semicolon(f, ge);
+// 	return ast_expr_stmt(f, ge);
+// }
 
 
 AstNode *parse_for_stmt(AstFile *f) {
 AstNode *parse_for_stmt(AstFile *f) {
 	if (f->curr_proc == NULL) {
 	if (f->curr_proc == NULL) {
@@ -3227,7 +3205,7 @@ AstNode *parse_stmt(AstFile *f) {
 	case Token_defer:  return parse_defer_stmt(f);
 	case Token_defer:  return parse_defer_stmt(f);
 	case Token_asm:    return parse_asm_stmt(f);
 	case Token_asm:    return parse_asm_stmt(f);
 	case Token_return: return parse_return_stmt(f);
 	case Token_return: return parse_return_stmt(f);
-	case Token_give:   return parse_give_stmt(f);
+	// case Token_give:   return parse_give_stmt(f);
 
 
 	case Token_break:
 	case Token_break:
 	case Token_continue:
 	case Token_continue: