authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-25 15:45:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-25 15:45:05-07:00
logdeb35868841fc3eb99228fe102a5b8ed1991d51f
treee84077cf298eec6f95cd3a75f1f05cd4cb0b501f
parentc0dc0ca6c90649f157dfcb43c7ec69fa4b5f6b09

implement %% prefix operator

See #23 also make undefined constants use llvm undef value

9 files changed, 54 insertions(+), 20 deletions(-)

README.md+2-2
...@@ -48,8 +48,8 @@ compromises backward compatibility....@@ -48,8 +48,8 @@ compromises backward compatibility.
48### Current Status48### Current Status
4949
50 * Have a look in the example/ folder to see some code examples.50 * Have a look in the example/ folder to see some code examples.
51 * Basic language features available such as loops, inline assembly,51 * Most language features are available, but many edge cases and errors are
52 expressions, literals, functions, importing, structs, tagged unions.52 not yet implemented.
53 * Linux x86_64 is supported.53 * Linux x86_64 is supported.
54 * Building for the native target is supported.54 * Building for the native target is supported.
55 * Optimized machine code that Zig produces is indistinguishable from55 * Optimized machine code that Zig produces is indistinguishable from
doc/langref.md+2-2
...@@ -137,7 +137,7 @@ ContainerInitBody : list(StructLiteralField, ",") | list(Expression, ",")...@@ -137,7 +137,7 @@ ContainerInitBody : list(StructLiteralField, ",") | list(Expression, ",")
137137
138StructLiteralField : "." "Symbol" "=" Expression138StructLiteralField : "." "Symbol" "=" Expression
139139
140PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%"140PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
141141
142PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")142PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
143143
...@@ -154,7 +154,7 @@ KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined"...@@ -154,7 +154,7 @@ KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined"
154154
155```155```
156x() x[] x.y156x() x[] x.y
157!x -x ~x *x &x ?x %x157!x -x ~x *x &x ?x %x %%x
158x{}158x{}
159* / %159* / %
160+ -160+ -
example/cat/main.zig+3-4
...@@ -5,7 +5,6 @@ import "std.zig";...@@ -5,7 +5,6 @@ import "std.zig";
5// Things to do to make this work:5// Things to do to make this work:
6// * var args printing6// * var args printing
7// * defer7// * defer
8// * %% binary operator
9// * %% prefix operator8// * %% prefix operator
10// * cast err type to string9// * cast err type to string
11// * string equality10// * string equality
...@@ -21,7 +20,7 @@ pub fn main(args: [][]u8) %void => {...@@ -21,7 +20,7 @@ pub fn main(args: [][]u8) %void => {
21 return usage(exe);20 return usage(exe);
22 } else {21 } else {
23 var is: InputStream;22 var is: InputStream;
24 is.open(arg, OpenReadOnly) %% (err) => {23 is.open(arg, OpenReadOnly) %% |err| {
25 %%stderr.print("Unable to open file: {}", ([]u8])(err));24 %%stderr.print("Unable to open file: {}", ([]u8])(err));
26 return err;25 return err;
27 }26 }
...@@ -45,7 +44,7 @@ fn cat_stream(is: InputStream) %void => {...@@ -45,7 +44,7 @@ fn cat_stream(is: InputStream) %void => {
45 var buf: [1024 * 4]u8;44 var buf: [1024 * 4]u8;
4645
47 while (true) {46 while (true) {
48 const bytes_read = is.read(buf) %% (err) => {47 const bytes_read = is.read(buf) %% |err| {
49 %%stderr.print("Unable to read from stream: {}", ([]u8)(err));48 %%stderr.print("Unable to read from stream: {}", ([]u8)(err));
50 return err;49 return err;
51 }50 }
...@@ -54,7 +53,7 @@ fn cat_stream(is: InputStream) %void => {...@@ -54,7 +53,7 @@ fn cat_stream(is: InputStream) %void => {
54 break;53 break;
55 }54 }
5655
57 stdout.write(buf[0...bytes_read]) %% (err) => {56 stdout.write(buf[0...bytes_read]) %% |err| {
58 %%stderr.print("Unable to write to stdout: {}", ([]u8)(err));57 %%stderr.print("Unable to write to stdout: {}", ([]u8)(err));
59 return err;58 return err;
60 }59 }
example/guess_number/main.zig+8-8
...@@ -4,35 +4,35 @@ import "std.zig";...@@ -4,35 +4,35 @@ import "std.zig";
4import "rand.zig";4import "rand.zig";
55
6pub fn main(args: [][]u8) %void => {6pub fn main(args: [][]u8) %void => {
7 stderr.print_str("Welcome to the Guess Number Game in Zig.\n");7 %%stderr.print_str("Welcome to the Guess Number Game in Zig.\n");
88
9 var seed : u32;9 var seed : u32;
10 const seed_bytes = (&u8)(&seed)[0...4];10 const seed_bytes = (&u8)(&seed)[0...4];
11 os_get_random_bytes(seed_bytes) %% unreachable{};11 %%os_get_random_bytes(seed_bytes);
1212
13 var rand = rand_new(seed);13 var rand = rand_new(seed);
1414
15 const answer = rand.range_u64(0, 100) + 1;15 const answer = rand.range_u64(0, 100) + 1;
1616
17 while (true) {17 while (true) {
18 stderr.print_str("\nGuess a number between 1 and 100: ");18 %%stderr.print_str("\nGuess a number between 1 and 100: ");
19 var line_buf : [20]u8;19 var line_buf : [20]u8;
2020
21 const line_len = stdin.read(line_buf) %% |err| {21 const line_len = stdin.read(line_buf) %% |err| {
22 stderr.print_str("Unable to read from stdin.\n");22 %%stderr.print_str("Unable to read from stdin.\n");
23 return err;23 return err;
24 };24 };
2525
26 const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {26 const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {
27 stderr.print_str("Invalid number.\n");27 %%stderr.print_str("Invalid number.\n");
28 continue;28 continue;
29 };29 };
30 if (guess > answer) {30 if (guess > answer) {
31 stderr.print_str("Guess lower.\n");31 %%stderr.print_str("Guess lower.\n");
32 } else if (guess < answer) {32 } else if (guess < answer) {
33 stderr.print_str("Guess higher.\n");33 %%stderr.print_str("Guess higher.\n");
34 } else {34 } else {
35 stderr.print_str("You win!\n");35 %%stderr.print_str("You win!\n");
36 return;36 return;
37 }37 }
38 }38 }
src/all_types.hpp+1
...@@ -405,6 +405,7 @@ enum PrefixOp {...@@ -405,6 +405,7 @@ enum PrefixOp {
405 PrefixOpDereference,405 PrefixOpDereference,
406 PrefixOpMaybe,406 PrefixOpMaybe,
407 PrefixOpError,407 PrefixOpError,
408 PrefixOpUnwrapError,
408};409};
409410
410struct AstNodePrefixOpExpr {411struct AstNodePrefixOpExpr {
src/analyze.cpp+14
...@@ -3656,6 +3656,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -3656,6 +3656,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
3656 }3656 }
36573657
3658 }3658 }
3659 case PrefixOpUnwrapError:
3660 {
3661 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
3662
3663 if (type_entry->id == TypeTableEntryIdInvalid) {
3664 return type_entry;
3665 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
3666 return type_entry->data.error.child_type;
3667 } else {
3668 add_node_error(g, expr_node,
3669 buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
3670 return g->builtin_types.entry_invalid;
3671 }
3672 }
3659 }3673 }
3660 zig_unreachable();3674 zig_unreachable();
3661}3675}
src/codegen.cpp+19-1
...@@ -833,6 +833,24 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -833,6 +833,24 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
833 {833 {
834 zig_panic("TODO codegen PrefixOpError");834 zig_panic("TODO codegen PrefixOpError");
835 }835 }
836 case PrefixOpUnwrapError:
837 {
838 LLVMValueRef expr_val = gen_expr(g, expr_node);
839 TypeTableEntry *expr_type = get_expr_type(expr_node);
840 assert(expr_type->id == TypeTableEntryIdErrorUnion);
841 TypeTableEntry *child_type = expr_type->data.error.child_type;
842 // TODO in debug mode, put a panic here if the error is not 0
843 if (child_type->size_in_bits > 0) {
844 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
845 if (handle_is_ptr(child_type)) {
846 return child_val_ptr;
847 } else {
848 return expr_val;
849 }
850 } else {
851 return nullptr;
852 }
853 }
836 }854 }
837 zig_unreachable();855 zig_unreachable();
838}856}
...@@ -2219,7 +2237,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2219,7 +2237,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2219 assert(const_val->ok);2237 assert(const_val->ok);
22202238
2221 if (const_val->undef) {2239 if (const_val->undef) {
2222 return LLVMConstNull(type_entry->type_ref);2240 return LLVMGetUndef(type_entry->type_ref);
2223 }2241 }
22242242
2225 if (type_entry->id == TypeTableEntryIdInt) {2243 if (type_entry->id == TypeTableEntryIdInt) {
src/parser.cpp+2
...@@ -64,6 +64,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {...@@ -64,6 +64,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
64 case PrefixOpDereference: return "*";64 case PrefixOpDereference: return "*";
65 case PrefixOpMaybe: return "?";65 case PrefixOpMaybe: return "?";
66 case PrefixOpError: return "%";66 case PrefixOpError: return "%";
67 case PrefixOpUnwrapError: return "%%";
67 }68 }
68 zig_unreachable();69 zig_unreachable();
69}70}
...@@ -1664,6 +1665,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {...@@ -1664,6 +1665,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
1664 case TokenIdStar: return PrefixOpDereference;1665 case TokenIdStar: return PrefixOpDereference;
1665 case TokenIdMaybe: return PrefixOpMaybe;1666 case TokenIdMaybe: return PrefixOpMaybe;
1666 case TokenIdPercent: return PrefixOpError;1667 case TokenIdPercent: return PrefixOpError;
1668 case TokenIdPercentPercent: return PrefixOpUnwrapError;
1667 case TokenIdBoolAnd: return PrefixOpAddressOf;1669 case TokenIdBoolAnd: return PrefixOpAddressOf;
1668 default: return PrefixOpInvalid;1670 default: return PrefixOpInvalid;
1669 }1671 }
std/bootstrap.zig+3-3
...@@ -3,9 +3,9 @@ import "syscall.zig";...@@ -3,9 +3,9 @@ import "syscall.zig";
3// The compiler treats this file special by implicitly importing the function `main`3// The compiler treats this file special by implicitly importing the function `main`
4// from the root source file.4// from the root source file.
55
6var argc: isize;6var argc: isize = undefined;
7var argv: &&u8;7var argv: &&u8 = undefined;
8var env: &&u8;8var env: &&u8 = undefined;
99
10#attribute("naked")10#attribute("naked")
11export fn _start() unreachable => {11export fn _start() unreachable => {