mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
analyze: BlockContext has concept of module scope
This commit is contained in:
parent
3049410260
commit
52e19b4a9b
@ -32,7 +32,9 @@ zig | C equivalent | Description
|
||||
```
|
||||
Root : many(TopLevelDecl) token(EOF)
|
||||
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
|
||||
|
||||
VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
|
||||
|
||||
StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
|
||||
|
||||
|
@ -445,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
||||
break;
|
||||
}
|
||||
case NodeTypeUse:
|
||||
case NodeTypeVariableDeclaration:
|
||||
// nothing to do here
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeType:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeReturnExpr:
|
||||
case NodeTypeVariableDeclaration:
|
||||
case NodeTypeRoot:
|
||||
case NodeTypeBlock:
|
||||
case NodeTypeBinOpExpr:
|
||||
@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
case NodeTypeFnDef:
|
||||
case NodeTypeRootExportDecl:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeVariableDeclaration:
|
||||
// nothing to do
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
case NodeTypeType:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeReturnExpr:
|
||||
case NodeTypeVariableDeclaration:
|
||||
case NodeTypeRoot:
|
||||
case NodeTypeBlock:
|
||||
case NodeTypeBinOpExpr:
|
||||
@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
}
|
||||
}
|
||||
|
||||
static TypeTableEntry * get_return_type(BlockContext *context) {
|
||||
AstNode *fn_def_node = context->root->node;
|
||||
assert(fn_def_node->type == NodeTypeFnDef);
|
||||
AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
|
||||
static FnTableEntry *get_context_fn_entry(BlockContext *context) {
|
||||
assert(context->fn_entry);
|
||||
return context->fn_entry;
|
||||
}
|
||||
|
||||
static TypeTableEntry *get_return_type(BlockContext *context) {
|
||||
FnTableEntry *fn_entry = get_context_fn_entry(context);
|
||||
AstNode *fn_proto_node = fn_entry->proto_node;
|
||||
assert(fn_proto_node->type == NodeTypeFnProto);
|
||||
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
|
||||
assert(return_type_node->codegen_node);
|
||||
return return_type_node->codegen_node->data.type_node.entry;
|
||||
}
|
||||
|
||||
static FnTableEntry *get_context_fn_entry(BlockContext *context) {
|
||||
AstNode *fn_def_node = context->root->node;
|
||||
assert(fn_def_node->type == NodeTypeFnDef);
|
||||
AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
|
||||
assert(fn_proto_node->type == NodeTypeFnProto);
|
||||
assert(fn_proto_node->codegen_node);
|
||||
assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry);
|
||||
return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
|
||||
}
|
||||
|
||||
static void check_type_compatibility(CodeGen *g, AstNode *node,
|
||||
TypeTableEntry *expected_type, TypeTableEntry *actual_type)
|
||||
{
|
||||
@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node,
|
||||
buf_ptr(&actual_type->name)));
|
||||
}
|
||||
|
||||
static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
||||
BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
||||
BlockContext *context = allocate<BlockContext>(1);
|
||||
context->node = node;
|
||||
context->parent = parent;
|
||||
if (parent != nullptr)
|
||||
context->root = parent->root;
|
||||
else
|
||||
context->root = context;
|
||||
context->variable_table.init(8);
|
||||
|
||||
AstNode *fn_def_node = context->root->node;
|
||||
assert(fn_def_node->type == NodeTypeFnDef);
|
||||
assert(fn_def_node->codegen_node);
|
||||
FnDefNode *fn_def_info = &fn_def_node->codegen_node->data.fn_def_node;
|
||||
fn_def_info->all_block_contexts.append(context);
|
||||
if (parent) {
|
||||
context->fn_entry = parent->fn_entry;
|
||||
} else if (node && node->type == NodeTypeFnDef) {
|
||||
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
|
||||
context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
|
||||
}
|
||||
|
||||
if (context->fn_entry) {
|
||||
context->fn_entry->all_block_contexts.append(context);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeStructDecl:
|
||||
// nothing to do
|
||||
break;
|
||||
case NodeTypeVariableDeclaration:
|
||||
analyze_variable_declaration(g, import, import->block_context, nullptr, node);
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeFnProto:
|
||||
case NodeTypeType:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeReturnExpr:
|
||||
case NodeTypeVariableDeclaration:
|
||||
case NodeTypeRoot:
|
||||
case NodeTypeBlock:
|
||||
case NodeTypeBinOpExpr:
|
||||
|
@ -90,6 +90,7 @@ struct ImportTableEntry {
|
||||
LLVMZigDIFile *di_file;
|
||||
Buf *source_code;
|
||||
ZigList<int> *line_offsets;
|
||||
BlockContext *block_context;
|
||||
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
|
||||
@ -116,6 +117,8 @@ struct FnTableEntry {
|
||||
unsigned calling_convention;
|
||||
ImportTableEntry *import_entry;
|
||||
ZigList<FnAttrId> fn_attr_list;
|
||||
// Required to be a pre-order traversal of the AST. (parents must come before children)
|
||||
ZigList<BlockContext *> all_block_contexts;
|
||||
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
|
||||
@ -201,9 +204,9 @@ struct LocalVariableTableEntry {
|
||||
};
|
||||
|
||||
struct BlockContext {
|
||||
AstNode *node; // either NodeTypeFnDef or NodeTypeBlock
|
||||
BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef
|
||||
BlockContext *parent; // nullptr when this is the root
|
||||
AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or null for module scope
|
||||
FnTableEntry *fn_entry; // null at the module scope
|
||||
BlockContext *parent; // null when this is the root
|
||||
HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
|
||||
ZigList<AstNode *> cast_expr_alloca_list;
|
||||
LLVMZigDIScope *di_scope;
|
||||
@ -221,8 +224,6 @@ struct FnDefNode {
|
||||
TypeTableEntry *implicit_return_type;
|
||||
BlockContext *block_context;
|
||||
bool skip;
|
||||
// Required to be a pre-order traversal of the AST. (parents must come before children)
|
||||
ZigList<BlockContext *> all_block_contexts;
|
||||
};
|
||||
|
||||
struct ExprNode {
|
||||
@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
|
||||
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||
LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
|
||||
BlockContext *new_block_context(AstNode *node, BlockContext *parent);
|
||||
|
||||
#endif
|
||||
|
@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
// Set up debug info for blocks and variables and
|
||||
// allocate all local variables
|
||||
for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) {
|
||||
BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i);
|
||||
for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
|
||||
BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
|
||||
|
||||
if (block_context->parent) {
|
||||
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
|
||||
@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
|
||||
import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
||||
g->import_table.put(full_path, import_entry);
|
||||
|
||||
import_entry->block_context = new_block_context(nullptr, nullptr);
|
||||
import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
|
||||
|
||||
|
||||
assert(import_entry->root->type == NodeTypeRoot);
|
||||
for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
|
||||
|
@ -2266,7 +2266,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
|
||||
}
|
||||
|
||||
/*
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
|
||||
*/
|
||||
static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
|
||||
for (;;) {
|
||||
@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
|
||||
}
|
||||
pc->directive_list = nullptr;
|
||||
|
||||
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false);
|
||||
if (var_decl_node) {
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
top_level_decls->append(var_decl_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
zig_unreachable();
|
||||
|
Loading…
Reference in New Issue
Block a user