From 7d04ce9d4c945cedf08ff2a7fa0af49ea4e6e1b0 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Thu, 15 Jan 2015 16:40:49 +0800 Subject: Working on parsing 'std' from a file (instead of hardcoding) --- src/ast/ast.cpp | 16 +++--- src/ast/ast.hpp | 7 +-- src/convert/resolve.cpp | 2 + src/main.cpp | 71 +++++++++++++++++++++++++- src/parse/lex.cpp | 2 +- src/parse/root.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 206 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index c2686787..a9336c31 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -49,7 +49,7 @@ SERIALISE_TYPE(Impl::, "AST_Impl", { }) Crate::Crate(): - m_root_module(*this, ""), + m_root_module(""), m_load_std(true) { } @@ -105,7 +105,7 @@ ExternCrate ExternCrate_std() // === Add modules === // - option - Module option(crate.crate(), "option"); + Module option("option"); option.add_enum(true, "Option", Enum( { TypeParam(false, "T"), @@ -117,7 +117,7 @@ ExternCrate ExternCrate_std() )); std_mod.add_submod(true, ::std::move(option)); // - result - Module result(crate.crate(), "result"); + Module result("result"); result.add_enum(true, "Result", Enum( { TypeParam(false, "R"), @@ -130,7 +130,7 @@ ExternCrate ExternCrate_std() )); std_mod.add_submod(true, ::std::move(result)); // - io - Module io(crate.crate(), "io"); + Module io("io"); io.add_typealias(true, "IoResult", TypeAlias( { TypeParam(false, "T") }, TypeRef( Path("std", { @@ -141,18 +141,20 @@ ExternCrate ExternCrate_std() std_mod.add_submod(true, ::std::move(io)); // - iter { - Module iter(crate.crate(), "iter"); + Module iter("iter"); + #if 0 { Trait iterator; iterator.add_type("Item", TypeRef()); //iterator.add_function("next", Function({}, Function::CLASS_REFMETHOD, "Option<::Item>", {}, Expr()); iter.add_trait(true, "Iterator", ::std::move(iterator)); } + #endif std_mod.add_submod(true, ::std::move(iter)); } // - prelude - Module prelude(crate.crate(), "prelude"); + Module prelude("prelude"); // Re-exports #define USE(mod, name, ...) do{ Path p("std", {__VA_ARGS__}); mod.add_alias(true, ::std::move(p), name); } while(0) USE(prelude, "Option", PathNode("option", {}), PathNode("Option",{}) ); @@ -178,8 +180,6 @@ SERIALISE_TYPE(Module::, "AST_Module", { void Module::add_ext_crate(::std::string ext_name, ::std::string int_name) { DEBUG("add_ext_crate(\"" << ext_name << "\" as " << int_name << ")"); - m_crate.load_extern_crate(ext_name); - m_extern_crates.push_back( Item< ::std::string>( ::std::move(int_name), ::std::move(ext_name), false ) ); } void Module::iterate_functions(fcn_visitor_t *visitor, const Crate& crate) diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 77eb4fe3..f04c5ab0 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -267,7 +267,6 @@ class Module: typedef ::std::vector< Item > itemlist_enum_t; typedef ::std::vector< Item > itemlist_struct_t; - Crate& m_crate; ::std::string m_name; ::std::vector m_attrs; itemlist_fcn_t m_functions; @@ -282,8 +281,7 @@ class Module: itemlist_struct_t m_structs; ::std::vector m_impls; public: - Module(Crate& crate, ::std::string name): - m_crate(crate), + Module(::std::string name): m_name(name) { } @@ -322,9 +320,6 @@ public: void iterate_functions(fcn_visitor_t* visitor, const Crate& crate); - Crate& crate() { return m_crate; } - const Crate& crate() const { return m_crate; } - const ::std::string& name() const { return m_name; } ::std::vector& attrs() { return m_attrs; } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index bba534a3..1ff0daab 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -402,6 +402,8 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod } //throw ParseError::Todo("ResolvePaths_HandleModule - wildcard use on module"); break; + case AST::Path::ALIAS: + throw ParseError::Todo("ResolvePaths_HandleModule_Use - ALIAS"); case AST::Path::ENUM: throw ParseError::Todo("ResolvePaths_HandleModule_Use - ENUM"); case AST::Path::ENUM_VAR: diff --git a/src/main.cpp b/src/main.cpp index f35f93ce..55b6f9d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "parse/parseerror.hpp" #include "ast/ast.hpp" #include +#include extern AST::Crate Parse_Crate(::std::string mainfile); extern void ResolvePaths(AST::Crate& crate); @@ -12,11 +13,71 @@ extern AST::Flat Convert_Flatten(const AST::Crate& crate); /// main! int main(int argc, char *argv[]) { + const char *infile = NULL; + ::std::string outfile; + const char *crate_path = "."; + const char *emit_type = "c"; + for( int i = 1; i < argc; i ++ ) + { + const char* arg = argv[i]; + + if( arg[0] != '-' ) + { + infile = arg; + } + else if( arg[1] != '-' ) + { + arg ++; // eat '-' + for( ; *arg; arg ++ ) + { + switch(*arg) + { + // "-o " : Set output file + case 'o': + if( i == argc - 1 ) { + // TODO: BAIL! + return 1; + } + outfile = argv[++i]; + break; + default: + return 1; + } + } + } + else + { + if( strcmp(arg, "--crate-path") == 0 ) { + if( i == argc - 1 ) { + // TODO: BAIL! + return 1; + } + crate_path = argv[++i]; + } + else if( strcmp(arg, "--emit") == 0 ) { + if( i == argc - 1 ) { + // TODO: BAIL! + return 1; + } + emit_type = argv[++i]; + } + else { + return 1; + } + } + } + + if( outfile == "" ) + { + outfile = infile; + outfile += ".o"; + } + Serialiser_TextTree s_tt(::std::cout); Serialiser& s = s_tt; try { - AST::Crate crate = Parse_Crate("samples/1.rs"); + AST::Crate crate = Parse_Crate(infile); s << crate; @@ -26,6 +87,13 @@ int main(int argc, char *argv[]) // Typecheck / type propagate module (type annotations of all values) + if( strcmp(emit_type, "ast") == 0 ) + { + ::std::ofstream os(outfile); + Serialiser_TextTree os_tt(os); + ((Serialiser&)os_tt) << crate; + return 0; + } // Flatten modules into "mangled" set AST::Flat flat_crate = Convert_Flatten(crate); @@ -35,6 +103,7 @@ int main(int argc, char *argv[]) catch(const ParseError::Base& e) { ::std::cerr << "Parser Error: " << e.what() << ::std::endl; + return 2; } return 0; } diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index f893f26c..9655df0a 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -140,8 +140,8 @@ static const struct { TOKENT("static", TOK_RWORD_STATIC), TOKENT("struct", TOK_RWORD_STRUCT), TOKENT("super", TOK_RWORD_SUPER), - TOKENT("true", TOK_RWORD_TRUE), TOKENT("trait", TOK_RWORD_TRAIT), + TOKENT("true", TOK_RWORD_TRUE), TOKENT("type", TOK_RWORD_TYPE), TOKENT("typeof", TOK_RWORD_TYPEOF), TOKENT("unsafe", TOK_RWORD_UNSAFE), diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 6be74e76..10eeacaf 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -328,8 +328,35 @@ AST::Function Parse_FunctionDef(TokenStream& lex) return AST::Function(params, fcn_class, ret_type, args, code); } +AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const ::std::vector meta_items) +{ + TRACE_FUNCTION; + + Token tok; + + // Params + tok = lex.getToken(); + AST::TypeParams params; + if( tok.type() == TOK_LT ) + { + params = Parse_TypeParams(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + tok = lex.getToken(); + } + + CHECK_TOK(tok, TOK_EQUAL); + + // Type + TypeRef type = Parse_Type(lex); + GET_CHECK_TOK(tok, lex, TOK_SEMICOLON); + + return AST::TypeAlias( ::std::move(params), ::std::move(type) ); +} + void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, const ::std::vector meta_items) { + TRACE_FUNCTION; + Token tok; GET_CHECK_TOK(tok, lex, TOK_IDENT); @@ -393,6 +420,57 @@ void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, cons } } +AST::Enum Parse_EnumDef(TokenStream& lex, const ::std::vector meta_items) +{ + TRACE_FUNCTION; + + Token tok; + + tok = lex.getToken(); + // Type params supporting "where" + AST::TypeParams params; + if( tok.type() == TOK_LT ) + { + params = Parse_TypeParams(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + tok = lex.getToken(); + if(tok.type() == TOK_RWORD_WHERE) + { + Parse_TypeConds(lex, params); + tok = lex.getToken(); + } + } + + // Body + CHECK_TOK(tok, TOK_BRACE_OPEN); + ::std::vector variants; + while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) + { + CHECK_TOK(tok, TOK_IDENT); + ::std::string name = tok.str(); + ::std::vector types; + if( GET_TOK(tok, lex) == TOK_PAREN_OPEN ) + { + // Get type list + // TODO: Handle 'Variant()'? + do + { + types.push_back( Parse_Type(lex) ); + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + GET_TOK(tok, lex); + } + + variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagTuple(), ::std::move(types))) ); + if( tok.type() != TOK_COMMA ) + break; + } + CHECK_TOK(tok, TOK_BRACE_CLOSE); + + + return AST::Enum( ::std::move(params), ::std::move(variants) ); +} + /// Parse a meta-item declaration (either #![ or #[) AST::MetaItem Parse_MetaItem(TokenStream& lex) { @@ -486,6 +564,8 @@ void Parse_Use_Wildcard(const AST::Path& base_path, ::std::function fcn) { + TRACE_FUNCTION; + Token tok; AST::Path path = AST::Path( AST::Path::TagAbsolute() ); @@ -515,8 +595,17 @@ void Parse_Use(Preproc& lex, ::std::function fcn switch( tok.type() ) { case TOK_BRACE_OPEN: - throw ParseError::Todo("Parse_Use - multiples"); - break; + do { + if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) { + fcn(path, path[path.size()-1].name()); + } + else { + CHECK_TOK(tok, TOK_IDENT); + fcn(path + AST::PathNode(tok.str(), {}), tok.str()); + } + } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_BRACE_CLOSE); + return; case TOK_STAR: Parse_Use_Wildcard(path, fcn); // early return - can't have anything else after @@ -545,12 +634,14 @@ void Parse_Use(Preproc& lex, ::std::function fcn fcn(path, name); } -void Parse_ModRoot(Preproc& lex, AST::Module& mod, const ::std::string& path) +void Parse_ModRoot(Preproc& lex, AST::Crate& crate, AST::Module& mod, const ::std::string& path) { + TRACE_FUNCTION; + const bool nested_module = (path.size() == 0); // 'mod name { code }', as opposed to 'mod name;' Token tok; - if( mod.crate().m_load_std ) + if( crate.m_load_std ) { // Import the prelude AST::Path prelude_path = AST::Path(AST::Path::TagAbsolute()); @@ -658,19 +749,42 @@ void Parse_ModRoot(Preproc& lex, AST::Module& mod, const ::std::string& path) ::std::string name = tok.str(); mod.add_function(is_public, name, Parse_FunctionDef(lex)); break; } + case TOK_RWORD_TYPE: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + mod.add_typealias(is_public, name, Parse_TypeAlias(lex, meta_items)); + break; } case TOK_RWORD_STRUCT: Parse_Struct(mod, lex, is_public, meta_items); break; - case TOK_RWORD_ENUM: - throw ParseError::Todo("modroot enum"); + case TOK_RWORD_ENUM: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + mod.add_enum(is_public, name, Parse_EnumDef(lex, meta_items)); + break; } case TOK_RWORD_IMPL: mod.add_impl(Parse_Impl(lex)); break; case TOK_RWORD_TRAIT: throw ParseError::Todo("modroot trait"); - case TOK_RWORD_MOD: - throw ParseError::Todo("sub-modules"); + case TOK_RWORD_MOD: { + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + AST::Module submod(name); + DEBUG("Sub module '"<