diff options
author | John Hodge <tpg@mutabah.net> | 2016-05-24 22:12:15 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-05-24 22:12:15 +0800 |
commit | c6404f9d52a6dd936a75a900748d8aa70268e923 (patch) | |
tree | 1b7ed3ad726b632977f08d56505366cd85b9df8c /src/ast/types.cpp | |
parent | 23cba420f497b5da5b0a63f078cea2ef2291078a (diff) | |
download | mrust-c6404f9d52a6dd936a75a900748d8aa70268e923.tar.gz |
AST - Move types.cpp to ast/ dir
Diffstat (limited to 'src/ast/types.cpp')
-rw-r--r-- | src/ast/types.cpp | 845 |
1 files changed, 845 insertions, 0 deletions
diff --git a/src/ast/types.cpp b/src/ast/types.cpp new file mode 100644 index 00000000..8a3ee638 --- /dev/null +++ b/src/ast/types.cpp @@ -0,0 +1,845 @@ +/* + * MRustC - Mutabah's Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * types.cpp + * - Backing code for the TypeRef class + * + * Handles a chunk of type resolution (merging) and matching/comparing types + */ +#include "types.hpp" +#include "ast/ast.hpp" +#include "ast/crate.hpp" + +/// Mappings from internal type names to the core type enum +static const struct { + const char* name; + enum eCoreType type; +} CORETYPES[] = { + // NOTE: Sorted + {"bool", CORETYPE_BOOL}, + {"char", CORETYPE_CHAR}, + {"f32", CORETYPE_F32}, + {"f64", CORETYPE_F64}, + {"i16", CORETYPE_I16}, + {"i32", CORETYPE_I32}, + {"i64", CORETYPE_I64}, + {"i8", CORETYPE_I8}, + {"int", CORETYPE_INT}, + {"isize", CORETYPE_INT}, + {"str", CORETYPE_STR}, + {"u16", CORETYPE_U16}, + {"u32", CORETYPE_U32}, + {"u64", CORETYPE_U64}, + {"u8", CORETYPE_U8}, + {"uint", CORETYPE_UINT}, + {"usize", CORETYPE_UINT}, +}; + +enum eCoreType coretype_fromstring(const ::std::string& name) +{ + for(unsigned int i = 0; i < sizeof(CORETYPES)/sizeof(CORETYPES[0]); i ++) + { + if( name < CORETYPES[i].name ) + break; + if( name == CORETYPES[i].name ) + return CORETYPES[i].type; + } + return CORETYPE_INVAL; +} + +const char* coretype_name(const eCoreType ct ) { + switch(ct) + { + case CORETYPE_INVAL:return "-"; + case CORETYPE_ANY: return "_"; + case CORETYPE_CHAR: return "char"; + case CORETYPE_STR: return "str"; + case CORETYPE_BOOL: return "bool"; + case CORETYPE_UINT: return "usize"; + case CORETYPE_INT: return "isize"; + case CORETYPE_U8: return "u8"; + case CORETYPE_I8: return "i8"; + case CORETYPE_U16: return "u16"; + case CORETYPE_I16: return "i16"; + case CORETYPE_U32: return "u32"; + case CORETYPE_I32: return "i32"; + case CORETYPE_U64: return "u64"; + case CORETYPE_I64: return "i64"; + case CORETYPE_F32: return "f32"; + case CORETYPE_F64: return "f64"; + } + DEBUG("Unknown core type?! " << 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) +{ +} +SERIALISE_TYPE_A(Type_Function::, "Type_Function", { + s.item( is_unsafe ); + s.item( m_abi ); + s.item( m_rettype ); + s.item( 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 ); +} + +TypeRef::TypeRef(const TypeRef& other) +{ + switch( other.m_data.tag() ) + { + case TypeData::TAGDEAD: throw ""; + #define _COPY(VAR) case TypeData::TAG_##VAR: m_data = TypeData::make_##VAR(other.m_data.as_##VAR()); break; + #define _CLONE(VAR, code...) case TypeData::TAG_##VAR: { auto& old = other.m_data.as_##VAR(); m_data = TypeData::make_##VAR(code); } break; + _COPY(None) + _COPY(Any) + case TypeData::TAG_Macro: assert( !"Copying an unexpanded type macro" ); + _COPY(Unit) + _COPY(Primitive) + _COPY(Function) + _COPY(Tuple) + _CLONE(Borrow, { old.is_mut, box$(TypeRef(*old.inner)) }) + _CLONE(Pointer, { old.is_mut, box$(TypeRef(*old.inner)) }) + _CLONE(Array, { box$(TypeRef(*old.inner)), old.size }) + _COPY(Generic) + _COPY(Path) + _COPY(TraitObject) + #undef _COPY + #undef _CLONE + } +} + +/// Replace this type reference with a dereferenced version +bool TypeRef::deref(bool is_implicit) +{ + #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; + switch(m_data.tag()) + { + case TypeData::TAGDEAD: throw ""; + case TypeData::TAG_None: throw ::std::runtime_error("Dereferencing ! - bugcheck"); + case TypeData::TAG_Macro: throw ::std::runtime_error("Dereferencing unexpanded macro - bugcheck"); + case TypeData::TAG_Any: throw ::std::runtime_error("Dereferencing _"); + case TypeData::TAG_Unit: throw ::std::runtime_error("Dereferencing ()"); + case TypeData::TAG_Primitive: throw ::std::runtime_error("Dereferencing a primtive type"); + case TypeData::TAG_Function: throw ::std::runtime_error("Dereferencing a function"); + + case TypeData::TAG_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; + ) + _(Pointer, + // raw pointers can't be implicitly dereferenced + if( is_implicit ) + return false; + *this = *ent.inner; + return true; + ) + case TypeData::TAG_Tuple: + case TypeData::TAG_Array: + case TypeData::TAG_Path: + throw ::std::runtime_error("TODO: Search for an impl of Deref"); + case TypeData::TAG_TraitObject: + throw ::std::runtime_error("TODO: TypeRef::deref on MULTIDST"); + } + #undef _ + throw ::std::runtime_error("BUGCHECK: Fell off end of TypeRef::deref"); +} + +/// Merge the contents of the passed type with this type +/// +/// \note Both types must be of the same form (i.e. both be tuples) +void TypeRef::merge_with(const TypeRef& other) +{ + // Ignore if other is wildcard + //if( other.m_class == TypeRef::ANY ) { + // assert(other.m_inner_types.size() == 0 && "TODO: merge_with on bounded _"); + // return; + //} + + // If this is a wildcard, then replace with the other type + 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_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 + if( is_concrete() && other.is_concrete() ) + { + if( *this != other ) + throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); + return; + } + + + TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent), + (None, + throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); + ), + (Macro, + throw ::std::runtime_error("TypeRef::merge_with - Reached unexpanded macro"); + ), + (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]"); + 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( 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 < ent.inner_types.size(); i ++) + { + ent.inner_types[i].merge_with( other_ent.inner_types[i] ); + } + ), + (Borrow, + 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 ); + ), + (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"); + ), + (Generic, + throw ::std::runtime_error("TODO: TypeRef::merge_with on GENERIC"); + ), + (Path, + throw ::std::runtime_error("TODO: TypeRef::merge_with on PATH"); + ), + (TraitObject, + throw ::std::runtime_error("TODO: TypeRef::merge_with on MULTIDST"); + ) + ) +} + +/// Resolve all Generic/Argument types to the value returned by the passed closure +/// +/// Replaces every instance of a TypeRef::GENERIC with the value returned from the passed +/// closure. +void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn) +{ + DEBUG("" << *this); + #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; + switch(m_data.tag()) + { + case TypeData::TAGDEAD: throw ""; + _(None, + throw ::std::runtime_error("TypeRef::resolve_args on !"); + ) + _(Macro, + throw ::std::runtime_error("TypeRef::resolve_args on unexpanded macro"); + ) + // 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); + ) + _(Tuple, + for( auto& t : ent.inner_types ) + t.resolve_args(fcn); + ) + _(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 +/// +/// \param other Type containing (possibly) concrete types +/// \param fcn Function to call for all generics (called with matching type from \a other) +/// This is used to handle extracting types passsed to methods/enum variants +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_data.tag() == TypeData::TAG_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_data.tag() == TypeData::TAG_Any ) + return; + + DEBUG("this = " << *this << ", other = " << other); + + // Any other case, it's a "pattern" match + if( m_data.tag() != other.m_data.tag() ) + throw ::std::runtime_error("Type mismatch (class)"); + TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent), + (None, + throw ::std::runtime_error("TypeRef::match_args on !"); + ), + (Macro, + throw CompileError::BugCheck("TypeRef::match_args - unexpanded macro"); + ), + (Any, + // Wait, isn't this an error? + throw ::std::runtime_error("Encountered '_' in match_args"); + ), + (Unit), + (Primitive, + // TODO: Should check if the type matches + if( ent.core_type != other_ent.core_type ) + throw ::std::runtime_error("Type mismatch (core)"); + ), + (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)"); + 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 < 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)"); + 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"); + } + ), + (Generic, + throw ::std::runtime_error("Encountered GENERIC in match_args"); + ), + (Path, + ent.path.match_args(other_ent.path, fcn); + ), + (TraitObject, + throw ::std::runtime_error("TODO: TypeRef::match_args on MULTIDST"); + ) + ) +} + +/// Checks if the type is fully bounded +bool TypeRef::is_concrete() const +{ + #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; + TU_MATCH(TypeData, (m_data), (ent), + (None, + throw ::std::runtime_error("TypeRef::is_concrete on !"); + ), + (Macro, throw CompileError::BugCheck("TypeRef::is_concrete - unexpanded macro");), + (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; + ), + (Tuple, + for(const auto& t : ent.inner_types) + if( not t.is_concrete() ) + return false; + return true; + ), + (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; + ), + (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_data.tag() == TypeData::TAG_Generic ) //|| x.m_class == TypeRef::GENERIC ) + return 1; + if( m_data.tag() != x.m_data.tag() ) return -1; + + TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent), + (None, return 0;), + (Macro, throw CompileError::BugCheck("TypeRef::equal_no_generic - unexpanded macro");), + (Unit, return 0;), + (Any, return 0;), + (Primitive, + if( ent.core_type != x_ent.core_type ) return -1; + return 0; + ), + (Function, + if( ent.info.m_abi != x_ent.info.m_abi ) return -1; + throw CompileError::Todo("TypeRef::equal_no_generic - FUNCTION"); + ), + (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 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 ent.inner->equal_no_generic( *x_ent.inner ); + ), + (Tuple, + bool fuzzy = false; + if( ent.inner_types.size() != x_ent.inner_types.size() ) + return -1; + for( unsigned int i = 0; i < ent.inner_types.size(); 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); + ), + (TraitObject, + throw CompileError::Todo("TypeRef::equal_no_generic - MULTIDST"); + ) + ) + throw CompileError::BugCheck("equal_no_generic - Ran off end"); +} +Ordering TypeRef::ord(const TypeRef& x) const +{ + Ordering rv; + + rv = ::ord( (unsigned)m_data.tag(), (unsigned)x.m_data.tag() ); + if(rv != OrdEqual) return rv; + + TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent), + (None, return OrdEqual;), + (Macro, throw CompileError::BugCheck("TypeRef::ord - unexpanded macro");), + (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 (*ent.inner).ord(*x_ent.inner); + ), + (Pointer, + rv = ::ord(ent.is_mut, x_ent.is_mut); + if(rv != OrdEqual) return rv; + return (*ent.inner).ord(*x_ent.inner); + ), + (Array, + rv = (*ent.inner).ord( *x_ent.inner ); + if(rv != OrdEqual) return rv; + if(ent.size.get()) + { + throw ::std::runtime_error("TODO: Sized array comparisons"); + } + return OrdEqual; + ), + (Generic, + if( ent.params != x_ent.params ) + { + DEBUG(*this << " == " << x); + if( ent.params ) DEBUG("- (L) " << *ent.params); + if( x_ent.params ) DEBUG("- (R) " << *x_ent.params); + throw ::std::runtime_error("Can't compare mismatched generic types"); + //BUG(m_span, "Can't compare mismatched generic types"); + } + else { + } + 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_data.tag() << "'")); +} + +::std::ostream& operator<<(::std::ostream& os, const eCoreType ct) { + return os << coretype_name(ct); +} + +::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr) { + //os << "TypeRef("; + #define _(VAR, ...) case TypeData::TAG_##VAR: { const auto &ent = tr.m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; + switch(tr.m_data.tag()) + { + case TypeData::TAGDEAD: throw ""; + _(None, + os << "!"; + ) + _(Any, + os << "_"; + ) + _(Macro, + os << ent.inv; + ) + _(Unit, + os << "()"; + ) + _(Primitive, + os << tr.m_data.as_Primitive().core_type; + ) + _(Function, + if( ent.info.m_abi != "" ) + os << "extern \"" << ent.info.m_abi << "\" "; + os << "fn ("; + 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 : ent.inner_types ) + os << it << ", "; + os << ")"; + ) + _(Borrow, + //os << "TagReference, " << (tr.m_is_inner_mutable ? "mut" : "const") << ", " << tr.m_inner_types[0]; + os << "&" << (ent.is_mut ? "mut " : "") << *ent.inner; + ) + _(Pointer, + //os << "TagPointer, " << (tr.m_is_inner_mutable ? "mut" : "const") << ", " << tr.m_inner_types[0]; + os << "*" << (ent.is_mut ? "mut" : "const") << " " << *ent.inner; + ) + _(Array, + os << "[" << *ent.inner; + if( ent.size.get() ) + os << "; " << *ent.size; + os << "]"; + ) + _(Generic, + os << "/* arg */ " << ent.name << "/*"<<ent.level<<"*/"; + ) + _(Path, + os << ent.path; + ) + _(TraitObject, + os << "("; + for( const auto& it : ent.traits ) { + if( &it != &ent.traits.front() ) + os << "+"; + os << it; + } + os << ")"; + ) + } + #undef _ + //os << ")"; + return os; +} + +void operator% (::Serialiser& s, eCoreType ct) { + s << coretype_name(ct); +} +void operator% (::Deserialiser& d, eCoreType& ct) { + ::std::string n; + d.item(n); + /* */if(n == "-") ct = CORETYPE_INVAL; + else if(n == "_") ct = CORETYPE_ANY; + else if(n == "bool") ct = CORETYPE_BOOL; + else if(n == "char") ct = CORETYPE_CHAR; + else if(n == "usize") ct = CORETYPE_UINT; + else if(n == "isize") ct = CORETYPE_INT; + else if(n == "u8") ct = CORETYPE_U8; + else if(n == "i8") ct = CORETYPE_I8; + else if(n == "u16") ct = CORETYPE_U16; + else if(n == "i16") ct = CORETYPE_I16; + else if(n == "u32") ct = CORETYPE_U32; + else if(n == "i32") ct = CORETYPE_I32; + else if(n == "u64") ct = CORETYPE_U64; + else if(n == "i64") ct = CORETYPE_I64; + else if(n == "f32") ct = CORETYPE_F32; + else if(n == "f64") ct = CORETYPE_F64; + else + throw ::std::runtime_error("Deserialise failure - coretype " + n); +} +void operator%(Serialiser& s, TypeData::Tag c) { + s << TypeData::tag_to_str(c); +} +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::TAG_##VAR: { const auto& ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; +#define _D(VAR, ...) case TypeData::TAG_##VAR: { m_data = TypeData::make_##VAR({}); auto& ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; +SERIALISE_TYPE(TypeRef::, "TypeRef", { + s % m_data.tag(); + switch(m_data.tag()) + { + case TypeData::TAGDEAD: throw ""; + _S(None) + _S(Macro, + s.item( ent.inv ); + ) + _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 ); + ) + } +},{ + TypeData::Tag tag; + s % tag; + switch(tag) + { + case TypeData::TAGDEAD: throw ""; + _D(None) + _D(Any) + _D(Unit) + _D(Macro, + m_data = TypeData::make_Macro({}); + s.item( ent.inv ); + ) + _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 +{ + #if 1 + os << m_type; + #else + switch(m_type.m_class) + { + case TypeRef::ANY: + os << "_"; + if( m_type.m_inner_types.size() ) { + os << "/* : " << m_type.m_inner_types << "*/"; + } + break; + case TypeRef::UNIT: + os << "()"; + break; + case TypeRef::PRIMITIVE: + os << m_type.m_core_type; + break; + case TypeRef::FUNCTION: + if( m_type.m_path[0].name() != "" ) + os << "extern \"" << m_type.m_path[0].name() << "\" "; + os << "fn ("; + for( unsigned int i = 0; i < m_type.m_inner_types.size()-1; i ++ ) + os << m_type.m_inner_types[i].print_pretty() << ", "; + os << ") -> " << m_type.m_inner_types.back().print_pretty(); + break; + case TypeRef::TUPLE: + os << "("; + for(const auto& t : m_type.m_inner_types) + os << t.print_pretty() << ","; + os << ")"; + break; + case TypeRef::REFERENCE: + os << "&" << (m_type.m_is_inner_mutable ? "mut " : "") << m_type.m_inner_types[0].print_pretty(); + break; + case TypeRef::POINTER: + os << "*" << (m_type.m_is_inner_mutable ? "mut" : "const") << " " << m_type.m_inner_types[0].print_pretty(); + break; + case TypeRef::ARRAY: + os << "[" << m_type.m_inner_types[0].print_pretty() << ", " << m_type.m_size_expr << "]"; + break; + case TypeRef::GENERIC: + os << m_type.m_path[0].name(); + break; + case TypeRef::PATH: + os << m_type.m_path; + break; + } + #endif +} + +::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v) +{ + v.print(os); + return os; +} |