diff options
author | John Hodge <tpg@mutabah.net> | 2016-10-26 14:47:57 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-10-26 14:47:57 +0800 |
commit | c49fabe8726e12fef6e8b61c7e2c3b11c7cc2b96 (patch) | |
tree | 4eadad27a30362c3ebbbb8253382f6ce97245748 /src | |
parent | 8a592b7cac6fc17b0ff0c0331b4d4db125ba0337 (diff) | |
download | mrust-c49fabe8726e12fef6e8b61c7e2c3b11c7cc2b96.tar.gz |
Expand - env! and option_env!
Diffstat (limited to 'src')
-rw-r--r-- | src/expand/env.cpp | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/expand/env.cpp b/src/expand/env.cpp new file mode 100644 index 00000000..989fbb7a --- /dev/null +++ b/src/expand/env.cpp @@ -0,0 +1,76 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * expand/env.cpp + * - env! and option_env! macros + */ +#include <synext_macro.hpp> +#include <parse/common.hpp> +#include <ast/expr.hpp> // ExprNode_* +#include <synext.hpp> // for Expand_BareExpr + +namespace { + // Read a string out of the input stream + ::std::string get_string(const Span& sp, const AST::Crate& crate, AST::Module& mod, const TokenTree& tt) { + auto lex = TTStream(tt); + + auto n = Parse_ExprVal(lex); + ASSERT_BUG(sp, n, "No expression returned"); + if( lex.lookahead(0) != TOK_EOF ) { + ERROR(sp, E0000, "Unexpected token after string literal - " << lex.getToken()); + } + Expand_BareExpr(crate, mod, n); + + auto* string_np = dynamic_cast<AST::ExprNode_String*>(&*n); + if( !string_np ) { + ERROR(sp, E0000, "Expected a string literal - got " << *n); + } + return mv$( string_np->m_value ); + } +} + +class CExpanderEnv: + public ExpandProcMacro +{ + ::std::unique_ptr<TokenStream> expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + { + if( ident != "" ) + ERROR(sp, E0000, "env! doesn't take an ident"); + ::std::string varname = get_string(sp, crate, mod, tt); + + const char* var_val_cstr = getenv(varname.c_str()); + if( !var_val_cstr ) { + ERROR(sp, E0000, "Environment variable '" << varname << "' not defined"); + } + return box$( TTStreamO(TokenTree(Token(TOK_STRING, var_val_cstr))) ); + } +}; + +class CExpanderOptionEnv: + public ExpandProcMacro +{ + ::std::unique_ptr<TokenStream> expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override + { + if( ident != "" ) + ERROR(sp, E0000, "option_env! doesn't take an ident"); + ::std::string varname = get_string(sp, crate, mod, tt); + + const char* var_val_cstr = getenv(varname.c_str()); + if( !var_val_cstr ) { + return box$( TTStreamO(TokenTree(Token(TOK_IDENT, "None"))) ); + } + else { + ::std::vector< TokenTree> rv; + rv.reserve(4); + rv.push_back( Token(TOK_IDENT, "Some") ); + rv.push_back( Token(TOK_PAREN_OPEN) ); + rv.push_back( Token(TOK_STRING, var_val_cstr) ); + rv.push_back( Token(TOK_PAREN_CLOSE) ); + return box$( TTStreamO(TokenTree( mv$(rv) )) ); + } + } +}; + +STATIC_MACRO("env", CExpanderEnv); +STATIC_MACRO("option_env", CExpanderOptionEnv); |