Add Struct types
This commit is contained in:
parent
66653553a5
commit
29fd757517
@ -149,4 +149,8 @@ namespace AST {
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string TopLevelTypedef::formatted() {
|
||||
return this->m_ty->formatted();
|
||||
}
|
||||
}
|
||||
16
src/ast.h
16
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<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
|
||||
@ -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];
|
||||
// }
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
32
src/types.h
32
src/types.h
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user