From 66880a641295734c437feb4eb32fb60bf5cd9af5 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 25 Mar 2015 21:37:29 +0800 Subject: Macros updated with concat!, stringify!, and $crate --- src/convert/resolve.cpp | 51 +++++++++++------ src/dump_as_rust.cpp | 10 +++- src/macros.cpp | 94 +++++++++++++++++++++++++------ src/parse/expr.cpp | 20 +++++++ src/parse/lex.cpp | 147 ++++++++++++++++++++++++++++++++++++++++++++++++ src/parse/lex.hpp | 20 +++++++ src/parse/pattern.cpp | 3 +- src/parse/root.cpp | 12 ++++ 8 files changed, 319 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 66dc1b3a..62eb0bbf 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -35,7 +35,8 @@ class CPathResolver: {} friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) { - return os << "'" << x.name << "' = " << x.path; + //return os << "'" << x.name << "' = " << x.path; + return os << "'" << x.name << "'"; } }; const AST::Crate& m_crate; @@ -365,26 +366,44 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) // - Invalid afaik, instead Trait::method() is used } - // Search backwards up the stack of anon modules - if( m_module_stack.size() ) + + if( path.nodes()[0].name() == "super" ) { + // Unwrap a single named node from the module path, and search that path + // - Requires resolving that path to a module to pass to lookup_path_in_module AST::Path local_path = m_module_path; - for(unsigned int i = 0; i < m_module_stack.size(); i ++) - local_path.nodes().push_back( AST::PathNode( FMT("#" << m_module_stack[i].first), {} ) ); - - for(unsigned int i = m_module_stack.size(); i--; ) + local_path.nodes().pop_back(); + local_path.resolve(m_crate); + DEBUG("'super' path is relative to " << local_path); + path.nodes().erase( path.nodes().begin() ); // delete the 'super' node + const AST::Module& mod = local_path.bound_module(); + if( lookup_path_in_module(m_crate, mod, local_path, path) ) + return ; + // this should always be an error, as 'super' paths are never MaybeBind + } + else + { + // Search backwards up the stack of anon modules + if( m_module_stack.size() ) { - if( lookup_path_in_module(m_crate, *m_module_stack[i].second, local_path, path) ) { - // Success! - return ; + AST::Path local_path = m_module_path; + for(unsigned int i = 0; i < m_module_stack.size(); i ++) + local_path.nodes().push_back( AST::PathNode( FMT("#" << m_module_stack[i].first), {} ) ); + + for(unsigned int i = m_module_stack.size(); i--; ) + { + if( lookup_path_in_module(m_crate, *m_module_stack[i].second, local_path, path) ) { + // Success! + return ; + } + local_path.nodes().pop_back(); } - local_path.nodes().pop_back(); } - } - // Search current module, if found return with no error - if( lookup_path_in_module(m_crate, *m_module, m_module_path, path) ) - { - return; + // Search current module, if found return with no error + if( lookup_path_in_module(m_crate, *m_module, m_module_path, path) ) + { + return; + } } DEBUG("no matches found for path = " << path); diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 764f5a86..b8fb1647 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -643,7 +643,10 @@ void RustPrinter::print_params(const AST::TypeParams& params) { if( !is_first ) m_os << ", "; - m_os << p.name(); + if( p.is_type() ) + m_os << p.name() << " = " << p.get_default(); + else + m_os << "'" << p.name(); is_first = false; } m_os << ">"; @@ -741,13 +744,14 @@ void RustPrinter::handle_struct(const AST::Struct& s) if( s.fields().size() == 0 ) { - m_os << "()\n"; + m_os << " /* unit-like */\n"; print_bounds(s.params()); m_os << indent() << ";\n"; } else if( s.fields().size() == 1 && s.fields()[0].name == "" ) { - m_os << "(" << "" <<")\n"; + const auto& tuple = s.fields()[0].data; + m_os << "(" << tuple.print_pretty() <<")\n"; print_bounds(s.params()); m_os << indent() << ";\n"; } diff --git a/src/macros.cpp b/src/macros.cpp index 26e8ada4..fa303574 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -12,11 +12,6 @@ typedef ::std::map< ::std::string, MacroRules> t_macro_regs; t_macro_regs g_macro_registrations; const LList* g_macro_module; -TokenTree g_crate_path_tt = TokenTree({ - TokenTree(Token(TOK_DOUBLE_COLON)), - TokenTree(Token(TOK_STRING, "--CRATE--")), - }); - class ParameterMappings { // MultiMap (layer, name) -> TokenTree @@ -141,7 +136,7 @@ public: private: const TokenStream& m_olex; - const TokenTree& m_crate_path; + const ::std::string m_crate_name; const ::std::vector& m_root_contents; const ParameterMappings m_mappings; @@ -158,7 +153,7 @@ private: public: MacroExpander(const MacroExpander& x): m_olex(x.m_olex), - m_crate_path(x.m_crate_path), + m_crate_name(x.m_crate_name), m_root_contents(x.m_root_contents), m_mappings(x.m_mappings), m_offsets({ {0,0} }), @@ -166,9 +161,9 @@ public: { prep_counts(); } - MacroExpander(const TokenStream& olex, const ::std::vector& contents, ParameterMappings mappings, const TokenTree& crate_path): + MacroExpander(const TokenStream& olex, const ::std::vector& contents, ParameterMappings mappings, ::std::string crate_name): m_olex(olex), - m_crate_path(crate_path), + m_crate_name(crate_name), m_root_contents(contents), m_mappings(mappings), m_offsets({ {0,0} }), @@ -219,6 +214,7 @@ const LList* Macro_GetModule() void Macro_InitDefaults() { + #if 0 // try!() macro { MacroRule rule; @@ -268,6 +264,7 @@ void Macro_InitDefaults() rules.push_back(rule); g_macro_registrations.insert( make_pair(::std::string("panic"), rules)); } + #endif } bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat) @@ -275,8 +272,17 @@ bool Macro_TryPattern(TTStream& lex, const MacroPatEnt& pat) DEBUG("pat = " << pat); switch(pat.type) { - case MacroPatEnt::PAT_TOKEN: - return LOOK_AHEAD(lex) == pat.tok.type(); + case MacroPatEnt::PAT_TOKEN: { + Token tok = lex.getToken(); + if( tok != pat.tok ) { + lex.putback(tok); + return false; + } + else { + lex.putback(tok); + return true; + } + } case MacroPatEnt::PAT_LOOP: if( pat.name == "*" ) return true; @@ -460,7 +466,8 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay // Count the number of repetitions bound_tts.calculate_counts(); - TokenStream* ret_ptr = new MacroExpander(olex, rule.m_contents, bound_tts, g_crate_path_tt); + DEBUG("TODO: Obtain crate name correctly"); + TokenStream* ret_ptr = new MacroExpander(olex, rule.m_contents, bound_tts, ""); // HACK! Disable nested macro expansion //ret_ptr->parse_state().no_expand_macros = true; @@ -487,7 +494,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay if( name == "concat_idents" ) { return Macro_Invoke_Concat(input, TOK_IDENT); } - else if( name == "concat_strings" ) { + else if( name == "concat_strings" || name == "concat" ) { return Macro_Invoke_Concat(input, TOK_STRING); } else if( name == "cfg" ) { @@ -496,6 +503,14 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay else if( name == "stringify" ) { return ::std::unique_ptr( (TokenStream*)new MacroStringify(input) ); } + else if( name == "file" ) { + const ::std::string& pos = olex.getPosition().filename; + return ::std::unique_ptr( (TokenStream*)new MacroToken(Token(TOK_STRING, pos)) ); + } + else if( name == "line" ) { + auto pos = olex.getPosition().line; + return ::std::unique_ptr( (TokenStream*)new MacroToken(Token((uint64_t)pos, CORETYPE_U32)) ); + } // Look for macro in builtins t_macro_regs::iterator macro_reg = g_macro_registrations.find(name); @@ -575,8 +590,11 @@ Token MacroExpander::realGetToken() if( ent.name == "*crate" ) { DEBUG("Crate name hack"); - m_ttstream.reset( new TTStream(m_crate_path) ); - return m_ttstream->getToken(); + if( m_crate_name != "" ) + { + m_next_token = Token(TOK_STRING, m_crate_name); + return Token(TOK_DOUBLE_COLON); + } } // - Expand to a parameter else if( ent.name != "" ) @@ -704,6 +722,37 @@ const ::std::vector* MacroExpander::getCurLayer() const return ents; } +void Macro_Invoke_Concat_Once(::std::string& s, TokenStream& lex, enum eTokenType exp) +{ + Token tok; + GET_TOK(tok, lex); + if( exp == TOK_STRING ) + { + if( tok.type() == TOK_MACRO ) + { + // Special case, expand both concat! and stringify! internally + // TODO: Invoke + auto tt = Parse_TT(lex, false); + auto slex = Macro_Invoke(lex, tok.str(), tt); + Macro_Invoke_Concat_Once(s, (*slex), exp); + GET_CHECK_TOK(tok, (*slex), TOK_EOF); + } + else if( tok.type() == exp ) + { + s += tok.str(); + } + else + { + CHECK_TOK(tok, exp); + } + } + else + { + CHECK_TOK(tok, exp); + s += tok.str(); + } +} + ::std::unique_ptr Macro_Invoke_Concat(const TokenTree& input, enum eTokenType exp) { Token tok; @@ -711,8 +760,7 @@ const ::std::vector* MacroExpander::getCurLayer() const ::std::string val; do { - GET_CHECK_TOK(tok, lex, exp); - val += tok.str(); + Macro_Invoke_Concat_Once(val, lex, exp); } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_EOF); @@ -758,7 +806,17 @@ Token MacroToken::realGetToken() } MacroStringify::MacroStringify(const TokenTree& input) { - throw ParseError::Todo("Stringify"); + Token tok; + TTStream lex(input); + + ::std::string rv; + while( GET_TOK(tok, lex) != TOK_EOF ) + { + rv += tok.to_str(); + rv += " "; + } + + m_tok = Token(TOK_STRING, ::std::move(rv)); } Position MacroStringify::getPosition() const { diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 222a6a3a..9b3ce04b 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -97,6 +97,26 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex) false ) ); break; } + // - 'static' + case TOK_RWORD_STATIC: + keep_mod = true; + { + bool is_mut = false; + if( GET_TOK(tok, lex) == TOK_RWORD_MUT ) + is_mut = true; + else + lex.putback(tok); + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_COLON); + TypeRef type = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_EQUAL); + auto val = Parse_Expr1(lex); + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + + local_mod->add_global(false, is_mut, ::std::move(name), ::std::move(type), ::std::move(val)); + break; + } // - 'struct' case TOK_RWORD_STRUCT: keep_mod = true; diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index d09bc2d8..34a2ff58 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -678,6 +678,153 @@ enum eTokenType Token::typefromstr(const ::std::string& s) return TOK_NULL; } +::std::string Token::to_str() const +{ + switch(m_type) + { + case TOK_NULL: return "/*null*/"; + case TOK_EOF: return "/*eof*/"; + + case TOK_NEWLINE: return "\n"; + case TOK_WHITESPACE: return " "; + case TOK_COMMENT: return "/*" + m_str + "*/"; + // Value tokens + case TOK_IDENT: return m_str; + case TOK_MACRO: return m_str + "!"; + case TOK_LIFETIME: return "'" + m_str; + case TOK_INTEGER: return FMT(m_intval); // TODO: suffix for type + case TOK_CHAR: return FMT("'\\u{"<< ::std::hex << m_intval << "}"); + case TOK_FLOAT: return FMT(m_floatval); + case TOK_STRING: return "\"" + m_str + "\""; + case TOK_CATTR_OPEN:return "#!["; + case TOK_ATTR_OPEN: return "#["; + case TOK_UNDERSCORE:return "_"; + // Symbols + case TOK_PAREN_OPEN: return "("; + case TOK_PAREN_CLOSE: return ")"; + case TOK_BRACE_OPEN: return "{"; + case TOK_BRACE_CLOSE: return "}"; + case TOK_LT: return "<"; + case TOK_GT: return ">"; + case TOK_SQUARE_OPEN: return "["; + case TOK_SQUARE_CLOSE: return "]"; + case TOK_COMMA: return ","; + case TOK_SEMICOLON: return ";"; + case TOK_COLON: return ":"; + case TOK_DOUBLE_COLON: return ":"; + case TOK_STAR: return "*"; + case TOK_AMP: return "&"; + case TOK_PIPE: return "|"; + + case TOK_FATARROW: return "=>"; // => + case TOK_THINARROW: return "->"; // -> + + case TOK_PLUS: return "+"; + case TOK_DASH: return "-"; + case TOK_EXCLAM: return "!"; + case TOK_PERCENT: return "%"; + case TOK_SLASH: return "/"; + + case TOK_DOT: return "."; + case TOK_DOUBLE_DOT: return "..."; + case TOK_TRIPLE_DOT: return ".."; + + case TOK_EQUAL: return "="; + case TOK_PLUS_EQUAL: return "+="; + case TOK_DASH_EQUAL: return "-"; + case TOK_PERCENT_EQUAL: return "%="; + case TOK_SLASH_EQUAL: return "/="; + case TOK_STAR_EQUAL: return "*="; + case TOK_AMP_EQUAL: return "&="; + case TOK_PIPE_EQUAL: return "|="; + + case TOK_DOUBLE_EQUAL: return "=="; + case TOK_EXCLAM_EQUAL: return "!="; + case TOK_GTE: return ">="; + case TOK_LTE: return "<="; + + case TOK_DOUBLE_AMP: return "&&"; + case TOK_DOUBLE_PIPE: return "||"; + case TOK_DOUBLE_LT: return "<<"; + case TOK_DOUBLE_GT: return ">>"; + case TOK_DOUBLE_LT_EQUAL: return "<="; + case TOK_DOUBLE_GT_EQUAL: return ">="; + + case TOK_DOLLAR: return "$"; + + case TOK_QMARK: return "?"; + case TOK_AT: return "@"; + case TOK_TILDE: return "~"; + case TOK_BACKSLASH: return "\\"; + case TOK_CARET: return "^"; + case TOK_CARET_EQUAL: return "^="; + case TOK_BACKTICK: return "`"; + + // Reserved Words + case TOK_RWORD_PUB: return "pub"; + case TOK_RWORD_PRIV: return "priv"; + case TOK_RWORD_MUT: return "mut"; + case TOK_RWORD_CONST: return "const"; + case TOK_RWORD_STATIC: return "static"; + case TOK_RWORD_UNSAFE: return "unsafe"; + case TOK_RWORD_EXTERN: return "extern"; + + case TOK_RWORD_CRATE: return "crate"; + case TOK_RWORD_MOD: return "mod"; + case TOK_RWORD_STRUCT: return "struct"; + case TOK_RWORD_ENUM: return "enum"; + case TOK_RWORD_TRAIT: return "trait"; + case TOK_RWORD_FN: return "fn"; + case TOK_RWORD_USE: return "use"; + case TOK_RWORD_IMPL: return "impl"; + case TOK_RWORD_TYPE: return "type"; + + case TOK_RWORD_WHERE: return "where"; + case TOK_RWORD_AS: return "as"; + + case TOK_RWORD_LET: return "let"; + case TOK_RWORD_MATCH: return "match"; + case TOK_RWORD_IF: return "if"; + case TOK_RWORD_ELSE: return "else"; + case TOK_RWORD_LOOP: return "loop"; + case TOK_RWORD_WHILE: return "while"; + case TOK_RWORD_FOR: return "for"; + case TOK_RWORD_IN: return "in"; + case TOK_RWORD_DO: return "do"; + + case TOK_RWORD_CONTINUE:return "continue"; + case TOK_RWORD_BREAK: return "break"; + case TOK_RWORD_RETURN: return "return"; + case TOK_RWORD_YIELD: return "yeild"; + case TOK_RWORD_BOX: return "box"; + case TOK_RWORD_REF: return "ref"; + + case TOK_RWORD_FALSE: return "false"; + case TOK_RWORD_TRUE: return "true"; + case TOK_RWORD_SELF: return "self"; + case TOK_RWORD_SUPER: return "super"; + + case TOK_RWORD_PROC: return "proc"; + case TOK_RWORD_MOVE: return "move"; + case TOK_RWORD_ONCE: return "once"; + + case TOK_RWORD_ABSTRACT:return "abstract"; + case TOK_RWORD_FINAL: return "final"; + case TOK_RWORD_PURE: return "pure"; + case TOK_RWORD_OVERRIDE:return "override"; + case TOK_RWORD_VIRTUAL: return "virtual"; + + case TOK_RWORD_ALIGNOF: return "alignof"; + case TOK_RWORD_OFFSETOF:return "offsetof"; + case TOK_RWORD_SIZEOF: return "sizeof"; + case TOK_RWORD_TYPEOF: return "typeof"; + + case TOK_RWORD_BE: return "be"; + case TOK_RWORD_UNSIZED: return "unsized"; + } + throw ParseError::BugCheck("Reached end of Token::to_str"); +} + void operator%(Serialiser& s, enum eTokenType c) { s << Token::typestr(c); } diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp index a32a569b..aa5ed623 100644 --- a/src/parse/lex.hpp +++ b/src/parse/lex.hpp @@ -63,7 +63,27 @@ public: enum eCoreType datatype() const { return m_datatype; } uint64_t intval() const { return m_intval; } double floatval() const { return m_floatval; } + bool operator==(const Token& r) const { + if(type() != r.type()) + return false; + switch(type()) + { + case TOK_STRING: + case TOK_IDENT: + case TOK_LIFETIME: + return str() == r.str(); + case TOK_INTEGER: + return intval() == r.intval() && datatype() == r.datatype(); + case TOK_FLOAT: + return floatval() == r.floatval() && datatype() == r.datatype(); + default: + return true; + } + } + bool operator!=(const Token& r) { return !(*this == r); } + ::std::string to_str() const; + void set_pos(Position pos) { m_pos = pos; } const Position& get_pos() const { return m_pos; } diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index 28e7ebaa..6d26cd4a 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -256,7 +256,8 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path) CHECK_TOK(tok, TOK_COLON); pat = Parse_Pattern(lex); } - // TODO: Append + + subpats.push_back( ::std::make_pair(::std::move(field), ::std::move(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 759c65ac..39776689 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -825,6 +825,18 @@ void Parse_Use(TokenStream& lex, ::std::function Token tok; AST::Path path = AST::Path( AST::Path::TagAbsolute() ); + // Leading :: is allowed and ignored for the $crate feature + if( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON ) { + GET_TOK(tok, lex); + // HACK! mrustc emits $crate as `::"crate-name"` + if( LOOK_AHEAD(lex) == TOK_STRING ) + { + GET_CHECK_TOK(tok, lex, TOK_STRING); + path.set_crate(tok.str()); + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); + } + } + switch( GET_TOK(tok, lex) ) { case TOK_RWORD_SELF: -- cgit v1.2.3