mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
local variables work
This commit is contained in:
parent
708cae3786
commit
5af4ef88ac
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(¶m_decl->data.param_decl.name);
|
||||
parameter_variable->value_ref = params[i];
|
||||
}
|
||||
|
||||
build_label_blocks(g, fn_def_node->data.fn_def.body);
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user