| author | |
| committer | |
| log | 32d8686da80d282e8cd6d84a0e5c331d269a1f69 |
| tree | 889c1f634f4ff2e7b9d8cb078f11dbb41c4a1b2a |
| parent | 17cb85dfb837949cd3a559fe8e99dee1f72463a4 |
* comptime expression is a block expression as it should be
* fix var args when number of args passed is 0
* implement const value equality for structs
* fix indent when rendering container decl AST
* IR: prevent duplicate generation of code when it is partially
compile-time evaluated
* implement compile time struct field pointer evaluation
* fix compile time evaluation of slicing10 files changed, 84 insertions(+), 42 deletions(-)
doc/langref.md+4-4| ... | @@ -69,7 +69,9 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un | ... | @@ -69,7 +69,9 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un |
| 69 | 69 | ||
| 70 | AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%=" | 70 | AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%=" |
| 71 | 71 | ||
| 72 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | 72 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression |
| 73 | |||
| 74 | CompTimeExpression = option("comptime") Expression | ||
| 73 | 75 | ||
| 74 | SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}" | 76 | SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}" |
| 75 | 77 | ||
| ... | @@ -141,14 +143,12 @@ StructLiteralField = "." Symbol "=" Expression | ... | @@ -141,14 +143,12 @@ StructLiteralField = "." Symbol "=" Expression |
| 141 | 143 | ||
| 142 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%" | 144 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%" |
| 143 | 145 | ||
| 144 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | CompTimeExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | 146 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl |
| 145 | 147 | ||
| 146 | ArrayType = "[" option(Expression) "]" option("const") TypeExpr | 148 | ArrayType = "[" option(Expression) "]" option("const") TypeExpr |
| 147 | 149 | ||
| 148 | GotoExpression = "goto" Symbol | 150 | GotoExpression = "goto" Symbol |
| 149 | 151 | ||
| 150 | CompTimeExpression = option("comptime") Expression | ||
| 151 | |||
| 152 | GroupedExpression = "(" Expression ")" | 152 | GroupedExpression = "(" Expression ")" |
| 153 | 153 | ||
| 154 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | 154 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" |
example/cat/main.zig+4-12| ... | @@ -16,9 +16,7 @@ pub fn main(args: [][]u8) -> %void { | ... | @@ -16,9 +16,7 @@ pub fn main(args: [][]u8) -> %void { |
| 16 | } else { | 16 | } else { |
| 17 | var is: io.InStream = undefined; | 17 | var is: io.InStream = undefined; |
| 18 | is.open(arg) %% |err| { | 18 | is.open(arg) %% |err| { |
| 19 | %%io.stderr.printf("Unable to open file: "); | 19 | %%io.stderr.printf("Unable to open file: {}\n", @errorName(err)); |
| 20 | %%io.stderr.printf(@errorName(err)); | ||
| 21 | %%io.stderr.printf("\n"); | ||
| 22 | return err; | 20 | return err; |
| 23 | }; | 21 | }; |
| 24 | defer %%is.close(); | 22 | defer %%is.close(); |
| ... | @@ -34,9 +32,7 @@ pub fn main(args: [][]u8) -> %void { | ... | @@ -34,9 +32,7 @@ pub fn main(args: [][]u8) -> %void { |
| 34 | } | 32 | } |
| 35 | 33 | ||
| 36 | fn usage(exe: []u8) -> %void { | 34 | fn usage(exe: []u8) -> %void { |
| 37 | %%io.stderr.printf("Usage: "); | 35 | %%io.stderr.printf("Usage: {} [FILE]...\n", exe); |
| 38 | %%io.stderr.printf(exe); | ||
| 39 | %%io.stderr.printf(" [FILE]...\n"); | ||
| 40 | return error.Invalid; | 36 | return error.Invalid; |
| 41 | } | 37 | } |
| 42 | 38 | ||
| ... | @@ -45,9 +41,7 @@ fn cat_stream(is: &io.InStream) -> %void { | ... | @@ -45,9 +41,7 @@ fn cat_stream(is: &io.InStream) -> %void { |
| 45 | 41 | ||
| 46 | while (true) { | 42 | while (true) { |
| 47 | const bytes_read = is.read(buf) %% |err| { | 43 | const bytes_read = is.read(buf) %% |err| { |
| 48 | %%io.stderr.printf("Unable to read from stream: "); | 44 | %%io.stderr.printf("Unable to read from stream: {}\n", @errorName(err)); |
| 49 | %%io.stderr.printf(@errorName(err)); | ||
| 50 | %%io.stderr.printf("\n"); | ||
| 51 | return err; | 45 | return err; |
| 52 | }; | 46 | }; |
| 53 | 47 | ||
| ... | @@ -56,9 +50,7 @@ fn cat_stream(is: &io.InStream) -> %void { | ... | @@ -56,9 +50,7 @@ fn cat_stream(is: &io.InStream) -> %void { |
| 56 | } | 50 | } |
| 57 | 51 | ||
| 58 | io.stdout.write(buf[0...bytes_read]) %% |err| { | 52 | io.stdout.write(buf[0...bytes_read]) %% |err| { |
| 59 | %%io.stderr.printf("Unable to write to stdout: "); | 53 | %%io.stderr.printf("Unable to write to stdout: {}\n", @errorName(err)); |
| 60 | %%io.stderr.printf(@errorName(err)); | ||
| 61 | %%io.stderr.printf("\n"); | ||
| 62 | return err; | 54 | return err; |
| 63 | }; | 55 | }; |
| 64 | } | 56 | } |
src/all_types.hpp-2| ... | @@ -1042,8 +1042,6 @@ struct FnTableEntry { | ... | @@ -1042,8 +1042,6 @@ struct FnTableEntry { |
| 1042 | 1042 | ||
| 1043 | ZigList<IrInstruction *> alloca_list; | 1043 | ZigList<IrInstruction *> alloca_list; |
| 1044 | ZigList<VariableTableEntry *> variable_list; | 1044 | ZigList<VariableTableEntry *> variable_list; |
| 1045 | |||
| 1046 | VariableTableEntry *var_args_var; | ||
| 1047 | }; | 1045 | }; |
| 1048 | 1046 | ||
| 1049 | uint32_t fn_table_entry_hash(FnTableEntry*); | 1047 | uint32_t fn_table_entry_hash(FnTableEntry*); |
src/analyze.cpp+7-1| ... | @@ -3263,7 +3263,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -3263,7 +3263,13 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 3263 | case TypeTableEntryIdArray: | 3263 | case TypeTableEntryIdArray: |
| 3264 | zig_panic("TODO"); | 3264 | zig_panic("TODO"); |
| 3265 | case TypeTableEntryIdStruct: | 3265 | case TypeTableEntryIdStruct: |
| 3266 | zig_panic("TODO"); | 3266 | for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { |
| 3267 | ConstExprValue *field_a = &a->data.x_struct.fields[i]; | ||
| 3268 | ConstExprValue *field_b = &b->data.x_struct.fields[i]; | ||
| 3269 | if (!const_values_equal(field_a, field_b)) | ||
| 3270 | return false; | ||
| 3271 | } | ||
| 3272 | return true; | ||
| 3267 | case TypeTableEntryIdUnion: | 3273 | case TypeTableEntryIdUnion: |
| 3268 | zig_panic("TODO"); | 3274 | zig_panic("TODO"); |
| 3269 | case TypeTableEntryIdUndefLit: | 3275 | case TypeTableEntryIdUndefLit: |
src/ast_render.cpp+1| ... | @@ -600,6 +600,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -600,6 +600,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 600 | } | 600 | } |
| 601 | 601 | ||
| 602 | ar->indent -= ar->indent_size; | 602 | ar->indent -= ar->indent_size; |
| 603 | print_indent(ar); | ||
| 603 | fprintf(ar->f, "}"); | 604 | fprintf(ar->f, "}"); |
| 604 | break; | 605 | break; |
| 605 | } | 606 | } |
src/ir.cpp+46-16| ... | @@ -5743,6 +5743,8 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { | ... | @@ -5743,6 +5743,8 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 5743 | IrInstruction *dep_instruction = ir_instruction_get_dep(instruction, dep_i); | 5743 | IrInstruction *dep_instruction = ir_instruction_get_dep(instruction, dep_i); |
| 5744 | if (dep_instruction == nullptr) | 5744 | if (dep_instruction == nullptr) |
| 5745 | break; | 5745 | break; |
| 5746 | if (dep_instruction->other) | ||
| 5747 | continue; | ||
| 5746 | if (dep_instruction->owner_bb == old_bb) | 5748 | if (dep_instruction->owner_bb == old_bb) |
| 5747 | continue; | 5749 | continue; |
| 5748 | ir_get_new_bb(ira, dep_instruction->owner_bb); | 5750 | ir_get_new_bb(ira, dep_instruction->owner_bb); |
| ... | @@ -7565,19 +7567,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -7565,19 +7567,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 7565 | } | 7567 | } |
| 7566 | 7568 | ||
| 7567 | Buf *param_name = param_decl_node->data.param_decl.name; | 7569 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 7568 | if (is_var_args) { | 7570 | if (!is_var_args) { |
| 7569 | if (!impl_fn->var_args_var) { | ||
| 7570 | ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, | ||
| 7571 | fn_type_id->param_count, fn_type_id->param_count + 1); | ||
| 7572 | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, | ||
| 7573 | *child_scope, param_name, true, var_args_val); | ||
| 7574 | var->value.depends_on_compile_var = true; | ||
| 7575 | *child_scope = var->child_scope; | ||
| 7576 | impl_fn->var_args_var = var; | ||
| 7577 | } | ||
| 7578 | impl_fn->var_args_var->value.data.x_arg_tuple.end_index = fn_type_id->param_count + 1; | ||
| 7579 | |||
| 7580 | } else { | ||
| 7581 | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, | 7571 | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, |
| 7582 | *child_scope, param_name, true, arg_val); | 7572 | *child_scope, param_name, true, arg_val); |
| 7583 | var->value.depends_on_compile_var = true; | 7573 | var->value.depends_on_compile_var = true; |
| ... | @@ -7611,7 +7601,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -7611,7 +7601,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 7611 | { | 7601 | { |
| 7612 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 7602 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 7613 | size_t first_arg_1_or_0 = first_arg_ptr ? 1 : 0; | 7603 | size_t first_arg_1_or_0 = first_arg_ptr ? 1 : 0; |
| 7614 | size_t src_param_count = fn_type_id->param_count; | 7604 | size_t var_args_1_or_0 = fn_type_id->is_var_args ? 1 : 0; |
| 7605 | size_t src_param_count = fn_type_id->param_count - var_args_1_or_0; | ||
| 7615 | size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0; | 7606 | size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0; |
| 7616 | AstNode *source_node = call_instruction->base.source_node; | 7607 | AstNode *source_node = call_instruction->base.source_node; |
| 7617 | 7608 | ||
| ... | @@ -7739,11 +7730,22 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -7739,11 +7730,22 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 7739 | return ira->codegen->builtin_types.entry_invalid; | 7730 | return ira->codegen->builtin_types.entry_invalid; |
| 7740 | } | 7731 | } |
| 7741 | } | 7732 | } |
| 7733 | |||
| 7734 | bool found_first_var_arg = false; | ||
| 7735 | size_t first_var_arg = inst_fn_type_id.param_count; | ||
| 7742 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { | 7736 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| 7743 | IrInstruction *arg = call_instruction->args[call_i]->other; | 7737 | IrInstruction *arg = call_instruction->args[call_i]->other; |
| 7744 | if (arg->value.type->id == TypeTableEntryIdInvalid) | 7738 | if (arg->value.type->id == TypeTableEntryIdInvalid) |
| 7745 | return ira->codegen->builtin_types.entry_invalid; | 7739 | return ira->codegen->builtin_types.entry_invalid; |
| 7746 | 7740 | ||
| 7741 | AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(next_proto_i); | ||
| 7742 | assert(param_decl_node->type == NodeTypeParamDecl); | ||
| 7743 | bool is_var_args = param_decl_node->data.param_decl.is_var_args; | ||
| 7744 | if (is_var_args && !found_first_var_arg) { | ||
| 7745 | first_var_arg = inst_fn_type_id.param_count; | ||
| 7746 | found_first_var_arg = true; | ||
| 7747 | } | ||
| 7748 | |||
| 7747 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, | 7749 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, |
| 7748 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) | 7750 | &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) |
| 7749 | { | 7751 | { |
| ... | @@ -7751,6 +7753,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -7751,6 +7753,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 7751 | } | 7753 | } |
| 7752 | } | 7754 | } |
| 7753 | 7755 | ||
| 7756 | if (fn_proto_node->data.fn_proto.is_var_args) { | ||
| 7757 | AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(next_proto_i); | ||
| 7758 | Buf *param_name = param_decl_node->data.param_decl.name; | ||
| 7759 | |||
| 7760 | ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, | ||
| 7761 | first_var_arg, inst_fn_type_id.param_count); | ||
| 7762 | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, | ||
| 7763 | impl_fn->child_scope, param_name, true, var_args_val); | ||
| 7764 | var->value.depends_on_compile_var = true; | ||
| 7765 | impl_fn->child_scope = var->child_scope; | ||
| 7766 | } | ||
| 7754 | { | 7767 | { |
| 7755 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 7768 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 7756 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); | 7769 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); |
| ... | @@ -8317,8 +8330,9 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8317,8 +8330,9 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8317 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { | 8330 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| 8318 | ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone; | 8331 | ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone; |
| 8319 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; | 8332 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| 8333 | depends_on_compile_var = mem_slot->depends_on_compile_var || depends_on_compile_var || is_comptime; | ||
| 8320 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, | 8334 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, |
| 8321 | mem_slot->depends_on_compile_var || depends_on_compile_var, ptr_special, is_const); | 8335 | depends_on_compile_var, ptr_special, is_const); |
| 8322 | } else { | 8336 | } else { |
| 8323 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); | 8337 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); |
| 8324 | type_ensure_zero_bits_known(ira->codegen, var->value.type); | 8338 | type_ensure_zero_bits_known(ira->codegen, var->value.type); |
| ... | @@ -8513,6 +8527,22 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -8513,6 +8527,22 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8513 | 8527 | ||
| 8514 | TypeStructField *field = find_struct_type_field(bare_type, field_name); | 8528 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| 8515 | if (field) { | 8529 | if (field) { |
| 8530 | if (instr_is_comptime(container_ptr)) { | ||
| 8531 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); | ||
| 8532 | if (!ptr_val) | ||
| 8533 | return ira->codegen->builtin_types.entry_invalid; | ||
| 8534 | |||
| 8535 | ConstExprValue *struct_val = const_ptr_pointee(ptr_val); | ||
| 8536 | if (value_is_comptime(struct_val)) { | ||
| 8537 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; | ||
| 8538 | if (value_is_comptime(field_val)) { | ||
| 8539 | bool depends_on_compile_var = field_val->depends_on_compile_var || | ||
| 8540 | struct_val->depends_on_compile_var || ptr_val->depends_on_compile_var; | ||
| 8541 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, field_val, | ||
| 8542 | field_val->type, depends_on_compile_var, ConstPtrSpecialNone, is_const); | ||
| 8543 | } | ||
| 8544 | } | ||
| 8545 | } | ||
| 8516 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 8546 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 8517 | return get_pointer_to_type(ira->codegen, field->type_entry, is_const); | 8547 | return get_pointer_to_type(ira->codegen, field->type_entry, is_const); |
| 8518 | } else { | 8548 | } else { |
| ... | @@ -10937,7 +10967,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -10937,7 +10967,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 10937 | init_const_ptr(ira->codegen, ptr_val, base_ptr, index, instruction->is_const); | 10967 | init_const_ptr(ira->codegen, ptr_val, base_ptr, index, instruction->is_const); |
| 10938 | 10968 | ||
| 10939 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; | 10969 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; |
| 10940 | init_const_usize(ira->codegen, len_val, rel_end); | 10970 | init_const_usize(ira->codegen, len_val, end_scalar - start_scalar); |
| 10941 | 10971 | ||
| 10942 | return return_type; | 10972 | return return_type; |
| 10943 | } | 10973 | } |
src/parser.cpp+6-6| ... | @@ -624,7 +624,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b | ... | @@ -624,7 +624,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | /* | 626 | /* |
| 627 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | CompTimeExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | 627 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl |
| 628 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | 628 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" |
| 629 | */ | 629 | */ |
| 630 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 630 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| ... | @@ -709,10 +709,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -709,10 +709,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 709 | if (goto_node) | 709 | if (goto_node) |
| 710 | return goto_node; | 710 | return goto_node; |
| 711 | 711 | ||
| 712 | AstNode *comptime_node = ast_parse_comptime_expr(pc, token_index, false); | ||
| 713 | if (comptime_node) | ||
| 714 | return comptime_node; | ||
| 715 | |||
| 716 | AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false); | 712 | AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false); |
| 717 | if (grouped_expr_node) { | 713 | if (grouped_expr_node) { |
| 718 | return grouped_expr_node; | 714 | return grouped_expr_node; |
| ... | @@ -1810,7 +1806,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo | ... | @@ -1810,7 +1806,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo |
| 1810 | } | 1806 | } |
| 1811 | 1807 | ||
| 1812 | /* | 1808 | /* |
| 1813 | BlockExpression : IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | 1809 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression |
| 1814 | */ | 1810 | */ |
| 1815 | static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1811 | static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1816 | Token *token = &pc->tokens->at(*token_index); | 1812 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1835,6 +1831,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool | ... | @@ -1835,6 +1831,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool |
| 1835 | if (block) | 1831 | if (block) |
| 1836 | return block; | 1832 | return block; |
| 1837 | 1833 | ||
| 1834 | AstNode *comptime_node = ast_parse_comptime_expr(pc, token_index, false); | ||
| 1835 | if (comptime_node) | ||
| 1836 | return comptime_node; | ||
| 1837 | |||
| 1838 | if (mandatory) | 1838 | if (mandatory) |
| 1839 | ast_invalid_token_error(pc, token); | 1839 | ast_invalid_token_error(pc, token); |
| 1840 | 1840 |
test/cases/eval.zig+14| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | ||
| 2 | 3 | ||
| 3 | fn compileTimeRecursion() { | 4 | fn compileTimeRecursion() { |
| 4 | @setFnTest(this); | 5 | @setFnTest(this); |
| ... | @@ -161,3 +162,16 @@ fn staticallyInitializedArrayLiteral() { | ... | @@ -161,3 +162,16 @@ fn staticallyInitializedArrayLiteral() { |
| 161 | assert(y[3] == 4); | 162 | assert(y[3] == 4); |
| 162 | } | 163 | } |
| 163 | const st_init_arr_lit_x = []u8{1,2,3,4}; | 164 | const st_init_arr_lit_x = []u8{1,2,3,4}; |
| 165 | |||
| 166 | |||
| 167 | fn constSlice() { | ||
| 168 | @setFnTest(this); | ||
| 169 | |||
| 170 | comptime { | ||
| 171 | const a = "1234567890"; | ||
| 172 | assert(a.len == 10); | ||
| 173 | const b = a[1...2]; | ||
| 174 | assert(b.len == 1); | ||
| 175 | assert(b[0] == '2'); | ||
| 176 | } | ||
| 177 | } |
test/cases/generics.zig+1-1| ... | @@ -13,7 +13,7 @@ fn max(comptime T: type, a: T, b: T) -> T { | ... | @@ -13,7 +13,7 @@ fn max(comptime T: type, a: T, b: T) -> T { |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | fn add(comptime a: i32, b: i32) -> i32 { | 15 | fn add(comptime a: i32, b: i32) -> i32 { |
| 16 | return comptime {a} + b; | 16 | return (comptime {a}) + b; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | const the_max = max(u32, 1234, 5678); | 19 | const the_max = max(u32, 1234, 5678); |
test/cases/var_args.zig+1| ... | @@ -13,4 +13,5 @@ fn testAddArbitraryArgs() { | ... | @@ -13,4 +13,5 @@ fn testAddArbitraryArgs() { |
| 13 | 13 | ||
| 14 | assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); | 14 | assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); |
| 15 | assert(add(i32(1234)) == 1234); | 15 | assert(add(i32(1234)) == 1234); |
| 16 | assert(add() == 0); | ||
| 16 | } | 17 | } |