summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/expr.hpp6
-rw-r--r--src/hir/type.cpp12
-rw-r--r--src/hir/type.hpp8
-rw-r--r--src/hir_typeck/expr.cpp126
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