diff options
author | John Hodge <tpg@mutabah.net> | 2015-08-24 22:50:49 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-08-24 22:50:49 +0800 |
commit | 7156d7d274184a085452a58ee3398d06024112b5 (patch) | |
tree | 874e8ca17500870c7aeb8e440e9d09d982284593 /src | |
parent | edbd5db807dd66876ad25e0b67a37a567187f076 (diff) | |
download | mrust-7156d7d274184a085452a58ee3398d06024112b5.tar.gz |
BROKEN - Halfway through a rewrite of type handling
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 6 | ||||
-rw-r--r-- | src/ast/ast.hpp | 6 | ||||
-rw-r--r-- | src/ast/path.cpp | 11 | ||||
-rw-r--r-- | src/ast/path.hpp | 2 | ||||
-rw-r--r-- | src/common.hpp | 12 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 5 | ||||
-rw-r--r-- | src/include/serialise.hpp | 2 | ||||
-rw-r--r-- | src/include/tagged_enum.hpp | 120 | ||||
-rw-r--r-- | src/main.cpp | 14 | ||||
-rw-r--r-- | src/types.cpp | 800 | ||||
-rw-r--r-- | src/types.hpp | 241 |
11 files changed, 693 insertions, 526 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index d712edd3..f0d38199 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -916,10 +916,10 @@ bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool if( bound.is_trait() && bound.test() == test )
{
const auto& trait = bound.bound();
- const auto& ty_traits = type.traits();
+ //const auto& ty_traits = type.traits();
- auto it = ::std::find(ty_traits.begin(), ty_traits.end(), trait);
- if( it == ty_traits.end() )
+ //auto it = ::std::find(ty_traits.begin(), ty_traits.end(), trait);
+ //if( it == ty_traits.end() )
{
throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<type));
}
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index f1229fb2..2376b054 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -653,10 +653,10 @@ public: m_submods.push_back( ::std::make_pair( move(mod), is_public ) );
}
void add_impl(Impl impl) {
- m_impls.push_back( ::std::move(impl) );
+ m_impls.emplace_back( ::std::move(impl) );
}
void add_neg_impl(ImplDef impl) {
- m_neg_impls.push_back( ::std::move(impl) );
+ m_neg_impls.emplace_back( ::std::move(impl) );
}
void add_macro(bool is_exported, ::std::string name, MacroRules macro) {
m_macros.push_back( Item<MacroRules>( move(name), move(macro), is_exported ) );
@@ -859,7 +859,7 @@ public: m_params(params),
m_args(args)
{}
- TypeRef operator()(const char *argname) {
+ const TypeRef& operator()(const char *argname) {
for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
{
if( m_params.ty_params()[i].name() == argname ) {
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index df00f147..9757e576 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -568,6 +568,17 @@ void Path::match_args(const Path& other, ::std::function<void(const char*,const } } +bool Path::is_concrete() const +{ + for(const auto& n : this->nodes()) + { + for(const auto& p : n.args()) + if( not p.is_concrete() ) + return false; + } + return true; +} + /// Compare if two paths refer to the same non-generic item /// /// - This doesn't handle the (impossible?) case where a generic might diff --git a/src/ast/path.hpp b/src/ast/path.hpp index f53561fa..ff267c73 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -317,6 +317,8 @@ public: bool is_absolute() const { return m_class == ABSOLUTE; } bool is_relative() const { return m_class == RELATIVE; } size_t size() const { return m_nodes.size(); } + + bool is_concrete() const; const PathBinding& binding() const { return m_binding; } diff --git a/src/common.hpp b/src/common.hpp index 457d58b0..8fef294a 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -8,15 +8,27 @@ #include <map> #include <cassert> #include <sstream> +#include <memory> #define FMT(ss) (dynamic_cast< ::std::stringstream&>(::std::stringstream() << ss).str()) // XXX: Evil hack - Define 'mv$' to be ::std::move #define mv$(x) ::std::move(x) +#define box$(x) ::make_unique_ptr(::std::move(x)) +#define rc_new$(x) ::make_shared_ptr(::std::move(x)) #include "include/debug.hpp" #include "include/rustic.hpp" // slice and option #include "include/compile_error.hpp" +template<typename T> +::std::unique_ptr<T> make_unique_ptr(T&& v) { + return ::std::unique_ptr<T>(new T(mv$(v))); +} +template<typename T> +::std::shared_ptr<T> make_shared_ptr(T&& v) { + return ::std::shared_ptr<T>(new T(mv$(v))); +} + enum Ordering { OrdLess, diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index 24dbf5f0..32125eaf 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -15,8 +15,9 @@ void CASTIterator::handle_type(TypeRef& type) } else { - for(auto& subtype : type.sub_types()) - handle_type(subtype); + throw ::std::runtime_error("TODO: handle_type"); + //for(auto& subtype : type.sub_types()) + // handle_type(subtype); } } void CASTIterator::handle_expr(AST::ExprNode& node) diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp index 0840d54b..5556a510 100644 --- a/src/include/serialise.hpp +++ b/src/include/serialise.hpp @@ -59,6 +59,7 @@ public: virtual Serialiser& operator<<(uint64_t val) = 0; virtual Serialiser& operator<<(int64_t val) = 0; virtual Serialiser& operator<<(double val) = 0; + Serialiser& operator<<(unsigned int val) { return *this << (uint64_t)val; }; virtual Serialiser& operator<<(const char* s) = 0; Serialiser& operator<<(const ::std::string& s) { return *this << s.c_str(); @@ -120,6 +121,7 @@ protected: public: virtual void item(bool& b) = 0; virtual void item(uint64_t& v) = 0; + void item(unsigned int& v) { uint64_t v1; this->item(v1); v = v1; } virtual void item(int64_t& val) = 0; virtual void item(double& v) = 0; virtual void item(::std::string& s) = 0; diff --git a/src/include/tagged_enum.hpp b/src/include/tagged_enum.hpp index e491e154..8f5b34e0 100644 --- a/src/include/tagged_enum.hpp +++ b/src/include/tagged_enum.hpp @@ -1,3 +1,8 @@ +/* + * The most evil CPP abuse I have ever written + */ +#ifndef INCLUDED_TAGGED_UNION_H_ +#define INCLUDED_TAGGED_UNION_H_ #define TE_DATANAME(name) Data_##name #define ENUM_CONS(__tag, __type) \ @@ -14,16 +19,29 @@ __type& as_##__tag() { return reinterpret_cast<__type&>(m_data); } \ __type unwrap_##__tag() { return ::std::move(reinterpret_cast<__type&>(m_data)); } \ +// Argument iteration +#define _DISP2(n, _1, _2) n _1 n _2 +#define _DISP3(n, v, v2, v3) n v n v2 n v3 // _DISP2(n, __VA_ARGS__) +#define _DISP4(n, v, v2, v3, v4) n v n v2 n v3 n v4 // #define _DISP4(n, v, ...) n v _DISP3(n, __VA_ARGS__) +#define _DISP5(n, v, ...) n v _DISP4(n, __VA_ARGS__) +#define _DISP6(n, v, ...) n v _DISP5(n, __VA_ARGS__) +#define _DISP7(n, v, ...) n v _DISP6(n, __VA_ARGS__) +#define _DISP8(n, v, ...) n v _DISP7(n, __VA_ARGS__) +#define _DISP9(n, v, ...) n v _DISP8(n, __VA_ARGS__) +#define _DISP10(n, v, ...) n v _DISP9(n, __VA_ARGS__) +#define _DISP11(n, v, ...) n v _DISP10(n, __VA_ARGS__) +#define _DISP12(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3,c4) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP4(n, c1,c2,c3,c4) //n v _DISP11(n, __VA_ARGS__) + +// Macro to obtain a numbered macro for argument counts +// - Raw variant +#define TE_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,COUNT,...) SUF##COUNT +#define TE_GM(SUF,...) TE_GM_I(SUF,__VA_ARGS__,12,11,10,9,8,7,6,5,4,3,2,x) +// - _DISP based variant (for iteration) +#define TE_GMX(...) TE_GM(_DISP,__VA_ARGS__) + + +// " #define TE_CONS(name, _) ENUM_CONS(name, TE_DATANAME(name)) -#define TE_CONS2(a, b) TE_CONS a TE_CONS b -#define TE_CONS3(a, ...) TE_CONS a TE_CONS2(__VA_ARGS__) -#define TE_CONS4(a, ...) TE_CONS a TE_CONS3(__VA_ARGS__) -#define TE_CONS5(a, ...) TE_CONS a TE_CONS4(__VA_ARGS__) -#define TE_CONS6(a, ...) TE_CONS a TE_CONS5(__VA_ARGS__) -#define TE_CONS7(a, ...) TE_CONS a TE_CONS6(__VA_ARGS__) -#define TE_CONS8(a, ...) TE_CONS a TE_CONS7(__VA_ARGS__) -#define TE_CONS9(a, ...) TE_CONS a TE_CONS8(__VA_ARGS__) -#define TE_CONS10(a, ...) TE_CONS a TE_CONS9(__VA_ARGS__) // Sizes of structures #define TE_SO(name, _) sizeof(TE_DATANAME(name)) @@ -37,94 +55,39 @@ #define MAXS8(a, b, c, d, e, f, g, h) MAX2(MAXS4(a, b, c, d), MAXS4(e, f, g, h)) #define MAXS9(a, b, c, d, e, f, g, h, i) MAX2(MAXS4(a, b, c, d), MAXS5(e, f, g, h, i)) #define MAXS10(a, b, c, d, e, f, g, h, i, j) MAX2(MAXS5(a, b, c, d, e), MAXS5(f, g, h, i, j)) +#define MAXS11(a, b, c, d, e, f, g, h, i, j, k) MAX2(MAXS6(a, b, c, d, e, f), MAXS5(g, h, i, j, k)) +#define MAXS12(a, b, c, d, e, f, g, h, i, j, k, l) MAX2(MAXS6(a, b, c, d, e, f), MAXS6(g, h, i, j, k, l)) // Type definitions #define TE_EXP(...) __VA_ARGS__ -#define TE_TYPEDEF(name, content) struct TE_DATANAME(name) { TE_EXP content };/* +#define TE_TYPEDEF(name, content) struct TE_DATANAME(name) { TE_EXP content; };/* */ -#define TE_TYPEDEF2(_1, _2) TE_TYPEDEF _1 TE_TYPEDEF _2 -#define TE_TYPEDEF3(v, ...) TE_TYPEDEF v TE_TYPEDEF2(__VA_ARGS__) -#define TE_TYPEDEF4(v, ...) TE_TYPEDEF v TE_TYPEDEF3(__VA_ARGS__) -#define TE_TYPEDEF5(v, ...) TE_TYPEDEF v TE_TYPEDEF4(__VA_ARGS__) -#define TE_TYPEDEF6(v, ...) TE_TYPEDEF v TE_TYPEDEF5(__VA_ARGS__) -#define TE_TYPEDEF7(v, ...) TE_TYPEDEF v TE_TYPEDEF6(__VA_ARGS__) -#define TE_TYPEDEF8(v, ...) TE_TYPEDEF v TE_TYPEDEF7(__VA_ARGS__) -#define TE_TYPEDEF9(v, ...) TE_TYPEDEF v TE_TYPEDEF8(__VA_ARGS__) -#define TE_TYPEDEF10(v, ...) TE_TYPEDEF v TE_TYPEDEF9(__VA_ARGS__) #define TE_TAG(name, _) name, -#define TE_TAG2(_1,_2) TE_TAG _1 TE_TAG _2 -#define TE_TAG3(_1,...) TE_TAG _1 TE_TAG2(__VA_ARGS__) -#define TE_TAG4(_1,...) TE_TAG _1 TE_TAG3(__VA_ARGS__) -#define TE_TAG5(_1,...) TE_TAG _1 TE_TAG4(__VA_ARGS__) -#define TE_TAG6(_1,...) TE_TAG _1 TE_TAG5(__VA_ARGS__) -#define TE_TAG7(_1,...) TE_TAG _1 TE_TAG6(__VA_ARGS__) -#define TE_TAG8(_1,...) TE_TAG _1 TE_TAG7(__VA_ARGS__) -#define TE_TAG9(_1,...) TE_TAG _1 TE_TAG9(__VA_ARGS__) -#define TE_TAG10(_1,...) TE_TAG _1 TE_TAG9(__VA_ARGS__) +// Destructor internals #define TE_DEST_CASE(tag, _) case tag: as_##tag().~TE_DATANAME(tag)(); break;/* */ -#define TE_DEST_CASE2(_1,_2) TE_DEST_CASE _1 TE_DEST_CASE _2 -#define TE_DEST_CASE3(v, ...) TE_DEST_CASE v TE_DEST_CASE2(__VA_ARGS__) -#define TE_DEST_CASE4(v, ...) TE_DEST_CASE v TE_DEST_CASE3(__VA_ARGS__) -#define TE_DEST_CASE5(v, ...) TE_DEST_CASE v TE_DEST_CASE4(__VA_ARGS__) -#define TE_DEST_CASE6(v, ...) TE_DEST_CASE v TE_DEST_CASE5(__VA_ARGS__) -#define TE_DEST_CASE7(v, ...) TE_DEST_CASE v TE_DEST_CASE6(__VA_ARGS__) -#define TE_DEST_CASE8(v, ...) TE_DEST_CASE v TE_DEST_CASE7(__VA_ARGS__) -#define TE_DEST_CASE9(v, ...) TE_DEST_CASE v TE_DEST_CASE8(__VA_ARGS__) -#define TE_DEST_CASE10(v, ...) TE_DEST_CASE v TE_DEST_CASE9(__VA_ARGS__) +// move constructor internals #define TE_MOVE_CASE(tag, _) case tag: new(m_data) TE_DATANAME(tag)(x.unwrap_##tag()); break;/* */ -#define TE_MOVE_CASE2(_1,_2) TE_MOVE_CASE _1 TE_MOVE_CASE _2 -#define TE_MOVE_CASE3(v, ...) TE_MOVE_CASE v TE_MOVE_CASE2(__VA_ARGS__) -#define TE_MOVE_CASE4(v, ...) TE_MOVE_CASE v TE_MOVE_CASE3(__VA_ARGS__) -#define TE_MOVE_CASE5(v, ...) TE_MOVE_CASE v TE_MOVE_CASE4(__VA_ARGS__) -#define TE_MOVE_CASE6(v, ...) TE_MOVE_CASE v TE_MOVE_CASE5(__VA_ARGS__) -#define TE_MOVE_CASE7(v, ...) TE_MOVE_CASE v TE_MOVE_CASE6(__VA_ARGS__) -#define TE_MOVE_CASE8(v, ...) TE_MOVE_CASE v TE_MOVE_CASE7(__VA_ARGS__) -#define TE_MOVE_CASE9(v, ...) TE_MOVE_CASE v TE_MOVE_CASE8(__VA_ARGS__) -#define TE_MOVE_CASE10(v, ...) TE_MOVE_CASE v TE_MOVE_CASE9(__VA_ARGS__) // "tag_to_str" internals #define TE_TOSTR_CASE(tag,_) case tag: return #tag;/* */ -#define TE_TOSTR_CASE2(a,b) TE_TOSTR_CASE a TE_TOSTR_CASE b -#define TE_TOSTR_CASE3(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE2(__VA_ARGS__) -#define TE_TOSTR_CASE4(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE3(__VA_ARGS__) -#define TE_TOSTR_CASE5(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE4(__VA_ARGS__) -#define TE_TOSTR_CASE6(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE5(__VA_ARGS__) -#define TE_TOSTR_CASE7(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE6(__VA_ARGS__) -#define TE_TOSTR_CASE8(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE7(__VA_ARGS__) -#define TE_TOSTR_CASE9(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE8(__VA_ARGS__) -#define TE_TOSTR_CASE10(a,...) TE_TOSTR_CASE a TE_TOSTR_CASE9(__VA_ARGS__) // "tag_from_str" internals #define TE_FROMSTR_CASE(tag,_) else if(str == #tag) return tag;/* */ -#define TE_FROMSTR_CASE2(a,b) TE_FROMSTR_CASE a TE_FROMSTR_CASE b -#define TE_FROMSTR_CASE3(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE2(__VA_ARGS__) -#define TE_FROMSTR_CASE4(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE3(__VA_ARGS__) -#define TE_FROMSTR_CASE5(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE4(__VA_ARGS__) -#define TE_FROMSTR_CASE6(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE5(__VA_ARGS__) -#define TE_FROMSTR_CASE7(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE6(__VA_ARGS__) -#define TE_FROMSTR_CASE8(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE7(__VA_ARGS__) -#define TE_FROMSTR_CASE9(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE8(__VA_ARGS__) -#define TE_FROMSTR_CASE10(a,...) TE_FROMSTR_CASE a TE_FROMSTR_CASE9(__VA_ARGS__) -// Macro to obtain a numbered macro for argument counts -#define TE_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,COUNT,...) SUF##COUNT -#define TE_GM(SUF,...) TE_GM_I(SUF,__VA_ARGS__,10,9,8,7,6,5,4,3,2,x) -//#define TE_GMx(SUF,...) TE_GM_I(SUF,__VA_ARGS__,x,x,x,x,x,x,2) - -#define MAXS(...) TE_GM(MAXS ,__VA_ARGS__)(__VA_ARGS__) -#define TE_CONSS(...) TE_GM(TE_CONS ,__VA_ARGS__)(__VA_ARGS__) -#define TE_TYPEDEFS(...) TE_GM(TE_TYPEDEF ,__VA_ARGS__)(__VA_ARGS__) -#define TE_TAGS(...) TE_GM(TE_TAG ,__VA_ARGS__)(__VA_ARGS__) -#define TE_DEST_CASES(...) TE_GM(TE_DEST_CASE,__VA_ARGS__)(__VA_ARGS__) -#define TE_MOVE_CASES(...) TE_GM(TE_MOVE_CASE,__VA_ARGS__)(__VA_ARGS__) -#define TE_TOSTR_CASES(...) TE_GM(TE_TOSTR_CASE ,__VA_ARGS__)(__VA_ARGS__) -#define TE_FROMSTR_CASES(...) TE_GM(TE_FROMSTR_CASE,__VA_ARGS__)(__VA_ARGS__) +#define MAXS(...) TE_GM(MAXS,__VA_ARGS__)(__VA_ARGS__) +#define TE_CONSS(...) TE_GMX(__VA_ARGS__)(TE_CONS , __VA_ARGS__) +#define TE_TYPEDEFS(...) TE_GMX(__VA_ARGS__)(TE_TYPEDEF ,__VA_ARGS__) +#define TE_TAGS(...) TE_GMX(__VA_ARGS__)(TE_TAG ,__VA_ARGS__) +#define TE_DEST_CASES(...) TE_GMX(__VA_ARGS__)(TE_DEST_CASE,__VA_ARGS__) +#define TE_MOVE_CASES(...) TE_GMX(__VA_ARGS__)(TE_MOVE_CASE,__VA_ARGS__) +#define TE_TOSTR_CASES(...) TE_GMX(__VA_ARGS__)(TE_TOSTR_CASE ,__VA_ARGS__) +#define TE_FROMSTR_CASES(...) TE_GMX(__VA_ARGS__)(TE_FROMSTR_CASE,__VA_ARGS__) #define TAGGED_ENUM(_name, _def, ...) \ class _name { \ @@ -175,3 +138,6 @@ class _name { \ Range, struct { ::std::unique_ptr<ExprNode> left; ::std::unique_ptr<ExprNode> right; } ) m_contents; */ + +#endif + diff --git a/src/main.cpp b/src/main.cpp index 710b7e89..6515685a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,12 +20,11 @@ int g_debug_indent_level = 0; bool debug_enabled()
{
-
- return true;
+ return true;
}
::std::ostream& debug_output(int indent, const char* function)
{
- return ::std::cout << g_cur_phase << "- " << RepeatLitStr { " ", indent } << function << ": ";
+ return ::std::cout << g_cur_phase << "- " << RepeatLitStr { " ", indent } << function << ": ";
}
struct ProgramParams
@@ -84,17 +83,19 @@ int main(int argc, char *argv[]) // XXX: Dump crate before resolve
CompilePhaseV("Temp output - Parsed", [&]() {
- Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate );
+ Dump_Rust( FMT(params.outfile << "_0_pp.rs").c_str(), crate );
});
// Resolve names to be absolute names (include references to the relevant struct/global/function)
+ // - This does name checking on types and free functions.
+ // - Resolves all identifiers/paths to references
CompilePhaseV("Resolve", [&]() {
ResolvePaths(crate);
});
// XXX: Dump crate before typecheck
CompilePhaseV("Temp output - Resolved", [&]() {
- Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate );
+ Dump_Rust( FMT(params.outfile << "_1_res.rs").c_str(), crate );
});
// Replace type aliases (`type`) into the actual type
@@ -102,6 +103,9 @@ int main(int argc, char *argv[]) //
});
+ // Perform type checking on items
+
+ //
// Typecheck / type propagate module (type annotations of all values)
// - Check all generic conditions (ensure referenced trait is valid)
// > Also mark parameter with applicable traits
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 diff --git a/src/types.hpp b/src/types.hpp index 997031de..8e869f19 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -13,17 +13,6 @@ class ExprNode; class Expr;
}
-/// Representation of restrictions placed on a type before it is made concrete
-// Possible bounds:
-// - Known to be a tuple of various inner types
-// - Unknown struct / enum
-// - Impls a trait
-// - Unknown
-class TypeBounds
-{
-
-};
-
class PrettyPrintType
{
const TypeRef& m_type;
@@ -37,117 +26,168 @@ public: friend ::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v);
};
+struct TypeArgRef
+{
+ ::std::string name;
+ unsigned int level;
+ const AST::TypeParams* params;
+};
+
+struct Type_Function:
+ public Serialisable
+{
+ bool is_unsafe;
+ ::std::string m_abi;
+ ::std::unique_ptr<TypeRef> m_rettype;
+ ::std::vector<TypeRef> m_arg_types;
+
+ Type_Function() {}
+ Type_Function(bool is_unsafe, ::std::string abi, ::std::unique_ptr<TypeRef> ret, ::std::vector<TypeRef> args):
+ is_unsafe(is_unsafe),
+ m_abi(abi),
+ m_rettype(mv$(ret)),
+ m_arg_types(mv$(args))
+ {}
+ Type_Function(const Type_Function& other);
+
+ Ordering ord(const Type_Function& x) const;
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+TAGGED_ENUM(TypeData, None,
+ (None, ()),
+ (Any, ()),
+ (Unit, ()),
+ (Primitive, (
+ enum eCoreType core_type;
+ )),
+ (Function, (
+ Type_Function info;
+ )),
+ (Tuple, (
+ ::std::vector<TypeRef> inner_types;
+ )),
+ (Borrow, (
+ bool is_mut;
+ ::std::unique_ptr<TypeRef> inner;
+ )),
+ (Pointer, (
+ bool is_mut;
+ ::std::unique_ptr<TypeRef> inner;
+ )),
+ (Array, (
+ ::std::unique_ptr<TypeRef> inner;
+ ::std::shared_ptr<AST::ExprNode> size;
+ )),
+ (Generic, (
+ ::std::string name;
+ unsigned int level;
+ const AST::TypeParams* params;
+ )),
+ (Path, (
+ AST::Path path;
+ )),
+ (TraitObject, (
+ ::std::vector<AST::Path> traits;
+ ))
+ );
+
/// A type
class TypeRef:
public Serialisable
{
- /// Class
- enum Class {
- NONE,
- ANY, //< '_' - Wildcard
- //BOUNDED, //< '_: Traits' - Bounded type (a resolved type parameter usually)
- UNIT, //< '()' - Unit / void
- PRIMITIVE, //< Any primitive (builtin type)
- FUNCTION,
- TUPLE,
- REFERENCE,
- POINTER,
- ARRAY,
- GENERIC,
- PATH,
- MULTIDST, // Multi-trait DST (e.g. Trait + Send + Sync)
- };
-
- Class m_class;
- enum eCoreType m_core_type;
- bool m_is_inner_mutable;
-
- AST::Path m_path; // local = argument
- ::std::vector<TypeRef> m_inner_types;
- ::std::shared_ptr<AST::ExprNode> m_size_expr; //< Can be null (unsized array)
+ TypeData m_data;
/// A generic pointer, used for tagging with extra information
/// e.g. The source TypeParams for GENERIC
const void* m_tagged_ptr;
public:
+ TypeRef(TypeRef&& other) noexcept:
+ m_data( mv$(other.m_data) )
+ {}
+
+ TypeRef(const TypeRef& other)
+ {
+ switch( other.m_data.tag() )
+ {
+ #define _COPY(VAR) case TypeData::VAR: m_data = TypeData::make_##VAR(other.m_data.as_##VAR()); break;
+ #define _CLONE(VAR, code...) case TypeData::VAR: { auto& old = other.m_data.as_##VAR(); m_data = TypeData::make_##VAR(code); } break;
+ _COPY(None)
+ _COPY(Any)
+ _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
+ }
+ }
+ TypeRef& operator=(const TypeRef& other) {
+ *this = TypeRef(other);
+ return *this;
+ }
+
TypeRef():
- m_class(ANY)
+ m_data(TypeData::make_Any({}))
{}
struct TagInvalid {};
TypeRef(TagInvalid):
- m_class(NONE)
- {}
-
- struct TagBoundedAny {};
- TypeRef(TagBoundedAny, ::std::vector<TypeRef> traits):
- m_class(ANY),
- m_inner_types( ::std::move(traits) )
+ m_data(TypeData::make_None({}))
{}
struct TagUnit {}; // unit maps to a zero-length tuple, just easier to type
TypeRef(TagUnit):
- m_class(UNIT)
+ m_data(TypeData::make_Unit({}))
{}
struct TagPrimitive {};
TypeRef(TagPrimitive, enum eCoreType type):
- m_class(PRIMITIVE),
- m_core_type(type)
+ m_data(TypeData::make_Primitive({type}))
{}
TypeRef(enum eCoreType type):
- m_class(PRIMITIVE),
- m_core_type(type)
+ m_data(TypeData::make_Primitive({type}))
{}
struct TagTuple {};
TypeRef(TagTuple _, ::std::vector<TypeRef> inner_types):
- m_class(TUPLE),
- m_inner_types( ::std::move(inner_types) )
+ m_data(TypeData::make_Tuple({::std::move(inner_types)}))
{}
struct TagFunction {};
TypeRef(TagFunction, ::std::string abi, ::std::vector<TypeRef> args, TypeRef ret):
- m_class(FUNCTION),
- m_path( {AST::PathNode( ::std::move(abi), {})} ), // abuse path for string
- m_inner_types( ::std::move(args) )
- {
- m_inner_types.push_back( ::std::move(ret) );
- }
+ m_data(TypeData::make_Function({ Type_Function( false, abi, box$(ret), mv$(args) ) }))
+ {}
struct TagReference {};
TypeRef(TagReference _, bool is_mut, TypeRef inner_type):
- m_class(REFERENCE),
- m_is_inner_mutable(is_mut),
- m_inner_types({::std::move(inner_type)})
+ m_data(TypeData::make_Borrow({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
{}
struct TagPointer {};
TypeRef(TagPointer _, bool is_mut, TypeRef inner_type):
- m_class(POINTER),
- m_is_inner_mutable(is_mut),
- m_inner_types({::std::move(inner_type)})
+ m_data(TypeData::make_Pointer({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
{}
struct TagSizedArray {};
TypeRef(TagSizedArray _, TypeRef inner_type, ::std::shared_ptr<AST::ExprNode> size):
- m_class(ARRAY),
- m_inner_types({::std::move(inner_type)}),
- m_size_expr( ::std::move(size) )
+ m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), mv$(size) }))
{}
struct TagUnsizedArray {};
TypeRef(TagUnsizedArray _, TypeRef inner_type):
- m_class(ARRAY),
- m_inner_types({::std::move(inner_type)})
+ m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), ::std::shared_ptr<AST::ExprNode>() }))
{}
struct TagArg {};
TypeRef(TagArg, ::std::string name):
- m_class(GENERIC),
- m_path( ::std::move(name) ),
- m_tagged_ptr(nullptr)
+ m_data(TypeData::make_Generic({ name, 0, nullptr }))
{}
TypeRef(TagArg, ::std::string name, const AST::TypeParams& params):
- m_class(GENERIC),
- m_path( ::std::move(name) ),
- m_tagged_ptr(¶ms)
+ m_data(TypeData::make_Generic({ name, 0, ¶ms }))
{}
TypeRef(::std::string name):
TypeRef(TagArg(), ::std::move(name))
@@ -155,19 +195,15 @@ public: struct TagPath {};
TypeRef(TagPath, AST::Path path):
- m_class(PATH),
- m_path( ::std::move(path) )
+ m_data(TypeData::make_Path({ ::std::move(path) }))
{}
TypeRef(AST::Path path):
TypeRef(TagPath(), ::std::move(path))
{}
TypeRef( ::std::vector<AST::Path> traits ):
- m_class(MULTIDST)
- {
- for( auto& t : traits )
- m_inner_types.push_back( TypeRef(::std::move(t)) );
- }
+ m_data(TypeData::make_TraitObject({ ::std::move(traits) }))
+ {}
/// Dereference the type (return the result of *type_instance)
bool deref(bool is_implicit);
@@ -183,33 +219,33 @@ public: /// Returns true if the type is fully known (all sub-types are not wildcards)
bool is_concrete() const;
- bool is_unbounded() const { return m_class == ANY && m_inner_types.size() == 0; }
- bool is_wildcard() const { return m_class == ANY; }
+ bool is_unbounded() const { return m_data.is_Any(); }
+ bool is_wildcard() const { return m_data.is_Any(); }
- bool is_unit() const { return m_class == UNIT; }
- bool is_primitive() const { return m_class == PRIMITIVE; }
+ bool is_unit() const { return m_data.is_Unit(); }
+ bool is_primitive() const { return m_data.is_Primitive(); }
- bool is_path() const { return m_class == PATH; }
- const AST::Path& path() const { assert(is_path()); return m_path; }
- AST::Path& path() { assert(is_path()); return m_path; }
+ bool is_path() const { return m_data.is_Path(); }
+ const AST::Path& path() const { return m_data.as_Path().path; }
+ AST::Path& path() { return m_data.as_Path().path; }
- bool is_type_param() const { return m_class == GENERIC; }
- const ::std::string& type_param() const { assert(is_type_param()); return m_path[0].name(); }
+ bool is_type_param() const { return m_data.is_Generic(); }
+ const ::std::string& type_param() const { return m_data.as_Generic().name; }
void set_type_params_ptr(const AST::TypeParams& p) { assert(is_type_param()); m_tagged_ptr = &p; };
const AST::TypeParams* type_params_ptr() const {
assert(is_type_param());
return reinterpret_cast<const AST::TypeParams*>(m_tagged_ptr);
}
- bool is_reference() const { return m_class == REFERENCE; }
- bool is_pointer() const { return m_class == POINTER; }
- bool is_tuple() const { return m_class == TUPLE; }
+ bool is_reference() const { return m_data.is_Borrow(); }
+ bool is_pointer() const { return m_data.is_Pointer(); }
+ bool is_tuple() const { return m_data.is_Tuple(); }
- ::std::vector<TypeRef>& sub_types() { return m_inner_types; }
- const ::std::vector<TypeRef>& sub_types() const { return m_inner_types; }
+ //::std::vector<TypeRef>& sub_types() { return m_inner_types; }
+ //const ::std::vector<TypeRef>& sub_types() const { return m_inner_types; }
- void add_trait(TypeRef trait) { assert(is_wildcard()); m_inner_types.push_back( ::std::move(trait) ); }
- const ::std::vector<TypeRef>& traits() const { assert(is_wildcard()); return m_inner_types; }
+ //void add_trait(TypeRef trait) { assert(is_wildcard()); m_inner_types.push_back( ::std::move(trait) ); }
+ //const ::std::vector<TypeRef>& traits() const { assert(is_wildcard()); return m_inner_types; }
/// Returns 0 if types are identical, 1 if TypeRef::TagArg is present in one, and -1 if form differs
int equal_no_generic(const TypeRef& x) const;
@@ -224,20 +260,9 @@ public: friend class PrettyPrintType;
friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
-
- static const char* class_name(TypeRef::Class c);
- friend void operator>>(::Deserialiser& d, TypeRef::Class& c);
+ static ::std::unique_ptr<TypeRef> from_deserialiser(Deserialiser& s);
SERIALISABLE_PROTOTYPES();
};
-class Type_Function:
- public Serialisable
-{
- bool is_unsafe;
- ::std::string m_abi;
- TypeRef m_rettype;
- ::std::vector<TypeRef> m_arg_types;
-};
-
#endif // TYPES_HPP_INCLUDED
|