From a5c6340316245f4f63e74d307f9d7c8be09360c6 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sat, 8 Oct 2016 10:01:29 +0100 Subject: [PATCH] "Maybe-fy" operator --- code/demo.odin | 12 +----------- src/checker/expr.cpp | 30 ++++++++++++++++++++++++++++-- src/codegen/ssa.cpp | 28 +++++++++++++++------------- src/exact_value.cpp | 2 +- src/parser.cpp | 1 + 5 files changed, 46 insertions(+), 27 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index 786392b77..e3e68596c 100644 --- a/code/demo.odin +++ b/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 } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 26b8399d5..23d877bd9 100644 --- a/src/checker/expr.cpp +++ b/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)) { diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index c144d0011..5d66b222e 100644 --- a/src/codegen/ssa.cpp +++ b/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; diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 83e9d5ad6..c8c47ea60 100644 --- a/src/exact_value.cpp +++ b/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; diff --git a/src/parser.cpp b/src/parser.cpp index c8559739e..d44a199ae 100644 --- a/src/parser.cpp +++ b/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: