aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-03-29 20:49:29 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit6927b6338b9655974db79c429e6ffc73037ab5e0 (patch)
tree269b4a096fcd38432fc709a72b6e872334652403
parentfe9971d379766a4f7d4576495caff9ffaa80cfef (diff)
Fix ssa call, use correct tokenizer in error
-rw-r--r--include/ast.h1
-rw-r--r--include/ssa/ssa.h5
-rw-r--r--src/ast.c104
-rw-r--r--src/compiler.c2
-rw-r--r--src/ssa/ssa.c66
-rw-r--r--src/std/hash_map.c4
6 files changed, 105 insertions, 77 deletions
diff --git a/include/ast.h b/include/ast.h
index 580ca24..d37fcb3 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -148,7 +148,6 @@ struct Binop {
typedef struct {
jmp_buf env;
- Parser *parser;
amal_compiler *compiler;
Scope *scope;
} AstCompilerContext;
diff --git a/include/ssa/ssa.h b/include/ssa/ssa.h
index c374ffb..16ceb25 100644
--- a/include/ssa/ssa.h
+++ b/include/ssa/ssa.h
@@ -38,7 +38,7 @@ typedef struct {
typedef u16 SsaRegister;
typedef u16 SsaIntermediateIndex;
typedef u16 SsaStringIndex;
-typedef u32 SsaFuncIndex;
+typedef usize SsaFuncIndex;
typedef struct {
Buffer/*instruction data*/ instructions;
@@ -63,12 +63,11 @@ CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstructionType binop_type, SsaRegi
CHECK_RESULT int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result);
CHECK_RESULT int ssa_ins_func_end(Ssa *self);
CHECK_RESULT int ssa_ins_push(Ssa *self, SsaRegister reg);
-CHECK_RESULT int ssa_ins_call(Ssa *self, SsaFuncIndex func, SsaRegister *result);
+CHECK_RESULT int ssa_ins_call(Ssa *self, void *func, SsaRegister *result);
typedef struct {
jmp_buf env;
- Parser *parser;
Ssa ssa;
} SsaCompilerContext;
diff --git a/src/ast.c b/src/ast.c
index a2a927c..a9f9be2 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -180,6 +180,16 @@ void scope_resolve(Scope *self, AstCompilerContext *context) {
context->scope = self->parent;
}
+static Parser* scope_get_parser(Scope *scope) {
+ while(scope) {
+ if(scope->parser)
+ return scope->parser;
+ scope = scope->parent;
+ }
+ assert(bool_false && "BUG: At least some scope parent is supposed to have a parser");
+ return NULL;
+}
+
static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) {
Ast *result;
bool exists;
@@ -188,11 +198,13 @@ static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context
assert(self);
exists = hash_map_get(&self->named_objects, name, &result);
if(!exists) {
+ Parser *parser;
if(self->parent)
return scope_get_resolved_variable(self->parent, context, name);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, name.data),
+ parser = scope_get_parser(self);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, name.data),
"Undefined reference to variable \"%.*s\"", name.size, name.data);
throw(AST_ERR);
}
@@ -216,13 +228,13 @@ static void variable_resolve(Variable *self, AstCompilerContext *context, AstRes
resolve_data->type = scope_get_resolved_variable(context->scope, context, self->name)->resolve_data.type;
}
-static LhsExpr* lhsexpr_resolve_rhs(Ast *ast, AstCompilerContext *context, LhsExpr *lhs_expr) {
+static LhsExpr* lhsexpr_resolve_rhs(LhsExpr *self, AstCompilerContext *context) {
LhsExpr *rhs_resolved_type;
- ast_resolve(ast, context);
- if(ast_is_decl(ast))
- rhs_resolved_type = lhs_expr;
+ ast_resolve(self->rhs_expr, context);
+ if(ast_is_decl(self->rhs_expr))
+ rhs_resolved_type = self;
else
- rhs_resolved_type = ast->resolve_data.type;
+ rhs_resolved_type = self->rhs_expr->resolve_data.type;
return rhs_resolved_type;
}
@@ -246,14 +258,14 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) {
if(self->rhs_expr->type == AST_FUNCTION_DECL)
ast->resolve_data.status = AST_RESOLVED;
- rhs_resolve_type = lhsexpr_resolve_rhs(self->rhs_expr, context, self);
+ rhs_resolve_type = lhsexpr_resolve_rhs(self, context);
/* self->rhs_expr can be null here because this is valid: var num: i32; */
- if(ast->resolve_data.type &&
- self->rhs_expr &&
- ast->resolve_data.type != rhs_resolve_type) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, self->type.name.data),
+ if(ast->resolve_data.type && self->rhs_expr && ast->resolve_data.type != rhs_resolve_type) {
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, self->type.name.data),
"Variable type and variable assignment type (right-hand side) do not match");
throw(AST_ERR);
}
@@ -289,17 +301,10 @@ static Scope* lhsexpr_get_scope(LhsExpr *self) {
return NULL;
}
-/* @self has to be resolved before calling this */
+/* @self has to have a resolved type before calling this */
static Parser* get_resolved_type_parser(Ast *self) {
- Scope *scope;
- scope = lhsexpr_get_scope(self->resolve_data.type);
- while(scope) {
- if(scope->parser)
- return scope->parser;
- scope = scope->parent;
- }
- assert(bool_false && "BUG: At least some parent is supposed to have a parser");
- return NULL;
+ assert(self->resolve_data.type);
+ return scope_get_parser(lhsexpr_get_scope(self->resolve_data.type));
}
static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) {
@@ -315,17 +320,20 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) {
func_call = self->value.func_call;
variable_resolve(&func_call->func, context, &self->resolve_data);
if(self->resolve_data.type->rhs_expr->type != AST_FUNCTION_DECL) {
+ Parser *caller_parser;
Parser *callee_parser;
BufferView callee_code_ref;
+
+ caller_parser = scope_get_parser(context->scope);
callee_parser = get_resolved_type_parser(self);
callee_code_ref = self->resolve_data.type->var_name;
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, func_call->func.name.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, func_call->func.name.data),
"\"%.*s\" is not a function. Only functions can be called", func_call->func.name.size, func_call->func.name.data);
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared here");
throw(AST_ERR);
@@ -354,19 +362,21 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) {
static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
Binop *self;
Scope *lhs_scope;
+ Parser *caller_parser;
Parser *callee_parser;
BufferView caller_code_ref;
BufferView callee_code_ref;
assert(ast->type == AST_BINOP);
self = ast->value.binop;
+ caller_parser = scope_get_parser(context->scope);
if(self->lhs->type != AST_VARIABLE) {
/* TODO: Allow field access for numbers and string as well */
BufferView code_ref;
code_ref = ast_get_code_reference(self->lhs);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, code_ref.data),
"Accessing fields is only applicable for variables");
throw(AST_ERR);
}
@@ -379,24 +389,24 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) {
callee_code_ref = self->rhs->resolve_data.type->var_name;
if(self->lhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data),
"Can only access field of structs");
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared here");
throw(AST_ERR);
}
if(!self->rhs->resolve_data.type->is_pub) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data),
+ tokenizer_print_error(&caller_parser->tokenizer,
+ tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data),
"Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data);
/* TODO: use tokenizer_print_note, once it has been added */
/* TODO: Print type */
- tokenizer_print_error(&context->parser->tokenizer,
+ tokenizer_print_error(&callee_parser->tokenizer,
tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data),
"Type was declared non-public here");
throw(AST_ERR);
@@ -425,17 +435,19 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) {
TODO: For this first error, only print the line without a reference to code.
This requires change in tokenizer_print_error to be able to take a line as reference.
*/
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->rhs).data),
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data),
"Can't cast type \"%.*s\" to type \"%.*s\"",
self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data,
self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->lhs).data),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->lhs).data),
"Left-hand side is of type %.*s",
self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->rhs).data),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data),
"Right-hand side is of type %.*s",
self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data);
throw(AST_ERR);
@@ -460,8 +472,10 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
if(self->resolve_data.status == AST_RESOLVED) {
return;
} else if(self->resolve_data.status == AST_RESOLVING) {
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data),
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data),
"Found recursive dependency");
throw(AST_ERR);
}
@@ -472,9 +486,11 @@ void ast_resolve(Ast *self, AstCompilerContext *context) {
amal_mutex_tryunlock(self->value.lhs_expr->mutex);
return;
} else if(self->resolve_data.status == AST_RESOLVING) {
+ Parser *parser;
+ parser = scope_get_parser(context->scope);
amal_mutex_tryunlock(self->value.lhs_expr->mutex);
- tokenizer_print_error(&context->parser->tokenizer,
- tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data),
+ tokenizer_print_error(&parser->tokenizer,
+ tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data),
"Found recursive dependency");
throw(AST_ERR);
}
diff --git a/src/compiler.c b/src/compiler.c
index 1feaf86..c9ae09a 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -208,7 +208,6 @@ static void* thread_callback_parse_file(void *userdata) {
static CHECK_RESULT int thread_resolve_ast(amal_compiler *compiler, Parser *parser) {
AstCompilerContext compiler_context;
int result;
- compiler_context.parser = parser;
compiler_context.compiler = compiler;
compiler_context.scope = NULL;
result = setjmp(compiler_context.env);
@@ -222,7 +221,6 @@ static CHECK_RESULT int thread_resolve_ast(amal_compiler *compiler, Parser *pars
static CHECK_RESULT int thread_generate_ssa(Parser *parser) {
SsaCompilerContext compiler_context;
int result;
- compiler_context.parser = parser;
result = setjmp(compiler_context.env);
if(result == 0) {
return_if_error(ssa_init(&compiler_context.ssa, parser->allocator));
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c
index 3fffb63..2391778 100644
--- a/src/ssa/ssa.c
+++ b/src/ssa/ssa.c
@@ -119,8 +119,8 @@ static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstructionType ins_type
return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister) + sizeof(u16)));
self->instructions.data[index + 0] = ins_type;
- *(SsaRegister*)&self->instructions.data[index + 1] = lhs;
- *(u16*)&self->instructions.data[index + 3] = rhs;
+ am_memcpy(self->instructions.data + index + 1, &lhs, sizeof(lhs));
+ am_memcpy(self->instructions.data + index + 3, &rhs, sizeof(rhs));
return 0;
}
@@ -147,9 +147,9 @@ static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstructionType ins_type
return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister) + sizeof(SsaRegister) + sizeof(SsaRegister)));
*result = self->reg_counter++;
self->instructions.data[index + 0] = ins_type;
- *(SsaRegister*)&self->instructions.data[index + 1] = *result;
- *(SsaRegister*)&self->instructions.data[index + 3] = lhs;
- *(SsaRegister*)&self->instructions.data[index + 5] = rhs;
+ am_memcpy(self->instructions.data + index + 1, &result, sizeof(*result));
+ am_memcpy(self->instructions.data + index + 3, &lhs, sizeof(lhs));
+ am_memcpy(self->instructions.data + index + 5, &rhs, sizeof(rhs));
amal_log_debug("r%u = r%u %s r%u", *result, lhs, binop_type_to_string(ins_type), rhs);
return 0;
}
@@ -170,7 +170,7 @@ int ssa_ins_assign_string(Ssa *self, SsaRegister dest, BufferView str) {
int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegister src) {
amal_log_debug("r%u = r%u", dest, src);
- return ssa_add_ins_form1(self, SSA_ASSIGN_INTER, dest, src);
+ return ssa_add_ins_form1(self, SSA_ASSIGN_REG, dest, src);
}
int ssa_ins_binop(Ssa *self, SsaInstructionType binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) {
@@ -189,7 +189,7 @@ int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) {
return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(u8)));
*result = self->func_counter++;
self->instructions.data[index + 0] = SSA_FUNC_START;
- *(SsaFuncIndex*)&self->instructions.data[index + 1] = *result;
+ am_memcpy(self->instructions.data + index + 1, result, sizeof(*result));
self->instructions.data[index + 3] = num_args;
amal_log_debug("FUNC_START f%u(%u)", *result, num_args);
return 0;
@@ -208,12 +208,12 @@ int ssa_ins_push(Ssa *self, SsaRegister reg) {
return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister)));
self->instructions.data[index + 0] = SSA_PUSH;
- *(SsaRegister*)&self->instructions.data[index + 1] = reg;
+ am_memcpy(self->instructions.data + index + 1, &reg, sizeof(reg));
amal_log_debug("PUSH r%u", reg);
return 0;
}
-int ssa_ins_call(Ssa *self, SsaFuncIndex func, SsaRegister *result) {
+int ssa_ins_call(Ssa *self, void *func, SsaRegister *result) {
usize index;
index = self->instructions.size;
@@ -224,9 +224,9 @@ int ssa_ins_call(Ssa *self, SsaFuncIndex func, SsaRegister *result) {
return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(SsaRegister)));
*result = self->reg_counter++;
self->instructions.data[index + 0] = SSA_CALL;
- *(SsaFuncIndex*)&self->instructions.data[index + 1] = func;
- *(SsaRegister*)&self->instructions.data[index + 3] = *result;
- amal_log_debug("r%u = CALL f%u", *result, func);
+ am_memcpy(self->instructions.data + index + 1, &func, sizeof(func));
+ am_memcpy(self->instructions.data + index + 3, result, sizeof(*result));
+ amal_log_debug("r%u = CALL %p", *result, func);
return 0;
}
@@ -247,20 +247,34 @@ static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerCon
return reg;
}
-
-static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) {
+static CHECK_RESULT SsaRegister lhsexpr_generate_ssa(Ast *self, SsaCompilerContext *context) {
/* TODO: Implement */
+ LhsExpr *lhs_expr;
SsaRegister reg;
- throw_if_error(amal_mutex_lock(self->mutex, "lhs_generate_ssa"));
- throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
- if(self->rhs_expr) {
+
+ assert(self->type == AST_LHS);
+ lhs_expr = self->value.lhs_expr;
+
+ if(lhs_expr->rhs_expr) {
SsaRegister rhs_reg;
- rhs_reg = ast_generate_ssa(self->rhs_expr, context);
+ rhs_reg = ast_generate_ssa(lhs_expr->rhs_expr, context);
+ /*
+ Declarations (struct and function declaration) resolves to itself and in that case this expression
+ is just a compile-time name for the declaration.
+ Import expression also has no meaning in SSA until it's used.
+ TODO: Shouldn't lhsexpr that have struct/function declaration as rhs be different ast expression types?
+ */
+ if(self->resolve_data.type == lhs_expr || lhs_expr->rhs_expr->type == AST_IMPORT)
+ return 0;
+ throw_if_error(ssa_get_unique_reg(&context->ssa, &reg));
+ if(reg == rhs_reg) {
+ amal_log_error("rhs_expr is same as reg.. rhs type: %d", lhs_expr->rhs_expr->type);
+ }
+ assert(reg != rhs_reg);
throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg));
} else {
/* TODO: assign default value to reg depending on LhsExpr type */
}
- throw_if_error(amal_mutex_unlock(self->mutex));
return reg;
}
@@ -270,6 +284,7 @@ in any order.
*/
static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCompilerContext *context) {
/* TODO: Implement */
+ amal_log_debug("SSA funcdecl %p", self);
throw_if_error(ssa_ins_func_start(&context->ssa, 0, &self->ssa_func_index));
scope_generate_ssa(&self->body, context);
throw_if_error(ssa_ins_func_end(&context->ssa));
@@ -279,6 +294,7 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom
static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerContext *context) {
/* TODO: Implement */
FunctionCall *func_call;
+ FunctionDecl *func_to_call;
Ast **ast;
Ast **ast_end;
SsaRegister reg;
@@ -294,9 +310,13 @@ static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerCont
}
assert(self->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL);
- ignore_result_int(lhs_generate_ssa(self->resolve_data.type, context));
- amal_log_debug("SSA funccall %.*s, func index: %d", func_call->func.name.size, func_call->func.name.data, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index);
- throw_if_error(ssa_ins_call(&context->ssa, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index, &reg));
+ func_to_call = self->resolve_data.type->rhs_expr->value.func_decl;
+ /*
+ TODO: Implement func reference instead of using 0. Perhaps the best way is to use function declaration pointer value?
+ then there is no need for mutex locks.
+ */
+ amal_log_debug("SSA funccall %.*s, func index ptr: %p", func_call->func.name.size, func_call->func.name.data, func_to_call);
+ throw_if_error(ssa_ins_call(&context->ssa, func_to_call, &reg));
return reg;
}
@@ -379,7 +399,7 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context
case AST_STRUCT_FIELD:
return structfield_generate_ssa(self->value.struct_field, context);
case AST_LHS:
- return lhs_generate_ssa(self->value.lhs_expr, context);
+ return lhsexpr_generate_ssa(self, context);
case AST_IMPORT:
/* TODO: When @import(...).data syntax is added, implement the generate ssa for it */
return 0;
diff --git a/src/std/hash_map.c b/src/std/hash_map.c
index ab580ba..d9914e7 100644
--- a/src/std/hash_map.c
+++ b/src/std/hash_map.c
@@ -142,10 +142,6 @@ static void hash_map_reorder_nodes(HashMap *self, usize end_index) {
bucket_node = bucket_node_get_next(bucket_node);
}
}
-
- /* All nodes removed in bucket */
- if(!prev_bucket_node)
- bucket->start = NULL;
}
}