added: coalesce operator (??)
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 6 Mar 2023 03:39:06 +0000 (21:39 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 6 Mar 2023 03:39:06 +0000 (21:39 -0600)
compiler/include/astnodes.h
compiler/include/lex.h
compiler/src/astnodes.c
compiler/src/lex.c
compiler/src/parser.c
core/container/optional.onyx

index 714c2e049e58340761766b36be673b4181564247..64be00f7000cfafa75abd5c018f75dfb4050c42f 100644 (file)
@@ -342,6 +342,8 @@ typedef enum BinaryOp {
     Binary_Op_Subscript_Equals = 37,
     Binary_Op_Ptr_Subscript    = 38,
 
+    Binary_Op_Coalesce         = 39,
+
     Binary_Op_Count
 } BinaryOp;
 
index 6665cd323e18792e1c54cd7d9a1a052c08a6566b..cd437ece6776251a44345fc878c41cb39378c91b 100644 (file)
@@ -70,6 +70,7 @@ typedef enum TokenType {
 
     Token_Type_Dot_Dot,
     Token_Type_Tilde_Tilde,
+    Token_Type_Question_Question,
 
     Token_Type_Symbol,
     Token_Type_Literal_String,
index b1a5f9841e0e2d3878f778b922b48ced5ce10542..8cc2e2ccc78da561c1b102a6dca7a6d4680f91c4 100644 (file)
@@ -131,6 +131,8 @@ const char *binaryop_string[Binary_Op_Count] = {
     "|>", "..", "->",
 
     "[]", "[]=", "^[]",
+    
+    "??"
 };
 
 const char* entity_state_strings[Entity_State_Count] = {
index 43079f6946a46927ecdd9bd0441cdbbec938317a..e85304ca68cd6f038edd4b903a5264676be0c59b 100644 (file)
@@ -450,6 +450,10 @@ whitespace_skipped:
     case '~':
         LITERAL_TOKEN("~~",          0, Token_Type_Tilde_Tilde);
         break;
+
+    case '?':
+        LITERAL_TOKEN("??",          0, Token_Type_Question_Question);
+        break;
     }
 
     // Symbols
index 76140ab75cb0d794f4a087d505e0e43dd4edae71..4e94e76d47e691aa2ffde8bb549f0df140ae79d9 100644 (file)
@@ -944,6 +944,8 @@ static inline i32 get_precedence(BinaryOp kind) {
         
         case Binary_Op_Method_Call:     return 10;
 
+        case Binary_Op_Coalesce:        return 11;
+
         default:                        return -1;
     }
 }
@@ -990,6 +992,7 @@ static BinaryOp binary_op_from_token_type(TokenType t) {
         case Token_Type_Dot_Dot:           return Binary_Op_Range;
         case '[':                          return Binary_Op_Subscript;
         case Token_Type_Right_Arrow:       return Binary_Op_Method_Call;
+        case Token_Type_Question_Question: return Binary_Op_Coalesce;
         default: return Binary_Op_Count;
     }
 }
index 3c5e85e3791574b8ccb3b7934027fcf53b010e93..87202b9d32995bfff825e8c0c91045071b5b53c4 100644 (file)
@@ -88,6 +88,13 @@ package core
         return #from_enclosing .{};
     }
 
+    catch :: macro (o: ?$T, body: Code) -> T {
+        value := o;
+        if value.has_value do return value.value;
+
+        #unquote body;
+    }
+
     hash :: (o: ?$T/core.hash.Hashable) -> u32 {
         if !o.has_value do return 0;
         return core.hash.to_u32(o.value);
@@ -100,6 +107,21 @@ package core
     return o1.value == o2.value;
 }
 
+#operator ?? macro (opt: ?$T, catch: Code) -> T {
+    value := opt;
+    if value do return value.value;
+
+    #unquote catch;
+}
+
+#operator ?? macro (opt: ?$T, default: T) -> T {
+    value := opt;
+    if value do return value.value;
+
+    return default;
+}
+
+
 #overload
 __implicit_bool_cast :: macro (o: ?$T) => o.has_value;