| author | |
| committer | |
| log | 187d00ca835d2c923cbc0a3ab9e861e82888d403 |
| tree | 923b224c44e801b3d6bb9e8a2432d216c1f7e6d6 |
| parent | 968b85ad77892da945d478799d4e775222248f1f |
closes #405 files changed, 113 insertions(+), 105 deletions(-)
example/arrays/arrays.zig+13-24| ... | @@ -2,37 +2,26 @@ export executable "arrays"; | ... | @@ -2,37 +2,26 @@ export executable "arrays"; |
| 2 | 2 | ||
| 3 | use "std.zig"; | 3 | use "std.zig"; |
| 4 | 4 | ||
| 5 | export fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | 5 | pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 6 | var array : [i32; 5]; | 6 | var array : [u32; 5]; |
| 7 | 7 | ||
| 8 | var i : i32 = 0; | 8 | var i : u32 = 0; |
| 9 | loop_start: | 9 | while (i < 5) { |
| 10 | if i == 5 { | 10 | array[i] = i + 1; |
| 11 | goto loop_end; | 11 | i = array[i]; |
| 12 | } | 12 | } |
| 13 | array[i] = i + 1; | ||
| 14 | i = array[i]; | ||
| 15 | goto loop_start; | ||
| 16 | |||
| 17 | loop_end: | ||
| 18 | 13 | ||
| 19 | i = 0; | 14 | i = 0; |
| 20 | var accumulator : i32 = 0; | 15 | var accumulator : u32 = 0; |
| 21 | loop_2_start: | 16 | while (i < 5) { |
| 22 | if i == 5 { | 17 | accumulator += array[i]; |
| 23 | goto loop_2_end; | ||
| 24 | } | ||
| 25 | |||
| 26 | accumulator += array[i]; | ||
| 27 | 18 | ||
| 28 | i = i + 1; | 19 | i += 1; |
| 29 | goto loop_2_start; | ||
| 30 | loop_2_end: | ||
| 31 | |||
| 32 | if accumulator == 15 { | ||
| 33 | print_str("OK\n" as string); | ||
| 34 | } | 20 | } |
| 35 | 21 | ||
| 22 | if (accumulator == 15) { | ||
| 23 | print_str("OK\n"); | ||
| 24 | } | ||
| 36 | 25 | ||
| 37 | return 0; | 26 | return 0; |
| 38 | } | 27 | } |
src/analyze.cpp+4-9| ... | @@ -1057,6 +1057,8 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1057,6 +1057,8 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i |
| 1057 | 1057 | ||
| 1058 | if (array_type->id == TypeTableEntryIdArray) { | 1058 | if (array_type->id == TypeTableEntryIdArray) { |
| 1059 | return_type = array_type->data.array.child_type; | 1059 | return_type = array_type->data.array.child_type; |
| 1060 | } else if (array_type->id == TypeTableEntryIdPointer) { | ||
| 1061 | return_type = array_type->data.pointer.child_type; | ||
| 1060 | } else { | 1062 | } else { |
| 1061 | if (array_type->id != TypeTableEntryIdInvalid) { | 1063 | if (array_type->id != TypeTableEntryIdInvalid) { |
| 1062 | add_node_error(g, node, buf_sprintf("array access of non-array")); | 1064 | add_node_error(g, node, buf_sprintf("array access of non-array")); |
| ... | @@ -1064,14 +1066,7 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -1064,14 +1066,7 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i |
| 1064 | return_type = g->builtin_types.entry_invalid; | 1066 | return_type = g->builtin_types.entry_invalid; |
| 1065 | } | 1067 | } |
| 1066 | 1068 | ||
| 1067 | TypeTableEntry *subscript_type = analyze_expression(g, import, context, nullptr, | 1069 | analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.array_access_expr.subscript); |
| 1068 | node->data.array_access_expr.subscript); | ||
| 1069 | if (subscript_type->id != TypeTableEntryIdInt && | ||
| 1070 | subscript_type->id != TypeTableEntryIdInvalid) | ||
| 1071 | { | ||
| 1072 | add_node_error(g, node, | ||
| 1073 | buf_sprintf("array subscripts must be integers")); | ||
| 1074 | } | ||
| 1075 | 1070 | ||
| 1076 | return return_type; | 1071 | return return_type; |
| 1077 | } | 1072 | } |
| ... | @@ -1150,7 +1145,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B | ... | @@ -1150,7 +1145,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 1150 | cast_node->after_type = wanted_type; | 1145 | cast_node->after_type = wanted_type; |
| 1151 | 1146 | ||
| 1152 | // special casing this for now, TODO think about casting and do a general solution | 1147 | // special casing this for now, TODO think about casting and do a general solution |
| 1153 | if (wanted_type == g->builtin_types.entry_isize && | 1148 | if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) && |
| 1154 | actual_type->id == TypeTableEntryIdPointer) | 1149 | actual_type->id == TypeTableEntryIdPointer) |
| 1155 | { | 1150 | { |
| 1156 | cast_node->op = CastOpPtrToInt; | 1151 | cast_node->op = CastOpPtrToInt; |
src/codegen.cpp+65-24| ... | @@ -199,19 +199,48 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -199,19 +199,48 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 199 | static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { | 199 | static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { |
| 200 | assert(node->type == NodeTypeArrayAccessExpr); | 200 | assert(node->type == NodeTypeArrayAccessExpr); |
| 201 | 201 | ||
| 202 | // TODO gen_lvalue | 202 | TypeTableEntry *type_entry = get_expr_type(node->data.array_access_expr.array_ref_expr); |
| 203 | LLVMValueRef array_ref_value = gen_expr(g, node->data.array_access_expr.array_ref_expr); | 203 | AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr; |
| 204 | |||
| 205 | LLVMValueRef array_ptr = gen_expr(g, array_expr_node); | ||
| 206 | /* | ||
| 207 | if (array_expr_node->type == NodeTypeSymbol) { | ||
| 208 | VariableTableEntry *var = find_variable(array_expr_node->codegen_node->expr_node.block_context, | ||
| 209 | &array_expr_node->data.symbol); | ||
| 210 | assert(var); | ||
| 211 | |||
| 212 | array_ptr = var->value_ref; | ||
| 213 | } else if (array_expr_node->type == NodeTypeFieldAccessExpr) { | ||
| 214 | zig_panic("TODO gen array ptr field access expr"); | ||
| 215 | } else if (array_expr_node->type == NodeTypeArrayAccessExpr) { | ||
| 216 | zig_panic("TODO gen array ptr array access expr"); | ||
| 217 | } else { | ||
| 218 | array_ptr = gen_expr(g, array_expr_node); | ||
| 219 | } | ||
| 220 | */ | ||
| 221 | |||
| 204 | LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript); | 222 | LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript); |
| 205 | 223 | ||
| 206 | assert(array_ref_value); | 224 | assert(array_ptr); |
| 207 | assert(subscript_value); | 225 | assert(subscript_value); |
| 208 | 226 | ||
| 209 | LLVMValueRef indices[] = { | 227 | if (type_entry->id == TypeTableEntryIdArray) { |
| 210 | LLVMConstInt(LLVMInt32Type(), 0, false), | 228 | LLVMValueRef indices[] = { |
| 211 | subscript_value | 229 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 212 | }; | 230 | subscript_value |
| 213 | add_debug_source_node(g, node); | 231 | }; |
| 214 | return LLVMBuildInBoundsGEP(g->builder, array_ref_value, indices, 2, ""); | 232 | add_debug_source_node(g, node); |
| 233 | return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); | ||
| 234 | } else if (type_entry->id == TypeTableEntryIdPointer) { | ||
| 235 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); | ||
| 236 | LLVMValueRef indices[] = { | ||
| 237 | subscript_value | ||
| 238 | }; | ||
| 239 | add_debug_source_node(g, node); | ||
| 240 | return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, ""); | ||
| 241 | } else { | ||
| 242 | zig_unreachable(); | ||
| 243 | } | ||
| 215 | } | 244 | } |
| 216 | 245 | ||
| 217 | static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) { | 246 | static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) { |
| ... | @@ -279,6 +308,14 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva | ... | @@ -279,6 +308,14 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva |
| 279 | if (buf_eql_str(name, "len")) { | 308 | if (buf_eql_str(name, "len")) { |
| 280 | return LLVMConstInt(g->builtin_types.entry_usize->type_ref, | 309 | return LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 281 | struct_type->data.array.len, false); | 310 | struct_type->data.array.len, false); |
| 311 | } else if (buf_eql_str(name, "ptr")) { | ||
| 312 | LLVMValueRef array_val = gen_expr(g, node->data.field_access_expr.struct_expr); | ||
| 313 | LLVMValueRef indices[] = { | ||
| 314 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | ||
| 315 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | ||
| 316 | }; | ||
| 317 | add_debug_source_node(g, node); | ||
| 318 | return LLVMBuildInBoundsGEP(g->builder, array_val, indices, 2, ""); | ||
| 282 | } else { | 319 | } else { |
| 283 | zig_panic("gen_field_access_expr bad array field"); | 320 | zig_panic("gen_field_access_expr bad array field"); |
| 284 | } | 321 | } |
| ... | @@ -314,9 +351,15 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, | ... | @@ -314,9 +351,15 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, |
| 314 | target_ref = var->value_ref; | 351 | target_ref = var->value_ref; |
| 315 | } else if (node->type == NodeTypeArrayAccessExpr) { | 352 | } else if (node->type == NodeTypeArrayAccessExpr) { |
| 316 | TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr); | 353 | TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr); |
| 317 | assert(array_type->id == TypeTableEntryIdArray); | 354 | if (array_type->id == TypeTableEntryIdArray) { |
| 318 | *out_type_entry = array_type->data.array.child_type; | 355 | *out_type_entry = array_type->data.array.child_type; |
| 319 | target_ref = gen_array_ptr(g, node); | 356 | target_ref = gen_array_ptr(g, node); |
| 357 | } else if (array_type->id == TypeTableEntryIdPointer) { | ||
| 358 | *out_type_entry = array_type->data.pointer.child_type; | ||
| 359 | target_ref = gen_array_ptr(g, node); | ||
| 360 | } else { | ||
| 361 | zig_unreachable(); | ||
| 362 | } | ||
| 320 | } else if (node->type == NodeTypeFieldAccessExpr) { | 363 | } else if (node->type == NodeTypeFieldAccessExpr) { |
| 321 | target_ref = gen_field_ptr(g, node, out_type_entry); | 364 | target_ref = gen_field_ptr(g, node, out_type_entry); |
| 322 | } else { | 365 | } else { |
| ... | @@ -389,28 +432,26 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v | ... | @@ -389,28 +432,26 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v |
| 389 | return cast_node->ptr; | 432 | return cast_node->ptr; |
| 390 | } | 433 | } |
| 391 | case CastOpPtrToInt: | 434 | case CastOpPtrToInt: |
| 435 | add_debug_source_node(g, node); | ||
| 392 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); | 436 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 393 | case CastOpPointerReinterpret: | 437 | case CastOpPointerReinterpret: |
| 438 | add_debug_source_node(g, node); | ||
| 394 | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); | 439 | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); |
| 395 | case CastOpIntWidenOrShorten: | 440 | case CastOpIntWidenOrShorten: |
| 396 | if (actual_type->size_in_bits == wanted_type->size_in_bits) { | 441 | if (actual_type->size_in_bits == wanted_type->size_in_bits) { |
| 397 | return expr_val; | 442 | return expr_val; |
| 398 | } else if (actual_type->size_in_bits < wanted_type->size_in_bits) { | 443 | } else if (actual_type->size_in_bits < wanted_type->size_in_bits) { |
| 399 | if (actual_type->data.integral.is_signed && wanted_type->data.integral.is_signed) { | 444 | if (actual_type->data.integral.is_signed) { |
| 445 | add_debug_source_node(g, node); | ||
| 400 | return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); | 446 | return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 401 | } else if (!actual_type->data.integral.is_signed && !wanted_type->data.integral.is_signed) { | ||
| 402 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); | ||
| 403 | } else { | 447 | } else { |
| 404 | zig_panic("TODO gen_cast_expr mixing of signness"); | 448 | add_debug_source_node(g, node); |
| 449 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); | ||
| 405 | } | 450 | } |
| 406 | } else { | 451 | } else { |
| 407 | assert(actual_type->size_in_bits > wanted_type->size_in_bits); | 452 | assert(actual_type->size_in_bits > wanted_type->size_in_bits); |
| 408 | 453 | add_debug_source_node(g, node); | |
| 409 | if (actual_type->data.integral.is_signed && wanted_type->data.integral.is_signed) { | 454 | return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 410 | return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | ||
| 411 | } else { | ||
| 412 | zig_panic("TODO gen_cast_expr shorten unsigned"); | ||
| 413 | } | ||
| 414 | } | 455 | } |
| 415 | case CastOpArrayToString: | 456 | case CastOpArrayToString: |
| 416 | { | 457 | { |
| ... | @@ -1232,8 +1273,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1232,8 +1273,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1232 | Buf *str = &node->data.string_literal.buf; | 1273 | Buf *str = &node->data.string_literal.buf; |
| 1233 | LLVMValueRef str_val = find_or_create_string(g, str, node->data.string_literal.c); | 1274 | LLVMValueRef str_val = find_or_create_string(g, str, node->data.string_literal.c); |
| 1234 | LLVMValueRef indices[] = { | 1275 | LLVMValueRef indices[] = { |
| 1235 | LLVMConstInt(LLVMInt32Type(), 0, false), | 1276 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 1236 | LLVMConstInt(LLVMInt32Type(), 0, false) | 1277 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 1237 | }; | 1278 | }; |
| 1238 | LLVMValueRef ptr_val = LLVMBuildInBoundsGEP(g->builder, str_val, indices, 2, ""); | 1279 | LLVMValueRef ptr_val = LLVMBuildInBoundsGEP(g->builder, str_val, indices, 2, ""); |
| 1239 | return ptr_val; | 1280 | return ptr_val; |
std/std.zig+19-26| ... | @@ -1,40 +1,37 @@ | ... | @@ -1,40 +1,37 @@ |
| 1 | const SYS_write : isize = 1; | 1 | const SYS_write : usize = 1; |
| 2 | const SYS_exit : isize = 60; | 2 | const SYS_exit : usize = 60; |
| 3 | const SYS_getrandom : isize = 278; | 3 | const SYS_getrandom : usize = 278; |
| 4 | 4 | ||
| 5 | const stdout_fileno : isize = 1; | 5 | const stdout_fileno : isize = 1; |
| 6 | const stderr_fileno : isize = 2; | 6 | const stderr_fileno : isize = 2; |
| 7 | 7 | ||
| 8 | fn syscall1(number: isize, arg1: isize) -> isize { | 8 | fn syscall1(number: usize, arg1: usize) -> usize { |
| 9 | asm volatile ("syscall" | 9 | asm volatile ("syscall" |
| 10 | : [ret] "={rax}" (-> isize) | 10 | : [ret] "={rax}" (-> usize) |
| 11 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) | 11 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1) |
| 12 | : "rcx", "r11") | 12 | : "rcx", "r11") |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { | 15 | fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { |
| 16 | asm volatile ("syscall" | 16 | asm volatile ("syscall" |
| 17 | : [ret] "={rax}" (-> isize) | 17 | : [ret] "={rax}" (-> usize) |
| 18 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) | 18 | : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3) |
| 19 | : "rcx", "r11") | 19 | : "rcx", "r11") |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | /* | ||
| 23 | pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { | 22 | pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize { |
| 24 | return syscall3(SYS_getrandom, buf as isize, count as isize, flags as isize); | 23 | return syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize; |
| 25 | } | 24 | } |
| 26 | */ | ||
| 27 | 25 | ||
| 28 | pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { | 26 | pub fn write(fd: isize, buf: &const u8, count: usize) -> isize { |
| 29 | return syscall3(SYS_write, fd, buf as isize, count as isize); | 27 | return syscall3(SYS_write, fd as usize, buf as usize, count) as isize; |
| 30 | } | 28 | } |
| 31 | 29 | ||
| 32 | pub fn exit(status: i32) -> unreachable { | 30 | pub fn exit(status: i32) -> unreachable { |
| 33 | syscall1(SYS_exit, status as isize); | 31 | syscall1(SYS_exit, status as usize); |
| 34 | unreachable; | 32 | unreachable; |
| 35 | } | 33 | } |
| 36 | 34 | ||
| 37 | /* | ||
| 38 | fn digit_to_char(digit: u64) -> u8 { '0' + (digit as u8) } | 35 | fn digit_to_char(digit: u64) -> u8 { '0' + (digit as u8) } |
| 39 | 36 | ||
| 40 | const max_u64_base10_digits: usize = 20; | 37 | const max_u64_base10_digits: usize = 20; |
| ... | @@ -66,17 +63,6 @@ fn buf_print_u64(out_buf: &u8, x: u64) -> usize { | ... | @@ -66,17 +63,6 @@ fn buf_print_u64(out_buf: &u8, x: u64) -> usize { |
| 66 | return len; | 63 | return len; |
| 67 | } | 64 | } |
| 68 | 65 | ||
| 69 | // TODO handle buffering and flushing (mutex protected) | ||
| 70 | // TODO error handling | ||
| 71 | pub fn print_u64(x: u64) -> isize { | ||
| 72 | // TODO use max_u64_base10_digits instead of hardcoding 20 | ||
| 73 | var buf: [u8; 20]; | ||
| 74 | const len = buf_print_u64(buf.ptr, x); | ||
| 75 | return write(stdout_fileno, buf.ptr, len); | ||
| 76 | } | ||
| 77 | */ | ||
| 78 | |||
| 79 | |||
| 80 | // TODO error handling | 66 | // TODO error handling |
| 81 | // TODO handle buffering and flushing (mutex protected) | 67 | // TODO handle buffering and flushing (mutex protected) |
| 82 | pub fn print_str(str: string) -> isize { fprint_str(stdout_fileno, str) } | 68 | pub fn print_str(str: string) -> isize { fprint_str(stdout_fileno, str) } |
| ... | @@ -87,9 +73,16 @@ pub fn fprint_str(fd: isize, str: string) -> isize { | ... | @@ -87,9 +73,16 @@ pub fn fprint_str(fd: isize, str: string) -> isize { |
| 87 | return write(fd, str.ptr, str.len); | 73 | return write(fd, str.ptr, str.len); |
| 88 | } | 74 | } |
| 89 | 75 | ||
| 90 | /* | 76 | // TODO handle buffering and flushing (mutex protected) |
| 77 | // TODO error handling | ||
| 78 | pub fn print_u64(x: u64) -> isize { | ||
| 79 | // TODO use max_u64_base10_digits instead of hardcoding 20 | ||
| 80 | var buf: [u8; 20]; | ||
| 81 | const len = buf_print_u64(buf.ptr, x); | ||
| 82 | return write(stdout_fileno, buf.ptr, len); | ||
| 83 | } | ||
| 84 | |||
| 91 | // TODO error handling | 85 | // TODO error handling |
| 92 | pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize { | 86 | pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize { |
| 93 | return getrandom(buf, count, 0); | 87 | return getrandom(buf, count, 0); |
| 94 | } | 88 | } |
| 95 | */ |
test/run_tests.cpp+12-22| ... | @@ -319,31 +319,21 @@ done: | ... | @@ -319,31 +319,21 @@ done: |
| 319 | use "std.zig"; | 319 | use "std.zig"; |
| 320 | 320 | ||
| 321 | pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | 321 | pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 322 | var array : [i32; 5]; | 322 | var array : [u32; 5]; |
| 323 | 323 | ||
| 324 | var i : i32 = 0; | 324 | var i : u32 = 0; |
| 325 | loop_start: | 325 | while (i < 5) { |
| 326 | if (i == 5) { | 326 | array[i] = i + 1; |
| 327 | goto loop_end; | 327 | i = array[i]; |
| 328 | } | 328 | } |
| 329 | array[i] = i + 1; | ||
| 330 | i = array[i]; | ||
| 331 | goto loop_start; | ||
| 332 | |||
| 333 | loop_end: | ||
| 334 | 329 | ||
| 335 | i = 0; | 330 | i = 0; |
| 336 | var accumulator = 0 as i32; | 331 | var accumulator = 0 as u32; |
| 337 | loop_2_start: | 332 | while (i < 5) { |
| 338 | if (i == 5) { | 333 | accumulator += array[i]; |
| 339 | goto loop_2_end; | ||
| 340 | } | ||
| 341 | 334 | ||
| 342 | accumulator = accumulator + array[i]; | 335 | i += 1; |
| 343 | 336 | } | |
| 344 | i = i + 1; | ||
| 345 | goto loop_2_start; | ||
| 346 | loop_2_end: | ||
| 347 | 337 | ||
| 348 | if (accumulator == 15) { | 338 | if (accumulator == 15) { |
| 349 | print_str("OK\n"); | 339 | print_str("OK\n"); |
| ... | @@ -871,9 +861,9 @@ fn f() { | ... | @@ -871,9 +861,9 @@ fn f() { |
| 871 | ".tmp_source.zig:4:12: error: use of undeclared identifier 'i'", | 861 | ".tmp_source.zig:4:12: error: use of undeclared identifier 'i'", |
| 872 | ".tmp_source.zig:4:14: error: use of undeclared identifier 'i'", | 862 | ".tmp_source.zig:4:14: error: use of undeclared identifier 'i'", |
| 873 | ".tmp_source.zig:5:8: error: array access of non-array", | 863 | ".tmp_source.zig:5:8: error: array access of non-array", |
| 874 | ".tmp_source.zig:5:8: error: array subscripts must be integers", | 864 | ".tmp_source.zig:5:9: error: expected type 'usize', got 'bool'", |
| 875 | ".tmp_source.zig:5:19: error: array access of non-array", | 865 | ".tmp_source.zig:5:19: error: array access of non-array", |
| 876 | ".tmp_source.zig:5:19: error: array subscripts must be integers"); | 866 | ".tmp_source.zig:5:20: error: expected type 'usize', got 'bool'"); |
| 877 | 867 | ||
| 878 | add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE( | 868 | add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE( |
| 879 | fn f(...) {} | 869 | fn f(...) {} |