authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-06 01:28:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-06 01:28:58-07:00
log3c43bc9208701af151a0346744e3bfc7eae43042
treeb3732004becc9b759ddad1a86813668059cfc8d9
parent4ef062b9c819a2d7bfa9dd3394713ac9e8051660

support unknown size arrays


8 files changed, 136 insertions(+), 82 deletions(-)

doc/langref.md+1-1
...@@ -72,7 +72,7 @@ PointerType : token(Ampersand) option(token(Const)) Type...@@ -72,7 +72,7 @@ PointerType : token(Ampersand) option(token(Const)) Type
7272
73MaybeType : token(Question) Type73MaybeType : token(Question) Type
7474
75ArrayType : token(LBracket) option(Expression) token(RBracket) Type75ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Type
7676
77Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)77Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
7878
example/arrays/arrays.zig+11-2
...@@ -19,9 +19,18 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -19,9 +19,18 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
19 i += 1;19 i += 1;
20 }20 }
2121
22 if (accumulator == 15) {22 if (accumulator != 15) {
23 print_str("OK\n");23 print_str("BAD\n");
24 }24 }
2525
26 if (get_array_len(array) != 5) {
27 print_str("BAD\n");
28 }
29
30 print_str("OK\n");
26 return 0;31 return 0;
27}32}
33
34fn get_array_len(a: []u32) -> usize {
35 a.len
36}
example/rand/main.zig+10-6
...@@ -7,8 +7,10 @@ const ARRAY_SIZE : u16 = 624;...@@ -7,8 +7,10 @@ const ARRAY_SIZE : u16 = 624;
77
8/// Use `rand_init` to initialize this state.8/// Use `rand_init` to initialize this state.
9struct Rand {9struct Rand {
10 array: [u32; ARRAY_SIZE],10 // TODO use ARRAY_SIZE here
11 index: #typeof(ARRAY_SIZE),11 array: [624]u32,
12 // TODO use ARRAY_SIZE here
13 index: #typeof(624),
1214
13 /// Get 32 bits of randomness.15 /// Get 32 bits of randomness.
14 pub fn get_u32(r: &Rand) -> u32 {16 pub fn get_u32(r: &Rand) -> u32 {
...@@ -31,10 +33,11 @@ struct Rand {...@@ -31,10 +33,11 @@ struct Rand {
31 pub fn get_bytes(r: &Rand, buf: []u8) {33 pub fn get_bytes(r: &Rand, buf: []u8) {
32 var bytes_left = r.get_bytes_aligned(buf);34 var bytes_left = r.get_bytes_aligned(buf);
33 if (bytes_left > 0) {35 if (bytes_left > 0) {
34 var rand_val_array : [u8; #sizeof(u32)];36 var rand_val_array : [#sizeof(u32)]u8;
35 *(rand_val_array.ptr as &u32) = r.get_u32();37 *(rand_val_array.ptr as &u32) = r.get_u32();
36 while (bytes_left > 0) {38 while (bytes_left > 0) {
37 buf[buf.len - bytes_left] = rand_val_array[#sizeof(u32) - bytes_left];39 // TODO array index operator so we can remove the .ptr
40 buf.ptr[buf.len - bytes_left] = rand_val_array[#sizeof(u32) - bytes_left];
38 bytes_left -= 1;41 bytes_left -= 1;
39 }42 }
40 }43 }
...@@ -46,7 +49,7 @@ struct Rand {...@@ -46,7 +49,7 @@ struct Rand {
46 const range = end - start;49 const range = end - start;
47 const leftover = #max_value(u64) % range;50 const leftover = #max_value(u64) % range;
48 const upper_bound = #max_value(u64) - leftover;51 const upper_bound = #max_value(u64) - leftover;
49 var rand_val_array : [u8; #sizeof(u64)];52 var rand_val_array : [#sizeof(u64)]u8;
5053
51 while (true) {54 while (true) {
52 r.get_bytes_aligned(rand_val_array);55 r.get_bytes_aligned(rand_val_array);
...@@ -79,7 +82,8 @@ struct Rand {...@@ -79,7 +82,8 @@ struct Rand {
79 fn get_bytes_aligned(r: &Rand, buf: []u8) -> usize {82 fn get_bytes_aligned(r: &Rand, buf: []u8) -> usize {
80 var bytes_left = buf.len;83 var bytes_left = buf.len;
81 while (bytes_left > 4) {84 while (bytes_left > 4) {
82 *(&buf[buf.len - bytes_left] as &u32) = r.get_u32();85 // TODO: array access so we can remove .ptr
86 *(&buf.ptr[buf.len - bytes_left] as &u32) = r.get_u32();
83 bytes_left -= #sizeof(u32);87 bytes_left -= #sizeof(u32);
84 }88 }
85 return bytes_left;89 return bytes_left;
src/analyze.cpp+88-28
...@@ -219,7 +219,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,...@@ -219,7 +219,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
219 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);219 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
220 entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);220 entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);
221 buf_resize(&entry->name, 0);221 buf_resize(&entry->name, 0);
222 buf_appendf(&entry->name, "[%s; %" PRIu64 "]", buf_ptr(&child_type->name), array_size);222 buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
223223
224 entry->size_in_bits = child_type->size_in_bits * array_size;224 entry->size_in_bits = child_type->size_in_bits * array_size;
225 entry->align_in_bits = child_type->align_in_bits;225 entry->align_in_bits = child_type->align_in_bits;
...@@ -235,6 +235,55 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,...@@ -235,6 +235,55 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
235 }235 }
236}236}
237237
238static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import,
239 TypeTableEntry *child_type, bool is_const)
240{
241 TypeTableEntry **parent_pointer = is_const ?
242 &child_type->unknown_size_array_const_parent :
243 &child_type->unknown_size_array_mut_parent;
244 if (*parent_pointer) {
245 return *parent_pointer;
246 } else {
247 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
248
249 buf_resize(&entry->name, 0);
250 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
251 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
252
253 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
254
255 unsigned element_count = 2;
256 LLVMTypeRef element_types[] = {
257 pointer_type->type_ref,
258 g->builtin_types.entry_usize->type_ref,
259 };
260 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
261
262 entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
263 entry->align_in_bits = g->pointer_size_bytes * 8;
264 entry->data.structure.is_packed = false;
265 entry->data.structure.is_unknown_size_array = true;
266 entry->data.structure.field_count = element_count;
267 entry->data.structure.fields = allocate<TypeStructField>(element_count);
268 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
269 entry->data.structure.fields[0].type_entry = pointer_type;
270 entry->data.structure.fields[1].name = buf_create_from_str("len");
271 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
272
273 LLVMZigDIType *di_element_types[] = {
274 pointer_type->di_type,
275 g->builtin_types.entry_usize->di_type,
276 };
277 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
278 entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, compile_unit_scope,
279 buf_ptr(&entry->name), g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
280 nullptr, di_element_types, element_count, 0, nullptr, "");
281
282 *parent_pointer = entry;
283 return entry;
284 }
285}
286
238static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,287static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
239 AstNode *node, AstNodeNumberLiteral *out_number_literal)288 AstNode *node, AstNodeNumberLiteral *out_number_literal)
240{289{
...@@ -313,38 +362,47 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry...@@ -313,38 +362,47 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
313 }362 }
314 case AstNodeTypeTypeArray:363 case AstNodeTypeTypeArray:
315 {364 {
316 resolve_type(g, node->data.type.child_type, import, context);365 TypeTableEntry *child_type = resolve_type(g, node->data.type.child_type, import, context);
317 TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
318 if (child_type->id == TypeTableEntryIdUnreachable) {366 if (child_type->id == TypeTableEntryIdUnreachable) {
319 add_node_error(g, node,367 add_node_error(g, node,
320 buf_create_from_str("array of unreachable not allowed"));368 buf_create_from_str("array of unreachable not allowed"));
321 }
322
323 AstNode *size_node = node->data.type.array_size;
324 TypeTableEntry *size_type = analyze_expression(g, import, context,
325 g->builtin_types.entry_usize, size_node);
326 if (size_type->id == TypeTableEntryIdInvalid) {
327 type_node->entry = g->builtin_types.entry_invalid;369 type_node->entry = g->builtin_types.entry_invalid;
328 return type_node->entry;370 return type_node->entry;
329 }371 }
330372
331 AstNodeNumberLiteral number_literal;373 AstNode *size_node = node->data.type.array_size;
332 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
333374
334 if (resolved_type->id == TypeTableEntryIdInt) {375 if (size_node) {
335 if (resolved_type->data.integral.is_signed) {376 TypeTableEntry *size_type = analyze_expression(g, import, context,
336 add_node_error(g, size_node,377 g->builtin_types.entry_usize, size_node);
337 buf_create_from_str("array size must be unsigned integer"));378 if (size_type->id == TypeTableEntryIdInvalid) {
338 type_node->entry = g->builtin_types.entry_invalid;379 type_node->entry = g->builtin_types.entry_invalid;
380 return type_node->entry;
381 }
382
383 AstNodeNumberLiteral number_literal;
384 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
385
386 if (resolved_type->id == TypeTableEntryIdInt) {
387 if (resolved_type->data.integral.is_signed) {
388 add_node_error(g, size_node,
389 buf_create_from_str("array size must be unsigned integer"));
390 type_node->entry = g->builtin_types.entry_invalid;
391 } else {
392 type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
393 }
339 } else {394 } else {
340 type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);395 add_node_error(g, size_node,
396 buf_create_from_str("unable to resolve constant expression"));
397 type_node->entry = g->builtin_types.entry_invalid;
341 }398 }
399 return type_node->entry;
342 } else {400 } else {
343 add_node_error(g, size_node,401 type_node->entry = get_unknown_size_array_type(g, import, child_type,
344 buf_create_from_str("unable to resolve constant expression"));402 node->data.type.is_const);
345 type_node->entry = g->builtin_types.entry_invalid;403 return type_node->entry;
346 }404 }
347 return type_node->entry;405
348 }406 }
349 case AstNodeTypeTypeMaybe:407 case AstNodeTypeTypeMaybe:
350 {408 {
...@@ -1016,13 +1074,14 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1016,13 +1074,14 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1016 return expected_type;1074 return expected_type;
1017 }1075 }
10181076
1019 // implicit constant sized array to string conversion1077 // implicit constant sized array to unknown size array conversion
1020 if (expected_type == g->builtin_types.entry_string &&1078 if (expected_type->id == TypeTableEntryIdStruct &&
1079 expected_type->data.structure.is_unknown_size_array &&
1021 actual_type->id == TypeTableEntryIdArray &&1080 actual_type->id == TypeTableEntryIdArray &&
1022 actual_type->data.array.child_type == g->builtin_types.entry_u8)1081 actual_type->data.array.child_type == expected_type->data.structure.fields[0].type_entry->data.pointer.child_type)
1023 {1082 {
1024 node->codegen_node->expr_node.implicit_cast.after_type = expected_type;1083 node->codegen_node->expr_node.implicit_cast.after_type = expected_type;
1025 node->codegen_node->expr_node.implicit_cast.op = CastOpArrayToString;1084 node->codegen_node->expr_node.implicit_cast.op = CastOpToUnknownSizeArray;
1026 node->codegen_node->expr_node.implicit_cast.source_node = node;1085 node->codegen_node->expr_node.implicit_cast.source_node = node;
1027 context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_cast);1086 context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_cast);
1028 return expected_type;1087 return expected_type;
...@@ -1292,11 +1351,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -1292,11 +1351,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
1292 {1351 {
1293 cast_node->op = CastOpIntWidenOrShorten;1352 cast_node->op = CastOpIntWidenOrShorten;
1294 return wanted_type;1353 return wanted_type;
1295 } else if (wanted_type == g->builtin_types.entry_string &&1354 } else if (wanted_type->id == TypeTableEntryIdStruct &&
1296 actual_type->id == TypeTableEntryIdArray &&1355 wanted_type->data.structure.is_unknown_size_array &&
1297 actual_type->data.array.child_type == g->builtin_types.entry_u8)1356 actual_type->id == TypeTableEntryIdArray &&
1357 actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry)
1298 {1358 {
1299 cast_node->op = CastOpArrayToString;1359 cast_node->op = CastOpToUnknownSizeArray;
1300 context->cast_expr_alloca_list.append(cast_node);1360 context->cast_expr_alloca_list.append(cast_node);
1301 return wanted_type;1361 return wanted_type;
1302 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&1362 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
src/analyze.hpp+4-2
...@@ -46,6 +46,7 @@ struct TypeTableEntryStruct {...@@ -46,6 +46,7 @@ struct TypeTableEntryStruct {
46 TypeStructField *fields;46 TypeStructField *fields;
47 uint64_t size_bytes;47 uint64_t size_bytes;
48 bool is_invalid; // true if any fields are invalid48 bool is_invalid; // true if any fields are invalid
49 bool is_unknown_size_array;
49 // reminder: hash tables must be initialized before use50 // reminder: hash tables must be initialized before use
50 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;51 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
5152
...@@ -100,6 +101,8 @@ struct TypeTableEntry {...@@ -100,6 +101,8 @@ struct TypeTableEntry {
100 TypeTableEntry *pointer_mut_parent;101 TypeTableEntry *pointer_mut_parent;
101 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;102 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
102 TypeTableEntry *maybe_parent;103 TypeTableEntry *maybe_parent;
104 TypeTableEntry *unknown_size_array_const_parent;
105 TypeTableEntry *unknown_size_array_mut_parent;
103106
104};107};
105108
...@@ -175,7 +178,6 @@ struct CodeGen {...@@ -175,7 +178,6 @@ struct CodeGen {
175 TypeTableEntry *entry_f32;178 TypeTableEntry *entry_f32;
176 TypeTableEntry *entry_f64;179 TypeTableEntry *entry_f64;
177 TypeTableEntry *entry_c_string_literal;180 TypeTableEntry *entry_c_string_literal;
178 TypeTableEntry *entry_string;
179 TypeTableEntry *entry_void;181 TypeTableEntry *entry_void;
180 TypeTableEntry *entry_unreachable;182 TypeTableEntry *entry_unreachable;
181 TypeTableEntry *entry_invalid;183 TypeTableEntry *entry_invalid;
...@@ -283,7 +285,7 @@ enum CastOp {...@@ -283,7 +285,7 @@ enum CastOp {
283 CastOpNothing,285 CastOpNothing,
284 CastOpPtrToInt,286 CastOpPtrToInt,
285 CastOpIntWidenOrShorten,287 CastOpIntWidenOrShorten,
286 CastOpArrayToString,288 CastOpToUnknownSizeArray,
287 CastOpMaybeWrap,289 CastOpMaybeWrap,
288 CastOpPointerReinterpret,290 CastOpPointerReinterpret,
289};291};
src/codegen.cpp+5-38
...@@ -462,14 +462,17 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v...@@ -462,14 +462,17 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v
462 add_debug_source_node(g, node);462 add_debug_source_node(g, node);
463 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");463 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
464 }464 }
465 case CastOpArrayToString:465 case CastOpToUnknownSizeArray:
466 {466 {
467 assert(cast_node->ptr);467 assert(cast_node->ptr);
468468
469 TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
470
469 add_debug_source_node(g, node);471 add_debug_source_node(g, node);
470472
471 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 0, "");473 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 0, "");
472 LLVMBuildStore(g->builder, expr_val, ptr_ptr);474 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
475 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
473476
474 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 1, "");477 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 1, "");
475 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,478 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
...@@ -1925,41 +1928,6 @@ static void define_builtin_types(CodeGen *g) {...@@ -1925,41 +1928,6 @@ static void define_builtin_types(CodeGen *g) {
1925 entry->di_type = g->builtin_types.entry_void->di_type;1928 entry->di_type = g->builtin_types.entry_void->di_type;
1926 g->builtin_types.entry_unreachable = entry;1929 g->builtin_types.entry_unreachable = entry;
1927 }1930 }
1928 {
1929 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
1930
1931 TypeTableEntry *const_pointer_to_u8 = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
1932
1933 unsigned element_count = 2;
1934 LLVMTypeRef element_types[] = {
1935 const_pointer_to_u8->type_ref,
1936 g->builtin_types.entry_usize->type_ref
1937 };
1938 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), "string");
1939 LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
1940
1941 buf_init_from_str(&entry->name, "string");
1942 entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
1943 entry->align_in_bits = g->pointer_size_bytes;
1944 entry->data.structure.is_packed = false;
1945 entry->data.structure.field_count = element_count;
1946 entry->data.structure.fields = allocate<TypeStructField>(element_count);
1947 entry->data.structure.fields[0].name = buf_create_from_str("ptr");
1948 entry->data.structure.fields[0].type_entry = const_pointer_to_u8;
1949 entry->data.structure.fields[1].name = buf_create_from_str("len");
1950 entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
1951
1952 LLVMZigDIType *di_element_types[] = {
1953 const_pointer_to_u8->di_type,
1954 g->builtin_types.entry_usize->di_type
1955 };
1956 LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
1957 entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, compile_unit_scope,
1958 "string", g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
1959 nullptr, di_element_types, element_count, 0, nullptr, "");
1960
1961 g->builtin_types.entry_string = entry;
1962 }
1963}1931}
19641932
19651933
...@@ -2103,7 +2071,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -2103,7 +2071,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2103 import_entry->type_table.put(&g->builtin_types.entry_f64->name, g->builtin_types.entry_f64);2071 import_entry->type_table.put(&g->builtin_types.entry_f64->name, g->builtin_types.entry_f64);
2104 import_entry->type_table.put(&g->builtin_types.entry_void->name, g->builtin_types.entry_void);2072 import_entry->type_table.put(&g->builtin_types.entry_void->name, g->builtin_types.entry_void);
2105 import_entry->type_table.put(&g->builtin_types.entry_unreachable->name, g->builtin_types.entry_unreachable);2073 import_entry->type_table.put(&g->builtin_types.entry_unreachable->name, g->builtin_types.entry_unreachable);
2106 import_entry->type_table.put(&g->builtin_types.entry_string->name, g->builtin_types.entry_string);
21072074
2108 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color);2075 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color);
2109 assert(import_entry->root);2076 assert(import_entry->root);
src/parser.cpp+11-3
...@@ -219,7 +219,7 @@ void ast_print(AstNode *node, int indent) {...@@ -219,7 +219,7 @@ void ast_print(AstNode *node, int indent) {
219 }219 }
220 case AstNodeTypeTypePointer:220 case AstNodeTypeTypePointer:
221 {221 {
222 const char *const_or_mut_str = node->data.type.is_const ? "const" : "mut";222 const char *const_or_mut_str = node->data.type.is_const ? "const" : "var";
223 fprintf(stderr, "'%s' PointerType\n", const_or_mut_str);223 fprintf(stderr, "'%s' PointerType\n", const_or_mut_str);
224224
225 ast_print(node->data.type.child_type, indent + 2);225 ast_print(node->data.type.child_type, indent + 2);
...@@ -227,9 +227,11 @@ void ast_print(AstNode *node, int indent) {...@@ -227,9 +227,11 @@ void ast_print(AstNode *node, int indent) {
227 }227 }
228 case AstNodeTypeTypeArray:228 case AstNodeTypeTypeArray:
229 {229 {
230 fprintf(stderr, "ArrayType\n");230 const char *const_or_mut_str = node->data.type.is_const ? "const" : "var";
231 fprintf(stderr, "'%s' ArrayType\n", const_or_mut_str);
232 if (node->data.type.array_size)
233 ast_print(node->data.type.array_size, indent + 2);
231 ast_print(node->data.type.child_type, indent + 2);234 ast_print(node->data.type.child_type, indent + 2);
232 ast_print(node->data.type.array_size, indent + 2);
233 break;235 break;
234 }236 }
235 case AstNodeTypeTypeMaybe:237 case AstNodeTypeTypeMaybe:
...@@ -1107,6 +1109,12 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {...@@ -1107,6 +1109,12 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {
11071109
1108 ast_eat_token(pc, token_index, TokenIdRBracket);1110 ast_eat_token(pc, token_index, TokenIdRBracket);
11091111
1112 Token *const_tok = &pc->tokens->at(*token_index);
1113 if (const_tok->id == TokenIdKeywordConst) {
1114 *token_index += 1;
1115 node->data.type.is_const = true;
1116 }
1117
1110 node->data.type.child_type = ast_parse_type(pc, token_index);1118 node->data.type.child_type = ast_parse_type(pc, token_index);
1111 } else {1119 } else {
1112 ast_invalid_token_error(pc, token);1120 ast_invalid_token_error(pc, token);
std/std.zig+6-2
...@@ -39,13 +39,13 @@ pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize {...@@ -39,13 +39,13 @@ pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize {
3939
40// TODO error handling40// TODO error handling
41// TODO handle buffering and flushing (mutex protected)41// TODO handle buffering and flushing (mutex protected)
42pub fn print_str(str: string) -> isize {42pub fn print_str(str: []const u8) -> isize {
43 fprint_str(stdout_fileno, str)43 fprint_str(stdout_fileno, str)
44}44}
4545
46// TODO error handling46// TODO error handling
47// TODO handle buffering and flushing (mutex protected)47// TODO handle buffering and flushing (mutex protected)
48pub fn fprint_str(fd: isize, str: string) -> isize {48pub fn fprint_str(fd: isize, str: []const u8) -> isize {
49 write(fd, str.ptr, str.len)49 write(fd, str.ptr, str.len)
50}50}
5151
...@@ -73,6 +73,9 @@ fn digit_to_char(digit: u64) -> u8 {...@@ -73,6 +73,9 @@ fn digit_to_char(digit: u64) -> u8 {
7373
74const max_u64_base10_digits: usize = 20;74const max_u64_base10_digits: usize = 20;
7575
76// TODO use an array for out_buf instead of pointer. this should give bounds checking in
77// debug mode and length can get optimized out in release mode. requires array slicing syntax
78// for the buf_print_u64 call.
76fn buf_print_i64(out_buf: &u8, x: i64) -> usize {79fn buf_print_i64(out_buf: &u8, x: i64) -> usize {
77 if (x < 0) {80 if (x < 0) {
78 out_buf[0] = '-';81 out_buf[0] = '-';
...@@ -82,6 +85,7 @@ fn buf_print_i64(out_buf: &u8, x: i64) -> usize {...@@ -82,6 +85,7 @@ fn buf_print_i64(out_buf: &u8, x: i64) -> usize {
82 }85 }
83}86}
8487
88// TODO use an array for out_buf instead of pointer.
85fn buf_print_u64(out_buf: &u8, x: u64) -> usize {89fn buf_print_u64(out_buf: &u8, x: u64) -> usize {
86 var buf: [max_u64_base10_digits]u8;90 var buf: [max_u64_base10_digits]u8;
87 var a = x;91 var a = x;