diff --git a/compiler/build_cf_graph.jou b/compiler/build_cf_graph.jou index 40231f43..bf6035f4 100644 --- a/compiler/build_cf_graph.jou +++ b/compiler/build_cf_graph.jou @@ -142,7 +142,7 @@ def build_bool_to_int_conversion( location: Location, t: Type*, ) -> LocalVariable*: - assert is_integer_type(t) + assert t->is_integer_type() result: LocalVariable* = add_local_var(st, t) set1 = add_block(st) @@ -167,39 +167,39 @@ def build_cast( if obj->type == to: return obj - if is_pointer_type(obj->type) and is_pointer_type(to): + if obj->type->is_pointer_type() and to->is_pointer_type(): result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::PtrCast, obj, result) return result - if is_number_type(obj->type) and is_number_type(to): + if obj->type->is_number_type() and to->is_number_type(): result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::NumCast, obj, result) return result - if is_number_type(obj->type) and obj->type->size_in_bits == 64 and is_pointer_type(to): + if obj->type->is_number_type() and obj->type->size_in_bits == 64 and to->is_pointer_type(): result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::Int64ToPtr, obj, result) return result - if is_integer_type(obj->type) or to->kind == TypeKind::Enum: + if obj->type->is_integer_type() or to->kind == TypeKind::Enum: i32var = add_local_var(st, intType) result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::NumCast, obj, i32var) add_unary_op(st, location, CfInstructionKind::Int32ToEnum, i32var, result) return result - if obj->type->kind == TypeKind::Enum and is_integer_type(to): + if obj->type->kind == TypeKind::Enum and to->is_integer_type(): i32var = add_local_var(st, intType) result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::EnumToInt32, obj, i32var) add_unary_op(st, location, CfInstructionKind::NumCast, i32var, result) return result - if obj->type == boolType and is_integer_type(to): + if obj->type == boolType and to->is_integer_type(): return build_bool_to_int_conversion(st, obj, location, to) - if is_pointer_type(obj->type) and is_integer_type(to) and to->size_in_bits == 64: + if obj->type->is_pointer_type() and to->is_integer_type() and to->size_in_bits == 64: result = add_local_var(st, to) add_unary_op(st, location, CfInstructionKind::PtrToInt64, obj, result) return result @@ -248,8 +248,8 @@ def build_binop( result_type: Type*, ) -> LocalVariable*: got_bools = lhs->type == boolType and rhs->type == boolType - got_numbers = is_number_type(lhs->type) and is_number_type(rhs->type) - got_pointers = is_pointer_type(lhs->type) and is_pointer_type(rhs->type) + got_numbers = lhs->type->is_number_type() and rhs->type->is_number_type() + got_pointers = lhs->type->is_pointer_type() and rhs->type->is_pointer_type() assert got_bools or got_numbers or got_pointers negate = False @@ -316,7 +316,7 @@ def build_class_field_pointer( for f = class_type->classdata.fields; f < &class_type->classdata.fields[class_type->classdata.nfields]; f++: if strcmp(f->name, fieldname) == 0: - result = add_local_var(st, get_pointer_type(f->type)) + result = add_local_var(st, f->type->pointer()) ins = CfInstruction{ location = location, @@ -340,7 +340,7 @@ def build_class_field( fieldname: byte*, location: Location, ) -> LocalVariable*: - ptr = add_local_var(st, get_pointer_type(instance->type)) + ptr = add_local_var(st, instance->type->pointer()) add_unary_op(st, location, CfInstructionKind::AddressOfLocalVar, instance, ptr) field_ptr = build_class_field_pointer(st, ptr, fieldname, location) field = add_local_var(st, field_ptr->type->value_type) @@ -366,7 +366,7 @@ def build_increment_or_decrement( assert addr->type->kind == TypeKind::Pointer t = addr->type->value_type - if not is_integer_type(t) and not is_pointer_type(t): + if not t->is_integer_type() and not t->is_pointer_type(): msg: byte[500] if diff == 1: snprintf(msg, sizeof(msg), "cannot increment a value of type %s", t->name) @@ -376,14 +376,14 @@ def build_increment_or_decrement( old_value = add_local_var(st, t) new_value = add_local_var(st, t) - if is_integer_type(t): + if t->is_integer_type(): diffvar = add_local_var(st, t) else: diffvar = add_local_var(st, intType) add_constant(st, location, int_constant(diffvar->type, diff), diffvar) add_unary_op(st, location, CfInstructionKind::PtrLoad, addr, old_value) - if is_number_type(t): + if t->is_number_type(): add_binary_op(st, location, CfInstructionKind::NumAdd, old_value, diffvar, new_value) else: add_binary_op(st, location, CfInstructionKind::PtrAddInt, old_value, diffvar, new_value) @@ -464,7 +464,7 @@ def build_and_or( def build_address_of_expression(st: State*, address_of_what: AstExpression*) -> LocalVariable*: if address_of_what->kind == AstExpressionKind::GetVariable: - ptrtype = get_pointer_type(get_expr_types(st, address_of_what)->type) + ptrtype = get_expr_types(st, address_of_what)->type->pointer() addr = add_local_var(st, ptrtype) local_var = find_local_var_cf(st, address_of_what->varname) @@ -483,7 +483,7 @@ def build_address_of_expression(st: State*, address_of_what: AstExpression*) -> return addr if address_of_what->kind == AstExpressionKind::Self: - ptrtype = get_pointer_type(get_expr_types(st, address_of_what)->type) + ptrtype = get_expr_types(st, address_of_what)->type->pointer() addr = add_local_var(st, ptrtype) local_var = find_local_var_cf(st, "self") @@ -512,7 +512,7 @@ def build_address_of_expression(st: State*, address_of_what: AstExpression*) -> assert ptr->type->kind == TypeKind::Pointer index = build_expression(st, &address_of_what->operands[1]) - assert is_integer_type(index->type) + assert index->type->is_integer_type() result = add_local_var(st, ptr->type) add_binary_op(st, address_of_what->location, CfInstructionKind::PtrAddInt, ptr, index, result) @@ -556,9 +556,9 @@ def build_function_or_method_call( } if call->method_call_self != NULL: - if is_pointer_type(sig->argtypes[0]) and not call->uses_arrow_operator: + if sig->argtypes[0]->is_pointer_type() and not call->uses_arrow_operator: ins.add_operand(build_address_of_expression(st, call->method_call_self)) - elif (not is_pointer_type(sig->argtypes[0])) and call->uses_arrow_operator: + elif (not sig->argtypes[0]->is_pointer_type()) and call->uses_arrow_operator: self_ptr = build_expression(st, call->method_call_self) assert self_ptr->type->kind == TypeKind::Pointer @@ -586,7 +586,7 @@ def build_function_or_method_call( def build_instantiation(st: State*, type: Type*, inst: AstInstantiation*, location: Location) -> LocalVariable*: instance = add_local_var(st, type) - instanceptr = add_local_var(st, get_pointer_type(type)) + instanceptr = add_local_var(st, type->pointer()) add_unary_op(st, location, CfInstructionKind::AddressOfLocalVar, instance, instanceptr) add_unary_op(st, location, CfInstructionKind::PtrMemsetToZero, instanceptr, NULL) @@ -603,9 +603,9 @@ def build_array(st: State*, type: Type*, items: AstExpression*, location: Locati assert type->kind == TypeKind::Array arr = add_local_var(st, type) - arrptr = add_local_var(st, get_pointer_type(type)) + arrptr = add_local_var(st, type->pointer()) add_unary_op(st, location, CfInstructionKind::AddressOfLocalVar, arr, arrptr) - first_item_ptr = add_local_var(st, get_pointer_type(type->array.item_type)) + first_item_ptr = add_local_var(st, type->array.item_type->pointer()) add_unary_op(st, location, CfInstructionKind::PtrCast, arrptr, first_item_ptr) for i = 0; i < type->array.len; i++: @@ -896,8 +896,8 @@ def build_assert(st: State*, assert_location: Location, assertion: AstAssertion* strcpy(argnames[2], "lineno") argtypes: Type** = malloc(3 * sizeof(argtypes[0])) - argtypes[0] = get_pointer_type(byteType) - argtypes[1] = get_pointer_type(byteType) + argtypes[0] = byteType->pointer() + argtypes[1] = byteType->pointer() argtypes[2] = intType ins = CfInstruction{ diff --git a/compiler/structs.jou b/compiler/structs.jou index e0d7890c..9000e21b 100644 --- a/compiler/structs.jou +++ b/compiler/structs.jou @@ -58,7 +58,7 @@ def copy_constant(c: Constant) -> Constant: return c def int_constant(type: Type*, value: long) -> Constant: - assert is_integer_type(type) + assert type->is_integer_type() return Constant{ kind = ConstantKind::Integer, integer = IntegerConstant{ @@ -68,6 +68,7 @@ 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 diff --git a/compiler/typecheck.jou b/compiler/typecheck.jou index 41f94e02..72d4571e 100644 --- a/compiler/typecheck.jou +++ b/compiler/typecheck.jou @@ -164,14 +164,14 @@ def type_from_ast(ft: FileTypes*, asttype: AstType*) -> Type*: if asttype->kind == AstTypeKind::Pointer: if asttype->value_type->is_void(): return voidPtrType - return get_pointer_type(type_from_ast(ft, asttype->value_type)) + return type_from_ast(ft, asttype->value_type)->pointer() if asttype->kind == AstTypeKind::Array: tmp = type_from_ast(ft, asttype->value_type) len = evaluate_array_length(asttype->array.length) if len <= 0: fail(asttype->array.length->location, "array length must be positive") - return get_array_type(tmp, len) + return tmp->array_type(len) assert False @@ -228,11 +228,11 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_class: Type*) - and astsig->args[i].type.name[0] == '\0' ): # just "self" without a type after it --> default to "self: Foo*" in class Foo - argtype = get_pointer_type(self_class) + argtype = self_class->pointer() else: argtype = type_from_ast(ft, &astsig->args[i].type) - if strcmp(sig.argnames[i], "self") == 0 and argtype != self_class and argtype != get_pointer_type(self_class): + if strcmp(sig.argnames[i], "self") == 0 and argtype != self_class and argtype != self_class->pointer(): snprintf(msg, sizeof(msg), "type of self must be %s* (default) or %s", self_class->name, self_class->name) fail(astsig->args[i].type.location, msg) @@ -255,7 +255,7 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_class: Type*) - and not ( sig.nargs == 2 and sig.argtypes[0] == intType - and sig.argtypes[1] == get_pointer_type(get_pointer_type(byteType)) + and sig.argtypes[1] == byteType->pointer()->pointer() ) ): fail( @@ -614,7 +614,7 @@ def do_implicit_cast( if ( types->expr->kind == AstExpressionKind::String - and from == get_pointer_type(byteType) + and from == byteType->pointer() and to->kind == TypeKind::Array and to->array.item_type == byteType ): @@ -629,7 +629,7 @@ def do_implicit_cast( fail_with_implicit_cast_error(location, errormsg_template, from, to) types->implicit_cast_type = to - types->implicit_array_to_pointer_cast = (from->kind == TypeKind::Array and is_pointer_type(to)) + types->implicit_array_to_pointer_cast = (from->kind == TypeKind::Array and to->is_pointer_type()) if types->implicit_array_to_pointer_cast: ensure_can_take_address( @@ -640,7 +640,7 @@ def do_implicit_cast( def cast_array_to_pointer(fom: FunctionOrMethodTypes*, types: ExpressionTypes*) -> None: assert types->type->kind == TypeKind::Array - do_implicit_cast(fom, types, get_pointer_type(types->type->array.item_type), Location{}, NULL) + do_implicit_cast(fom, types, types->type->array.item_type->pointer(), Location{}, NULL) def do_explicit_cast(fom: FunctionOrMethodTypes*, types: ExpressionTypes*, to: Type*, location: Location) -> None: assert types->implicit_cast_type == NULL @@ -656,7 +656,7 @@ def do_explicit_cast(fom: FunctionOrMethodTypes*, types: ExpressionTypes*, to: T snprintf(msg, sizeof(msg), "cannot cast from type %s to %s", from->name, to->name) fail(location, msg) - if from->kind == TypeKind::Array and is_pointer_type(to): + if from->kind == TypeKind::Array and to->is_pointer_type(): cast_array_to_pointer(fom, types) def typecheck_expression_not_void(ft: FileTypes*, expr: AstExpression*) -> ExpressionTypes*: @@ -714,12 +714,12 @@ def check_binop( assert False got_bools = lhstypes->type == boolType and rhstypes->type == boolType - got_integers = is_integer_type(lhstypes->type) and is_integer_type(rhstypes->type) - got_numbers = is_number_type(lhstypes->type) and is_number_type(rhstypes->type) + got_integers = lhstypes->type->is_integer_type() and rhstypes->type->is_integer_type() + got_numbers = lhstypes->type->is_number_type() and rhstypes->type->is_number_type() got_enums = lhstypes->type->kind == TypeKind::Enum and rhstypes->type->kind == TypeKind::Enum got_pointers = ( - is_pointer_type(lhstypes->type) - and is_pointer_type(rhstypes->type) + lhstypes->type->is_pointer_type() + and rhstypes->type->is_pointer_type() and ( # Ban comparisons like int* == byte*, unless one of the two types is void* lhstypes->type == rhstypes->type @@ -811,7 +811,7 @@ def check_increment_or_decrement(ft: FileTypes*, expr: AstExpression*) -> Type*: ensure_can_take_address(ft->current_fom_types, &expr->operands[0], bad_expr_fmt) t = typecheck_expression_not_void(ft, &expr->operands[0])->type - if not is_integer_type(t) and not is_pointer_type(t): + if not t->is_integer_type() and not t->is_pointer_type(): msg: byte[500] snprintf(msg, sizeof(msg), bad_type_fmt, t->name) fail(expr->location, msg) @@ -847,7 +847,7 @@ def typecheck_indexing( assert ptrtype->kind == TypeKind::Pointer indextypes = typecheck_expression_not_void(ft, indexexpr) - if not is_integer_type(indextypes->type): + if not indextypes->type->is_integer_type(): snprintf(msg, sizeof(msg), "the index inside [...] must be an integer, not %s", indextypes->type->name) fail(indexexpr->location, msg) @@ -962,7 +962,7 @@ def typecheck_function_or_method_call(ft: FileTypes*, call: AstCall*, self_type: if types->type->kind == TypeKind::Array: cast_array_to_pointer(ft->current_fom_types, types) elif ( - (is_integer_type(types->type) and types->type->size_in_bits < 32) + (types->type->is_integer_type() and types->type->size_in_bits < 32) or types->type == boolType ): # Add implicit cast to signed int, just like in C. @@ -1120,7 +1120,7 @@ def typecheck_expression(ft: FileTypes*, expr: AstExpression*) -> ExpressionType elif expr->kind == AstExpressionKind::Null: result = voidPtrType elif expr->kind == AstExpressionKind::String: - result = get_pointer_type(byteType) + result = byteType->pointer() elif expr->kind == AstExpressionKind::GetEnumMember: result = find_type(ft, expr->enum_member.enum_name) @@ -1157,7 +1157,7 @@ def typecheck_expression(ft: FileTypes*, expr: AstExpression*) -> ExpressionType membertype = cast_array_members_to_a_common_type(ft->current_fom_types, expr->location, exprtypes) free(exprtypes) - result = get_array_type(membertype, n) + result = membertype->array_type(n) elif expr->kind == AstExpressionKind::GetClassField: if expr->class_field.uses_arrow_operator: @@ -1201,7 +1201,7 @@ def typecheck_expression(ft: FileTypes*, expr: AstExpression*) -> ExpressionType if strcmp(m->name, expr->call.name) != 0: continue - if is_pointer_type(m->argtypes[0]): + if m->argtypes[0]->is_pointer_type(): assert strstr(expr->call.name, "%") == NULL snprintf( msg, sizeof msg, @@ -1224,7 +1224,7 @@ def typecheck_expression(ft: FileTypes*, expr: AstExpression*) -> ExpressionType elif expr->kind == AstExpressionKind::AddressOf: ensure_can_take_address(ft->current_fom_types, &expr->operands[0], "the '&' operator cannot be used with %s") temptype = typecheck_expression_not_void(ft, &expr->operands[0])->type - result = get_pointer_type(temptype) + result = temptype->pointer() elif expr->kind == AstExpressionKind::GetVariable: result = find_any_var(ft, expr->varname) diff --git a/compiler/types.jou b/compiler/types.jou index c8c845a5..3abcaca8 100644 --- a/compiler/types.jou +++ b/compiler/types.jou @@ -50,24 +50,61 @@ class Type: return self->kind == TypeKind::SignedInteger or self->kind == TypeKind::UnsignedInteger def is_number_type(self) -> bool: - return is_integer_type(self) or self->kind == TypeKind::FloatingPoint + return self->is_integer_type() or self->kind == TypeKind::FloatingPoint def is_pointer_type(self) -> bool: - return (self->kind == TypeKind::Pointer or self->kind == TypeKind::VoidPointer) + return self->kind == TypeKind::Pointer or self->kind == TypeKind::VoidPointer + + # Returns a type that represents pointer to the original type. + # Result is cached. Don't worry about freeing it. + def pointer(self) -> Type*: + info = self as TypeInfo* + assert self == &info->type # the 'type' field is first member and has 0 bytes offset + + if info->pointer == NULL: + ptr: TypeInfo* = calloc(1, sizeof *ptr) + ptr->type = Type{kind=TypeKind::Pointer, value_type=self} + snprintf(ptr->type.name, sizeof ptr->type.name, "%s*", self->name) + info->pointer = ptr + + return &info->pointer->type + + # Returns a type that represents array where items are the original type. + # Result is cached. Don't worry about freeing it. + def array_type(self, len: int) -> Type*: + info = self as TypeInfo* + assert &info->type == self + + assert len > 0 + for existing = info->arrays; existing < &info->arrays[info->narrays]; existing++: + if (*existing)->type.array.len == len: + return &(*existing)->type + + arr: TypeInfo* = calloc(1, sizeof *arr) + arr->type = Type{kind = TypeKind::Array, array = ArrayType{item_type = self, len = len}} + snprintf(arr->type.name, sizeof arr->type.name, "%s[%d]", self->name, len) + info->arrays = realloc(info->arrays, sizeof(info->arrays[0]) * (info->narrays + 1)) + assert info->arrays != NULL + info->arrays[info->narrays++] = arr + return &arr->type + +# The TypeInfo for type T contains the type T* (if it has been used) +# and all array and pointer types with element type T. class TypeInfo: type: Type - # TODO: pointer should be TypeInfo* but can't be due to compiler bug - pointer: void* # type that represents a pointer to this type, or NULL - # TODO: arrays should be TypeInfo** but can't be due to compiler bug - arrays: void* # types that represent arrays of this type + pointer: TypeInfo* + arrays: TypeInfo** narrays: long - def get_pointer(self) -> TypeInfo*: - return self->pointer + def free_pointer_and_array_types(self) -> None: + if self->pointer != NULL: + free_type(&self->pointer->type) + for arrtype = self->arrays; arrtype < &self->arrays[self->narrays]; arrtype++: + assert &(*arrtype)->type != NULL + free_type(&(*arrtype)->type) + free(self->arrays) - def get_arrays(self) -> TypeInfo**: - return self->arrays # Types are cached into global state. This makes a lot of things easier # because you don't need to copy and free the types everywhere. This is @@ -99,36 +136,6 @@ global floatType: Type* # float (32-bit) global doubleType: Type* # double (64-bit) global voidPtrType: Type* # void* -# The TypeInfo for type T contains the type T* (if it has been used) -# and all array types with element type T. -def free_pointer_and_array_types(info: TypeInfo*) -> None: - free_type(&info->get_pointer()->type) - for arrtype = info->get_arrays(); arrtype < &info->get_arrays()[info->narrays]; arrtype++: - free_type(&(*arrtype)->type) - free(info->arrays) - -def free_type(t: Type*) -> None: - if t != NULL: - if t->kind == TypeKind::Class: - for m = t->classdata.methods; m < &t->classdata.methods[t->classdata.nmethods]; m++: - free_signature(m) - free(t->classdata.fields) - free(t->classdata.methods) - - ti = t as TypeInfo* - assert &ti->type == t - - free_pointer_and_array_types(ti) - free(t) - -def free_global_type_state() -> None: - free_pointer_and_array_types(&global_type_state.boolean) - free_pointer_and_array_types(&global_type_state.floater) - free_pointer_and_array_types(&global_type_state.doublelele) - free_pointer_and_array_types(&global_type_state.voidptr) - for size = 8; size <= 64; size *= 2: - for is_signed = 0; is_signed <= 1; is_signed++: - free_pointer_and_array_types(&global_type_state.integers[size][is_signed]) def init_types() -> None: memset(&global_type_state, 0, sizeof(global_type_state)) @@ -162,48 +169,40 @@ def init_types() -> None: strcpy(global_type_state.integers[32][1].type.name, "int") strcpy(global_type_state.integers[64][1].type.name, "long") -def get_integer_type(size_in_bits: int, is_signed: bool) -> Type*: - assert size_in_bits==8 or size_in_bits==16 or size_in_bits==32 or size_in_bits==64 - return &global_type_state.integers[size_in_bits][is_signed as int].type - -def get_pointer_type(t: Type*) -> Type*: - info = t as TypeInfo* - assert t == &info->type # the 'type' field is first member and has 0 bytes offset - if info->pointer == NULL: - ptr: TypeInfo* = calloc(1, sizeof *ptr) - ptr->type = Type{kind=TypeKind::Pointer, value_type=t} - snprintf(ptr->type.name, sizeof ptr->type.name, "%s*", t->name) - info->pointer = ptr +# Usually you don't need to free a type. This is in a function to make you +# think twice about it. +def free_type(t: Type*) -> None: + assert t != NULL + if t->kind == TypeKind::Class: + for m = t->classdata.methods; m < &t->classdata.methods[t->classdata.nmethods]; m++: + free_signature(m) + free(t->classdata.fields) + free(t->classdata.methods) - return &info->get_pointer()->type + ti = t as TypeInfo* + assert &ti->type == t -def get_array_type(t: Type*, len: int) -> Type*: - info = t as TypeInfo* - assert &info->type == t + ti->free_pointer_and_array_types() + free(t) - assert len > 0 - for existing = info->get_arrays(); existing < &info->get_arrays()[info->narrays]; existing++: - if (*existing)->type.array.len == len: - return &(*existing)->type - arr: TypeInfo* = calloc(1, sizeof *arr) - arr->type = Type{kind = TypeKind::Array, array = ArrayType{item_type = t, len = len}} - snprintf(arr->type.name, sizeof arr->type.name, "%s[%d]", t->name, len) - info->arrays = realloc(info->arrays, sizeof(info->get_arrays()[0]) * (info->narrays + 1)) - assert info->arrays != NULL - info->get_arrays()[info->narrays++] = arr - return &arr->type +def free_global_type_state() -> None: + global_type_state.boolean.free_pointer_and_array_types() + global_type_state.floater.free_pointer_and_array_types() + global_type_state.doublelele.free_pointer_and_array_types() + global_type_state.voidptr.free_pointer_and_array_types() + for size = 8; size <= 64; size *= 2: + for is_signed = 0; is_signed <= 1; is_signed++: + global_type_state.integers[size][is_signed].free_pointer_and_array_types() -def is_integer_type(t: Type*) -> bool: - return t->kind == TypeKind::SignedInteger or t->kind == TypeKind::UnsignedInteger -def is_number_type(t: Type*) -> bool: - return is_integer_type(t) or t->kind == TypeKind::FloatingPoint +def get_integer_type(size_in_bits: int, is_signed: bool) -> Type*: + assert size_in_bits==8 or size_in_bits==16 or size_in_bits==32 or size_in_bits==64 + return &global_type_state.integers[size_in_bits][is_signed as int].type -def is_pointer_type(t: Type*) -> bool: - return (t->kind == TypeKind::Pointer or t->kind == TypeKind::VoidPointer) +# TODO: move out def type_of_constant(c: Constant*) -> Type*: if c->kind == ConstantKind::EnumMember: return c->enum_member.enumtype @@ -216,11 +215,12 @@ def type_of_constant(c: Constant*) -> Type*: if c->kind == ConstantKind::Bool: return boolType if c->kind == ConstantKind::String: - return get_pointer_type(byteType) + return byteType->pointer() if c->kind == ConstantKind::Integer: return get_integer_type(c->integer.size_in_bits, c->integer.is_signed) assert False + def create_opaque_class(name: byte*) -> Type*: result: TypeInfo* = calloc(1, sizeof *result) result->type = Type{kind = TypeKind::OpaqueClass} @@ -243,6 +243,7 @@ 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: @@ -252,6 +253,7 @@ def get_self_class(sig: Signature*) -> Type*: 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 @@ -298,6 +300,7 @@ def signature_to_string(sig: Signature*, include_return_type: bool, include_self return result +# TODO: move out def copy_signature(sig: Signature*) -> Signature: result = *sig