Commit 5af4ef88ac

Josh Wolfe <thejoshwolfe@gmail.com>
2015-12-03 18:56:17
local variables work
1 parent 708cae3
example/expressions/expressions.zig
@@ -7,8 +7,8 @@ extern {
 export fn _start() -> unreachable {
     let a : i32 = 1;
     let b = 2;
-    let c : i32;
-    // let d; // compile error
+    // let c : i32; // not yet support for const variables
+    // let d; // parse error
     puts("Hello, world!");
     exit(a + b);
 }
src/analyze.cpp
@@ -115,12 +115,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
     for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
         AstNode *child = node->data.fn_proto.params.at(i);
         assert(child->type == NodeTypeParamDecl);
-
-        Buf *param_name = &child->data.param_decl.name;
-        SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1);
-        symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type);
-        symbol_entry->param_index = i;
-        fn_table_entry->symbol_table.put(param_name, symbol_entry);
+        resolve_type(g, child->data.param_decl.type);
     }
 
     resolve_type(g, node->data.fn_proto.return_type);
@@ -171,7 +166,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
                 fn_table_entry->is_extern = true;
                 fn_table_entry->calling_convention = LLVMCCallConv;
                 fn_table_entry->import_entry = import;
-                fn_table_entry->symbol_table.init(8);
                 fn_table_entry->label_table.init(8);
 
                 resolve_function_proto(g, fn_proto, fn_table_entry);
@@ -222,7 +216,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
                     fn_table_entry->fn_def_node = node;
                     fn_table_entry->internal_linkage = is_internal;
                     fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;
-                    fn_table_entry->symbol_table.init(8);
                     fn_table_entry->label_table.init(8);
 
                     g->fn_protos.append(fn_table_entry);
@@ -363,7 +356,7 @@ static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
     return context;
 }
 
-static LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {
+LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {
     while (true) {
         auto entry = context->variable_table.maybe_get(name);
         if (entry != nullptr)
@@ -432,6 +425,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
                 TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ?
                     analyze_expression(g, import, context, explicit_type, variable_declaration->expr) : nullptr;
 
+                if (implicit_type == nullptr) {
+                    add_node_error(g, node, buf_sprintf("initial values are required for variable declaration."));
+                }
+
                 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
                 assert(type != nullptr); // should have been caught by the parser
 
@@ -736,6 +733,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
 
                 node->codegen_node = allocate<CodeGenNode>(1);
                 node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type;
+                node->codegen_node->data.fn_def_node.block_context = context;
             }
             break;
 
src/analyze.hpp
@@ -13,9 +13,12 @@ struct AstNode;
 struct Buf;
 
 struct TypeTableEntry;
+struct LocalVariableTableEntry;
+struct BlockContext;
 
 void semantic_analyze(CodeGen *g);
 void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
 TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
+LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
 
 #endif
src/codegen.cpp
@@ -103,17 +103,6 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
     return global_value;
 }
 
-static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) {
-    assert(g->cur_fn->proto_node->type == NodeTypeFnProto);
-
-    SymbolTableEntry *symbol_entry = g->cur_fn->symbol_table.get(name);
-
-    CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;
-    assert(codegen_node);
-    FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
-    return codegen_fn_def->params[symbol_entry->param_index];
-}
-
 static TypeTableEntry *get_expr_type(AstNode *node) {
     return node->codegen_node->expr_node.type_entry;
 }
@@ -481,7 +470,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
         case NodeTypeReturnExpr:
             return gen_return_expr(g, node);
         case NodeTypeVariableDeclaration:
-            zig_panic("TODO: variable declaration code gen");
+            {
+                LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.variable_declaration.symbol);
+                assert(node->data.variable_declaration.expr);
+                variable->value_ref = gen_expr(g, node->data.variable_declaration.expr);
+                return nullptr;
+            }
         case NodeTypeCastExpr:
             return gen_cast_expr(g, node);
         case NodeTypePrefixOpExpr:
@@ -516,8 +510,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
             }
         case NodeTypeSymbol:
             {
-                Buf *name = &node->data.symbol;
-                return get_variable_value(g, name);
+                LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.symbol);
+                return variable->value_ref;
             }
         case NodeTypeBlock:
             return gen_block(g, node, nullptr);
@@ -648,8 +642,17 @@ static void do_code_gen(CodeGen *g) {
 
         FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
         assert(codegen_fn_def);
-        codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn));
-        LLVMGetParams(fn, codegen_fn_def->params);
+        int param_count = fn_proto->params.length;
+        assert(param_count == (int)LLVMCountParams(fn));
+        LLVMValueRef *params = allocate<LLVMValueRef>(param_count);
+        LLVMGetParams(fn, params);
+
+        for (int i = 0; i < param_count; i += 1) {
+            AstNode *param_decl = fn_proto->params.at(i);
+            assert(param_decl->type == NodeTypeParamDecl);
+            LocalVariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(&param_decl->data.param_decl.name);
+            parameter_variable->value_ref = params[i];
+        }
 
         build_label_blocks(g, fn_def_node->data.fn_def.body);
 
src/semantic_info.hpp
@@ -38,11 +38,6 @@ struct ImportTableEntry {
     HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
 };
 
-struct SymbolTableEntry {
-    TypeTableEntry *type_entry;
-    int param_index; // only valid in the case of parameters
-};
-
 struct LabelTableEntry {
     AstNode *label_node;
     LLVMBasicBlockRef basic_block;
@@ -58,7 +53,6 @@ struct FnTableEntry {
     ImportTableEntry *import_entry;
 
     // reminder: hash tables must be initialized before use
-    HashMap<Buf *, SymbolTableEntry *, buf_hash, buf_eql_buf> symbol_table;
     HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
 };
 
@@ -120,6 +114,7 @@ struct CodeGen {
 struct LocalVariableTableEntry {
     Buf name;
     TypeTableEntry *type;
+    LLVMValueRef value_ref;
 };
 
 struct BlockContext {
@@ -139,8 +134,8 @@ struct FnProtoNode {
 
 struct FnDefNode {
     TypeTableEntry *implicit_return_type;
+    BlockContext *block_context;
     bool skip;
-    LLVMValueRef *params;
 };
 
 struct ExprNode {