Skip to content

Commit 698829b

Browse files
committed
change while syntax
Old: ``` while (condition; expression) {} ``` New: ``` while (condition) : (expression) {} ``` This is in preparation to allow nullable and error union types as the condition. See #357
1 parent 644ea2d commit 698829b

25 files changed

+97
-65
lines changed

doc/langref.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbo
7979
8080
SwitchItem = Expression | (Expression "..." Expression)
8181
82-
WhileExpression(body) = "while" "(" Expression option(";" Expression) ")" body
83-
8482
ForExpression(body) = "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") body
8583
8684
BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
@@ -95,6 +93,8 @@ TryExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|")
9593
9694
TestExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
9795
96+
WhileExpression(body) = "while" "(" Expression ")" option("|" option("*") Symbol "|") option(":" "(" Expression ")") body option("else" option("|" Symbol "|") BlockExpression(body))
97+
9898
BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
9999
100100
ComparisonExpression = BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression

example/cat/main.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub fn main() -> %void {
77
const exe = os.args.at(0);
88
var catted_anything = false;
99
var arg_i: usize = 1;
10-
while (arg_i < os.args.count(); arg_i += 1) {
10+
while (arg_i < os.args.count()) : (arg_i += 1) {
1111
const arg = os.args.at(arg_i);
1212
if (mem.eql(u8, arg, "-")) {
1313
catted_anything = true;

src/all_types.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,12 @@ struct AstNodeTestExpr {
609609

610610
struct AstNodeWhileExpr {
611611
AstNode *condition;
612+
Buf *var_symbol;
613+
bool var_is_ptr;
612614
AstNode *continue_expr;
613615
AstNode *body;
616+
AstNode *else_node;
617+
Buf *err_symbol;
614618
bool is_inline;
615619
};
616620

src/parser.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo
15801580
}
15811581

15821582
/*
1583-
WhileExpression(body) = option("inline") "while" "(" Expression option(";" Expression) ")" body
1583+
WhileExpression(body) = option("inline") "while" "(" Expression ")" option("|" option("*") Symbol "|") option(":" "(" Expression ")") body option("else" option("|" Symbol "|") BlockExpression(body))
15841584
*/
15851585
static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
15861586
Token *first_token = &pc->tokens->at(*token_index);
@@ -1613,21 +1613,49 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool
16131613

16141614
ast_eat_token(pc, token_index, TokenIdLParen);
16151615
node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);
1616+
ast_eat_token(pc, token_index, TokenIdRParen);
16161617

1617-
Token *semi_or_rparen = &pc->tokens->at(*token_index);
1618-
1619-
if (semi_or_rparen->id == TokenIdRParen) {
1618+
Token *open_bar_tok = &pc->tokens->at(*token_index);
1619+
if (open_bar_tok->id == TokenIdBinOr) {
16201620
*token_index += 1;
1621-
node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true);
1622-
} else if (semi_or_rparen->id == TokenIdSemicolon) {
1621+
1622+
Token *star_tok = &pc->tokens->at(*token_index);
1623+
if (star_tok->id == TokenIdStar) {
1624+
*token_index += 1;
1625+
node->data.while_expr.var_is_ptr = true;
1626+
}
1627+
1628+
Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
1629+
node->data.while_expr.var_symbol = token_buf(var_name_tok);
1630+
ast_eat_token(pc, token_index, TokenIdBinOr);
1631+
}
1632+
1633+
Token *colon_tok = &pc->tokens->at(*token_index);
1634+
if (colon_tok->id == TokenIdColon) {
16231635
*token_index += 1;
1636+
ast_eat_token(pc, token_index, TokenIdLParen);
16241637
node->data.while_expr.continue_expr = ast_parse_expression(pc, token_index, true);
16251638
ast_eat_token(pc, token_index, TokenIdRParen);
1626-
node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true);
1627-
} else {
1628-
ast_invalid_token_error(pc, semi_or_rparen);
16291639
}
16301640

1641+
node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true);
1642+
1643+
Token *else_tok = &pc->tokens->at(*token_index);
1644+
if (else_tok->id == TokenIdKeywordElse) {
1645+
*token_index += 1;
1646+
1647+
Token *else_bar_tok = &pc->tokens->at(*token_index);
1648+
if (else_bar_tok->id == TokenIdBinOr) {
1649+
*token_index += 1;
1650+
1651+
Token *err_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
1652+
node->data.while_expr.err_symbol = token_buf(err_name_tok);
1653+
1654+
ast_eat_token(pc, token_index, TokenIdBinOr);
1655+
}
1656+
1657+
node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true);
1658+
}
16311659

