Commit 6237411716

Andrew Kelley <superjoe30@gmail.com>
2017-05-10 04:54:23
inline function call with builtin function instead...
...of special syntax. partially reverts 41144a8566a6fbd779403f6b69424bb640c94a7f closes #306
1 parent 01f066d
doc/langref.md
@@ -79,7 +79,7 @@ SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbo
 
 SwitchItem = Expression | (Expression "..." Expression)
 
-ForExpression(body) = "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") body option("else" BlockExpression(body))
+ForExpression(body) = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") body option("else" BlockExpression(body))
 
 BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
 
@@ -95,7 +95,7 @@ TryExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|")
 
 TestExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
 
-WhileExpression(body) = "while" "(" Expression ")" option("|" option("*") Symbol "|") option(":" "(" Expression ")") body option("else" option("|" Symbol "|") BlockExpression(body))
+WhileExpression(body) = option("inline") "while" "(" Expression ")" option("|" option("*") Symbol "|") option(":" "(" Expression ")") body option("else" option("|" Symbol "|") BlockExpression(body))
 
 BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
 
@@ -125,9 +125,7 @@ MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
 
 PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
 
-SuffixOpExpression = InlineExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
-
-InlineExpression = option("inline") PrimaryExpression
+SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
 
 FieldAccessExpression = "." Symbol
 
