summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/ast.hpp3
-rw-r--r--src/coretypes.hpp2
-rw-r--r--src/dump_as_rust.cpp1
-rw-r--r--src/hir/from_ast.cpp3
-rw-r--r--src/macros.cpp14
-rw-r--r--src/parse/types.cpp4
-rw-r--r--src/resolve/absolute.cpp238
-rw-r--r--src/resolve/index.cpp3
-rw-r--r--src/resolve/use.cpp12
-rw-r--r--src/types.cpp3
10 files changed, 254 insertions, 29 deletions
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index a5d4ec8c..06ff857e 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -554,7 +554,8 @@ public:
char m_index_populated = 0; // 0 = no, 1 = partial, 2 = complete
// TODO: Add "namespace" list (separate to types)
struct IndexEnt {
- bool is_pub;
+ bool is_pub; // Used as part of glob import checking
+ bool is_import; // Set if this item has a path that isn't `mod->path() + name`
::AST::Path path;
};
::std::unordered_map< ::std::string, IndexEnt > m_namespace_items;
diff --git a/src/coretypes.hpp b/src/coretypes.hpp
index 1d3cba67..bdf161e1 100644
--- a/src/coretypes.hpp
+++ b/src/coretypes.hpp
@@ -9,7 +9,7 @@ enum eCoreType
CORETYPE_INVAL,
CORETYPE_ANY,
CORETYPE_BOOL,
- CORETYPE_CHAR,
+ CORETYPE_CHAR, CORETYPE_STR,
CORETYPE_UINT, CORETYPE_INT,
CORETYPE_U8, CORETYPE_I8,
CORETYPE_U16, CORETYPE_I16,
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index 361bd245..4e233663 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -327,6 +327,7 @@ public:
{
case CORETYPE_INVAL: break;
case CORETYPE_BOOL:
+ case CORETYPE_STR:
break;
case CORETYPE_CHAR:
m_os << "'\\u{" << ::std::hex << n.m_value << ::std::dec << "}'";
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index d8e21496..3acb64ac 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -424,7 +424,8 @@
switch(e.core_type)
{
case CORETYPE_BOOL: return ::HIR::TypeRef( ::HIR::CoreType::Bool );
- case CORETYPE_CHAR: return ::HIR::TypeRef( ::HIR::CoreType::Char );
+ case CORETYPE_CHAR: return ::HIR::TypeRef( ::HIR::CoreType::Str );
+ case CORETYPE_STR : return ::HIR::TypeRef( ::HIR::CoreType::Char );
case CORETYPE_F32: return ::HIR::TypeRef( ::HIR::CoreType::F32 );
case CORETYPE_F64: return ::HIR::TypeRef( ::HIR::CoreType::F64 );
diff --git a/src/macros.cpp b/src/macros.cpp
index 89fcbe86..12f6df05 100644
--- a/src/macros.cpp
+++ b/src/macros.cpp
@@ -107,6 +107,8 @@ class MacroExpander:
public:
private:
+ const ::std::string m_macro_name;
+
const ::std::string m_crate_name;
const ::std::vector<MacroRuleEnt>& m_root_contents;
const ParameterMappings m_mappings;
@@ -129,6 +131,7 @@ private:
public:
MacroExpander(const MacroExpander& x):
+ m_macro_name( x.m_macro_name ),
m_crate_name(x.m_crate_name),
m_root_contents(x.m_root_contents),
m_mappings(x.m_mappings),
@@ -137,10 +140,11 @@ public:
{
prep_counts();
}
- MacroExpander(const ::std::vector<MacroRuleEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
- m_crate_name(crate_name),
+ MacroExpander(::std::string macro_name, const ::std::vector<MacroRuleEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
+ m_macro_name( mv$(macro_name) ),
+ m_crate_name( mv$(crate_name) ),
m_root_contents(contents),
- m_mappings(mappings),
+ m_mappings( mv$(mappings) ),
m_offsets({ {0,0,0} }),
m_cur_ents(&m_root_contents)
{
@@ -383,7 +387,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
}
DEBUG("TODO: Obtain crate name correctly");
- TokenStream* ret_ptr = new MacroExpander(rule.m_contents, bound_tts, "");
+ TokenStream* ret_ptr = new MacroExpander(name, rule.m_contents, bound_tts, "");
// HACK! Disable nested macro expansion
//ret_ptr->parse_state().no_expand_macros = true;
@@ -440,7 +444,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay
Position MacroExpander::getPosition() const
{
- return Position(FMT("Macro:" << ""), 0, m_offsets[0].read_pos);
+ return Position(FMT("Macro:" << m_macro_name << ":"), 0, m_offsets[0].read_pos);
}
Token MacroExpander::realGetToken()
{
diff --git a/src/parse/types.cpp b/src/parse/types.cpp
index 01acf074..fe23b509 100644
--- a/src/parse/types.cpp
+++ b/src/parse/types.cpp
@@ -86,10 +86,6 @@ TypeRef Parse_Type_Int(TokenStream& lex)
{
return TypeRef(TypeRef::TagPrimitive(), Span(tok.get_pos()), ct);
}
- if( tok.str() == "str" )
- {
- return TypeRef(TypeRef::TagPath(), Span(tok.get_pos()), AST::Path("", { AST::PathNode("#",{}), AST::PathNode("str",{}) }));
- }
lex.putback(tok);
return Parse_Type_Path(lex, {});
// - Fall through to path handling
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 5685ae82..a41ef04a 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -197,7 +197,7 @@ struct Context
}
return rv;
}
- bool lookup_in_mod(const ::AST::Module& mod, const ::std::string& name, LookupMode mode, ::AST::Path& path) const {
+ static bool lookup_in_mod(const ::AST::Module& mod, const ::std::string& name, LookupMode mode, ::AST::Path& path) {
switch(mode)
{
case LookupMode::Namespace:
@@ -386,9 +386,211 @@ void Resolve_Absolute_PathNodes(/*const*/ Context& context, const Span& sp, ::st
}
}
}
+
+void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path)
+{
+ const auto& ufcs = path.m_class.as_UFCS();
+
+ if( ufcs.nodes.size() > 1 )
+ {
+ // More than one node, break into inner UFCS
+ TODO(sp, "Split multi-node UFCS - " << path);
+ }
+ if( ufcs.nodes.size() == 0 ) {
+
+ if( mode == Context::LookupMode::Type && ! ufcs.trait ) {
+ return ;
+ }
+
+ BUG(sp, "UFCS with no nodes encountered - " << path);
+ }
+ const auto& node = ufcs.nodes.at(0);
+
+ if( ufcs.trait && ufcs.trait->is_valid() )
+ {
+ // Trait is specified, definitely a trait item
+ // - Must resolve here
+ if( ! ufcs.trait->binding().is_Trait() ) {
+ ERROR(sp, E0000, "UFCS trait was not a trait - " << *ufcs.trait);
+ }
+ const auto& tr = *ufcs.trait->binding().as_Trait().trait_;
+
+ switch(mode)
+ {
+ case Context::LookupMode::Pattern:
+ ERROR(sp, E0000, "Invalid use of UFCS in pattern");
+ break;
+ case Context::LookupMode::Namespace:
+ case Context::LookupMode::Type:
+ for( const auto& item : tr.items() )
+ {
+ if( item.name != node.name() ) {
+ break;
+ }
+ TU_MATCH_DEF(::AST::Item, (item.data), (e),
+ (
+ // TODO: Error
+ ),
+ (Type,
+ // Resolve to asociated type
+ )
+ )
+ }
+ break;
+ case Context::LookupMode::Constant:
+ case Context::LookupMode::Variable:
+ for( const auto& item : tr.items() )
+ {
+ if( item.name != node.name() ) {
+ break;
+ }
+ TU_MATCH_DEF(::AST::Item, (item.data), (e),
+ (
+ // TODO: Error
+ ),
+ (Static,
+ // Resolve to asociated type
+ )
+ )
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Trait is unknown or inherent, search for items on the type (if known) otherwise leave it until type resolution
+ // - Methods can't be known until typeck (after the impl map is created)
+ }
+}
+void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path)
+{
+ const auto& path_abs = path.m_class.as_Absolute();
+
+ if( path_abs.crate != "" ) {
+ // TODO: Handle items from other crates (back-converting HIR paths)
+ TODO(sp, "Handle binding to items from extern crates");
+ }
+
+ const ::AST::Module* mod = &context.m_crate.m_root_module;
+ for(unsigned int i = 0; i < path_abs.nodes.size() - 1; i ++ )
+ {
+ const auto& n = path_abs.nodes[i];
+
+ //::AST::Path tmp;
+ //if( ! Context::lookup_in_mod(*mod, e.name(), Context::LookupMode::Namespace, tmp) ) {
+ // ERROR(sp, E0000, "Couldn't find path component '" << e.name() << "' of " << path);
+ //}
+
+
+ if( n.name()[0] == '#' ) {
+ if( n.args().size() > 0 ) {
+ ERROR(sp, E0000, "Type parameters were not expected here");
+ }
+
+ if( n.name() == "#" ) {
+ TODO(sp, "magic module");
+ }
+
+ char c;
+ unsigned int idx;
+ ::std::stringstream ss( n.name() );
+ ss >> c;
+ ss >> idx;
+ assert( idx < mod->anon_mods().size() );
+ mod = mod->anon_mods()[idx];
+ }
+ else
+ {
+ auto it = mod->m_namespace_items.find( n.name() );
+ if( it == mod->m_namespace_items.end() ) {
+ ERROR(sp, E0000, "Couldn't find path component '" << n.name() << "' of " << path);
+ }
+ const auto& name_ref = it->second;
+
+ TU_MATCH_DEF(::AST::PathBinding, (name_ref.path.binding()), (e),
+ (
+ ERROR(sp, E0000, "Encountered non-namespace item '" << n.name() << "' ("<<name_ref.path<<") in path " << path);
+ ),
+ (Trait,
+ auto trait_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ trait_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ ),
+ (Enum,
+ if( name_ref.is_import ) {
+ TODO(sp, "Replace path component with new path - " << path << "[.."<<i<<"] with " << name_ref.path);
+ }
+ else {
+ const auto& last_node = path_abs.nodes.back();
+ for( const auto& var : e.enum_->variants() ) {
+ if( var.m_name == last_node.name() ) {
+
+ if( i != path_abs.nodes.size() - 2 ) {
+ ERROR(sp, E0000, "Unexpected enum in path " << path);
+ }
+ // NOTE: Type parameters for enums go after the _variant_
+ if( n.args().size() ) {
+ ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
+ }
+
+ path.bind_enum_var(*e.enum_, var.m_name);
+ return;
+ }
+ }
+
+ auto type_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ type_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ }
+ ),
+ (Struct,
+ auto type_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ type_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ ),
+ (Module,
+ if( name_ref.is_import ) {
+ TODO(sp, "Replace path component with new path - " << path << "[.."<<i<<"] with " << name_ref.path);
+ }
+ else {
+ mod = e.module_;
+ }
+ )
+ )
+ }
+ }
+
+ // Set binding to binding of node in last module
+ ::AST::Path tmp;
+ if( ! Context::lookup_in_mod(*mod, path_abs.nodes.back().name(), mode, tmp) ) {
+ ERROR(sp, E0000, "Couldn't find path component '" << path_abs.nodes.back().name() << "' of " << path);
+ }
+ assert( ! tmp.binding().is_Unbound() );
+
+ path.bind( tmp.binding().clone() );
+}
+
void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::LookupMode mode, ::AST::Path& path)
{
- DEBUG("mode = " << mode << ", path = " << path);
+ TRACE_FUNCTION_F("mode = " << mode << ", path = " << path);
TU_MATCH(::AST::Path::Class, (path.m_class), (e),
(Invalid,
@@ -428,12 +630,12 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
else {
// Look up value
auto p = context.lookup(sp, e.nodes[0].name(), mode);
- DEBUG("Found val - " << p);
+ DEBUG("Found val - " << p << " for " << path);
path = mv$(p);
}
if( !path.is_trivial() )
- Resolve_Absolute_PathNodes(context, Span(), path.nodes());
+ Resolve_Absolute_PathNodes(context, sp, path.nodes());
),
(Self,
DEBUG("- Self");
@@ -458,27 +660,29 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
// TODO: Resolve to the actual item?
if( !path.is_trivial() )
- Resolve_Absolute_PathNodes(context, Span(), np_nodes);
+ Resolve_Absolute_PathNodes(context, sp, np_nodes);
path = mv$(np);
),
(Absolute,
DEBUG("- Absolute");
// Nothing to do (TODO: Bind?)
- Resolve_Absolute_PathNodes(context, Span(), e.nodes);
+ Resolve_Absolute_PathNodes(context, sp, e.nodes);
),
(UFCS,
DEBUG("- UFCS");
Resolve_Absolute_Type(context, *e.type);
if( e.trait ) {
- Resolve_Absolute_Path(context, Span(), Context::LookupMode::Type, *e.trait);
+ Resolve_Absolute_Path(context, sp, Context::LookupMode::Type, *e.trait);
}
- Resolve_Absolute_PathNodes(context, Span(), e.nodes);
+ Resolve_Absolute_PathNodes(context, sp, e.nodes);
)
)
- #if 0
+ // TODO: Should this be deferred until the HIR?
+ // - Doing it here so the HIR lowering has a bit more information
+ // - Also handles splitting "absolute" paths into UFCS
TU_MATCH_DEF(::AST::Path::Class, (path.m_class), (e),
(
BUG(sp, "Path wasn't absolutised correctly");
@@ -487,20 +691,17 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
// TODO: Ensure that local paths are bound to the variable/type index
),
(Absolute,
- if( e.crate != "" ) {
- // TODO: Handle items from other crates (back-converting HIR paths)
- }
- TODO(sp, "Bind absolute paths to relevant items (and expand)");
+ Resolve_Absolute_Path_BindAbsolute(context, sp, mode, path);
),
(UFCS,
- // TODO: Resolve UFCS to item class (if possible)
+ Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
)
)
- #endif
}
void Resolve_Absolute_Type(Context& context, TypeRef& type)
{
+ TRACE_FUNCTION_F("type = " << type);
const auto& sp = type.span();
TU_MATCH(TypeData, (type.m_data), (e),
(None,
@@ -544,6 +745,13 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type)
),
(Path,
Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, e.path);
+ TU_IFLET(::AST::Path::Class, e.path.m_class, UFCS, ufcs,
+ if( ufcs.nodes.size() == 0 && ! ufcs.trait ) {
+ type = mv$(*ufcs.type);
+ return ;
+ }
+ assert( ufcs.nodes.size() == 1);
+ )
),
(TraitObject,
//context.push_lifetimes( e.hrls );
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index b98c3b8e..0155455d 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -42,7 +42,8 @@ void _add_item(AST::Module& mod, IndexName location, const ::std::string& name,
DEBUG("Add " << location << " item '" << name << "': " << ir);
auto& list = get_mod_index(mod, location);
- if( false == list.insert(::std::make_pair(name, ::AST::Module::IndexEnt { is_pub, mv$(ir) } )).second )
+ bool was_import = (ir != mod.path() + name);
+ if( false == list.insert(::std::make_pair(name, ::AST::Module::IndexEnt { is_pub, was_import, mv$(ir) } )).second )
{
if( error_on_collision )
{
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 2d86be13..2ebdc058 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -35,7 +35,17 @@ void Resolve_Use(::AST::Crate& crate)
return base_path + path;
),
(Self,
- return base_path + path;
+ // EVIL HACK: If the current module is an anon module, refer to the parent
+ if( base_path.nodes().back().name()[0] == '#' ) {
+ AST::Path np("", {});
+ for( unsigned int i = 0; i < base_path.nodes().size() - 1; i ++ )
+ np.nodes().push_back( base_path.nodes()[i] );
+ np += path;
+ return np;
+ }
+ else {
+ return base_path + path;
+ }
),
(Super,
assert(e.count >= 1);
diff --git a/src/types.cpp b/src/types.cpp
index ffa4db42..a75506d1 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -16,6 +16,7 @@ static const struct {
const char* name;
enum eCoreType type;
} CORETYPES[] = {
+ // NOTE: Sorted
{"bool", CORETYPE_BOOL},
{"char", CORETYPE_CHAR},
{"f32", CORETYPE_F32},
@@ -26,6 +27,7 @@ static const struct {
{"i8", CORETYPE_I8},
{"int", CORETYPE_INT},
{"isize", CORETYPE_INT},
+ {"str", CORETYPE_STR},
{"u16", CORETYPE_U16},
{"u32", CORETYPE_U32},
{"u64", CORETYPE_U64},
@@ -52,6 +54,7 @@ const char* coretype_name(const eCoreType ct ) {
case CORETYPE_INVAL:return "-";
case CORETYPE_ANY: return "_";
case CORETYPE_CHAR: return "char";
+ case CORETYPE_STR: return "str";
case CORETYPE_BOOL: return "bool";
case CORETYPE_UINT: return "usize";
case CORETYPE_INT: return "isize";