Commit 52e19b4a9b
Changed files (5)
doc/langref.md
@@ -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)
src/analyze.cpp
@@ -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:
src/analyze.hpp
@@ -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
src/codegen.cpp
@@ -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) {
src/parser.cpp
@@ -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();