Browse Source

"Maybe-fy" operator

Ginger Bill 8 years ago
parent
commit
a5c6340316
5 changed files with 46 additions and 27 deletions
  1. 1 11
      code/demo.odin
  2. 28 2
      src/checker/expr.cpp
  3. 15 13
      src/codegen/ssa.cpp
  4. 1 1
      src/exact_value.cpp
  5. 1 0
      src/parser.cpp

+ 1 - 11
code/demo.odin

@@ -1,16 +1,6 @@
 #import "fmt.odin"
 
-
 main :: proc() {
-	maybe_print :: proc(x: ?int) {
-		if v, ok := x?; ok {
-			fmt.println(v)
-		} else {
-			fmt.println("nowt")
-		}
-	}
-
-	maybe_print(123) // 123
-	maybe_print(nil) // nowt
+	x := ?123
 }
 

+ 28 - 2
src/checker/expr.cpp

@@ -1044,6 +1044,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 		if (ue->op.kind == Token_Pointer) {
 			type = make_type_pointer(c->allocator, check_type(c, ue->expr));
 			goto end;
+		} else if (ue->op.kind == Token_Maybe) {
+			type = make_type_maybe(c->allocator, check_type(c, ue->expr));
+			goto end;
 		}
 	case_end;
 
@@ -1365,7 +1368,8 @@ b32 check_is_expr_vector_index(Checker *c, AstNode *expr) {
 }
 
 void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
-	if (op.kind == Token_Pointer) { // Pointer address
+	switch (op.kind) {
+	case Token_Pointer: { // Pointer address
 		if (o->mode != Addressing_Variable ||
 		    check_is_expr_vector_index(c, o->expr)) {
 			ast_node(ue, UnaryExpr, node);
@@ -1380,6 +1384,27 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 		return;
 	}
 
+	case Token_Maybe: { // Make maybe
+		Type *t = default_type(o->type);
+		b32 is_value =
+			o->mode == Addressing_Variable ||
+			o->mode == Addressing_Value ||
+			o->mode == Addressing_Constant;
+
+		if (!is_value || is_type_untyped(t)) {
+			ast_node(ue, UnaryExpr, node);
+			gbString str = expr_to_string(ue->expr);
+			defer (gb_string_free(str));
+			error(op, "Cannot convert `%s` to a maybe", str);
+			o->mode = Addressing_Invalid;
+			return;
+		}
+		o->mode = Addressing_Value;
+		o->type = make_type_maybe(c->allocator, t);
+		return;
+	}
+	}
+
 	if (!check_unary_op(c, o, op)) {
 		o->mode = Addressing_Invalid;
 		return;
@@ -1399,8 +1424,9 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 
 
 		i32 precision = 0;
-		if (is_type_unsigned(type))
+		if (is_type_unsigned(type)) {
 			precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
+		}
 		o->value = exact_unary_operator_value(op, o->value, precision);
 
 		if (is_type_typed(type)) {

+ 15 - 13
src/codegen/ssa.cpp

@@ -2099,24 +2099,26 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 	case_ast_node(ue, UnaryExpr, expr);
 		switch (ue->op.kind) {
-		case Token_Pointer: {
-			return ssa_emit_zero_gep(proc, ssa_build_addr(proc, ue->expr).addr);
-		}
+		case Token_Pointer:
+			return ssa_emit_zero_gep(proc, ssa_build_addr(proc, ue->expr).addr); // Make a copy of the pointer
+
+		case Token_Maybe:
+			return ssa_emit_conv(proc, ssa_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr));
+
 		case Token_Add:
 			return ssa_build_expr(proc, ue->expr);
-		case Token_Sub: {
-			// NOTE(bill): -`x` == 0 - `x`
-			ssaValue *left = v_zero;
-			ssaValue *right = ssa_build_expr(proc, ue->expr);
-			return ssa_emit_arith(proc, ue->op, left, right, tv->type);
-		} break;
-		case Token_Not: // Boolean not
+
+		case Token_Sub: // NOTE(bill): -`x` == 0 - `x`
+			return ssa_emit_arith(proc, ue->op, v_zero, ssa_build_expr(proc, ue->expr), tv->type);
+
+		case Token_Not:   // Boolean not
 		case Token_Xor: { // Bitwise not
 			// NOTE(bill): "not" `x` == `x` "xor" `-1`
-			ExactValue neg_one = make_exact_value_integer(-1);
 			ssaValue *left = ssa_build_expr(proc, ue->expr);
-			ssaValue *right = ssa_add_module_constant(proc->module, tv->type, neg_one);
-			return ssa_emit_arith(proc, ue->op, left, right, tv->type);
+			ssaValue *right = ssa_add_module_constant(proc->module, tv->type, make_exact_value_integer(-1));
+			return ssa_emit_arith(proc, ue->op,
+			                      left, right,
+			                      tv->type);
 		} break;
 		}
 	case_end;

+ 1 - 1
src/exact_value.cpp

@@ -23,7 +23,7 @@ struct ExactValue {
 	union {
 		b32      value_bool;
 		String   value_string;
-		i64      value_integer;
+		i64      value_integer; // NOTE(bill): This must be an integer and not a pointer
 		f64      value_float;
 		i64      value_pointer;
 		AstNode *value_compound;

+ 1 - 0
src/parser.cpp

@@ -1610,6 +1610,7 @@ AstNode *parse_type(AstFile *f);
 AstNode *parse_unary_expr(AstFile *f, b32 lhs) {
 	switch (f->curr_token.kind) {
 	case Token_Pointer:
+	case Token_Maybe:
 	case Token_Add:
 	case Token_Sub:
 	case Token_Not: