From 98a8b6831584efa417eae95acd16249e1f9fe53e Mon Sep 17 00:00:00 2001 From: SaptakBhoumik Date: Wed, 22 Jun 2022 01:51:51 +0530 Subject: [PATCH] fix add union tyoe --- Peregrine/analyzer/typeChecker.cpp | 15 ++++--- Peregrine/analyzer/typeChecker.hpp | 1 - Peregrine/ast/types.cpp | 72 +++++++++++++++++++++++++++++- Peregrine/ast/types.hpp | 19 ++++++++ Peregrine/utils/symbolTable.hpp | 12 +++++ 5 files changed, 110 insertions(+), 9 deletions(-) diff --git a/Peregrine/analyzer/typeChecker.cpp b/Peregrine/analyzer/typeChecker.cpp index 8b48f123..76f70ce3 100644 --- a/Peregrine/analyzer/typeChecker.cpp +++ b/Peregrine/analyzer/typeChecker.cpp @@ -425,8 +425,9 @@ bool TypeChecker::visit(const ast::DotExpression& node) { if(node.owner()->type()==ast::KAstIdentifier&&node.referenced()->type()==ast::KAstIdentifier){ auto name=identifierName(node.owner()); auto ref=identifierName(node.referenced()); - if(m_enumMap.contains(name)){ - auto type=m_enumMap[name]; + auto enum_map=m_env->getEnumMap(); + if(enum_map.contains(name)){ + auto type=enum_map[name]; auto _enum=std::dynamic_pointer_cast(type); auto items=_enum->getItem(); if(std::count(items.begin(),items.end(),ref)){ @@ -458,8 +459,9 @@ bool TypeChecker::visit(const ast::IdentifierExpression& node) { } bool TypeChecker::visit(const ast::TypeExpression& node) { - if(m_enumMap.contains(node.value())){ - m_result=m_enumMap[node.value()]; + auto enum_map = m_env->getEnumMap(); + if(enum_map.contains(node.value())){ + m_result=enum_map[node.value()]; } else if (!identifierToTypeMap.count(node.value())) { auto type = m_env->get(node.value()); @@ -580,11 +582,12 @@ bool TypeChecker::visit(const ast::EnumLiteral& node) { values.push_back(itemName); } } - if(m_enumMap.contains(name)){ + auto enum_map= m_env->getEnumMap(); + if(enum_map.contains(name)){ add_error(node.token(), "Redefination of enum: " + name); } else{ - m_enumMap[name] = types::TypeProducer::enumT(name, values); + m_env->add_enum(name,types::TypeProducer::enumT(name, values)); } return true; } diff --git a/Peregrine/analyzer/typeChecker.hpp b/Peregrine/analyzer/typeChecker.hpp index 82389a60..75944bbd 100644 --- a/Peregrine/analyzer/typeChecker.hpp +++ b/Peregrine/analyzer/typeChecker.hpp @@ -86,7 +86,6 @@ class TypeChecker : public ast::AstVisitor { // the function whose body is being currently checked std::shared_ptr m_currentFunction; - std::map m_enumMap;//TODO:Nested enum TypePtr m_returnType=NULL;//current return type }; } diff --git a/Peregrine/ast/types.cpp b/Peregrine/ast/types.cpp index 72248666..25efc86d 100644 --- a/Peregrine/ast/types.cpp +++ b/Peregrine/ast/types.cpp @@ -1,4 +1,6 @@ //TODO: handle user defined types like `type name=int` properly +//int==user_defined_type +//should be checked properly #include "types.hpp" #include "lexer/tokens.hpp" #include "ast.hpp" @@ -400,7 +402,7 @@ bool PointerType::isCastableTo(const Type& type) const { switch (type.category()) { case TypeCategory::UserDefined: case TypeCategory::Integer: - case TypeCategory::Pointer: + case TypeCategory::Pointer://TODO:Check if it inherits from the same basetype break; default: @@ -776,11 +778,77 @@ std::string EnumType::getCurrValue() const{ bool EnumType::operator==(const Type& type) const{ if(type.category()==TypeCategory::Enum){ auto& enumType=dynamic_cast(type); - return m_name==enumType.getName(); + auto item=enumType.getItem(); + if(m_name==enumType.getName()&&item.size()==m_items.size()){ + for(size_t i=0; i items){ + m_name=name; + m_items=items; +} + +ast::AstNodePtr UnionTypeDef::getTypeAst() const{ + return std::make_shared((Token){},m_name.c_str()); +} + +TypeCategory UnionTypeDef::category() const{ + return TypeCategory::Union; +} + +bool UnionTypeDef::isConvertibleTo(const Type& type) const{ + return false; +} + +bool UnionTypeDef::isCastableTo(const Type& type) const{ + switch(type.category()){ + case TypeCategory::Pointer: + return true; + default: + return false; + } +} + +std::string UnionTypeDef::stringify() const{ + return m_name; +} + +std::map UnionTypeDef::getItem() const{ + return m_items; +} + +std::string UnionTypeDef::getName() const{ + return m_name; +} + +bool UnionTypeDef::operator==(const Type& type) const{ + if(type.category() == TypeCategory::Union){ + auto& unionType=dynamic_cast(type); + auto items=unionType.getItem(); + if(m_name==unionType.getName()&&items.size()==m_items.size()){ + for(auto& item : items){ + if(m_items.contains(item.first)){ + auto pos = m_items.find(item.first); + if(pos->second!=item.second){ + return false; + } + } + else{ + return false; + } + } + } + } + return false; +} std::array TypeProducer::m_integer = { std::make_shared(IntType::IntSizes::Int8), diff --git a/Peregrine/ast/types.hpp b/Peregrine/ast/types.hpp index 654c5efb..3d6d98d8 100644 --- a/Peregrine/ast/types.hpp +++ b/Peregrine/ast/types.hpp @@ -29,6 +29,7 @@ enum TypeCategory { MultipleReturn, Enum, Void, + Union }; class Type; @@ -283,6 +284,24 @@ class EnumType : public Type { std::string m_name; }; +class UnionTypeDef : public Type { + public: + UnionTypeDef(std::string name,std::map items); + + ast::AstNodePtr getTypeAst() const; + TypeCategory category() const; + bool isConvertibleTo(const Type& type) const; + bool isCastableTo(const Type& type) const; + std::string stringify() const; + std::map getItem() const; + std::string getName() const; + + bool operator==(const Type& type) const; + private: + std::map m_items; + std::string m_name; +}; + class TypeProducer { static std::array m_integer; static std::array m_decimal; diff --git a/Peregrine/utils/symbolTable.hpp b/Peregrine/utils/symbolTable.hpp index b1ad4f2a..be4a2c1c 100644 --- a/Peregrine/utils/symbolTable.hpp +++ b/Peregrine/utils/symbolTable.hpp @@ -15,10 +15,14 @@ template class SymbolTable { std::map m_symbols; std::shared_ptr> m_parent; + std::map m_enumMap; public: SymbolTable(std::shared_ptr parent) { m_parent = parent; + if(m_parent!=nullptr){ + m_enumMap = parent->getEnumMap(); + } } std::optional get(std::string name) { @@ -33,6 +37,14 @@ class SymbolTable { return m_symbols[name]; } + std::map getEnumMap(){ + return m_enumMap; + } + + void add_enum(std::string key,T value){ + m_enumMap[key]=value; + } + bool set(std::string name, T value) { if (get(name)) { return false; // the symbol has been defined already