analyze: BlockContext has concept of module scope

This commit is contained in:
Andrew Kelley 2015-12-14 22:01:39 -07:00
parent 3049410260
commit 52e19b4a9b
5 changed files with 47 additions and 36 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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) {

View File

@ -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();