Add Struct types

This commit is contained in:
Sofia 2026-04-15 18:40:26 +03:00
parent 66653553a5
commit 29fd757517
8 changed files with 96 additions and 31 deletions

View File

@ -149,4 +149,8 @@ namespace AST {
}
return out.str();
}
std::string TopLevelTypedef::formatted() {
return this->m_ty->formatted();
}
}

View File

@ -373,6 +373,22 @@ namespace AST {
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override;
};
class TopLevelTypedef : public TopLevelStatement {
private:
std::shared_ptr<types::Type> m_ty;
public:
TopLevelTypedef(
token::Metadata meta,
std::shared_ptr<types::Type> type)
: TopLevelStatement{ meta }
, m_ty{ type } {
}
virtual ~TopLevelTypedef() override = default;
virtual std::string formatted() override;
virtual void codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) override;
};
}
#endif

View File

@ -503,6 +503,16 @@ namespace AST {
builder.block = nullptr;
}
void TopLevelTypedef::codegen(codegen::Builder& builder, codegen::Scope& scope) {
auto ty = this->m_ty->codegen(builder, scope.structs);
if (this->m_ty->m_kind == types::TypeKind::Struct) {
auto struct_ty = dynamic_cast<types::StructType*>(this->m_ty.get());
if (struct_ty->m_name) {
scope.structs[*struct_ty->m_name] = ty;
}
}
}
}
namespace types {
@ -542,6 +552,14 @@ namespace types {
}
llvm::Type* StructType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) {
if (this->m_is_ref) {
if (this->m_name) {
return structs[*this->m_name];
}
else {
throw CompileError("reference to nonexistant struct", {});
}
}
if (this->m_fields) {
std::vector<llvm::Type*> fields{};
for (auto& field : *this->m_fields) {
@ -554,11 +572,14 @@ namespace types {
return ty;
}
else {
return llvm::StructType::get(*builder.context);
auto ty = llvm::StructType::get(*builder.context);
if (this->m_name)
ty->setName(*this->m_name);
return ty;
}
}
llvm::Type* StructRef::codegen(codegen::Builder&, codegen::TypeMap& structs) {
return structs[this->m_name];
}
// llvm::Type* StructRef::codegen(codegen::Builder&, codegen::TypeMap& structs) {
// return structs[this->m_name];
// }
}

View File

@ -428,4 +428,21 @@ namespace AST {
}
}
}
void TopLevelTypedef::typecheck(typecheck::State& state, typecheck::Scope& scope) {
if (this->m_ty->m_kind == types::TypeKind::Struct) {
auto struct_ty = dynamic_cast<types::StructType*>(this->m_ty.get());
if (struct_ty->m_is_ref) {
return;
}
if (struct_ty->m_name) {
if (scope.structs.find(*struct_ty->m_name) == scope.structs.end()) {
scope.structs[*struct_ty->m_name] = this->m_ty;
}
else {
state.errors.push_back(CompileError("Struct " + *struct_ty->m_name + " declared twice!", this->m_meta));
}
}
}
}
}

View File

@ -11,6 +11,7 @@
namespace typecheck {
struct Scope {
std::map<std::string, std::shared_ptr<types::Type>> symbols;
std::map<std::string, std::shared_ptr<types::Type>> structs;
std::optional<std::shared_ptr<types::Type>> return_ty;
};

View File

@ -198,20 +198,20 @@ namespace types {
}
std::string StructRef::formatted() {
std::stringstream out{ "" };
out << "struct(ref) " << this->m_name;
return out.str();
}
// std::string StructRef::formatted() {
// std::stringstream out{ "" };
// out << "struct(ref) " << this->m_name;
// return out.str();
// }
std::pair<llvm::Value*, std::shared_ptr<Type>> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
auto self = std::make_shared<StructRef>(*this);
return std::pair(ptr, self);
}
// std::pair<llvm::Value*, std::shared_ptr<Type>> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
// auto self = std::make_shared<StructRef>(*this);
// return std::pair(ptr, self);
// }
uint32_t StructRef::size() {
return this->m_referred->size();
}
// uint32_t StructRef::size() {
// return this->m_referred->size();
// }
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
if (type1->m_kind != type2->m_kind)

View File

@ -12,6 +12,7 @@ namespace types {
Function,
Pointer,
Array,
Struct,
};
enum FundamentalTypeKind {
@ -103,9 +104,10 @@ namespace types {
public:
std::optional<std::string> m_name;
std::optional<std::vector<StructField>> m_fields;
bool m_is_ref;
StructType(std::optional<std::string> name, std::optional<std::vector<StructField>> fields)
: Type(TypeKind::Array), m_name{ name }, m_fields{ fields } {
StructType(std::optional<std::string> name, std::optional<std::vector<StructField>> fields, bool is_ref)
: Type(TypeKind::Struct), m_name{ name }, m_fields{ fields }, m_is_ref{ is_ref } {
}
virtual ~StructType() override = default;
virtual std::string formatted() override;
@ -114,20 +116,20 @@ namespace types {
virtual uint32_t size() override;
};
class StructRef : public Type {
public:
std::string m_name;
std::shared_ptr<types::Type> m_referred;
// class StructRef : public Type {
// public:
// std::string m_name;
// std::shared_ptr<types::Type> m_referred;
StructRef(std::string name, std::shared_ptr<types::Type> referred)
: Type(TypeKind::Array), m_name{ name }, m_referred{ referred } {
}
virtual ~StructRef() override = default;
virtual std::string formatted() override;
virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override;
virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
virtual uint32_t size() override;
};
// StructRef(std::string name, std::shared_ptr<types::Type> referred)
// : Type(TypeKind::StructRef), m_name{ name }, m_referred{ referred } {
// }
// virtual ~StructRef() override = default;
// virtual std::string formatted() override;
// virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) override;
// virtual std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
// virtual uint32_t size() override;
// };
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2);
}

4
test.c
View File

@ -10,6 +10,10 @@ void change_first(char otus[5]) {
otus[0] = 115;
}
struct Otus {
int field
};
int main() {
char text[29] = "10th fibonacci number is %d!";
printf(text, fibonacci(10));