diff options
Diffstat (limited to 'src/types.cpp')
-rw-r--r-- | src/types.cpp | 800 |
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 |