Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory leaks #606

Merged
merged 6 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading