Add Struct types
This commit is contained in:
parent
66653553a5
commit
29fd757517
@ -149,4 +149,8 @@ namespace AST {
|
|||||||
}
|
}
|
||||||
return out.str();
|
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 codegen(codegen::Builder& builder, codegen::Scope& scope) override;
|
||||||
virtual void typecheck(typecheck::State& state, typecheck::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
|
#endif
|
||||||
@ -503,6 +503,16 @@ namespace AST {
|
|||||||
|
|
||||||
builder.block = nullptr;
|
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 {
|
namespace types {
|
||||||
@ -542,6 +552,14 @@ namespace types {
|
|||||||
}
|
}
|
||||||
|
|
||||||
llvm::Type* StructType::codegen(codegen::Builder& builder, codegen::TypeMap& structs) {
|
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) {
|
if (this->m_fields) {
|
||||||
std::vector<llvm::Type*> fields{};
|
std::vector<llvm::Type*> fields{};
|
||||||
for (auto& field : *this->m_fields) {
|
for (auto& field : *this->m_fields) {
|
||||||
@ -554,11 +572,14 @@ namespace types {
|
|||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
// llvm::Type* StructRef::codegen(codegen::Builder&, codegen::TypeMap& structs) {
|
||||||
return structs[this->m_name];
|
// 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 {
|
namespace typecheck {
|
||||||
struct Scope {
|
struct Scope {
|
||||||
std::map<std::string, std::shared_ptr<types::Type>> symbols;
|
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;
|
std::optional<std::shared_ptr<types::Type>> return_ty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -198,20 +198,20 @@ namespace types {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string StructRef::formatted() {
|
// std::string StructRef::formatted() {
|
||||||
std::stringstream out{ "" };
|
// std::stringstream out{ "" };
|
||||||
out << "struct(ref) " << this->m_name;
|
// out << "struct(ref) " << this->m_name;
|
||||||
return out.str();
|
// return out.str();
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
// std::pair<llvm::Value*, std::shared_ptr<Type>> StructRef::load(codegen::Builder&, llvm::Value* ptr, codegen::TypeMap&) {
|
||||||
auto self = std::make_shared<StructRef>(*this);
|
// auto self = std::make_shared<StructRef>(*this);
|
||||||
return std::pair(ptr, self);
|
// return std::pair(ptr, self);
|
||||||
}
|
// }
|
||||||
|
|
||||||
uint32_t StructRef::size() {
|
// uint32_t StructRef::size() {
|
||||||
return this->m_referred->size();
|
// return this->m_referred->size();
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
|
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
|
||||||
if (type1->m_kind != type2->m_kind)
|
if (type1->m_kind != type2->m_kind)
|
||||||
|
|||||||
32
src/types.h
32
src/types.h
@ -12,6 +12,7 @@ namespace types {
|
|||||||
Function,
|
Function,
|
||||||
Pointer,
|
Pointer,
|
||||||
Array,
|
Array,
|
||||||
|
Struct,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FundamentalTypeKind {
|
enum FundamentalTypeKind {
|
||||||
@ -103,9 +104,10 @@ namespace types {
|
|||||||
public:
|
public:
|
||||||
std::optional<std::string> m_name;
|
std::optional<std::string> m_name;
|
||||||
std::optional<std::vector<StructField>> m_fields;
|
std::optional<std::vector<StructField>> m_fields;
|
||||||
|
bool m_is_ref;
|
||||||
|
|
||||||
StructType(std::optional<std::string> name, std::optional<std::vector<StructField>> fields)
|
StructType(std::optional<std::string> name, std::optional<std::vector<StructField>> fields, bool is_ref)
|
||||||
: Type(TypeKind::Array), m_name{ name }, m_fields{ fields } {
|
: Type(TypeKind::Struct), m_name{ name }, m_fields{ fields }, m_is_ref{ is_ref } {
|
||||||
}
|
}
|
||||||
virtual ~StructType() override = default;
|
virtual ~StructType() override = default;
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
@ -114,20 +116,20 @@ namespace types {
|
|||||||
virtual uint32_t size() override;
|
virtual uint32_t size() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructRef : public Type {
|
// class StructRef : public Type {
|
||||||
public:
|
// public:
|
||||||
std::string m_name;
|
// std::string m_name;
|
||||||
std::shared_ptr<types::Type> m_referred;
|
// std::shared_ptr<types::Type> m_referred;
|
||||||
|
|
||||||
StructRef(std::string name, std::shared_ptr<types::Type> referred)
|
// StructRef(std::string name, std::shared_ptr<types::Type> referred)
|
||||||
: Type(TypeKind::Array), m_name{ name }, m_referred{ referred } {
|
// : Type(TypeKind::StructRef), m_name{ name }, m_referred{ referred } {
|
||||||
}
|
// }
|
||||||
virtual ~StructRef() override = default;
|
// virtual ~StructRef() override = default;
|
||||||
virtual std::string formatted() override;
|
// virtual std::string formatted() override;
|
||||||
virtual llvm::Type* codegen(codegen::Builder& builder, codegen::TypeMap& structs) 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 std::pair<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr, codegen::TypeMap& structs) override;
|
||||||
virtual uint32_t size() override;
|
// virtual uint32_t size() override;
|
||||||
};
|
// };
|
||||||
|
|
||||||
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2);
|
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2);
|
||||||
}
|
}
|
||||||
|
|||||||
4
test.c
4
test.c
@ -10,6 +10,10 @@ void change_first(char otus[5]) {
|
|||||||
otus[0] = 115;
|
otus[0] = 115;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Otus {
|
||||||
|
int field
|
||||||
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
char text[29] = "10th fibonacci number is %d!";
|
char text[29] = "10th fibonacci number is %d!";
|
||||||
printf(text, fibonacci(10));
|
printf(text, fibonacci(10));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user