From 52c363340a4f2ee589d2e6753f1c685ef7b907f5 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 2 Nov 2016 14:51:21 +0800 Subject: All - Hack in start of macro hygine - requires rework so is disabled --- Makefile | 2 +- src/ast/dump.cpp | 34 +++++++++++++---- src/ast/expr.cpp | 29 ++++++++++++--- src/ast/path.cpp | 2 +- src/ast/path.hpp | 11 ++++-- src/ast/pattern.cpp | 28 +++++++++----- src/ast/pattern.hpp | 46 +++++++++++++---------- src/expand/derive.cpp | 6 +-- src/expand/format_args.cpp | 20 +++++----- src/expand/mod.cpp | 4 ++ src/hir/from_ast.cpp | 59 ++++++++++++++--------------- src/ident.cpp | 60 ++++++++++++++++++++++++++++++ src/include/ident.hpp | 78 +++++++++++++++++++++++++++++++++++++++ src/include/rc_string.hpp | 1 + src/macro_rules/parse.cpp | 9 +++-- src/parse/expr.cpp | 6 +-- src/parse/lex.cpp | 25 ++++++++++++- src/parse/lex.hpp | 4 ++ src/parse/paths.cpp | 17 ++++----- src/parse/pattern.cpp | 78 +++++++++++++++++++++++---------------- src/parse/root.cpp | 92 ++++++++++++++++++++++++---------------------- src/parse/token.cpp | 25 +++++++++++-- src/parse/token.hpp | 18 ++++++++- src/resolve/absolute.cpp | 54 ++++++++++++--------------- 24 files changed, 489 insertions(+), 219 deletions(-) create mode 100644 src/ident.cpp create mode 100644 src/include/ident.hpp 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 @@ -921,21 +921,39 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) m_os << ")"; ), (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 << "/*"<(&node) != nullptr ) { - node.print(os); - //} - //else { - // os << "/* NULLPTR */"; - //} + assert( static_cast(&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 #include #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 nodes; } ), (Self, struct { // Module-relative @@ -224,8 +226,8 @@ public: // RELATIVE struct TagRelative {}; - Path(TagRelative, ::std::vector nodes): - m_class( Class::make_Relative({ mv$(nodes) }) ) + Path(TagRelative, Ident::Hygine hygine, ::std::vector 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 @@ -112,21 +112,26 @@ namespace AST { os << ent.path << " {" << ent.sub_patterns << "}"; ), (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 clone_sp(const ::std::unique_ptr& 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 #include #include +#include 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 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 leading; ::std::string extra_bind; ::std::vector trailing; } ) + (Slice, struct { ::std::vector sub_pats; }), + (SplitSlice, struct { ::std::vector leading; PatternBinding extra_bind; ::std::vector 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 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 { @@ -432,38 +432,39 @@ } ), (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 +#include +#include +#include // 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 +#include + +struct Ident +{ + struct Hygine + { + unsigned int file_num; + ::std::vector indexes; + + Hygine(unsigned int file, ::std::vector 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> > 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 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 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" 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 #include #include "../coretypes.hpp" +#include 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( m_data.as_Fragment() ); } AST::Path& frag_path() { assert(m_type == TOK_INTERPOLATED_PATH); return *reinterpret_cast( m_data.as_Fragment() ); } AST::Pattern& frag_pattern() { assert(m_type == TOK_INTERPOLATED_PATTERN); return *reinterpret_cast( 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 > 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 { 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))); @@ -1782,11 +1771,16 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa Resolve_Absolute_Pattern(context, allow_refutable, sp.second); ), (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); -- cgit v1.2.3