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 = "*" | "/" | "%" | "**" | "*%"...@@ -123,7 +123,7 @@ MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
123123
124PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression124PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
125125
126SuffixOpExpression = option("inline") PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)126SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
127127
128FieldAccessExpression = "." Symbol128FieldAccessExpression = "." Symbol
129129
...@@ -141,11 +141,13 @@ StructLiteralField = "." Symbol "=" Expression...@@ -141,11 +141,13 @@ StructLiteralField = "." Symbol "=" Expression
141141
142PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"142PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
143143
144PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl144PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | CompTimeExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
145145
146ArrayType = "[" option(Expression) "]" option("const") TypeExpr146ArrayType = "[" option(Expression) "]" option("const") TypeExpr
147147
148GotoExpression = option("inline") "goto" Symbol148GotoExpression = "goto" Symbol
149
150CompTimeExpression = option("comptime") Expression
149151
150GroupedExpression = "(" Expression ")"152GroupedExpression = "(" Expression ")"
151153
src/all_types.hpp+14-1
...@@ -280,6 +280,7 @@ enum NodeType {...@@ -280,6 +280,7 @@ enum NodeType {
280 NodeTypeSwitchRange,280 NodeTypeSwitchRange,
281 NodeTypeLabel,281 NodeTypeLabel,
282 NodeTypeGoto,282 NodeTypeGoto,
283 NodeTypeCompTime,
283 NodeTypeBreak,284 NodeTypeBreak,
284 NodeTypeContinue,285 NodeTypeContinue,
285 NodeTypeAsmExpr,286 NodeTypeAsmExpr,
...@@ -449,7 +450,6 @@ struct AstNodeFnCallExpr {...@@ -449,7 +450,6 @@ struct AstNodeFnCallExpr {
449 AstNode *fn_ref_expr;450 AstNode *fn_ref_expr;
450 ZigList<AstNode *> params;451 ZigList<AstNode *> params;
451 bool is_builtin;452 bool is_builtin;
452 bool is_comptime;
453};453};
454454
455struct AstNodeArrayAccessExpr {455struct AstNodeArrayAccessExpr {
...@@ -556,6 +556,10 @@ struct AstNodeGoto {...@@ -556,6 +556,10 @@ struct AstNodeGoto {
556 bool is_inline;556 bool is_inline;
557};557};
558558
559struct AstNodeCompTime {
560 AstNode *expr;
561};
562
559struct AsmOutput {563struct AsmOutput {
560 Buf *asm_symbolic_name;564 Buf *asm_symbolic_name;
561 Buf *constraint;565 Buf *constraint;
...@@ -721,6 +725,7 @@ struct AstNode {...@@ -721,6 +725,7 @@ struct AstNode {
721 AstNodeSwitchRange switch_range;725 AstNodeSwitchRange switch_range;
722 AstNodeLabel label;726 AstNodeLabel label;
723 AstNodeGoto goto_expr;727 AstNodeGoto goto_expr;
728 AstNodeCompTime comptime_expr;
724 AstNodeAsmExpr asm_expr;729 AstNodeAsmExpr asm_expr;
725 AstNodeFieldAccessExpr field_access_expr;730 AstNodeFieldAccessExpr field_access_expr;
726 AstNodeContainerDecl container_decl;731 AstNodeContainerDecl container_decl;
...@@ -1289,6 +1294,7 @@ enum ScopeId {...@@ -1289,6 +1294,7 @@ enum ScopeId {
1289 ScopeIdCImport,1294 ScopeIdCImport,
1290 ScopeIdLoop,1295 ScopeIdLoop,
1291 ScopeIdFnDef,1296 ScopeIdFnDef,
1297 ScopeIdCompTime,
1292};1298};
12931299
1294struct Scope {1300struct Scope {
...@@ -1366,6 +1372,13 @@ struct ScopeLoop {...@@ -1366,6 +1372,13 @@ struct ScopeLoop {
1366 Scope base;1372 Scope base;
1367};1373};
13681374
1375// This scope is created for a comptime expression.
1376// NodeTypeCompTime
1377struct ScopeCompTime {
1378 Scope base;
1379};
1380
1381
1369// This scope is created for a function definition.1382// This scope is created for a function definition.
1370// NodeTypeFnDef1383// NodeTypeFnDef
1371struct ScopeFnDef {1384struct ScopeFnDef {
src/analyze.cpp+9-61
...@@ -24,67 +24,6 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type);...@@ -24,67 +24,6 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type);
24static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type);24static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type);
25static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type);25static 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
88ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {27ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
89 // if this assert fails, then parseh generated code that28 // if this assert fails, then parseh generated code that
90 // failed semantic analysis, which isn't supposed to happen29 // failed semantic analysis, which isn't supposed to happen
...@@ -199,6 +138,13 @@ ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_en...@@ -199,6 +138,13 @@ ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_en
199 return scope;138 return scope;
200}139}
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
202ImportTableEntry *get_scope_import(Scope *scope) {148ImportTableEntry *get_scope_import(Scope *scope) {
203 while (scope) {149 while (scope) {
204 if (scope->id == ScopeIdDecls) {150 if (scope->id == ScopeIdDecls) {
...@@ -1804,6 +1750,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -1804,6 +1750,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
1804 case NodeTypeSwitchRange:1750 case NodeTypeSwitchRange:
1805 case NodeTypeLabel:1751 case NodeTypeLabel:
1806 case NodeTypeGoto:1752 case NodeTypeGoto:
1753 case NodeTypeCompTime:
1807 case NodeTypeBreak:1754 case NodeTypeBreak:
1808 case NodeTypeContinue:1755 case NodeTypeContinue:
1809 case NodeTypeAsmExpr:1756 case NodeTypeAsmExpr:
...@@ -2199,6 +2146,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {...@@ -2199,6 +2146,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope) {
2199 case ScopeIdVarDecl:2146 case ScopeIdVarDecl:
2200 case ScopeIdCImport:2147 case ScopeIdCImport:
2201 case ScopeIdLoop:2148 case ScopeIdLoop:
2149 case ScopeIdCompTime:
2202 scope = scope->parent;2150 scope = scope->parent;
2203 continue;2151 continue;
2204 case ScopeIdFnDef:2152 case ScopeIdFnDef:
src/analyze.hpp+1-2
...@@ -42,8 +42,6 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);...@@ -42,8 +42,6 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
42ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,42ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
43 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);43 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
4444
45AstNode *first_executing_node(AstNode *node);
46
4745
48// TODO move these over, these used to be static46// TODO move these over, these used to be static
49bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);47bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
...@@ -95,6 +93,7 @@ ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);...@@ -95,6 +93,7 @@ ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
95Scope *create_loop_scope(AstNode *node, Scope *parent);93Scope *create_loop_scope(AstNode *node, Scope *parent);
96ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);94ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
97ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);95ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
96Scope *create_comptime_scope(AstNode *node, Scope *parent);
9897
99void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);98void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
100ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);99ConstExprValue *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) {...@@ -197,6 +197,8 @@ static const char *node_type_str(NodeType node_type) {
197 return "Label";197 return "Label";
198 case NodeTypeGoto:198 case NodeTypeGoto:
199 return "Goto";199 return "Goto";
200 case NodeTypeCompTime:
201 return "CompTime";
200 case NodeTypeBreak:202 case NodeTypeBreak:
201 return "Break";203 return "Break";
202 case NodeTypeContinue:204 case NodeTypeContinue:
...@@ -810,8 +812,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -810,8 +812,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
810 }812 }
811 case NodeTypeGoto:813 case NodeTypeGoto:
812 {814 {
813 const char *inline_str = node->data.goto_expr.is_inline ? "inline " : "";815 fprintf(ar->f, "goto %s", buf_ptr(node->data.goto_expr.name));
814 fprintf(ar->f, "%sgoto %s", inline_str, 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);
815 break;822 break;
816 }823 }
817 case NodeTypeForExpr:824 case NodeTypeForExpr:
src/codegen.cpp+2-1
...@@ -316,7 +316,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -316,7 +316,6 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
316 case ScopeIdBlock:316 case ScopeIdBlock:
317 case ScopeIdDefer:317 case ScopeIdDefer:
318 case ScopeIdVarDecl:318 case ScopeIdVarDecl:
319 case ScopeIdLoop:
320 {319 {
321 assert(scope->parent);320 assert(scope->parent);
322 ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder,321 ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder,
...@@ -328,6 +327,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -328,6 +327,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
328 return scope->di_scope;327 return scope->di_scope;
329 }328 }
330 case ScopeIdDeferExpr:329 case ScopeIdDeferExpr:
330 case ScopeIdLoop:
331 case ScopeIdCompTime:
331 return get_di_scope(g, scope->parent);332 return get_di_scope(g, scope->parent);
332 }333 }
333 zig_unreachable();334 zig_unreachable();
src/ir.cpp+44-27
...@@ -64,8 +64,16 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {...@@ -64,8 +64,16 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
64 }64 }
65}65}
6666
67static bool ir_should_inline(IrBuilder *irb) {67static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
68 return irb->exec->is_inline;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;
69}77}
7078
71static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {79static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
...@@ -2904,7 +2912,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -2904,7 +2912,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
2904 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);2912 IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
29052913
2906 IrInstruction *is_comptime;2914 IrInstruction *is_comptime;
2907 if (ir_should_inline(irb)) {2915 if (ir_should_inline(irb->exec, scope)) {
2908 is_comptime = ir_build_const_bool(irb, scope, node, true);2916 is_comptime = ir_build_const_bool(irb, scope, node, true);
2909 } else {2917 } else {
2910 is_comptime = ir_build_test_comptime(irb, scope, node, is_err);2918 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,...@@ -2926,7 +2934,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
2926 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value);2934 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value);
29272935
2928 IrInstruction *is_comptime;2936 IrInstruction *is_comptime;
2929 if (ir_should_inline(irb)) {2937 if (ir_should_inline(irb->exec, scope)) {
2930 is_comptime = ir_build_const_bool(irb, scope, node, true);2938 is_comptime = ir_build_const_bool(irb, scope, node, true);
2931 } else {2939 } else {
2932 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);2940 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,...@@ -2958,7 +2966,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29582966
2959 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");2967 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");
2960 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");2968 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));
2962 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));2970 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
29632971
2964 ir_set_cursor_at_end(irb, return_block);2972 ir_set_cursor_at_end(irb, return_block);
...@@ -2984,7 +2992,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -2984,7 +2992,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
29842992
2985 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");2993 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");
2986 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue");2994 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));
2988 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime));2996 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime));
29892997
2990 ir_set_cursor_at_end(irb, return_block);2998 ir_set_cursor_at_end(irb, return_block);
...@@ -3128,7 +3136,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3128,7 +3136,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31283136
3129 if (!return_value || !instr_is_unreachable(return_value)) {3137 if (!return_value || !instr_is_unreachable(return_value)) {
3130 IrInstruction *is_comptime = ir_mark_gen(ir_build_const_bool(irb, child_scope, statement_node,3138 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)));
3132 ir_mark_gen(ir_build_br(irb, child_scope, statement_node, label_block, is_comptime));3140 ir_mark_gen(ir_build_br(irb, child_scope, statement_node, label_block, is_comptime));
3133 }3141 }
3134 ir_set_cursor_at_end(irb, label_block);3142 ir_set_cursor_at_end(irb, label_block);
...@@ -3207,7 +3215,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -3207,7 +3215,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
3207 IrBasicBlock *post_val1_block = irb->current_basic_block;3215 IrBasicBlock *post_val1_block = irb->current_basic_block;
32083216
3209 IrInstruction *is_comptime;3217 IrInstruction *is_comptime;
3210 if (ir_should_inline(irb)) {3218 if (ir_should_inline(irb->exec, scope)) {
3211 is_comptime = ir_build_const_bool(irb, scope, node, true);3219 is_comptime = ir_build_const_bool(irb, scope, node, true);
3212 } else {3220 } else {
3213 is_comptime = ir_build_test_comptime(irb, scope, node, val1);3221 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...@@ -3249,7 +3257,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3249 IrBasicBlock *post_val1_block = irb->current_basic_block;3257 IrBasicBlock *post_val1_block = irb->current_basic_block;
32503258
3251 IrInstruction *is_comptime;3259 IrInstruction *is_comptime;
3252 if (ir_should_inline(irb)) {3260 if (ir_should_inline(irb->exec, scope)) {
3253 is_comptime = ir_build_const_bool(irb, scope, node, true);3261 is_comptime = ir_build_const_bool(irb, scope, node, true);
3254 } else {3262 } else {
3255 is_comptime = ir_build_test_comptime(irb, scope, node, val1);3263 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...@@ -3296,7 +3304,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3296 IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_val);3304 IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_val);
32973305
3298 IrInstruction *is_comptime;3306 IrInstruction *is_comptime;
3299 if (ir_should_inline(irb)) {3307 if (ir_should_inline(irb->exec, parent_scope)) {
3300 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);3308 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
3301 } else {3309 } else {
3302 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);3310 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...@@ -4042,8 +4050,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
4042 return args[i];4050 return args[i];
4043 }4051 }
40444052
4045 bool is_comptime = node->data.fn_call_expr.is_comptime;4053 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false);
4046 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, is_comptime);
4047}4054}
40484055
4049static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {4056static 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...@@ -4054,7 +4061,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4054 return condition;4061 return condition;
40554062
4056 IrInstruction *is_comptime;4063 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) {
4058 is_comptime = ir_build_const_bool(irb, scope, node, true);4065 is_comptime = ir_build_const_bool(irb, scope, node, true);
4059 } else {4066 } else {
4060 is_comptime = ir_build_test_comptime(irb, scope, node, condition);4067 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...@@ -4281,7 +4288,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
4281 bool is_const = variable_declaration->is_const;4288 bool is_const = variable_declaration->is_const;
4282 bool is_extern = variable_declaration->is_extern;4289 bool is_extern = variable_declaration->is_extern;
4283 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,4290 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);
4285 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,4292 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
4286 is_const, is_const, is_shadowable, is_comptime);4293 is_const, is_const, is_shadowable, is_comptime);
4287 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node4294 // 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...@@ -4312,7 +4319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
4312 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");4319 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");
43134320
4314 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,4321 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);
4316 ir_build_br(irb, scope, node, cond_block, is_comptime);4323 ir_build_br(irb, scope, node, cond_block, is_comptime);
43174324
4318 if (continue_expr_node) {4325 if (continue_expr_node) {
...@@ -4381,7 +4388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -4381,7 +4388,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
4381 }4388 }
43824389
4383 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,4390 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
4386 Scope *child_scope = create_loop_scope(node, parent_scope);4393 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 *...@@ -4602,7 +4609,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
4602 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");4609 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");
46034610
4604 IrInstruction *is_comptime;4611 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) {
4606 is_comptime = ir_build_const_bool(irb, scope, node, true);4613 is_comptime = ir_build_const_bool(irb, scope, node, true);
4607 } else {4614 } else {
4608 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);4615 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 *...@@ -4714,7 +4721,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
4714 ZigList<IrInstructionSwitchBrCase> cases = {0};4721 ZigList<IrInstructionSwitchBrCase> cases = {0};
47154722
4716 IrInstruction *is_comptime;4723 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) {
4718 is_comptime = ir_build_const_bool(irb, scope, node, true);4725 is_comptime = ir_build_const_bool(irb, scope, node, true);
4719 } else {4726 } else {
4720 is_comptime = ir_build_test_comptime(irb, scope, node, target_value);4727 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) {...@@ -4892,6 +4899,13 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, Scope *scope, AstNode *node) {
4892 return ir_build_unreachable(irb, scope, node);4899 return ir_build_unreachable(irb, scope, node);
4893}4900}
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
4895static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) {4909static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node) {
4896 assert(node->type == NodeTypeBreak);4910 assert(node->type == NodeTypeBreak);
48974911
...@@ -4904,7 +4918,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -4904,7 +4918,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
4904 LoopStackItem *loop_stack_item = &irb->loop_stack.last();4918 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
49054919
4906 IrInstruction *is_comptime;4920 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) {
4908 is_comptime = ir_build_const_bool(irb, scope, node, true);4922 is_comptime = ir_build_const_bool(irb, scope, node, true);
4909 } else {4923 } else {
4910 is_comptime = loop_stack_item->is_comptime;4924 is_comptime = loop_stack_item->is_comptime;
...@@ -4927,7 +4941,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -4927,7 +4941,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
4927 LoopStackItem *loop_stack_item = &irb->loop_stack.last();4941 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
49284942
4929 IrInstruction *is_comptime;4943 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) {
4931 is_comptime = ir_build_const_bool(irb, scope, node, true);4945 is_comptime = ir_build_const_bool(irb, scope, node, true);
4932 } else {4946 } else {
4933 is_comptime = loop_stack_item->is_comptime;4947 is_comptime = loop_stack_item->is_comptime;
...@@ -5003,7 +5017,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -5003,7 +5017,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
5003 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);5017 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_val);
50045018
5005 IrInstruction *is_comptime;5019 IrInstruction *is_comptime;
5006 if (ir_should_inline(irb)) {5020 if (ir_should_inline(irb->exec, parent_scope)) {
5007 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);5021 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
5008 } else {5022 } else {
5009 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err);5023 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...@@ -5197,6 +5211,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
5197 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);5211 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
5198 case NodeTypeGoto:5212 case NodeTypeGoto:
5199 return ir_lval_wrap(irb, scope, ir_gen_goto(irb, scope, node), lval);5213 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);
5200 case NodeTypeTypeLiteral:5216 case NodeTypeTypeLiteral:
5201 return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);5217 return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);
5202 case NodeTypeErrorType:5218 case NodeTypeErrorType:
...@@ -5259,7 +5275,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {...@@ -5259,7 +5275,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {
5259 label->used = true;5275 label->used = true;
52605276
5261 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,5277 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);
5263 if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false)) {5279 if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false)) {
5264 add_node_error(irb->codegen, source_node,5280 add_node_error(irb->codegen, source_node,
5265 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));5281 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)...@@ -5379,7 +5395,7 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
5379}5395}
53805396
5381static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {5397static 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)) {
5383 ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression"));5399 ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression"));
5384 return false;5400 return false;
5385 }5401 }
...@@ -7841,7 +7857,8 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -7841,7 +7857,8 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
7841 if (fn_ref->value.type->id == TypeTableEntryIdInvalid)7857 if (fn_ref->value.type->id == TypeTableEntryIdInvalid)
7842 return ira->codegen->builtin_types.entry_invalid;7858 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
7846 if (is_inline || instr_is_comptime(fn_ref)) {7863 if (is_inline || instr_is_comptime(fn_ref)) {
7847 if (fn_ref->value.type->id == TypeTableEntryIdMetaType) {7864 if (fn_ref->value.type->id == TypeTableEntryIdMetaType) {
...@@ -8146,7 +8163,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -8146,7 +8163,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
8146 return ir_unreach_error(ira);8163 return ir_unreach_error(ira);
81478164
8148 if (!cond_br_instruction->base.is_gen && !condition->value.depends_on_compile_var &&8165 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))
8150 {8167 {
8151 const char *true_or_false = cond_is_true ? "true" : "false";8168 const char *true_or_false = cond_is_true ? "true" : "false";
8152 ir_add_error(ira, &cond_br_instruction->base,8169 ir_add_error(ira, &cond_br_instruction->base,
...@@ -9814,7 +9831,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru...@@ -9814,7 +9831,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
98149831
9815 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);9832 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
9819 ConstExprValue const_val = {};9836 ConstExprValue const_val = {};
9820 const_val.special = ConstValSpecialStatic;9837 const_val.special = ConstValSpecialStatic;
...@@ -9931,7 +9948,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -9931,7 +9948,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
9931 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);9948 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
9932 const_val.data.x_array.size = elem_count;9949 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
9936 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);9953 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...@@ -585,29 +585,14 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
585}585}
586586
587/*587/*
588GotoExpression = option("inline") "goto" Symbol588GotoExpression = "goto" Symbol
589*/589*/
590static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool mandatory) {590static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
591 Token *first_token = &pc->tokens->at(*token_index);591 Token *goto_token = &pc->tokens->at(*token_index);
592 Token *goto_token;592 if (goto_token->id == TokenIdKeywordGoto) {
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;
608 *token_index += 1;593 *token_index += 1;
609 } else if (mandatory) {594 } else if (mandatory) {
610 ast_expect_token(pc, first_token, TokenIdKeywordGoto);595 ast_expect_token(pc, goto_token, TokenIdKeywordGoto);
611 zig_unreachable();596 zig_unreachable();
612 } else {597 } else {
613 return nullptr;598 return nullptr;
...@@ -617,11 +602,30 @@ static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool...@@ -617,11 +602,30 @@ static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool
617602
618 Token *dest_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);603 Token *dest_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
619 node->data.goto_expr.name = token_buf(dest_symbol);604 node->data.goto_expr.name = token_buf(dest_symbol);
620 node->data.goto_expr.is_inline = is_inline;
621 return node;605 return node;
622}606}
607
623/*608/*
624PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl609CompTimeExpression = "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
625KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"629KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
626*/630*/
627static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {631static 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...@@ -706,6 +710,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
706 if (goto_node)710 if (goto_node)
707 return goto_node;711 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
709 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);717 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
710 if (grouped_expr_node) {718 if (grouped_expr_node) {
711 return grouped_expr_node;719 return grouped_expr_node;
...@@ -835,7 +843,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde...@@ -835,7 +843,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde
835}843}
836844
837/*845/*
838SuffixOpExpression = option("inline") PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)846SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
839FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)847FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
840ArrayAccessExpression : token(LBracket) Expression token(RBracket)848ArrayAccessExpression : token(LBracket) Expression token(RBracket)
841SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))849SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
...@@ -843,24 +851,9 @@ FieldAccessExpression : token(Dot) token(Symbol)...@@ -843,24 +851,9 @@ FieldAccessExpression : token(Dot) token(Symbol)
843StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression851StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
844*/852*/
845static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {853static 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
857 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);854 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
858 if (!primary_expr) {855 if (!primary_expr)
859 if (is_comptime) {
860 *token_index -= 1;
861 }
862 return nullptr;856 return nullptr;
863 }
864857
865 while (true) {858 while (true) {
866 Token *first_token = &pc->tokens->at(*token_index);859 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,...@@ -869,7 +862,6 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
869862
870 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);863 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);
871 node->data.fn_call_expr.fn_ref_expr = primary_expr;864 node->data.fn_call_expr.fn_ref_expr = primary_expr;
872 node->data.fn_call_expr.is_comptime = is_comptime;
873 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);865 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
874866
875 primary_expr = node;867 primary_expr = node;
...@@ -2624,6 +2616,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2624,6 +2616,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2624 case NodeTypeGoto:2616 case NodeTypeGoto:
2625 // none2617 // none
2626 break;2618 break;
2619 case NodeTypeCompTime:
2620 visit_field(&node->data.comptime_expr.expr, visit, context);
2621 break;
2627 case NodeTypeBreak:2622 case NodeTypeBreak:
2628 // none2623 // none
2629 break;2624 break;