authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-24 01:34:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-24 01:34:57-07:00
log5c18826240fe983a30a9de6e04d3848643db7cf6
treed427af30c78ff59d768bf75cd194e008757ab7bf
parent37aae530098f10565ea3408891c901e086b8d5b8

introduce the error keyword and type

See #23

12 files changed, 223 insertions(+), 128 deletions(-)

doc/langref.md+4-4
......@@ -7,7 +7,7 @@ Root : many(TopLevelDecl) "EOF"
77
88TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl
99
10ErrorValueDecl : option(FnVisibleMod) "%." "Symbol"
10ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"
1111
1212VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
1313
......@@ -133,9 +133,9 @@ ContainerInitBody : list(StructLiteralField, ",") | list(Expression, ",")
133133
134134StructLiteralField : "." "Symbol" "=" Expression
135135
136PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?"
136PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%"
137137
138PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("%." "Symbol")
138PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
139139
140140ArrayType : "[" option(Expression) "]" option("const") PrefixOpExpression
141141
......@@ -143,7 +143,7 @@ GotoExpression: "goto" "Symbol"
143143
144144GroupedExpression : "(" Expression ")"
145145
146KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined"
146KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
147147```
148148
149149## Operator Precedence
doc/vim/syntax/zig.vim+1-1
......@@ -15,7 +15,7 @@ syn keyword zigRepeat while for
1515
1616syn keyword zigConstant null undefined
1717syn keyword zigKeyword fn import
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void unreachable type
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void unreachable type error
1919
2020syn keyword zigBoolean true false
2121
example/cat/main.zig+2-1
......@@ -10,6 +10,7 @@ import "std.zig";
1010// * %% binary operator
1111// * %% prefix operator
1212// * cast err type to string
13// * string equality
1314
1415pub fn main(args: [][]u8) %void => {
1516 const exe = args[0];
......@@ -39,7 +40,7 @@ pub fn main(args: [][]u8) %void => {
3940
4041fn usage(exe: []u8) %void => {
4142 %%stderr.print("Usage: {} [FILE]...\n", exe);
42 return %.Invalid;
43 return error.Invalid;
4344}
4445
4546fn cat_stream(is: InputStream) %void => {
example/guess_number/main.zig+4-4
......@@ -3,8 +3,8 @@ export executable "guess_number";
33import "std.zig";
44import "rand.zig";
55
6%.GetRandomFail;
7%.ReadInputFail;
6error GetRandomFail;
7error ReadInputFail;
88
99pub fn main(args: [][]u8) %void => {
1010 print_str("Welcome to the Guess Number Game in Zig.\n");
......@@ -15,7 +15,7 @@ pub fn main(args: [][]u8) %void => {
1515 if (err != @sizeof(u32)) {
1616 // TODO full error message
1717 fprint_str(stderr_fileno, "unable to get random bytes\n");
18 return %.GetRandomFail;
18 return error.GetRandomFail;
1919 }
2020
2121 var rand : Rand;
......@@ -31,7 +31,7 @@ pub fn main(args: [][]u8) %void => {
3131 if (readline(line_buf, &line_len) || line_len == line_buf.len) {
3232 // TODO full error message
3333 fprint_str(stderr_fileno, "unable to read input\n");
34 return %.ReadInputFail;
34 return error.ReadInputFail;
3535 }
3636
3737 var guess : u64;
src/all_types.hpp+11-10
......@@ -133,7 +133,6 @@ enum NodeType {
133133 NodeTypeNumberLiteral,
134134 NodeTypeStringLiteral,
135135 NodeTypeCharLiteral,
136 NodeTypeErrorLiteral,
137136 NodeTypeSymbol,
138137 NodeTypePrefixOpExpr,
139138 NodeTypeFnCallExpr,
......@@ -161,6 +160,7 @@ enum NodeType {
161160 NodeTypeContainerInitExpr,
162161 NodeTypeStructValueField,
163162 NodeTypeArrayType,
163 NodeTypeErrorType,
164164};
165165
166166struct AstNodeRoot {
......@@ -315,6 +315,7 @@ enum CastOp {
315315 CastOpToUnknownSizeArray,
316316 CastOpMaybeWrap,
317317 CastOpErrorWrap,
318 CastOpPureErrorWrap,
318319 CastOpPointerReinterpret,
319320 CastOpErrToInt,
320321};
......@@ -584,13 +585,6 @@ struct AstNodeNumberLiteral {
584585 Expr resolved_expr;
585586};
586587
587struct AstNodeErrorLiteral {
588 Buf symbol;
589
590 // populated by semantic analyzer
591 Expr resolved_expr;
592};
593
594588struct AstNodeStructValueField {
595589 Buf name;
596590 AstNode *expr;
......@@ -663,6 +657,11 @@ struct AstNodeArrayType {
663657 Expr resolved_expr;
664658};
665659
660struct AstNodeErrorType {
661 // populated by semantic analyzer
662 Expr resolved_expr;
663};
664
666665struct AstNode {
667666 enum NodeType type;
668667 int line;
......@@ -705,7 +704,6 @@ struct AstNode {
705704 AstNodeStringLiteral string_literal;
706705 AstNodeCharLiteral char_literal;
707706 AstNodeNumberLiteral number_literal;
708 AstNodeErrorLiteral error_literal;
709707 AstNodeContainerInitExpr container_init_expr;
710708 AstNodeStructValueField struct_val_field;
711709 AstNodeNullLiteral null_literal;
......@@ -715,6 +713,7 @@ struct AstNode {
715713 AstNodeBreakExpr break_expr;
716714 AstNodeContinueExpr continue_expr;
717715 AstNodeArrayType array_type;
716 AstNodeErrorType error_type;
718717 } data;
719718};
720719
......@@ -820,7 +819,8 @@ enum TypeTableEntryId {
820819 TypeTableEntryIdNumLitInt,
821820 TypeTableEntryIdUndefLit,
822821 TypeTableEntryIdMaybe,
823 TypeTableEntryIdError,
822 TypeTableEntryIdErrorUnion,
823 TypeTableEntryIdPureError,
824824 TypeTableEntryIdEnum,
825825 TypeTableEntryIdFn,
826826};
......@@ -961,6 +961,7 @@ struct CodeGen {
961961 TypeTableEntry *entry_num_lit_int;
962962 TypeTableEntry *entry_num_lit_float;
963963 TypeTableEntry *entry_undef;
964 TypeTableEntry *entry_pure_error;
964965 } builtin_types;
965966
966967 LLVMTargetDataRef target_data_ref;
src/analyze.cpp+111-50
......@@ -19,6 +19,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
1919static TypeTableEntry *unwrapped_node_type(AstNode *node);
2020static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2121 AstNode *node);
22static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
23 BlockContext *context, AstNode *node, Buf *err_name);
2224
2325static AstNode *first_executing_node(AstNode *node) {
2426 switch (node->type) {
......@@ -47,7 +49,6 @@ static AstNode *first_executing_node(AstNode *node) {
4749 case NodeTypeVariableDeclaration:
4850 case NodeTypeErrorValueDecl:
4951 case NodeTypeNumberLiteral:
50 case NodeTypeErrorLiteral:
5152 case NodeTypeStringLiteral:
5253 case NodeTypeCharLiteral:
5354 case NodeTypeSymbol:
......@@ -71,6 +72,7 @@ static AstNode *first_executing_node(AstNode *node) {
7172 case NodeTypeSwitchExpr:
7273 case NodeTypeSwitchProng:
7374 case NodeTypeArrayType:
75 case NodeTypeErrorType:
7476 case NodeTypeContainerInitExpr:
7577 return node;
7678 }
......@@ -110,7 +112,8 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
110112 case TypeTableEntryIdNumLitInt:
111113 case TypeTableEntryIdMaybe:
112114 case TypeTableEntryIdFn:
113 case TypeTableEntryIdError:
115 case TypeTableEntryIdErrorUnion:
116 case TypeTableEntryIdPureError:
114117 case TypeTableEntryIdUndefLit:
115118 // nothing to init
116119 break;
......@@ -200,7 +203,7 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
200203 "val", di_file, line, child_type->size_in_bits, child_type->align_in_bits, 0, 0,
201204 child_type->di_type),
202205 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
203 "maybe", di_file, line, 8, 8, 8, 0,
206 "maybe", di_file, line, 8, 8, child_type->size_in_bits, 0,
204207 child_type->di_type),
205208 };
206209 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
......@@ -223,7 +226,7 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
223226 if (child_type->error_parent) {
224227 return child_type->error_parent;
225228 } else {
226 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdError);
229 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorUnion);
227230 assert(child_type->type_ref);
228231 assert(child_type->di_type);
229232
......@@ -239,7 +242,38 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
239242 entry->di_type = g->err_tag_type->di_type;
240243
241244 } else {
242 zig_panic("TODO get_error_type non-void");
245 LLVMTypeRef elem_types[] = {
246 g->err_tag_type->type_ref,
247 child_type->type_ref,
248 };
249 entry->type_ref = LLVMStructType(elem_types, 2, false);
250 entry->size_in_bits = g->err_tag_type->size_in_bits + child_type->size_in_bits;
251 entry->align_in_bits = g->err_tag_type->align_in_bits;
252
253 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
254 LLVMZigDIFile *di_file = nullptr;
255 unsigned line = 0;
256 entry->di_type = LLVMZigCreateReplaceableCompositeType(g->dbuilder,
257 LLVMZigTag_DW_structure_type(), buf_ptr(&entry->name),
258 compile_unit_scope, di_file, line);
259
260 LLVMZigDIType *di_element_types[] = {
261 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
262 "tag", di_file, line, g->err_tag_type->size_in_bits, g->err_tag_type->align_in_bits,
263 0, 0, child_type->di_type),
264 LLVMZigCreateDebugMemberType(g->dbuilder, LLVMZigTypeToScope(entry->di_type),
265 "value", di_file, line, child_type->size_in_bits, child_type->align_in_bits,
266 g->err_tag_type->size_in_bits, 0, child_type->di_type),
267 };
268
269 LLVMZigDIType *replacement_di_type = LLVMZigCreateDebugStructType(g->dbuilder,
270 compile_unit_scope,
271 buf_ptr(&entry->name),
272 di_file, line, entry->size_in_bits, entry->align_in_bits, 0,
273 nullptr, di_element_types, 2, 0, nullptr, "");
274
275 LLVMZigReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type);
276 entry->di_type = replacement_di_type;
243277 }
244278
245279 child_type->error_parent = entry;
......@@ -1012,7 +1046,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
10121046 case NodeTypeArrayAccessExpr:
10131047 case NodeTypeSliceExpr:
10141048 case NodeTypeNumberLiteral:
1015 case NodeTypeErrorLiteral:
10161049 case NodeTypeStringLiteral:
10171050 case NodeTypeCharLiteral:
10181051 case NodeTypeBoolLiteral:
......@@ -1037,6 +1070,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
10371070 case NodeTypeStructValueField:
10381071 case NodeTypeContainerInitExpr:
10391072 case NodeTypeArrayType:
1073 case NodeTypeErrorType:
10401074 zig_unreachable();
10411075 }
10421076}
......@@ -1083,7 +1117,8 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
10831117 case TypeTableEntryIdArray:
10841118 case TypeTableEntryIdStruct:
10851119 case TypeTableEntryIdMaybe:
1086 case TypeTableEntryIdError:
1120 case TypeTableEntryIdErrorUnion:
1121 case TypeTableEntryIdPureError:
10871122 case TypeTableEntryIdEnum:
10881123 case TypeTableEntryIdFn:
10891124 return true;
......@@ -1166,8 +1201,8 @@ static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTable
11661201 }
11671202
11681203 // error
1169 if (expected_type->id == TypeTableEntryIdError &&
1170 actual_type->id == TypeTableEntryIdError)
1204 if (expected_type->id == TypeTableEntryIdErrorUnion &&
1205 actual_type->id == TypeTableEntryIdErrorUnion)
11711206 {
11721207 return types_match_const_cast_only(
11731208 expected_type->data.error.child_type,
......@@ -1224,11 +1259,11 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
12241259 prev_type = cur_type;
12251260 prev_node = cur_node;
12261261 }
1227 } else if (prev_type->id == TypeTableEntryIdError &&
1262 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&
12281263 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
12291264 {
12301265 continue;
1231 } else if (cur_type->id == TypeTableEntryIdError &&
1266 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&
12321267 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
12331268 {
12341269 prev_type = cur_type;
......@@ -1287,13 +1322,20 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
12871322 }
12881323
12891324 // implicit conversion from error child type to error type
1290 if (expected_type->id == TypeTableEntryIdError &&
1325 if (expected_type->id == TypeTableEntryIdErrorUnion &&
12911326 types_match_with_implicit_cast(g, expected_type->data.error.child_type, actual_type,
12921327 literal_node, reported_err))
12931328 {
12941329 return true;
12951330 }
12961331
1332 // implicit conversion from pure error to error union type
1333 if (expected_type->id == TypeTableEntryIdErrorUnion &&
1334 actual_type->id == TypeTableEntryIdPureError)
1335 {
1336 return true;
1337 }
1338
12971339 // implicit widening conversion
12981340 if (expected_type->id == TypeTableEntryIdInt &&
12991341 actual_type->id == TypeTableEntryIdInt &&
......@@ -1695,12 +1737,11 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
16951737
16961738 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
16971739 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);
1740 Buf *field_name = &node->data.field_access_expr.field_name;
16981741
16991742 if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
17001743 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
17011744 {
1702 Buf *field_name = &node->data.field_access_expr.field_name;
1703
17041745 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
17051746 struct_type : struct_type->data.pointer.child_type;
17061747
......@@ -1713,15 +1754,14 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
17131754 return g->builtin_types.entry_invalid;
17141755 }
17151756 } else if (struct_type->id == TypeTableEntryIdArray) {
1716 Buf *name = &node->data.field_access_expr.field_name;
1717 if (buf_eql_str(name, "len")) {
1757 if (buf_eql_str(field_name, "len")) {
17181758 return g->builtin_types.entry_isize;
1719 } else if (buf_eql_str(name, "ptr")) {
1759 } else if (buf_eql_str(field_name, "ptr")) {
17201760 // TODO determine whether the pointer should be const
17211761 return get_pointer_to_type(g, struct_type->data.array.child_type, false);
17221762 } else {
17231763 add_node_error(g, node,
1724 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
1764 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
17251765 buf_ptr(&struct_type->name)));
17261766 return g->builtin_types.entry_invalid;
17271767 }
......@@ -1731,8 +1771,9 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
17311771 if (enum_type->id == TypeTableEntryIdInvalid) {
17321772 return g->builtin_types.entry_invalid;
17331773 } else if (enum_type->id == TypeTableEntryIdEnum) {
1734 Buf *field_name = &node->data.field_access_expr.field_name;
17351774 return analyze_enum_value_expr(g, import, context, node, nullptr, enum_type, field_name);
1775 } else if (enum_type->id == TypeTableEntryIdPureError) {
1776 return analyze_error_literal_expr(g, import, context, node, field_name);
17361777 } else {
17371778 add_node_error(g, node,
17381779 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
......@@ -1846,7 +1887,7 @@ static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node,
18461887 Expr *expr = get_resolved_expr(node);
18471888 expr->const_val.ok = true;
18481889 expr->const_val.data.x_err.err = err;
1849 return get_error_type(g, g->builtin_types.entry_void);
1890 return g->builtin_types.entry_pure_error;
18501891}
18511892
18521893static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value) {
......@@ -1959,6 +2000,21 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
19592000 return resolved_type;
19602001}
19612002
2003static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2004 BlockContext *context, AstNode *node, Buf *err_name)
2005{
2006 auto err_table_entry = import->block_context->error_table.maybe_get(err_name);
2007
2008 if (err_table_entry) {
2009 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
2010 }
2011
2012 add_node_error(g, node,
2013 buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
2014
2015 return get_error_type(g, g->builtin_types.entry_void);
2016}
2017
19622018
19632019static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
19642020 TypeTableEntry *expected_type, AstNode *node)
......@@ -2564,23 +2620,6 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
25642620 }
25652621}
25662622
2567static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2568 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
2569{
2570 Buf *err_name = &node->data.error_literal.symbol;
2571
2572 auto err_table_entry = import->block_context->error_table.maybe_get(err_name);
2573
2574 if (err_table_entry) {
2575 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
2576 }
2577
2578 add_node_error(g, node,
2579 buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
2580
2581 return get_error_type(g, g->builtin_types.entry_void);
2582}
2583
25842623static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
25852624 TypeTableEntry *expected_type, AstNode *node)
25862625{
......@@ -2906,6 +2945,10 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
29062945 const_val->data.x_err.payload = other_val;
29072946 const_val->ok = true;
29082947 break;
2948 case CastOpPureErrorWrap:
2949 const_val->data.x_err.err = other_val->data.x_err.err;
2950 const_val->ok = true;
2951 break;
29092952 case CastOpErrToInt:
29102953 {
29112954 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
......@@ -3007,7 +3050,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
30073050 }
30083051
30093052 // explicit cast from child type of error type to error type
3010 if (wanted_type->id == TypeTableEntryIdError) {
3053 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
30113054 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
30123055 node->data.fn_call_expr.cast_op = CastOpErrorWrap;
30133056 eval_const_expr_implicit_cast(g, node, expr_node);
......@@ -3025,6 +3068,15 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
30253068 }
30263069 }
30273070
3071 // explicit cast from pure error to error union type
3072 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
3073 actual_type->id == TypeTableEntryIdPureError)
3074 {
3075 node->data.fn_call_expr.cast_op = CastOpPureErrorWrap;
3076 eval_const_expr_implicit_cast(g, node, expr_node);
3077 return wanted_type;
3078 }
3079
30283080 // explicit cast from number literal to another type
30293081 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
30303082 actual_type->id == TypeTableEntryIdNumLitInt)
......@@ -3039,8 +3091,10 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
30393091 }
30403092
30413093 // explicit cast from %void to integer type which can fit it
3042 if (actual_type->id == TypeTableEntryIdError &&
3043 actual_type->data.error.child_type->size_in_bits == 0 &&
3094 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
3095 actual_type->data.error.child_type->size_in_bits == 0;
3096 bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError;
3097 if ((actual_type_is_void_err || actual_type_is_pure_err) &&
30443098 wanted_type->id == TypeTableEntryIdInt)
30453099 {
30463100 BigNum bn;
......@@ -3754,9 +3808,6 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
37543808 case NodeTypeNumberLiteral:
37553809 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
37563810 break;
3757 case NodeTypeErrorLiteral:
3758 return_type = analyze_error_literal_expr(g, import, context, expected_type, node);
3759 break;
37603811 case NodeTypeStringLiteral:
37613812 return_type = analyze_string_literal_expr(g, import, context, expected_type, node);
37623813 break;
......@@ -3794,6 +3845,9 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
37943845 case NodeTypeArrayType:
37953846 return_type = analyze_array_type(g, import, context, expected_type, node);
37963847 break;
3848 case NodeTypeErrorType:
3849 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error);
3850 break;
37973851 case NodeTypeSwitchExpr:
37983852 return_type = analyze_switch_expr(g, import, context, expected_type, node);
37993853 break;
......@@ -3933,7 +3987,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
39333987 case NodeTypeArrayAccessExpr:
39343988 case NodeTypeSliceExpr:
39353989 case NodeTypeNumberLiteral:
3936 case NodeTypeErrorLiteral:
39373990 case NodeTypeStringLiteral:
39383991 case NodeTypeCharLiteral:
39393992 case NodeTypeBoolLiteral:
......@@ -3958,6 +4011,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
39584011 case NodeTypeStructValueField:
39594012 case NodeTypeContainerInitExpr:
39604013 case NodeTypeArrayType:
4014 case NodeTypeErrorType:
39614015 zig_unreachable();
39624016 }
39634017}
......@@ -3967,7 +4021,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
39674021{
39684022 switch (node->type) {
39694023 case NodeTypeNumberLiteral:
3970 case NodeTypeErrorLiteral:
39714024 case NodeTypeStringLiteral:
39724025 case NodeTypeCharLiteral:
39734026 case NodeTypeBoolLiteral:
......@@ -3977,6 +4030,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
39774030 case NodeTypeBreak:
39784031 case NodeTypeContinue:
39794032 case NodeTypeErrorValueDecl:
4033 case NodeTypeErrorType:
39804034 // no dependencies on other top level declarations
39814035 break;
39824036 case NodeTypeSymbol:
......@@ -4286,7 +4340,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
42864340 case NodeTypeArrayAccessExpr:
42874341 case NodeTypeSliceExpr:
42884342 case NodeTypeNumberLiteral:
4289 case NodeTypeErrorLiteral:
42904343 case NodeTypeStringLiteral:
42914344 case NodeTypeCharLiteral:
42924345 case NodeTypeBoolLiteral:
......@@ -4311,6 +4364,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
43114364 case NodeTypeContainerInitExpr:
43124365 case NodeTypeStructValueField:
43134366 case NodeTypeArrayType:
4367 case NodeTypeErrorType:
43144368 zig_unreachable();
43154369 }
43164370}
......@@ -4419,7 +4473,14 @@ void semantic_analyze(CodeGen *g) {
44194473 }
44204474 }
44214475
4422 g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);
4476 {
4477 g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);
4478
4479 g->builtin_types.entry_pure_error->type_ref = g->err_tag_type->type_ref;
4480 g->builtin_types.entry_pure_error->size_in_bits = g->err_tag_type->size_in_bits;
4481 g->builtin_types.entry_pure_error->align_in_bits = g->err_tag_type->align_in_bits;
4482 g->builtin_types.entry_pure_error->di_type = g->err_tag_type->di_type;
4483 }
44234484
44244485 {
44254486 auto it = g->import_table.entry_iterator();
......@@ -4493,8 +4554,6 @@ Expr *get_resolved_expr(AstNode *node) {
44934554 return &node->data.container_init_expr.resolved_expr;
44944555 case NodeTypeNumberLiteral:
44954556 return &node->data.number_literal.resolved_expr;
4496 case NodeTypeErrorLiteral:
4497 return &node->data.error_literal.resolved_expr;
44984557 case NodeTypeStringLiteral:
44994558 return &node->data.string_literal.resolved_expr;
45004559 case NodeTypeBlock:
......@@ -4521,6 +4580,8 @@ Expr *get_resolved_expr(AstNode *node) {
45214580 return &node->data.label.resolved_expr;
45224581 case NodeTypeArrayType:
45234582 return &node->data.array_type.resolved_expr;
4583 case NodeTypeErrorType:
4584 return &node->data.error_type.resolved_expr;
45244585 case NodeTypeSwitchExpr:
45254586 return &node->data.switch_expr.resolved_expr;
45264587 case NodeTypeSwitchProng:
......@@ -4554,7 +4615,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
45544615 case NodeTypeErrorValueDecl:
45554616 return &node->data.error_value_decl.top_level_decl;
45564617 case NodeTypeNumberLiteral:
4557 case NodeTypeErrorLiteral:
45584618 case NodeTypeReturnExpr:
45594619 case NodeTypeBinOpExpr:
45604620 case NodeTypePrefixOpExpr:
......@@ -4593,6 +4653,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
45934653 case NodeTypeStructField:
45944654 case NodeTypeStructValueField:
45954655 case NodeTypeArrayType:
4656 case NodeTypeErrorType:
45964657 zig_unreachable();
45974658 }
45984659 zig_unreachable();
src/codegen.cpp+39-7
......@@ -306,7 +306,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
306306 case CastOpNoop:
307307 return expr_val;
308308 case CastOpErrToInt:
309 assert(actual_type->id == TypeTableEntryIdError);
309 assert(actual_type->id == TypeTableEntryIdErrorUnion);
310310 if (actual_type->data.error.child_type->size_in_bits == 0) {
311311 return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
312312 } else {
......@@ -330,12 +330,19 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
330330 return cast_expr->tmp_ptr;
331331 }
332332 case CastOpErrorWrap:
333 assert(wanted_type->id == TypeTableEntryIdError);
333 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
334334 if (wanted_type->data.error.child_type->size_in_bits == 0) {
335335 return LLVMConstNull(g->err_tag_type->type_ref);
336336 } else {
337337 zig_panic("TODO");
338338 }
339 case CastOpPureErrorWrap:
340 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
341 if (wanted_type->data.error.child_type->size_in_bits == 0) {
342 return expr_val;
343 } else {
344 zig_panic("TODO");
345 }
339346 case CastOpPtrToInt:
340347 add_debug_source_node(g, node);
341348 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
......@@ -1292,7 +1299,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
12921299 return nullptr;
12931300 }
12941301
1295 assert(!use_expr_value || then_type->id == TypeTableEntryIdError);
1302 assert(!use_expr_value || then_type->id == TypeTableEntryIdErrorUnion);
12961303
12971304 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
12981305 LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
......@@ -2011,7 +2018,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
20112018 return gen_container_init_expr(g, node);
20122019 case NodeTypeSwitchExpr:
20132020 return gen_switch_expr(g, node);
2014 case NodeTypeErrorLiteral:
20152021 case NodeTypeNumberLiteral:
20162022 case NodeTypeBoolLiteral:
20172023 case NodeTypeStringLiteral:
......@@ -2033,6 +2039,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
20332039 case NodeTypeStructField:
20342040 case NodeTypeStructValueField:
20352041 case NodeTypeArrayType:
2042 case NodeTypeErrorType:
20362043 case NodeTypeSwitchProng:
20372044 case NodeTypeSwitchRange:
20382045 case NodeTypeErrorValueDecl:
......@@ -2063,6 +2070,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
20632070
20642071 if (type_entry->id == TypeTableEntryIdInt) {
20652072 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
2073 } else if (type_entry->id == TypeTableEntryIdPureError) {
2074 assert(const_val->data.x_err.err);
2075 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, const_val->data.x_err.err->value, false);
20662076 } else if (type_entry->id == TypeTableEntryIdFloat) {
20672077 if (const_val->data.x_bignum.kind == BigNumKindFloat) {
20682078 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
......@@ -2148,12 +2158,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
21482158 } else {
21492159 return global_value;
21502160 }
2151 } else if (type_entry->id == TypeTableEntryIdError) {
2152 if (type_entry->data.error.child_type->size_in_bits == 0) {
2161 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
2162 TypeTableEntry *child_type = type_entry->data.error.child_type;
2163 if (child_type->size_in_bits == 0) {
21532164 uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0;
21542165 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
21552166 } else {
2156 zig_panic("TODO");
2167 LLVMValueRef err_tag_value;
2168 LLVMValueRef err_payload_value;
2169 if (const_val->data.x_err.err) {
2170 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err.err->value, false);
2171 err_payload_value = LLVMConstNull(child_type->type_ref);
2172 } else {
2173 err_tag_value = LLVMConstNull(g->err_tag_type->type_ref);
2174 err_payload_value = gen_const_val(g, child_type, const_val->data.x_err.payload);
2175 }
2176 LLVMValueRef fields[] = {
2177 err_tag_value,
2178 err_payload_value,
2179 };
2180 return LLVMConstStruct(fields, 2, false);
21572181 }
21582182 } else {
21592183 zig_unreachable();
......@@ -2557,6 +2581,14 @@ static void define_builtin_types(CodeGen *g) {
25572581 g->builtin_types.entry_type = entry;
25582582 g->primitive_type_table.put(&entry->name, entry);
25592583 }
2584 {
2585 // partially complete the error type. we complete it later after we know
2586 // error_value_count.
2587 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
2588 buf_init_from_str(&entry->name, "error");
2589 g->builtin_types.entry_pure_error = entry;
2590 g->primitive_type_table.put(&entry->name, entry);
2591 }
25602592
25612593 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
25622594 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
src/parser.cpp+18-22
......@@ -113,8 +113,6 @@ const char *node_type_str(NodeType node_type) {
113113 return "ErrorValueDecl";
114114 case NodeTypeNumberLiteral:
115115 return "NumberLiteral";
116 case NodeTypeErrorLiteral:
117 return "ErrorLiteral";
118116 case NodeTypeStringLiteral:
119117 return "StringLiteral";
120118 case NodeTypeCharLiteral:
......@@ -167,6 +165,8 @@ const char *node_type_str(NodeType node_type) {
167165 return "ContainerInitExpr";
168166 case NodeTypeArrayType:
169167 return "ArrayType";
168 case NodeTypeErrorType:
169 return "ErrorType";
170170 }
171171 zig_unreachable();
172172}
......@@ -313,11 +313,6 @@ void ast_print(AstNode *node, int indent) {
313313 }
314314 break;
315315 }
316 case NodeTypeErrorLiteral:
317 {
318 fprintf(stderr, "%s '%s'", node_type_str(node->type), buf_ptr(&node->data.error_literal.symbol));
319 break;
320 }
321316 case NodeTypeStringLiteral:
322317 {
323318 const char *c = node->data.string_literal.c ? "c" : "";
......@@ -465,6 +460,9 @@ void ast_print(AstNode *node, int indent) {
465460 ast_print(node->data.array_type.child_type, indent + 2);
466461 break;
467462 }
463 case NodeTypeErrorType:
464 fprintf(stderr, "%s\n", node_type_str(node->type));
465 break;
468466 }
469467}
470468
......@@ -1372,8 +1370,8 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
13721370}
13731371
13741372/*
1375PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("%." "Symbol")
1376KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined"
1373PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
1374KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
13771375*/
13781376static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
13791377 Token *token = &pc->tokens->at(*token_index);
......@@ -1419,6 +1417,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
14191417 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);
14201418 *token_index += 1;
14211419 return node;
1420 } else if (token->id == TokenIdKeywordError) {
1421 AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
1422 *token_index += 1;
1423 return node;
14221424 } else if (token->id == TokenIdAtSign) {
14231425 *token_index += 1;
14241426 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
......@@ -1448,12 +1450,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
14481450
14491451 ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name);
14501452 return node;
1451 } else if (token->id == TokenIdPercentDot) {
1452 *token_index += 1;
1453 Token *symbol_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
1454 AstNode *node = ast_create_node(pc, NodeTypeErrorLiteral, token);
1455 ast_buf_from_token(pc, symbol_tok, &node->data.error_literal.symbol);
1456 return node;
14571453 }
14581454
14591455 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
......@@ -2969,7 +2965,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
29692965}
29702966
29712967/*
2972ErrorValueDecl : option(FnVisibleMod) "%." "Symbol"
2968ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"
29732969*/
29742970static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, bool mandatory) {
29752971 Token *first_token = &pc->tokens->at(*token_index);
......@@ -2978,7 +2974,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b
29782974
29792975 if (first_token->id == TokenIdKeywordPub) {
29802976 Token *next_token = &pc->tokens->at(*token_index + 1);
2981 if (next_token->id == TokenIdPercentDot) {
2977 if (next_token->id == TokenIdKeywordError) {
29822978 visib_mod = VisibModPub;
29832979 *token_index += 2;
29842980 } else if (mandatory) {
......@@ -2988,7 +2984,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b
29882984 }
29892985 } else if (first_token->id == TokenIdKeywordExport) {
29902986 Token *next_token = &pc->tokens->at(*token_index + 1);
2991 if (next_token->id == TokenIdPercentDot) {
2987 if (next_token->id == TokenIdKeywordError) {
29922988 visib_mod = VisibModExport;
29932989 *token_index += 2;
29942990 } else if (mandatory) {
......@@ -2996,7 +2992,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b
29962992 } else {
29972993 return nullptr;
29982994 }
2999 } else if (first_token->id == TokenIdPercentDot) {
2995 } else if (first_token->id == TokenIdKeywordError) {
30002996 visib_mod = VisibModPrivate;
30012997 *token_index += 1;
30022998 } else if (mandatory) {
......@@ -3177,9 +3173,6 @@ void normalize_parent_ptrs(AstNode *node) {
31773173 case NodeTypeCharLiteral:
31783174 // none
31793175 break;
3180 case NodeTypeErrorLiteral:
3181 // none
3182 break;
31833176 case NodeTypeSymbol:
31843177 // none
31853178 break;
......@@ -3290,5 +3283,8 @@ void normalize_parent_ptrs(AstNode *node) {
32903283 set_field(&node->data.array_type.size);
32913284 set_field(&node->data.array_type.child_type);
32923285 break;
3286 case NodeTypeErrorType:
3287 // none
3288 break;
32933289 }
32943290}
src/tokenizer.cpp+3
......@@ -247,6 +247,8 @@ static void end_token(Tokenize *t) {
247247 t->cur_tok->id = TokenIdKeywordSwitch;
248248 } else if (mem_eql_str(token_mem, token_len, "undefined")) {
249249 t->cur_tok->id = TokenIdKeywordUndefined;
250 } else if (mem_eql_str(token_mem, token_len, "error")) {
251 t->cur_tok->id = TokenIdKeywordError;
250252 }
251253
252254 t->cur_tok = nullptr;
......@@ -1046,6 +1048,7 @@ const char * token_name(TokenId id) {
10461048 case TokenIdKeywordNoAlias: return "noalias";
10471049 case TokenIdKeywordSwitch: return "switch";
10481050 case TokenIdKeywordUndefined: return "undefined";
1051 case TokenIdKeywordError: return "error";
10491052 case TokenIdLParen: return "(";
10501053 case TokenIdRParen: return ")";
10511054 case TokenIdComma: return ",";
src/tokenizer.hpp+1
......@@ -38,6 +38,7 @@ enum TokenId {
3838 TokenIdKeywordNoAlias,
3939 TokenIdKeywordSwitch,
4040 TokenIdKeywordUndefined,
41 TokenIdKeywordError,
4142 TokenIdLParen,
4243 TokenIdRParen,
4344 TokenIdComma,
std/std.zig+23-23
......@@ -25,15 +25,15 @@ pub var stderr = OutStream {
2525};
2626*/
2727
28pub %.Unexpected;
29pub %.DiskQuota;
30pub %.FileTooBig;
31pub %.SigInterrupt;
32pub %.Io;
33pub %.NoSpaceLeft;
34pub %.BadPerm;
35pub %.PipeFail;
36pub %.Invalid;
28pub error Unexpected;
29pub error DiskQuota;
30pub error FileTooBig;
31pub error SigInterrupt;
32pub error Io;
33pub error NoSpaceLeft;
34pub error BadPerm;
35pub error PipeFail;
36pub error Invalid;
3737
3838const buffer_size = 4 * 1024;
3939const max_u64_base10_digits = 20;
......@@ -100,14 +100,14 @@ pub struct OutStream {
100100 os.index = 0;
101101 switch (write(os.fd, os.buffer.ptr, amt_to_write)) {
102102 EINVAL => unreachable{},
103 EDQUOT => %.DiskQuota,
104 EFBIG => %.FileTooBig,
105 EINTR => %.SigInterrupt,
106 EIO => %.Io,
107 ENOSPC => %.NoSpaceLeft,
108 EPERM => %.BadPerm,
109 EPIPE => %.PipeFail,
110 else => %.Unexpected,
103 EDQUOT => error.DiskQuota,
104 EFBIG => error.FileTooBig,
105 EINTR => error.SigInterrupt,
106 EIO => error.Io,
107 ENOSPC => error.NoSpaceLeft,
108 EPERM => error.BadPerm,
109 EPIPE => error.PipeFail,
110 else => error.Unexpected,
111111 }
112112 }
113113}
......@@ -121,10 +121,10 @@ pub struct InStream {
121121 switch (-amt_read) {
122122 EINVAL => unreachable{},
123123 EFAULT => unreachable{},
124 EBADF => %.BadFd,
125 EINTR => %.SigInterrupt,
126 EIO => %.Io,
127 else => %.Unexpected,
124 EBADF => error.BadFd,
125 EINTR => error.SigInterrupt,
126 EIO => error.Io,
127 else => error.Unexpected,
128128 }
129129 }
130130 return amt_read;
......@@ -136,8 +136,8 @@ pub fn os_get_random_bytes(buf: []u8) %void => {
136136 switch (getrandom(buf.ptr, buf.len, 0)) {
137137 EINVAL => unreachable{},
138138 EFAULT => unreachable{},
139 EINTR => %.SigInterrupt,
140 else => %.Unexpected,
139 EINTR => error.SigInterrupt,
140 else => error.Unexpected,
141141 }
142142}
143143*/
test/run_tests.cpp+6-6
......@@ -1213,11 +1213,11 @@ pub fn main(args: [][]u8) %void => {
12131213
12141214 add_simple_case("error values", R"SOURCE(
12151215import "std.zig";
1216%.err1;
1217%.err2;
1216error err1;
1217error err2;
12181218pub fn main(args: [][]u8) %void => {
1219 const a = i32(%.err1);
1220 const b = i32(%.err2);
1219 const a = i32(error.err1);
1220 const b = i32(error.err2);
12211221 if (a == b) {
12221222 print_str("BAD\n");
12231223 }
......@@ -1467,8 +1467,8 @@ enum A {}
14671467 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'");
14681468
14691469 add_compile_fail_case("redefinition of error values", R"SOURCE(
1470%.A;
1471%.A;
1470error A;
1471error A;
14721472 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of error 'A'");
14731473
14741474 add_compile_fail_case("redefinition of global variables", R"SOURCE(