Skip to content

Commit

Permalink
Fix memory leaks (#606)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Jan 12, 2025
1 parent 86b9c8d commit acbd5ed
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 12 deletions.
1 change: 1 addition & 0 deletions bootstrap_compiler/typecheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,7 @@ static void handle_conflicting_class_field_and_enum_member_syntax(const FileType
return;
}

free(expr->data.classfield.obj);
expr->kind = AST_EXPR_GET_ENUM_MEMBER;
memset(&expr->data, 0, sizeof(expr->data));
safe_strcpy(expr->data.enummember.enumname, enum_name);
Expand Down
55 changes: 44 additions & 11 deletions compiler/ast.jou
Original file line number Diff line number Diff line change
Expand Up @@ -328,19 +328,19 @@ class AstExpression:
self->operands[i].print_with_tree_printer(tp.print_prefix(i == self->get_arity()-1))

def free(self) -> None:
if self->kind == AstExpressionKind.Call:
self->call.free()
elif self->kind == AstExpressionKind.As:
self->as_->free()
free(self->as_)
elif self->kind == AstExpressionKind.String:
if self->kind == AstExpressionKind.String:
free(self->string)
elif self->kind == AstExpressionKind.Array:
self->array.free()
elif self->kind == AstExpressionKind.Call:
self->call.free()
elif self->kind == AstExpressionKind.Instantiate:
self->instantiation.free()
elif self->kind == AstExpressionKind.GetClassField:
self->class_field.free()
elif self->kind == AstExpressionKind.As:
self->as_->free()
free(self->as_)

if self->get_arity() != 0:
for i = 0; i < self->get_arity(); i++:
Expand Down Expand Up @@ -454,6 +454,9 @@ class AstCall:
for i = 0; i < self->nargs; i++:
self->args[i].free()
free(self->args)
if self->method_call_self != NULL:
self->method_call_self->free()
free(self->method_call_self)

# Useful for formatting error messages, but not much else.
# TODO: use this
Expand All @@ -469,6 +472,10 @@ class AstAssertion:
condition: AstExpression
condition_str: byte*

def free(self) -> None:
self->condition.free()
free(self->condition_str)


enum AstStatementKind:
ExpressionStatement # Evaluate an expression. Discard the result.
Expand Down Expand Up @@ -502,8 +509,8 @@ class AstStatement:
if_statement: AstIfStatement
while_loop: AstConditionAndBody
for_loop: AstForLoop
return_value: AstExpression* # can be NULL
assignment: AstAssignment
return_value: AstExpression* # can be NULL
assignment: AstAssignment # also used for +=, -= etc
var_declaration: AstNameTypeValue # DeclareLocalVar
function: AstFunctionOrMethod
classdef: AstClassDef
Expand Down Expand Up @@ -582,19 +589,40 @@ class AstStatement:
printf("??????\n")

def free(self) -> None:
if self->kind == AstStatementKind.Enum:
self->enumdef.free()
if self->kind == AstStatementKind.ExpressionStatement:
self->expression.free()
if self->kind == AstStatementKind.Assert:
self->assertion.free()
if self->kind == AstStatementKind.Return and self->return_value != NULL:
self->return_value->free()
free(self->return_value)
if self->kind == AstStatementKind.If:
self->if_statement.free()
if self->kind == AstStatementKind.WhileLoop:
self->while_loop.free()
if self->kind == AstStatementKind.ForLoop:
self->for_loop.free()
if (
self->kind == AstStatementKind.DeclareLocalVar
or self->kind == AstStatementKind.GlobalVariableDeclaration
or self->kind == AstStatementKind.GlobalVariableDefinition
):
self->var_declaration.free()
if (
self->kind == AstStatementKind.Assign
or self->kind == AstStatementKind.InPlaceAdd
or self->kind == AstStatementKind.InPlaceSub
or self->kind == AstStatementKind.InPlaceMul
or self->kind == AstStatementKind.InPlaceDiv
or self->kind == AstStatementKind.InPlaceMod
):
self->assignment.free()
if self->kind == AstStatementKind.Function:
self->function.free()
if self->kind == AstStatementKind.Class:
self->classdef.free()
if self->kind == AstStatementKind.Enum:
self->enumdef.free()


# Useful for e.g. "while condition: body", "if condition: body"
Expand Down Expand Up @@ -631,6 +659,10 @@ class AstAssignment:
self->target.print_with_tree_printer(tp.print_prefix(False))
self->value.print_with_tree_printer(tp.print_prefix(True))

def free(self) -> None:
self->target.free()
self->value.free()


# if foo:
# ...
Expand Down Expand Up @@ -730,9 +762,10 @@ class AstNameTypeValue:
self->value->print_with_tree_printer(sub)

def free(self) -> None:
self->type.free()
if self->value != NULL:
self->value->free()
free(self->value)
free(self->value)


# typically multiple indented lines after a ":" at end of line
Expand Down
2 changes: 1 addition & 1 deletion compiler/build_cf_graph.jou
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class CfBuilder:
assert sizeof(c.double_or_float_text) == sizeof(expr->float_or_double_text)
strcpy(c.double_or_float_text, expr->float_or_double_text)
elif expr->kind == AstExpressionKind.String:
c = Constant{kind = ConstantKind.String, str = strdup(expr->string)}
c = Constant{kind = ConstantKind.String, str = expr->string}
else:
assert False
result = self->add_var(t)
Expand Down
2 changes: 2 additions & 0 deletions compiler/parser.jou
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ def check_class_for_duplicate_names(classdef: AstClassDef*) -> None:
)
fail(p2->name_location, message)

free(infos)


# TODO: this function is just bad...
def read_assertion_from_file(start: Location, end: Location) -> byte*:
Expand Down
2 changes: 2 additions & 0 deletions compiler/tokenizer.jou
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,8 @@ def tokenize(path: byte*, import_location: Location*) -> Token*:
fail(*import_location, message)

raw_tokens = tokenize_without_indent_dedent_tokens(file, path)
fclose(file)

better_tokens = handle_indentations(raw_tokens)
free(raw_tokens)
return better_tokens
Expand Down
1 change: 1 addition & 0 deletions compiler/typecheck/step3_function_and_method_bodies.jou
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ def handle_conflicting_class_field_and_enum_member_syntax(ft: FileTypes*, expr:
if expr->class_field.uses_arrow_operator:
fail(expr->location, "the '->' operator cannot be used to look up enum members")

free(expr->class_field.instance)
expr->kind = AstExpressionKind.GetEnumMember
expr->enum_member = AstEnumMember{
enum_name = enum_name,
Expand Down

0 comments on commit acbd5ed

Please sign in to comment.