@@ -161,7 +159,6 @@ ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" ma
 ## Operator Precedence
 
 ```
-inline x
 x() x[] x.y
 !x -x -%x ~x *x &x ?x %x %%x ??x
 x{}
src/all_types.hpp
@@ -175,7 +175,6 @@ struct ConstErrValue {
 struct ConstBoundFnValue {
     FnTableEntry *fn;
     IrInstruction *first_arg;
-    bool is_inline;
 };
 
 struct ConstArgTuple {
@@ -209,7 +208,6 @@ enum RuntimeHintPtr {
 
 struct ConstFn {
     FnTableEntry *fn_entry;
-    bool is_inline;
 };
 
 struct ConstExprValue {
@@ -379,7 +377,6 @@ enum NodeType {
     NodeTypeVarLiteral,
     NodeTypeTryExpr,
     NodeTypeTestExpr,
-    NodeTypeInlineExpr,
 };
 
 struct AstNodeRoot {
@@ -796,10 +793,6 @@ struct AstNodeErrorType {
 struct AstNodeVarLiteral {
 };
 
-struct AstNodeInlineExpr {
-    AstNode *body;
-};
-
 struct AstNode {
     enum NodeType type;
     size_t line;
@@ -857,7 +850,6 @@ struct AstNode {
         AstNodeArrayType array_type;
         AstNodeErrorType error_type;
         AstNodeVarLiteral var_literal;
-        AstNodeInlineExpr inline_expr;
     } data;
 };
 
@@ -1214,6 +1206,7 @@ enum BuiltinFnId {
     BuiltinFnIdEnumTagName,
     BuiltinFnIdFieldParentPtr,
     BuiltinFnIdOffsetOf,
+    BuiltinFnIdInlineCall,
 };
 
 struct BuiltinFnEntry {
@@ -1791,7 +1784,6 @@ enum IrInstructionId {
     IrInstructionIdDeclRef,
     IrInstructionIdPanic,
     IrInstructionIdEnumTagName,
-    IrInstructionIdSetFnRefInline,
     IrInstructionIdFieldParentPtr,
     IrInstructionIdOffsetOf,
 };
@@ -2532,12 +2524,6 @@ struct IrInstructionEnumTagName {
     IrInstruction *target;
 };
 
-struct IrInstructionSetFnRefInline {
-    IrInstruction base;
-
-    IrInstruction *fn_ref;
-};
-
 struct IrInstructionFieldParentPtr {
     IrInstruction base;
 
src/analyze.cpp
@@ -2195,7 +2195,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
         case NodeTypeVarLiteral:
         case NodeTypeTryExpr:
         case NodeTypeTestExpr:
-        case NodeTypeInlineExpr:
             zig_unreachable();
     }
 }
@@ -3304,8 +3303,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
             // TODO better hashing algorithm
             return 31643936;
         case TypeTableEntryIdFn:
-            return hash_ptr(const_val->data.x_fn.fn_entry) +
-                (const_val->data.x_fn.is_inline ? 4133894920 : 3983484790);
+            return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);
         case TypeTableEntryIdNamespace:
             return hash_ptr(const_val->data.x_import);
         case TypeTableEntryIdBlock:
@@ -3756,8 +3754,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
         case TypeTableEntryIdPureError:
             return a->data.x_pure_err == b->data.x_pure_err;
         case TypeTableEntryIdFn:
-            return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry &&
-                a->data.x_fn.is_inline == b->data.x_fn.is_inline;
+            return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry;
         case TypeTableEntryIdBool:
             return a->data.x_bool == b->data.x_bool;
         case TypeTableEntryIdInt:
@@ -3997,8 +3994,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
         case TypeTableEntryIdFn:
             {
                 FnTableEntry *fn_entry = const_val->data.x_fn.fn_entry;
-                const char *inline_str = const_val->data.x_fn.is_inline ? "inline " : "";
-                buf_appendf(buf, "%s%s", inline_str, buf_ptr(&fn_entry->symbol_name));
+                buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name));
                 return;
             }
         case TypeTableEntryIdBlock:
@@ -4080,8 +4076,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
         case TypeTableEntryIdBoundFn:
             {
                 FnTableEntry *fn_entry = const_val->data.x_bound_fn.fn;
-                const char *inline_str = const_val->data.x_bound_fn.is_inline ? "inline " : "";
-                buf_appendf(buf, "(%sbound fn %s)", inline_str, buf_ptr(&fn_entry->symbol_name));
+                buf_appendf(buf, "(bound fn %s)", buf_ptr(&fn_entry->symbol_name));
                 return;
             }
         case TypeTableEntryIdStruct:
src/ast_render.cpp
@@ -236,8 +236,6 @@ static const char *node_type_str(NodeType node_type) {
             return "TryExpr";
         case NodeTypeTestExpr:
             return "TestExpr";
-        case NodeTypeInlineExpr:
-            return "InlineExpr";
     }
     zig_unreachable();
 }
@@ -927,12 +925,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
                 render_node_ungrouped(ar, node->data.unwrap_err_expr.op2);
                 break;
             }
-        case NodeTypeInlineExpr:
-            {
-                fprintf(ar->f, "inline ");
-                render_node_grouped(ar, node->data.inline_expr.body);
-                break;
-            }
         case NodeTypeFnDecl:
         case NodeTypeParamDecl:
         case NodeTypeErrorValueDecl:
src/codegen.cpp
@@ -3017,7 +3017,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
         case IrInstructionIdSetGlobalLinkage:
         case IrInstructionIdDeclRef:
         case IrInstructionIdSwitchVar:
-        case IrInstructionIdSetFnRefInline:
         case IrInstructionIdOffsetOf:
             zig_unreachable();
         case IrInstructionIdReturn:
@@ -3596,6 +3595,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const
 }
 
 static void delete_unused_builtin_fns(CodeGen *g) {
+    // TODO get rid of this function
     auto it = g->builtin_fn_table.entry_iterator();
     for (;;) {
         auto *entry = it.next();
@@ -4330,6 +4330,7 @@ static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char
 
 static void define_builtin_fns(CodeGen *g) {
     {
+        // TODO make lazy and get rid of delete_unused_builtin_fns
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);
         builtin_fn->ref_count = 1;
 
@@ -4340,6 +4341,7 @@ static void define_builtin_fns(CodeGen *g) {
         g->trap_fn_val = builtin_fn->fn_val;
     }
     {
+        // TODO make lazy and get rid of delete_unused_builtin_fns
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdReturnAddress,
                 "returnAddress", 0);
         TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
@@ -4352,6 +4354,7 @@ static void define_builtin_fns(CodeGen *g) {
         g->return_address_fn_val = builtin_fn->fn_val;
     }
     {
+        // TODO make lazy and get rid of delete_unused_builtin_fns
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdFrameAddress,
                 "frameAddress", 0);
         TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
@@ -4364,6 +4367,7 @@ static void define_builtin_fns(CodeGen *g) {
         g->frame_address_fn_val = builtin_fn->fn_val;
     }
     {
+        // TODO make lazy and get rid of delete_unused_builtin_fns
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
         builtin_fn->ref_count = 1;
 
@@ -4382,6 +4386,7 @@ static void define_builtin_fns(CodeGen *g) {
         g->memcpy_fn_val = builtin_fn->fn_val;
     }
     {
+        // TODO make lazy and get rid of delete_unused_builtin_fns
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
         builtin_fn->ref_count = 1;
 
@@ -4443,6 +4448,7 @@ static void define_builtin_fns(CodeGen *g) {
     create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);
     create_builtin_fn(g, BuiltinFnIdRem, "rem", 2);
     create_builtin_fn(g, BuiltinFnIdMod, "mod", 2);
+    create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
 }
 
 static const char *bool_to_str(bool b) {
src/ir.cpp
@@ -553,10 +553,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumTagName *) {
     return IrInstructionIdEnumTagName;
 }
 
-static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnRefInline *) {
-    return IrInstructionIdSetFnRefInline;
-}
-
 static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) {
     return IrInstructionIdFieldParentPtr;
 }
@@ -2142,18 +2138,6 @@ static IrInstruction *ir_build_enum_tag_name(IrBuilder *irb, Scope *scope, AstNo
     return &instruction->base;
 }
 
-static IrInstruction *ir_build_set_fn_ref_inline(IrBuilder *irb, Scope *scope, AstNode *source_node,
-        IrInstruction *fn_ref)
-{
-    IrInstructionSetFnRefInline *instruction = ir_build_instruction<IrInstructionSetFnRefInline>(
-            irb, scope, source_node);
-    instruction->fn_ref = fn_ref;
-
-    ir_ref_instruction(fn_ref, irb->current_basic_block);
-
-    return &instruction->base;
-}
-
 static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
         IrInstruction *type_value, IrInstruction *field_name, IrInstruction *field_ptr, TypeStructField *field)
 {
@@ -2838,13 +2822,6 @@ static IrInstruction *ir_instruction_enumtagname_get_dep(IrInstructionEnumTagNam
     }
 }
 
-static IrInstruction *ir_instruction_setfnrefinline_get_dep(IrInstructionSetFnRefInline *instruction, size_t index) {
-    switch (index) {
-        case 0: return instruction->fn_ref;
-        default: return nullptr;
-    }
-}
-
 static IrInstruction *ir_instruction_fieldparentptr_get_dep(IrInstructionFieldParentPtr *instruction, size_t index) {
     switch (index) {
         case 0: return instruction->type_value;
@@ -3048,8 +3025,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
             return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);
         case IrInstructionIdEnumTagName:
             return ir_instruction_enumtagname_get_dep((IrInstructionEnumTagName *) instruction, index);
-        case IrInstructionIdSetFnRefInline:
-            return ir_instruction_setfnrefinline_get_dep((IrInstructionSetFnRefInline *) instruction, index);
         case IrInstructionIdFieldParentPtr:
             return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index);
         case IrInstructionIdOffsetOf:
@@ -4376,6 +4351,30 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
 
                 return ir_build_offset_of(irb, scope, node, arg0_value, arg1_value);
             }
+        case BuiltinFnIdInlineCall:
+            {
+                if (node->data.fn_call_expr.params.length == 0) {
+                    add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));
+                    return irb->codegen->invalid_instruction;
+                }
+
+                AstNode *fn_ref_node = node->data.fn_call_expr.params.at(0);
+                IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
+                if (fn_ref == irb->codegen->invalid_instruction)
+                    return fn_ref;
+
+                size_t arg_count = node->data.fn_call_expr.params.length - 1;
+
+                IrInstruction **args = allocate<IrInstruction*>(arg_count);
+                for (size_t i = 0; i < arg_count; i += 1) {
+                    AstNode *arg_node = node->data.fn_call_expr.params.at(i + 1);
+                    args[i] = ir_gen_node(irb, arg_node, scope);
+                    if (args[i] == irb->codegen->invalid_instruction)
+                        return args[i];
+                }
+
+                return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, true);
+            }
     }
     zig_unreachable();
 }
@@ -5800,19 +5799,6 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
     return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type);
 }
 
-static IrInstruction *ir_gen_inline_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
-    assert(node->type == NodeTypeInlineExpr);
-
-    AstNode *body_node = node->data.inline_expr.body;
-
-    IrInstruction *fn_ptr = ir_gen_node(irb, body_node, parent_scope);
-    if (fn_ptr == irb->codegen->invalid_instruction)
-        return irb->codegen->invalid_instruction;
-
-    return ir_build_set_fn_ref_inline(irb, parent_scope, node, fn_ptr);
-}
-
-
 static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
         LVal lval)
 {
@@ -5903,8 +5889,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
             return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
         case NodeTypeFnProto:
             return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
-        case NodeTypeInlineExpr:
-            return ir_lval_wrap(irb, scope, ir_gen_inline_expr(irb, scope, node), lval);
         case NodeTypeFnDef:
             zig_panic("TODO IR gen NodeTypeFnDef");
         case NodeTypeFnDecl:
@@ -6809,7 +6793,7 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
     return const_val->data.x_type;
 }
 
-static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value, bool *is_inline) {
+static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
     if (fn_value == ira->codegen->invalid_instruction)
         return nullptr;
 
@@ -6826,7 +6810,6 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value, bool
     if (!const_val)
         return nullptr;
 
-    *is_inline = const_val->data.x_fn.is_inline;
     return const_val->data.x_fn.fn_entry;
 }
 
@@ -9179,17 +9162,15 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
             ir_link_new_instruction(cast_instruction, &call_instruction->base);
             return ir_finish_anal(ira, cast_instruction->value.type);
         } else if (fn_ref->value.type->id == TypeTableEntryIdFn) {
-            bool is_inline;
-            FnTableEntry *fn_table_entry = ir_resolve_fn(ira, fn_ref, &is_inline);
+            FnTableEntry *fn_table_entry = ir_resolve_fn(ira, fn_ref);
             return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
-                fn_ref, nullptr, is_comptime, is_inline);
+                fn_ref, nullptr, is_comptime, call_instruction->is_inline);
         } else if (fn_ref->value.type->id == TypeTableEntryIdBoundFn) {
             assert(fn_ref->value.special == ConstValSpecialStatic);
             FnTableEntry *fn_table_entry = fn_ref->value.data.x_bound_fn.fn;
             IrInstruction *first_arg_ptr = fn_ref->value.data.x_bound_fn.first_arg;
-            bool is_inline = fn_ref->value.data.x_bound_fn.is_inline;
             return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
-                nullptr, first_arg_ptr, is_comptime, is_inline);
+                nullptr, first_arg_ptr, is_comptime, call_instruction->is_inline);
         } else {
             ir_add_error_node(ira, fn_ref->source_node,
                 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value.type->name)));
@@ -11736,38 +11717,6 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn
     return result->value.type;
 }
 
-static TypeTableEntry *ir_analyze_instruction_set_fn_ref_inline(IrAnalyze *ira,
-        IrInstructionSetFnRefInline *instruction)
-{
-    IrInstruction *fn_ref = instruction->fn_ref->other;
-    if (type_is_invalid(fn_ref->value.type))
-        return ira->codegen->builtin_types.entry_invalid;
-
-    if (fn_ref->value.type->id == TypeTableEntryIdFn) {
-        ConstExprValue *fn_ref_val = ir_resolve_const(ira, fn_ref, UndefBad);
-        if (!fn_ref_val)
-            return ira->codegen->builtin_types.entry_invalid;
-
-        ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
-        *out_val = *fn_ref_val;
-        out_val->data.x_fn.is_inline = true;
-        return out_val->type;
-    } else if (fn_ref->value.type->id == TypeTableEntryIdBoundFn) {
-        ConstExprValue *fn_ref_val = ir_resolve_const(ira, fn_ref, UndefBad);
-        if (!fn_ref_val)
-            return ira->codegen->builtin_types.entry_invalid;
-
-        ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
-        *out_val = *fn_ref_val;
-        out_val->data.x_bound_fn.is_inline = true;
-        return out_val->type;
-    } else {
-        ir_add_error(ira, &instruction->base,
-                buf_sprintf("expected function type, found '%s'", buf_ptr(&fn_ref->value.type->name)));
-        return ira->codegen->builtin_types.entry_invalid;
-    }
-}
-
 static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
         IrInstructionFieldParentPtr *instruction)
 {
@@ -13403,8 +13352,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
             return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction);
         case IrInstructionIdEnumTagName:
             return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionEnumTagName *)instruction);
-        case IrInstructionIdSetFnRefInline:
-            return ir_analyze_instruction_set_fn_ref_inline(ira, (IrInstructionSetFnRefInline *)instruction);
         case IrInstructionIdFieldParentPtr:
             return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction);
         case IrInstructionIdOffsetOf:
@@ -13585,7 +13532,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
         case IrInstructionIdErrName:
         case IrInstructionIdTypeName:
         case IrInstructionIdEnumTagName:
-        case IrInstructionIdSetFnRefInline:
         case IrInstructionIdFieldParentPtr:
         case IrInstructionIdOffsetOf:
             return false;
src/ir_print.cpp
@@ -866,11 +866,6 @@ static void ir_print_panic(IrPrint *irp, IrInstructionPanic *instruction) {
     fprintf(irp->f, ")");
 }
 
-static void ir_print_set_fn_ref_inline(IrPrint *irp, IrInstructionSetFnRefInline *instruction) {
-    fprintf(irp->f, "inline ");
-    ir_print_other_instruction(irp, instruction->fn_ref);
-}
-
 static void ir_print_field_parent_ptr(IrPrint *irp, IrInstructionFieldParentPtr *instruction) {
     fprintf(irp->f, "@fieldParentPtr(");
     ir_print_other_instruction(irp, instruction->type_value);
@@ -1167,9 +1162,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
         case IrInstructionIdPanic:
             ir_print_panic(irp, (IrInstructionPanic *)instruction);
             break;
-        case IrInstructionIdSetFnRefInline:
-            ir_print_set_fn_ref_inline(irp, (IrInstructionSetFnRefInline *)instruction);
-            break;
         case IrInstructionIdFieldParentPtr:
             ir_print_field_parent_ptr(irp, (IrInstructionFieldParentPtr *)instruction);
             break;
src/parser.cpp
@@ -850,32 +850,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde
 }
 
 /*
-InlineExpression = option("inline") PrimaryExpression
-*/
-static AstNode *ast_parse_inline_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
-    Token *token = &pc->tokens->at(*token_index);
-
-    if (token->id == TokenIdKeywordInline) {
-        *token_index += 1;
-        AstNode *primary_expr_node = ast_parse_primary_expr(pc, token_index, true);
-        if (primary_expr_node->type == NodeTypeWhileExpr) {
-            primary_expr_node->data.while_expr.is_inline = true;
-            return primary_expr_node;
-        } else if (primary_expr_node->type == NodeTypeForExpr) {
-            primary_expr_node->data.for_expr.is_inline = true;
-            return primary_expr_node;
-        } else {
-            AstNode *node = ast_create_node(pc, NodeTypeInlineExpr, token);
-            node->data.inline_expr.body = primary_expr_node;
-            return node;
-        }
-    } else {
-        return ast_parse_primary_expr(pc, token_index, mandatory);
-    }
-}
-
-/*
-SuffixOpExpression = InlineExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
+SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
 FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
 ArrayAccessExpression : token(LBracket) Expression token(RBracket)
 SliceExpression = "[" Expression "..." option(Expression) "]"
@@ -883,8 +858,8 @@ FieldAccessExpression : token(Dot) token(Symbol)
 StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
 */
 static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
-    AstNode *inline_expr = ast_parse_inline_expr(pc, token_index, mandatory);
-    if (!inline_expr)
+    AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
+    if (!primary_expr)
         return nullptr;
 
     while (true) {
@@ -893,10 +868,10 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
             *token_index += 1;
 
             AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);
-            node->data.fn_call_expr.fn_ref_expr = inline_expr;
+            node->data.fn_call_expr.fn_ref_expr = primary_expr;
             ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
 
-            inline_expr = node;
+            primary_expr = node;
         } else if (first_token->id == TokenIdLBracket) {
             *token_index += 1;
 
@@ -908,21 +883,21 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
                 *token_index += 1;
 
                 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, first_token);
-                node->data.slice_expr.array_ref_expr = inline_expr;
+                node->data.slice_expr.array_ref_expr = primary_expr;
                 node->data.slice_expr.start = expr_node;
                 node->data.slice_expr.end = ast_parse_expression(pc, token_index, false);
 
                 ast_eat_token(pc, token_index, TokenIdRBracket);
 
-                inline_expr = node;
+                primary_expr = node;
             } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {
                 *token_index += 1;
 
                 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, first_token);
-                node->data.array_access_expr.array_ref_expr = inline_expr;
+                node->data.array_access_expr.array_ref_expr = primary_expr;
                 node->data.array_access_expr.subscript = expr_node;
 
-                inline_expr = node;
+                primary_expr = node;
             } else {
                 ast_invalid_token_error(pc, first_token);
             }
@@ -932,12 +907,12 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
             Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
 
             AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
-            node->data.field_access_expr.struct_expr = inline_expr;
+            node->data.field_access_expr.struct_expr = primary_expr;
             node->data.field_access_expr.field_name = token_buf(name_token);
 
-            inline_expr = node;
+            primary_expr = node;
         } else {
-            return inline_expr;
+            return primary_expr;
         }
     }
 }
@@ -2733,7 +2708,5 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
         case NodeTypeVarLiteral:
             // none
             break;
-        case NodeTypeInlineExpr:
-            visit_field(&node->data.inline_expr.body, visit, context);
     }
 }
test/cases/fn.zig
@@ -90,7 +90,7 @@ fn fn4() -> u32 {8}
 
 
 test "inline function call" {
-    assert((inline add(3, 9)) == 12);
+    assert(@inlineCall(add, 3, 9) == 12);
 }
 
 fn add(a: i32, b: i32) -> i32 { a + b }