summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-10-26 14:47:57 +0800
committerJohn Hodge <tpg@mutabah.net>2016-10-26 14:47:57 +0800
commitc49fabe8726e12fef6e8b61c7e2c3b11c7cc2b96 (patch)
tree4eadad27a30362c3ebbbb8253382f6ce97245748 /src
parent8a592b7cac6fc17b0ff0c0331b4d4db125ba0337 (diff)
downloadmrust-c49fabe8726e12fef6e8b61c7e2c3b11c7cc2b96.tar.gz
Expand - env! and option_env!
Diffstat (limited to 'src')
-rw-r--r--src/expand/env.cpp76
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);