diff --git a/src/ast.cpp b/src/ast.cpp index 5207d9b..3e68664 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -149,4 +149,8 @@ namespace AST { } return out.str(); } + + std::string TopLevelTypedef::formatted() { + return this->m_ty->formatted(); + } } \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 4eb27ef..5538827 100644 --- a/src/ast.h +++ b/src/ast.h @@ -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 m_ty; + public: + TopLevelTypedef( + token::Metadata meta, + std::shared_ptr 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 \ No newline at end of file diff --git a/src/codegen.cpp b/src/codegen.cpp index aacd07f..6a62a71 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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(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 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]; + // } } \ No newline at end of file diff --git a/src/typechecker.cpp b/src/typechecker.cpp index e4b8a31..37ff29b 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -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(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)); + } + } + } + } } \ No newline at end of file diff --git a/src/typechecker.h b/src/typechecker.h index 089f79c..401b9cf 100644 --- a/src/typechecker.h +++ b/src/typechecker.h @@ -11,6 +11,7 @@ namespace typecheck { struct Scope { std::map> symbols; + std::map> structs; std::optional> return_ty; }; diff --git a/src/types.cpp b/src/types.cpp index 69726bf..306b3e2 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -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> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { - auto self = std::make_shared(*this); - return std::pair(ptr, self); - } + // std::pair> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) { + // auto self = std::make_shared(*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 type1, std::shared_ptr type2) { if (type1->m_kind != type2->m_kind) diff --git a/src/types.h b/src/types.h index 604d85f..e9f923a 100644 --- a/src/types.h +++ b/src/types.h @@ -12,6 +12,7 @@ namespace types { Function, Pointer, Array, + Struct, }; enum FundamentalTypeKind { @@ -103,9 +104,10 @@ namespace types { public: std::optional m_name; std::optional> m_fields; + bool m_is_ref; - StructType(std::optional name, std::optional> fields) - : Type(TypeKind::Array), m_name{ name }, m_fields{ fields } { + StructType(std::optional name, std::optional> 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 m_referred; + // class StructRef : public Type { + // public: + // std::string m_name; + // std::shared_ptr m_referred; - StructRef(std::string name, std::shared_ptr 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> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; - virtual uint32_t size() override; - }; + // StructRef(std::string name, std::shared_ptr 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> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override; + // virtual uint32_t size() override; + // }; bool types_equal(std::shared_ptr type1, std::shared_ptr type2); } diff --git a/test.c b/test.c index aef3f68..77acb4a 100644 --- a/test.c +++ b/test.c @@ -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));