Skip to content

Commit 92fc594

Browse files
committedJan 16, 2018
fix compiler crash related to @Alignof
1 parent 5a49684 commit 92fc594

File tree

5 files changed

+267
-2
lines changed

5 files changed

+267
-2
lines changed
 

‎src/analyze.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2231,6 +2231,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
22312231
// is a pointer to this very struct, or a function pointer with parameters that
22322232
// reference such a type.
22332233
union_type->data.unionation.zero_bits_known = true;
2234+
union_type->data.unionation.zero_bits_loop_flag = false;
22342235
if (union_type->data.unionation.abi_alignment == 0) {
22352236
if (union_type->data.unionation.layout == ContainerLayoutPacked) {
22362237
union_type->data.unionation.abi_alignment = 1;

‎src/ir.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -9858,7 +9858,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
98589858

98599859
if (fn_proto_node->data.fn_proto.is_var_args) {
98609860
ir_add_error(ira, &call_instruction->base,
9861-
buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/andrewrk/zig/issues/313"));
9861+
buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/zig-lang/zig/issues/313"));
98629862
return ira->codegen->builtin_types.entry_invalid;
98639863
}
98649864

@@ -14011,7 +14011,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
1401114011
return ira->codegen->builtin_types.entry_invalid;
1401214012
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
1401314013

14014-
ensure_complete_type(ira->codegen, type_entry);
14014+
type_ensure_zero_bits_known(ira->codegen, type_entry);
1401514015
if (type_is_invalid(type_entry))
1401614016
return ira->codegen->builtin_types.entry_invalid;
1401714017

‎test/build_examples.zig

+1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ pub fn addCases(cases: &tests.BuildExamplesContext) {
1616
cases.addBuildFile("test/standalone/issue_339/build.zig");
1717
cases.addBuildFile("test/standalone/pkg_import/build.zig");
1818
cases.addBuildFile("test/standalone/use_alias/build.zig");
19+
cases.addBuildFile("test/standalone/brace_expansion/build.zig");
1920
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const Builder = @import("std").build.Builder;
2+
3+
pub fn build(b: &Builder) -> %void {
4+
const main = b.addTest("main.zig");
5+
main.setBuildMode(b.standardReleaseOptions());
6+
7+
const test_step = b.step("test", "Test it");
8+
test_step.dependOn(&main.step);
9+
}
+254
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
const std = @import("std");
2+
const io = std.io;
3+
const mem = std.mem;
4+
const debug = std.debug;
5+
const assert = debug.assert;
6+
const Buffer = std.Buffer;
7+
const ArrayList = std.ArrayList;
8+
9+
error InvalidInput;
10+
error OutOfMem;
11+
12+
const Token = union(enum) {
13+
Word: []const u8,
14+
OpenBrace,
15+
CloseBrace,
16+
Comma,
17+
Eof,
18+
};
19+
20+
var global_allocator: &mem.Allocator = undefined;
21+
22+
fn tokenize(input:[] const u8) -> %ArrayList(Token) {
23+
const State = enum {
24+
Start,
25+
Word,
26+
};
27+
28+
var token_list = ArrayList(Token).init(global_allocator);
29+
var tok_begin: usize = undefined;
30+
var state = State.Start;
31+
32+
for (input) |b, i| {
33+
switch (state) {
34+
State.Start => switch (b) {
35+
'a'...'z', 'A'...'Z' => {
36+
state = State.Word;
37+
tok_begin = i;
38+
},
39+
'{' => try token_list.append(Token.OpenBrace),
40+
'}' => try token_list.append(Token.CloseBrace),
41+
',' => try token_list.append(Token.Comma),
42+
else => return error.InvalidInput,
43+
},
44+
State.Word => switch (b) {
45+
'a'...'z', 'A'...'Z' => {},
46+
'{', '}', ',' => {
47+
try token_list.append(Token { .Word = input[tok_begin..i] });
48+
switch (b) {
49+
'{' => try token_list.append(Token.OpenBrace),
50+
'}' => try token_list.append(Token.CloseBrace),
51+
',' => try token_list.append(Token.Comma),
52+
else => unreachable,
53+
}
54+
state = State.Start;
55+
},
56+
else => return error.InvalidInput,
57+
},
58+
}
59+
}
60+
switch (state) {
61+
State.Start => {},
62+
State.Word => try token_list.append(Token {.Word = input[tok_begin..] }),
63+
}
64+
try token_list.append(Token.Eof);
65+
return token_list;
66+
}
67+
68+
const Node = union(enum) {
69+
Scalar: []const u8,
70+
List: ArrayList(Node),
71+
Combine: []Node,
72+
};
73+
74+
fn parse(tokens: &const ArrayList(Token), token_index: &usize) -> %Node {
75+
const first_token = tokens.items[*token_index];
76+
*token_index += 1;
77+
78+
const result_node = switch (first_token) {
79+
Token.Word => |word| Node { .Scalar = word },
80+
Token.OpenBrace => blk: {
81+
var list = ArrayList(Node).init(global_allocator);
82+
while (true) {
83+
try list.append(try parse(tokens, token_index));
84+
85+
const token = tokens.items[*token_index];
86+
*token_index += 1;
87+
88+
switch (token) {
89+
Token.CloseBrace => break,
90+
Token.Comma => continue,
91+
else => return error.InvalidInput,
92+
}
93+
}
94+
break :blk Node { .List = list };
95+
},
96+
else => return error.InvalidInput,
97+
};
98+
99+
switch (tokens.items[*token_index]) {
100+
Token.Word, Token.OpenBrace => {
101+
const pair = try global_allocator.alloc(Node, 2);
102+
pair[0] = result_node;
103+
pair[1] = try parse(tokens, token_index);
104+
return Node { .Combine = pair };
105+
},
106+
else => return result_node,
107+
}
108+
}
109+
110+
fn expandString(input: []const u8, output: &Buffer) -> %void {
111+
const tokens = try tokenize(input);
112+
if (tokens.len == 1) {
113+
return output.resize(0);
114+
}
115+
116+
var token_index: usize = 0;
117+
const root = try parse(tokens, &token_index);
118+
const last_token = tokens.items[token_index];
119+
switch (last_token) {
120+
Token.Eof => {},
121+
else => return error.InvalidInput,
122+
}
123+
124+
var result_list = ArrayList(Buffer).init(global_allocator);
125+
defer result_list.deinit();
126+
127+
try expandNode(root, &result_list);
128+
129+
try output.resize(0);
130+
for (result_list.toSliceConst()) |buf, i| {
131+
if (i != 0) {
132+
try output.appendByte(' ');
133+
}
134+
try output.append(buf.toSliceConst());
135+
}
136+
}
137+
138+
const ListOfBuffer0 = ArrayList(Buffer); // TODO this is working around a compiler bug, fix and delete this
139+
140+
fn expandNode(node: &const Node, output: &ListOfBuffer0) -> %void {
141+
assert(output.len == 0);
142+
switch (*node) {
143+
Node.Scalar => |scalar| {
144+
try output.append(try Buffer.init(global_allocator, scalar));
145+
},
146+
Node.Combine => |pair| {
147+
const a_node = pair[0];
148+
const b_node = pair[1];
149+
150+
var child_list_a = ArrayList(Buffer).init(global_allocator);
151+
try expandNode(a_node, &child_list_a);
152+
153+
var child_list_b = ArrayList(Buffer).init(global_allocator);
154+
try expandNode(b_node, &child_list_b);
155+
156+
for (child_list_a.toSliceConst()) |buf_a| {
157+
for (child_list_b.toSliceConst()) |buf_b| {
158+
var combined_buf = try Buffer.initFromBuffer(buf_a);
159+
try combined_buf.append(buf_b.toSliceConst());
160+
try output.append(combined_buf);
161+
}
162+
}
163+
},
164+
Node.List => |list| {
165+
for (list.toSliceConst()) |child_node| {
166+
var child_list = ArrayList(Buffer).init(global_allocator);
167+
try expandNode(child_node, &child_list);
168+
169+
for (child_list.toSliceConst()) |buf| {
170+
try output.append(buf);
171+
}
172+
}
173+
},
174+
}
175+
}
176+
177+
pub fn main() -> %void {
178+
var stdin_file = try io.getStdIn();
179+
var stdout_file = try io.getStdOut();
180+
181+
var inc_allocator = try std.heap.IncrementingAllocator.init(2 * 1024 * 1024);
182+
defer inc_allocator.deinit();
183+
184+
global_allocator = &inc_allocator.allocator;
185+
186+
var stdin_buf = try Buffer.initSize(global_allocator, 0);
187+
defer stdin_buf.deinit();
188+
189+
var stdin_adapter = io.FileInStream.init(&stdin_file);
190+
try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));
191+
192+
var result_buf = try Buffer.initSize(global_allocator, 0);
193+
defer result_buf.deinit();
194+
195+
try expandString(stdin_buf.toSlice(), &result_buf);
196+
try stdout_file.write(result_buf.toSliceConst());
197+
}
198+
199+
test "invalid inputs" {
200+
global_allocator = std.debug.global_allocator;
201+
202+
expectError("}ABC", error.InvalidInput);
203+
expectError("{ABC", error.InvalidInput);
204+
expectError("}{", error.InvalidInput);
205+
expectError("{}", error.InvalidInput);
206+
expectError("A,B,C", error.InvalidInput);
207+
expectError("{A{B,C}", error.InvalidInput);
208+
expectError("{A,}", error.InvalidInput);
209+
210+
expectError("\n", error.InvalidInput);
211+
}
212+
213+
fn expectError(test_input: []const u8, expected_err: error) {
214+
var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;
215+
defer output_buf.deinit();
216+
217+
if (expandString("}ABC", &output_buf)) {
218+
unreachable;
219+
} else |err| {
220+
assert(expected_err == err);
221+
}
222+
}
223+
224+
test "valid inputs" {
225+
global_allocator = std.debug.global_allocator;
226+
227+
expectExpansion("{x,y,z}", "x y z");
228+
expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
229+
expectExpansion("{A,B{x,y}}", "A Bx By");
230+
231+
expectExpansion("{ABC}", "ABC");
232+
expectExpansion("{A,B,C}", "A B C");
233+
expectExpansion("ABC", "ABC");
234+
235+
expectExpansion("", "");
236+
expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
237+
expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
238+
expectExpansion("{A,B}a", "Aa Ba");
239+
expectExpansion("{C,{x,y}}", "C x y");
240+
expectExpansion("z{C,{x,y}}", "zC zx zy");
241+
expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
242+
expectExpansion("a{x,y}b", "axb ayb");
243+
expectExpansion("z{{a,b}}", "za zb");
244+
expectExpansion("a{b}", "ab");
245+
}
246+
247+
fn expectExpansion(test_input: []const u8, expected_result: []const u8) {
248+
var result = Buffer.initSize(global_allocator, 0) catch unreachable;
249+
defer result.deinit();
250+
251+
expandString(test_input, &result) catch unreachable;
252+
253+
assert(mem.eql(u8, result.toSlice(), expected_result));
254+
}

0 commit comments

Comments
 (0)
Please sign in to comment.