From 5d29fdaa42c638e9420bd3111fb15f3594342354 Mon Sep 17 00:00:00 2001 From: "John Hodge (bugs)" Date: Sun, 14 Dec 2014 10:03:30 +0800 Subject: Parse working, starting on conversion --- ast/ast.cpp | 6 + ast/ast.hpp | 49 ++++++++ convert/resolve.cpp | 38 ++++++ main.cpp | 15 ++- mrustc.cbp | 1 + parse/expr.cpp | 17 ++- parse/lex.cpp | 7 +- parse/root.cpp | 345 ++++++++++++++++++++++++++++++++-------------------- types.hpp | 7 +- 9 files changed, 344 insertions(+), 141 deletions(-) create mode 100644 convert/resolve.cpp diff --git a/ast/ast.cpp b/ast/ast.cpp index ffe485cb..575d3c60 100644 --- a/ast/ast.cpp +++ b/ast/ast.cpp @@ -3,6 +3,7 @@ #include "ast.hpp" #include "../types.hpp" #include +#include "../parse/parseerror.hpp" namespace AST { @@ -69,6 +70,11 @@ void Module::add_impl(Impl impl) { } +void Expr::visit_nodes(const NodeVisitor& v) +{ + throw ParseError::Todo("Expr::visit_nodes"); +} + ExprNode::ExprNode() { diff --git a/ast/ast.hpp b/ast/ast.hpp index f05747ac..194c79b8 100644 --- a/ast/ast.hpp +++ b/ast/ast.hpp @@ -5,11 +5,29 @@ #include #include #include "../coretypes.hpp" +#include class TypeRef; namespace AST { +class MetaItem +{ + ::std::string m_name; + ::std::vector m_items; + ::std::string m_str_val; +public: + MetaItem(::std::string name): + m_name(name) + { + } + MetaItem(::std::string name, ::std::vector items): + m_name(name), + m_items(items) + { + } +}; + class ExprNode; class TypeParam @@ -120,15 +138,26 @@ public: ExprNode(TagBinOp, BinOpType type, ExprNode left, ExprNode right); }; +class NodeVisitor +{ +public: + virtual void visit(ExprNode::TagBlock, ExprNode& node) {} + virtual void visit(ExprNode::TagNamedValue, ExprNode& node) {} +}; + class Expr { public: Expr() {} Expr(ExprNode node) {} + + void visit_nodes(const NodeVisitor& v); }; class Function { + Expr m_code; + ::std::auto_ptr m_rettype; public: enum Class @@ -140,6 +169,11 @@ public: }; Function(::std::string name, TypeParams params, Class fcn_class, TypeRef ret_type, ::std::vector args, Expr code); + + Expr& code() { return m_code; } + const Expr code() const { return m_code; } + + TypeRef& rettype() { return *m_rettype; } }; class Impl @@ -152,6 +186,7 @@ public: class Module { + ::std::vector m_functions; public: void add_alias(bool is_public, Path path) {} void add_constant(bool is_public, ::std::string name, TypeRef type, Expr val); @@ -161,6 +196,20 @@ public: void add_impl(Impl impl); }; +class Crate +{ + Module m_root_module; +public: + Crate(Module root_module): + m_root_module(root_module) + { + } + + typedef void fcn_visitor_t(const AST::Crate& crate, Function& fcn); + + void iterate_functions( fcn_visitor_t* visitor ); +}; + } #endif // AST_HPP_INCLUDED diff --git a/convert/resolve.cpp b/convert/resolve.cpp new file mode 100644 index 00000000..23d49726 --- /dev/null +++ b/convert/resolve.cpp @@ -0,0 +1,38 @@ + +#include "../ast/ast.hpp" + +// Path resolution checking +void ResolvePaths(AST::Crate& crate); +void ResolvePaths_HandleFunction(const AST::Crate& crate, AST::Function& fcn); + +class CResolvePaths_NodeVisitor: + public AST::NodeVisitor +{ + const AST::Crate& m_crate; +public: + CResolvePaths_NodeVisitor(const AST::Crate& crate): + m_crate(crate) + { + } + + void visit(AST::ExprNode::TagNamedValue, AST::ExprNode& node) { + // TODO: Convert into a real absolute path + } +}; + +void ResolvePaths_HandleFunction(const AST::Crate& crate, AST::Function& fcn) +{ + fcn.code().visit_nodes( CResolvePaths_NodeVisitor(crate) ); + + ResolvePaths_Type(fcn.rettype()); + + FOREACH(arg, fcn.args()) + { + ResolvePaths_Type(arg.type()); + } +} + +void ResolvePaths(AST::Crate& crate) +{ + crate.iterate_functions(ResolvePaths_HandleFunction); +} diff --git a/main.cpp b/main.cpp index 34c7e0a4..f3349257 100644 --- a/main.cpp +++ b/main.cpp @@ -4,13 +4,24 @@ using namespace std; -extern void Parse_Crate(::std::string mainfile); +extern AST::Crate Parse_Crate(::std::string mainfile); +extern void ResolvePaths(AST::Crate& crate); +/// main! int main(int argc, char *argv[]) { try { - Parse_Crate("samples/1.rs"); + AST::Crate crate = Parse_Crate("samples/1.rs"); + + // Resolve names into absolute? + ResolvePaths(crate); + + // Flatten modules into "mangled" set + + // Typecheck / type propagate module (type annotations of all values) + + // Convert structures to C structures / tagged enums } catch(const ParseError::Base& e) { diff --git a/mrustc.cbp b/mrustc.cbp index edc901f1..90fa7330 100644 --- a/mrustc.cbp +++ b/mrustc.cbp @@ -37,6 +37,7 @@ + diff --git a/parse/expr.cpp b/parse/expr.cpp index 29741b85..e632d47f 100644 --- a/parse/expr.cpp +++ b/parse/expr.cpp @@ -60,7 +60,6 @@ AST::Pattern Parse_Pattern(TokenStream& lex) case TOK_DOUBLE_COLON: // 2. Paths are enum/struct names { - lex.putback(tok); path = Parse_Path(lex, true, PATH_GENERIC_EXPR); } switch( GET_TOK(tok, lex) ) @@ -196,6 +195,8 @@ AST::ExprNode Parse_Expr0(TokenStream& lex) return rv; } +/// Parse an 'if' statement +// Note: TOK_RWORD_IF has already been eaten AST::ExprNode Parse_IfStmt(TokenStream& lex) { TRACE_FUNCTION; @@ -210,19 +211,24 @@ AST::ExprNode Parse_IfStmt(TokenStream& lex) cond = Parse_Expr0(lex); } + // Contents ExprNode code = Parse_ExprBlockNode(lex); + // Handle else: ExprNode altcode; if( GET_TOK(tok, lex) == TOK_RWORD_ELSE ) { + // Recurse for 'else if' if( GET_TOK(tok, lex) == TOK_RWORD_IF ) { altcode = Parse_IfStmt(lex); } + // - or get block else { lex.putback(tok); altcode = Parse_ExprBlockNode(lex); } } + // - or nothing else { lex.putback(tok); altcode = ExprNode(); @@ -269,7 +275,6 @@ AST::ExprNode Parse_ExprBlocks(TokenStream& lex) AST::ExprNode _next(TokenStream& lex); \ AST::ExprNode cur(TokenStream& lex) \ { \ - ::std::cout << ">>" << #cur << ::std::endl; \ AST::ExprNode (*next)(TokenStream&) = _next;\ AST::ExprNode rv = next(lex); \ while(true) \ @@ -394,7 +399,7 @@ AST::ExprNode Parse_ExprFC(TokenStream& lex) while(true) { Token tok; - switch((tok = lex.getToken()).type()) + switch(GET_TOK(tok, lex)) { case TOK_PAREN_OPEN: // Function call @@ -474,8 +479,10 @@ AST::ExprNode Parse_ExprVal(TokenStream& lex) path.append( AST::PathNode("self", ::std::vector()) ); return ExprNode(ExprNode::TagNamedValue(), path); } - case TOK_PAREN_OPEN: - return Parse_Expr0(lex); + case TOK_PAREN_OPEN: { + ExprNode rv = Parse_Expr0(lex); + GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + return rv; } case TOK_MACRO: { // Need to create a token tree, pass to the macro, then pass the result of that to Parse_Expr0 MacroExpander expanded_macro = Macro_Invoke(tok.str().c_str(), Parse_TT(lex)); diff --git a/parse/lex.cpp b/parse/lex.cpp index e80f42ca..79db4603 100644 --- a/parse/lex.cpp +++ b/parse/lex.cpp @@ -244,7 +244,11 @@ Token Lexer::getToken() } } else { - throw ParseError::Todo("Lex decimal numbers"); + while( isdigit(ch) ) { + val *= val * 10; + val += ch - '0'; + ch = this->getc(); + } } if(ch == 'u' || ch == 'i') { @@ -255,6 +259,7 @@ Token Lexer::getToken() throw ParseError::Todo("Lex floats"); } else { + this->putback(); return Token(val, CORETYPE_ANY); } } diff --git a/parse/root.cpp b/parse/root.cpp index f123eee6..c9fc0401 100644 --- a/parse/root.cpp +++ b/parse/root.cpp @@ -17,7 +17,13 @@ unsigned int TraceLog::depth = 0; do { types.push_back( Parse_Type(lex) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); - CHECK_TOK(tok, TOK_GT); + // HACK: Split >> into > + if(tok.type() == TOK_DOUBLE_GT) { + lex.putback(Token(TOK_GT)); + } + else { + CHECK_TOK(tok, TOK_GT); + } return types; } @@ -326,29 +332,215 @@ AST::Function Parse_FunctionDef(TokenStream& lex) return AST::Function(name, params, fcn_class, ret_type, args, code); } -AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) +void Parse_Struct(AST::Module& mod, TokenStream& lex, const bool is_public, const ::std::vector meta_items) +{ + Token tok; + + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + 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(); + if(tok.type() == TOK_RWORD_WHERE) + { + Parse_TypeConds(lex, params); + tok = lex.getToken(); + } + } + if(tok.type() == TOK_PAREN_OPEN) + { + TypeRef inner = Parse_Type(lex); + tok = lex.getToken(); + if(tok.type() != TOK_PAREN_CLOSE) + { + ::std::vector refs; + refs.push_back(inner); + while( (tok = lex.getToken()).type() == TOK_COMMA ) + { + refs.push_back( Parse_Type(lex) ); + } + if( tok.type() != TOK_PAREN_CLOSE ) + throw ParseError::Unexpected(tok, Token(TOK_PAREN_CLOSE)); + inner = TypeRef(TypeRef::TagTuple(), refs); + } + throw ParseError::Todo("tuple struct"); + } + else if(tok.type() == TOK_SEMICOLON) + { + throw ParseError::Todo("unit-like struct"); + } + else if(tok.type() == TOK_BRACE_OPEN) + { + ::std::vector items; + while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE ) + { + CHECK_TOK(tok, TOK_IDENT); + ::std::string name = tok.str(); + GET_CHECK_TOK(tok, lex, TOK_COLON); + TypeRef type = Parse_Type(lex); + items.push_back( ::std::make_pair(name, type) ); + tok = lex.getToken(); + if(tok.type() == TOK_BRACE_CLOSE) + break; + if(tok.type() != TOK_COMMA) + throw ParseError::Unexpected(tok, Token(TOK_COMMA)); + } + mod.add_struct(is_public, name, params, items); + } + else + { + throw ParseError::Unexpected(tok); + } +} + +/// Parse a meta-item declaration (either #![ or #[) +AST::MetaItem Parse_MetaItem(TokenStream& lex) +{ + Token tok; + GET_CHECK_TOK(tok, lex, TOK_IDENT); + ::std::string name = tok.str(); + switch(GET_TOK(tok, lex)) + { + case TOK_EQUAL: + throw ParseError::Todo("Meta item key-value"); + case TOK_PAREN_OPEN: { + ::std::vector items; + do { + items.push_back(Parse_MetaItem(lex)); + } while(GET_TOK(tok, lex) == TOK_COMMA); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + return AST::MetaItem(name, items); } + default: + lex.putback(tok); + return AST::MetaItem(name); + } +} + +AST::Impl Parse_Impl(TokenStream& lex) +{ + Token tok; + + AST::TypeParams params; + // 1. (optional) type parameters + if( GET_TOK(tok, lex) == TOK_LT ) + { + params = Parse_TypeParams(lex); + GET_CHECK_TOK(tok, lex, TOK_GT); + } + else { + lex.putback(tok); + } + // 2. Either a trait name (with type params), or the type to impl + // - Don't care which at this stage + TypeRef trait_type; + TypeRef impl_type = Parse_Type(lex); + if( GET_TOK(tok, lex) == TOK_RWORD_FOR ) + { + // Implementing a trait for another type, get the target type + trait_type = impl_type; + impl_type = Parse_Type(lex); + } + else { + lex.putback(tok); + } + // Where clause + if( GET_TOK(tok, lex) == TOK_RWORD_WHERE ) + { + Parse_TypeConds(lex, params); + } + else { + lex.putback(tok); + } + GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); + + AST::Impl impl(impl_type, trait_type); + + // A sequence of method implementations + while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) + { + bool is_public = false; + if(tok.type() == TOK_RWORD_PUB) { + is_public = true; + GET_TOK(tok, lex); + } + switch(tok.type()) + { + case TOK_RWORD_FN: + impl.add_function(is_public, Parse_FunctionDef(lex)); + break; + + default: + throw ParseError::Unexpected(tok); + } + } + + return impl; +} + +AST::Module Parse_ModRoot(const ::std::string& path, Preproc& lex) { + Token tok; + AST::Module mod; + + // Attributes on module/crate (will continue loop) + while( GET_TOK(tok, lex) == TOK_CATTR_OPEN ) + { + AST::MetaItem item = Parse_MetaItem(lex); + GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); + + throw ParseError::Todo("Parent attrs"); + //mod_attrs.push_back( item ); + } + lex.putback(tok); + + // TODO: Handle known parent attribs if operating on crate root + for(;;) { - bool is_public = false; - Token tok = lex.getToken(); - switch(tok.type()) + // Check 1 - End of module (either via a closing brace, or EOF) + switch(GET_TOK(tok, lex)) { case TOK_BRACE_CLOSE: - if( is_own_file ) + if( path.size() > 0 ) throw ParseError::Unexpected(tok); return mod; case TOK_EOF: - if( !is_own_file ) + if( path.size() == 0 ) throw ParseError::Unexpected(tok); return mod; - - case TOK_RWORD_PUB: - assert(!is_public); - is_public = false; + default: + lex.putback(tok); break; + } + + // Attributes on the following item + ::std::vector meta_items; + while( GET_TOK(tok, lex) == TOK_ATTR_OPEN ) + { + meta_items.push_back( Parse_MetaItem(lex) ); + GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); + } + lex.putback(tok); + + // Module visibility + bool is_public = false; + if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) + { + is_public = true; + } + else + { + lex.putback(tok); + } + // The actual item! + switch( GET_TOK(tok, lex) ) + { case TOK_RWORD_USE: // TODO: Do manual path parsing here, as use has its own special set of quirks mod.add_alias( is_public, Parse_Path(lex, true, PATH_GENERIC_NONE) ); @@ -390,137 +582,28 @@ AST::Module Parse_ModRoot(bool is_own_file, Preproc& lex) case TOK_RWORD_FN: mod.add_function(is_public, Parse_FunctionDef(lex)); break; - case TOK_RWORD_STRUCT: { - GET_CHECK_TOK(tok, lex, TOK_IDENT); - ::std::string name = tok.str(); - 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(); - if(tok.type() == TOK_RWORD_WHERE) - { - Parse_TypeConds(lex, params); - tok = lex.getToken(); - } - } - if(tok.type() == TOK_PAREN_OPEN) - { - TypeRef inner = Parse_Type(lex); - tok = lex.getToken(); - if(tok.type() != TOK_PAREN_CLOSE) - { - ::std::vector refs; - refs.push_back(inner); - while( (tok = lex.getToken()).type() == TOK_COMMA ) - { - refs.push_back( Parse_Type(lex) ); - } - if( tok.type() != TOK_PAREN_CLOSE ) - throw ParseError::Unexpected(tok, Token(TOK_PAREN_CLOSE)); - inner = TypeRef(TypeRef::TagTuple(), refs); - } - throw ParseError::Todo("tuple struct"); - } - else if(tok.type() == TOK_SEMICOLON) - { - throw ParseError::Todo("unit-like struct"); - } - else if(tok.type() == TOK_BRACE_OPEN) - { - ::std::vector items; - while( (tok = lex.getToken()).type() != TOK_BRACE_CLOSE ) - { - CHECK_TOK(tok, TOK_IDENT); - ::std::string name = tok.str(); - GET_CHECK_TOK(tok, lex, TOK_COLON); - TypeRef type = Parse_Type(lex); - items.push_back( ::std::make_pair(name, type) ); - tok = lex.getToken(); - if(tok.type() == TOK_BRACE_CLOSE) - break; - if(tok.type() != TOK_COMMA) - throw ParseError::Unexpected(tok, Token(TOK_COMMA)); - } - mod.add_struct(is_public, name, params, items); - } - else - { - throw ParseError::Unexpected(tok); - } - 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_IMPL: { - AST::TypeParams params; - // 1. (optional) type parameters - if( GET_TOK(tok, lex) == TOK_LT ) - { - params = Parse_TypeParams(lex); - GET_CHECK_TOK(tok, lex, TOK_GT); - } - else { - lex.putback(tok); - } - // 2. Either a trait name (with type params), or the type to impl - // - Don't care which at this stage - TypeRef trait_type; - TypeRef impl_type = Parse_Type(lex); - if( GET_TOK(tok, lex) == TOK_RWORD_FOR ) - { - // Implementing a trait for another type, get the target type - trait_type = impl_type; - impl_type = Parse_Type(lex); - } - else { - lex.putback(tok); - } - // Where clause - if( GET_TOK(tok, lex) == TOK_RWORD_WHERE ) - { - Parse_TypeConds(lex, params); - } - else { - lex.putback(tok); - } - GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - - AST::Impl impl(impl_type, trait_type); - - // A sequence of method implementations - while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) - { - bool is_public = false; - if(tok.type() == TOK_RWORD_PUB) { - is_public = true; - GET_TOK(tok, lex); - } - switch(tok.type()) - { - case TOK_RWORD_FN: - impl.add_function(is_public, Parse_FunctionDef(lex)); - break; - - default: - throw ParseError::Unexpected(tok); - } - } - - mod.add_impl(impl); - 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"); + default: throw ParseError::Unexpected(tok); } } } -void Parse_Crate(::std::string mainfile) +AST::Crate Parse_Crate(::std::string mainfile) { Preproc lex(mainfile); - AST::Module rootmodule = Parse_ModRoot(true, lex); + return AST::Crate( Parse_ModRoot(mainfile, lex) ); } diff --git a/types.hpp b/types.hpp index ef540a93..02355d66 100644 --- a/types.hpp +++ b/types.hpp @@ -3,7 +3,10 @@ #include #include "coretypes.hpp" -#include "ast/ast.hpp" + +namespace AST { +class Expr; +} class TypeRef { @@ -22,7 +25,7 @@ public: struct TagPointer {}; TypeRef(TagPointer _, bool is_mut, TypeRef inner_type) {} struct TagSizedArray {}; - TypeRef(TagSizedArray _, TypeRef inner_type, AST::Expr size) {} + TypeRef(TagSizedArray _, TypeRef inner_type, AST::Expr size); struct TagUnsizedArray {}; TypeRef(TagUnsizedArray _, TypeRef inner_type) {} -- cgit v1.2.3