authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:11:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:11:46-07:00
log179443bd61c85c7d808304dc334bb407aa793988
tree5c743af7c986521be3ceaf366738daf22ece139e
parentb3459f64e795118c4c12890ed0fec75638b74a2c

add ?? prefix operator


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, ",")
143143
144StructLiteralField = "." "Symbol" "=" Expression144StructLiteralField = "." "Symbol" "=" Expression
145145
146PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"146PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??"
147147
148PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")148PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
149149
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};
422423
423struct AstNodePrefixOpExpr {424struct 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}
5859
...@@ -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
85static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,85static 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);
88static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
8889
89static TypeTableEntry *get_type_for_type_node(AstNode *node) {90static 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}
251251
252static 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
261static 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
271static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) {252static 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);
274255
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);
279257
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")
2118pub fn foo() {2118pub fn foo() {
2119 (fn_ptr ?? (unreachable){})()2119 (??fn_ptr)()
2120})SOURCE");2120})SOURCE");
2121}2121}
21222122