mirror of
https://github.com/ziglang/zig.git
synced 2026-01-07 14:03:26 +00:00
inline is a keyword instead of a directive
This commit is contained in:
parent
122b7b9966
commit
06f6acb4b1
@ -35,7 +35,7 @@ Directive = "#" "Symbol" "(" "String" ")"
|
||||
|
||||
VisibleMod = "pub" | "export"
|
||||
|
||||
FnDef = FnProto Block
|
||||
FnDef = option("inline") FnProto Block
|
||||
|
||||
ParamDeclList = "(" list(ParamDecl, ",") ")"
|
||||
|
||||
|
||||
@ -174,13 +174,14 @@ enum VisibMod {
|
||||
};
|
||||
|
||||
struct AstNodeFnProto {
|
||||
ZigList<AstNode *> *directives;
|
||||
ZigList<AstNode *> *directives; // can be null if no directives
|
||||
VisibMod visib_mod;
|
||||
Buf name;
|
||||
ZigList<AstNode *> params;
|
||||
AstNode *return_type;
|
||||
bool is_var_args;
|
||||
bool is_extern;
|
||||
bool is_inline;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
|
||||
|
||||
@ -714,29 +714,32 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_naked = false;
|
||||
for (int i = 0; i < fn_proto->directives->length; i += 1) {
|
||||
AstNode *directive_node = fn_proto->directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
fn_table_entry->is_inline = fn_proto->is_inline;
|
||||
|
||||
if (buf_eql_str(name, "attribute")) {
|
||||
Buf *attr_name = &directive_node->data.directive.param;
|
||||
if (fn_table_entry->fn_def_node) {
|
||||
if (buf_eql_str(attr_name, "naked")) {
|
||||
is_naked = true;
|
||||
} else if (buf_eql_str(attr_name, "inline")) {
|
||||
fn_table_entry->is_inline = true;
|
||||
bool is_naked = false;
|
||||
|
||||
if (fn_proto->directives) {
|
||||
for (int i = 0; i < fn_proto->directives->length; i += 1) {
|
||||
AstNode *directive_node = fn_proto->directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
|
||||
if (buf_eql_str(name, "attribute")) {
|
||||
Buf *attr_name = &directive_node->data.directive.param;
|
||||
if (fn_table_entry->fn_def_node) {
|
||||
if (buf_eql_str(attr_name, "naked")) {
|
||||
is_naked = true;
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -5174,11 +5177,13 @@ void semantic_analyze(CodeGen *g) {
|
||||
for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
|
||||
AstNode *child = import->root->data.root.top_level_decls.at(i);
|
||||
if (child->type == NodeTypeImport) {
|
||||
for (int i = 0; i < child->data.import.directives->length; i += 1) {
|
||||
AstNode *directive_node = child->data.import.directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
if (child->data.import.directives) {
|
||||
for (int i = 0; i < child->data.import.directives->length; i += 1) {
|
||||
AstNode *directive_node = child->data.import.directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
|
||||
ImportTableEntry *target_import = child->data.import.import;
|
||||
|
||||
@ -77,6 +77,10 @@ static const char *extern_string(bool is_extern) {
|
||||
return is_extern ? "extern " : "";
|
||||
}
|
||||
|
||||
static const char *inline_string(bool is_inline) {
|
||||
return is_inline ? "inline " : "";
|
||||
}
|
||||
|
||||
static const char *const_or_var_string(bool is_const) {
|
||||
return is_const ? "const" : "var";
|
||||
}
|
||||
@ -553,7 +557,8 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
const char *fn_name = buf_ptr(&node->data.fn_proto.name);
|
||||
const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
|
||||
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
|
||||
fprintf(ar->f, "%s%sfn %s(", pub_str, extern_str, fn_name);
|
||||
const char *inline_str = inline_string(node->data.fn_proto.is_inline);
|
||||
fprintf(ar->f, "%s%s%sfn %s(", pub_str, inline_str, extern_str, fn_name);
|
||||
int arg_count = node->data.fn_proto.params.length;
|
||||
bool is_var_args = node->data.fn_proto.is_var_args;
|
||||
for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
|
||||
@ -583,8 +588,10 @@ static void render_node(AstRender *ar, AstNode *node) {
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnDef:
|
||||
for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
|
||||
render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
|
||||
if (node->data.fn_def.fn_proto->data.fn_proto.directives) {
|
||||
for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
|
||||
render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
|
||||
}
|
||||
}
|
||||
render_node(ar, node->data.fn_def.fn_proto);
|
||||
fprintf(ar->f, " ");
|
||||
|
||||
@ -3338,20 +3338,23 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("root export declaration only valid in root source file"));
|
||||
} else {
|
||||
for (int i = 0; i < top_level_decl->data.root_export_decl.directives->length; i += 1) {
|
||||
AstNode *directive_node = top_level_decl->data.root_export_decl.directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
Buf *param = &directive_node->data.directive.param;
|
||||
if (buf_eql_str(name, "version")) {
|
||||
set_root_export_version(g, param, directive_node);
|
||||
} else if (buf_eql_str(name, "link")) {
|
||||
g->link_table.put(param, true);
|
||||
if (buf_eql_str(param, "c")) {
|
||||
g->link_libc = true;
|
||||
ZigList<AstNode *> *directives = top_level_decl->data.root_export_decl.directives;
|
||||
if (directives) {
|
||||
for (int i = 0; i < directives->length; i += 1) {
|
||||
AstNode *directive_node = directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
Buf *param = &directive_node->data.directive.param;
|
||||
if (buf_eql_str(name, "version")) {
|
||||
set_root_export_version(g, param, directive_node);
|
||||
} else if (buf_eql_str(name, "link")) {
|
||||
g->link_table.put(param, true);
|
||||
if (buf_eql_str(param, "c")) {
|
||||
g->link_libc = true;
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -115,10 +115,6 @@ static AstNode *create_field_access_node(Context *c, const char *lhs, const char
|
||||
return node;
|
||||
}
|
||||
|
||||
static ZigList<AstNode *> *create_empty_directives(Context *c) {
|
||||
return allocate<ZigList<AstNode*>>(1);
|
||||
}
|
||||
|
||||
static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char *var_name,
|
||||
AstNode *type_node, AstNode *init_node)
|
||||
{
|
||||
@ -127,7 +123,7 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char
|
||||
node->data.variable_declaration.is_const = is_const;
|
||||
node->data.variable_declaration.visib_mod = c->visib_mod;
|
||||
node->data.variable_declaration.expr = init_node;
|
||||
node->data.variable_declaration.directives = create_empty_directives(c);
|
||||
node->data.variable_declaration.directives = nullptr;
|
||||
node->data.variable_declaration.type = type_node;
|
||||
normalize_parent_ptrs(node);
|
||||
return node;
|
||||
@ -150,7 +146,6 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *
|
||||
assert(type_node);
|
||||
AstNode *node = create_node(c, NodeTypeStructField);
|
||||
buf_init_from_str(&node->data.struct_field.name, name);
|
||||
node->data.struct_field.directives = create_empty_directives(c);
|
||||
node->data.struct_field.visib_mod = VisibModPub;
|
||||
node->data.struct_field.type = type_node;
|
||||
|
||||
@ -197,18 +192,10 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
|
||||
return create_prefix_node(c, PrefixOpNegation, num_lit_node);
|
||||
}
|
||||
|
||||
static AstNode *create_directive_node(Context *c, const char *name, const char *value) {
|
||||
AstNode *node = create_node(c, NodeTypeDirective);
|
||||
buf_init_from_str(&node->data.directive.name, name);
|
||||
buf_init_from_str(&node->data.directive.param, value);
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
|
||||
AstNode *node = create_node(c, NodeTypeTypeDecl);
|
||||
buf_init_from_str(&node->data.type_decl.symbol, name);
|
||||
node->data.type_decl.visib_mod = c->visib_mod;
|
||||
node->data.type_decl.directives = create_empty_directives(c);
|
||||
node->data.type_decl.child_type = child_type_node;
|
||||
|
||||
normalize_parent_ptrs(node);
|
||||
@ -224,8 +211,7 @@ static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {
|
||||
static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) {
|
||||
assert(fn_type->id == TypeTableEntryIdFn);
|
||||
AstNode *node = create_node(c, NodeTypeFnProto);
|
||||
node->data.fn_proto.directives = create_empty_directives(c);
|
||||
node->data.fn_proto.directives->append(create_directive_node(c, "attribute", "inline"));
|
||||
node->data.fn_proto.is_inline = true;
|
||||
node->data.fn_proto.visib_mod = c->visib_mod;
|
||||
buf_init_from_buf(&node->data.fn_proto.name, name);
|
||||
node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
|
||||
@ -642,7 +628,6 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
|
||||
|
||||
node->data.fn_proto.is_extern = fn_type->data.fn.fn_type_id.is_extern;
|
||||
node->data.fn_proto.visib_mod = c->visib_mod;
|
||||
node->data.fn_proto.directives = create_empty_directives(c);
|
||||
node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
|
||||
node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
|
||||
|
||||
@ -826,7 +811,6 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
||||
buf_init_from_buf(&enum_node->data.struct_decl.name, full_type_name);
|
||||
enum_node->data.struct_decl.kind = ContainerKindEnum;
|
||||
enum_node->data.struct_decl.visib_mod = VisibModExport;
|
||||
enum_node->data.struct_decl.directives = create_empty_directives(c);
|
||||
enum_node->data.struct_decl.type_entry = enum_type;
|
||||
|
||||
for (uint32_t i = 0; i < field_count; i += 1) {
|
||||
@ -998,7 +982,6 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
|
||||
buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name);
|
||||
struct_node->data.struct_decl.kind = ContainerKindStruct;
|
||||
struct_node->data.struct_decl.visib_mod = VisibModExport;
|
||||
struct_node->data.struct_decl.directives = create_empty_directives(c);
|
||||
struct_node->data.struct_decl.type_entry = struct_type;
|
||||
|
||||
for (uint32_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
|
||||
|
||||
@ -82,13 +82,6 @@ static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_to
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNode *other_node) {
|
||||
AstNode *node = ast_create_node_no_line_info(pc, type);
|
||||
node->line = other_node->line;
|
||||
node->column = other_node->column;
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
|
||||
buf_init_from_str(&node->data.symbol_expr.symbol, "void");
|
||||
@ -2240,15 +2233,26 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
|
||||
}
|
||||
|
||||
/*
|
||||
FnDef : FnProto Block
|
||||
FnDef = option("inline") FnProto Block
|
||||
*/
|
||||
static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory,
|
||||
ZigList<AstNode*> *directives, VisibMod visib_mod)
|
||||
{
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
bool is_inline;
|
||||
if (first_token->id == TokenIdKeywordInline) {
|
||||
*token_index += 1;
|
||||
is_inline = true;
|
||||
} else {
|
||||
is_inline = false;
|
||||
}
|
||||
|
||||
AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);
|
||||
if (!fn_proto)
|
||||
return nullptr;
|
||||
AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);
|
||||
AstNode *node = ast_create_node(pc, NodeTypeFnDef, first_token);
|
||||
|
||||
fn_proto->data.fn_proto.is_inline = is_inline;
|
||||
|
||||
node->data.fn_def.fn_proto = fn_proto;
|
||||
node->data.fn_def.body = ast_parse_block(pc, token_index, true);
|
||||
@ -2646,8 +2650,10 @@ static void set_field(AstNode **field) {
|
||||
}
|
||||
|
||||
static void set_list_fields(ZigList<AstNode*> *list) {
|
||||
for (int i = 0; i < list->length; i += 1) {
|
||||
set_field(&list->at(i));
|
||||
if (list) {
|
||||
for (int i = 0; i < list->length; i += 1) {
|
||||
set_field(&list->at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2661,9 +2667,7 @@ void normalize_parent_ptrs(AstNode *node) {
|
||||
break;
|
||||
case NodeTypeFnProto:
|
||||
set_field(&node->data.fn_proto.return_type);
|
||||
if (node->data.fn_proto.directives) {
|
||||
set_list_fields(node->data.fn_proto.directives);
|
||||
}
|
||||
set_list_fields(node->data.fn_proto.directives);
|
||||
set_list_fields(&node->data.fn_proto.params);
|
||||
break;
|
||||
case NodeTypeFnDef:
|
||||
@ -2686,9 +2690,7 @@ void normalize_parent_ptrs(AstNode *node) {
|
||||
set_field(&node->data.return_expr.expr);
|
||||
break;
|
||||
case NodeTypeVariableDeclaration:
|
||||
if (node->data.variable_declaration.directives) {
|
||||
set_list_fields(node->data.variable_declaration.directives);
|
||||
}
|
||||
set_list_fields(node->data.variable_declaration.directives);
|
||||
set_field(&node->data.variable_declaration.type);
|
||||
set_field(&node->data.variable_declaration.expr);
|
||||
break;
|
||||
|
||||
@ -101,7 +101,7 @@ const char * zig_keywords[] = {
|
||||
"true", "false", "null", "fn", "return", "var", "const", "extern",
|
||||
"pub", "export", "import", "c_import", "if", "else", "goto", "asm",
|
||||
"volatile", "struct", "enum", "while", "for", "continue", "break",
|
||||
"null", "noalias", "switch", "undefined", "error", "type"
|
||||
"null", "noalias", "switch", "undefined", "error", "type", "inline",
|
||||
};
|
||||
|
||||
bool is_zig_keyword(Buf *buf) {
|
||||
@ -273,6 +273,8 @@ static void end_token(Tokenize *t) {
|
||||
t->cur_tok->id = TokenIdKeywordError;
|
||||
} else if (mem_eql_str(token_mem, token_len, "type")) {
|
||||
t->cur_tok->id = TokenIdKeywordType;
|
||||
} else if (mem_eql_str(token_mem, token_len, "inline")) {
|
||||
t->cur_tok->id = TokenIdKeywordInline;
|
||||
}
|
||||
|
||||
t->cur_tok = nullptr;
|
||||
@ -1087,6 +1089,7 @@ const char * token_name(TokenId id) {
|
||||
case TokenIdKeywordUndefined: return "undefined";
|
||||
case TokenIdKeywordError: return "error";
|
||||
case TokenIdKeywordType: return "type";
|
||||
case TokenIdKeywordInline: return "inline";
|
||||
case TokenIdLParen: return "(";
|
||||
case TokenIdRParen: return ")";
|
||||
case TokenIdComma: return ",";
|
||||
|
||||
@ -41,6 +41,7 @@ enum TokenId {
|
||||
TokenIdKeywordUndefined,
|
||||
TokenIdKeywordError,
|
||||
TokenIdKeywordType,
|
||||
TokenIdKeywordInline,
|
||||
TokenIdLParen,
|
||||
TokenIdRParen,
|
||||
TokenIdComma,
|
||||
|
||||
@ -2114,8 +2114,7 @@ extern void (*fn_ptr)(void);
|
||||
#define foo fn_ptr
|
||||
)SOURCE", 2,
|
||||
"pub extern var fn_ptr: ?extern fn();",
|
||||
R"SOURCE(#attribute("inline")
|
||||
pub fn foo() {
|
||||
R"SOURCE(pub inline fn foo() {
|
||||
(??fn_ptr)()
|
||||
})SOURCE");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user