| author | |
| committer | |
| log | 179443bd61c85c7d808304dc334bb407aa793988 |
| tree | 5c743af7c986521be3ceaf366738daf22ece139e |
| parent | b3459f64e795118c4c12890ed0fec75638b74a2c |
8 files changed, 29 insertions(+), 26 deletions(-)
doc/langref.md+1-1| ... | @@ -143,7 +143,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") | ... | @@ -143,7 +143,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 143 | 143 | ||
| 144 | StructLiteralField = "." "Symbol" "=" Expression | 144 | StructLiteralField = "." "Symbol" "=" Expression |
| 145 | 145 | ||
| 146 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | 146 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" |
| 147 | 147 | ||
| 148 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol") | 148 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol") |
| 149 | 149 |
src/all_types.hpp+1| ... | @@ -418,6 +418,7 @@ enum PrefixOp { | ... | @@ -418,6 +418,7 @@ enum PrefixOp { |
| 418 | PrefixOpMaybe, | 418 | PrefixOpMaybe, |
| 419 | PrefixOpError, | 419 | PrefixOpError, |
| 420 | PrefixOpUnwrapError, | 420 | PrefixOpUnwrapError, |
| 421 | PrefixOpUnwrapMaybe, | ||
| 421 | }; | 422 | }; |
| 422 | 423 | ||
| 423 | struct AstNodePrefixOpExpr { | 424 | struct AstNodePrefixOpExpr { |
src/analyze.cpp+14| ... | @@ -4207,6 +4207,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo | ... | @@ -4207,6 +4207,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 4207 | return g->builtin_types.entry_invalid; | 4207 | return g->builtin_types.entry_invalid; |
| 4208 | } | 4208 | } |
| 4209 | } | 4209 | } |
| 4210 | case PrefixOpUnwrapMaybe: | ||
| 4211 | { | ||
| 4212 | TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node); | ||
| 4213 | |||
| 4214 | if (type_entry->id == TypeTableEntryIdInvalid) { | ||
| 4215 | return type_entry; | ||
| 4216 | } else if (type_entry->id == TypeTableEntryIdMaybe) { | ||
| 4217 | return type_entry->data.maybe.child_type; | ||
| 4218 | } else { | ||
| 4219 | add_node_error(g, expr_node, | ||
| 4220 | buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name))); | ||
| 4221 | return g->builtin_types.entry_invalid; | ||
| 4222 | } | ||
| 4223 | } | ||
| 4210 | } | 4224 | } |
| 4211 | zig_unreachable(); | 4225 | zig_unreachable(); |
| 4212 | } | 4226 | } |
src/ast_render.cpp+3-1| ... | @@ -53,6 +53,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) { | ... | @@ -53,6 +53,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 53 | case PrefixOpMaybe: return "?"; | 53 | case PrefixOpMaybe: return "?"; |
| 54 | case PrefixOpError: return "%"; | 54 | case PrefixOpError: return "%"; |
| 55 | case PrefixOpUnwrapError: return "%%"; | 55 | case PrefixOpUnwrapError: return "%%"; |
| 56 | case PrefixOpUnwrapMaybe: return "??"; | ||
| 56 | } | 57 | } |
| 57 | } | 58 | } |
| 58 | 59 | ||
| ... | @@ -696,8 +697,9 @@ static void render_node(AstRender *ar, AstNode *node) { | ... | @@ -696,8 +697,9 @@ static void render_node(AstRender *ar, AstNode *node) { |
| 696 | if (node->data.fn_call_expr.is_builtin) { | 697 | if (node->data.fn_call_expr.is_builtin) { |
| 697 | fprintf(ar->f, "@"); | 698 | fprintf(ar->f, "@"); |
| 698 | } | 699 | } |
| 699 | render_node(ar, node->data.fn_call_expr.fn_ref_expr); | ||
| 700 | fprintf(ar->f, "("); | 700 | fprintf(ar->f, "("); |
| 701 | render_node(ar, node->data.fn_call_expr.fn_ref_expr); | ||
| 702 | fprintf(ar->f, ")("); | ||
| 701 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { | 703 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { |
| 702 | AstNode *param = node->data.fn_call_expr.params.at(i); | 704 | AstNode *param = node->data.fn_call_expr.params.at(i); |
| 703 | if (i != 0) { | 705 | if (i != 0) { |
src/codegen.cpp+7| ... | @@ -85,6 +85,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa | ... | @@ -85,6 +85,7 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 85 | static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op, | 85 | static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op, |
| 86 | LLVMValueRef target_ref, LLVMValueRef value, | 86 | LLVMValueRef target_ref, LLVMValueRef value, |
| 87 | TypeTableEntry *op1_type, TypeTableEntry *op2_type); | 87 | TypeTableEntry *op1_type, TypeTableEntry *op2_type); |
| 88 | static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref); | ||
| 88 | 89 | ||
| 89 | static TypeTableEntry *get_type_for_type_node(AstNode *node) { | 90 | static TypeTableEntry *get_type_for_type_node(AstNode *node) { |
| 90 | Expr *expr = get_resolved_expr(node); | 91 | Expr *expr = get_resolved_expr(node); |
| ... | @@ -1005,6 +1006,12 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -1005,6 +1006,12 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1005 | return nullptr; | 1006 | return nullptr; |
| 1006 | } | 1007 | } |
| 1007 | } | 1008 | } |
| 1009 | case PrefixOpUnwrapMaybe: | ||
| 1010 | { | ||
| 1011 | LLVMValueRef expr_val = gen_expr(g, expr_node); | ||
| 1012 | // TODO in debug mode, put a panic here if null | ||
| 1013 | return gen_unwrap_maybe(g, expr_node, expr_val); | ||
| 1014 | } | ||
| 1008 | } | 1015 | } |
| 1009 | zig_unreachable(); | 1016 | zig_unreachable(); |
| 1010 | } | 1017 | } |
src/parseh.cpp+1-23| ... | @@ -249,33 +249,11 @@ static AstNode *create_one_statement_block(Context *c, AstNode *statement) { | ... | @@ -249,33 +249,11 @@ static AstNode *create_one_statement_block(Context *c, AstNode *statement) { |
| 249 | return node; | 249 | return node; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | static AstNode *create_container_init_node(Context *c, AstNode *type_node) { | ||
| 253 | AstNode *node = create_node(c, NodeTypeContainerInitExpr); | ||
| 254 | node->data.container_init_expr.kind = ContainerInitKindArray; | ||
| 255 | node->data.container_init_expr.type = type_node; | ||
| 256 | |||
| 257 | normalize_parent_ptrs(node); | ||
| 258 | return node; | ||
| 259 | } | ||
| 260 | |||
| 261 | static AstNode *create_bin_op_node(Context *c, AstNode *lhs, BinOpType op, AstNode *rhs) { | ||
| 262 | AstNode *node = create_node(c, NodeTypeBinOpExpr); | ||
| 263 | node->data.bin_op_expr.op1 = lhs; | ||
| 264 | node->data.bin_op_expr.bin_op = op; | ||
| 265 | node->data.bin_op_expr.op2 = rhs; | ||
| 266 | |||
| 267 | normalize_parent_ptrs(node); | ||
| 268 | return node; | ||
| 269 | } | ||
| 270 | |||
| 271 | static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) { | 252 | static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) { |
| 272 | AstNode *node = create_node(c, NodeTypeFnDef); | 253 | AstNode *node = create_node(c, NodeTypeFnDef); |
| 273 | node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type); | 254 | node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type); |
| 274 | 255 | ||
| 275 | AstNode *unreach_type_node = make_type_node(c, c->codegen->builtin_types.entry_unreachable); | 256 | AstNode *unwrap_node = create_prefix_node(c, PrefixOpUnwrapMaybe, create_symbol_node(c, buf_ptr(var_name))); |
| 276 | AstNode *unreach_node = create_container_init_node(c, unreach_type_node); | ||
| 277 | AstNode *unwrap_node = create_bin_op_node(c, create_symbol_node(c, buf_ptr(var_name)), | ||
| 278 | BinOpTypeUnwrapMaybe, unreach_node); | ||
| 279 | 257 | ||
| 280 | AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr); | 258 | AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr); |
| 281 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; | 259 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; |
src/parser.cpp+1| ... | @@ -1206,6 +1206,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { | ... | @@ -1206,6 +1206,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 1206 | case TokenIdMaybe: return PrefixOpMaybe; | 1206 | case TokenIdMaybe: return PrefixOpMaybe; |
| 1207 | case TokenIdPercent: return PrefixOpError; | 1207 | case TokenIdPercent: return PrefixOpError; |
| 1208 | case TokenIdPercentPercent: return PrefixOpUnwrapError; | 1208 | case TokenIdPercentPercent: return PrefixOpUnwrapError; |
| 1209 | case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe; | ||
| 1209 | case TokenIdBoolAnd: return PrefixOpAddressOf; | 1210 | case TokenIdBoolAnd: return PrefixOpAddressOf; |
| 1210 | default: return PrefixOpInvalid; | 1211 | default: return PrefixOpInvalid; |
| 1211 | } | 1212 | } |
test/run_tests.cpp+1-1| ... | @@ -2116,7 +2116,7 @@ extern void (*fn_ptr)(void); | ... | @@ -2116,7 +2116,7 @@ extern void (*fn_ptr)(void); |
| 2116 | "pub extern var fn_ptr: ?extern fn();", | 2116 | "pub extern var fn_ptr: ?extern fn();", |
| 2117 | R"SOURCE(#attribute("inline") | 2117 | R"SOURCE(#attribute("inline") |
| 2118 | pub fn foo() { | 2118 | pub fn foo() { |
| 2119 | (fn_ptr ?? (unreachable){})() | 2119 | (??fn_ptr)() |
| 2120 | })SOURCE"); | 2120 | })SOURCE"); |
| 2121 | } | 2121 | } |
| 2122 | 2122 |