authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-22 22:59:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-22 22:59:52-05:00
log201a3c121a5c28273138b1160c5aac4e24d619bd
tree68480040ae3c4cedce7d8bf953cd69359b6749f1
parent47cf8520adb245dbd34ad60fc9206b7eaab5e0be

introduce comptime expression

closes #221

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

doc/langref.md+5-3
......@@ -123,7 +123,7 @@ MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
123123
124124PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
125125
126SuffixOpExpression = option("inline") PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
126SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
127127
128128FieldAccessExpression = "." Symbol
129129
......@@ -141,11 +141,13 @@ StructLiteralField = "." Symbol "=" Expression
141141
142142PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
143143
144PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
144PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | CompTimeExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
145145
146146ArrayType = "[" option(Expression) "]" option("const") TypeExpr
147147
148GotoExpression = option("inline") "goto" Symbol
148GotoExpression = "goto" Symbol
149
150CompTimeExpression = option("comptime") Expression
149151
150152GroupedExpression = "(" Expression ")"
151153
src/all_types.hpp+14-1
......@@ -280,6 +280,7 @@ enum NodeType {
280280 NodeTypeSwitchRange,
281281 NodeTypeLabel,
282282 NodeTypeGoto,
283 NodeTypeCompTime,
283284 NodeTypeBreak,
284285 NodeTypeContinue,
285286 NodeTypeAsmExpr,
......@@ -449,7 +450,6 @@ struct AstNodeFnCallExpr {
449450 AstNode *fn_ref_expr;
450451 ZigList<AstNode *> params;
451452 bool is_builtin;
452 bool is_comptime;
453453};
454454
455455struct AstNodeArrayAccessExpr {
......@@ -556,6 +556,10 @@ struct AstNodeGoto {
556556 bool is_inline;
557557};
558558
559struct AstNodeCompTime {
560 AstNode *expr;
561};
562
559563struct AsmOutput {
560564 Buf *asm_symbolic_name;
561565 Buf *constraint;
......@@ -721,6 +725,7 @@ struct AstNode {
721725 AstNodeSwitchRange switch_range;
722726 AstNodeLabel label;
723727 AstNodeGoto goto_expr;
728 AstNodeCompTime comptime_expr;
724729 AstNodeAsmExpr asm_expr;
725730 AstNodeFieldAccessExpr field_access_expr;
726731 AstNodeContainerDecl container_decl;
......@@ -1289,6 +1294,7 @@ enum ScopeId {
12891294 ScopeIdCImport,
12901295 ScopeIdLoop,
12911296 ScopeIdFnDef,
1297 ScopeIdCompTime,
12921298};
12931299
12941300struct Scope {
......@@ -1366,6 +1372,13 @@ struct ScopeLoop {
13661372 Scope base;
13671373};
13681374
1375// This scope is created for a comptime expression.
1376// NodeTypeCompTime
1377struct ScopeCompTime {
1378 Scope base;
1379};
1380
1381
13691382// This scope is created for a function definition.
13701383// NodeTypeFnDef
13711384struct ScopeFnDef {
src/analyze.cpp+9-61
......@@ -24,67 +24,6 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type);
2424static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type);
2525static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type);
2626
27AstNode *first_executing_node(AstNode *node) {
28 switch (node->type) {
29 case NodeTypeFnCallExpr:
30 return first_executing_node(node->data.fn_call_expr.fn_ref_expr);
31 case NodeTypeBinOpExpr:
32 return first_executing_node(node->data.bin_op_expr.op1);
33 case NodeTypeUnwrapErrorExpr:
34 return first_executing_node(node->data.unwrap_err_expr.op1);
35 case NodeTypeArrayAccessExpr:
36 return first_executing_node(node->data.array_access_expr.array_ref_expr);
37 case NodeTypeSliceExpr:
38 return first_executing_node(node->data.slice_expr.array_ref_expr);
39 case NodeTypeFieldAccessExpr:
40 return first_executing_node(node->data.field_access_expr.struct_expr);
41 case NodeTypeSwitchRange:
42 return first_executing_node(node->data.switch_range.start);
43 case NodeTypeRoot:
44 case NodeTypeFnProto:
45 case NodeTypeFnDef:
46 case NodeTypeFnDecl:
47 case NodeTypeParamDecl:
48 case NodeTypeBlock:
49 case NodeTypeReturnExpr:
50 case NodeTypeDefer:
51 case NodeTypeVariableDeclaration:
52 case NodeTypeTypeDecl:
53 case NodeTypeErrorValueDecl:
54 case NodeTypeNumberLiteral:
55 case NodeTypeStringLiteral:
56 case NodeTypeCharLiteral:
57 case NodeTypeSymbol:
58 case NodeTypePrefixOpExpr:
59 case NodeTypeUse:
60 case NodeTypeBoolLiteral:
61 case NodeTypeNullLiteral:
62 case NodeTypeUndefinedLiteral:
63 case NodeTypeThisLiteral:
64 case NodeTypeIfBoolExpr:
65 case NodeTypeIfVarExpr:
66 case NodeTypeLabel:
67 case NodeTypeGoto:
68 case NodeTypeBreak:
69 case NodeTypeContinue:
70 case NodeTypeAsmExpr:
71 case NodeTypeContainerDecl:
72 case NodeTypeStructField:
73 case NodeTypeStructValueField:
74 case NodeTypeWhileExpr:
75 case NodeTypeForExpr:
76 case NodeTypeSwitchExpr:
77 case NodeTypeSwitchProng:
78 case NodeTypeArrayType:
79 case NodeTypeErrorType:
80 case NodeTypeTypeLiteral:
81 case NodeTypeContainerInitExpr:
82 case NodeTypeVarLiteral:
83 return node;
84 }
85 zig_unreachable();
86}
87
8827ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
8928 // if this assert fails, then parseh generated code that
9029 // failed semantic analysis, which isn't supposed to happen
......@@ -199,6 +138,13 @@ ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_en
199138 return scope;
200139}
201140
141Scope *create_comptime_scope(AstNode *node, Scope *parent) {
142 assert(node->type == NodeTypeCompTime);
143 ScopeCompTime *scope = allocate<ScopeCompTime>(1);
144 init_scope(&scope->base, ScopeIdCompTime, node, parent);
145 return &scope->base;
146}
147
202148ImportTableEntry *get_scope_import(Scope *scope) {
203149 while (scope) {
204150 if (scope->id == ScopeIdDecls) {
......@@ -1804,6 +1750,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
18041750 case NodeTypeSwitchRange:
18051751 case NodeTypeLabel:
18061752 case NodeTypeGoto:
1753 case NodeTypeCompTime:
18071754 case NodeTypeBreak:
18081755 case NodeTypeContinue:
18091756 case NodeTypeAsmExpr:
......@@ -2199,6 +2146,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {
21992146 case ScopeIdVarDecl:
22002147 case ScopeIdCImport:
22012148 case ScopeIdLoop:
2149 case ScopeIdCompTime:
22022150 scope = scope->parent;
22032151 continue;
22042152 case ScopeIdFnDef:
src/analyze.hpp+1-2
......@@ -42,8 +42,6 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
4242ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
4343 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
4444
45AstNode *first_executing_node(AstNode *node);
46
4745
4846// TODO move these over, these used to be static
4947bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
......@@ -95,6 +93,7 @@ ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
9593Scope *create_loop_scope(AstNode *node, Scope *parent);
9694ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
9795ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
96Scope *create_comptime_scope(AstNode *node, Scope *parent);
9897
9998void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
10099ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
src/ast_render.cpp+9-2
......@@ -197,6 +197,8 @@ static const char *node_type_str(NodeType node_type) {
197197 return "Label";
198198 case NodeTypeGoto:
199199 return "Goto";
200 case NodeTypeCompTime:
201 return "CompTime";
200202 case NodeTypeBreak:
201203 return "Break";
202204 case NodeTypeContinue:
......@@ -810,8 +812,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
810812 }
811813 case NodeTypeGoto:
812814 {
813 const char *inline_str = node->data.goto_expr.is_inline ? "inline " : "";
814 fprintf(ar->f, "%sgoto %s", inline_str, buf_ptr(node->data.goto_expr.name));
815 fprintf(ar->f, "goto %s", buf_ptr(node->data.goto_expr.name));
816 break;
817 }
818 case NodeTypeCompTime:
819 {
820 fprintf(ar->f, "comptime ");
821 render_node_grouped(ar, node->data.comptime_expr.expr);
815822 break;
816823 }
817824 case NodeTypeForExpr:
src/codegen.cpp+2-1
......@@ -316,7 +316,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
316316 case ScopeIdBlock:
317317 case ScopeIdDefer:
318318 case ScopeIdVarDecl:
319 case ScopeIdLoop:
320319 {
321320 assert(scope->parent);
322321 ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder,
......@@ -328,6 +327,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
328327 return scope->di_scope;
329328 }
330329 case ScopeIdDeferExpr:
330 case ScopeIdLoop:
331 case ScopeIdCompTime:
331332 return get_di_scope(g, scope->parent);
332333 }
333334 zig_unreachable();
src/ir.cpp+44-27
......@@ -64,8 +64,16 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
6464 }
6565}
6666
67static bool ir_should_inline(IrBuilder *irb) {
68 return irb->exec->is_inline;
67static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
68 if (exec->is_inline)
69 return true;
70
71 while (scope != nullptr) {
72 if (scope->id == ScopeIdCompTime)
73 return true;
74 scope = scope->parent;
75 }
76 return false;
6977}
7078
7179static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
......@@ -2904,7 +2912,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29042912 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
29052913
29062914 IrInstruction *is_comptime;
2907 if (ir_should_inline(irb)) {
2915 if (ir_should_inline(irb->exec, scope)) {
29082916 is_comptime = ir_build_const_bool(irb, scope, node, true);
29092917 } else {
29102918 is_comptime = ir_build_test_comptime(irb, scope, node, is_err);
......@@ -2926,7 +2934,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29262934 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value);
29272935
29282936 IrInstruction *is_comptime;
2929 if (ir_should_inline(irb)) {
2937 if (ir_should_inline(irb->exec, scope)) {
29302938 is_comptime = ir_build_const_bool(irb, scope, node, true);
29312939 } else {
29322940 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
......@@ -2958,7 +2966,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29582966
29592967 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");
29602968 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");
2961 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb));
2969 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope));
29622970 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
29632971
29642972 ir_set_cursor_at_end(irb, return_block);
......@@ -2984,7 +2992,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29842992
29852993 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");
29862994 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue");
2987 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb));
2995 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope));
29882996 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime));
29892997
29902998 ir_set_cursor_at_end(irb, return_block);
......@@ -3128,7 +3136,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31283136
31293137 if (!return_value || !instr_is_unreachable(return_value)) {
31303138 IrInstruction *is_comptime = ir_mark_gen(ir_build_const_bool(irb, child_scope, statement_node,
3131 ir_should_inline(irb)));
3139 ir_should_inline(irb->exec, child_scope)));
31323140 ir_mark_gen(ir_build_br(irb, child_scope, statement_node, label_block, is_comptime));
31333141 }
31343142 ir_set_cursor_at_end(irb, label_block);
......@@ -3207,7 +3215,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
32073215 IrBasicBlock *post_val1_block = irb->current_basic_block;
32083216
32093217 IrInstruction *is_comptime;
3210 if (ir_should_inline(irb)) {
3218 if (ir_should_inline(irb->exec, scope)) {
32113219 is_comptime = ir_build_const_bool(irb, scope, node, true);
32123220 } else {
32133221 is_comptime = ir_build_test_comptime(irb, scope, node, val1);
......@@ -3249,7 +3257,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
32493257 IrBasicBlock *post_val1_block = irb->current_basic_block;
32503258
32513259 IrInstruction *is_comptime;
3252 if (ir_should_inline(irb)) {
3260 if (ir_should_inline(irb->exec, scope)) {
32533261 is_comptime = ir_build_const_bool(irb, scope, node, true);
32543262 } else {
32553263 is_comptime = ir_build_test_comptime(irb, scope, node, val1);
......@@ -3296,7 +3304,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
32963304 IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_val);
32973305
32983306 IrInstruction *is_comptime;
3299 if (ir_should_inline(irb)) {
3307 if (ir_should_inline(irb->exec, parent_scope)) {
33003308 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
33013309 } else {
33023310 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);
......@@ -4042,8 +4050,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
40424050 return args[i];
40434051 }
40444052
4045 bool is_comptime = node->data.fn_call_expr.is_comptime;
4046 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, is_comptime);
4053 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false);
40474054}
40484055
40494056static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -4054,7 +4061,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
40544061 return condition;
40554062
40564063 IrInstruction *is_comptime;
4057 if (ir_should_inline(irb) || node->data.if_bool_expr.is_inline) {
4064 if (ir_should_inline(irb->exec, scope) || node->data.if_bool_expr.is_inline) {
40584065 is_comptime = ir_build_const_bool(irb, scope, node, true);
40594066 } else {
40604067 is_comptime = ir_build_test_comptime(irb, scope, node, condition);
......@@ -4281,7 +4288,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
42814288 bool is_const = variable_declaration->is_const;
42824289 bool is_extern = variable_declaration->is_extern;
42834290 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
4284 ir_should_inline(irb) || variable_declaration->is_inline);
4291 ir_should_inline(irb->exec, scope) || variable_declaration->is_inline);
42854292 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
42864293 is_const, is_const, is_shadowable, is_comptime);
42874294 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
......@@ -4312,7 +4319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
43124319 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");
43134320
43144321 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
4315 ir_should_inline(irb) || node->data.while_expr.is_inline);
4322 ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline);
43164323 ir_build_br(irb, scope, node, cond_block, is_comptime);
43174324
43184325 if (continue_expr_node) {
......@@ -4381,7 +4388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
43814388 }
43824389
43834390 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
4384 ir_should_inline(irb) || node->data.for_expr.is_inline);
4391 ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline);
43854392
43864393 Scope *child_scope = create_loop_scope(node, parent_scope);
43874394
......@@ -4602,7 +4609,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
46024609 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");
46034610
46044611 IrInstruction *is_comptime;
4605 if (ir_should_inline(irb) || node->data.if_var_expr.is_inline) {
4612 if (ir_should_inline(irb->exec, scope) || node->data.if_var_expr.is_inline) {
46064613 is_comptime = ir_build_const_bool(irb, scope, node, true);
46074614 } else {
46084615 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
......@@ -4714,7 +4721,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
47144721 ZigList<IrInstructionSwitchBrCase> cases = {0};
47154722
47164723 IrInstruction *is_comptime;
4717 if (ir_should_inline(irb) || node->data.switch_expr.is_inline) {
4724 if (ir_should_inline(irb->exec, scope) || node->data.switch_expr.is_inline) {
47184725 is_comptime = ir_build_const_bool(irb, scope, node, true);
47194726 } else {
47204727 is_comptime = ir_build_test_comptime(irb, scope, node, target_value);
......@@ -4892,6 +4899,13 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, Scope *scope, AstNode *node) {
48924899 return ir_build_unreachable(irb, scope, node);
48934900}
48944901
4902static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LValPurpose lval) {
4903 assert(node->type == NodeTypeCompTime);
4904
4905 Scope *child_scope = create_comptime_scope(node, parent_scope);
4906 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval);
4907}
4908
48954909static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) {
48964910 assert(node->type == NodeTypeBreak);
48974911
......@@ -4904,7 +4918,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
49044918 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
49054919
49064920 IrInstruction *is_comptime;
4907 if (ir_should_inline(irb) || node->data.break_expr.is_inline) {
4921 if (ir_should_inline(irb->exec, scope) || node->data.break_expr.is_inline) {
49084922 is_comptime = ir_build_const_bool(irb, scope, node, true);
49094923 } else {
49104924 is_comptime = loop_stack_item->is_comptime;
......@@ -4927,7 +4941,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
49274941 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
49284942
49294943 IrInstruction *is_comptime;
4930 if (ir_should_inline(irb) || node->data.continue_expr.is_inline) {
4944 if (ir_should_inline(irb->exec, scope) || node->data.continue_expr.is_inline) {
49314945 is_comptime = ir_build_const_bool(irb, scope, node, true);
49324946 } else {
49334947 is_comptime = loop_stack_item->is_comptime;
......@@ -5003,7 +5017,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
50035017 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
50045018
50055019 IrInstruction *is_comptime;
5006 if (ir_should_inline(irb)) {
5020 if (ir_should_inline(irb->exec, parent_scope)) {
50075021 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
50085022 } else {
50095023 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err);
......@@ -5197,6 +5211,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
51975211 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
51985212 case NodeTypeGoto:
51995213 return ir_lval_wrap(irb, scope, ir_gen_goto(irb, scope, node), lval);
5214 case NodeTypeCompTime:
5215 return ir_gen_comptime(irb, scope, node, lval);
52005216 case NodeTypeTypeLiteral:
52015217 return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);
52025218 case NodeTypeErrorType:
......@@ -5259,7 +5275,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {
52595275 label->used = true;
52605276
52615277 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,
5262 ir_should_inline(irb) || source_node->data.goto_expr.is_inline);
5278 ir_should_inline(irb->exec, goto_item->scope) || source_node->data.goto_expr.is_inline);
52635279 if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false)) {
52645280 add_node_error(irb->codegen, source_node,
52655281 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
......@@ -5379,7 +5395,7 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
53795395}
53805396
53815397static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
5382 if (ir_should_inline(&ira->new_irb)) {
5398 if (ir_should_inline(ira->new_irb.exec, source_instruction->scope)) {
53835399 ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression"));
53845400 return false;
53855401 }
......@@ -7841,7 +7857,8 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
78417857 if (fn_ref->value.type->id == TypeTableEntryIdInvalid)
78427858 return ira->codegen->builtin_types.entry_invalid;
78437859
7844 bool is_inline = call_instruction->is_comptime || ir_should_inline(&ira->new_irb);
7860 bool is_inline = call_instruction->is_comptime ||
7861 ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);
78457862
78467863 if (is_inline || instr_is_comptime(fn_ref)) {
78477864 if (fn_ref->value.type->id == TypeTableEntryIdMetaType) {
......@@ -8146,7 +8163,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
81468163 return ir_unreach_error(ira);
81478164
81488165 if (!cond_br_instruction->base.is_gen && !condition->value.depends_on_compile_var &&
8149 !ir_should_inline(&ira->new_irb))
8166 !ir_should_inline(ira->new_irb.exec, cond_br_instruction->base.scope))
81508167 {
81518168 const char *true_or_false = cond_is_true ? "true" : "false";
81528169 ir_add_error(ira, &cond_br_instruction->base,
......@@ -9814,7 +9831,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
98149831
98159832 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
98169833
9817 bool is_comptime = ir_should_inline(&ira->new_irb);
9834 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
98189835
98199836 ConstExprValue const_val = {};
98209837 const_val.special = ConstValSpecialStatic;
......@@ -9931,7 +9948,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
99319948 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
99329949 const_val.data.x_array.size = elem_count;
99339950
9934 bool is_comptime = ir_should_inline(&ira->new_irb);
9951 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
99359952
99369953 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
99379954
src/parser.cpp+34-39
......@@ -585,29 +585,14 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
585585}
586586
587587/*
588GotoExpression = option("inline") "goto" Symbol
588GotoExpression = "goto" Symbol
589589*/
590590static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
591 Token *first_token = &pc->tokens->at(*token_index);
592 Token *goto_token;
593 bool is_inline;
594 if (first_token->id == TokenIdKeywordInline) {
595 is_inline = true;
596 goto_token = &pc->tokens->at(*token_index + 1);
597 if (goto_token->id == TokenIdKeywordGoto) {
598 *token_index += 2;
599 } else if (mandatory) {
600 ast_expect_token(pc, first_token, TokenIdKeywordGoto);
601 zig_unreachable();
602 } else {
603 return nullptr;
604 }
605 } else if (first_token->id == TokenIdKeywordGoto) {
606 goto_token = first_token;
607 is_inline = false;
591 Token *goto_token = &pc->tokens->at(*token_index);
592 if (goto_token->id == TokenIdKeywordGoto) {
608593 *token_index += 1;
609594 } else if (mandatory) {
610 ast_expect_token(pc, first_token, TokenIdKeywordGoto);
595 ast_expect_token(pc, goto_token, TokenIdKeywordGoto);
611596 zig_unreachable();
612597 } else {
613598 return nullptr;
......@@ -617,11 +602,30 @@ static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool
617602
618603 Token *dest_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
619604 node->data.goto_expr.name = token_buf(dest_symbol);
620 node->data.goto_expr.is_inline = is_inline;
621605 return node;
622606}
607
623608/*
624PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
609CompTimeExpression = "comptime" Expression
610*/
611static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
612 Token *comptime_token = &pc->tokens->at(*token_index);
613 if (comptime_token->id == TokenIdKeywordCompTime) {
614 *token_index += 1;
615 } else if (mandatory) {
616 ast_expect_token(pc, comptime_token, TokenIdKeywordCompTime);
617 zig_unreachable();
618 } else {
619 return nullptr;
620 }
621
622 AstNode *node = ast_create_node(pc, NodeTypeCompTime, comptime_token);
623 node->data.comptime_expr.expr = ast_parse_expression(pc, token_index, true);
624 return node;
625}
626
627/*
628PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | CompTimeExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
625629KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
626630*/
627631static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
......@@ -706,6 +710,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
706710 if (goto_node)
707711 return goto_node;
708712
713 AstNode *comptime_node = ast_parse_comptime_expr(pc, token_index, false);
714 if (comptime_node)
715 return comptime_node;
716
709717 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
710718 if (grouped_expr_node) {
711719 return grouped_expr_node;
......@@ -835,7 +843,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde
835843}
836844
837845/*
838SuffixOpExpression = option("inline") PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
846SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
839847FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
840848ArrayAccessExpression : token(LBracket) Expression token(RBracket)
841849SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
......@@ -843,24 +851,9 @@ FieldAccessExpression : token(Dot) token(Symbol)
843851StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
844852*/
845853static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
846 Token *inline_token = &pc->tokens->at(*token_index);
847 bool is_comptime;
848 if (inline_token->id == TokenIdKeywordInline) {
849 // TODO make it an error if something other than function call has the comptime keyword
850 is_comptime = true;
851 *token_index += 1;
852 } else {
853 is_comptime = false;
854 }
855
856
857854 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
858 if (!primary_expr) {
859 if (is_comptime) {
860 *token_index -= 1;
861 }
855 if (!primary_expr)
862856 return nullptr;
863 }
864857
865858 while (true) {
866859 Token *first_token = &pc->tokens->at(*token_index);
......@@ -869,7 +862,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
869862
870863 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);
871864 node->data.fn_call_expr.fn_ref_expr = primary_expr;
872 node->data.fn_call_expr.is_comptime = is_comptime;
873865 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
874866
875867 primary_expr = node;
......@@ -2624,6 +2616,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
26242616 case NodeTypeGoto:
26252617 // none
26262618 break;
2619 case NodeTypeCompTime:
2620 visit_field(&node->data.comptime_expr.expr, visit, context);
2621 break;
26272622 case NodeTypeBreak:
26282623 // none
26292624 break;