diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 33 | ||||
-rw-r--r-- | src/ast/ast.hpp | 5 | ||||
-rw-r--r-- | src/ast/path.cpp | 5 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 127 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 6 | ||||
-rw-r--r-- | src/main.cpp | 33 | ||||
-rw-r--r-- | src/parse/root.cpp | 12 |
7 files changed, 178 insertions, 43 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 7ab461d5..7d9e16c5 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -217,6 +217,16 @@ void Crate::post_parse() };
iterate_module(m_root_module, cb);
iterate_module(g_compiler_module, cb);
+
+ // Create a map of inherent impls
+ for( const auto& impl : m_impl_index )
+ {
+ if( impl->def().trait().is_valid() == false )
+ {
+ auto& ent = m_impl_map[impl->def().type()];
+ ent.push_back( impl );
+ }
+ }
}
void Crate::iterate_functions(fcn_visitor_t* visitor)
@@ -286,24 +296,31 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const }
-::std::vector<ImplRef> Crate::find_inherent_impls(const TypeRef& type) const
+bool Crate::find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )> callback) const
{
assert( !type.is_type_param() );
- ::std::vector<ImplRef> ret;
-
for( auto implptr : m_impl_index )
{
Impl& impl = *implptr;
- DEBUG("- " << impl.def());
- ::std::vector<TypeRef> out_params;
- if( impl.def().matches(out_params, AST::Path(), type) )
+ if( impl.def().trait().is_valid() )
+ {
+ // Trait
+ }
+ else
{
- ret.push_back( ImplRef(impl, out_params) );
+ DEBUG("- " << impl.def());
+ ::std::vector<TypeRef> out_params;
+ if( impl.def().matches(out_params, AST::Path(), type) )
+ {
+ if( callback(impl, out_params) ) {
+ return true;
+ }
+ }
}
}
- return ret;
+ return false;
}
::rust::option<ImplRef> Crate::find_impl(const Path& trait, const TypeRef& type) const
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 3b510168..8e6f0361 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -819,6 +819,8 @@ struct ImplRef class Crate:
public Serialisable
{
+public:
+ ::std::map< TypeRef, ::std::vector<Impl*> > m_impl_map;
::std::vector<Impl*> m_impl_index;
::std::vector<const ImplDef*> m_neg_impl_index;
@@ -848,7 +850,8 @@ public: bool is_trait_implicit(const Path& trait) const;
- ::std::vector<ImplRef> find_inherent_impls(const TypeRef& type) const;
+ //::std::vector<ImplRef> find_inherent_impls(const TypeRef& type) const;
+ bool find_inherent_impls(const TypeRef& type, ::std::function<bool(const Impl& , ::std::vector<TypeRef> )>) const;
::rust::option<ImplRef> find_impl(const Path& trait, const TypeRef& type) const;
bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_prams=nullptr) const;
const ::rust::option<Impl&> get_impl(const Path& trait, const TypeRef& type) {
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 1703da53..9ad36515 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -335,6 +335,9 @@ bool Path::is_concrete() const /// cause two different paths to look the same. int Path::equal_no_generic(const Path& x) const { + if( m_class.is_Invalid() && x.m_class.is_Invalid() ) + return 0; + DEBUG("equal_no_generic(this = " << *this << ", x = " << x << ")"); if( m_class.tag() != x.m_class.tag() ) return -1; if( m_crate != x.m_crate ) @@ -435,6 +438,8 @@ void Path::print_pretty(::std::ostream& os, bool is_type_context) const TU_MATCH(Path::Class, (m_class), (ent), (Invalid, os << "/*inv*/"; + // NOTE: Don't print the binding for invalid paths + return ; ), (Local, // Only print comment if there's no binding diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 0e5b9598..5072f57f 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -89,7 +89,7 @@ public: void handle_path_abs__into_ufcs(const Span& span, AST::Path& path, unsigned slice_from, unsigned split_point);
void handle_path_ufcs(const Span& span, AST::Path& path, CASTIterator::PathMode mode);
void handle_path_rel(const Span& span, AST::Path& path, CASTIterator::PathMode mode);
- bool find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path);
+ bool find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, const void*& out_ptr, AST::Path& out_trait_path);
virtual void handle_type(TypeRef& type) override;
virtual void handle_expr(AST::ExprNode& node) override;
@@ -152,6 +152,7 @@ private: ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > inscope_traits() const
{
::std::vector< ::std::pair<AST::Path, const AST::Trait&> > ret;
+ DEBUG("m_module_path = " << m_module_path);
for( auto it = m_scope_stack.rbegin(); it != m_scope_stack.rend(); ++it )
{
for( const auto& t : it->traits ) {
@@ -159,7 +160,33 @@ private: //assert(t.first.binding().is_Trait());
ret.push_back(t);
}
+ if( it->module ) {
+ for( const auto& t : it->module->traits() ) {
+ auto trait_path = it->module_path + t.name;
+ DEBUG("t = " << trait_path);
+ ::std::pair<AST::Path, const AST::Trait&> tr(trait_path, t.data);
+ ret.push_back( tr );
+ }
+ }
+ }
+
+ for( const auto& t : m_module->traits() ) {
+ auto trait_path = m_module_path + t.name;
+ DEBUG("(mod) t = " << trait_path);
+ ::std::pair<AST::Path, const AST::Trait&> tr(trait_path, t.data);
+ ret.push_back( tr );
+ }
+ for( const auto& i : m_module->imports() ) {
+ if( i.data.binding().is_Trait() )
+ {
+ auto& t = *i.data.binding().as_Trait().trait_;
+
+ DEBUG("(use) t = " << i.data);
+ ::std::pair<AST::Path, const AST::Trait&> tr(i.data, t);
+ ret.push_back( tr );
+ }
}
+
return ret;
}
@@ -828,6 +855,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera }
else {
this->handle_path_abs__into_ufcs(span, path, slice_from, i+1);
+ this->handle_path_ufcs(span, path, mode);
// Explicit return - rebase slicing is already done
return ;
}
@@ -851,6 +879,23 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera (Trait,
const auto& t = item;
DEBUG("Found trait");
+ auto& node_args = nodes[i].args();
+ if( mode == MODE_TYPE )
+ {
+ const auto& params = t.params();
+ if( params.ty_params().size() != node_args.size() )
+ {
+ if( node_args.size() == 0 )
+ {
+ while( node_args.size() < params.ty_params().size() )
+ node_args.push_back( params.ty_params()[node_args.size()].get_default() );
+ }
+ else
+ {
+ ERROR(span, E0000, "Incorrect number of type parameters");
+ }
+ }
+ }
if( is_last ) {
//check_param_counts(t.params(), expect_params, nodes[i]);
path.bind_trait(t);
@@ -858,6 +903,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera }
else {
this->handle_path_abs__into_ufcs(span, path, slice_from, i+1);
+ this->handle_path_ufcs(span, path, mode);
// Explicit return - rebase slicing is already done
return ;
}
@@ -867,6 +913,22 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera (Struct,
const auto& str = item;
DEBUG("Found struct");
+ auto& node_args = nodes[i].args();
+ if( mode == MODE_TYPE )
+ {
+ if( str.params().ty_params().size() != node_args.size() )
+ {
+ if( node_args.size() == 0 )
+ {
+ while( node_args.size() < str.params().ty_params().size() )
+ node_args.push_back( str.params().ty_params()[node_args.size()].get_default() );
+ }
+ else
+ {
+ ERROR(span, E0000, "Incorrect number of type parameters");
+ }
+ }
+ }
if( is_last ) {
//check_param_counts(str.params(), expect_params, nodes[i]);
path.bind_struct(str, node.args());
@@ -874,6 +936,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera }
else {
this->handle_path_abs__into_ufcs(span, path, slice_from, i+1);
+ this->handle_path_ufcs(span, path, mode);
// Explicit return - rebase slicing is already done
return ;
}
@@ -890,6 +953,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera }
else {
this->handle_path_abs__into_ufcs(span, path, slice_from, i+1);
+ this->handle_path_ufcs(span, path, mode);
// Explicit return - rebase slicing is already done
return ;
}
@@ -1014,7 +1078,7 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter // 1. Search inherent impls
// 2. If doing a late pass (after module-level names are resolved) search for traits
if( this->m_second_pass ) {
- #if 0
+ #if 1
const ::std::string& item_name = info.nodes[0].name();
DEBUG("Searching for matching trait for '"<<item_name<<"' on type " << *info.type);
@@ -1036,15 +1100,20 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter AST::Trait& t = *const_cast<AST::Trait*>(m_self_type.back().as_Trait().trait);
bool is_method;
+ const void* ptr;
AST::Path found_trait_path;
- if( this->find_trait_item(span, p, t, item_name, is_method, found_trait_path) ) {
+ if( this->find_trait_item(span, p, t, item_name, is_method, ptr, found_trait_path) ) {
if( is_method ) {
if( info.nodes.size() != 1 )
ERROR(path.span(), E0000, "CPathResolver::handle_path_ufcs - Sub-nodes to method");
+ auto f = reinterpret_cast<const ::AST::Function*>(ptr);
+ path.bind_function(*f, path.nodes()[0].args());
}
else {
if( info.nodes.size() != 1 )
throw ParseError::Todo("CPathResolver::handle_path_ufcs - Sub nodes on associated type");
+ auto t = reinterpret_cast<const ::AST::TypeAlias*>(ptr);
+ path.bind_type_alias(*t);
}
*info.trait = TypeRef( mv$(found_trait_path) );
}
@@ -1054,6 +1123,7 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter }
else if( info.type->is_type_param() )
{
+ #if 0
DEBUG("Checking applicable generic bounds");
const auto& tp = *info.type->type_params_ptr();
assert(&tp != nullptr);
@@ -1098,34 +1168,47 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter throw ParseError::Todo( FMT("CPathResolver::handle_path_ufcs - UFCS, find trait for generic matching '" << item_name << "'") );
// - re-handle, to ensure that the bound is resolved
handle_type(*info.trait);
+ #endif
}
else
{
+ const auto& name = path.nodes()[0].name();
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), {
- DEBUG("Found matching inherent impl");
- *info.trait = TypeRef(TypeRef::TagInvalid());
- return ;
- })
- }
+ DEBUG("Searching for inherent impls on " << *info.type);
+ bool found = m_crate.find_inherent_impls( *info.type, [&](const AST::Impl& impl, ::std::vector<TypeRef> _) -> bool {
+ DEBUG("Searching impl " << impl);
+ for( const auto& fcn : impl.functions() )
+ {
+ if( fcn.name == name) {
+ path.bind_function(fcn.data, path.nodes()[0].args());
+ info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid()) );
+ return true;
+ }
+ }
+ return false;
+ });
+ if( found )
+ return ;
+
+ DEBUG("Searching traits");
// Iterate all traits in scope, and find one that is implemented for this type
// - TODO: Iterate traits to find match for <Type as _>
for( const auto& trait_ref : this->inscope_traits() )
{
const auto& trait_p = trait_ref.first;
const auto& trait = trait_ref.second;
+ DEBUG("Searching trait: " << trait_p);
bool is_fcn;
if( trait.has_named_item(item_name, is_fcn) ) {
- IF_OPTION_SOME(impl, m_crate.find_impl( trait_p, *info.type ), {
+ IF_OPTION_SOME(impl, m_crate.find_impl( trait_p, *info.type ),
*info.trait = TypeRef( trait_p );
return ;
- })
+ )
}
}
- throw ParseError::Todo( FMT("CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type) );
+ TODO(span, "CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type << " - name='"<<name<<"'");
}
#endif
}
@@ -1149,11 +1232,11 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter }
)
)
-
}
}
}
- else {
+ else
+ {
#if 0
const auto& name = path.nodes()[0].name();
// Trait is known, need to ensure that the named item exists
@@ -1280,7 +1363,7 @@ void CPathResolver::handle_path_rel(const Span& span, AST::Path& path, CASTItera ERROR(span, E0000, "CPathResolver::handle_path - Name resolution failed");
}
-bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path)
+bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, const void*& out_ptr, AST::Path& out_trait_path)
{
TRACE_FUNCTION_F("path=" << path << ", trait=..., item_name=" << item_name);
{
@@ -1290,6 +1373,7 @@ bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST if( it != fcns.end() ) {
// Found it.
out_is_method = true;
+ out_ptr = &it->data;
out_trait_path = AST::Path(path);
DEBUG("Fcn, out_trait_path = " << out_trait_path);
return true;
@@ -1301,6 +1385,7 @@ bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST if( it != types.end() ) {
// Found it.
out_is_method = false;
+ out_ptr = &it->data;
out_trait_path = AST::Path(path);
DEBUG("Ty, out_trait_path = " << out_trait_path << " path=" << path);
return true;
@@ -1313,13 +1398,15 @@ bool CPathResolver::find_trait_item(const Span& span, const AST::Path& path, AST //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(span, st, super_t, item_name, out_is_method, out_trait_path) ) {
+ if( this->find_trait_item(span, st, super_t, item_name, out_is_method, out_ptr, 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) {
+ out_trait_path.resolve_args([&](const char* name) -> TypeRef {
int idx = trait.params().find_name(name);
if(idx < 0)
ERROR(st.span(), E0000, "Parameter " << name << " not found");
+ if(static_cast<unsigned int>(idx) >= path.nodes().back().args().size())
+ ERROR(st.span(), E0000, "Path '"<<path<<"' had too few args");
const auto& tr = path.nodes().back().args().at(idx);
DEBUG("Replacing '" << name << "' with " << tr);
return tr;
@@ -1504,7 +1591,9 @@ void CPathResolver::handle_type(TypeRef& type) // No change
}
DEBUG("type = " << type);
-
+
+ //if
+
//if( type.is_type_param() && type.type_param() == "Self" )
//{
// auto l = lookup_local(LocalItem::TYPE, "Self");
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index fee1ac34..11ace14b 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -837,19 +837,21 @@ void RustPrinter::handle_enum(const AST::Enum& s) m_os << indent() << "{\n"; inc_indent(); + unsigned int idx = 0; for( const auto& i : s.variants() ) { - m_os << indent() << i.m_name; + m_os << indent() << "/*"<<idx<<"*/" << i.m_name; if( i.m_sub_types.size() ) { for( const auto& t : i.m_sub_types ) m_os << t.print_pretty() << ", "; } - else + else if(i.m_value > 0) { m_os << " = " << i.m_value; } m_os << ",\n"; + idx ++; } dec_indent(); m_os << indent() << "}\n"; diff --git a/src/main.cpp b/src/main.cpp index b8b661cc..0e0ad016 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,14 @@ struct ProgramParams {
static const unsigned int EMIT_C = 0x1;
static const unsigned int EMIT_AST = 0x2;
+ enum eLastStage {
+ STAGE_PARSE,
+ STAGE_EXPAND,
+ STAGE_RESOLVE,
+ STAGE_TYPECK,
+ STAGE_BORROWCK,
+ STAGE_ALL,
+ } last_stage = STAGE_ALL;
const char *infile = NULL;
::std::string outfile;
@@ -68,10 +76,15 @@ int main(int argc, char *argv[]) AST::Crate crate = CompilePhase<AST::Crate>("Parse", [&]() {
return Parse_Crate(params.infile);
});
+
+ if( params.emit_flags == ProgramParams::STAGE_PARSE ) {
+ return 0;
+ }
// Iterate all items in the AST, applying syntax extensions
CompilePhaseV("Decorators", [&]() {
Process_Decorators(crate);
+ Process_Synexts(crate);
});
// Run a quick post-parse pass
@@ -84,7 +97,11 @@ int main(int argc, char *argv[]) CompilePhaseV("Temp output - Parsed", [&]() {
Dump_Rust( FMT(params.outfile << "_0_pp.rs").c_str(), crate );
});
-
+
+ if( params.emit_flags == ProgramParams::STAGE_EXPAND ) {
+ return 0;
+ }
+
// 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
@@ -210,6 +227,20 @@ ProgramParams::ProgramParams(int argc, char *argv[]) exit(1);
}
}
+ else if( strcmp(arg, "--stop-after") == 0 ) {
+ if( i == argc - 1 ) {
+ // TODO: BAIL!
+ exit(1);
+ }
+
+ arg = argv[++i];
+ if( strcmp(arg, "parse") == 0 )
+ this->last_stage = STAGE_PARSE;
+ else {
+ ::std::cerr << "Unknown argument to --stop-after : '" << arg << "'" << ::std::endl;
+ exit(1);
+ }
+ }
else {
exit(1);
}
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index f7d82987..5ba66dbc 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -1715,18 +1715,6 @@ AST::Crate Parse_Crate(::std::string mainfile) // TODO:
}
}
-
- if( crate.m_load_std )
- {
- // Load the standard library (add 'extern crate std;')
- crate.load_extern_crate("std");
- rootmod.add_ext_crate("std", "std");
- rootmod.add_macro_import(crate, "std", "");
- // Prelude imports are handled in Parse_ModRoot
- }
-
- // Include the std if the 'no_std' attribute was absent
- // - First need to load the std macros, then can import the prelude
Parse_ModRoot(lex, crate, rootmod, NULL, mainpath);
|