16321660
return node;
16331661
}

std/base64.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn encodeWithAlphabet(dest: []u8, source: []const u8, alphabet: []const u8)
1717

1818
var i: usize = 0;
1919
var out_index: usize = 0;
20-
while (i + 2 < source.len; i += 3) {
20+
while (i + 2 < source.len) : (i += 3) {
2121
dest[out_index] = alphabet[(source[i] >> 2) & 0x3f];
2222
out_index += 1;
2323

std/cstr.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ const assert = debug.assert;
33

44
pub fn len(ptr: &const u8) -> usize {
55
var count: usize = 0;
6-
while (ptr[count] != 0; count += 1) {}
6+
while (ptr[count] != 0) : (count += 1) {}
77
return count;
88
}
99

1010
pub fn cmp(a: &const u8, b: &const u8) -> i8 {
1111
var index: usize = 0;
12-
while (a[index] == b[index] and a[index] != 0; index += 1) {}
12+
while (a[index] == b[index] and a[index] != 0) : (index += 1) {}
1313
if (a[index] > b[index]) {
1414
return 1;
1515
} else if (a[index] < b[index]) {

std/debug.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
7979
var ignored_count: usize = 0;
8080

8181
var fp = usize(@frameAddress());
82-
while (fp != 0; fp = *@intToPtr(&const usize, fp)) {
82+
while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) {
8383
if (ignored_count < ignore_frame_count) {
8484
ignored_count += 1;
8585
continue;
@@ -108,7 +108,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
108108
if (line_info.column == 0) {
109109
%return out_stream.write("\n");
110110
} else {
111-
{var col_i: usize = 1; while (col_i < line_info.column; col_i += 1) {
111+
{var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) {
112112
%return out_stream.writeByte(' ');
113113
}}
114114
%return out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
@@ -594,7 +594,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
594594
var this_offset = st.debug_line.offset;
595595
var this_index: usize = 0;
596596

597-
while (this_offset < debug_line_end; this_index += 1) {
597+
while (this_offset < debug_line_end) : (this_index += 1) {
598598
%return in_stream.seekTo(this_offset);
599599

600600
var is_64: bool = undefined;
@@ -628,7 +628,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
628628

629629
const standard_opcode_lengths = %return st.allocator().alloc(u8, opcode_base - 1);
630630

631-
{var i: usize = 0; while (i < opcode_base - 1; i += 1) {
631+
{var i: usize = 0; while (i < opcode_base - 1) : (i += 1) {
632632
standard_opcode_lengths[i] = %return in_stream.readByte();
633633
}}
634634

std/fmt.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ pub fn formatBuf(buf: []const u8, width: usize,
200200

201201
var leftover_padding = if (width > buf.len) (width - buf.len) else return true;
202202
const pad_byte: u8 = ' ';
203-
while (leftover_padding > 0; leftover_padding -= 1) {
203+
while (leftover_padding > 0) : (leftover_padding -= 1) {
204204
if (!output(context, (&pad_byte)[0...1]))
205205
return false;
206206
}

std/hash_map.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
4343
assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
4444
}
4545
if (it.count >= it.hm.size) return null;
46-
while (it.index < it.hm.entries.len; it.index += 1) {
46+
while (it.index < it.hm.entries.len) : (it.index += 1) {
4747
const entry = &it.hm.entries[it.index];
4848
if (entry.used) {
4949
it.index += 1;
@@ -112,7 +112,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
112112
pub fn remove(hm: &Self, key: K) -> ?&Entry {
113113
hm.incrementModificationCount();
114114
const start_index = hm.keyToIndex(key);
115-
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) {
115+
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
116116
const index = (start_index + roll_over) % hm.entries.len;
117117
var entry = &hm.entries[index];
118118

@@ -121,7 +121,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
121121

122122
if (!eql(entry.key, key)) continue;
123123

124-
while (roll_over < hm.entries.len; roll_over += 1) {
124+
while (roll_over < hm.entries.len) : (roll_over += 1) {
125125
const next_index = (start_index + roll_over + 1) % hm.entries.len;
126126
const next_entry = &hm.entries[next_index];
127127
if (!next_entry.used or next_entry.distance_from_start_index == 0) {
@@ -169,7 +169,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
169169
const start_index = hm.keyToIndex(key);
170170
var roll_over: usize = 0;
171171
var distance_from_start_index: usize = 0;
172-
while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) {
172+
while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1}) {
173173
const index = (start_index + roll_over) % hm.entries.len;
174174
const entry = &hm.entries[index];
175175

@@ -215,7 +215,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
215215

216216
fn internalGet(hm: &Self, key: K) -> ?&Entry {
217217
const start_index = hm.keyToIndex(key);
218-
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) {
218+
{var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
219219
const index = (start_index + roll_over) % hm.entries.len;
220220
const entry = &hm.entries[index];
221221

std/list.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ test "basic list test" {
7878
var list = List(i32).init(&debug.global_allocator);
7979
defer list.deinit();
8080

81-
{var i: usize = 0; while (i < 10; i += 1) {
81+
{var i: usize = 0; while (i < 10) : (i += 1) {
8282
%%list.append(i32(i + 1));
8383
}}
8484

85-
{var i: usize = 0; while (i < 10; i += 1) {
85+
{var i: usize = 0; while (i < 10) : (i += 1) {
8686
assert(list.items[i] == i32(i + 1));
8787
}}
8888

std/mem.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub fn set(comptime T: type, dest: []T, value: T) {
123123
pub fn cmp(comptime T: type, a: []const T, b: []const T) -> Cmp {
124124
const n = math.min(a.len, b.len);
125125
var i: usize = 0;
126-
while (i < n; i += 1) {
126+
while (i < n) : (i += 1) {
127127
if (a[i] == b[i]) continue;
128128
return if (a[i] > b[i]) Cmp.Greater else if (a[i] < b[i]) Cmp.Less else Cmp.Equal;
129129
}
@@ -164,7 +164,7 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) -> ?usi
164164

165165
var i: usize = 0;
166166
const end = haystack.len - needle.len;
167-
while (i <= end; i += 1) {
167+
while (i <= end) : (i += 1) {
168168
if (eql(T, haystack[i...i + needle.len], needle))
169169
return i;
170170
}
@@ -263,14 +263,14 @@ const SplitIterator = struct {
263263

264264
pub fn next(self: &SplitIterator) -> ?[]const u8 {
265265
// move to beginning of token
266-
while (self.index < self.s.len and self.s[self.index] == self.c; self.index += 1) {}
266+
while (self.index < self.s.len and self.s[self.index] == self.c) : (self.index += 1) {}
267267
const start = self.index;
268268
if (start == self.s.len) {
269269
return null;
270270
}
271271

272272
// move to end of token
273-
while (self.index < self.s.len and self.s[self.index] != self.c; self.index += 1) {}
273+
while (self.index < self.s.len and self.s[self.index] != self.c) : (self.index += 1) {}
274274
const end = self.index;
275275

276276
return self.s[start...end];
@@ -280,7 +280,7 @@ const SplitIterator = struct {
280280
pub fn rest(self: &const SplitIterator) -> []const u8 {
281281
// move to beginning of token
282282
var index: usize = self.index;
283-
while (index < self.s.len and self.s[index] == self.c; index += 1) {}
283+
while (index < self.s.len and self.s[index] == self.c) : (index += 1) {}
284284
return self.s[index...];
285285
}
286286
};

std/os/index.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
276276
{
277277
var it = env_map.iterator();
278278
var i: usize = 0;
279-
while (true; i += 1) {
279+
while (true) : (i += 1) {
280280
const pair = it.next() ?? break;
281281

282282
const env_buf = %return allocator.alloc(u8, pair.key.len + pair.value.len + 2);
@@ -354,11 +354,11 @@ pub fn getEnvMap(allocator: &Allocator) -> %BufMap {
354354

355355
for (environ_raw) |ptr| {
356356
var line_i: usize = 0;
357-
while (ptr[line_i] != 0 and ptr[line_i] != '='; line_i += 1) {}
357+
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
358358
const key = ptr[0...line_i];
359359

360360
var end_i: usize = line_i;
361-
while (ptr[end_i] != 0; end_i += 1) {}
361+
while (ptr[end_i] != 0) : (end_i += 1) {}
362362
const value = ptr[line_i + 1...end_i];
363363

364364
%return result.set(key, value);
@@ -369,13 +369,13 @@ pub fn getEnvMap(allocator: &Allocator) -> %BufMap {
369369
pub fn getEnv(key: []const u8) -> ?[]const u8 {
370370
for (environ_raw) |ptr| {
371371
var line_i: usize = 0;
372-
while (ptr[line_i] != 0 and ptr[line_i] != '='; line_i += 1) {}
372+
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
373373
const this_key = ptr[0...line_i];
374374
if (!mem.eql(u8, key, this_key))
375375
continue;
376376

377377
var end_i: usize = line_i;
378-
while (ptr[end_i] != 0; end_i += 1) {}
378+
while (ptr[end_i] != 0) : (end_i += 1) {}
379379
const this_value = ptr[line_i + 1...end_i];
380380

381381
return this_value;

std/os/path.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn join(allocator: &Allocator, paths: ...) -> %[]u8 {
2525
var total_paths_len: usize = paths.len; // 1 slash per path
2626
{
2727
comptime var path_i = 0;
28-
inline while (path_i < paths.len; path_i += 1) {
28+
inline while (path_i < paths.len) : (path_i += 1) {
2929
const arg = ([]const u8)(paths[path_i]);
3030
total_paths_len += arg.len;
3131
}
@@ -74,7 +74,7 @@ pub fn isAbsolute(path: []const u8) -> bool {
7474
pub fn resolve(allocator: &Allocator, args: ...) -> %[]u8 {
7575
var paths: [args.len][]const u8 = undefined;
7676
comptime var arg_i = 0;
77-
inline while (arg_i < args.len; arg_i += 1) {
77+
inline while (arg_i < args.len) : (arg_i += 1) {
7878
paths[arg_i] = args[arg_i];
7979
}
8080
return resolveSlice(allocator, paths);

std/rand.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn MersenneTwister(
121121
var prev_value = seed;
122122
mt.array[0] = prev_value;
123123
var i: usize = 1;
124-
while (i < n; i += 1) {
124+
while (i < n) : (i += 1) {
125125
prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2)));
126126
mt.array[i] = prev_value;
127127
}
@@ -136,12 +136,12 @@ fn MersenneTwister(
136136
if (mt.index >= n) {
137137
var i: usize = 0;
138138

139-
while (i < n - m; i += 1) {
139+
while (i < n - m) : (i += 1) {
140140
const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
141141
mt.array[i] = mt.array[i + m] ^ (x >> 1) ^ mag01[x & 0x1];
142142
}
143143

144-
while (i < n - 1; i += 1) {
144+
while (i < n - 1) : (i += 1) {
145145
const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
146146
mt.array[i] = mt.array[i + m - n] ^ (x >> 1) ^ mag01[x & 0x1];
147147

@@ -168,7 +168,7 @@ fn MersenneTwister(
168168
test "rand float 32" {
169169
var r = Rand.init(42);
170170
var i: usize = 0;
171-
while (i < 1000; i += 1) {
171+
while (i < 1000) : (i += 1) {
172172
const val = r.float(f32);
173173
assert(val >= 0.0);
174174
assert(val < 1.0);

std/special/bootstrap.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void {
4242
std.os.args.raw = argv[0...argc];
4343

4444
var env_count: usize = 0;
45-
while (envp[env_count] != null; env_count += 1) {}
45+
while (envp[env_count] != null) : (env_count += 1) {}
4646
std.os.environ_raw = @ptrCast(&&u8, envp)[0...env_count];
4747

4848
std.debug.user_main_fn = root.main;

std/special/build_runner.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub fn main() -> %void {
5555

5656
var prefix: ?[]const u8 = null;
5757

58-
while (arg_i < os.args.count(); arg_i += 1) {
58+
while (arg_i < os.args.count()) : (arg_i += 1) {
5959
const arg = os.args.at(arg_i);
6060
if (mem.startsWith(u8, arg, "-D")) {
6161
const option_contents = arg[2...];

0 commit comments

Comments
 (0)