diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/expr.hpp | 6 | ||||
-rw-r--r-- | src/hir/type.cpp | 12 | ||||
-rw-r--r-- | src/hir/type.hpp | 8 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 126 |
4 files changed, 127 insertions, 25 deletions
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index eb1b43a5..bd952348 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -392,11 +392,17 @@ struct ExprNode_Literal: if( e.m_type != ::HIR::CoreType::Str ) { m_res_type = ::HIR::TypeRef::Data::make_Primitive(e.m_type); } + else { + m_res_type.m_data.as_Infer().ty_class = ::HIR::InferClass::Integer; + } ), (Float, if( e.m_type != ::HIR::CoreType::Str ) { m_res_type = ::HIR::TypeRef::Data::make_Primitive(e.m_type); } + else { + m_res_type.m_data.as_Infer().ty_class = ::HIR::InferClass::Float; + } ), (Boolean, m_res_type = ::HIR::TypeRef::Data::make_Primitive( ::HIR::CoreType::Bool ); diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 61ba9419..acd5ab1c 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -42,7 +42,17 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const TU_MATCH(::HIR::TypeRef::Data, (m_data), (e), (Infer, os << "_"; - if( e.index != ~0u ) os << "/*" << e.index << "*/"; + if( e.index != ~0u || e.ty_class != ::HIR::InferClass::None ) { + os << "/*"; + if(e.index != ~0u) os << e.index; + switch(e.ty_class) + { + case ::HIR::InferClass::None: break; + case ::HIR::InferClass::Float: os << ":f"; break; + case ::HIR::InferClass::Integer:os << ":i"; break; + } + os << "*/"; + } ), (Diverge, os << "!"; diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 573cad70..01254270 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -15,6 +15,13 @@ class Enum; class TypeRef; +enum class InferClass +{ + None, + Integer, + Float, +}; + enum class CoreType { Usize, Isize, @@ -73,6 +80,7 @@ public: TAGGED_UNION(Data, Infer, (Infer, struct { unsigned int index = ~0u; + InferClass ty_class = InferClass::None; }), (Diverge, struct {}), (Primitive, ::HIR::CoreType), diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index de0d11e3..06332d49 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -190,14 +190,13 @@ namespace { }, false); } + struct IVar { - bool deleted; - unsigned int alias; - ::std::unique_ptr< ::HIR::TypeRef> type; + unsigned int alias; // If not ~0, this points to another ivar + ::std::unique_ptr< ::HIR::TypeRef> type; // Type (only nullptr if alias!=0) IVar(): - deleted(false), alias(~0u), type(new ::HIR::TypeRef()) {} @@ -295,6 +294,7 @@ namespace { (Infer, if( e.index == ~0u ) { e.index = this->new_ivar(); + this->m_ivars[e.index].type->m_data.as_Infer().ty_class = e.ty_class; } ), (Diverge, @@ -1370,7 +1370,6 @@ namespace { } else { assert(!"Can't delete an ivar after it's been used"); - m_ivars[index].deleted = true; } } ::HIR::TypeRef new_ivar_tr() { @@ -1379,24 +1378,6 @@ namespace { return rv; } - IVar& get_pointed_ivar(unsigned int slot) const - { - auto index = slot; - unsigned int count = 0; - assert(index < m_ivars.size()); - while( m_ivars.at(index).is_alias() ) { - assert( m_ivars.at(index).deleted == false ); - index = m_ivars.at(index).alias; - - if( count >= m_ivars.size() ) { - this->dump(); - BUG(Span(), "Loop detected in ivar list when starting at " << slot << ", current is " << index); - } - count ++; - } - assert( m_ivars.at(index).deleted == false ); - return const_cast<IVar&>(m_ivars.at(index)); - } ::HIR::TypeRef& get_type(::HIR::TypeRef& type) { TU_IFLET(::HIR::TypeRef::Data, type.m_data, Infer, e, @@ -1418,18 +1399,70 @@ namespace { } } + void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct) + { + switch(ic) + { + case ::HIR::InferClass::None: + break; + case ::HIR::InferClass::Float: + switch(ct) + { + case ::HIR::CoreType::F32: case ::HIR::CoreType::F64: + break; + default: + ERROR(sp, E0000, "Type unificiation of integer literal with non-integer - " << type); + } + break; + case ::HIR::InferClass::Integer: + switch(ct) + { + case ::HIR::CoreType::I8: case ::HIR::CoreType::U8: + case ::HIR::CoreType::I16: case ::HIR::CoreType::U16: + case ::HIR::CoreType::I32: case ::HIR::CoreType::U32: + case ::HIR::CoreType::I64: case ::HIR::CoreType::U64: + case ::HIR::CoreType::Isize: case ::HIR::CoreType::Usize: + break; + default: + ERROR(sp, E0000, "Type unificiation of integer literal with non-integer - " << type); + } + break; + } + } + void set_ivar_to(unsigned int slot, ::HIR::TypeRef type) { + auto sp = Span(); auto& root_ivar = this->get_pointed_ivar(slot); + DEBUG("set_ivar_to(" << slot << " { " << *root_ivar.type << " }, " << type << ")"); - // If the left type wasn't a reference to an ivar, store it in the righthand ivar + // If the left type was '_', alias the right to it TU_IFLET(::HIR::TypeRef::Data, type.m_data, Infer, l_e, assert( l_e.index != slot ); DEBUG("Set IVar " << slot << " = @" << l_e.index); + + if( l_e.ty_class != ::HIR::InferClass::None ) { + TU_MATCH_DEF(::HIR::TypeRef::Data, (root_ivar.type->m_data), (e), + ( + ERROR(sp, E0000, "Type unificiation of literal with invalid type - " << *root_ivar.type); + ), + (Primitive, + check_type_class_primitive(sp, type, l_e.ty_class, e); + ), + (Infer, + // TODO: Check for right having a ty_class + if( e.ty_class != ::HIR::InferClass::None && e.ty_class != l_e.ty_class ) { + ERROR(sp, E0000, "Unifying types with mismatching literal classes"); + } + ) + ) + } + root_ivar.alias = l_e.index; root_ivar.type.reset(); ) else { + // Otherwise, store left in right's slot DEBUG("Set IVar " << slot << " = " << type); root_ivar.type = box$( mv$(type) ); } @@ -1439,16 +1472,61 @@ namespace { void ivar_unify(unsigned int left_slot, unsigned int right_slot) { + auto sp = Span(); if( left_slot != right_slot ) { + auto& left_ivar = this->get_pointed_ivar(left_slot); + // TODO: Assert that setting this won't cause a loop. auto& root_ivar = this->get_pointed_ivar(right_slot); + + TU_IFLET(::HIR::TypeRef::Data, root_ivar.type->m_data, Infer, re, + if(re.ty_class != ::HIR::InferClass::None) { + TU_MATCH_DEF(::HIR::TypeRef::Data, (left_ivar.type->m_data), (le), + ( + ERROR(sp, E0000, "Type unificiation of literal with invalid type - " << *left_ivar.type); + ), + (Infer, + if( le.ty_class != ::HIR::InferClass::None && le.ty_class != re.ty_class ) + { + ERROR(sp, E0000, "Unifying types with mismatching literal classes"); + } + le.ty_class = re.ty_class; + ), + (Primitive, + check_type_class_primitive(sp, *left_ivar.type, re.ty_class, le); + ) + ) + } + ) + else { + BUG(sp, "Unifying over a concrete type - " << *root_ivar.type); + } + root_ivar.alias = left_slot; root_ivar.type.reset(); this->mark_change(); } } + + private: + IVar& get_pointed_ivar(unsigned int slot) const + { + auto index = slot; + unsigned int count = 0; + assert(index < m_ivars.size()); + while( m_ivars.at(index).is_alias() ) { + index = m_ivars.at(index).alias; + + if( count >= m_ivars.size() ) { + this->dump(); + BUG(Span(), "Loop detected in ivar list when starting at " << slot << ", current is " << index); + } + count ++; + } + return const_cast<IVar&>(m_ivars.at(index)); + } }; // Enumerate inferrence variables (most of them) in the expression tree |