1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/*
*/
#include "crate.hpp"
#include "ast.hpp"
#include "../parse/parseerror.hpp"
#include "../expand/cfg.hpp"
#include <hir/hir.hpp> // HIR::Crate
#include <hir/main_bindings.hpp> // HIR_Deserialise
namespace {
bool check_item_cfg(const ::AST::MetaItems& attrs)
{
for(const auto& at : attrs.m_items) {
if( at.name() == "cfg" && !check_cfg(attrs.m_span, at) ) {
return false;
}
}
return true;
}
void iterate_module(::AST::Module& mod, ::std::function<void(::AST::Module& mod)> fcn)
{
fcn(mod);
for( auto& sm : mod.items() )
{
TU_IFLET(::AST::Item, sm.data, Module, e,
if( check_item_cfg(sm.data.attrs) )
{
iterate_module(e, fcn);
}
)
}
}
}
namespace AST {
Crate::Crate():
m_root_module(::AST::Path("",{})),
m_load_std(LOAD_STD)
{
}
void Crate::load_externs()
{
auto cb = [this](Module& mod) {
for( const auto& it : mod.items() )
{
TU_IFLET(AST::Item, it.data, Crate, c,
const auto& name = c.name;
if( check_item_cfg(it.data.attrs) )
{
load_extern_crate( it.data.span, name );
}
)
}
};
iterate_module(m_root_module, cb);
// Check for no_std or no_core, and load libstd/libcore
// - Duplicates some of the logic in "Expand", but also helps keep crate loading separate to most of expand
// NOTE: Not all crates are loaded here, any crates loaded by macro invocations will be done during expand.
bool no_std = false;
bool no_core = false;
for( const auto& a : this->m_attrs.m_items )
{
if( a.name() == "no_std" )
no_std = true;
if( a.name() == "no_core" )
no_core = true;
if( a.name() == "cfg_attr" && a.items().size() == 2 ) {
if( check_cfg(this->m_attrs.m_span, a.items().at(0)) )
{
const auto& a2 = a.items().at(1);
if( a2.name() == "no_std" )
no_std = true;
if( a2.name() == "no_core" )
no_core = true;
}
}
}
if( no_core ) {
// Don't load anything
}
else if( no_std ) {
this->load_extern_crate(Span(), "core");
}
else {
this->load_extern_crate(Span(), "std");
}
}
void Crate::load_extern_crate(Span sp, const ::std::string& name)
{
DEBUG("Loading crate '" << name << "'");
// TODO: Search a list of load paths for the crate
::std::string path = "output/lib"+name+".hir";
if( !::std::ifstream(path).good() ) {
ERROR(sp, E0000, "Unable to locate crate '" << name << "'");
}
m_extern_crates.insert(::std::make_pair( name, ExternCrate { name, path } ));
}
ExternCrate::ExternCrate(const ::std::string& name, const ::std::string& path):
m_name(name)
{
TRACE_FUNCTION_F("name=" << name << ", path='" << path << "'");
m_hir = HIR_Deserialise(path, name);
m_hir->post_load_update(name);
// TODO: Load referenced crates
}
void ExternCrate::with_all_macros(::std::function<void(const ::std::string& , const MacroRules&)> cb) const
{
for(const auto& m : m_hir->m_exported_macros)
{
cb(m.first, *m.second);
}
}
const MacroRules* ExternCrate::find_macro_rules(const ::std::string& name) const
{
auto i = m_hir->m_exported_macros.find(name);
if(i != m_hir->m_exported_macros.end())
return &*i->second;
return nullptr;
}
} // namespace AST
|