mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
add ?? prefix operator
This commit is contained in:
parent
b3459f64e7
commit
179443bd61
@ -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")
|
||||
|
||||
|
||||
@ -418,6 +418,7 @@ enum PrefixOp {
|
||||
PrefixOpMaybe,
|
||||
PrefixOpError,
|
||||
PrefixOpUnwrapError,
|
||||
PrefixOpUnwrapMaybe,
|
||||
};
|
||||
|
||||
struct AstNodePrefixOpExpr {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user