summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-02 14:51:21 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-02 14:51:21 +0800
commit52c363340a4f2ee589d2e6753f1c685ef7b907f5 (patch)
tree758c04ec4aada28255cb5cd7865ad27025f29e7f
parent563520207ad1a6c0deff41b881ac5d0168d3439e (diff)
downloadmrust-52c363340a4f2ee589d2e6753f1c685ef7b907f5.tar.gz
All - Hack in start of macro hygine - requires rework so is disabled
-rw-r--r--Makefile2
-rw-r--r--src/ast/dump.cpp34
-rw-r--r--src/ast/expr.cpp29
-rw-r--r--src/ast/path.cpp2
-rw-r--r--src/ast/path.hpp11
-rw-r--r--src/ast/pattern.cpp28
-rw-r--r--src/ast/pattern.hpp46
-rw-r--r--src/expand/derive.cpp6
-rw-r--r--src/expand/format_args.cpp20
-rw-r--r--src/expand/mod.cpp4
-rw-r--r--src/hir/from_ast.cpp59
-rw-r--r--src/ident.cpp60
-rw-r--r--src/include/ident.hpp78
-rw-r--r--src/include/rc_string.hpp1
-rw-r--r--src/macro_rules/parse.cpp9
-rw-r--r--src/parse/expr.cpp6
-rw-r--r--src/parse/lex.cpp25
-rw-r--r--src/parse/lex.hpp4
-rw-r--r--src/parse/paths.cpp17
-rw-r--r--src/parse/pattern.cpp78
-rw-r--r--src/parse/root.cpp92
-rw-r--r--src/parse/token.cpp25
-rw-r--r--src/parse/token.hpp18
-rw-r--r--src/resolve/absolute.cpp54
24 files changed, 489 insertions, 219 deletions
diff --git a/Makefile b/Makefile
index 014074df..2217ae0f 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@ OBJDIR = .obj/
BIN := bin/mrustc$(EXESUF)
OBJ := main.o serialise.o
-OBJ += span.o rc_string.o debug.o
+OBJ += span.o rc_string.o debug.o ident.o
OBJ += ast/ast.o
OBJ += ast/types.o ast/crate.o ast/path.o ast/expr.o ast/pattern.o
OBJ += ast/dump.o
diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp
index fa31401a..33ef5911 100644
--- a/src/ast/dump.cpp
+++ b/src/ast/dump.cpp
@@ -922,20 +922,38 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable)
),
(Slice,
m_os << "[";
+ m_os << v.sub_pats;
+ m_os << "]";
+ ),
+ (SplitSlice,
+ m_os << "[";
bool needs_comma = false;
if(v.leading.size()) {
m_os << v.leading;
- needs_comma = true;
+ m_os << ", ";
}
- if(v.extra_bind.size() > 0) {
- if( needs_comma ) {
- m_os << ", ";
+
+ if(v.extra_bind.is_valid())
+ {
+ const auto& b = v.extra_bind;
+ if( b.m_mutable )
+ m_os << "mut ";
+ switch(b.m_type)
+ {
+ case ::AST::PatternBinding::Type::MOVE:
+ break;
+ case ::AST::PatternBinding::Type::REF:
+ m_os << "ref ";
+ break;
+ case ::AST::PatternBinding::Type::MUTREF:
+ m_os << "ref mut ";
+ break;
}
- if(v.extra_bind != "_")
- m_os << v.extra_bind;
- m_os << "..";
- needs_comma = true;
+ m_os << b.m_name << "/*"<<b.m_slot<<"*/";
}
+ m_os << "..";
+ needs_comma = true;
+
if(v.trailing.size()) {
if( needs_comma ) {
m_os << ", ";
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index bfe3ad98..d856029a 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -55,12 +55,8 @@ Expr Expr::clone() const
::std::ostream& operator<<(::std::ostream& os, const ExprNode& node)
{
- //if( static_cast<const void*>(&node) != nullptr ) {
- node.print(os);
- //}
- //else {
- // os << "/* NULLPTR */";
- //}
+ assert( static_cast<const void*>(&node) != nullptr );
+ node.print(os);
return os;
}
ExprNode::~ExprNode() {
@@ -332,6 +328,27 @@ NODE(ExprNode_TypeAnnotation, {
})
NODE(ExprNode_BinOp, {
+ if( m_type == RANGE_INC ) {
+ os << "(";
+ if( m_left ) {
+ os << *m_left << " ";
+ }
+ os << "... " << *m_right;
+ os << ")";
+ return ;
+ }
+ if( m_type == RANGE ) {
+ os << "(";
+ if( m_left ) {
+ os << *m_left;
+ }
+ os << "..";
+ if( m_right ) {
+ os << " " << *m_right;
+ }
+ os << ")";
+ return ;
+ }
os << "(" << *m_left << " ";
switch(m_type)
{
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index d1781e1f..25c0c208 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -162,7 +162,7 @@ AST::Path::Path(const Path& x):
m_class = Class::make_Local({ent.name});
),
(Relative,
- m_class = Class::make_Relative({ent.nodes});
+ m_class = Class::make_Relative({ent.hygine, ent.nodes});
),
(Self,
m_class = Class::make_Self({ent.nodes});
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index c47f37ca..5c2481a0 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -13,6 +13,7 @@
#include <tagged_union.hpp>
#include <string>
#include "../include/span.hpp"
+#include "../include/ident.hpp"
class TypeRef;
@@ -161,6 +162,7 @@ public:
::std::string name;
} ),
(Relative, struct { // General relative
+ Ident::Hygine hygine; // Taken from the first ident
::std::vector<PathNode> nodes;
} ),
(Self, struct { // Module-relative
@@ -224,8 +226,8 @@ public:
// RELATIVE
struct TagRelative {};
- Path(TagRelative, ::std::vector<PathNode> nodes):
- m_class( Class::make_Relative({ mv$(nodes) }) )
+ Path(TagRelative, Ident::Hygine hygine, ::std::vector<PathNode> nodes):
+ m_class( Class::make_Relative({ mv$(hygine), mv$(nodes) }) )
{}
// SELF
struct TagSelf {};
@@ -266,8 +268,9 @@ public:
Path& operator+=(const Path& x);
void append(PathNode node) {
- if( m_class.is_Invalid() )
- m_class = Class::make_Relative({});
+ assert( !m_class.is_Invalid() );
+ //if( m_class.is_Invalid() )
+ // m_class = Class::make_Relative({});
nodes().push_back( mv$(node) );
m_binding = PathBinding();
}
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp
index df1d0caf..3128fd91 100644
--- a/src/ast/pattern.cpp
+++ b/src/ast/pattern.cpp
@@ -113,20 +113,25 @@ namespace AST {
),
(Slice,
os << "[";
+ os << ent.sub_pats;
+ os << "]";
+ ),
+ (SplitSlice,
+ os << "[";
bool needs_comma = false;
if(ent.leading.size()) {
os << ent.leading;
needs_comma = true;
}
- if(ent.extra_bind.size() > 0) {
- if( needs_comma ) {
- os << ", ";
- }
- if(ent.extra_bind != "_")
- os << ent.extra_bind;
- os << "..";
- needs_comma = true;
+
+ if( needs_comma ) {
+ os << ", ";
}
+ if( ent.extra_bind.is_valid() )
+ os << ent.extra_bind.m_name;
+ os << "..";
+ needs_comma = true;
+
if(ent.trailing.size()) {
if( needs_comma ) {
os << ", ";
@@ -161,7 +166,7 @@ AST::Pattern AST::Pattern::clone() const
{
AST::Pattern rv;
rv.m_span = m_span;
- rv.m_binding = m_binding;
+ rv.m_binding = PatternBinding(m_binding);
struct H {
static ::std::unique_ptr<Pattern> clone_sp(const ::std::unique_ptr<Pattern>& p) {
@@ -226,7 +231,10 @@ AST::Pattern AST::Pattern::clone() const
rv.m_data = Data::make_Struct({ ::AST::Path(e.path), mv$(sps) });
),
(Slice,
- rv.m_data = Data::make_Slice({ H::clone_list(e.leading), e.extra_bind, H::clone_list(e.trailing) });
+ rv.m_data = Data::make_Slice({ H::clone_list(e.sub_pats) });
+ ),
+ (SplitSlice,
+ rv.m_data = Data::make_SplitSlice({ H::clone_list(e.leading), e.extra_bind, H::clone_list(e.trailing) });
)
)
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 3a1dacc5..0dff4071 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -1,3 +1,10 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * ast/pattern.hpp
+ * - AST Pattern representation
+ */
#ifndef _AST__PATTERN_HPP_INCLUDED_
#define _AST__PATTERN_HPP_INCLUDED_
@@ -6,6 +13,7 @@
#include <memory>
#include <string>
#include <tagged_union.hpp>
+#include <ident.hpp>
namespace AST {
@@ -21,25 +29,29 @@ public:
REF,
MUTREF,
};
- ::std::string m_name;
+ Ident m_name;
Type m_type;
bool m_mutable;
unsigned int m_slot;
PatternBinding():
- m_name(""),
+ m_name({0,{}}, ""),
m_type(Type::MOVE),
m_mutable(false),
m_slot( ~0u )
{}
- PatternBinding(::std::string name, Type ty, bool ismut):
- m_name(name),
+ PatternBinding(Ident name, Type ty, bool ismut):
+ m_name(::std::move(name)),
m_type(ty),
m_mutable(ismut),
m_slot( ~0u )
{}
- bool is_valid() const { return m_name != ""; }
+ PatternBinding(PatternBinding&& x) = default;
+ PatternBinding(const PatternBinding& x) = default;
+ PatternBinding& operator=(PatternBinding&& x) = default;
+
+ bool is_valid() const { return m_name.name != ""; }
};
class Pattern:
@@ -68,7 +80,7 @@ public:
};
TAGGED_UNION(Data, Any,
- (MaybeBind, struct { ::std::string name; } ),
+ (MaybeBind, struct { Ident name; } ),
(Macro, struct { unique_ptr<::AST::MacroInvocation> inv; } ),
(Any, struct { } ),
(Box, struct { unique_ptr<Pattern> sub; } ),
@@ -77,7 +89,8 @@ public:
(Tuple, TuplePat ),
(StructTuple, struct { Path path; TuplePat tup_pat; } ),
(Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; bool is_exhaustive; } ),
- (Slice, struct { ::std::vector<Pattern> leading; ::std::string extra_bind; ::std::vector<Pattern> trailing; } )
+ (Slice, struct { ::std::vector<Pattern> sub_pats; }),
+ (SplitSlice, struct { ::std::vector<Pattern> leading; PatternBinding extra_bind; ::std::vector<Pattern> trailing; } )
);
private:
Span m_span;
@@ -98,19 +111,19 @@ public:
{};
struct TagMaybeBind {};
- Pattern(TagMaybeBind, ::std::string name):
+ Pattern(TagMaybeBind, Ident name):
m_binding(),
- m_data( Data::make_MaybeBind({name}) )
+ m_data( Data::make_MaybeBind({ mv$(name) }) )
{}
struct TagMacro {};
Pattern(TagMacro, unique_ptr<::AST::MacroInvocation> inv):
- m_data( Data::make_Macro({mv$(inv)}) )
+ m_data( Data::make_Macro({ mv$(inv) }) )
{}
struct TagBind {};
- Pattern(TagBind, ::std::string name, PatternBinding::Type ty = PatternBinding::Type::MOVE, bool is_mut=false):
- m_binding( PatternBinding(name, ty, is_mut) )
+ Pattern(TagBind, Ident name, PatternBinding::Type ty = PatternBinding::Type::MOVE, bool is_mut=false):
+ m_binding( PatternBinding(mv$(name), ty, is_mut) )
{}
struct TagBox {};
@@ -152,15 +165,10 @@ public:
Pattern(TagStruct, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns, bool is_exhaustive):
m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) )
{}
-
- struct TagSlice {};
- Pattern(TagSlice):
- m_data( Data::make_Slice( {} ) )
- {}
// Mutators
- void set_bind(::std::string name, PatternBinding::Type type, bool is_mut) {
- m_binding = PatternBinding(name, type, is_mut);
+ void set_bind(Ident name, PatternBinding::Type type, bool is_mut) {
+ m_binding = PatternBinding(mv$(name), type, is_mut);
}
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index 55fb662d..983ab8c0 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -1772,15 +1772,15 @@ public:
unsigned int idx = 0;
for( const auto& fld : e.m_fields )
{
- auto name_a = FMT("a" << fld.m_name);
- pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
+ auto name_a = Ident( FMT("a" << fld.m_name) );
+ pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), Ident(name_a), ::AST::PatternBinding::Type::REF)) );
nodes.push_back( NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_struct_variant_field",
vec$(
NEWNODE(NamedValue, AST::Path("s")),
NEWNODE(String, fld.m_name),
NEWNODE(Integer, idx, CORETYPE_UINT),
- this->enc_closure(sp, this->enc_val_direct(NEWNODE(NamedValue, AST::Path(name_a))))
+ this->enc_closure(sp, this->enc_val_direct(NEWNODE(NamedValue, AST::Path(name_a.name))))
)
) );
idx ++;
diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp
index 9696a586..977d7d69 100644
--- a/src/expand/format_args.cpp
+++ b/src/expand/format_args.cpp
@@ -365,17 +365,17 @@ namespace {
break;
case ::AST::Crate::LOAD_CORE:
toks.push_back( TokenTree(TOK_DOUBLE_COLON) );
- toks.push_back( Token(TOK_STRING, "core") );
+ toks.push_back( Token(Ident("core")) );
break;
case ::AST::Crate::LOAD_STD:
toks.push_back( TokenTree(TOK_DOUBLE_COLON) );
- toks.push_back( Token(TOK_IDENT, "std") );
+ toks.push_back( Token(Ident("std")) );
break;
}
for(auto ent : il)
{
toks.push_back( TokenTree(TOK_DOUBLE_COLON) );
- toks.push_back( Token(TOK_IDENT, ent) );
+ toks.push_back( Token(Ident(ent)) );
}
}
}
@@ -417,7 +417,7 @@ class CFormatArgsExpander:
if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_EQUAL )
{
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
@@ -478,7 +478,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_PAREN_OPEN) );
for(unsigned int i = 0; i < free_args.size() + named_args.size(); i ++ )
{
- toks.push_back( Token(TOK_IDENT, FMT("a" << i)) );
+ toks.push_back( Token(Ident(FMT("a" << i))) );
toks.push_back( TokenTree(TOK_COMMA) );
}
toks.push_back( TokenTree(TOK_PAREN_CLOSE) );
@@ -490,13 +490,13 @@ class CFormatArgsExpander:
// - Contains N+1 entries, where N is the number of fragments
{
toks.push_back( TokenTree(TOK_RWORD_STATIC) );
- toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
+ toks.push_back( Token(Ident("FRAGMENTS")) );
toks.push_back( TokenTree(TOK_COLON) );
toks.push_back( TokenTree(TOK_SQUARE_OPEN) );
toks.push_back( Token(TOK_AMP) );
toks.push_back( Token(TOK_LIFETIME, "static") );
- toks.push_back( Token(TOK_IDENT, "str") );
+ toks.push_back( Token(Ident("str")) );
toks.push_back( Token(TOK_SEMICOLON) );
toks.push_back( Token(fragments.size() + 1, CORETYPE_UINT) );
toks.push_back( TokenTree(TOK_SQUARE_CLOSE) );
@@ -522,7 +522,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_PAREN_OPEN) );
{
toks.push_back( TokenTree(TOK_AMP) );
- toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
+ toks.push_back( Token(Ident("FRAGMENTS")) );
toks.push_back( TokenTree(TOK_COMMA) );
toks.push_back( TokenTree(TOK_AMP) );
@@ -531,7 +531,7 @@ class CFormatArgsExpander:
{
push_path(toks, crate, {"fmt", "ArgumentV1", "new"});
toks.push_back( Token(TOK_PAREN_OPEN) );
- toks.push_back( Token(TOK_IDENT, FMT("a" << frag.arg_index)) );
+ toks.push_back( Token(Ident(FMT("a" << frag.arg_index))) );
toks.push_back( TokenTree(TOK_COMMA) );
@@ -554,7 +554,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_PAREN_OPEN) );
{
toks.push_back( TokenTree(TOK_AMP) );
- toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
+ toks.push_back( Token(Ident("FRAGMENTS")) );
toks.push_back( TokenTree(TOK_COMMA) );
// 1. Generate a set of arguments+formatters
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index 5542b333..0b9eb146 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -183,6 +183,10 @@ void Expand_Pattern(::AST::Crate& crate, LList<const AST::Module*> modstack, ::A
Expand_Pattern(crate, modstack, mod, sp.second, is_refutable);
),
(Slice,
+ for(auto& sp : e.sub_pats)
+ Expand_Pattern(crate, modstack, mod, sp, is_refutable);
+ ),
+ (SplitSlice,
for(auto& sp : e.leading)
Expand_Pattern(crate, modstack, mod, sp, is_refutable);
for(auto& sp : e.trailing)
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index b600879e..b1d8bd38 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -132,7 +132,7 @@
case ::AST::PatternBinding::Type::REF: bt = ::HIR::PatternBinding::Type::Ref; break;
case ::AST::PatternBinding::Type::MUTREF: bt = ::HIR::PatternBinding::Type::MutRef; break;
}
- binding = ::HIR::PatternBinding(pat.binding().m_mutable, bt, pat.binding().m_name, pat.binding().m_slot);
+ binding = ::HIR::PatternBinding(pat.binding().m_mutable, bt, pat.binding().m_name.name, pat.binding().m_slot);
}
struct H {
@@ -433,37 +433,38 @@
),
(Slice,
::std::vector< ::HIR::Pattern> leading;
+ for(const auto& sp : e.sub_pats)
+ leading.push_back( LowerHIR_Pattern(sp) );
+ return ::HIR::Pattern {
+ mv$(binding),
+ ::HIR::Pattern::Data::make_Slice({
+ mv$(leading)
+ })
+ };
+ ),
+ (SplitSlice,
+ ::std::vector< ::HIR::Pattern> leading;
for(const auto& sp : e.leading)
leading.push_back( LowerHIR_Pattern(sp) );
- if( e.extra_bind != "" || e.trailing.size() > 0 ) {
- ::std::vector< ::HIR::Pattern> trailing;
- for(const auto& sp : e.trailing)
- trailing.push_back( LowerHIR_Pattern(sp) );
-
- auto extra_bind = (e.extra_bind == "_" || e.extra_bind == "")
- ? ::HIR::PatternBinding()
- // TODO: Get slot name for `extra_bind`
- : ::HIR::PatternBinding(false, ::HIR::PatternBinding::Type::Ref, e.extra_bind, 0)
- ;
-
- return ::HIR::Pattern {
- mv$(binding),
- ::HIR::Pattern::Data::make_SplitSlice({
- mv$(leading),
- mv$(extra_bind),
- mv$(trailing)
- })
- };
- }
- else {
- return ::HIR::Pattern {
- mv$(binding),
- ::HIR::Pattern::Data::make_Slice({
- mv$(leading)
- })
- };
- }
+ ::std::vector< ::HIR::Pattern> trailing;
+ for(const auto& sp : e.trailing)
+ trailing.push_back( LowerHIR_Pattern(sp) );
+
+ auto extra_bind = e.extra_bind.is_valid()
+ ? ::HIR::PatternBinding()
+ // TODO: Share code with the outer binding code
+ : ::HIR::PatternBinding(false, ::HIR::PatternBinding::Type::Ref, e.extra_bind.m_name.name, e.extra_bind.m_slot)
+ ;
+
+ return ::HIR::Pattern {
+ mv$(binding),
+ ::HIR::Pattern::Data::make_SplitSlice({
+ mv$(leading),
+ mv$(extra_bind),
+ mv$(trailing)
+ })
+ };
)
)
throw ::std::runtime_error("TODO: LowerHIR_Pattern");
diff --git a/src/ident.cpp b/src/ident.cpp
new file mode 100644
index 00000000..5d0fe00c
--- /dev/null
+++ b/src/ident.cpp
@@ -0,0 +1,60 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * include/ident.cpp
+ * - Identifiers with hygine
+ */
+#include <iostream>
+#include <ident.hpp>
+#include <debug.hpp>
+#include <common.hpp> // vector print
+
+bool Ident::Hygine::is_visible(const Hygine& src) const
+{
+ // HACK: Disable hygine for now
+ return true;
+
+ DEBUG("*this = " << *this << ", src=" << src);
+ if( this->file_num != src.file_num ) {
+ DEBUG("- Different file");
+ return false;
+ }
+
+ // `this` is the item, `src` is the ident used to access it
+
+ // If this is from a deeper point than the source, it won't work.
+ if( this->indexes.size() > src.indexes.size() ) {
+ DEBUG("- Not subset: len");
+ return false;
+ }
+
+ // If this hygine list (barring the last) is a subset of the source
+ for(unsigned int i = 0; i < this->indexes.size()-1 - 1; i ++)
+ {
+ if( this->indexes[i] != src.indexes[i] ) {
+ DEBUG("- Not subset: " << i);
+ return false;
+ }
+ }
+
+ unsigned int end = this->indexes.size()-1-1;
+ // Allow match if this ident is from before the addressing ident
+ if( this->indexes[end] < src.indexes[end] ) {
+ return true;
+ }
+
+ DEBUG("- Not before");
+ return false;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const Ident& x) {
+ os << x.name;
+ return os;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const Ident::Hygine& x) {
+ os << "{" << x.file_num << ": [" << x.indexes << "]}";
+ return os;
+}
+
diff --git a/src/include/ident.hpp b/src/include/ident.hpp
new file mode 100644
index 00000000..d5ce2e77
--- /dev/null
+++ b/src/include/ident.hpp
@@ -0,0 +1,78 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * include/ident.hpp
+ * - Identifiers with hygine
+ */
+#pragma once
+#include <vector>
+#include <string>
+
+struct Ident
+{
+ struct Hygine
+ {
+ unsigned int file_num;
+ ::std::vector<unsigned int> indexes;
+
+ Hygine(unsigned int file, ::std::vector<unsigned int> indexes):
+ file_num(file),
+ indexes(::std::move(indexes))
+ {}
+
+ Hygine(Hygine&& x) = default;
+ Hygine(const Hygine& x) = default;
+ Hygine& operator=(Hygine&& x) = default;
+ Hygine& operator=(const Hygine& x) = default;
+
+ // Returns true if an ident with hygine `souce` can see an ident with this hygine
+ bool is_visible(const Hygine& source) const;
+ bool operator==(const Hygine& x) const { return file_num == x.file_num && indexes == x.indexes; }
+ bool operator!=(const Hygine& x) const { return file_num != x.file_num || indexes != x.indexes; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Hygine& v);
+ };
+
+ Hygine hygine;
+ ::std::string name;
+
+ Ident(const char* name):
+ hygine(~0u, {}),
+ name(name)
+ { }
+ Ident(::std::string name):
+ hygine(~0u, {}),
+ name(::std::move(name))
+ { }
+ Ident(Hygine hygine, ::std::string name):
+ hygine(::std::move(hygine)), name(::std::move(name))
+ { }
+
+ Ident(Ident&& x) = default;
+ Ident(const Ident& x) = default;
+ Ident& operator=(Ident&& x) = default;
+ Ident& operator=(const Ident& x) = default;
+
+ ::std::string into_string() {
+ return ::std::move(name);
+ }
+
+ bool operator==(const char* s) const {
+ return this->name == s;
+ }
+
+ bool operator==(const Ident& x) const {
+ if( this->name != x.name )
+ return false;
+ //if( this->hygine.indexes != x.hygine.indexes )
+ // return false;
+ return true;
+ }
+ bool operator!=(const Ident& x) const {
+ return !(*this == x);
+ }
+ bool operator<(const Ident& x) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Ident& x);
+};
diff --git a/src/include/rc_string.hpp b/src/include/rc_string.hpp
index 4649b36e..630f8e89 100644
--- a/src/include/rc_string.hpp
+++ b/src/include/rc_string.hpp
@@ -75,6 +75,7 @@ public:
return "";
}
}
+ bool operator==(const RcString& s) const { return *this == s.c_str(); }
bool operator==(const char* s) const;
friend ::std::ostream& operator<<(::std::ostream& os, const RcString& x) {
return os << x.c_str();
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index dce01c86..bd54c67d 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -49,10 +49,10 @@ public:
switch( GET_TOK(tok, lex) )
{
case TOK_IDENT: {
- ::std::string name = tok.str();
+ ::std::string name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string type = tok.str();
+ ::std::string type = mv$(tok.ident_str());
unsigned int idx = ::std::find( names.begin(), names.end(), name ) - names.begin();
if( idx == names.size() )
@@ -202,9 +202,10 @@ public:
else if( tok.type() == TOK_IDENT )
{
// Look up the named parameter in the list of param names for this arm
- unsigned int idx = ::std::find(var_names.begin(), var_names.end(), tok.str()) - var_names.begin();
+ const auto& name = tok.ident_str();
+ unsigned int idx = ::std::find(var_names.begin(), var_names.end(), name) - var_names.begin();
if( idx == var_names.size() )
- ERROR(lex.getPosition(), E0000, "Macro variable $" << tok.str() << " not found");
+ ERROR(lex.getPosition(), E0000, "Macro variable $" << name << " not found");
if( var_set_ptr ) {
var_set_ptr->insert( ::std::make_pair(idx,true) );
}
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index a45e4384..f6ebca1f 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -889,7 +889,7 @@ ExprNodeP Parse_ExprFC(TokenStream& lex)
switch(GET_TOK(tok, lex))
{
case TOK_IDENT: {
- AST::PathNode path(tok.str(), {});
+ AST::PathNode path( mv$(tok.ident_str()) , {});
switch( GET_TOK(tok, lex) )
{
case TOK_PAREN_OPEN:
@@ -965,7 +965,7 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
while( GET_TOK(tok, lex) == TOK_IDENT )
{
- ::std::string name = tok.str();
+ auto name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
ExprNodeP val = Parse_Stmt(lex);
items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
@@ -1224,7 +1224,7 @@ ExprNodeP Parse_ExprMacro(TokenStream& lex, Token tok)
::std::string name = tok.str();
::std::string ident;
if( GET_TOK(tok, lex) == TOK_IDENT ) {
- ident = mv$(tok.str());
+ ident = mv$(tok.ident_str());
}
else {
PUTBACK(tok, lex);
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index 76c8ab5d..a5c4e372 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -251,6 +251,29 @@ Token Lexer::realGetToken()
//::std::cout << "getTokenInt: tok = " << tok << ::std::endl;
switch(tok.type())
{
+ case TOK_IDENT:
+ if( m_hygine_stack.size() > 0 )
+ {
+ m_hygine_stack.back() ++;
+ }
+ return tok;
+
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+ case TOK_BRACE_OPEN:
+ case TOK_ATTR_OPEN:
+ case TOK_CATTR_OPEN:
+ m_hygine_stack.push_back(0);
+ return tok;
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ case TOK_BRACE_CLOSE:
+ m_hygine_stack.pop_back();
+ if( m_hygine_stack.size() > 0 ) {
+ m_hygine_stack.back() ++;
+ }
+ return tok;
+
case TOK_NEWLINE:
m_line ++;
m_line_ofs = 0;
@@ -767,7 +790,7 @@ Token Lexer::getTokenInt_Identifier(Codepoint leader, Codepoint leader2)
if( str < RWORDS[i].chars ) break;
if( str == RWORDS[i].chars ) return Token((enum eTokenType)RWORDS[i].type);
}
- return Token(TOK_IDENT, str);
+ return Token(Ident( Ident::Hygine(m_file_index, m_hygine_stack), mv$(str) ));
}
}
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index 77151bea..208fa670 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -125,6 +125,10 @@ class Lexer:
bool m_last_char_valid;
Codepoint m_last_char;
Token m_next_token; // Used when lexing generated two tokens
+
+ unsigned int m_file_index;
+ // Incremented on every ident and TT close, pushed on TT open
+ ::std::vector<unsigned int> m_hygine_stack;
public:
Lexer(const ::std::string& filename);
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp
index e7fe1b0b..5e0faf90 100644
--- a/src/parse/paths.cpp
+++ b/src/parse/paths.cpp
@@ -91,14 +91,10 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
}
}
else {
- //assert( GET_TOK(tok, lex) == TOK_IDENT );
- //if( lex.lookahead(0) != TOK_DOUBLE_COLON ) {
- // return AST::Path( tok.str() );
- //}
- //else {
- // PUTBACK(tok, lex);
- return AST::Path(AST::Path::TagRelative(), Parse_PathNodes(lex, generic_mode));
- //}
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto hygine = mv$( tok.ident().hygine );
+ PUTBACK(tok, lex);
+ return AST::Path(AST::Path::TagRelative(), mv$(hygine), Parse_PathNodes(lex, generic_mode));
}
}
@@ -115,7 +111,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
::AST::PathParams params;
CHECK_TOK(tok, TOK_IDENT);
- ::std::string component = tok.str();
+ auto component = mv$( tok.ident_str() );
GET_TOK(tok, lex);
if( generic_mode == PATH_GENERIC_TYPE )
@@ -144,6 +140,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
{
PUTBACK(tok, lex);
do {
+ // TODO: Trailing commas
args.push_back( Parse_Type(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
}
@@ -221,7 +218,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
case TOK_IDENT:
if( LOOK_AHEAD(lex) == TOK_EQUAL )
{
- ::std::string name = tok.str();
+ ::std::string name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
assoc_bounds.push_back( ::std::make_pair( mv$(name), Parse_Type(lex,false) ) );
break;
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
index 2b1be50e..df251bd3 100644
--- a/src/parse/pattern.cpp
+++ b/src/parse/pattern.cpp
@@ -80,18 +80,19 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
// Fall through
}
- ::std::string bind_name;
+ AST::PatternBinding binding;
// If a 'ref' or 'mut' annotation was seen, the next name must be a binding name
if( expect_bind )
{
CHECK_TOK(tok, TOK_IDENT);
- bind_name = tok.str();
+ auto bind_name = tok.take_ident();
// If there's no '@' after it, it's a name binding only (_ pattern)
if( GET_TOK(tok, lex) != TOK_AT )
{
PUTBACK(tok, lex);
- return AST::Pattern(AST::Pattern::TagBind(), bind_name, bind_type, is_mut);
+ return AST::Pattern(AST::Pattern::TagBind(), mv$(bind_name), bind_type, is_mut);
}
+ binding = AST::PatternBinding( mv$(bind_name), bind_type, is_mut );
// '@' consumed, move on to next token
GET_TOK(tok, lex);
@@ -113,8 +114,8 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
break;
// Known binding `ident @`
case TOK_AT:
- bind_name = mv$(tok.str());
- GET_TOK(tok, lex);
+ binding = AST::PatternBinding( tok.take_ident(), bind_type/*MOVE*/, is_mut/*false*/ );
+ GET_TOK(tok, lex); // '@'
GET_TOK(tok, lex); // Match lex.putback() below
break;
default: // Maybe bind
@@ -122,11 +123,11 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
if( is_refutable ) {
assert(bind_type == ::AST::PatternBinding::Type::MOVE);
assert(is_mut == false);
- return AST::Pattern(AST::Pattern::TagMaybeBind(), mv$(tok.str()));
+ return AST::Pattern(AST::Pattern::TagMaybeBind(), tok.take_ident());
}
// Otherwise, it IS a binding
else {
- return AST::Pattern(AST::Pattern::TagBind(), mv$(tok.str()), bind_type, is_mut);
+ return AST::Pattern(AST::Pattern::TagBind(), tok.take_ident(), bind_type, is_mut);
}
}
}
@@ -137,8 +138,9 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
PUTBACK(tok, lex);
auto pat = Parse_PatternReal(lex, is_refutable);
- pat.set_bind(bind_name, bind_type, is_mut);
- return mv$(pat);
+ //pat.set_bind( mv$(binding) );
+ pat.binding() = mv$(binding);
+ return pat;
}
AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable)
@@ -263,46 +265,48 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
auto sp = lex.start_span();
Token tok;
- auto rv = ::AST::Pattern( AST::Pattern::TagSlice() );
- auto& rv_array = rv.data().as_Slice();
+ ::std::vector< ::AST::Pattern> leading;
+ ::std::vector< ::AST::Pattern> trailing;
+ ::AST::PatternBinding inner_binding;
+ bool is_split = false;
- bool is_trailing = false;
while(GET_TOK(tok, lex) != TOK_SQUARE_CLOSE)
{
- ::std::string binding_name;
+ bool has_binding = true;
+ ::AST::PatternBinding binding;
if( tok.type() == TOK_RWORD_REF && lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_DOUBLE_DOT ) {
GET_TOK(tok, lex);
- // TODO: Bind type
- binding_name = tok.str();
+ binding = ::AST::PatternBinding( tok.take_ident(), ::AST::PatternBinding::Type::REF, false );
}
else if( tok.type() == TOK_IDENT && lex.lookahead(0) == TOK_DOUBLE_DOT) {
- // TODO: Bind type
- binding_name = tok.str();
+ binding = ::AST::PatternBinding( tok.take_ident(), ::AST::PatternBinding::Type::MOVE, false );
}
else if( tok.type() == TOK_UNDERSCORE && lex.lookahead(0) == TOK_DOUBLE_DOT) {
- binding_name = "_";
+ // No binding, but switching to trailing
}
else if( tok.type() == TOK_DOUBLE_DOT ) {
- binding_name = "_";
+ // No binding, but switching to trailing
PUTBACK(tok, lex);
}
else {
+ has_binding = false;
}
- if( binding_name != "" ) {
- if(is_trailing)
+ if( has_binding ) {
+ if(is_split)
ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in a slice pattern");
- rv_array.extra_bind = mv$(binding_name);
- is_trailing = true;
+
+ inner_binding = mv$(binding);
+ is_split = true;
GET_TOK(tok, lex); // TOK_DOUBLE_DOT
}
else {
PUTBACK(tok, lex);
- if(is_trailing) {
- rv_array.trailing.push_back( Parse_Pattern(lex, is_refutable) );
+ if(!is_split) {
+ leading.push_back( Parse_Pattern(lex, is_refutable) );
}
else {
- rv_array.leading.push_back( Parse_Pattern(lex, is_refutable) );
+ trailing.push_back( Parse_Pattern(lex, is_refutable) );
}
}
@@ -311,7 +315,16 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
}
CHECK_TOK(tok, TOK_SQUARE_CLOSE);
- return rv;
+ if( is_split )
+ {
+ return ::AST::Pattern( ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) );
+ }
+ else
+ {
+ assert( !inner_binding.is_valid() );
+ assert( trailing.empty() );
+ return ::AST::Pattern( ::AST::Pattern::Data::make_Slice({ mv$(leading) }) );
+ }
}
::AST::Pattern::TuplePat Parse_PatternTuple(TokenStream& lex, bool is_refutable)
@@ -453,14 +466,16 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
}
CHECK_TOK(tok, TOK_IDENT);
- ::std::string field = tok.str();
+ auto field_ident = tok.take_ident();
+ ::std::string field_name;
GET_TOK(tok, lex);
AST::Pattern pat;
if( is_short_bind || tok.type() != TOK_COLON ) {
PUTBACK(tok, lex);
- pat = AST::Pattern(AST::Pattern::TagBind(), field);
- pat.set_bind(field, bind_type, is_mut);
+ pat = AST::Pattern();
+ field_name = field_ident.name;
+ pat.set_bind(mv$(field_ident), bind_type, is_mut);
if( is_box )
{
pat = AST::Pattern(AST::Pattern::TagBox(), mv$(pat));
@@ -468,10 +483,11 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
}
else {
CHECK_TOK(tok, TOK_COLON);
+ field_name = mv$(field_ident.name);
pat = Parse_Pattern(lex, is_refutable);
}
- subpats.push_back( ::std::make_pair(::std::move(field), ::std::move(pat)) );
+ subpats.push_back( ::std::make_pair(mv$(field_name), mv$(pat)) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_BRACE_CLOSE);
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 5954c76d..6c9acc14 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -132,7 +132,8 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex)
if( tok.type() == TOK_IDENT )
{
- ::std::string param_name = tok.str();
+ // TODO: Hygine
+ ::std::string param_name = mv$(tok.ident_str());
ret.add_ty_param( AST::TypeParam( param_name ) );
auto param_ty = TypeRef(lex.getPosition(), param_name);
@@ -150,6 +151,7 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex)
}
else if( tok.type() == TOK_LIFETIME )
{
+ // TODO: Should lifetimes have hygine?
::std::string param_name = tok.str();
ret.add_lft_param( param_name );
if( GET_TOK(tok, lex) == TOK_COLON )
@@ -527,7 +529,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
}
CHECK_TOK(tok, TOK_IDENT);
- ::std::string name = tok.str();
+ auto name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
TypeRef type = Parse_Type(lex);
@@ -613,7 +615,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
bool is_specialisable = false;
- if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
+ if( tok.type() == TOK_IDENT && tok.ident_str() == "default" ) {
is_specialisable = true;
GET_TOK(tok, lex);
}
@@ -627,7 +629,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
{
case TOK_RWORD_STATIC: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto ty = Parse_Type(lex);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
@@ -644,7 +646,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
break; }
case TOK_RWORD_CONST: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto ty = Parse_Type(lex);
@@ -662,7 +664,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
case TOK_RWORD_TYPE: {
auto atype_params = ::AST::GenericParams { };
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
+ auto name = mv$(tok.ident_str());
if( GET_TOK(tok, lex) == TOK_COLON )
{
// Bounded associated type
@@ -702,7 +704,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
CHECK_TOK(tok, TOK_RWORD_FN);
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
+ ::std::string name = tok.take_ident().into_string();
// Self allowed, prototype-form allowed (optional names and no code)
auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const);
if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
@@ -766,7 +768,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
SET_ATTRS(lex, item_attrs);
CHECK_TOK(tok, TOK_IDENT);
- ::std::string name = tok.str();
+ ::std::string name = tok.take_ident().into_string();
if( GET_TOK(tok, lex) == TOK_PAREN_OPEN )
{
::std::vector<TypeRef> types;
@@ -813,7 +815,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = tok.take_ident().into_string();
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto ty = Parse_Type(lex);
fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) );
@@ -886,7 +888,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = tok.take_ident().into_string();
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto ty = Parse_Type(lex);
@@ -911,7 +913,7 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
}
CHECK_TOK(tok, TOK_IDENT);
- ::std::string name = tok.str();
+ ::std::string name = tok.take_ident().into_string();
switch(GET_TOK(tok, lex))
{
case TOK_EQUAL:
@@ -1069,7 +1071,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
}
bool is_specialisable = false;
- if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
+ if( tok.type() == TOK_IDENT && tok.ident() == "default" ) {
is_specialisable = true;
GET_TOK(tok, lex);
}
@@ -1081,7 +1083,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
{
case TOK_RWORD_TYPE: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
+ auto name = tok.take_ident().into_string();
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
impl.add_type(is_public, is_specialisable, name, Parse_Type(lex));
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
@@ -1096,7 +1098,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE && !fn_is_unsafe )
{
CHECK_TOK(tok, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = tok.take_ident().into_string();
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto ty = Parse_Type(lex);
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
@@ -1131,7 +1133,8 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
// FALL
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = tok.str();
+ // TODO: Hygine on function names? - Not in impl blocks?
+ ::std::string name = tok.take_ident().into_string();
DEBUG("Function " << name);
// - Self allowed, can't be prototype-form
auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const);
@@ -1182,7 +1185,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::M
{
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = tok.take_ident().into_string();
// parse function as prototype
// - no self, "safe" and not const
auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, false,false) );
@@ -1200,7 +1203,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::M
else
PUTBACK(tok, lex);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = tok.take_ident().into_string();
GET_CHECK_TOK(tok, lex, TOK_COLON);
auto type = Parse_Type(lex);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
@@ -1239,12 +1242,13 @@ void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_
}
else {
CHECK_TOK(tok, TOK_IDENT);
- path = base_path + AST::PathNode(tok.str(), {});
- name = mv$(tok.str());
+ path = base_path + AST::PathNode(tok.ident_str(), {});
+ name = mv$(tok.ident_str());
}
+
if( GET_TOK(tok, lex) == TOK_RWORD_AS ) {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = mv$(tok.str());
+ name = mv$(tok.ident_str());
}
else {
PUTBACK(tok, lex);
@@ -1278,7 +1282,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
path = AST::Path( AST::Path::TagSuper(), count, {} );
break; }
case TOK_IDENT:
- path.append( AST::PathNode(tok.str(), {}) );
+ path.append( AST::PathNode(tok.take_ident().into_string(), {}) );
break;
// Leading :: is allowed and ignored for the $crate feature
case TOK_DOUBLE_COLON:
@@ -1305,7 +1309,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
{
if( GET_TOK(tok, lex) == TOK_IDENT )
{
- path.append( AST::PathNode(tok.str(), {}) );
+ path.append( AST::PathNode(tok.take_ident().into_string(), {}) );
}
else
{
@@ -1334,7 +1338,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
if( tok.type() == TOK_RWORD_AS )
{
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = tok.str();
+ name = tok.take_ident().into_string();
}
else
{
@@ -1352,7 +1356,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
Token tok;
::std::string ident;
if( GET_TOK(tok, lex) == TOK_IDENT ) {
- ident = mv$(tok.str());
+ ident = tok.take_ident().into_string();
}
else {
PUTBACK(tok, lex);
@@ -1443,7 +1447,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
// `extern "<ABI>" fn ...`
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, false,false) );
break; }
// `extern "ABI" {`
@@ -1458,7 +1462,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
// `extern fn ...`
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, "C", false, false,false) );
break;
@@ -1480,17 +1484,17 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
item_data = ::AST::Item::make_Crate({ tok.str() });
GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
break;
// `extern crate crate_name;`
// `extern crate crate_name as other_name;`
case TOK_IDENT:
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
if(GET_TOK(tok, lex) == TOK_RWORD_AS) {
item_data = ::AST::Item::make_Crate({ mv$(item_name) });
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
}
else {
PUTBACK(tok, lex);
@@ -1513,7 +1517,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
switch( GET_TOK(tok, lex) )
{
case TOK_IDENT: {
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
TypeRef type = Parse_Type(lex);
@@ -1525,12 +1529,12 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
case TOK_RWORD_UNSAFE:
GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,true/*unsafe,const*/) );
break;
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
// - self not allowed, not prototype
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,true/*unsafe,const*/) );
break;
@@ -1547,7 +1551,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
GET_TOK(tok, lex);
}
CHECK_TOK(tok, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
GET_CHECK_TOK(tok, lex, TOK_COLON);
TypeRef type = Parse_Type(lex);
@@ -1578,20 +1582,20 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
}
GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$( tok.str() );
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, true,false/*unsafe,const*/) );
break; }
// `unsafe fn`
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$( tok.str() );
+ item_name = mv$(tok.ident_str());
// - self not allowed, not prototype
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,false/*unsafe,const*/) );
break;
// `unsafe trait`
case TOK_RWORD_TRAIT:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
// TODO: Mark as unsafe
meta_items.push_back( AST::MetaItem("#UNSAFE") );
item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
@@ -1606,33 +1610,33 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
// `fn`
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
// - self not allowed, not prototype
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,false/*unsafe,const*/) );
break;
// `type`
case TOK_RWORD_TYPE:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_TypeAlias(lex) );
break;
// `struct`
case TOK_RWORD_STRUCT:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_Struct(lex, meta_items) );
break;
// `enum`
case TOK_RWORD_ENUM:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_EnumDef(lex, meta_items) );
break;
// Contextual keywords
case TOK_IDENT:
- if( tok.str() == "union" ) {
+ if( tok.ident_str() == "union" ) {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_Union(lex, meta_items) );
}
else {
@@ -1645,13 +1649,13 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
// `trait`
case TOK_RWORD_TRAIT:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = tok.str();
+ item_name = mv$(tok.ident_str());
item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
break;
case TOK_RWORD_MOD: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
+ auto name = mv$(tok.ident_str());
DEBUG("Sub module '" << name << "'");
AST::Module submod( mod_path + name );
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index 05ded69f..9f84df79 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -53,7 +53,12 @@ Token::Token(enum eTokenType type, ::std::string str):
m_type(type),
m_data(Data::make_String(mv$(str)))
{
+ assert( m_type != TOK_IDENT );
}
+Token::Token(Ident ident):
+ m_type(TOK_IDENT),
+ m_data(Data( mv$(ident) ))
+{}
Token::Token(uint64_t val, enum eCoreType datatype):
m_type(TOK_INTEGER),
m_data( Data::make_Integer({datatype, val}) )
@@ -152,6 +157,7 @@ Token::Token(const Token& t):
(None, ),
(String, m_data = Data::make_String(e); ),
(Integer, m_data = Data::make_Integer(e);),
+ (Ident , m_data = Data(e);),
(Float, m_data = Data::make_Float(e);),
(Fragment, BUG(t.m_pos, "Attempted to copy a fragment - " << t);)
)
@@ -171,6 +177,7 @@ Token Token::clone() const
(Integer,
rv.m_data = Data::make_Integer(e);
),
+ (Ident, rv.m_data = Data(e); ),
(Float,
rv.m_data = Data::make_Float(e);
),
@@ -299,7 +306,7 @@ struct EscapedString {
case TOK_INTERPOLATED_META: return "/*:meta*/";
case TOK_INTERPOLATED_ITEM: return "/*:item*/";
// Value tokens
- case TOK_IDENT: return m_data.as_String();
+ case TOK_IDENT: return m_data.as_Ident().name;
case TOK_MACRO: return m_data.as_String() + "!";
case TOK_LIFETIME: return "'" + m_data.as_String();
case TOK_INTEGER: return FMT(m_data.as_Integer().m_intval); // TODO: suffix for type
@@ -464,6 +471,10 @@ SERIALISE_TYPE(Token::, "Token", {
s % e.m_datatype;
s.item( e.m_intval );
),
+ (Ident,
+ // Hygine contex for serialised idents is left for the loader
+ s << e.name;
+ ),
(Float,
s % e.m_datatype;
s.item( e.m_floatval );
@@ -484,19 +495,25 @@ SERIALISE_TYPE(Token::, "Token", {
{
case Token::Data::TAGDEAD: break;
case Token::Data::TAG_None: break;
- case Token::Data::TAG_String:{
+ case Token::Data::TAG_String: {
::std::string str;
s.item( str );
m_data = Token::Data::make_String(str);
break; }
- case Token::Data::TAG_Integer:{
+ case Token::Data::TAG_Integer: {
enum eCoreType dt;
uint64_t v;
s % dt;
s.item( v );
m_data = Token::Data::make_Integer({dt, v});
break; }
- case Token::Data::TAG_Float:{
+ case Token::Data::TAG_Ident: {
+ ::std::string str;
+ s.item( str );
+ // - Hygine is populated by caller, fill with dummy values for now
+ m_data = Token::Data::make_Ident(Ident { {~0u,{}}, mv$(str) });
+ break; }
+ case Token::Data::TAG_Float: {
enum eCoreType dt;
double v;
s % dt;
diff --git a/src/parse/token.hpp b/src/parse/token.hpp
index 5fdcbc77..94458f1f 100644
--- a/src/parse/token.hpp
+++ b/src/parse/token.hpp
@@ -1,4 +1,9 @@
/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/token.hpp
+ * - Lexer Tokens
*/
#pragma once
@@ -6,6 +11,7 @@
#include <tagged_union.hpp>
#include <serialise.hpp>
#include "../coretypes.hpp"
+#include <ident.hpp>
enum eTokenType
{
@@ -55,6 +61,7 @@ class Token:
TAGGED_UNION(Data, None,
(None, struct {}),
(String, ::std::string),
+ (Ident, Ident),
(Integer, struct {
enum eCoreType m_datatype;
uint64_t m_intval;
@@ -69,6 +76,7 @@ class Token:
enum eTokenType m_type;
Data m_data;
Position m_pos;
+
public:
virtual ~Token();
Token();
@@ -91,6 +99,7 @@ public:
Token(enum eTokenType type);
Token(enum eTokenType type, ::std::string str);
+ Token(Ident ident);
Token(uint64_t val, enum eCoreType datatype);
Token(double val, enum eCoreType datatype);
Token(const InterpolatedFragment& );
@@ -98,11 +107,17 @@ public:
Token(TagTakeIP, InterpolatedFragment );
enum eTokenType type() const { return m_type; }
+ ::std::string& str() { return m_data.as_String(); }
const ::std::string& str() const { return m_data.as_String(); }
enum eCoreType datatype() const { TU_MATCH_DEF(Data, (m_data), (e), (assert(!"Getting datatype of invalid token type");), (Integer, return e.m_datatype;), (Float, return e.m_datatype;)) }
uint64_t intval() const { return m_data.as_Integer().m_intval; }
double floatval() const { return m_data.as_Float().m_floatval; }
+ const Ident& ident() const { return m_data.as_Ident(); }
+ Ident take_ident() { return ::std::move(m_data.as_Ident()); }
+ ::std::string& ident_str() { return m_data.as_Ident().name; }
+ const ::std::string& ident_str() const { return m_data.as_Ident().name; }
+
TypeRef& frag_type() { assert(m_type == TOK_INTERPOLATED_TYPE); return *reinterpret_cast<TypeRef*>( m_data.as_Fragment() ); }
AST::Path& frag_path() { assert(m_type == TOK_INTERPOLATED_PATH); return *reinterpret_cast<AST::Path*>( m_data.as_Fragment() ); }
AST::Pattern& frag_pattern() { assert(m_type == TOK_INTERPOLATED_PATTERN); return *reinterpret_cast<AST::Pattern*>( m_data.as_Fragment() ); }
@@ -115,7 +130,8 @@ public:
return false;
TU_MATCH(Data, (m_data, r.m_data), (e, re),
(None, return true;),
- (String, return e == re;),
+ (String, return e == re; ),
+ (Ident, return e == re; ),
(Integer, return e.m_datatype == re.m_datatype && e.m_intval == re.m_intval;),
(Float, return e.m_datatype == re.m_datatype && e.m_floatval == re.m_floatval;),
(Fragment, assert(!"Token equality on Fragment");)
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 0d47eb21..a37e0fce 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -47,7 +47,7 @@ struct Context
(VarBlock, struct {
unsigned int level;
// "Map" of names to function-level variable slots
- ::std::vector< Named< unsigned int > > variables;
+ ::std::vector< ::std::pair<Ident, unsigned int> > variables;
}),
(Generic, struct {
// Map of names to slots
@@ -169,7 +169,7 @@ struct Context
m_block_level += 1;
DEBUG("Push block to " << m_block_level);
}
- unsigned int push_var(const Span& sp, const ::std::string& name) {
+ unsigned int push_var(const Span& sp, const Ident& name) {
if( m_var_count == ~0u ) {
BUG(sp, "Assigning local when there's no variable context");
}
@@ -183,8 +183,8 @@ struct Context
for( const auto& v : vb.variables )
{
// TODO: Error when a binding is used twice or not at all
- if( v.name == name ) {
- return v.value;
+ if( v.first == name ) {
+ return v.second;
}
}
ERROR(sp, E0000, "Mismatched bindings in pattern");
@@ -198,7 +198,7 @@ struct Context
DEBUG("New var @ " << m_block_level << ": #" << m_var_count << " " << name);
auto& vb = m_name_context.back().as_VarBlock();
assert(vb.level == m_block_level);
- vb.variables.push_back( Named<unsigned int> { name, m_var_count } );
+ vb.variables.push_back( ::std::make_pair(mv$(name), m_var_count) );
m_var_count += 1;
assert( m_var_count >= vb.variables.size() );
return m_var_count - 1;
@@ -209,7 +209,7 @@ struct Context
if( m_name_context.size() > 0 && m_name_context.back().is_VarBlock() && m_name_context.back().as_VarBlock().level == m_block_level ) {
DEBUG("Pop block from " << m_block_level << " with vars:" << FMT_CB(os,
for(const auto& v : m_name_context.back().as_VarBlock().variables)
- os << " " << v.name << "#" << v.value;
+ os << " " << v.first << "#" << v.second;
));
m_name_context.pop_back();
}
@@ -259,20 +259,8 @@ struct Context
}
return "";
}
- AST::Path lookup_mod(const Span& sp, const ::std::string& name) const {
- return this->lookup(sp, name, LookupMode::Namespace);
- }
- AST::Path lookup_type(const Span& sp, const ::std::string& name) const {
- return this->lookup(sp, name, LookupMode::Type);
- }
- AST::Path lookup_constant(const Span& sp, const ::std::string& name) const {
- return this->lookup(sp, name, LookupMode::Constant);
- }
- AST::Path lookup_value(const Span& sp, const ::std::string& name) const {
- return this->lookup(sp, name, LookupMode::Variable);
- }
- AST::Path lookup(const Span& sp, const ::std::string& name, LookupMode mode) const {
- auto rv = this->lookup_opt(name, mode);
+ AST::Path lookup(const Span& sp, const ::std::string& name, const Ident::Hygine& src_context, LookupMode mode) const {
+ auto rv = this->lookup_opt(name, src_context, mode);
if( !rv.is_valid() ) {
switch(mode)
{
@@ -364,7 +352,7 @@ struct Context
}
return false;
}
- AST::Path lookup_opt(const ::std::string& name, LookupMode mode) const {
+ AST::Path lookup_opt(const ::std::string& name, const Ident::Hygine& src_context, LookupMode mode) const {
for(auto it = m_name_context.rbegin(); it != m_name_context.rend(); ++ it)
{
@@ -391,9 +379,9 @@ struct Context
else {
for( auto it2 = e.variables.rbegin(); it2 != e.variables.rend(); ++ it2 )
{
- if( it2->name == name ) {
+ if( it2->first.name == name && it2->first.hygine.is_visible(src_context) ) {
::AST::Path rv(name);
- rv.bind_variable( it2->value );
+ rv.bind_variable( it2->second );
return rv;
}
}
@@ -457,8 +445,9 @@ struct Context
if( mode == LookupMode::Variable ) {
for( auto it2 = e.variables.rbegin(); it2 != e.variables.rend(); ++ it2 )
{
- if( it2->name == name ) {
- return it2->value;
+ // TODO: Hyginic lookup?
+ if( it2->first.name == name ) {
+ return it2->second;
}
}
}
@@ -1255,7 +1244,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
if(e.nodes.size() > 1)
{
// Look up type/module name
- auto p = context.lookup(sp, e.nodes[0].name(), Context::LookupMode::Namespace);
+ auto p = context.lookup(sp, e.nodes[0].name(), e.hygine, Context::LookupMode::Namespace);
DEBUG("Found type/mod - " << p);
// HACK: If this is a primitive name, and resolved to a module.
// - If the next component isn't found in the located module
@@ -1344,7 +1333,7 @@ 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);
+ auto p = context.lookup(sp, e.nodes[0].name(), e.hygine, mode);
//DEBUG("Found path " << p << " for " << path);
if( p.is_absolute() ) {
assert( !p.nodes().empty() );
@@ -1726,7 +1715,7 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa
if( allow_refutable ) {
auto name = mv$( e.name );
// Attempt to resolve the name in the current namespace, and if it fails, it's a binding
- auto p = context.lookup_opt( name, Context::LookupMode::Pattern );
+ auto p = context.lookup_opt( name.name, name.hygine, Context::LookupMode::Pattern );
if( p.is_valid() ) {
Resolve_Absolute_Path(context, pat.span(), Context::LookupMode::Pattern, p);
pat = ::AST::Pattern(::AST::Pattern::TagValue(), ::AST::Pattern::Value::make_Named(mv$(p)));
@@ -1783,10 +1772,15 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa
),
(Slice,
// NOTE: Can be irrefutable (if the type is array)
+ for(auto& sp : e.sub_pats)
+ Resolve_Absolute_Pattern(context, allow_refutable, sp);
+ ),
+ (SplitSlice,
+ // NOTE: Can be irrefutable (if the type is array)
for(auto& sp : e.leading)
Resolve_Absolute_Pattern(context, allow_refutable, sp);
- if( e.extra_bind != "" && e.extra_bind != "_" ) {
- context.push_var( pat.span(), e.extra_bind );
+ if( e.extra_bind.is_valid() ) {
+ context.push_var( pat.span(), e.extra_bind.m_name );
}
for(auto& sp : e.trailing)
Resolve_Absolute_Pattern(context, allow_refutable, sp);