diff options
author | John Hodge <tpg@mutabah.net> | 2015-09-19 18:16:36 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-09-19 18:16:36 +0800 |
commit | e6738ed57d644572e7cbefa6d68a4118935a5f80 (patch) | |
tree | a38b823d4b3771b045239a2f811eb63824a1032c | |
parent | 03e211d6eeb3f8f3c6f0b22f77c2074e81443952 (diff) | |
download | mrust-e6738ed57d644572e7cbefa6d68a4118935a5f80.tar.gz |
Disable UFCS resolve (due to ordering issues), fix Self handling
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | src/ast/path.cpp | 23 | ||||
-rw-r--r-- | src/ast/path.hpp | 3 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 40 | ||||
-rw-r--r-- | src/convert/ast_iterate.hpp | 5 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 172 | ||||
-rw-r--r-- | src/include/span.hpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/parse/root.cpp | 1 | ||||
-rw-r--r-- | src/types.hpp | 1 |
10 files changed, 210 insertions, 51 deletions
@@ -28,6 +28,8 @@ OBJ += convert/resolve.o convert/typecheck_bounds.o convert/typecheck_params.o c OBJ += convert/flatten.o convert/render.o OBJ += synexts/derive.o synexts/lang_item.o +PCHS := ast/ast.hpp + OBJ := $(addprefix $(OBJDIR),$(OBJ)) @@ -64,6 +66,12 @@ $(OBJDIR)%.o: src/%.cpp @echo [CXX] -o $@ $V$(CXX) -o $@ -c $< $(CXXFLAGS) $(CPPFLAGS) -MMD -MP -MF $@.dep +src/main.cpp: $(PCHS:%=src/%.gch) + +%.hpp.gch: %.hpp + @echo [CXX] -o $@ + $V$(CXX) -std=c++11 -o $@ $< $(CPPFLAGS) -MMD -MP -MF $@.dep + -include $(OBJ:%=%.dep) # vim: noexpandtab ts=4 diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 247a6b2b..8fe42527 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -115,6 +115,24 @@ AST::Path::Path(const Path& x): ) ) + memcpy(&m_binding, &x.m_binding, sizeof(PathBinding)); + //TU_MATCH(PathBinding, (x.m_binding), (ent), + //(Unbound, m_binding = PathBinding::make_Unbound({}); ), + //(Module, os << "Module"; ), + //(Trait, os << "Trait"; ), + //(Struct, os << "Struct"; ), + //(Enum, os << "Enum"; ), + //(Static, os << "Static"; ), + //(Function, os << "Function";), + //(EnumVar, os << "EnumVar(" << i.idx << ")"; ), + //(TypeAlias, os << "TypeAlias";), + //(StructMethod, os << "StructMethod"; ), + //(TraitMethod, os << "TraitMethod"; ), + // + //(TypeParameter, os << "TypeParameter(" << i.level << " # " << i.idx << ")"; ), + //(Variable, os << "Variable(" << i.slot << ")"; ) + //) + DEBUG("clone, x = " << x << ", this = " << *this ); } @@ -454,7 +472,7 @@ void Path::resolve_ufcs(const Crate& root_crate, bool expect_params) void Path::resolve_ufcs_trait(const AST::Path& trait_path, AST::PathNode& node) { if( !trait_path.m_binding.is_Trait() ) - throw ParseError::Generic("Path::resolve_ufcs - Trait in UFCS path is not a trait"); + ERROR(trait_path.span(), E0000, "Trait in UFCS path is not a trait"); const auto& trait_def = *trait_path.m_binding.as_Trait().trait_; // Check that the requested item exists within the trait, and bind to that item @@ -843,7 +861,6 @@ void Path::print_pretty(::std::ostream& os) const #endif os << n; } - os << "/*" << path.m_binding << "*/"; ), (UFCS, os << "/*ufcs*/<" << *ent.type << " as " << *ent.trait << ">"; @@ -851,7 +868,7 @@ void Path::print_pretty(::std::ostream& os) const os << "::" << n; ) ) - os << "/*[" << path.span().filename << ":" << path.span().start_line << "]*/"; + os << "/*" << path.m_binding << " [" << path.span().filename << ":" << path.span().start_line << "]*/"; #else switch(path.m_class) { diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 9e190453..d0cc5648 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -145,7 +145,8 @@ public: m_crate = mv$(x.m_crate); m_class = mv$(x.m_class); //m_span = mv$(x.m_span); - x.m_binding = mv$(x.m_binding); + m_binding = mv$(x.m_binding); + //DEBUG("Path, " << x); return *this; } diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index cdb927e6..2946fd63 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -70,16 +70,22 @@ void CASTIterator::handle_params(AST::TypeParams& params) (IsTrait, handle_type(ent.type); // TODO: Define HRLs + push_self(ent.type); handle_path(ent.trait, CASTIterator::MODE_TYPE); + pop_self(); ), (MaybeTrait, handle_type(ent.type); + push_self(ent.type); handle_path(ent.trait, CASTIterator::MODE_TYPE); + pop_self(); // TODO: Process trait, ensuring that it's a valid lang item ), (NotTrait, handle_type(ent.type); + push_self(ent.type); handle_path(ent.trait, CASTIterator::MODE_TYPE); + pop_self(); ), (Equality, handle_type(ent.type); @@ -347,24 +353,24 @@ void CASTIterator::handle_function(AST::Path path, AST::Function& fcn) void CASTIterator::handle_impl_def(AST::ImplDef& impl) { - // First, so that handle_params can use it - local_type("Self", impl.type()); - // Generic params handle_params( impl.params() ); + // Type + handle_type( impl.type() ); + + push_self(impl.type()); + // Trait if( impl.trait() != AST::Path() ) handle_path( impl.trait(), MODE_TYPE ); - // Type - handle_type( impl.type() ); } void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) { start_scope(); - handle_impl_def(impl.def()); + handle_impl_def(impl.def()); // Associated types for( auto& at : impl.types() ) @@ -380,6 +386,7 @@ void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) handle_function(AST::Path(AST::Path::TagRelative(), { AST::PathNode(fcn.name) }), fcn.data); } + pop_self(); end_scope(); } @@ -405,14 +412,21 @@ void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm) void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait) { start_scope(); - local_type("Self", TypeRef(TypeRef::TagArg(), "Self")); + push_self(path, trait); handle_params( trait.params() ); - //local_type("Self", TypeRef(path)); - //local_type("Self", TypeRef(TypeRef::TagArg(), "Self")); + for( auto& st : trait.supertraits() ) { + if( st.m_class.is_Invalid() ) { + // An invalid path is used for 'static + } + else { + handle_path(st, MODE_TYPE); + } + } for( auto& fcn : trait.functions() ) handle_function( path + fcn.name, fcn.data ); + pop_self(); end_scope(); } void CASTIterator::handle_alias(AST::Path path, AST::TypeAlias& alias) @@ -422,3 +436,11 @@ void CASTIterator::handle_alias(AST::Path path, AST::TypeAlias& alias) handle_type( alias.type() ); end_scope(); } +void CASTIterator::push_self() { +} +void CASTIterator::push_self(AST::Path path, const AST::Trait& trait) { +} +void CASTIterator::push_self(TypeRef real_type) { +} +void CASTIterator::pop_self() { +} diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp index 14537b10..4b271bfb 100644 --- a/src/convert/ast_iterate.hpp +++ b/src/convert/ast_iterate.hpp @@ -54,6 +54,11 @@ public: virtual void handle_enum(AST::Path path, AST::Enum& enm); virtual void handle_trait(AST::Path path, AST::Trait& trait); virtual void handle_alias(AST::Path path, AST::TypeAlias& alias); + + virtual void push_self(); + virtual void push_self(AST::Path path, const AST::Trait& trait); + virtual void push_self(TypeRef real_type); + virtual void pop_self(); private: void handle_impl_def(AST::ImplDef& impl); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index bdbf1854..38808831 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -16,6 +16,11 @@ class CPathResolver:
public CASTIterator
{
+ const AST::Crate& m_crate;
+ AST::Module* m_module;
+ AST::Path m_module_path;
+
+
struct LocalItem
{
enum Type {
@@ -43,10 +48,8 @@ class CPathResolver: return os << "var '" << x.name << "'";
}
};
- const AST::Crate& m_crate;
- AST::Module* m_module;
- AST::Path m_module_path;
::std::vector< LocalItem > m_locals;
+
struct Scope {
unsigned int module_idx;
AST::Module *module; // can be NULL
@@ -56,7 +59,19 @@ class CPathResolver: ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > traits;
};
::std::vector<Scope> m_scope_stack;
- ::std::vector< TypeRef > m_self_type;
+
+
+ TAGGED_UNION(SelfType, None,
+ (None, ()),
+ (Type, (
+ TypeRef type;
+ )),
+ (Trait, (
+ AST::Path path;
+ const AST::Trait* trait;
+ ))
+ );
+ ::std::vector<SelfType> m_self_type;
friend class CResolvePaths_NodeVisitor;
@@ -106,6 +121,19 @@ public: bool find_super_mod_item(AST::Path& path, const ::std::string& name);
bool find_type_param(const ::std::string& name);
+ virtual void push_self() override {
+ m_self_type.push_back( SelfType::make_None({}) );
+ }
+ virtual void push_self(AST::Path path, const AST::Trait& trait) override {
+ m_self_type.push_back( SelfType::make_Trait( {path, &trait} ) );
+ }
+ virtual void push_self(TypeRef real_type) override {
+ m_self_type.push_back( SelfType::make_Type( {real_type} ) );
+ }
+ virtual void pop_self() override {
+ m_self_type.pop_back();
+ }
+
// TODO: Handle a block and obtain the local module (if any)
private:
void handle_path_int(AST::Path& path, CASTIterator::PathMode mode);
@@ -393,6 +421,7 @@ bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, c /// Perform path resolution within a generic definition block
void CPathResolver::handle_params(AST::TypeParams& params)
{
+ TRACE_FUNCTION;
// Parameters
DEBUG("params");
for( auto& param : params.ty_params() )
@@ -405,6 +434,8 @@ void CPathResolver::handle_params(AST::TypeParams& params) DEBUG("Bounds");
for( auto& bound : params.bounds() )
{
+ DEBUG("- Bound " << bound);
+
TU_MATCH(AST::GenericBound, (bound), (ent),
(Lifetime,
{}
@@ -414,21 +445,22 @@ void CPathResolver::handle_params(AST::TypeParams& params) ),
(IsTrait,
handle_type(ent.type);
- m_self_type.push_back( TypeRef() );
+ // TODO: Should 'Self' in this trait be ent.type?
+ push_self(ent.type);
handle_path(ent.trait, MODE_TYPE);
- m_self_type.pop_back();
+ pop_self();
),
(MaybeTrait,
handle_type(ent.type);
- m_self_type.push_back( TypeRef() );
+ push_self();
handle_path(ent.trait, MODE_TYPE);
- m_self_type.pop_back();
+ pop_self();
),
(NotTrait,
handle_type(ent.type);
- m_self_type.push_back( TypeRef() );
+ push_self();
handle_path(ent.trait, MODE_TYPE);
- m_self_type.pop_back();
+ pop_self();
),
(Equality,
handle_type(ent.type);
@@ -480,7 +512,7 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) )
}
void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode)
-{
+{
// Convert to absolute
// - This means converting all partial forms (i.e. not UFCS, Variable, or Absolute)
switch( path.class_tag() )
@@ -565,7 +597,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode // - If there are more nodes, replace with a UFCS block
{
auto tp = this->find_type_param(path[0].name());
- if( tp != false /*nullptr*/ )
+ if( tp != false /*nullptr*/ || path[0].name() == "Self" )
{
if(path.size() > 1) {
// Repalce with UFCS
@@ -633,14 +665,16 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod assert(path.m_class.is_UFCS());
auto& info = path.m_class.as_UFCS();
TRACE_FUNCTION_F("info={< " << *info.type << " as " << *info.trait << ">::" << info.nodes << "}");
- const ::std::string& item_name = info.nodes[0].name();
// 1. Handle sub-types
handle_type(*info.type);
handle_type(*info.trait);
// 2. Handle wildcard traits (locate in inherent impl, or from an in-scope trait)
+ // TODO: Disabled, as it requires having all traits (semi) path resolved, so that trait resolution works cleanly
if( info.trait->is_wildcard() )
{
- DEBUG("Searching for impls when trait is _ (trait = " << *info.trait << ")");
+ #if 0
+ const ::std::string& item_name = info.nodes[0].name();
+ DEBUG("Searching for matching trait for '"<<item_name<<"' on type " << *info.type);
// Search applicable type parameters for known implementations
@@ -649,10 +683,32 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod ::std::vector<TypeRef> params;
if( info.type->is_type_param() && info.type->type_param() == "Self" )
{
+ DEBUG("Checking Self trait and sub-traits");
// TODO: What is "Self" here? May want to use `GenericBound`s to replace Self with the actual type when possible.
// In which case, Self will refer to "implementor of this trait".
// - Look up applicable traits for this type, using bounds (basically same as next)
- throw ParseError::Todo("CPathResolver::handle_path_ufcs - Handle '<Self as _>::...'");
+ assert( !m_self_type.empty() );
+ assert( m_self_type.back().is_Trait() );
+ AST::Path p = m_self_type.back().as_Trait().path;
+ handle_path(p, MODE_TYPE);
+ AST::Trait& t = *const_cast<AST::Trait*>(m_self_type.back().as_Trait().trait);
+
+ bool is_method;
+ AST::Path found_trait_path;
+ if( this->find_trait_item(p, t, item_name, is_method, found_trait_path) ) {
+ if( is_method ) {
+ if( info.nodes.size() != 1 )
+ ERROR(path.span(), E0000, "CPathResolver::handle_path_ufcs - Sub-nodes to method");
+ }
+ else {
+ if( info.nodes.size() != 1 )
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - Sub nodes on associated type");
+ }
+ *info.trait = TypeRef( mv$(found_trait_path) );
+ }
+ else {
+ ERROR(path.span(), E0000, "Cannot find item '" << item_name << "' on Self");
+ }
}
else if( info.type->is_type_param() )
{
@@ -703,6 +759,7 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod }
else
{
+ DEBUG("(maybe) known type");
// Iterate all inherent impls
for( auto impl : m_crate.find_inherent_impls(*info.type) ) {
IF_OPTION_SOME(item, impl.find_named_item(item_name), {
@@ -733,13 +790,19 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait");
}
+
+ path.resolve(m_crate);
+ #endif
+ }
+ else {
+ // 3. Call resolve to attempt binding
+ path.resolve(m_crate);
}
- // 3. Call resolve to attempt binding
- path.resolve(m_crate);
}
bool CPathResolver::find_trait_item(const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path)
{
+ TRACE_FUNCTION_F("path=" << path << ", trait=..., item_name=" << item_name);
{
const auto& fcns = trait.functions();
//DEBUG("fcns = " << fcns);
@@ -747,8 +810,8 @@ bool CPathResolver::find_trait_item(const AST::Path& path, AST::Trait& trait, co if( it != fcns.end() ) {
// Found it.
out_is_method = true;
- DEBUG("&out_trait_path = " << &out_trait_path);
out_trait_path = AST::Path(path);
+ DEBUG("Fcn, out_trait_path = " << out_trait_path);
return true;
}
}
@@ -759,14 +822,30 @@ bool CPathResolver::find_trait_item(const AST::Path& path, AST::Trait& trait, co // Found it.
out_is_method = false;
out_trait_path = AST::Path(path);
+ DEBUG("Ty, out_trait_path = " << out_trait_path << " path=" << path);
return true;
}
}
for( auto& st : trait.supertraits() ) {
- assert(st.is_bound());
- if( this->find_trait_item(st, *const_cast<AST::Trait*>(st.binding().as_Trait().trait_), item_name, out_is_method, out_trait_path) )
+ if(!st.is_bound()) {
+ handle_path(st, MODE_TYPE);
+ //BUG(st.span(), "Supertrait path '"<<st<<"' of '"<<path<<"' is not bound");
+ }
+ AST::Trait& super_t = *const_cast<AST::Trait*>(st.binding().as_Trait().trait_);
+ if( this->find_trait_item(st, super_t, item_name, out_is_method, out_trait_path) ) {
+ DEBUG("path = " << path << ", super_t.params() = " << super_t.params() << ", out_trait_path = " << out_trait_path);
+ //
+ out_trait_path.resolve_args([&](const char* name) {
+ int idx = trait.params().find_name(name);
+ if(idx < 0)
+ ERROR(st.span(), E0000, "Parameter " << name << " not found");
+ const auto& tr = path.nodes().back().args().at(idx);
+ DEBUG("Replacing '" << name << "' with " << tr);
+ return tr;
+ });
return true;
+ }
}
return false;
@@ -865,11 +944,25 @@ void CPathResolver::handle_type(TypeRef& type) else if( name == "Self" )
{
// If the name was "Self", but Self isn't already defined... then we need to make it an arg?
- ERROR(type.path().span(), E0000, "Unexpected 'Self'");
-
- TypeRef nt = TypeRef(TypeRef::TagArg(), "Self");
- nt.set_span(type.span());
- type = nt;
+ if( this->m_self_type.empty() || this->m_self_type.back().is_None() ) {
+ ERROR(type.path().span(), E0000, "Unexpected 'Self'");
+ }
+ else {
+ TU_MATCH(SelfType, (this->m_self_type.back()), (ent),
+ (None,
+ assert(!"");
+ ),
+ (Type,
+ type = ent.type;
+ return ;
+ ),
+ (Trait,
+ // TODO: Need to have the trait encoded in the type. To avoid interpolation and bad replacement
+ // - Would also reduce the need to look at the m_self_type stack
+ type = TypeRef(TypeRef::TagArg(), "Self");
+ )
+ )
+ }
}
else
{
@@ -880,14 +973,25 @@ void CPathResolver::handle_type(TypeRef& type) {
const auto& name = type.type_param();
auto opt_local = lookup_local(LocalItem::TYPE, name);
- /*if( name == "Self" )
+ if( name == "Self" )
{
- // Good as it is
- // - TODO: Allow replacing this with the real Self (e.g. in an impl block)
- // - NEED to annotate with the relevant impl block, and with other bounds
- // > So that you can handle 'where Self: Sized' etc
+ if( m_self_type.empty() ) {
+ ERROR(type.span(), E0000, "Self type not set");
+ }
+ TU_MATCH(SelfType, (m_self_type.back()), (ent),
+ (None,
+ ERROR(type.span(), E0000, "Self type not set");
+ ),
+ (Type,
+ type = ent.type;
+ return ;
+ ),
+ (Trait,
+ // Valid...
+ )
+ )
}
- else*/ if( opt_local.is_some() )
+ else if( opt_local.is_some() )
{
type = opt_local.unwrap().tr;
}
@@ -965,11 +1069,11 @@ void CPathResolver::handle_module(AST::Path path, AST::Module& mod) }
void CPathResolver::handle_trait(AST::Path path, AST::Trait& trait)
{
+ path.resolve(m_crate);
+
// Handle local
- for( auto& st : trait.supertraits() ) {
- handle_path(st, MODE_TYPE);
- }
m_scope_stack.back().traits.push_back( ::std::pair<AST::Path, const AST::Trait&>(path, trait) );
+ CASTIterator::handle_trait(path, trait);
}
void CPathResolver::handle_function(AST::Path path, AST::Function& fcn)
{
diff --git a/src/include/span.hpp b/src/include/span.hpp index c8c61627..452f37ba 100644 --- a/src/include/span.hpp +++ b/src/include/span.hpp @@ -52,5 +52,6 @@ struct Span void note(::std::function<void(::std::ostream&)> msg) const; }; -#define ERROR(span, code, msg) do { (span).error(code, [](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0) +#define ERROR(span, code, msg) do { (span).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0) +#define BUG(span, msg) do { (span).bug([&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Bug fell through"); } while(0) diff --git a/src/main.cpp b/src/main.cpp index 6515685a..e883b7ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,13 +45,12 @@ Rv CompilePhase(const char *name, Fcn f) { g_cur_phase = name;
auto rv = f();
g_cur_phase = "";
+ ::std::cout << name << ": DONE" << ::std::endl;
return rv;
}
template <typename Fcn>
void CompilePhaseV(const char *name, Fcn f) {
- g_cur_phase = name;
- f();
- g_cur_phase = "";
+ CompilePhase<int>(name, [&]() { f(); return 0; });
}
/// main!
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 422f036e..d0bf795c 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -227,6 +227,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt if( tok.type() == TOK_AMP )
{
// By-reference method?
+ // TODO: If a lifetime is seen (and not a prototype), it is definitely a self binding
unsigned int ofs = 0;
if( lex.lookahead(0) == TOK_LIFETIME )
diff --git a/src/types.hpp b/src/types.hpp index 5bb257c7..90f9ee3b 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -103,6 +103,7 @@ public: TypeData m_data;
TypeRef(TypeRef&& other) noexcept:
+ //m_span( mv$(other.m_span) ),
m_data( mv$(other.m_data) )
{}
|