summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--src/ast/ast.hpp3
-rw-r--r--src/ast/crate.cpp22
-rw-r--r--src/ast/crate.hpp1
-rw-r--r--src/ast/provided_module.cpp59
-rw-r--r--src/convert/ast_iterate.cpp552
-rw-r--r--src/convert/ast_iterate.hpp80
-rw-r--r--src/convert/decorators.cpp78
-rw-r--r--src/convert/resolve.cpp1856
-rw-r--r--src/convert/typecheck_bounds.cpp58
-rw-r--r--src/convert/typecheck_expr.cpp609
-rw-r--r--src/convert/typecheck_params.cpp344
-rw-r--r--src/main.cpp8
13 files changed, 0 insertions, 3675 deletions
diff --git a/Makefile b/Makefile
index 23d7cac5..e8b1d58e 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,6 @@ BIN := bin/mrustc$(EXESUF)
OBJ := main.o macros.o types.o serialise.o
OBJ += span.o rc_string.o
OBJ += ast/ast.o ast/crate.o ast/path.o ast/expr.o ast/pattern.o
-OBJ += ast/provided_module.o
OBJ += parse/parseerror.o parse/lex.o parse/token.o
OBJ += parse/root.o parse/paths.o parse/types.o parse/expr.o parse/pattern.o parse/macro_rules.o
OBJ += expand/mod.o expand/macro_rules.o expand/cfg.o
@@ -42,10 +41,6 @@ OBJ += hir/from_ast.o hir/from_ast_expr.o
OBJ += hir/crate_ptr.o hir/type_ptr.o hir/expr_ptr.o
OBJ += hir/type.o hir/path.o hir/expr.o
OBJ += dump_as_rust.o
-OBJ += convert/ast_iterate.o
-#OBJ += convert/decorators.o
-#OBJ += convert/resolve.o
-OBJ += convert/typecheck_bounds.o convert/typecheck_params.o convert/typecheck_expr.o
PCHS := ast/ast.hpp
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index b7601192..b7de73ac 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -713,8 +713,5 @@ public:
}
};
-extern AST::Module g_compiler_module;
-extern void AST_InitProvidedModule();
-
#endif // AST_HPP_INCLUDED
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp
index 699bd288..d40879f3 100644
--- a/src/ast/crate.cpp
+++ b/src/ast/crate.cpp
@@ -45,28 +45,6 @@ void Crate::load_externs()
iterate_module(m_root_module, cb);
}
-void Crate::index_impls()
-{
- // Iterate all modules, grabbing pointers to all impl blocks
- auto cb = [this](Module& mod){
- for( auto& impl : mod.impls() )
- m_impl_index.push_back( &impl );
- for( auto& impl : mod.neg_impls() )
- m_neg_impl_index.push_back( &impl );
- };
- 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)
{
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
index a25d2480..dbb9ca0d 100644
--- a/src/ast/crate.hpp
+++ b/src/ast/crate.hpp
@@ -45,7 +45,6 @@ public:
/// Load referenced crates
void load_externs();
- void index_impls();
bool is_trait_implicit(const Path& trait) const;
diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp
deleted file mode 100644
index e36784f0..00000000
--- a/src/ast/provided_module.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- */
-#include "ast.hpp"
-
-void AST_InitProvidedModule_Impls();
-
-AST::Module g_compiler_module;
-AST::Path g_copy_marker_path;
-AST::Path g_sized_marker_path;
-
-void AST_InitProvidedModule()
-{
- // "struct str([u8])"
- ::std::vector<AST::StructItem> fields;
- fields.push_back( AST::StructItem(AST::MetaItems(), false, "", TypeRef(TypeRef::TagUnsizedArray(), Span(), TypeRef(Span(), CORETYPE_U8))) );
- g_compiler_module.add_struct(true, "str", AST::Struct(AST::GenericParams(), mv$(fields)), AST::MetaItems());
-
- AST_InitProvidedModule_Impls();
-}
-
-void AST_InitProvidedModule_Impls()
-{
- if( !g_copy_marker_path.is_valid() ) {
- g_copy_marker_path = AST::Path( "", {AST::PathNode("marker"),AST::PathNode("Copy")} );
- }
-
- if( !g_sized_marker_path.is_valid() ) {
- g_sized_marker_path = AST::Path( "", {AST::PathNode("marker"),AST::PathNode("Sized")} );
- }
-
- #define impl(trait, type) \
- g_compiler_module.add_impl(AST::Impl(AST::MetaItems(), AST::GenericParams(), type, trait))
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U8));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U16));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U32));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U64));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_UINT));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I8));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I16));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I32));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I64));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_INT));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_F32));
- impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_F64));
-
- // A hacky default impl of 'Sized', with a negative impl on [T]
- impl(g_sized_marker_path, TypeRef());
-
- {
- AST::GenericParams tps;
- tps.add_ty_param( AST::TypeParam("T") );
- g_compiler_module.add_neg_impl(AST::ImplDef(
- AST::MetaItems(), ::std::move(tps),
- g_sized_marker_path,
- TypeRef(TypeRef::TagUnsizedArray(), Span(), TypeRef(TypeRef::TagArg(), "T"))
- ));
- }
-}
-
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
deleted file mode 100644
index 7e70f1f0..00000000
--- a/src/convert/ast_iterate.cpp
+++ /dev/null
@@ -1,552 +0,0 @@
-/**
- */
-#include "ast_iterate.hpp"
-#include "../ast/ast.hpp"
-
-void CASTIterator::handle_path(AST::Path& path, CASTIterator::PathMode pm)
-{
-}
-void CASTIterator::handle_type(TypeRef& type)
-{
- TRACE_FUNCTION_F("type = " << type);
-
- TU_MATCH(TypeData, (type.m_data), (ent),
- (None),
- (Any),
- (Unit),
- (Macro),
- (Primitive),
- (Path,
- handle_path(ent.path, MODE_TYPE);
- ),
- (Tuple,
- for(auto& subtype : ent.inner_types)
- handle_type(subtype);
- ),
- (Borrow,
- handle_type(*ent.inner);
- ),
- (Pointer,
- handle_type(*ent.inner);
- ),
- (Array,
- handle_type(*ent.inner);
- ),
- (Function,
- handle_type(*ent.info.m_rettype);
- for(auto& arg : ent.info.m_arg_types)
- handle_type(arg);
- ),
- (Generic),
- (TraitObject,
- for(auto& trait : ent.traits)
- handle_path(trait, MODE_TYPE);
- )
- )
-}
-void CASTIterator::handle_expr(AST::ExprNode& node)
-{
-}
-void CASTIterator::handle_params(AST::GenericParams& params)
-{
- DEBUG("params");
- for( auto& param : params.ty_params() )
- {
- handle_type(param.get_default());
- local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name(), params) );
- }
- DEBUG("Bounds");
- for( auto& bound : params.bounds() )
- {
- TU_MATCH( AST::GenericBound, (bound), (ent),
- (Lifetime,
- DEBUG("namecheck lifetime bounds?");
- ),
- (TypeLifetime,
- handle_type(ent.type);
- DEBUG("namecheck lifetime bounds?");
- ),
- (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);
- handle_type(ent.replacement);
- )
- )
- }
-}
-
-
-void CASTIterator::start_scope()
-{
- INDENT();
-}
-void CASTIterator::local_type(::std::string name, TypeRef type)
-{
- DEBUG("type " << name << " = " << type);
-}
-void CASTIterator::local_variable(bool is_mut, ::std::string name, const TypeRef& type)
-{
- DEBUG( (is_mut ? "mut " : "") << name << " : " << type );
-}
-void CASTIterator::local_use(::std::string name, AST::Path path)
-{
- DEBUG( name << " = " << path );
-}
-void CASTIterator::end_scope()
-{
- UNINDENT();
-}
-
-void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
-{
- //DEBUG("pat = " << pat);
- // Resolve names
- TU_MATCH(AST::Pattern::Data, (pat.data()), (v),
- (Any,
- // Wildcard, nothing to do
- ),
- (Macro,
- // Macro, nothing really (should be impossible?)
- ),
- (Box, {
- auto& v = pat.data().as_Box();
- if( type_hint.is_wildcard() )
- handle_pattern(*v.sub, (const TypeRef&)TypeRef());
- else {
- throw ::std::runtime_error("TODO: Handle box patterns in CASTIterator::handle_pattern");
- handle_pattern(*v.sub, type_hint.inner_type());
- }
- }),
- (Ref, {
- auto& v = pat.data().as_Ref();
- if( type_hint.is_wildcard() )
- handle_pattern(*v.sub, (const TypeRef&)TypeRef());
- else if( !type_hint.is_reference() )
- throw ::std::runtime_error( FMT("Ref pattern on non-ref value: " << type_hint) );
- else
- handle_pattern(*v.sub, type_hint.inner_type());
- }),
- (MaybeBind,
- throw ::std::runtime_error("Calling CASTIterator::handle_pattern on MAYBE_BIND, not valid");
- ),
- (Value,
- TU_IFLET(AST::Pattern::Value, v.start, Named, e,
- handle_path(e, CASTIterator::MODE_TYPE);
- )
- TU_IFLET(AST::Pattern::Value, v.end, Named, e,
- handle_path(e, CASTIterator::MODE_TYPE);
- )
- ),
- (Tuple, {
- auto& v = pat.data().as_Tuple();
- // Tuple is handled by subpattern code
- if( type_hint.is_wildcard() )
- {
- for( auto& sp : v.sub_patterns )
- handle_pattern(sp, (const TypeRef&)TypeRef());
- }
- else if( !type_hint.is_tuple() )
- {
- throw ::std::runtime_error("Tuple pattern on non-tuple value");
- }
- else
- {
- const auto& inner_types = type_hint.m_data.as_Tuple().inner_types;
- if( inner_types.size() != v.sub_patterns.size() )
- {
- throw ::std::runtime_error("Tuple pattern count doesn't match");
- }
- for( unsigned int i = 0; i < v.sub_patterns.size(); i ++ )
- {
- handle_pattern(v.sub_patterns[i], inner_types[i]);
- }
- }
- }),
- (Struct, {
- auto& v = pat.data().as_Struct();
- handle_path( v.path, CASTIterator::MODE_TYPE );
- if( type_hint.is_wildcard() )
- {
- for( auto& sp : v.sub_patterns )
- handle_pattern(sp.second, (const TypeRef&)TypeRef());
- }
- else if( !type_hint.is_path() )
- {
- throw ::std::runtime_error("Tuple struct pattern on non-tuple value");
- }
- else
- {
- auto& path = type_hint.m_data.as_Path().path;
- if( path.is_bound() ) {
- throw ::std::runtime_error("TODO: Typecheck/iterate struct pattern (with known type)");
- }
- else {
- for( auto& sp : v.sub_patterns )
- handle_pattern(sp.second, (const TypeRef&)TypeRef());
- }
- }
- }),
- (StructTuple, {
- auto& v = pat.data().as_StructTuple();
- // Resolve the path!
- handle_path( v.path, CASTIterator::MODE_TYPE );
- // Handle sub-patterns
- if( type_hint.is_wildcard() )
- {
- for( auto& sp : v.sub_patterns )
- handle_pattern(sp, (const TypeRef&)TypeRef());
- }
- else if( !type_hint.is_path() )
- {
- throw ::std::runtime_error("Tuple struct pattern on non-tuple value");
- }
- else
- {
- auto& hint_path = type_hint.path();
- auto& pat_path = v.path;
- const auto& hint_binding = hint_path.binding();
- const auto& pat_binding = pat_path.binding();
- DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path());
- TU_MATCH_DEF( AST::PathBinding, (hint_binding), (info),
- (
- throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path()))
- ),
- (Unbound,
- throw ::std::runtime_error("Unbound path in pattern");
- ),
- (Enum,
- // The pattern's path must refer to a variant of the hint path
- // - Actual type params are checked by the 'handle_pattern_enum' code
- if( !pat_binding.is_EnumVar() )
- throw ::std::runtime_error(FMT("Paths in pattern are invalid"));
- if( pat_binding.as_EnumVar().enum_ != info.enum_ )
- throw ::std::runtime_error(FMT("Paths in pattern are invalid"));
- const auto& enm = *pat_binding.as_EnumVar().enum_;
- auto idx = pat_binding.as_EnumVar().idx;
- auto& var = enm.variants().at(idx);
- handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns);
- )
- )
- }
- }),
- (Slice,
- TypeRef null_type;
- const auto* inner_type = &null_type;
- if( !type_hint.is_wildcard() )
- {
- TU_MATCH_DEF( TypeData, (type_hint.m_data), (v),
- (
- ERROR(Span(), E0000, "Slice pattern on non-slice/array");
- ),
- (Array,
- inner_type = v.inner.get();
- ),
- (Borrow,
- if( v.inner->is_wildcard() ) {
- }
- else if( v.inner->m_data.is_Array() ) {
- inner_type = v.inner->m_data.as_Array().inner.get();
- }
- else {
- // TODO: Deref more?
- ERROR(Span(), E0000, "Slice pattern on non-slice/array");
- }
- )
- )
- }
- for( auto& sp : v.leading )
- handle_pattern(sp, *inner_type);
- for( auto& sp : v.trailing )
- handle_pattern(sp, *inner_type);
- )
- )
- // Extract bindings and add to namespace
- if( pat.binding().size() > 0 )
- {
- // TODO: Mutable bindings
- if(pat.binding() != "_")
- {
- local_variable( false, pat.binding(), type_hint );
- }
- }
-}
-void CASTIterator::handle_pattern_enum(
- ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::GenericParams& enum_params, const AST::EnumVariant& var,
- ::std::vector<AST::Pattern>& sub_patterns
- )
-{
- // This implementation doesn't attempt to do anything with types, just propagates _
- for( auto& sp : sub_patterns )
- handle_pattern(sp, (const TypeRef&)TypeRef());
-}
-
-void CASTIterator::handle_module(AST::Path path, AST::Module& mod)
-{
- INDENT();
- start_scope();
-
- for( auto& item : mod.items() )
- {
- TU_MATCH(::AST::Item, (item.data), (e),
- (None,
- // Explicitly ignored (represents a deleted item)
- ),
- (Crate,
- // Nothing to be done
- ),
- (Struct,
- DEBUG("Handling struct " << item.name);
- handle_struct(path + item.name, e);
- ),
- (Enum,
- DEBUG("Handling enum " << item.name);
- handle_enum(path + item.name, e);
- ),
- (Trait,
- DEBUG("Handling trait " << item.name);
- handle_trait(path + item.name, e);
- ),
- (Type,
- DEBUG("Handling alias " << item.name);
- handle_alias(path + item.name, e);
- ),
- (Static,
- DEBUG("handling static " << item.name);
- handle_type(e.type());
- if( e.value().is_valid() )
- {
- handle_expr(e.value().node());
- }
- ),
- (Function,
- DEBUG("Handling function '" << item.name << "'");
- handle_function(path + item.name, e);
- ),
- (Module,
- // Skip, done after all items
- )
- )
- }
-
- for( auto& impl : mod.impls() )
- {
- DEBUG("Handling 'impl' " << impl);
- handle_impl(path, impl);
- }
-
- // End scope before handling sub-modules
- end_scope();
-
- for( auto& item : mod.items() )
- {
- if(!item.data.is_Module()) continue;
- auto& submod = item.data.as_Module();
- DEBUG("Handling submod '" << item.name << "'");
- handle_module(path + item.name, submod);
- }
- unsigned int anon_mod_idx = 0;
- for( auto& anonmod : mod.anon_mods() )
- {
- auto& submod = *anonmod;
- DEBUG("Handling submod #" << anon_mod_idx);
- handle_module(path + FMT("#" << anon_mod_idx), submod);
- anon_mod_idx += 1;
- }
- UNINDENT();
-}
-void CASTIterator::handle_function(AST::Path path, AST::Function& fcn)
-{
- TRACE_FUNCTION_F("path = " << path << ", fcn.params() = " << fcn.params());
- start_scope();
-
- DEBUG("params");
- handle_params(fcn.params());
-
- DEBUG("ret type");
- handle_type(fcn.rettype());
-
- //switch( fcn.fcn_class() )
- //{
- //case AST::Function::CLASS_UNBOUND:
- // break;
- //case AST::Function::CLASS_REFMETHOD:
- // local_variable(false, "self", TypeRef(TypeRef::TagReference(), false, TypeRef(TypeRef::TagArg(), "Self")));
- // break;
- //case AST::Function::CLASS_MUTMETHOD:
- // local_variable(false, "self", TypeRef(TypeRef::TagReference(), true, TypeRef(TypeRef::TagArg(), "Self")));
- // break;
- //case AST::Function::CLASS_VALMETHOD:
- // local_variable(false, "self", TypeRef(TypeRef::TagArg(), "Self"));
- // break;
- //case AST::Function::CLASS_MUTVALMETHOD:
- // local_variable(true, "self", TypeRef(TypeRef::TagArg(), "Self"));
- // break;
- //}
-
- DEBUG("args");
- for( auto& arg : fcn.args() )
- {
- handle_type(arg.second);
- // TODO: Check if pattern is irrefutable?
- handle_pattern( arg.first, arg.second );
- }
-
- DEBUG("code");
- if( fcn.code().is_valid() )
- {
- INDENT();
- handle_expr( fcn.code().node() );
- UNINDENT();
- }
-
- end_scope();
-}
-
-void CASTIterator::handle_impl_def(AST::ImplDef& impl)
-{
- // 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 );
-}
-
-void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl)
-{
- start_scope();
-
- handle_impl_def(impl.def());
-
- // Associated types
- for( auto& it : impl.items() )
- {
- TU_MATCH_DEF(AST::Item, (it.data), (e),
- (
- ),
- (Type,
- DEBUG("- Type '" << it.name << "'");
- handle_type( e.type() );
- ),
- (Function,
- DEBUG("- Function '" << it.name << "'");
- handle_function(AST::Path(AST::Path::TagRelative(), { AST::PathNode(it.name) }), e);
- )
- )
- }
-
- pop_self();
- end_scope();
-}
-
-void CASTIterator::handle_struct(AST::Path path, AST::Struct& str)
-{
- start_scope();
- handle_params( str.params() );
- TU_MATCH(AST::StructData, (str.m_data), (e),
- (Tuple,
- for( auto& f : e.ents )
- handle_type( f.m_type );
- ),
- (Struct,
- for( auto& f : e.ents )
- handle_type( f.m_type );
- )
- )
- end_scope();
-}
-void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm)
-{
- start_scope();
- handle_params( enm.params() );
- for( auto& f : enm.variants() )
- {
- TU_MATCH(AST::EnumVariantData, (f.m_data), (e),
- (Value,
- ),
- (Tuple,
- for( auto& t : e.m_sub_types )
- handle_type(t);
- ),
- (Struct,
- for( auto& t : e.m_fields )
- handle_type(t.m_type);
- )
- )
- }
- end_scope();
-}
-void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait)
-{
- start_scope();
- push_self(path, trait);
- handle_params( trait.params() );
-
- 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& i : trait.items() )
- {
- TU_MATCH_DEF(AST::Item, (i.data), (e),
- (
- ),
- (Type,
- // TODO: Can trait associated types have default types?
- ),
- (Static,
- handle_type(e.type());
- ),
- (Function,
- handle_function( path + i.name, e );
- )
- )
- }
- pop_self();
- end_scope();
-}
-void CASTIterator::handle_alias(AST::Path path, AST::TypeAlias& alias)
-{
- start_scope();
- handle_params( alias.params() );
- 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
deleted file mode 100644
index fc57cf57..00000000
--- a/src/convert/ast_iterate.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef _AST_ITERATE_HPP_INCLUDED_
-#define _AST_ITERATE_HPP_INCLUDED_
-
-#include <string>
-#include "../types.hpp"
-#include "../ast/path.hpp"
-
-namespace AST {
-
-class ExprNode;
-class Pattern;
-class GenericParams;
-class Impl;
-class ImplDef;
-class EnumVariant;
-template<typename T> struct Named;
-
-};
-
-// Iterator for the AST, calls virtual functions on paths/types
-class CASTIterator
-{
-public:
- enum PathMode {
- MODE_EXPR, // Variables allowed
- MODE_TYPE,
- MODE_BIND, // Failure is allowed
- };
- virtual void handle_path(AST::Path& path, PathMode mode);
- virtual void handle_type(TypeRef& type);
- virtual void handle_expr(AST::ExprNode& node);
-
- virtual void handle_params(AST::GenericParams& params);
-
- virtual void start_scope();
- virtual void local_type(::std::string name, TypeRef type);
- virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type);
- virtual void local_use(::std::string name, AST::Path path);
- virtual void end_scope();
-
- virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint);
- virtual void handle_pattern_enum(
- ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::GenericParams& enum_params, const AST::EnumVariant& var,
- ::std::vector<AST::Pattern>& sub_patterns
- );
-
- virtual void handle_module(AST::Path path, AST::Module& mod);
-
- virtual void handle_function(AST::Path path, AST::Function& fcn);
- virtual void handle_impl(AST::Path modpath, AST::Impl& impl);
-
- virtual void handle_struct(AST::Path path, AST::Struct& str);
- 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);
-};
-
-static inline ::std::ostream& operator<<(::std::ostream& os, const CASTIterator::PathMode& mode) {
- switch(mode)
- {
- case CASTIterator::MODE_EXPR: return os << "MODE_EXPR";
- case CASTIterator::MODE_TYPE: return os << "MODE_TYPE";
- case CASTIterator::MODE_BIND: return os << "MODE_BIND";
- }
- return os;
-}
-
-
-
-#endif
-
diff --git a/src/convert/decorators.cpp b/src/convert/decorators.cpp
deleted file mode 100644
index 06716e5f..00000000
--- a/src/convert/decorators.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * convert/decorators.cpp
- * - Handles #[...] item decorators by delegating
- */
-#include "ast_iterate.hpp"
-#include "../ast/ast.hpp"
-#include "../ast/crate.hpp"
-#include <main_bindings.hpp>
-#include <unordered_map> // C++11, hashmap
-#include <synext.hpp>
-
-::std::unordered_map< ::std::string, ::std::unique_ptr<CDecoratorHandler> > g_decorators;
-
-template<typename T>
-void Decorator_Apply(AST::Crate& crate, AST::Module& mod, const AST::MetaItems& attrs, const AST::Path& path, T& ent)
-{
- // For all attributes on the item, search for a handler and call handler
- for( const auto& attr : attrs.m_items )
- {
- auto it = g_decorators.find(attr.name());
- if( it != g_decorators.end() )
- {
- const CDecoratorHandler& handler = *it->second;
-
- handler.handle_item(crate, mod, attr, path, ent);
- }
- else {
- }
- }
-}
-
-class CProcessor:
- public CASTIterator
-{
- AST::Crate& m_crate;
- ::std::vector<AST::Module*> m_modstack;
-public:
- CProcessor(AST::Crate& crate):
- m_crate(crate)
- {}
-
- void handle_module(AST::Path path, AST::Module& mod) override
- {
- m_modstack.push_back(&mod);
- CASTIterator::handle_module(mv$(path), mod);
- m_modstack.pop_back();
- }
-
- void handle_struct(AST::Path path, AST::Struct& str) override
- {
- Decorator_Apply(m_crate, *m_modstack.back(), str.attrs(), path, str);
- }
-
- void handle_trait(AST::Path path, AST::Trait& tr) override
- {
- Decorator_Apply(m_crate, *m_modstack.back(), tr.attrs(), path, tr);
- }
-};
-
-void Register_Synext_Decorator(::std::string name, ::std::unique_ptr<CDecoratorHandler> handler)
-{
- auto res = g_decorators.insert( ::std::make_pair(name, mv$(handler)) );
- if( res.second == false )
- {
- DEBUG("Duplicate definition of decorator '"<<name<<"'");
- }
-}
-
-void Process_Decorators(AST::Crate& crate)
-{
- CProcessor processor(crate);
-
- processor.handle_module(AST::Path("", {}), crate.root_module());
-}
-
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
deleted file mode 100644
index a240c6fc..00000000
--- a/src/convert/resolve.cpp
+++ /dev/null
@@ -1,1856 +0,0 @@
-/*
- * "mrustc" Rust->C converter
- * - By John Hodge (Mutabah / thePowersGang)
- *
- * convert/resolve.cpp
- * - Resolve names into absolute format
- *
- * - Converts all paths into a canonical format (absolute, local, or UFCS)
- */
-#include "../common.hpp"
-#include "../ast/ast.hpp"
-#include "../ast/crate.hpp"
-#include "../parse/parseerror.hpp"
-#include "ast_iterate.hpp"
-
-// ====================================================================
-// -- Path resolver (converts paths to absolute form)
-// ====================================================================
-class CPathResolver:
- public CASTIterator
-{
- const AST::Crate& m_crate;
- AST::Module* m_module;
- AST::Path m_module_path;
- ::std::vector< ::std::pair<AST::Module*, AST::Path> > m_module_stack;
-
- struct LocalItem
- {
- enum Type {
- TYPE,
- VAR,
- } type;
- ::std::string name;
- TypeRef tr;
-
- LocalItem():
- type(VAR), name()
- {}
- LocalItem(Type t, ::std::string name, TypeRef tr=TypeRef()):
- type(t),
- name( ::std::move(name) ),
- tr( ::std::move(tr) )
- {}
-
- friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) {
- if( x.name == "" )
- return os << "#";
- else if( x.type == TYPE )
- return os << "type '" << x.name << "' = " << x.tr;
- else
- return os << "var '" << x.name << "'";
- }
- };
- ::std::vector< LocalItem > m_locals;
-
- struct Scope {
- unsigned int module_idx;
- AST::Module *module; // can be NULL
- AST::Path module_path;
- ::std::vector< ::std::string > locals;
-
- ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > traits;
- };
- ::std::vector<Scope> m_scope_stack;
-
-
- TAGGED_UNION(SelfType, None,
- (None, struct {}),
- (Type, struct {
- TypeRef type;
- }),
- (Trait, struct {
- AST::Path path;
- const AST::Trait* trait;
- })
- );
- ::std::vector<SelfType> m_self_type;
-
- friend class CResolvePaths_NodeVisitor;
-
-public:
- bool m_second_pass = false;
-
- CPathResolver(const AST::Crate& crate);
-
- void handle_params(AST::GenericParams& params) override;
-
- virtual void handle_path(AST::Path& path, CASTIterator::PathMode mode) override;
- void handle_path_abs(const Span& span, AST::Path& path, CASTIterator::PathMode mode);
- 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, const void*& out_ptr, AST::Path& out_trait_path);
- virtual void handle_type(TypeRef& type) override;
- virtual void handle_expr(AST::ExprNode& node) override;
-
- virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) override;
- virtual void handle_module(AST::Path path, AST::Module& mod) override;
- virtual void handle_trait(AST::Path path, AST::Trait& trait) override;
- virtual void handle_function(AST::Path path, AST::Function& fcn) override;
-
- virtual void start_scope() override;
- virtual void local_type(::std::string name, TypeRef type) override {
- DEBUG("(name = " << name << ", type = " << type << ")");
- if( lookup_local(LocalItem::TYPE, name).is_some() ) {
- // Shadowing the type... check for recursion by doing a resolve check?
- type.resolve_args([&](const char *an){ if(an == name) return TypeRef(name+" "); else return TypeRef(an); });
- }
- m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name), ::std::move(type)) );
- }
- virtual void local_variable(bool _is_mut, ::std::string name, const TypeRef& _type) override {
- assert(m_scope_stack.size() > 0);
- m_scope_stack.back().locals.push_back( ::std::move(name) );
- }
- virtual void local_use(::std::string name, AST::Path path) override {
- assert( !path.binding().is_Unbound() );
- if( path.binding().is_Trait() ) {
- m_scope_stack.back().traits.push_back( ::std::pair<AST::Path, const AST::Trait&>(path, *path.binding().as_Trait().trait_) );
- }
- }
- virtual void end_scope() override;
-
- ::rust::option<const LocalItem&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
-
- bool find_local_item(const Span& span, AST::Path& path, const ::std::string& name, bool allow_variables);
- //bool find_local_item(AST::Path& path, bool allow_variables);
- bool find_mod_item(const Span& span, AST::Path& path, const ::std::string& name);
- bool find_self_mod_item(const Span& span, AST::Path& path, const ::std::string& name);
- bool find_super_mod_item(const Span& span, 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 {
- // 'Self' must be resolved because ...
- //if( real_type.is_path() && real_type.path().binding().is_Unbound() ) {
- // assert( !"Unbound path passed to push_self" );
- //}
- 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(const Span& span, AST::Path& path, CASTIterator::PathMode mode);
-
- ::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 ) {
- DEBUG("t = " << t.first);
- //assert(t.first.binding().is_Trait());
- ret.push_back(t);
- }
- if( it->module ) {
- for( const auto& i : it->module->items() ) {
- if( !i.data.is_Trait() ) continue ;
- const auto& t = i.data.as_Trait();
- auto trait_path = it->module_path + i.name;
- DEBUG("t = " << trait_path);
- ret.push_back( ::std::pair<AST::Path, const AST::Trait&>(trait_path, t) );
- }
- }
- }
-
- for( const auto& i : m_module->items() ) {
- if( !i.data.is_Trait() ) continue ;
- const auto& t = i.data.as_Trait();
- auto trait_path = m_module_path + i.name;
- DEBUG("(mod) t = " << trait_path);
- ret.push_back( ::std::pair<AST::Path, const AST::Trait&>(trait_path, t) );
- }
- for( const auto& i : m_module->imports() ) {
- if( i.data.path.binding().is_Trait() )
- {
- auto& t = *i.data.path.binding().as_Trait().trait_;
-
- DEBUG("(use) t = " << i.data);
- ::std::pair<AST::Path, const AST::Trait&> tr(i.data.path, t);
- ret.push_back( tr );
- }
- }
-
- return ret;
- }
-
-
-};
-
-// Path resolution checking
-void ResolvePaths(AST::Crate& crate);
-void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod);
-
-class CResolvePaths_NodeVisitor:
- public AST::NodeVisitorDef
-{
- CPathResolver& m_res;
-public:
- CResolvePaths_NodeVisitor(CPathResolver& res):
- m_res(res)
- {
- }
-
- void visit(AST::ExprNode_Macro& node) {
- BUG(node.get_pos(), "Un-resolved macro in expression");
-
- //MacroExpander expanded_macro = Macro_Invoke(node.m_name.c_str(), node.m_tokens);
- // TODO: Requires being able to replace the node with a completely different type of node
- //node.replace( Parse_Expr0(expanded_macro) );
- }
-
- void visit(AST::ExprNode_NamedValue& node) {
- DEBUG("ExprNode_NamedValue");
- m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR);
- }
- void visit(AST::ExprNode_CallPath& node) {
- DEBUG(node.get_pos() << " ExprNode_CallPath - " << node);
- AST::NodeVisitorDef::visit(node);
- m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR);
- }
-
- void visit(AST::ExprNode_Block& node) {
- // If there's an inner module on this node
- if( node.m_local_mod.get() )
- {
-
- // Add a reference to it to the parent node (add_anon_module will do dedup)
- AST::Module* parent_mod_p = m_res.m_module;
- for(const auto& e : m_res.m_scope_stack)
- if(e.module != nullptr)
- parent_mod_p = e.module;
- AST::Module& parent_mod = *parent_mod_p;
- auto idx = parent_mod.add_anon_module( node.m_local_mod.get() );
-
- // Obtain the path
- AST::Path local_path = m_res.m_module_path;
- for(const auto& e : m_res.m_scope_stack ) {
- if( e.module != nullptr ) {
- local_path.nodes().push_back( AST::PathNode( FMT("#" << e.module_idx), {} ) );
- }
- }
- local_path.nodes().push_back( AST::PathNode(FMT("#" << idx), {}) );
-
- // And add to the list of modules to use in lookup
- m_res.m_scope_stack.push_back( {idx, node.m_local_mod.get(), local_path, {}} );
-
- // Do use resolution on this module
- // TODO: When is more advanced resolution done?
- ResolvePaths_HandleModule_Use(m_res.m_crate, m_res.m_scope_stack.back().module_path, *node.m_local_mod);
- }
- else {
- m_res.m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} );
- }
- AST::NodeVisitorDef::visit(node);
- // Once done, pop the module
- m_res.m_scope_stack.pop_back();
- }
-
- void visit(AST::ExprNode_IfLet& node)
- {
- DEBUG("ExprNode_IfLet");
- AST::NodeVisitor::visit(node.m_value);
-
- m_res.start_scope();
- m_res.handle_pattern(node.m_pattern, TypeRef());
- AST::NodeVisitor::visit(node.m_true);
- m_res.end_scope();
-
- AST::NodeVisitor::visit(node.m_false);
- }
-
- void visit(AST::ExprNode_Match& node)
- {
- DEBUG("ExprNode_Match");
- AST::NodeVisitor::visit(node.m_val);
-
- for( auto& arm : node.m_arms )
- {
- m_res.start_scope();
- for( auto& pat : arm.m_patterns )
- m_res.handle_pattern(pat, TypeRef());
- AST::NodeVisitor::visit(arm.m_cond);
- AST::NodeVisitor::visit(arm.m_code);
- m_res.end_scope();
- }
- }
-
- void visit(AST::ExprNode_Loop& node)
- {
- switch( node.m_type )
- {
- case AST::ExprNode_Loop::FOR:
- AST::NodeVisitor::visit(node.m_cond);
- m_res.start_scope();
- m_res.handle_pattern(node.m_pattern, TypeRef());
- AST::NodeVisitor::visit(node.m_code);
- m_res.end_scope();
- break;
- case AST::ExprNode_Loop::WHILELET:
- AST::NodeVisitor::visit(node.m_cond);
- m_res.start_scope();
- m_res.handle_pattern(node.m_pattern, TypeRef());
- AST::NodeVisitor::visit(node.m_code);
- m_res.end_scope();
- break;
- default:
- AST::NodeVisitorDef::visit(node);
- break;
- }
- }
-
- void visit(AST::ExprNode_LetBinding& node)
- {
- DEBUG("ExprNode_LetBinding");
-
- AST::NodeVisitor::visit(node.m_value);
- m_res.handle_type(node.m_type);
- m_res.handle_pattern(node.m_pat, TypeRef());
- }
-
- void visit(AST::ExprNode_StructLiteral& node) override
- {
- DEBUG("ExprNode_StructLiteral");
-
- m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR);
- AST::NodeVisitorDef::visit(node);
- }
-
- void visit(AST::ExprNode_Closure& node) override
- {
- DEBUG("ExprNode_Closure");
- m_res.start_scope();
- for( auto& param : node.m_args )
- {
- DEBUG("- ExprNode_Closure: pat=" << param.first << ", ty=" << param.second);
- m_res.handle_type(param.second);
- m_res.handle_pattern(param.first, param.second);
- }
- DEBUG("- ExprNode_Closure: rt=" << node.m_return);
- m_res.handle_type(node.m_return);
- AST::NodeVisitor::visit(node.m_code);
- m_res.end_scope();
- }
-
- void visit(AST::ExprNode_Cast& node) override
- {
- DEBUG("ExprNode_Cast");
- m_res.handle_type(node.m_type);
- AST::NodeVisitorDef::visit(node);
- }
-
- void visit(AST::ExprNode_CallMethod& node) override
- {
- DEBUG("ExprNode_CallMethod");
- for( auto& arg : node.m_method.args() )
- m_res.handle_type(arg);
- AST::NodeVisitorDef::visit(node);
- }
-};
-
-/// Do simple path resolution on this path
-/// - Simple involves only doing item name lookups, no checks of generic params at all or handling UFCS
-void resolve_path(const Span& span, const AST::Crate& root_crate, AST::Path& path)
-{
- if( !path.is_absolute() ) {
- BUG(span, "Calling resolve_path on non-absolute path - " << path);
- }
- const AST::Module* mod = &root_crate.root_module();
- for(const auto& node : path.nodes() ) {
- if( node.args().size() > 0 ) {
- throw ParseError::Generic("Unexpected generic params in use path");
- }
- if( mod == nullptr ) {
- if( path.binding().is_Enum() ) {
- auto& enm = *path.binding().as_Enum().enum_;
- for(const auto& variant : enm.variants()) {
- if( variant.m_name == node.name() ) {
- path.bind_enum_var(enm, node.name());
- break;
- }
- }
- if( path.binding().is_Enum() ) {
- ERROR(span, E0000, "Unable to find component '" << node.name() << "' of import " << path << " (enum)" );
- }
- break;
- }
- else {
- throw ParseError::Generic("Extra path components after final item");
- }
- }
- auto item = mod->find_item(node.name());
- //while( item.is_None() && node.name()[0] == '#' ) {
- //}
- // HACK: Not actually a normal TU, but it fits the same pattern
- TU_MATCH(AST::Module::ItemRef, (item), (i),
- (None,
- ERROR(span, E0000, "Unable to find component '" << node.name() << "' of import " << path);
- ),
- (Module,
- mod = &i;
- ),
- (Crate,
- mod = &root_crate.get_root_module(i);
- ),
- (TypeAlias,
- path.bind_type_alias(i);
- mod = nullptr;
- ),
- (Function,
- path.bind_function(i);
- mod = nullptr;
- ),
- (Trait,
- path.bind_trait(i);
- mod = nullptr;
- ),
- (Struct,
- path.bind_struct(i);
- mod = nullptr;
- ),
- (Enum,
- // - Importing an enum item will be handled in the nullptr check above
- path.bind_enum(i);
- mod = nullptr;
- ),
- (Static,
- path.bind_static(i);
- mod = nullptr;
- ),
- (Use,
- if(i.name == "") {
- throw ParseError::Todo("Handle resolving to wildcard use in use resolution");
- }
- else {
- // Restart lookup using new path
- }
- )
- )
- }
- if( mod != nullptr ) {
- path.bind_module(*mod);
- }
-}
-
-CPathResolver::CPathResolver(const AST::Crate& crate):
- m_crate(crate),
- m_module(nullptr)
-{
-}
-void CPathResolver::start_scope()
-{
- DEBUG("");
- m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} );
- m_locals.push_back( LocalItem() );
-}
-void CPathResolver::end_scope()
-{
- m_scope_stack.pop_back( );
- DEBUG(m_locals.size() << " items");
- for( auto it = m_locals.end(); it-- != m_locals.begin(); )
- {
- if( it->name == "" ) {
- m_locals.erase(it, m_locals.end());
- return ;
- }
- }
- m_locals.clear();
-}
-// Returns the bound path for the local item
-::rust::option<const CPathResolver::LocalItem&> CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& src_name) const
-{
- DEBUG("m_locals = [" << m_locals << "]");
- ::std::string name = src_name;
- unsigned int count = 0;
- while( name.size() > 0 && name.back() == ' ') {
- name.pop_back();
- count ++;
- }
- for( auto it = m_locals.end(); it -- != m_locals.begin(); )
- {
- if( it->type == type )
- {
- if( it->name == name && count-- == 0 )
- return ::rust::option<const LocalItem&>(*it);
- }
- }
- return ::rust::option<const LocalItem&>();
-}
-
-// Search relative to current module
-// > Search local use definitions (function-level)
-// - TODO: Local use statements (scoped)
-// > Search module-level definitions
-bool lookup_path_in_module(const Span& span, const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path, const ::std::string& name, bool is_leaf)
-{
- TRACE_FUNCTION_F("mod_path="<<mod_path);
- // - Allow leaf nodes if path is a single node, don't skip private wildcard imports
- auto item = module.find_item(name, is_leaf, false);
- TU_MATCH_DEF(AST::Module::ItemRef, (item), (i),
- (
- path = mod_path + path;
- //path.resolve( crate );
- return true;
- ),
- (None,
- return false;
- ),
- (Use,
- const auto& imp = i;
- if( imp.name == "" )
- {
- DEBUG("Wildcard import found, " << imp.data << " + " << path);
- // Wildcard path, prefix entirely with the path
- path = imp.data.path + path;
- //path.resolve( crate );
- return true;
- }
- else
- {
- DEBUG("Named import found, " << imp.data << " + " << path << " [1..]");
- path = AST::Path::add_tailing(imp.data.path, path);
- //path.resolve( crate );
- return true;
- }
- return false;
- ),
- (Module,
- // Check name down?
- // Add current module path
- path = mod_path + path;
- //path.resolve( crate );
- return true;
- )
- )
- assert(!"");
-}
-bool lookup_path_in_module(const Span &span, const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path) {
- return lookup_path_in_module(span, crate, module, mod_path, path, path[0].name(), path.size() == 1);
-}
-
-/// Perform path resolution within a generic definition block
-void CPathResolver::handle_params(AST::GenericParams& params)
-{
- TRACE_FUNCTION;
- // Parameters
- DEBUG("params");
- for( auto& param : params.ty_params() )
- {
- // - Resolve the default type
- handle_type(param.get_default());
- // - Register each param as a type name within this scope
- local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name(), params) );
- }
- DEBUG("Bounds");
- for( auto& bound : params.bounds() )
- {
- DEBUG("- Bound " << bound);
-
- TU_MATCH(AST::GenericBound, (bound), (ent),
- (Lifetime,
- {}
- ),
- (TypeLifetime,
- handle_type(ent.type);
- ),
- (IsTrait,
- handle_type(ent.type);
- // TODO: Should 'Self' in this trait be ent.type?
-
- //if(ent.type.is_path() && ent.type.path().binding().is_Unbound())
- // BUG(span, "Unbound path after handle_type in handle_params - ent.type=" << ent.type);
- push_self(ent.type);
- handle_path(ent.trait, MODE_TYPE);
- pop_self();
- ),
- (MaybeTrait,
- handle_type(ent.type);
- push_self();
- handle_path(ent.trait, MODE_TYPE);
- pop_self();
- ),
- (NotTrait,
- handle_type(ent.type);
- push_self();
- handle_path(ent.trait, MODE_TYPE);
- pop_self();
- ),
- (Equality,
- handle_type(ent.type);
- handle_type(ent.replacement);
- )
- )
- }
-}
-
-/// Resolve names within a path
-void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode)
-{
- const Span span = Span();
- TRACE_FUNCTION_F("(path = " << path << ", mode = "<<mode<<"), m_module_path = " << m_module_path);
-
- handle_path_int(span, path, mode);
-
- // Handle generic components of the path
- // - Done AFTER resoltion, as binding might introduce defaults (which may not have been resolved)
- TU_MATCH(AST::Path::Class, (path.m_class), (info),
- (Invalid),
- (Local),
- (Relative,
- DEBUG("Relative path after handle_path_int - path=" << path);
- assert( !"Relative path after handle_path_int");
- ),
- (Self,
- assert( !"Relative (self) path after handle_path_int");
- ),
- (Super,
- assert( !"Relative (super) path after handle_path_int");
- ),
- (Absolute,
- if( path.binding().is_Unbound() ) {
- BUG(span, "Path wasn't bound after handle_path - path=" << path);
- }
- for( auto& ent : info.nodes )
- for( auto& arg : ent.args() )
- handle_type(arg);
- ),
- (UFCS,
- handle_type(*info.type);
- handle_type(*info.trait);
- for( auto& ent : info.nodes )
- for( auto& arg : ent.args() )
- handle_type(arg);
- )
- )
-}
-
-void CPathResolver::handle_path_int(const Span& span, 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() )
- {
- case AST::Path::Class::TAG_Invalid:
- // TODO: Throw an error
- assert( !path.m_class.is_Invalid() );
- return;
- // --- Already absolute forms
- // > Absolute: Resolve
- case AST::Path::Class::TAG_Absolute:
- DEBUG("Absolute - binding");
- INDENT();
- handle_path_abs(span, path, mode);
- // TODO: Move Path::resolve() to this file
- // Already absolute, our job is done
- // - However, if the path isn't bound, bind it
- if( path.binding().is_Unbound() ) {
- //path.resolve(m_crate);
- }
- else {
- DEBUG("- Path " << path << " already bound");
- }
- UNINDENT();
- break;
- // > UFCS: Resolve the type and trait
- case AST::Path::Class::TAG_UFCS:
- handle_path_ufcs(span, path, mode);
- break;
- // > Variable: (wait, how is this known already?)
- // - 'self', 'Self'
- case AST::Path::Class::TAG_Local:
- DEBUG("Check local");
- if( !path.binding().is_Unbound() )
- {
- DEBUG("- Path " << path << " already bound");
- }
- else
- {
- const auto& info = path.m_class.as_Local();
- // 1. Check for local items
- if( this->find_local_item(span, path, info.name, (mode == CASTIterator::MODE_EXPR)) ) {
- if( path.is_absolute() ) {
- handle_path_abs(span, path, mode);
- }
- break ;
- }
- else {
- // No match, fall through
- }
- // 2. Type parameters (ONLY when in type mode)
- if( mode == CASTIterator::MODE_TYPE ) {
- throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int type param");
- }
- // 3. Module items
- if( this->find_mod_item(span, path, info.name) ) {
- handle_path_abs(span, path, mode);
- break;
- }
- else {
- }
-
- DEBUG("no matches found for path = " << path);
- if( mode != MODE_BIND )
- throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (Local)");
- return ;
- }
- if(0)
-
- // Unannotated relative
- case AST::Path::Class::TAG_Relative:
- handle_path_rel(span, path, mode);
- if(0)
-
- // Module relative
- case AST::Path::Class::TAG_Self:
- {
- if( this->find_self_mod_item(span, path, path[0].name()) ) {
- // Fall
- }
- else {
- DEBUG("no matches found for path = " << path);
- if( mode != MODE_BIND )
- throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed");
- }
- }
- if(0)
- // Parent module relative
- // TODO: "super::" can be chained
- case AST::Path::Class::TAG_Super:
- {
- if( this->find_super_mod_item(span, path, path[0].name()) ) {
- // Fall
- }
- else {
- DEBUG("no matches found for path = " << path);
- if( mode != MODE_BIND )
- throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed");
- }
- }
- // Common for Relative, Self, and Super
- DEBUG("Post relative resolve - path=" << path);
- if( path.is_absolute() ) {
- handle_path_abs(span, path, mode);
- }
- else {
- }
- return ;
- }
-
- // TODO: Are there any reasons not to be bound at this point?
- //assert( !path.binding().is_Unbound() );
-}
-
-// Validates all components are able to be located, and converts Trait/Struct/Enum::Item into UFCS format
-void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTIterator::PathMode mode)
-{
- //bool expect_params = false;
-
- if( !path.m_class.is_Absolute() ) {
- BUG(span, "Non-absolute path passed to CPathResolver::handle_path_abs - path=" << path);
- }
-
- auto& nodes = path.m_class.as_Absolute().nodes;
-
- unsigned int slice_from = 0; // Used when rewriting the path to be relative to its crate root
-
- // Iterate through nodes, starting at the root module of the specified crate
- // - Locate the referenced item, and fail if any component isn't found
- ::std::vector<const AST::Module*> mod_stack;
- const AST::Module* mod = &this->m_crate.get_root_module(path.crate());
- for(unsigned int i = 0; i < nodes.size(); i ++ )
- {
- mod_stack.push_back(mod);
- const bool is_last = (i+1 == nodes.size());
- const AST::PathNode& node = nodes[i];
- DEBUG("[" << i << "/"<<nodes.size()<<"]: " << node);
-
- if( node.name()[0] == '#' )
- {
- // HACK - Compiler-provided functions/types live in the special '#' module
- if( node.name() == "#" ) {
- if( i != 0 )
- throw ParseError::BugCheck("# module not at path root");
- mod = &g_compiler_module;
- continue ;
- }
-
- // Hacky special case - Anon modules are indexed
- // - Darn you C++ and no string views
- unsigned int index = ::std::strtoul(node.name().c_str()+1, nullptr, 10); // Parse the number at +1
- DEBUG(" index = " << index);
- if( index >= mod->anon_mods().size() )
- throw ParseError::Generic("Anon module index out of range");
- mod = mod->anon_mods().at(index);
- continue ;
- }
-
- auto item_ref = mod->find_item(node.name(), is_last); // Only allow leaf nodes (functions and statics) if this is the last node
- TU_MATCH( AST::Module::ItemRef, (item_ref), (item),
- // Not found
- (None,
- // If parent node is anon, backtrack and try again
- // TODO: I feel like this shouldn't be done here, instead perform this when absolutising (now that find_item is reusable)
- if( i > 0 && nodes[i-1].name()[0] == '#' && nodes[i-1].name().size() > 1 )
- {
- i --;
- mod_stack.pop_back();
- mod = mod_stack.back();
- mod_stack.pop_back();
- nodes.erase(nodes.begin()+i);
- i --;
- DEBUG("Failed to locate item in nested, look upwards");
-
- continue ;
- }
- ERROR(span, E0000, "Unable to find component '" << node.name() << "' of path " << path);
- ),
- // Sub-module
- (Module,
- DEBUG("Sub-module : " << node.name());
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to module");
- mod = &item;
- ),
- // Crate
- (Crate,
- const ::std::string& crate_name = item;
- DEBUG("Extern crate '" << node.name() << "' = '" << crate_name << "'");
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to extern crate");
- path.set_crate( crate_name );
- slice_from = i+1;
- mod = &this->m_crate.get_root_module(crate_name);
- ),
-
- // Type Alias
- (TypeAlias,
- const auto& ta = item;
- DEBUG("Type alias <"<<ta.params()<<"> " << ta.type());
- //if( node.args().size() != ta.params().size() )
- // throw ParseError::Generic("Param count mismatch when referencing type alias");
- // Make a copy of the path, replace params with it, then replace *this?
- // - Maybe leave that up to other code?
- if( is_last ) {
- //check_param_counts(ta.params(), expect_params, nodes[i]);
- // TODO: Bind / replace
- // - Replacing requires checking type params (well, at least the count)
- path.bind_type_alias(ta);
- goto ret;
- }
- 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 ;
- }
- ),
-
- // Function
- (Function,
- const auto& fn = item;
- DEBUG("Found function");
- if( is_last ) {
- //check_param_counts(fn.params(), expect_params, nodes[i]);
- path.bind_function(fn);
- goto ret;
- }
- else {
- throw ParseError::Generic("Import of function, too many extra nodes");
- }
- ),
-
- // Trait
- (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);
- goto ret;
- }
- 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 ;
- }
- ),
-
- // Struct
- (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());
- goto ret;
- }
- 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 ;
- }
- ),
-
- // Enum / enum variant
- (Enum,
- const auto& enm = item;
- DEBUG("Found enum");
- if( is_last ) {
- //check_param_counts(enm.params(), expect_params, nodes[i]);
- path.bind_enum(enm, node.args());
- goto ret;
- }
- 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 ;
- }
- ),
-
- (Static,
- const auto& st = item;
- DEBUG("Found static/const");
- if( is_last ) {
- if( node.args().size() )
- throw ParseError::Generic("Unexpected generic params on static/const");
- path.bind_static(st);
- goto ret;
- }
- else {
- throw ParseError::Generic("Binding path to static, trailing nodes");
- }
- ),
-
- // Re-export
- (Use,
- const auto& imp = item;
- AST::Path newpath = imp.data.path;
- auto& newnodes = newpath.m_class.as_Absolute().nodes;
- DEBUG("Re-exported path " << imp.data);
- if( imp.name == "" )
- {
- // Replace nodes 0:i-1 with source path, then recurse
- for( unsigned int j = i; j < nodes.size(); j ++ )
- {
- newnodes.push_back( nodes[j] );
- }
- }
- else
- {
- // replace nodes 0:i with the source path
- for( unsigned int j = i+1; j < nodes.size(); j ++ )
- {
- newnodes.push_back( nodes[j] );
- }
- }
-
- DEBUG("- newpath = " << newpath);
- // TODO: This should check for recursion somehow
- this->handle_path_abs(span, newpath, mode);
-
- path = mv$(newpath);
- return;
- )
- )
- }
-
- // We only reach here if the path points to a module
- path.bind_module( *mod );
-ret:
- if( slice_from > 0 )
- {
- DEBUG("Removing " << slice_from << " nodes to rebase path to crate root");
- nodes.erase(nodes.begin(), nodes.begin()+slice_from);
- }
- return ;
-}
-// Starting from the `slice_from`th element, take until `split_point` as the type path, and the rest of the nodes as UFCS items
-void CPathResolver::handle_path_abs__into_ufcs(const Span& span, AST::Path& path, unsigned slice_from, unsigned split_point)
-{
- TRACE_FUNCTION_F("(path = " << path << ", slice_from=" << slice_from << ", split_point=" << split_point << ")");
- assert(slice_from < path.size());
- assert(slice_from < split_point);
- // Split point must be at most the last index
- assert(split_point < path.size());
-
- const auto& nodes = path.nodes();
- AST::Path type_path(path.crate(), ::std::vector<AST::PathNode>( nodes.begin() + slice_from, nodes.begin() + split_point ));
- for(unsigned i = split_point; i < nodes.size(); i ++)
- {
- DEBUG("type_path = " << type_path << ", nodes[i] = " << nodes[i]);
- resolve_path(span, m_crate, type_path);
- // If the type path refers to a trait, put it in the trait location
- if(type_path.binding().is_Trait()) {
- type_path = AST::Path(AST::Path::TagUfcs(), TypeRef(span), TypeRef(span, mv$(type_path)), {mv$(nodes[i])} );
- }
- else {
- type_path = AST::Path(AST::Path::TagUfcs(), TypeRef(span, mv$(type_path)), TypeRef(span), {mv$(nodes[i])} );
- }
- }
-
- path = mv$(type_path);
-}
-
-
-/// Handles path resolution for UFCS format paths (<Type as Trait>::Item)
-void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIterator::PathMode mode)
-{
- assert(path.m_class.is_UFCS());
- auto& info = path.m_class.as_UFCS();
- TRACE_FUNCTION_F("info={< " << *info.type << " as " << *info.trait << ">::" << info.nodes << "}");
- // 1. Handle sub-types
- handle_type(*info.type);
- handle_type(*info.trait);
-
- // - Some quick assertions
- if( info.type->is_path() )
- {
- TU_MATCH_DEF(AST::PathBinding, (info.type->path().binding()), (i),
- (
- // Invalid
- BUG(span, "Invalid item class for type in path " << path);
- ),
- //(Unbound,
- // ),
- //(Trait, ),
- (Struct, ),
- (Enum, )
- )
- }
-
- // 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
- // - Impl heads and trait heads could be resolved in an earlier pass
- if( info.trait->is_wildcard() )
- {
- // 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 1
- 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
-
- // 1. Inherent
- //AST::Impl* impl_ptr;
- ::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)
- 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;
- const void* ptr;
- AST::Path 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(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 )
- TODO(span, "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( span, mv$(found_trait_path) );
- }
- else {
- ERROR(span, E0000, "Cannot find item '" << item_name << "' on Self");
- }
- }
- 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);
- bool success = false;
-
- // Enumerate bounds
- for( const auto& bound : tp.bounds() )
- {
- DEBUG("bound = " << bound);
- TU_MATCH_DEF(AST::GenericBound, (bound), (ent),
- (),
- (IsTrait,
- if( ent.type == *info.type ) {
- auto& t = *const_cast<AST::Trait*>(ent.trait.binding().as_Trait().trait_);
- DEBUG("Type match, t.params() = " << t.params());
- bool is_method;
- AST::Path found_trait_path;
- DEBUG("find_trait_item(" << ent.trait << /*", t=" << t <<*/ ", item_name = " << item_name);
- if( this->find_trait_item(span, ent.trait, t, item_name, is_method, found_trait_path) )
- {
- if( is_method ) {
- if( info.nodes.size() != 1 )
- throw ParseError::Generic("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) );
- success = true;
- break ;
- }
- }
- else {
- DEBUG("Type mismatch " << ent.type << " != " << *info.type);
- }
- )
- )
- }
-
- if( !success )
- 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
- 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& i : impl.items() )
- {
- if( i.name == name ) {
- TU_MATCH_DEF(AST::Item, (i.data), (e),
- (
- // Ignore?
- ),
- (Function,
- path.bind_function(e, path.nodes()[0].args());
- info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid(), span) );
- 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 ),
- *info.trait = TypeRef( span, trait_p );
- return ;
- )
- }
- }
-
- TODO(span, "CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type << " - name='"<<name<<"'");
- }
- #endif
- }
- else
- {
- const auto& name = path.nodes()[0].name();
- if( info.type->is_path() )
- {
- // 1. Search for enum constructors
- TU_MATCH_DEF(AST::PathBinding, (info.type->path().binding()), (i),
- ( ),
- (Enum,
- const auto& e = *i.enum_;
- for(const auto& var : e.variants())
- {
- if( var.m_name == name ) {
- path.bind_enum_var(e, name);
- info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid(), span) );
- return ;
- }
- }
- )
- )
- }
- }
- }
- else
- {
- #if 0
- const auto& name = path.nodes()[0].name();
- // Trait is known, need to ensure that the named item exists
- assert(info.trait->path().binding().is_Trait());
- const auto &tr = *info.trait->path().binding().as_Trait().trait_;
-
- // TODO: Need to try super-traits AND applicable type impls
- // - E.g. "impl Any {"
- switch(mode)
- {
- case MODE_EXPR:
- for( const auto& fcn : tr.functions() )
- {
- DEBUG("fcn.name = " << fcn.name);
- if(fcn.name == name) {
- path.bind_function(fcn.data);
- break;
- }
- }
- //for( const auto& fcn : tr.constants() )
- //{
- //}
- break;
- case MODE_BIND:
- //for( const auto& fcn : tr.constants() )
- //{
- //}
- break;
- case MODE_TYPE:
- for( const auto& it : tr.types() )
- {
- if(it.name == name) {
- path.bind_type_alias(it.data);
- break;
- }
- }
- break;
- }
- if(mode == MODE_EXPR && path.binding().is_Unbound()) {
- // TODO: Locate an 'impl Trait' block for methods
- }
- if(path.binding().is_Unbound()) {
- ERROR(span, E0000, "Unable to locate item '" << name << "' in trait " << *info.trait << " (mode=" << mode << ")");
- }
- #endif
- }
-}
-void CPathResolver::handle_path_rel(const Span& span, AST::Path& path, CASTIterator::PathMode mode)
-{
- // 1. function scopes (variables and local items)
- // > Return values: name or path
- {
- bool allow_variables = (mode == CASTIterator::MODE_EXPR && path.is_trivial());
- if( this->find_local_item(span, path, path[0].name(), allow_variables) ) {
- return ;
- }
- }
-
- // 2. Type parameters
- // - Should probably check if this is expression mode, bare types are invalid there
- // NOTES:
- // - If the path is bare (i.e. there are no more nodes), then ensure that the mode is TYPE
- // - If there are more nodes, replace with a UFCS block
- {
- auto tp = this->find_type_param(path[0].name());
- if( tp != false /*nullptr*/ || path[0].name() == "Self" )
- {
- if(path.size() > 1) {
- auto ty = TypeRef(TypeRef::TagArg(), path[0].name());
- //ty.set_span( path.span() );
- // Repalce with UFCS
- auto newpath = AST::Path(AST::Path::TagUfcs(), ty, TypeRef());
- newpath.add_tailing(path);
- path = mv$(newpath);
- }
- else {
- // Mark as local
- // - TODO: Not being trivial is an error, not a bug
- assert( path.is_trivial() );
- path = AST::Path(AST::Path::TagLocal(), path[0].name());
- // - TODO: Need to bind this to the source parameter block
- }
- return ;
- }
- }
-
- // 3. current module
- {
- if( this->find_mod_item(span, path, path[0].name()) ) {
- return ;
- }
- else {
- }
- }
-
- // 4. If there was no match above, and we're in bind mode, set the path to local and return
- DEBUG("no matches found for path = " << path);
- if( mode == MODE_BIND )
- {
- // If mode == MODE_BIND, must be trivial
- if( !path.is_trivial() )
- throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (non-trivial path failed to resolve in MODE_BIND)");
- path = AST::Path(AST::Path::TagLocal(), path[0].name());
- return ;
- }
-
- // 5. Check if the unresolved name is a primitive type
- {
- if( path[0].name() == "str" ) {
- TODO(span, "Expand `str` to internal path");
- }
- else if( auto ct = coretype_fromstring(path[0].name()) ) {
- auto ty = TypeRef(TypeRef::TagPrimitive(), span, ct);
- auto newpath = AST::Path(AST::Path::TagUfcs(), ty, TypeRef());
- newpath.add_tailing(path);
- path = mv$(newpath);
- return ;
- }
- else {
- }
- }
-
- // Z. Otherwise, error
- 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, const void*& out_ptr, AST::Path& out_trait_path)
-{
- TRACE_FUNCTION_F("path=" << path << ", trait=..., item_name=" << item_name);
- {
- const auto& items = trait.items();
- auto it = ::std::find_if( items.begin(), items.end(), [&](const auto& a) { DEBUG("fcn " << a.name); return a.name == item_name; } );
- if( it != items.end() ) {
- // Found it.
- const auto& i = *it;
- TU_MATCH_DEF(AST::Item, (i.data), (e),
- (
- BUG(Span(), "Unknown item type in trait");
- ),
- (Function,
- out_is_method = true;
- out_ptr = &e;
- out_trait_path = AST::Path(path);
- DEBUG("Fcn, out_trait_path = " << out_trait_path);
- return true;
- ),
- (Type,
- 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;
- ),
- (Static,
- TODO(Span(), "Handle resolving associated statics/consts in traits (CPathResolver::find_trait_item)");
- )
- )
- }
- }
-
- for( auto& st : trait.supertraits() ) {
- 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(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) -> TypeRef {
- int idx = trait.params().find_name(name);
- if(idx < 0)
- ERROR(span, E0000, "Parameter " << name << " not found");
- if(static_cast<unsigned int>(idx) >= path.nodes().back().args().size())
- ERROR(span, E0000, "Path '"<<path<<"' had too few args");
- const auto& tr = path.nodes().back().args().at(idx);
- DEBUG("Replacing '" << name << "' with " << tr);
- return tr;
- });
- return true;
- }
- }
-
- return false;
-}
-
-bool CPathResolver::find_local_item(const Span& span, AST::Path& path, const ::std::string& name, bool allow_variables)
-{
- TRACE_FUNCTION_F("path="<<path<<", allow_variables="<<allow_variables);
- // Search current scopes for a name
- // - This should search both the expression stack
- // - and the scope's module (if any)
- for(auto it = m_scope_stack.rbegin(); it != m_scope_stack.rend(); ++it)
- {
- const auto& s = *it;
- if( allow_variables )
- {
- for( auto it2 = s.locals.rbegin(); it2 != s.locals.rend(); ++it2 )
- {
- if( *it2 == name ) {
- path = AST::Path(AST::Path::TagLocal(), name);
- path.bind_variable(0);
- return true;
- }
- }
- }
- if( s.module != nullptr )
- {
- DEBUG("- Looking in sub-module '" << s.module_path << "'");
- if( lookup_path_in_module(span, m_crate, *s.module, s.module_path, path, name, path.is_trivial()) )
- return true;
- }
- }
- DEBUG("- find_local_item: Not found");
- return false;
-}
-bool CPathResolver::find_mod_item(const Span& span, AST::Path& path, const ::std::string& name) {
- TRACE_FUNCTION_F("path="<<path<<", name="<<name);
- const AST::Module* mod = m_module;
- const AST::Path* modpath = &m_module_path;
- unsigned int idx = m_module_stack.size() - 1;
- for(;;)
- {
- DEBUG("modpath = " << *modpath << ", mod->path() = '" << mod->path() << "'");
- if( lookup_path_in_module(span, m_crate, *mod, *modpath, path, name, path.size()==1) )
- return true;
- DEBUG("mod->path() = '" << mod->path() << "', idx = " << idx);
- if( mod->is_anon() && idx > 0 ) {
- idx --;
- mod = m_module_stack[idx].first;
- modpath = &m_module_stack[idx].second;
- }
- else {
- break ;
- }
- }
- return false;
-}
-bool CPathResolver::find_self_mod_item(const Span& span, AST::Path& path, const ::std::string& name) {
- if( m_module->is_anon() )
- throw ParseError::Todo("Correct handling of 'self' in anon modules");
-
- return lookup_path_in_module(span, m_crate, *m_module, m_module_path, path, name, path.size()==1);
-}
-bool CPathResolver::find_super_mod_item(const Span& span, AST::Path& path, const ::std::string& name) {
- if( m_module->is_anon() )
- throw ParseError::Todo("Correct handling of 'super' in anon modules");
-
- // 1. Construct path to parent module
- AST::Path super_path = m_module_path;
- super_path.nodes().pop_back();
- assert( super_path.nodes().size() > 0 );
- if( super_path.nodes().back().name()[0] == '#' )
- throw ParseError::Todo("Correct handling of 'super' in anon modules (parent is anon)");
- // 2. Resolve that path
- resolve_path(span, m_crate, super_path);
- // 3. Call lookup_path_in_module
- assert( super_path.binding().is_Module() );
- return lookup_path_in_module(span, m_crate, *super_path.binding().as_Module().module_, super_path, path, name, path.size()==1);
-}
-bool CPathResolver::find_type_param(const ::std::string& name) {
- for( auto it = m_locals.end(); it -- != m_locals.begin(); )
- {
- if( it->type == LocalItem::TYPE ) {
- if( it->name == name ) {
- return true;
- }
- }
- }
- return false;
-}
-
-void CPathResolver::handle_type(TypeRef& type)
-{
- TRACE_FUNCTION_F("type = " << type);
- // PROBLEM: Recursion when evaluating Self that expands to UFCS mentioning Self
- // > The inner Self shouldn't be touched, but it gets hit by this method, and sudden recursion
- //if( type.is_locked() )
- //{
- //}
- //else
- if( type.is_path() && type.path().is_trivial() )
- {
- const auto& name = type.path()[0].name();
- auto opt_local = lookup_local(LocalItem::TYPE, name);
-
- if( opt_local.is_some() )
- {
- DEBUG("Found local '" << name << "' aliasing to " << opt_local.unwrap().tr);
- type = opt_local.unwrap().tr;
- }
- else if( name == "Self" )
- {
- // TODO: Should I always resolve `Self` when it's concretely known?
- // If the name was "Self", but Self isn't already defined... then we need to make it an arg?
- if( this->m_self_type.empty() || this->m_self_type.back().is_None() ) {
- ERROR(Span(), E0000, "Unexpected 'Self'");
- }
- else {
- TU_MATCH(SelfType, (this->m_self_type.back()), (ent),
- (None,
- assert(!"SelfType is None in CPathResolver::handle_type");
- ),
- (Type,
- DEBUG("Self type is " << ent.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
- {
- // Not a type param, fall back to other checks
- }
- }
- else if( type.is_type_param() )
- {
- const auto& name = type.type_param();
- auto opt_local = lookup_local(LocalItem::TYPE, name);
- if( name == "Self" )
- {
- 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,
- DEBUG("Self type is " << ent.type);
- type = ent.type;
- return ;
- ),
- (Trait,
- // Valid...
- )
- )
- }
- else if( opt_local.is_some() )
- {
- type = opt_local.unwrap().tr;
- }
- else
- {
- // Not a type param, fall back to other checks
- throw CompileError::Generic( FMT("CPathResolver::handle_type - Invalid parameter '" << name << "'") );
- }
- }
- else
- {
- // No change
- }
- DEBUG("type = " << type);
-
- //if
-
- //if( type.is_type_param() && type.type_param() == "Self" )
- //{
- // auto l = lookup_local(LocalItem::TYPE, "Self");
- // if( l.is_some() )
- // {
- // type = l.unwrap().tr;
- // DEBUG("Replacing Self with " << type);
- // // TODO: Can this recurse?
- // handle_type(type);
- // return ;
- // }
- //}
- CASTIterator::handle_type(type);
- DEBUG("res = " << type);
-}
-void CPathResolver::handle_expr(AST::ExprNode& node)
-{
- CResolvePaths_NodeVisitor nv(*this);
- node.visit(nv);
-}
-
-void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
-{
- TRACE_FUNCTION_F("pat = " << pat);
- // Resolve "Maybe Bind" entries
- if( pat.data().is_MaybeBind() )
- {
- ::std::string name = pat.binding();
- // Locate a _constant_ within the current namespace which matches this name
- // - Variables don't count
- AST::Path newpath = AST::Path(AST::Path::TagRelative(), { AST::PathNode(name) });
- handle_path(newpath, CASTIterator::MODE_BIND);
- if( newpath.is_relative() || newpath.is_trivial() )
- {
- // It's a name binding (desugar to 'name @ _')
- pat = AST::Pattern();
- pat.set_bind(name, AST::Pattern::BIND_MOVE, false);
- }
- else
- {
- // It's a constant (enum variant usually)
- pat = AST::Pattern(
- AST::Pattern::TagValue(),
- AST::Pattern::Value::make_Named( mv$(newpath) )
- );
- }
- }
-
- // hand off to original code
- CASTIterator::handle_pattern(pat, type_hint);
-}
-void CPathResolver::handle_module(AST::Path path, AST::Module& mod)
-{
- ::std::vector<Scope> saved = mv$(m_scope_stack);
- // NOTE: Assigning here is safe, as the CASTIterator handle_module iterates submodules as the last action
- m_module = &mod;
- m_module_path = AST::Path(path);
- m_module_stack.push_back( ::std::make_pair(&mod, m_module_path) );
- CASTIterator::handle_module(mv$(path), mod);
- m_module_stack.pop_back();
- m_scope_stack = mv$(saved);
-}
-void CPathResolver::handle_trait(AST::Path path, AST::Trait& trait)
-{
- //path.resolve(m_crate);
-
- // Handle local
- 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)
-{
- m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} );
- CASTIterator::handle_function(::std::move(path), fcn);
- m_scope_stack.pop_back();
-}
-
-
-void absolutise_path(const Span& span, const AST::Crate& crate, const AST::Module& mod, const AST::Path& modpath, AST::Path& path)
-{
- // TODO: Should this code resolve encountered use statements into the real path?
- TU_MATCH(AST::Path::Class, (path.m_class), (info),
- (Invalid,
- BUG(span, "Invalid path type encountered - Class::Invalid");
- ),
- (Local,
- // Known-local paths don't need to be absolutised
- ),
- (Absolute,
- // Nothing needs to be done
- ),
- (Super,
- // TODO: Super supports multiple instances
- auto newpath = modpath;
- newpath.nodes().pop_back();
- newpath += path;
- DEBUG("Absolutised path " << path << " into " << newpath);
- path = ::std::move(newpath);
- ),
- (Self,
- auto modpath_tmp = modpath;
- const AST::Module* mod_ptr = &mod;
- while( modpath_tmp.size() > 0 && modpath_tmp.nodes().back().name()[0] == '#' )
- {
- if( !mod_ptr->find_item(path.nodes()[0].name()).is_None() ) {
- break ;
- }
- modpath_tmp.nodes().pop_back();
- resolve_path(span, crate, modpath_tmp);
- DEBUG("modpath_tmp = " << modpath_tmp);
- assert( modpath_tmp.binding().is_Module() );
- mod_ptr = modpath_tmp.binding().as_Module().module_;
- }
- auto newpath = modpath_tmp + path;
- DEBUG("Absolutised path " << path << " into " << newpath);
- path = ::std::move(newpath);
- ),
- (Relative,
- auto newpath = modpath + path;
- DEBUG("Absolutised path " << path << " into " << newpath);
- path = ::std::move(newpath);
- ),
- (UFCS,
- throw ParseError::Generic( FMT("Invalid path type encounted - UFCS " << path) );
- )
- )
-}
-
-void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod)
-{
- TRACE_FUNCTION_F("modpath = " << modpath << ", mod = {path:" << mod.path() << "}");
- ::std::vector<AST::Path> new_imports;
- for( auto& imp : mod.imports() )
- {
- const Span& span = imp.data.sp;
- DEBUG("p = " << imp.data);
- absolutise_path(span, crate, mod, modpath, imp.data.path);
-
- resolve_path(span, crate, imp.data.path);
- DEBUG("Resolved import : " << imp.data);
-
- // If wildcard, make sure it's sane
- if( imp.name == "" )
- {
- TU_MATCH_DEF(AST::PathBinding, (imp.data.path.binding()), (info),
- (
- throw ParseError::Generic("Wildcard imports are only allowed on modules and enums");
- ),
- (Unbound,
- throw ParseError::BugCheck("Wildcard import path unbound after calling .resolve()");
- ),
- (Module, (void)0;),
- (Enum, (void)0;)
- )
- }
- }
-
- for( auto& new_imp : new_imports )
- {
- //if( new_imp.binding().is_Unbound() ) {
- // new_imp.resolve(crate, false);
- //}
- // TODO: Get attributes from the source import
- mod.add_alias(false, ::AST::UseStmt(Span(), new_imp), new_imp[new_imp.size()-1].name(), ::AST::MetaItems());
- }
-
- for(auto& item : mod.items()) {
- if( item.data.is_Module() ) {
- ResolvePaths_HandleModule_Use(crate, modpath + item.name, item.data.as_Module());
- }
- }
-}
-
-void SetCrateName_Type(const AST::Crate& crate, ::std::string name, TypeRef& type)
-{
- if( type.is_path() )
- {
- type.path().set_crate(name);
- //type.path().resolve(crate);
- }
-}
-
-void SetCrateName_Mod(const AST::Crate& crate, ::std::string name, AST::Module& mod)
-{
- for(auto& item : mod.items()) {
- if( item.data.is_Module() ) {
- SetCrateName_Mod(crate, name, item.data.as_Module());
- }
- }
- // Imports 'use' statements
- for(auto& imp : mod.imports())
- {
- imp.data.path.set_crate(name);
- // - Disable expectation of type parameters
- //imp.data.resolve(crate, false);
- }
-
- // TODO: All other types
- for(auto& item : mod.items()) {
- if( item.data.is_Function() ) {
- SetCrateName_Type(crate, name, item.data.as_Function().rettype());
- }
- }
-}
-
-
-// First pass of conversion
-// - Tag paths of external crate items with crate name
-// - Convert all paths into absolute paths (or local variable references)
-void ResolvePaths(AST::Crate& crate)
-{
- DEBUG(" >>>");
- // Pre-process external crates to tag all paths
- #if 0
- DEBUG(" --- Extern crates");
- INDENT();
- for(auto& ec : crate.extern_crates())
- {
- SetCrateName_Mod(crate, ec.first, ec.second.root_module());
- }
- UNINDENT();
- #endif
-
- // Handle 'use' statements in an initial parss
- DEBUG(" --- Use Statements");
- INDENT();
- ResolvePaths_HandleModule_Use(crate, AST::Path("", {}), crate.root_module());
- UNINDENT();
-
- // Resolve traits next, to ensure they're usable
- //ResolvePaths_HandleModule_Trait(crate, AST::Path("", {}), crate.root_module());
- // Resolve impl block headers
- //ResolvePaths_HandleModule_Impl(crate, AST::Path("", {}), crate.root_module());
-
- // Then do path resolution on all other items
- CPathResolver pr(crate);
- DEBUG(" ---");
- pr.handle_module(AST::Path("", {}), crate.root_module());
- DEBUG(" <<<");
-
- pr.m_second_pass = true;
- DEBUG(" ---");
- pr.handle_module(AST::Path("", {}), crate.root_module());
- DEBUG(" <<<");
-}
diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp
deleted file mode 100644
index f2cda828..00000000
--- a/src/convert/typecheck_bounds.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- */
-#include <main_bindings.hpp>
-#include "ast_iterate.hpp"
-#include "../ast/crate.hpp"
-#include "../common.hpp"
-#include <stdexcept>
-
-class CGenericBoundChecker:
- public CASTIterator
-{
- void check_is_trait(const AST::Path& trait) const;
-public:
- virtual void handle_expr(AST::ExprNode& root) override;
- virtual void handle_params(AST::GenericParams& params) override;
-};
-
-void CGenericBoundChecker::handle_expr(AST::ExprNode& root)
-{
- // Do nothing (this iterator shouldn't recurse into expressions)
-}
-
-void CGenericBoundChecker::check_is_trait(const AST::Path& trait) const {
- assert( !trait.binding().is_Unbound() );
- DEBUG("trait = " << trait);
- if( trait.binding().is_Trait() )
- {
- //throw CompileError::BoundNotTrait( bound.lex_scope(), bound.param(), trait );
- throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait : " << trait.binding()));
- }
- else {
- DEBUG("Bound is a trait, good");
- }
-}
-
-void CGenericBoundChecker::handle_params(AST::GenericParams& params)
-{
- for(auto& bound : params.bounds())
- {
- TU_MATCH(AST::GenericBound, (bound), (ent),
- (Lifetime, {}),
- (TypeLifetime, {}),
- (IsTrait, this->check_is_trait(ent.trait);),
- (MaybeTrait, this->check_is_trait(ent.trait);),
- (NotTrait, this->check_is_trait(ent.trait);),
- (Equality, {})
- )
- }
-}
-
-/// Typecheck generic bounds (where clauses)
-void Typecheck_GenericBounds(AST::Crate& crate)
-{
- DEBUG(" --- ");
- CGenericBoundChecker chk;
- chk.handle_module(AST::Path("", {}), crate.root_module());
-}
-
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp
deleted file mode 100644
index 59e9a4aa..00000000
--- a/src/convert/typecheck_expr.cpp
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * MRustC - Mutabah's Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * convert/typecheck_expr.cpp
- * - Handles type checking, expansion, and method resolution for expressions (function bodies)
- */
-#include <main_bindings.hpp>
-#include "ast_iterate.hpp"
-#include "../ast/expr.hpp"
-#include "../ast/crate.hpp"
-#include "../common.hpp"
-#include <stdexcept>
-
-// === PROTOTYPES ===
-class CTypeChecker:
- public CASTIterator
-{
- friend class CTC_NodeVisitor;
-
- struct Scope {
- ::std::vector< ::std::tuple<bool, ::std::string, TypeRef> > vars;
- ::std::vector< ::std::tuple< ::std::string, TypeRef> > types;
- ::std::map< ::std::string, TypeRef > params;
- ::std::vector< AST::Path > traits;
- };
-
- AST::Crate& m_crate;
- ::std::vector<Scope> m_scopes;
-
-public:
- CTypeChecker(AST::Crate& crate):
- m_crate(crate)
- {}
-
- virtual void start_scope() override;
- virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type) override;
- virtual void local_type(::std::string name, TypeRef type) override;
- virtual void end_scope() override;
-
- virtual void handle_params(AST::GenericParams& params) override;
-
- virtual void handle_pattern_enum(
- ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::GenericParams& enum_params, const AST::EnumVariant& var,
- ::std::vector<AST::Pattern>& sub_patterns
- ) override;
-
- virtual void handle_function(AST::Path path, AST::Function& fcn) override;
- // - Ignore all non-function items on this pass
- virtual void handle_enum(AST::Path path, AST::Enum& ) override {}
- virtual void handle_struct(AST::Path path, AST::Struct& str) override {}
- virtual void handle_alias(AST::Path path, AST::TypeAlias& ) override {}
-
-private:
- TypeRef& get_local_var(const char* name);
- const TypeRef& get_local_type(const char* name);
- const TypeRef& get_type_param(const char* name);
-
- void check_enum_variant(
- ::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes,
- const AST::GenericParams& params, const AST::EnumVariant& var
- );
- void iterate_traits(::std::function<bool(const TypeRef& trait)> fcn);
-};
-class CTC_NodeVisitor:
- public AST::NodeVisitorDef
-{
- CTypeChecker& m_tc;
-public:
- CTC_NodeVisitor(CTypeChecker& tc):
- m_tc(tc)
- {}
-
- virtual void visit(AST::ExprNode_NamedValue& node) override;
-
- virtual void visit(AST::ExprNode_LetBinding& node) override;
- virtual void visit(AST::ExprNode_Assign& node) override;
-
- virtual void visit(AST::ExprNode_Match& node) override;
-
- virtual void visit(AST::ExprNode_Field& node) override;
- virtual void visit(AST::ExprNode_Cast& node) override;
-
- virtual void visit(AST::ExprNode_CallMethod& node) override;
- virtual void visit(AST::ExprNode_CallPath& node) override;
-};
-
-void CTypeChecker::start_scope()
-{
- m_scopes.push_back( Scope() );
-}
-void CTypeChecker::local_variable(bool is_mut, ::std::string name, const TypeRef& type)
-{
- DEBUG("is_mut=" << is_mut << " name=" << name << " type=" << type);
- m_scopes.back().vars.push_back( make_tuple(is_mut, name, TypeRef(type)) );
-}
-void CTypeChecker::local_type(::std::string name, TypeRef type)
-{
- DEBUG("name=" << name << " type=" << type);
- m_scopes.back().types.push_back( make_tuple(name, ::std::move(type)) );
-}
-void CTypeChecker::end_scope()
-{
- m_scopes.pop_back();
-}
-
-void CTypeChecker::handle_params(AST::GenericParams& params)
-{
- ::std::map<std::string,TypeRef> trs;
-
- for( const auto& param : params.ty_params() )
- {
- trs.insert( make_pair(param.name(), TypeRef()) );
- }
-
- for( const auto& bound : params.bounds() )
- {
- if( bound.is_IsTrait() && bound.as_IsTrait().type.is_type_param() )
- {
- const auto& name = bound.as_IsTrait().type.type_param();
- int i = params.find_name(name.c_str());
- assert(i >= 0);
- // - Just assert that it's valid.
- //trs[name].add_trait( bound.bound() );
- }
- }
-
- assert(m_scopes.back().params.size() == 0);
- m_scopes.back().params = trs;
-}
-void CTypeChecker::handle_pattern_enum(
- ::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::GenericParams& enum_params, const AST::EnumVariant& var,
- ::std::vector<AST::Pattern>& sub_patterns
- )
-{
- #if 0
- check_enum_variant(pat_args, hint_args, enum_params, var);
-
- // Ensure that sub_patterns is the same length as the variant
- const auto& var_types = var.m_sub_types;
- if( sub_patterns.size() != var_types.size() )
- throw ::std::runtime_error(FMT("Enum pattern size mismatch"));
- for( unsigned int i = 0; i < sub_patterns.size(); i ++ )
- {
- // TODO: Need to propagate types through here correctly.
- // - hint_args -> enum -> this
- TypeRef arg = var_types[i];
- arg.resolve_args([&](const char *name){
- int i = enum_params.find_name(name);
- if(i < 0) throw "";
- return hint_args[i];
- });
- handle_pattern(sub_patterns[i], var_types[i]);
- }
- #else
- throw ::std::runtime_error("TODO: CTypeChecker::handle_pattern_enum ");
- #endif
-}
-
-TypeRef& CTypeChecker::get_local_var(const char* name)
-{
- for( auto it = m_scopes.end(); it-- != m_scopes.begin(); )
- {
- for( auto it2 = it->vars.end(); it2-- != it->vars.begin(); )
- {
- if( name == ::std::get<1>(*it2) )
- {
- return ::std::get<2>(*it2);
- }
- }
- }
- throw ::std::runtime_error(FMT("get_local_var - name " << name << " not found"));
-}
-const TypeRef& CTypeChecker::get_local_type(const char* name)
-{
- for( auto it = m_scopes.end(); it-- != m_scopes.begin(); )
- {
- for( auto it2 = it->types.end(); it2-- != it->types.begin(); )
- {
- if( name == ::std::get<0>(*it2) )
- {
- return ::std::get<1>(*it2);
- }
- }
- }
- throw ::std::runtime_error(FMT("get_local_type - name " << name << " not found"));
-}
-const TypeRef& CTypeChecker::get_type_param(const char* name)
-{
- DEBUG("name = " << name);
- for( auto it = m_scopes.end(); it-- != m_scopes.begin(); )
- {
- DEBUG("- params = " << it->params);
- auto ent = it->params.find(name);
- if( ent != it->params.end() )
- {
- DEBUG("> match " << ent->second);
- return ent->second;
- }
- }
- throw ::std::runtime_error(FMT("get_type_param - name " << name << " not found"));
-}
-
-void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn)
-{
- DEBUG("(path = " << path << ")");
- start_scope();
-
- handle_params(fcn.params());
-
- handle_type(fcn.rettype());
-
- for( auto& arg : fcn.args() )
- {
- handle_type(arg.second);
- handle_pattern( arg.first, arg.second );
- }
-
- CTC_NodeVisitor nv(*this);
- if( fcn.code().is_valid() )
- {
- fcn.code().node().get_res_type() = fcn.rettype();
- fcn.code().visit_nodes(nv);
- }
-
- end_scope();
-}
-
-void CTypeChecker::iterate_traits(::std::function<bool(const TypeRef& trait)> fcn)
-{
- for( auto scopei = m_scopes.end(); scopei-- != m_scopes.begin(); )
- {
- for( auto& trait : scopei->traits )
- {
- if( !fcn(TypeRef(Span(), trait)) )
- {
- return;
- }
- }
- }
-}
-
-void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::GenericParams& params, const AST::EnumVariant& var)
-{
- #if 0
- // We know the enum, but it might have type params, need to handle that case
- // TODO: Check for more parameters than required
- if( params.ty_params().size() > 0 )
- {
- // 1. Obtain the pattern set from the path (should it be pre-marked with _ types?)
- while( path_args.size() < params.ty_params().size() )
- path_args.push_back( TypeRef() );
- DEBUG("path_args = [" << path_args << "]");
- // 2. Create a pattern from the argument types and the format of the variant
- DEBUG("argtypes = [" << argtypes << "]");
- ::std::vector<TypeRef> item_args(params.ty_params().size());
- DEBUG("variant type = " << var.m_sub_types << "");
- for( unsigned int i = 0; i < var.m_sub_types.size(); i ++ )
- {
- var.m_sub_types[i].match_args(
- TypeRef(TypeRef::TagTuple(), Span(), argtypes),
- [&](const char *name, const TypeRef& t) {
- DEBUG("Binding " << name << " to type " << t);
- int idx = params.find_name(name);
- if( idx == -1 ) {
- throw ::std::runtime_error(FMT("Can't find generic " << name));
- }
- item_args.at(idx).merge_with( t );
- }
- );
- }
- DEBUG("item_args = [" << item_args << "]");
- // 3. Merge the two sets of arguments
- for( unsigned int i = 0; i < path_args.size(); i ++ )
- {
- path_args[i].merge_with( item_args[i] );
- }
- DEBUG("new path_args = [" << path_args << "]");
- }
- #else
- throw ::std::runtime_error("TODO: CTypeChecker::check_enum_variant");
- #endif
-}
-
-/// Named value - leaf
-void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)
-{
- DEBUG("ExprNode_NamedValue - " << node.m_path);
- const AST::Path& p = node.m_path;
- if( p.is_absolute() )
- {
- // grab bound item
- TU_MATCH_DEF(AST::PathBinding, (p.binding()), (info),
- (
- throw ::std::runtime_error( FMT("Unknown binding type on named value : "<<p) );
- ),
- (Static,
- node.get_res_type() = info.static_->type();
- ),
- (EnumVar,
- const AST::Enum& enm = *info.enum_;
- auto idx = info.idx;
- // Enum variant:
- // - Check that this variant takes no arguments
- if( ! enm.variants()[idx].m_data.is_Value() )
- throw ::std::runtime_error( "Used a non-unit variant as a raw value" );
- // - Set output type to the enum (wildcard params, not default)
- AST::Path tp = p;
- tp.nodes().pop_back();
- AST::PathNode& pn = tp.nodes().back();
- unsigned int num_params = enm.params().ty_params().size();
- if(pn.args().size() > num_params)
- throw ::std::runtime_error( FMT("Too many arguments to enum variant - " << p) );
- while(pn.args().size() < num_params)
- pn.args().push_back( TypeRef() );
- node.get_res_type() = TypeRef(Span(node.get_pos()), tp);
- )
- )
- }
- else
- {
- TypeRef& local_type = m_tc.get_local_var( p[0].name().c_str() );
- node.get_res_type().merge_with( local_type );
- DEBUG("res type = " << node.get_res_type());
- local_type = node.get_res_type();
- }
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_LetBinding& node)
-{
- DEBUG("ExprNode_LetBinding");
-
- node.get_res_type() = TypeRef(TypeRef::TagUnit(), Span(node.get_pos()));
-
- // Evaluate value
- AST::NodeVisitor::visit(node.m_value);
-
- const TypeRef& bind_type = node.m_type;
- const TypeRef& val_type = node.m_value->get_res_type();
-
- // Obtain resultant type from value
- // Compare to binding type
- // - If both concrete, but different : error
- if( bind_type.is_concrete() && val_type.is_concrete() )
- {
- if( bind_type != val_type ) {
- throw ::std::runtime_error( FMT("Type mismatch on let, expected " << bind_type << ", got " << val_type) );
- }
- }
- // - If neither concrete, merge requirements of both
- else
- {
- node.m_type.merge_with( val_type );
- node.m_value->get_res_type() = node.m_type;
- }
-
- m_tc.handle_pattern(node.m_pat, node.m_type);
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_Assign& node)
-{
- node.get_res_type() = TypeRef(TypeRef::TagUnit(), Span(node.get_pos()));
- AST::NodeVisitor::visit(node.m_slot);
- AST::NodeVisitor::visit(node.m_value);
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_Match& node)
-{
- DEBUG("ExprNode_Match");
- AST::NodeVisitor::visit(node.m_val);
-
- for( auto& arm : node.m_arms )
- {
- m_tc.start_scope();
- for( auto& pat : arm.m_patterns )
- m_tc.handle_pattern(pat, node.m_val->get_res_type());
- AST::NodeVisitor::visit(arm.m_cond);
- AST::NodeVisitor::visit(arm.m_code);
- m_tc.end_scope();
- }
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_Field& node)
-{
- DEBUG("ExprNode_Field " << node.m_name);
-
- AST::NodeVisitor::visit(node.m_obj);
-
- TypeRef* tr = &node.m_obj->get_res_type();
- DEBUG("ExprNode_Field - tr = " << *tr);
- if( tr->is_concrete() )
- {
- // Must be a structure type (what about associated items?)
- unsigned int deref_count = 0;
- while( tr->is_reference() )
- {
- tr = &tr->inner_type();
- DEBUG("ExprNode_Field - ref deref to " << *tr);
- deref_count ++;
- }
- if( !tr->is_path() )
- {
- throw ::std::runtime_error("ExprNode_Field - Type not a path");
- }
-
- // TODO Move this logic to types.cpp?
- const AST::Path& p = tr->path();
- TU_MATCH_DEF( AST::PathBinding, (p.binding()), (info),
- (
- throw ::std::runtime_error("TODO: Get field from non-structure");
- ),
- (Struct,
- const AST::PathNode& lastnode = p.nodes().back();
- AST::Struct& s = const_cast<AST::Struct&>( *info.struct_ );
- node.get_res_type().merge_with( s.get_field_type(node.m_name.c_str(), lastnode.args()) );
- )
- )
- DEBUG("deref_count = " << deref_count);
- for( unsigned i = 0; i < deref_count; i ++ )
- {
- node.m_obj = ::std::unique_ptr<AST::ExprNode>(new AST::ExprNode_Deref( ::std::move(node.m_obj) ));
- }
- }
- else
- {
- DEBUG("ExprNode_Field - Type not concrete, can't get field");
- }
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_Cast& node)
-{
- DEBUG("ExprNode_Cast " << node.m_type);
-
- AST::NodeVisitor::visit(node.m_value);
-
- node.get_res_type().merge_with( node.m_type );
-}
-
-void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node)
-{
- DEBUG("ExprNode_CallMethod " << node.m_method);
-
- AST::NodeVisitor::visit(node.m_val);
-
- for( auto& arg : node.m_args )
- {
- AST::NodeVisitor::visit(arg);
- }
-
- // Locate method
- const TypeRef& type = node.m_val->get_res_type();
- DEBUG("CallMethod - type = " << type);
-
- // Replace generic references in 'type' (copying the type) with
- // '_: Bounds' (allowing method lookup to succeed)
- TypeRef ltype = type;
- unsigned int deref_count = 0;
- ltype.resolve_args( [&](const char* name) {
- return m_tc.get_type_param(name);
- } );
-
- // Begin trying options (attempting an autoderef each time)
- const char * const name = node.m_method.name().c_str();
- AST::Function* fcnp = nullptr;
- do
- {
- // 1. Handle bounded wildcard types
- if( ltype.is_wildcard() )
- {
- throw ::std::runtime_error("TODO: _ in CallMethod");
- //if( ltype.traits().size() == 0 ) {
- // DEBUG("- Unconstrained wildcard, returning");
- // return ;
- //}
- //
- //for( const auto& t : ltype.traits() )
- //{
- // DEBUG("- Trait " << t.path());
- // AST::Trait& trait = const_cast<AST::Trait&>( t.path().binding().bound_trait() );
- // // - Find method on one of them
- // for( auto& m : trait.functions() )
- // {
- // DEBUG(" > method: " << m.name << " search: " << node.m_method.name());
- // if( m.name == node.m_method.name() )
- // {
- // DEBUG(" > Found method");
- // fcnp = &m.data;
- // break;
- // }
- // }
- // if(fcnp) break;
- //}
- //if(fcnp) break;
- }
- else
- {
- // 2. Find inherent impl
- auto oimpl = m_tc.m_crate.get_impl(AST::Path(), ltype);
- if( oimpl.is_some() )
- {
- AST::Impl& impl = oimpl.unwrap();
- // 1.1. Search impl for this method
- for(auto& i : impl.items())
- {
- if( i.name == name && i.data.is_Function() )
- {
- fcnp = &i.data.as_Function();
- break;
- }
- }
- if(fcnp) break;
- }
-
- // 2. Iterate in-scope traits
- m_tc.iterate_traits( [&](const TypeRef& trait) {
- // TODO: Check trait first, then find an impl
- auto oimpl = m_tc.m_crate.get_impl(trait.path(), ltype);
- if( oimpl.is_some() )
- {
- AST::Impl& impl = oimpl.unwrap();
- for(auto& i : impl.items())
- {
- if( i.name == name && i.data.is_Function() )
- {
- fcnp = &i.data.as_Function();
- break;
- }
- }
- }
- return fcnp == nullptr;
- });
- }
- if( fcnp )
- break;
- deref_count ++;
- } while( ltype.deref(true) );
-
- if( fcnp )
- {
- DEBUG("deref_count = " << deref_count);
- for( unsigned i = 0; i < deref_count; i ++ )
- {
- node.m_val = ::std::unique_ptr<AST::ExprNode>(new AST::ExprNode_Deref( ::std::move(node.m_val) ));
- }
-
- AST::Function& fcn = *fcnp;
- if( fcn.params().ty_params().size() != node.m_method.args().size() )
- {
- throw ::std::runtime_error("CallMethod with param count mismatch");
- }
- if( fcn.params().ty_params().size() )
- {
- throw ::std::runtime_error("TODO: CallMethod with params");
- }
- node.get_res_type().merge_with( fcn.rettype() );
- }
-}
-void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node)
-{
- DEBUG("ExprNode_CallPath - " << node.m_path);
- ::std::vector<TypeRef> argtypes;
- for( auto& arg : node.m_args )
- {
- AST::NodeVisitor::visit(arg);
- argtypes.push_back( arg->get_res_type() );
- }
-
- TU_MATCH_DEF( AST::PathBinding, (node.m_path.binding()), (info),
- (
- throw ::std::runtime_error("CallPath on non-function");
- ),
- (Function,
- const AST::Function& fcn = *info.func_;
-
- if( fcn.params().ty_params().size() > 0 )
- {
- throw ::std::runtime_error("CallPath - TODO: Params on functions");
- }
-
- DEBUG("ExprNode_CallPath - rt = " << fcn.rettype());
- node.get_res_type().merge_with( fcn.rettype() );
- ),
- (EnumVar,
- const AST::Enum& enm = *info.enum_;
- const unsigned int idx = info.idx;
-
- auto& path_node_enum = node.m_path[node.m_path.size()-2];
- m_tc.check_enum_variant(path_node_enum.args(), argtypes, enm.params(), enm.variants().at(idx));
-
- AST::Path p = node.m_path;
- p.nodes().pop_back();
- TypeRef ty(Span(), ::std::move(p) );
-
- DEBUG("ExprNode_CallPath - enum t = " << ty);
- node.get_res_type().merge_with(ty);
- )
- )
-}
-
-void Typecheck_Expr(AST::Crate& crate)
-{
- DEBUG(" >>>");
- CTypeChecker tc(crate);
- tc.handle_module(AST::Path("", {}), crate.root_module());
- DEBUG(" <<<");
-}
-
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp
deleted file mode 100644
index aa53d3bd..00000000
--- a/src/convert/typecheck_params.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
-/// Typecheck generic parameters (ensure that they match all generic bounds)
- */
-#include <main_bindings.hpp>
-#include "ast_iterate.hpp"
-#include "../ast/crate.hpp"
-#include "../common.hpp"
-#include <stdexcept>
-
-// === PROTOTYPES ===
-class CGenericParamChecker:
- public CASTIterator
-{
- int m_within_expr = 0;
- struct LocalType {
- const ::std::string name;
- const AST::GenericParams* source_params; // if nullptr, use fixed_type
- TypeRef fixed_type;
-
- LocalType():
- name("")
- {}
- LocalType(const ::std::string& n, const AST::GenericParams* tps):
- name(n), source_params(tps)
- {}
- LocalType(const ::std::string& n, TypeRef ty):
- name(n), source_params(nullptr), fixed_type( ::std::move(ty) )
- {}
-
- bool is_separator() const { return name == ""; }
- };
- // name == "" indicates edge of a scope
- ::std::vector<LocalType> m_types_stack;
-
- AST::Crate& m_crate;
-public:
- CGenericParamChecker(AST::Crate& c):
- m_crate(c)
- {
- }
-
- virtual void handle_path(AST::Path& path, CASTIterator::PathMode pm) override;
- virtual void handle_expr(AST::ExprNode& root) override;
- void start_scope() override;
- void local_type(::std::string name, TypeRef type) override;
- void end_scope() override;
- virtual void handle_params(AST::GenericParams& params) override;
-
-private:
- bool has_impl_for_param(const ::std::string name, const AST::Path& trait) const;
- bool has_impl(const TypeRef& type, const AST::Path& trait) const;
- void check_generic_params(const AST::GenericParams& info, ::std::vector<TypeRef>& types, TypeRef self_type, bool allow_infer = false);
-
- const LocalType* find_type_by_name(const ::std::string& name) const;
-};
-
-class CNodeVisitor:
- public AST::NodeVisitorDef
-{
- CGenericParamChecker& m_pc;
-public:
- CNodeVisitor(CGenericParamChecker& pc):
- m_pc(pc)
- {}
-};
-
-// === CODE ===
-bool CGenericParamChecker::has_impl_for_param(const ::std::string name, const AST::Path& trait) const
-{
- TRACE_FUNCTION_F("name = " << name << ", trait = " << trait);
-
- if( m_crate.is_trait_implicit(trait) )
- return true;
-
- const AST::GenericParams* tps = nullptr;
- // Locate params set that contains the passed name
- for( const auto lt : m_types_stack )
- {
- if( lt.name == name )
- {
- if( lt.source_params != nullptr ) {
- tps = lt.source_params;
- }
- else {
- DEBUG("Type name '" << name << "' isn't a param");
- return has_impl(lt.fixed_type, trait);
- }
- //break ;
- }
- }
-
- if( !tps )
- {
- throw ::std::runtime_error(FMT("Param '"<<name<<"' isn't in scope"));
- }
-
- // Search bound list for the passed trait
- for( const auto& bound : tps->bounds() )
- {
- DEBUG("bound = " << bound);
- TU_IFLET( AST::GenericBound, bound, IsTrait, ent,
- if( ent.type.is_type_param() && ent.type.type_param() == name )
- {
- DEBUG("bound.type() {" << ent.trait << "} == trait {" << trait << "}");
- if( ent.trait == trait )
- return true;
- }
- )
- }
-
- // TODO: Search for generic ("impl<T: Trait2> Trait1 for T") that fits bounds
-
- DEBUG("No match in generics, returning failure");
- return false;
-}
-
-bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) const
-{
- TRACE_FUNCTION_F("type = " << type << ", trait = " << trait);
- if( type.is_type_param() )
- {
- // TODO: Search current scope (requires access to CGenericParamChecker) for this type,
- // and search the bounds for this trait
- // - Also accept bounded generic impls (somehow)
- {
- return true;
- }
- }
- else
- {
- // Search all known impls of this trait (TODO: keep a list at the crate level) for a match to this type
- if( m_crate.find_impl(trait, type, nullptr, nullptr) == false ) {
- DEBUG("- Nope");
- return false;
- }
-
- return true;
- }
- return false;
-}
-
-/// Check that the passed set of parameters match the requiremens for a generic item
-///
-/// \param info Generic item information (param names and bounds)
-/// \param types Type parameters being passed to the generic item
-/// \param allow_infer Allow inferrence (mutates \a types with conditions from \a info)
-void CGenericParamChecker::check_generic_params(const AST::GenericParams& info, ::std::vector<TypeRef>& types, TypeRef self_type, bool allow_infer)
-{
- TRACE_FUNCTION_F("info = " << info << ", types = {" << types << "}");
- // TODO: Need to correctly handle lifetime params here, they should be in a different list
- const auto& params = info.ty_params();
-
- if( types.size() > params.size() )
- {
- throw ::std::runtime_error(FMT("Too many generic params ("<<types.size()<<" passed, expecting "<< params.size()<<")"));
- }
- else if( types.size() < params.size() )
- {
- // Fill with defaults
- while( types.size() < params.size() && params[types.size()].get_default() != TypeRef() )
- types.push_back( params[types.size()].get_default() );
-
- // And (optionally) infer
- if( allow_infer )
- {
- while( types.size() < params.size() )
- {
- types.push_back( TypeRef() );
- }
- }
- else if( types.size() < params.size() )
- {
- throw ::std::runtime_error(FMT("Too few generic params, ("<<types.size()<<" passed, expecting "<<params.size()<<")"));
- }
- }
- else
- {
- // Counts are good, time to validate types
- }
-
- for( unsigned int i = 0; i < types.size(); i ++ )
- {
- auto& type = types[i];
- auto& param = params[i].name();
- DEBUG("#" << i << " - checking type " << type << " against " << param);
- if( type.is_wildcard() )
- {
- // Type is a wildcard - this can match any condition
- if( allow_infer )
- {
- // Apply conditions for this param to the type
- // TODO: Requires supporting type "ranges" on the TypeRef
- // Should also check for conflicting requirements (negative bounds?)
- DEBUG("TODO: Type inferrence");
- }
- else
- {
- // This is an error, as inferrence is not currently allowed
- throw ::std::runtime_error(FMT("Type of '_' present for param " << param << " when inferrence isn't allowed"));
- }
- }
- else
- {
- // Not a wildcard!
- // Check that the type fits the bounds applied to it
- TypeRef param_type(TypeRef::TagArg(), param);
- }
- }
-
- for( const auto& bound : info.bounds() )
- {
- TU_IFLET(AST::GenericBound, bound, IsTrait, ent,
- auto ra_fcn = [&](const char *a){
- if( strcmp(a, "Self") == 0 ) {
- if( ! self_type.is_valid() )
- throw CompileError::Generic("Unexpected use of 'Self' in bounds");
- return self_type;
- }
- return types.at(info.find_name(a));
- };
- auto bound_type = ent.type;
- bound_type.resolve_args(ra_fcn);
-
- auto trait = ent.trait;
- trait.resolve_args(ra_fcn);
-
- // Check if 'type' impls 'trait'
- if( !has_impl(bound_type, trait) )
- {
- throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<bound_type));
- }
- )
- }
-}
-
-void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode pm)
-{
- TRACE_FUNCTION_F("path = " << path);
- AST::PathNode& last_node = path[path.size()-1];
-
- auto comm = [&](const AST::GenericParams& params) {
- auto lt = find_type_by_name("Self");
- TypeRef self_type; // =TypeRef(TypeRef::TagPath(), path)
- if( lt )
- self_type = lt->fixed_type;
- check_generic_params(params, last_node.args(), self_type, (m_within_expr > 0));
- };
-
- TU_MATCH( AST::PathBinding, (path.binding()), (info),
- (Unbound,
- throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) );
- ),
- (Module,
- DEBUG("WTF - Module path, isn't this invalid at this stage?");
- ),
- (Trait,
- comm( info.trait_->params() );
- ),
- (Struct,
- comm( info.struct_->params() );
- ),
- (Enum,
- comm( info.enum_->params() );
- ),
- (TypeAlias,
- comm( info.alias_->params() );
- ),
- (Function,
- check_generic_params(info.func_->params(), last_node.args(), TypeRef(TypeRef::TagInvalid(), Span()), (m_within_expr > 0));
- ),
-
- (EnumVar,
- throw ::std::runtime_error("TODO: handle_path EnumVar");
- ),
- (Static,
- throw ::std::runtime_error("TODO: handle_path Static");
- ),
- (StructMethod,
- throw ::std::runtime_error("TODO: handle_path StructMethod");
- ),
- (TraitMethod,
- throw ::std::runtime_error("TODO: handle_path TraitMethod");
- ),
- (TypeParameter,
- throw ::std::runtime_error("TODO: handle_path TypeParameter");
- ),
- (Variable,
- throw ::std::runtime_error("TODO: handle_path Variable");
- )
- )
-}
-
-void CGenericParamChecker::handle_expr(AST::ExprNode& root)
-{
- m_within_expr += 1;
- // Do nothing (this iterator shouldn't recurse into expressions)
- CNodeVisitor nv(*this);
- root.visit(nv);
- m_within_expr -= 1;
-}
-
-void CGenericParamChecker::start_scope()
-{
- m_types_stack.push_back( LocalType() );
-}
-void CGenericParamChecker::local_type(::std::string name, TypeRef type)
-{
- DEBUG("name = " << name << ", type = " << type);
- m_types_stack.push_back( LocalType(::std::move(name), ::std::move(type)) );
-}
-void CGenericParamChecker::end_scope()
-{
- assert( m_types_stack.size() > 0 );
- while( !m_types_stack.back().is_separator() )
- m_types_stack.pop_back();
- // pop the separator
- m_types_stack.pop_back();
-}
-void CGenericParamChecker::handle_params(AST::GenericParams& params)
-{
- DEBUG("params = " << params);
- for( const auto& p : params.ty_params())
- m_types_stack.push_back( LocalType(p.name(), &params) );
-}
-
-const CGenericParamChecker::LocalType* CGenericParamChecker::find_type_by_name(const ::std::string& name) const
-{
- for( unsigned int i = m_types_stack.size(); i --; )
- {
- if( m_types_stack[i].name == name )
- return &m_types_stack[i];
- }
- return nullptr;
-}
-
-/// Typecheck generic parameters (ensure that they match all generic bounds)
-void Typecheck_GenericParams(AST::Crate& crate)
-{
- DEBUG(" >>> ");
- CGenericParamChecker chk(crate);
- chk.handle_module(AST::Path("", {}), crate.root_module());
- DEBUG(" <<< ");
-}
-
diff --git a/src/main.cpp b/src/main.cpp
index b6dd9254..963491d5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -69,9 +69,6 @@ void CompilePhaseV(const char *name, Fcn f) {
/// main!
int main(int argc, char *argv[])
{
- AST_InitProvidedModule();
-
-
ProgramParams params(argc, argv);
// Set up cfg values
@@ -104,11 +101,6 @@ int main(int argc, char *argv[])
CompilePhaseV("Expand", [&]() {
Expand(crate);
});
-
- // Run a quick post-parse pass
- CompilePhaseV("PostParse", [&]() {
- crate.index_impls();
- });
// XXX: Dump crate before resolve
CompilePhaseV("Temp output - Parsed", [&]() {