From 138de9de61da9fdc44ef0c9be14393c4dbcbf65c Mon Sep 17 00:00:00 2001 From: Akuli Date: Fri, 10 Jan 2025 16:48:40 +0200 Subject: [PATCH] Signature methods --- compiler/build_cf_graph.jou | 8 +-- compiler/cf_graph.jou | 6 +- compiler/codegen.jou | 6 +- compiler/main.jou | 2 +- compiler/structs.jou | 15 +---- compiler/typecheck.jou | 6 +- compiler/types.jou | 129 +++++++++++++++++++----------------- 7 files changed, 85 insertions(+), 87 deletions(-) diff --git a/compiler/build_cf_graph.jou b/compiler/build_cf_graph.jou index bf6035f4..1f02a67d 100644 --- a/compiler/build_cf_graph.jou +++ b/compiler/build_cf_graph.jou @@ -536,7 +536,7 @@ def build_function_or_method_call( assert selfclass->kind == TypeKind::Class for s = selfclass->classdata.methods; s < &selfclass->classdata.methods[selfclass->classdata.nmethods]; s++: - assert get_self_class(s) == selfclass + assert s->get_self_class() == selfclass if strcmp(s->name, call->name) == 0: sig = s break @@ -552,7 +552,7 @@ def build_function_or_method_call( ins = CfInstruction{ location = location, kind = CfInstructionKind::Call, - signature = copy_signature(sig), + signature = sig->copy(), } if call->method_call_self != NULL: @@ -1093,13 +1093,13 @@ def build_function_or_method( assert st->fomtypes == NULL for f = st->filetypes->fomtypes; f < &st->filetypes->fomtypes[st->filetypes->nfomtypes]; f++: - if strcmp(f->signature.name, name) == 0 and get_self_class(&f->signature) == selfclass: + if strcmp(f->signature.name, name) == 0 and f->signature.get_self_class() == selfclass: st->fomtypes = f break assert st->fomtypes != NULL st->cfg = calloc(1, sizeof *st->cfg) - st->cfg->signature = copy_signature(&st->fomtypes->signature) + st->cfg->signature = st->fomtypes->signature.copy() # Copy local variables over from type checking. # Ownership of the variables changes, they will be freed when graphs are freed. diff --git a/compiler/cf_graph.jou b/compiler/cf_graph.jou index fed7cc6e..af9ed5ad 100644 --- a/compiler/cf_graph.jou +++ b/compiler/cf_graph.jou @@ -91,8 +91,8 @@ class CfInstruction: printf("boolean negation of ") self->operands[0]->print() elif self->kind == CfInstructionKind::Call: - if get_self_class(&self->signature) != NULL: - printf("call method %s.", get_self_class(&self->signature)->name) + if self->signature.get_self_class() != NULL: + printf("call method %s.", self->signature.get_self_class()->name) else: printf("call function ") printf("%s(", self->signature.name) @@ -236,7 +236,7 @@ class CfGraph: def print(self) -> None: printed_varnames_idx = 0 - sigstr: byte* = signature_to_string(&self->signature, True, True) + sigstr: byte* = self->signature.to_string(True, True) printf("Function %s\n", sigstr) free(sigstr) diff --git a/compiler/codegen.jou b/compiler/codegen.jou index 583e658d..9fd0fee4 100644 --- a/compiler/codegen.jou +++ b/compiler/codegen.jou @@ -181,8 +181,8 @@ class CodeGen: def do_function_or_method_decl(self, sig: Signature*) -> LLVMValue*: fullname: byte[200] - if get_self_class(sig) != NULL: - snprintf(fullname, sizeof fullname, "%s.%s", get_self_class(sig)->name, sig->name) + if sig->get_self_class() != NULL: + snprintf(fullname, sizeof fullname, "%s.%s", sig->get_self_class()->name, sig->name) else: assert sizeof(fullname) >= sizeof(sig->name) assert sizeof(sig->name) > 50 # this is an array, not a pointer to dynamic length string @@ -419,7 +419,7 @@ class CodeGen: assert cfg->all_blocks[0] == &cfg->start_block LLVMPositionBuilderAtEnd(self->builder, blocks[0]) - if get_self_class(&cfg->signature) == NULL and strcmp(cfg->signature.name, "main") == 0: + if cfg->signature.get_self_class() == NULL and strcmp(cfg->signature.name, "main") == 0: # Insert special code at start of main() self->do_call_of_special_startup_func() diff --git a/compiler/main.jou b/compiler/main.jou index 8061744b..d14b3ae8 100644 --- a/compiler/main.jou +++ b/compiler/main.jou @@ -208,7 +208,7 @@ class FileState: self->types.functions = realloc(self->types.functions, sizeof(self->types.functions[0]) * (self->types.nfunctions + 1)) assert self->types.functions != NULL self->types.functions[self->types.nfunctions++] = SignatureAndUsedPtr{ - signature = copy_signature(&es->funcsignature), + signature = es->funcsignature.copy(), usedptr = &imp->used, } elif es->kind == ExportSymbolKind::Type: diff --git a/compiler/structs.jou b/compiler/structs.jou index 9000e21b..5ae69b84 100644 --- a/compiler/structs.jou +++ b/compiler/structs.jou @@ -6,7 +6,7 @@ import "stdlib/io.jou" import "./ast.jou" import "./types.jou" -import "./errors_and_warnings.jou" + class CommandLineArgs: argv0: byte* # Program name @@ -69,19 +69,6 @@ def int_constant(type: Type*, value: long) -> Constant: } -class Signature: - name: byte[100] # Function or method name. For methods it does not include the name of the class. - nargs: int - argtypes: Type** - argnames: byte[100]* - takes_varargs: bool # true for functions like printf() - # TODO: rename to return_type - returntype: Type* # NULL, if does not return a value - is_noreturn: bool - # TODO: rename to return_type_location - returntype_location: Location # meaningful even if returntype is NULL - - class GlobalVariable: name: byte[100] # Same as in user's code, never empty type: Type* diff --git a/compiler/typecheck.jou b/compiler/typecheck.jou index 72d4571e..bc394a64 100644 --- a/compiler/typecheck.jou +++ b/compiler/typecheck.jou @@ -269,7 +269,7 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_class: Type*) - ft->functions = realloc(ft->functions, sizeof(ft->functions[0]) * (ft->nfunctions + 1)) assert ft->functions != NULL ft->functions[ft->nfunctions++] = SignatureAndUsedPtr{ - signature = copy_signature(&sig), + signature = sig.copy(), usedptr = NULL, } @@ -928,7 +928,7 @@ def typecheck_function_or_method_call(ft: FileTypes*, call: AstCall*, self_type: else: function_or_method = "method" - sigstr = signature_to_string(sig, False, False) + sigstr = sig->to_string(False, False) nargs = sig->nargs if self_type != NULL: @@ -1482,7 +1482,7 @@ def typecheck_function_or_method_body(ft: FileTypes*, sig: Signature*, body: Ast ft->fomtypes[ft->nfomtypes++] = FunctionOrMethodTypes{} ft->current_fom_types = &ft->fomtypes[ft->nfomtypes - 1] - ft->current_fom_types->signature = copy_signature(sig) + ft->current_fom_types->signature = sig->copy() for i = 0; i < sig->nargs; i++: v = add_variable(ft, sig->argtypes[i], sig->argnames[i]) diff --git a/compiler/types.jou b/compiler/types.jou index 3abcaca8..017be749 100644 --- a/compiler/types.jou +++ b/compiler/types.jou @@ -1,6 +1,8 @@ import "stdlib/mem.jou" import "stdlib/str.jou" + import "./structs.jou" +import "./errors_and_warnings.jou" import "./free.jou" class ClassField: @@ -243,71 +245,80 @@ def create_enum(name: byte*, membercount: int, membernames: byte[100]*) -> Type* return &result->type -# TODO: move out -def get_self_class(sig: Signature*) -> Type*: - if sig->nargs > 0 and strcmp(sig->argnames[0], "self") == 0: - if sig->argtypes[0]->kind == TypeKind::Pointer: - return sig->argtypes[0]->value_type - if sig->argtypes[0]->kind == TypeKind::Class: - return sig->argtypes[0] - assert False - return NULL - -# TODO: move out -def signature_to_string(sig: Signature*, include_return_type: bool, include_self: bool) -> byte*: - result = strdup(sig->name) - assert result != NULL - - result = realloc(result, strlen(result) + 2) - assert result != NULL - strcat(result, "(") - - for i = 0; i < sig->nargs; i++: - if strcmp(sig->argnames[i], "self") == 0 and not include_self: - continue +class Signature: + name: byte[100] # Function or method name. For methods it does not include the name of the class. + nargs: int + argtypes: Type** + argnames: byte[100]* + takes_varargs: bool # true for functions like printf() + # TODO: rename to return_type + returntype: Type* # NULL, if does not return a value + is_noreturn: bool + # TODO: rename to return_type_location + returntype_location: Location # meaningful even if returntype is NULL + + def get_self_class(self) -> Type*: + if self->nargs > 0 and strcmp(self->argnames[0], "self") == 0: + if self->argtypes[0]->kind == TypeKind::Pointer: + return self->argtypes[0]->value_type + if self->argtypes[0]->kind == TypeKind::Class: + return self->argtypes[0] + assert False + return NULL + + def to_string(self, include_return_type: bool, include_self: bool) -> byte*: + result = strdup(self->name) + assert result != NULL - assert sizeof sig->argnames[i] == 100 - assert sizeof sig->argtypes[i]->name == 500 - result = realloc(result, strlen(result) + 1000) + result = realloc(result, strlen(result) + 2) assert result != NULL - strcat(result, sig->argnames[i]) - strcat(result, ": ") - strcat(result, sig->argtypes[i]->name) - if i < sig->nargs - 1: - strcat(result, ", ") - - result = realloc(result, strlen(result) + 100) - assert result != NULL - - if sig->takes_varargs: - if sig->nargs != 0: - strcat(result, ", ") - strcat(result, "...") - strcat(result, ")") - - if include_return_type: - assert sizeof(sig->returntype->name) == 500 - result = realloc(result, strlen(result) + 600) + strcat(result, "(") + + for i = 0; i < self->nargs; i++: + if strcmp(self->argnames[i], "self") == 0 and not include_self: + continue + + assert sizeof self->argnames[i] == 100 + assert sizeof self->argtypes[i]->name == 500 + result = realloc(result, strlen(result) + 1000) + assert result != NULL + strcat(result, self->argnames[i]) + strcat(result, ": ") + strcat(result, self->argtypes[i]->name) + if i < self->nargs - 1: + strcat(result, ", ") + + result = realloc(result, strlen(result) + 100) assert result != NULL - strcat(result, " -> ") - if sig->is_noreturn: - strcat(result, "noreturn") - elif sig->returntype == NULL: - strcat(result, "void") - else: - strcat(result, sig->returntype->name) + if self->takes_varargs: + if self->nargs != 0: + strcat(result, ", ") + strcat(result, "...") + strcat(result, ")") - return result + if include_return_type: + assert sizeof(self->returntype->name) == 500 + result = realloc(result, strlen(result) + 600) + assert result != NULL -# TODO: move out -def copy_signature(sig: Signature*) -> Signature: - result = *sig + strcat(result, " -> ") + if self->is_noreturn: + strcat(result, "noreturn") + elif self->returntype == NULL: + strcat(result, "void") + else: + strcat(result, self->returntype->name) + + return result + + def copy(self) -> Signature: + result = *self - result.argtypes = malloc(sizeof(result.argtypes[0]) * result.nargs) - memcpy(result.argtypes, sig->argtypes, sizeof(result.argtypes[0]) * result.nargs) + result.argtypes = malloc(sizeof(result.argtypes[0]) * result.nargs) + memcpy(result.argtypes, self->argtypes, sizeof(result.argtypes[0]) * result.nargs) - result.argnames = malloc(sizeof(result.argnames[0]) * result.nargs) - memcpy(result.argnames, sig->argnames, sizeof(result.argnames[0]) * result.nargs) + result.argnames = malloc(sizeof(result.argnames[0]) * result.nargs) + memcpy(result.argnames, self->argnames, sizeof(result.argnames[0]) * result.nargs) - return result + return result