diff options
-rw-r--r-- | src/ast/ast.cpp | 36 | ||||
-rw-r--r-- | src/ast/ast.hpp | 80 | ||||
-rw-r--r-- | src/common.hpp | 55 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 128 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/parse/root.cpp | 2 |
6 files changed, 254 insertions, 52 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index d1e8c9fd..48cbdb9d 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -10,7 +10,6 @@ namespace AST { ExternCrate ExternCrate_std();
-
SERIALISE_TYPE(MetaItem::, "AST_MetaItem", {
s << m_name;
s << m_str_val;
@@ -42,12 +41,12 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", { }
-Impl::Impl(TypeRef impl_type, TypeRef trait_type)
-{
-}
-void Impl::add_function(bool is_public, ::std::string name, Function fcn)
-{
-}
+SERIALISE_TYPE(Impl::, "AST_Impl", {
+ s << m_params;
+ s << m_trait;
+ s << m_type;
+ s << m_functions;
+})
Crate::Crate():
m_root_module(*this, ""),
@@ -144,9 +143,6 @@ void Module::add_ext_crate(::std::string ext_name, ::std::string int_name) m_extern_crates.push_back( Item< ::std::string>( ::std::move(int_name), ::std::move(ext_name), false ) );
}
-void Module::add_impl(Impl impl)
-{
-}
void Module::iterate_functions(fcn_visitor_t *visitor, const Crate& crate)
{
for( auto fcn_item : this->m_functions )
@@ -200,10 +196,6 @@ SERIALISE_TYPE(Struct::, "AST_Struct", { s << m_fields;
})
-TypeParam::TypeParam(bool is_lifetime, ::std::string name)
-{
-
-}
void TypeParam::addLifetimeBound(::std::string name)
{
@@ -212,6 +204,22 @@ void TypeParam::addTypeBound(TypeRef type) {
}
+::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp)
+{
+ os << "TypeParam(";
+ switch(tp.m_class)
+ {
+ case TypeParam::LIFETIME: os << "'"; break;
+ case TypeParam::TYPE: os << ""; break;
+ }
+ os << tp.m_name;
+ if( tp.m_trait_bounds.size() )
+ {
+ os << ": [" << tp.m_trait_bounds << "]";
+ }
+ os << ")";
+ return os;
+}
SERIALISE_TYPE(TypeParam::, "AST_TypeParam", {
// TODO: TypeParam
})
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 7a417e4f..f1289940 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -24,11 +24,30 @@ using ::std::move; class TypeParam:
public Serialisable
{
+ enum Class {
+ LIFETIME,
+ TYPE,
+ //INTEGER,
+ };
+ Class m_class;
+ ::std::string m_name;
+ ::std::vector<TypeRef> m_trait_bounds;
public:
- TypeParam(bool is_lifetime, ::std::string name);
+ TypeParam(bool is_lifetime, ::std::string name):
+ m_class( is_lifetime ? LIFETIME : TYPE ),
+ m_name( ::std::move(name) )
+ {}
void addLifetimeBound(::std::string name);
void addTypeBound(TypeRef type);
+ void setDefault(TypeRef type);
+
+ const ::std::string& name() const { return m_name; }
+ bool is_type() const { return m_class == TYPE; }
+ //TypeRef& get_default() const { return m_
+ ::std::vector<TypeRef>& get_bounds() { assert(is_type()); return m_trait_bounds; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp);
SERIALISABLE_PROTOTYPES();
};
@@ -158,21 +177,6 @@ public: SERIALISABLE_PROTOTYPES();
};
-class Impl
-{
-public:
- Impl(TypeRef impl_type, TypeRef trait_type);
-
- void add_function(bool is_public, ::std::string name, Function fcn);
-};
-
-
-class Crate;
-class ExternCrate;
-class Module;
-
-typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Function& fcn);
-
template <typename T>
struct Item:
public Serialisable
@@ -195,6 +199,44 @@ struct Item: })
};
+class Impl:
+ public Serialisable
+{
+ TypeParams m_params;
+ TypeRef m_trait;
+ TypeRef m_type;
+
+ ::std::vector<Item<Function> > m_functions;
+public:
+ Impl(TypeParams params, TypeRef impl_type, TypeRef trait_type):
+ m_params( move(params) ),
+ m_trait( move(trait_type) ),
+ m_type( move(impl_type) )
+ {}
+
+ void add_function(bool is_public, ::std::string name, Function fcn) {
+ m_functions.push_back( Item<Function>( ::std::move(name), ::std::move(fcn), is_public ) );
+ }
+
+ const TypeParams& params() const { return m_params; }
+ const TypeRef& trait() const { return m_trait; }
+ const TypeRef& type() const { return m_type; }
+
+ TypeParams& params() { return m_params; }
+ TypeRef& trait() { return m_trait; }
+ TypeRef& type() { return m_type; }
+ ::std::vector<Item<Function> >& functions() { return m_functions; }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+
+class Crate;
+class ExternCrate;
+class Module;
+
+typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Function& fcn);
+
/// Representation of a parsed (and being converted) function
class Module:
public Serialisable
@@ -218,6 +260,7 @@ class Module: itemlist_static_t m_statics;
itemlist_enum_t m_enums;
itemlist_struct_t m_structs;
+ ::std::vector<Impl> m_impls;
public:
Module(Crate& crate, ::std::string name):
m_crate(crate),
@@ -246,7 +289,9 @@ public: void add_submod(bool is_public, Module mod) {
m_submods.push_back( ::std::make_pair( move(mod), is_public ) );
}
- void add_impl(Impl impl);
+ void add_impl(Impl impl) {
+ m_impls.push_back( ::std::move(impl) );
+ }
void add_attr(MetaItem item) {
m_attrs.push_back(item);
@@ -264,6 +309,7 @@ public: itemlist_mod_t& submods() { return m_submods; }
itemlist_use_t& imports() { return m_imports; }
itemlist_ext_t& extern_crates() { return m_extern_crates; }
+ ::std::vector<Impl>& impls() { return m_impls; }
const ::std::vector<MetaItem>& attrs() const { return m_attrs; }
const itemlist_fcn_t& functions() const { return m_functions; }
diff --git a/src/common.hpp b/src/common.hpp index a7b14fdd..4e3e9be7 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -8,9 +8,64 @@ #include <iostream> #include <vector> +#include <cassert> #define DEBUG(ss) do{ ::std::cerr << __FUNCTION__ << ": " << ss << ::std::endl; } while(0) +namespace rust { + +template<typename T> +class option +{ + bool m_set; + T m_data; +public: + option(T ent): + m_set(true), + m_data( ::std::move(ent) ) + {} + option(): + m_set(false) + {} + + bool is_none() const { return !m_set; } + bool is_some() const { return m_set; } + + const T& unwrap() const { + assert(is_some()); + return m_data; + } +}; +template<typename T> +class option<T&> +{ + T* m_ptr; +public: + option(T& ent): + m_ptr(&ent) + {} + option(): + m_ptr(nullptr) + {} + + bool is_none() const { return m_ptr == nullptr; } + bool is_some() const { return m_ptr != nullptr; } + T& unwrap() const { + assert(is_some()); + return *m_ptr; + } +}; +template<typename T> +option<T> Some(T data) { + return option<T>( ::std::move(data) ); +} +template<typename T> +option<T> None() { + return option<T>( ); +} + +}; + namespace AST { template <typename T> diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 67e0eda6..a696e802 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -11,10 +11,28 @@ class CPathResolver
{
+ struct LocalItem
+ {
+ enum Type {
+ TYPE,
+ VAR,
+ } type;
+ ::std::string name;
+ AST::Path path;
+
+ LocalItem():
+ type(VAR), name()
+ {}
+ LocalItem(Type t, ::std::string name, AST::Path path=AST::Path()):
+ type(t),
+ name( ::std::move(name) ),
+ path( ::std::move(path) )
+ {}
+ };
const AST::Crate& m_crate;
const AST::Module& m_module;
const AST::Path m_module_path;
- ::std::vector< ::std::string > m_locals;
+ ::std::vector< LocalItem > m_locals;
// TODO: Maintain a stack of variable scopes
public:
@@ -34,19 +52,38 @@ public: void push_scope() {
DEBUG("");
- m_locals.push_back( ::std::string() );
+ m_locals.push_back( LocalItem() );
}
void pop_scope() {
DEBUG(m_locals.size() << " items");
for( auto it = m_locals.end(); it-- != m_locals.begin(); )
{
- if( *it == "" ) {
+ if( it->name == "" ) {
m_locals.erase(it, m_locals.end());
return ;
}
}
m_locals.clear();
}
+ void add_local_type(::std::string name) {
+ m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name)) );
+ }
+ void add_local_var(::std::string name) {
+ m_locals.push_back( LocalItem(LocalItem::VAR, ::std::move(name)) );
+ }
+ void add_local_use(::std::string name, AST::Path path) {
+ throw ParseError::Todo("CPathResolver::add_local_use - Determine type of path (type or value)");
+ m_locals.push_back( LocalItem(LocalItem::VAR, ::std::move(name), path) );
+ }
+ ::rust::option<const AST::Path&> lookup_local(LocalItem::Type type, const ::std::string& name) const {
+ for( auto it = m_locals.end(); it -- != m_locals.begin(); )
+ {
+ if( it->type == type && it->name == name ) {
+ return ::rust::option<const AST::Path&>(it->path);
+ }
+ }
+ return ::rust::option<const AST::Path&>();
+ }
};
// Path resolution checking
@@ -122,25 +159,43 @@ void CPathResolver::resolve_path(AST::Path& path, ResolvePathMode mode) const }
else
{
- if( mode == MODE_EXPR && path.size() == 1 && path[0].args().size() == 0 )
+ // If there's a single node, and we're in expresion mode, look for a variable
+ // Otherwise, search for a type
+ bool is_trivial_path = path.size() == 1 && path[0].args().size() == 0;
+ LocalItem::Type search_type = (is_trivial_path && mode == MODE_EXPR ? LocalItem::VAR : LocalItem::TYPE);
+ auto local = lookup_local( search_type, path[0].name() );
+ if( local.is_some() )
{
- // One non-generic component, look in the current function for a variable
- const ::std::string& var = path[0].name();
- DEBUG("varname = " << var);
- auto varslot = m_locals.end();
- for(auto slot = m_locals.begin(); slot != m_locals.end(); ++slot)
+ auto rpath = local.unwrap();
+ DEBUG("Local hit: " << path[0].name() << " = " << rpath);
+
+ // Local import?
+ if( rpath.size() > 0 )
{
- if( *slot == var ) {
- varslot = slot;
- }
+ path = AST::Path::add_tailing(rpath, path);
+ path.resolve( m_crate );
+ return ;
}
- if( varslot != m_locals.end() )
+ // Local variable?
+ // - TODO: What would happen if MODE_EXPR but path isn't a single ident?
+ if( mode == MODE_EXPR && is_trivial_path )
{
- DEBUG("Located slot");
- path = AST::Path(AST::Path::TagLocal(), var);
+ DEBUG("Local variable " << path[0].name());
+ path = AST::Path(AST::Path::TagLocal(), path[0].name());
return ;
}
+
+ // Type parameter, return verbatim?
+ // - TODO: Are extra params/entries valid here?
+ if( mode == MODE_TYPE )
+ {
+ DEBUG("Local type " << path[0].name());
+ return ;
+ }
+
+ // TODO: What about sub-types and methods on type params?
+ // - Invalid afaik, instead Trait::method() is used
}
// Search relative to current module
@@ -165,6 +220,14 @@ void CPathResolver::resolve_path(AST::Path& path, ResolvePathMode mode) const return ;
}
}
+ for( const auto& item : m_module.structs() )
+ {
+ if( item.name == path[0].name() ) {
+ path = m_module_path + path;
+ path.resolve( m_crate );
+ return ;
+ }
+ }
for( const auto& item : m_module.statics() )
{
if( item.name == path[0].name() ) {
@@ -254,7 +317,7 @@ void CPathResolver::handle_pattern(AST::Pattern& pat) }
// Extract bindings and add to namespace
if( pat.binding().size() > 0 )
- m_locals.push_back( pat.binding() );
+ add_local_var(pat.binding());
for( auto& subpat : pat.sub_patterns() )
handle_pattern(subpat);
@@ -275,7 +338,7 @@ void CPathResolver::handle_function(AST::Function& fcn) DEBUG("Code");
for( auto& arg : fcn.args() )
- m_locals.push_back(arg.first);
+ add_local_var(arg.first);
fcn.code().visit_nodes( node_visitor );
pop_scope();
if( m_locals.size() != 0 )
@@ -362,13 +425,42 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod void ResolvePaths_HandleModule(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod)
{
+ CPathResolver pr(crate, mod, modpath);
for( auto& fcn : mod.functions() )
{
- CPathResolver pr(crate, mod, modpath);
DEBUG("Handling function '" << fcn.name << "'");
pr.handle_function(fcn.data);
}
+ for( auto& impl : mod.impls() )
+ {
+ DEBUG("Handling impl<" << impl.params() << "> " << impl.trait() << " for " << impl.type());
+
+ // Params
+ pr.push_scope();
+ for( auto& param : impl.params() )
+ {
+ DEBUG("Param " << param);
+ pr.add_local_type(param.name());
+ for(auto& trait : param.get_bounds())
+ pr.resolve_type(trait);
+ }
+ // Trait
+ pr.resolve_type( impl.trait() );
+ // Type
+ pr.resolve_type( impl.type() );
+
+ // TODO: Associated types
+
+ // Functions
+ for( auto& fcn : impl.functions() )
+ {
+ DEBUG("- Function '" << fcn.name << "'");
+ pr.handle_function(fcn.data);
+ }
+ pr.pop_scope();
+ }
+
for( auto& submod : mod.submods() )
{
DEBUG("Handling submod '" << submod.first.name() << "'");
diff --git a/src/main.cpp b/src/main.cpp index 19841c12..f35f93ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,16 +12,17 @@ extern AST::Flat Convert_Flatten(const AST::Crate& crate); /// main!
int main(int argc, char *argv[])
{
+ Serialiser_TextTree s_tt(::std::cout);
+ Serialiser& s = s_tt;
try
{
AST::Crate crate = Parse_Crate("samples/1.rs");
- Serialiser_TextTree s_tt(::std::cout);
- Serialiser& s = s_tt;
s << crate;
// Resolve names to be absolute names (include references to the relevant struct/global/function)
ResolvePaths(crate);
+ s << crate;
// Typecheck / type propagate module (type annotations of all values)
diff --git a/src/parse/root.cpp b/src/parse/root.cpp index a0b8329f..6be74e76 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -453,7 +453,7 @@ AST::Impl Parse_Impl(TokenStream& lex) }
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
- AST::Impl impl(impl_type, trait_type);
+ AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_type) );
// A sequence of method implementations
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
|