summaryrefslogtreecommitdiff
path: root/src/types.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-08-24 22:50:49 +0800
committerJohn Hodge <tpg@mutabah.net>2015-08-24 22:50:49 +0800
commit7156d7d274184a085452a58ee3398d06024112b5 (patch)
tree874e8ca17500870c7aeb8e440e9d09d982284593 /src/types.cpp
parentedbd5db807dd66876ad25e0b67a37a567187f076 (diff)
downloadmrust-7156d7d274184a085452a58ee3398d06024112b5.tar.gz
BROKEN - Halfway through a rewrite of type handling
Diffstat (limited to 'src/types.cpp')
-rw-r--r--src/types.cpp800
1 files changed, 472 insertions, 328 deletions
diff --git a/src/types.cpp b/src/types.cpp
index 25c2f159..9924ff0f 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -34,41 +34,59 @@ const char* coretype_name(const eCoreType ct ) {
return "NFI";
}
+Type_Function::Type_Function(const Type_Function& other):
+ is_unsafe(other.is_unsafe),
+ m_abi(other.m_abi),
+ m_rettype( box$( TypeRef(*other.m_rettype) ) ),
+ m_arg_types(other.m_arg_types)
+{
+}
+
+Ordering Type_Function::ord(const Type_Function& x) const
+{
+ Ordering rv;
+
+ rv = ::ord(m_abi, x.m_abi);
+ if(rv != OrdEqual) return rv;
+ rv = ::ord(m_arg_types, x.m_arg_types);
+ if(rv != OrdEqual) return rv;
+ return (*m_rettype).ord( *x.m_rettype );
+}
+
/// Replace this type reference with a dereferenced version
bool TypeRef::deref(bool is_implicit)
{
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
- throw ::std::runtime_error("Dereferencing ! - bugcheck");
- case TypeRef::ANY:
- // TODO: Check if the _ is bounded by Deref<Output=?>, if so use that
- throw ::std::runtime_error("Dereferencing _");
- break;
- case TypeRef::UNIT:
- throw ::std::runtime_error("Dereferencing ()");
- case TypeRef::PRIMITIVE:
- throw ::std::runtime_error("Dereferencing a primtive type");
- case TypeRef::GENERIC:
- throw ::std::runtime_error("Dereferencing a generic");
- case TypeRef::FUNCTION:
- throw ::std::runtime_error("Dereferencing a function");
- case TypeRef::REFERENCE:
- *this = m_inner_types[0];
+ case TypeData::None: throw ::std::runtime_error("Dereferencing ! - bugcheck");
+ case TypeData::Any: throw ::std::runtime_error("Dereferencing _");
+ case TypeData::Unit: throw ::std::runtime_error("Dereferencing ()");
+ case TypeData::Primitive: throw ::std::runtime_error("Dereferencing a primtive type");
+ case TypeData::Function: throw ::std::runtime_error("Dereferencing a function");
+
+ case TypeData::Generic:
+ // TODO: Check for Deref<Output=?> bound
+ throw ::std::runtime_error("TODO: Check for a Deref bound on generic");
+ _(Borrow,
+ *this = *ent.inner;
return true;
- case TypeRef::POINTER:
+ )
+ _(Pointer,
// raw pointers can't be implicitly dereferenced
if( is_implicit )
return false;
- *this = m_inner_types[0];
+ *this = *ent.inner;
return true;
- case TypeRef::TUPLE:
- case TypeRef::ARRAY:
- case TypeRef::PATH:
+ )
+ case TypeData::Tuple:
+ case TypeData::Array:
+ case TypeData::Path:
throw ::std::runtime_error("TODO: Search for an impl of Deref");
- case TypeRef::MULTIDST:
+ case TypeData::TraitObject:
throw ::std::runtime_error("TODO: TypeRef::deref on MULTIDST");
}
+ #undef _
throw ::std::runtime_error("BUGCHECK: Fell off end of TypeRef::deref");
}
@@ -84,15 +102,15 @@ void TypeRef::merge_with(const TypeRef& other)
//}
// If this is a wildcard, then replace with the other type
- if( m_class == TypeRef::ANY ) {
- if( m_inner_types.size() && m_inner_types.size() != other.m_inner_types.size() )
- throw ::std::runtime_error("TypeRef::merge_with - Handle bounded wildcards");
+ if( m_data.is_Any() ) {
+ //if( m_inner_types.size() && m_inner_types.size() != other.m_inner_types.size() )
+ // throw ::std::runtime_error("TypeRef::merge_with - Handle bounded wildcards");
*this = other;
return;
}
// If classes don't match, then merge is impossible
- if( m_class != other.m_class )
+ if( m_data.tag() != other.m_data.tag() )
throw ::std::runtime_error("TypeRef::merge_with - Types not compatible");
// If both types are concrete, then they must be the same
@@ -102,45 +120,66 @@ void TypeRef::merge_with(const TypeRef& other)
throw ::std::runtime_error("TypeRef::merge_with - Types not compatible");
return;
}
-
- switch(m_class)
+
+ #define _(VAR, ...) case TypeData::VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; const auto &other_ent = other.m_data.as_##VAR(); (void)&other_ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
- case TypeRef::ANY:
- case TypeRef::UNIT:
- case TypeRef::PRIMITIVE:
+ _(None,
throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
- case TypeRef::FUNCTION:
- if( m_inner_types.size() != other.m_inner_types.size() )
+ )
+ _(Any,
+ throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
+ )
+ _(Unit,
+ throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
+ )
+ _(Primitive,
+ throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
+ )
+ _(Function,
+ ent.info.m_rettype->merge_with( *other_ent.info.m_rettype );
+
+ if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() )
throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [function sz]");
- // - fall through to tuple code
- case TypeRef::TUPLE:
+ for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++)
+ {
+ ent.info.m_arg_types[i].merge_with( other_ent.info.m_arg_types[i] );
+ }
+ )
+ _(Tuple,
// Other is known not to be wildcard, and is also a tuple, so it must be the same size
- if( m_inner_types.size() != other.m_inner_types.size() )
+ if( ent.inner_types.size() != other_ent.inner_types.size() )
throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [tuple sz]");
- for(unsigned int i = 0; i < m_inner_types.size(); i ++)
+ for(unsigned int i = 0; i < ent.inner_types.size(); i ++)
{
- m_inner_types[i].merge_with( other.m_inner_types[i] );
+ ent.inner_types[i].merge_with( other_ent.inner_types[i] );
}
- break;
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- if( m_is_inner_mutable != other.m_is_inner_mutable )
+ )
+ _(Borrow,
+ if( ent.is_mut != other_ent.is_mut )
throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]");
- assert( m_inner_types.size() == 1 );
- assert( other.m_inner_types.size() == 1 );
- m_inner_types[0].merge_with( other.m_inner_types[0] );
- break;
- case TypeRef::ARRAY:
+ ent.inner->merge_with( *other_ent.inner );
+ )
+ _(Pointer,
+ if( ent.is_mut != other_ent.is_mut )
+ throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]");
+ ent.inner->merge_with( *other_ent.inner );
+ )
+ _(Array,
throw ::std::runtime_error("TODO: TypeRef::merge_with on ARRAY");
- case TypeRef::GENERIC:
+ )
+ _(Generic,
throw ::std::runtime_error("TODO: TypeRef::merge_with on GENERIC");
- case TypeRef::PATH:
+ )
+ _(Path,
throw ::std::runtime_error("TODO: TypeRef::merge_with on PATH");
- case TypeRef::MULTIDST:
+ )
+ _(TraitObject,
throw ::std::runtime_error("TODO: TypeRef::merge_with on MULTIDST");
+ )
}
+ #undef _
}
/// Resolve all Generic/Argument types to the value returned by the passed closure
@@ -150,35 +189,46 @@ void TypeRef::merge_with(const TypeRef& other)
void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn)
{
DEBUG("" << *this);
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
+ _(None,
throw ::std::runtime_error("TypeRef::resolve_args on !");
- case TypeRef::ANY:
- // TODO: Is resolving args on an ANY an erorr?
- break;
- case TypeRef::UNIT:
- case TypeRef::PRIMITIVE:
- break;
- case TypeRef::FUNCTION:
- case TypeRef::TUPLE:
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- case TypeRef::ARRAY:
- for( auto& t : m_inner_types )
+ )
+ // TODO: Is resolving args on an ANY an erorr?
+ _(Any)
+ _(Unit)
+ _(Primitive)
+ _(Function,
+ ent.info.m_rettype->resolve_args(fcn);
+ for( auto& t : ent.info.m_arg_types )
t.resolve_args(fcn);
- break;
- case TypeRef::GENERIC:
- *this = fcn(m_path[0].name().c_str());
- break;
- case TypeRef::PATH:
- m_path.resolve_args(fcn);
- break;
- case TypeRef::MULTIDST:
- for(auto& t : m_inner_types )
+ )
+ _(Tuple,
+ for( auto& t : ent.inner_types )
t.resolve_args(fcn);
- break;
+ )
+ _(Borrow,
+ ent.inner->resolve_args(fcn);
+ )
+ _(Pointer,
+ ent.inner->resolve_args(fcn);
+ )
+ _(Array,
+ ent.inner->resolve_args(fcn);
+ )
+ _(Generic,
+ *this = fcn(ent.name.c_str());
+ )
+ _(Path,
+ ent.path.resolve_args(fcn);
+ )
+ _(TraitObject,
+ for( auto& p : ent.traits )
+ p.resolve_args(fcn);
+ )
}
+ #undef _
}
/// Match this type against another type, calling the provided function for all generics found in this
@@ -189,119 +239,135 @@ void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn)
void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const
{
// If this type is a generic, then call the closure with the other type
- if( m_class == TypeRef::GENERIC ) {
- fcn( m_path[0].name().c_str(), other );
+ if( m_data.tag() == TypeData::Generic ) {
+ fcn( m_data.as_Generic().name.c_str(), other );
return ;
}
// If the other type is a wildcard, early return
// - TODO - Might want to restrict the other type to be of the same form as this type
- if( other.m_class == TypeRef::ANY )
+ if( other.m_data.tag() == TypeData::Any )
return;
DEBUG("this = " << *this << ", other = " << other);
// Any other case, it's a "pattern" match
- if( m_class != other.m_class )
+ if( m_data.tag() != other.m_data.tag() )
throw ::std::runtime_error("Type mismatch (class)");
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); const auto &other_ent = other.m_data.as_##VAR(); (void)&ent; (void)&other_ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
+ _(None,
throw ::std::runtime_error("TypeRef::match_args on !");
- case TypeRef::ANY:
+ )
+ _(Any,
// Wait, isn't this an error?
throw ::std::runtime_error("Encountered '_' in match_args");
- case TypeRef::UNIT:
- break;
- case TypeRef::PRIMITIVE:
+ )
+ _(Unit)
+ _(Primitive,
// TODO: Should check if the type matches
- if( m_core_type != other.m_core_type )
+ if( ent.core_type != other_ent.core_type )
throw ::std::runtime_error("Type mismatch (core)");
- break;
- case TypeRef::FUNCTION:
- if( m_path[0].name() != other.m_path[0].name() )
- throw ::std::runtime_error("Type mismatch (function abo)");
- if( m_inner_types.size() != other.m_inner_types.size() )
+ )
+ _(Function,
+ if( ent.info.m_abi != other_ent.info.m_abi )
+ throw ::std::runtime_error("Type mismatch (function abi)");
+ ent.info.m_rettype->match_args( *other_ent.info.m_rettype, fcn );
+
+ if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() )
throw ::std::runtime_error("Type mismatch (function size)");
- case TypeRef::TUPLE:
- if( m_inner_types.size() != other.m_inner_types.size() )
+ for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++ )
+ ent.info.m_arg_types[i].match_args( other_ent.info.m_arg_types[i], fcn );
+ )
+ _(Tuple,
+ if( ent.inner_types.size() != other_ent.inner_types.size() )
throw ::std::runtime_error("Type mismatch (tuple size)");
- for(unsigned int i = 0; i < m_inner_types.size(); i ++ )
- m_inner_types[i].match_args( other.m_inner_types[i], fcn );
- break;
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- if( m_is_inner_mutable != other.m_is_inner_mutable )
+ for(unsigned int i = 0; i < ent.inner_types.size(); i ++ )
+ ent.inner_types[i].match_args( other_ent.inner_types[i], fcn );
+ )
+ _(Borrow,
+ if( ent.is_mut != other_ent.is_mut )
throw ::std::runtime_error("Type mismatch (inner mutable)");
- m_inner_types[0].match_args( other.m_inner_types[0], fcn );
- break;
- case TypeRef::ARRAY:
- m_inner_types[0].match_args( other.m_inner_types[0], fcn );
- if(m_size_expr.get())
+ ent.inner->match_args( *other_ent.inner, fcn );
+ )
+ _(Pointer,
+ if( ent.is_mut != other_ent.is_mut )
+ throw ::std::runtime_error("Type mismatch (inner mutable)");
+ ent.inner->match_args( *other_ent.inner, fcn );
+ )
+ _(Array,
+ ent.inner->match_args( *other_ent.inner, fcn );
+ if(ent.size.get() || other_ent.size.get())
{
throw ::std::runtime_error("TODO: Sized array match_args");
}
- break;
- case TypeRef::GENERIC:
+ )
+ _(Generic,
throw ::std::runtime_error("Encountered GENERIC in match_args");
- case TypeRef::PATH:
- m_path.match_args(other.m_path, fcn);
- break;
- case TypeRef::MULTIDST:
+ )
+ _(Path,
+ ent.path.match_args(other_ent.path, fcn);
+ )
+ _(TraitObject,
throw ::std::runtime_error("TODO: TypeRef::match_args on MULTIDST");
+ )
}
+ #undef _
}
bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) const
{
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
+ _(None,
throw CompileError::BugCheck("TypeRef::impls_wildcard on !");
- case TypeRef::ANY:
+ )
+ _(Any,
throw CompileError::BugCheck("TypeRef::impls_wildcard on _");
+ )
// Generics are an error?
- case GENERIC:
+ _(Generic,
// TODO: Include an annotation to the TypeParams structure relevant to this type
// - Allows searching the params for the impl, without having to pass the params down
throw CompileError::Todo("TypeRef::impls_wildcard - param");
+ )
// Primitives always impl
- case UNIT:
- case PRIMITIVE:
- return true;
+ _(Unit, return true; )
+ _(Primitive, return true; )
// Functions are pointers (currently), so they implement the trait
- case FUNCTION:
- return true;
+ _(Function, return true; )
// Pointers/arrays inherit directly
- case REFERENCE:
- return crate.find_impl(trait, sub_types()[0], nullptr, nullptr);
- case POINTER:
- return crate.find_impl(trait, sub_types()[0], nullptr, nullptr);
- case ARRAY:
- return crate.find_impl(trait, sub_types()[0], nullptr, nullptr);
+ _(Borrow,
+ return crate.find_impl(trait, *ent.inner, nullptr, nullptr);
+ )
+ _(Pointer,
+ return crate.find_impl(trait, *ent.inner, nullptr, nullptr);
+ )
+ _(Array,
+ return crate.find_impl(trait, *ent.inner, nullptr, nullptr);
+ )
// Tuples just destructure
- case TUPLE:
- for( const auto& fld : sub_types() )
+ _(Tuple,
+ for( const auto& fld : ent.inner_types )
{
if( !crate.find_impl(trait, fld, nullptr, nullptr) )
return false;
}
return true;
- // MultiDST is special - It only impls if this trait is in the list
- // (or if a listed trait requires/impls the trait)
- case MULTIDST:
- throw CompileError::Todo("TypeRef::impls_wildcard - MULTIDST");
+ )
// Path types destructure
- case PATH:
+ _(Path,
// - structs need all fields to impl this trait (cache result)
// - same for enums, tuples, arrays, pointers...
// - traits check the Self bounds
// CATCH: Need to handle recursion, keep a list of currently processing paths and assume true if found
- switch(m_path.binding().type())
+ switch(ent.path.binding().type())
{
case AST::PathBinding::STRUCT: {
- const auto &s = m_path.binding().bound_struct();
- GenericResolveClosure resolve_fn( s.params(), m_path.nodes().back().args() );
+ const auto &s = ent.path.binding().bound_struct();
+ GenericResolveClosure resolve_fn( s.params(), ent.path.nodes().back().args() );
for(const auto& fld : s.fields())
{
TypeRef fld_ty = fld.data;
@@ -313,8 +379,8 @@ bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) co
}
return true; }
case AST::PathBinding::ENUM: {
- const auto& i = m_path.binding().bound_enum();
- GenericResolveClosure resolve_fn( i.params(), m_path.nodes().back().args() );
+ const auto& i = ent.path.binding().bound_enum();
+ GenericResolveClosure resolve_fn( i.params(), ent.path.nodes().back().args() );
for( const auto& var : i.variants() )
{
for( const auto& ty : var.m_sub_types )
@@ -331,138 +397,172 @@ bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) co
default:
throw CompileError::Todo("wildcard impls - auto determine path");
}
+ )
+ // MultiDST is special - It only impls if this trait is in the list
+ // (or if a listed trait requires/impls the trait)
+ _(TraitObject,
+ throw CompileError::Todo("TypeRef::impls_wildcard - MULTIDST");
+ )
}
+ #undef _
throw CompileError::BugCheck("TypeRef::impls_wildcard - Fell off end");
}
/// Checks if the type is fully bounded
bool TypeRef::is_concrete() const
{
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
+ _(None,
throw ::std::runtime_error("TypeRef::is_concrete on !");
- case TypeRef::ANY:
- return false;
- case TypeRef::UNIT:
- case TypeRef::PRIMITIVE:
+ )
+ _(Any, return false;)
+ _(Unit, return true; )
+ _(Primitive, return true; )
+ _(Function,
+ if( not ent.info.m_rettype->is_concrete() )
+ return false;
+ for(const auto& t : ent.info.m_arg_types )
+ if( not t.is_concrete() )
+ return false;
return true;
- case TypeRef::FUNCTION:
- case TypeRef::TUPLE:
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- case TypeRef::ARRAY:
- for(const auto& t : m_inner_types )
+ )
+ _(Tuple,
+ for(const auto& t : ent.inner_types)
if( not t.is_concrete() )
return false;
return true;
- case TypeRef::GENERIC:
+ )
+ _(Borrow,
+ return ent.inner->is_concrete();
+ )
+ _(Pointer,
+ return ent.inner->is_concrete();
+ )
+ _(Array,
+ return ent.inner->is_concrete();
+ )
+ _(Generic,
// Well, I guess a generic param is "concrete"
return true;
- case TypeRef::PATH:
- for(const auto& n : m_path.nodes())
- {
- for(const auto& p : n.args())
- if( not p.is_concrete() )
- return false;
- }
- return true;
- case TypeRef::MULTIDST:
- for(const auto& t : m_inner_types )
- if( not t.is_concrete() )
+ )
+ _(Path,
+ return ent.path.is_concrete();
+ )
+ _(TraitObject,
+ for(const auto& p : ent.traits )
+ if( not p.is_concrete() )
return false;
return true;
+ )
}
+ #undef _
throw ::std::runtime_error( FMT("BUGCHECK - Invalid type class on " << *this) );
}
int TypeRef::equal_no_generic(const TypeRef& x) const
{
//DEBUG(*this << ", " << x);
- if( m_class == TypeRef::GENERIC ) //|| x.m_class == TypeRef::GENERIC )
+ if( m_data.tag() == TypeData::Generic ) //|| x.m_class == TypeRef::GENERIC )
return 1;
- if( m_class != x.m_class ) return -1;
- switch(m_class)
+ if( m_data.tag() != x.m_data.tag() ) return -1;
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); const auto& x_ent = x.m_data.as_##VAR(); (void)&ent; (void)&x_ent; __VA_ARGS__ } break;
+ switch(m_data.tag())
{
- case TypeRef::NONE:
- case TypeRef::UNIT:
+ _(None, return 0;)
+ _(Unit, return 0;)
+ _(Any, return 0;)
+ _(Primitive,
+ if( ent.core_type != x_ent.core_type ) return -1;
return 0;
- case TypeRef::ANY:
- return 0;
- case TypeRef::PRIMITIVE:
- if( m_core_type != x.m_core_type ) return -1;
- return 0;
- case TypeRef::FUNCTION:
- if( m_path[0].name() != x.m_path[0].name() ) return -1;
+ )
+ _(Function,
+ if( ent.info.m_abi != x_ent.info.m_abi ) return -1;
throw CompileError::Todo("TypeRef::equal_no_generic - FUNCTION");
- case TypeRef::PATH:
- return m_path.equal_no_generic( x.m_path );
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- if( m_is_inner_mutable != x.m_is_inner_mutable )
+ )
+ _(Generic,
+ throw CompileError::BugCheck("equal_no_generic - Generic should have been handled above");
+ )
+ _(Path,
+ return ent.path.equal_no_generic( x_ent.path );
+ )
+ _(Borrow,
+ if( ent.is_mut != x_ent.is_mut )
return -1;
- return m_inner_types[0].equal_no_generic( x.m_inner_types[0] );
- case TypeRef::ARRAY:
- if( m_size_expr.get() || x.m_size_expr.get() )
+ return ent.inner->equal_no_generic( *x_ent.inner );
+ )
+ _(Pointer,
+ if( ent.is_mut != x_ent.is_mut )
+ return -1;
+ return ent.inner->equal_no_generic( *x_ent.inner );
+ )
+ _(Array,
+ if( ent.size.get() || x_ent.size.get() )
throw CompileError::Todo("TypeRef::equal_no_generic - sized array");
- return m_inner_types[0].equal_no_generic( x.m_inner_types[0] );
- case TypeRef::TUPLE: {
+ return ent.inner->equal_no_generic( *x_ent.inner );
+ )
+ _(Tuple,
bool fuzzy = false;
- if( m_inner_types.size() != x.m_inner_types.size() )
+ if( ent.inner_types.size() != x_ent.inner_types.size() )
return -1;
- for( unsigned int i = 0; i < m_inner_types.size(); i ++ )
+ for( unsigned int i = 0; i < ent.inner_types.size(); i ++ )
{
- int rv = m_inner_types[i].equal_no_generic( x.m_inner_types[i] );
+ int rv = ent.inner_types[i].equal_no_generic( x_ent.inner_types[i] );
if(rv < 0) return -1;
if(rv > 0) fuzzy = true;
}
- return (fuzzy ? 1 : 0); }
- case TypeRef::MULTIDST:
+ return (fuzzy ? 1 : 0);
+ )
+ _(TraitObject,
throw CompileError::Todo("TypeRef::equal_no_generic - MULTIDST");
- case TypeRef::GENERIC:
- throw CompileError::BugCheck("equal_no_generic - Generic should have been handled above");
+ )
}
+ #undef _
throw CompileError::BugCheck("equal_no_generic - Ran off end");
}
Ordering TypeRef::ord(const TypeRef& x) const
{
Ordering rv;
- rv = ::ord( (unsigned)m_class, (unsigned)x.m_class );
+ rv = ::ord( (unsigned)m_data.tag(), (unsigned)x.m_data.tag() );
if(rv != OrdEqual) return rv;
- switch(m_class)
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); const auto& x_ent = x.m_data.as_##VAR(); (void)&ent; (void)&x_ent; __VA_ARGS__ } break;
+ switch(x.m_data.tag())
{
- case TypeRef::NONE:
- return OrdEqual;
- case TypeRef::ANY:
- case TypeRef::UNIT:
- return OrdEqual;
- case TypeRef::PRIMITIVE:
- rv = ::ord( (unsigned)m_core_type, (unsigned)x.m_core_type );
+ _(None, return OrdEqual;)
+ _(Any, return OrdEqual;)
+ _(Unit, return OrdEqual;)
+ _(Primitive,
+ return ::ord( (unsigned)ent.core_type, (unsigned)x_ent.core_type );
+ )
+ _(Function,
+ return ent.info.ord( x_ent.info );
+ )
+ _(Tuple,
+ return ::ord(ent.inner_types, x_ent.inner_types);
+ )
+ _(Borrow,
+ rv = ::ord(ent.is_mut, x_ent.is_mut);
if(rv != OrdEqual) return rv;
- return OrdEqual;
- case TypeRef::FUNCTION:
- rv = ::ord(m_path[0].name(),x.m_path[0].name());
- if(rv != OrdEqual) return rv;
- return ::ord(m_inner_types, x.m_inner_types);
- case TypeRef::TUPLE:
- return ::ord(m_inner_types, x.m_inner_types);
- //return m_inner_types == x.m_inner_types;
- case TypeRef::REFERENCE:
- case TypeRef::POINTER:
- rv = ::ord(m_is_inner_mutable, x.m_is_inner_mutable);
+ return (*ent.inner).ord(*x_ent.inner);
+ )
+ _(Pointer,
+ rv = ::ord(ent.is_mut, x_ent.is_mut);
if(rv != OrdEqual) return rv;
- return ::ord(m_inner_types, x.m_inner_types);
- case TypeRef::ARRAY:
- rv = m_inner_types[0].ord( x.m_inner_types[0] );
+ return (*ent.inner).ord(*x_ent.inner);
+ )
+ _(Array,
+ rv = (*ent.inner).ord( *x_ent.inner );
if(rv != OrdEqual) return rv;
- if(m_size_expr.get())
+ if(ent.size.get())
{
throw ::std::runtime_error("TODO: Sized array comparisons");
}
return OrdEqual;
- case TypeRef::GENERIC:
+ )
+ _(Generic,
if( m_tagged_ptr != x.m_tagged_ptr )
{
DEBUG(*this << " == " << x);
@@ -472,13 +572,17 @@ Ordering TypeRef::ord(const TypeRef& x) const
}
else {
}
- return m_path.ord( x.m_path );
- case TypeRef::PATH:
- return m_path.ord( x.m_path );
- case TypeRef::MULTIDST:
- return ::ord(m_inner_types, x.m_inner_types);
+ return ::ord(ent.name, x_ent.name);
+ )
+ _(Path,
+ return ent.path.ord( x_ent.path );
+ )
+ _(TraitObject,
+ return ::ord(ent.traits, x_ent.traits);
+ )
}
- throw ::std::runtime_error(FMT("BUGCHECK - Unhandled TypeRef class '" << m_class << "'"));
+ #undef _
+ throw ::std::runtime_error(FMT("BUGCHECK - Unhandled TypeRef class '" << m_data.tag() << "'"));
}
::std::ostream& operator<<(::std::ostream& os, const eCoreType ct) {
@@ -487,71 +591,67 @@ Ordering TypeRef::ord(const TypeRef& x) const
::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr) {
//os << "TypeRef(";
- switch(tr.m_class)
+ #define _(VAR, ...) case TypeData::VAR: { const auto &ent = tr.m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+ switch(tr.m_data.tag())
{
- case TypeRef::NONE:
+ _(None,
os << "!";
- break;
- case TypeRef::ANY:
- //os << "TagAny";
+ )
+ _(Any,
os << "_";
- if( tr.m_inner_types.size() ) {
- os << ": " << tr.m_inner_types << "";
- }
- break;
- case TypeRef::UNIT:
- //os << "TagUnit";
+ )
+ _(Unit,
os << "()";
- break;
- case TypeRef::PRIMITIVE:
- //os << "TagPrimitive, " << tr.m_core_type;
- os << tr.m_core_type;
- break;
- case TypeRef::FUNCTION:
- if( tr.m_path[0].name() != "" )
- os << "extern \"" << tr.m_path[0].name() << "\" ";
+ )
+ _(Primitive,
+ os << tr.m_data.as_Primitive().core_type;
+ )
+ _(Function,
+ if( ent.info.m_abi != "" )
+ os << "extern \"" << ent.info.m_abi << "\" ";
os << "fn (";
- for( unsigned int i = 0; i < tr.m_inner_types.size()-1; i ++ )
- os << tr.m_inner_types[i] << ", ";
- os << ") -> " << tr.m_inner_types.back();
- break;
- case TypeRef::TUPLE:
+ for( const auto& arg : ent.info.m_arg_types )
+ os << arg << ", ";
+ os << ") -> " << *ent.info.m_rettype;
+ )
+ _(Tuple,
//os << "TagTuple, {" << tr.m_inner_types << "}";
os << "( ";
- for( const auto& it : tr.m_inner_types )
+ for( const auto& it : ent.inner_types )
os << it << ", ";
os << ")";
- break;
- case TypeRef::REFERENCE:
+ )
+ _(Borrow,
//os << "TagReference, " << (tr.m_is_inner_mutable ? "mut" : "const") << ", " << tr.m_inner_types[0];
- os << "&" << (tr.m_is_inner_mutable ? "mut " : "") << tr.m_inner_types[0];
- break;
- case TypeRef::POINTER:
+ os << "&" << (ent.is_mut ? "mut " : "") << *ent.inner;
+ )
+ _(Pointer,
//os << "TagPointer, " << (tr.m_is_inner_mutable ? "mut" : "const") << ", " << tr.m_inner_types[0];
- os << "*" << (tr.m_is_inner_mutable ? "mut" : "const") << " " << tr.m_inner_types[0];
- break;
- case TypeRef::ARRAY:
- os << "[" << tr.m_inner_types[0];
- if( tr.m_size_expr.get() )
- os << "; " << *tr.m_size_expr;
+ os << "*" << (ent.is_mut ? "mut" : "const") << " " << *ent.inner;
+ )
+ _(Array,
+ os << "[" << *ent.inner;
+ if( ent.size.get() )
+ os << "; " << *ent.size;
os << "]";
- break;
- case TypeRef::GENERIC:
- os << "/* arg */ " << tr.m_path[0].name();
- break;
- case TypeRef::PATH:
- os << tr.m_path;
- break;
- case TypeRef::MULTIDST:
+ )
+ _(Generic,
+ os << "/* arg */ " << ent.name << "/*"<<ent.level<<"*/";
+ )
+ _(Path,
+ os << ent.path;
+ )
+ _(TraitObject,
os << "(";
- for( const auto& it : tr.m_inner_types ) {
- if( &it != &tr.m_inner_types.front() )
+ for( const auto& it : ent.traits ) {
+ if( &it != &ent.traits.front() )
os << "+";
os << it;
}
os << ")";
- break;
+ )
}
+ #undef _
//os << ")";
return os;
}
@@ -581,70 +681,114 @@ void operator% (::Deserialiser& d, eCoreType& ct) {
else
throw ::std::runtime_error("Deserialise failure - coretype " + n);
}
-const char* TypeRef::class_name(TypeRef::Class c) {
- switch(c)
- {
- #define _(x) case TypeRef::x: return #x;
- _(NONE)
- _(ANY)
- _(UNIT)
- _(PRIMITIVE)
- _(FUNCTION)
- _(TUPLE)
- _(REFERENCE)
- _(POINTER)
- _(ARRAY)
- _(GENERIC)
- _(PATH)
- _(MULTIDST)
- #undef _
- }
- return "NFI";
+void operator%(Serialiser& s, TypeData::Tag c) {
+ s << TypeData::tag_to_str(c);
}
-void operator>>(::Deserialiser& d, TypeRef::Class& c) {
- ::std::string n;
- d.item(n);
- #define _(x) if(n == #x) c = TypeRef::x;
- /**/ _(ANY)
- else _(NONE)
- else _(UNIT)
- else _(PRIMITIVE)
- else _(FUNCTION)
- else _(TUPLE)
- else _(REFERENCE)
- else _(POINTER)
- else _(ARRAY)
- else _(GENERIC)
- else _(PATH)
- else _(MULTIDST)
- else
- throw ::std::runtime_error("Deserialise failure - " + n);
- #undef _
+void operator%(::Deserialiser& s, TypeData::Tag& c) {
+ ::std::string n;
+ s.item(n);
+ c = TypeData::tag_from_str(n);
+}
+
+::std::unique_ptr<TypeRef> TypeRef::from_deserialiser(Deserialiser& s) {
+ TypeRef n;
+ n.deserialise(s);
+ return box$(n);
}
+
+#define _S(VAR, ...) case TypeData::VAR: { const auto& ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
+#define _D(VAR, ...) case TypeData::VAR: { m_data = TypeData::make_null_##VAR(); auto& ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
SERIALISE_TYPE(TypeRef::, "TypeRef", {
- s << class_name(m_class);
- if(m_class == PRIMITIVE)
- s << coretype_name(m_core_type);
- s << m_inner_types;
- if(m_class == REFERENCE || m_class == POINTER)
- s << m_is_inner_mutable;
- s << m_size_expr;
- s << m_path;
+ s % m_data.tag();
+ switch(m_data.tag())
+ {
+ _S(None)
+ _S(Any)
+ _S(Unit)
+ _S(Primitive,
+ s << coretype_name(ent.core_type);
+ )
+ _S(Function,
+ s.item( ent.info );
+ )
+ _S(Tuple,
+ s.item( ent.inner_types );
+ )
+ _S(Borrow,
+ s.item( ent.is_mut );
+ s.item( ent.inner );
+ )
+ _S(Pointer,
+ s.item( ent.is_mut );
+ s.item( ent.inner );
+ )
+ _S(Generic,
+ s.item( ent.name );
+ s.item( ent.level );
+ )
+ _S(Array,
+ s.item( ent.inner );
+ bool size_present = (ent.size.get() != 0);
+ s.item( size_present );
+ if(ent.size.get()) {
+ s.item( ent.size );
+ }
+ )
+ _S(Path,
+ s.item( ent.path );
+ )
+ _S(TraitObject,
+ s.item( ent.traits );
+ )
+ }
},{
- s >> m_class;
- if(m_class == PRIMITIVE)
- s % m_core_type;
- s.item( m_inner_types );
- if(m_class == REFERENCE || m_class == POINTER)
- s.item( m_is_inner_mutable );
- bool size_expr_present;
- s.item(size_expr_present);
- if( size_expr_present )
- m_size_expr = AST::ExprNode::from_deserialiser(s);
- else
- m_size_expr.reset();
- s.item( m_path );
+ TypeData::Tag tag;
+ s % tag;
+ switch(tag)
+ {
+ _D(None)
+ _D(Any)
+ _D(Unit)
+ _D(Primitive,
+ s % ent.core_type;
+ )
+ _D(Function,
+ s.item( ent.info );
+ )
+ _D(Tuple,
+ s.item( ent.inner_types );
+ )
+ _D(Borrow,
+ s.item( ent.is_mut );
+ s.item( ent.inner );
+ )
+ _D(Pointer,
+ s.item( ent.is_mut );
+ s.item( ent.inner );
+ )
+ _D(Generic,
+ s.item( ent.name );
+ s.item( ent.level );
+ )
+ _D(Array,
+ s.item( ent.inner );
+ bool size_present;
+ s.item( size_present );
+ if( size_present )
+ ent.size = AST::ExprNode::from_deserialiser(s);
+ else
+ ent.size.reset();
+ )
+ _D(Path,
+ s.item( ent.path );
+ )
+ _D(TraitObject,
+ s.item( ent.traits );
+ )
+ }
})
+#undef _D
+#undef _S
void PrettyPrintType::print(::std::ostream& os) const