Commit 179443bd61
Changed files (8)
doc/langref.md
@@ -143,7 +143,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
StructLiteralField = "." "Symbol" "=" Expression
-PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
+PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??"
PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
src/all_types.hpp
@@ -418,6 +418,7 @@ enum PrefixOp {
PrefixOpMaybe,
PrefixOpError,
PrefixOpUnwrapError,
+ PrefixOpUnwrapMaybe,
};
struct AstNodePrefixOpExpr {
src/analyze.cpp
@@ -4207,6 +4207,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
return g->builtin_types.entry_invalid;
}
}
+ case PrefixOpUnwrapMaybe:
+ {
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+
+ if (type_entry->id == TypeTableEntryIdInvalid) {
+ return type_entry;
+ } else if (type_entry->id == TypeTableEntryIdMaybe) {
+ return type_entry->data.maybe.child_type;
+ } else {
+ add_node_error(g, expr_node,
+ buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
+ return g->builtin_types.entry_invalid;
+ }
+ }
}
zig_unreachable();
}
src/ast_render.cpp
@@ -53,6 +53,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
case PrefixOpMaybe: return "?";
case PrefixOpError: return "%";
case PrefixOpUnwrapError: return "%%";
+ case PrefixOpUnwrapMaybe: return "??";
}
}
@@ -696,8 +697,9 @@ static void render_node(AstRender *ar, AstNode *node) {
if (node->data.fn_call_expr.is_builtin) {
fprintf(ar->f, "@");
}
- render_node(ar, node->data.fn_call_expr.fn_ref_expr);
fprintf(ar->f, "(");
+ render_node(ar, node->data.fn_call_expr.fn_ref_expr);
+ fprintf(ar->f, ")(");
for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
AstNode *param = node->data.fn_call_expr.params.at(i);
if (i != 0) {
src/codegen.cpp
@@ -85,6 +85,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
LLVMValueRef target_ref, LLVMValueRef value,
TypeTableEntry *op1_type, TypeTableEntry *op2_type);
+static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
static TypeTableEntry *get_type_for_type_node(AstNode *node) {
Expr *expr = get_resolved_expr(node);
@@ -1005,6 +1006,12 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
return nullptr;
}
}
+ case PrefixOpUnwrapMaybe:
+ {
+ LLVMValueRef expr_val = gen_expr(g, expr_node);
+ // TODO in debug mode, put a panic here if null
+ return gen_unwrap_maybe(g, expr_node, expr_val);
+ }
}
zig_unreachable();
}
src/parseh.cpp
@@ -249,33 +249,11 @@ static AstNode *create_one_statement_block(Context *c, AstNode *statement) {
return node;
}
-static AstNode *create_container_init_node(Context *c, AstNode *type_node) {
- AstNode *node = create_node(c, NodeTypeContainerInitExpr);
- node->data.container_init_expr.kind = ContainerInitKindArray;
- node->data.container_init_expr.type = type_node;
-
- normalize_parent_ptrs(node);
- return node;
-}
-
-static AstNode *create_bin_op_node(Context *c, AstNode *lhs, BinOpType op, AstNode *rhs) {
- AstNode *node = create_node(c, NodeTypeBinOpExpr);
- node->data.bin_op_expr.op1 = lhs;
- node->data.bin_op_expr.bin_op = op;
- node->data.bin_op_expr.op2 = rhs;
-
- normalize_parent_ptrs(node);
- return node;
-}
-
static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) {
AstNode *node = create_node(c, NodeTypeFnDef);
node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type);
- AstNode *unreach_type_node = make_type_node(c, c->codegen->builtin_types.entry_unreachable);
- AstNode *unreach_node = create_container_init_node(c, unreach_type_node);
- AstNode *unwrap_node = create_bin_op_node(c, create_symbol_node(c, buf_ptr(var_name)),
- BinOpTypeUnwrapMaybe, unreach_node);
+ AstNode *unwrap_node = create_prefix_node(c, PrefixOpUnwrapMaybe, create_symbol_node(c, buf_ptr(var_name)));
AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr);
fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
src/parser.cpp
@@ -1206,6 +1206,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
case TokenIdMaybe: return PrefixOpMaybe;
case TokenIdPercent: return PrefixOpError;
case TokenIdPercentPercent: return PrefixOpUnwrapError;
+ case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
case TokenIdBoolAnd: return PrefixOpAddressOf;
default: return PrefixOpInvalid;
}
test/run_tests.cpp
@@ -2116,7 +2116,7 @@ extern void (*fn_ptr)(void);
"pub extern var fn_ptr: ?extern fn();",
R"SOURCE(#attribute("inline")
pub fn foo() {
- (fn_ptr ?? (unreachable){})()
+ (??fn_ptr)()
})SOURCE");
}