From 17ea6a8317e7bf1c86f150b486892bae7e312c11 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 27 Mar 2015 11:10:49 +0800 Subject: Rework paths bindings to be a separate (printable) structure, add -Werror --- Makefile | 17 ++-- src/ast/ast.cpp | 15 ++-- src/ast/path.cpp | 34 +++----- src/ast/path.hpp | 162 +++++++++++++++++++++++---------------- src/convert/ast_iterate.cpp | 16 ++-- src/convert/render.cpp | 18 ++--- src/convert/resolve.cpp | 14 ++-- src/convert/typecheck_bounds.cpp | 5 +- src/convert/typecheck_expr.cpp | 30 ++++---- src/convert/typecheck_params.cpp | 26 +++---- src/main.cpp | 155 +++++++++++++++++++++---------------- 11 files changed, 272 insertions(+), 220 deletions(-) diff --git a/Makefile b/Makefile index 081bbad6..9bea4a43 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ V ?= @ LINKFLAGS := -g LIBS := -CXXFLAGS := -g -Wall -std=c++11 +CXXFLAGS := -g -Wall -std=c++11 -Werror CPPFLAGS := -I src/include/ SHELL = bash @@ -35,13 +35,16 @@ output/%.ast: samples/%.rs $(BIN) @mkdir -p output/ $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0 -TEST_FILE = ../../../Source/rust/rustc-nightly/src/libcore/lib.rs -test: $(TEST_FILE) $(BIN) output/std.ast output/log.ast output/env_logger.ast output/getopts.ast - mkdir -p output/ +RUSTCSRC := ../../../Source/rust/rustc-nightly/ +output/core.ast: $(RUSTCSRC)src/libcore/lib.rs $(BIN) + @mkdir -p output/ + $(DBG) $(BIN) $< --emit ast -o $@ 2>&1 | tee $@_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0 + + +test: output/core.ast $(BIN) +# output/std.ast output/log.ast output/env_logger.ast output/getopts.ast + @mkdir -p output/ # $(DBG) $(BIN) samples/1.rs --crate-path output/std.ast -o output/test.c 2>&1 | tee output/1_dbg.txt -# $(DBG) $(BIN) ../../BinaryView2/src/main.rs --crate-path output/ -o output/test.c 2>&1 | tee output/1_dbg.txt ; test $${PIPESTATUS[0]} -eq 0 -# $(DBG) $(BIN) ../../RustPorts/LogicCircuit/src/main.rs --crate-path output/ -o output/test.c 2>&1 | tee output/1_dbg.txt ; test $${PIPESTATUS[0]} -eq 0 - $(DBG) $(BIN) $(TEST_FILE) --crate-path output/ -o output/test.c 2>&1 | tee output/1_dbg.txt | tail -n 20 ; test $${PIPESTATUS[0]} -eq 0 $(BIN): $(OBJ) @mkdir -p $(dir $@) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 11632996..efd1e830 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -500,7 +500,8 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves //if( &imp.data == this ) // continue ; // - if( !imp.data.is_bound() ) + const auto& binding = imp.data.binding(); + if( !binding.is_bound() ) { // not yet bound, so run resolution (recursion) DEBUG("Recursively resolving pub wildcard use " << imp.data); @@ -508,13 +509,13 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves throw ParseError::Todo("Path::resolve() wildcard re-export call resolve"); } - switch(imp.data.binding_type()) + switch(binding.type()) { - case AST::Path::UNBOUND: + case AST::PathBinding::UNBOUND: throw ParseError::BugCheck("Wildcard import path not bound"); // - If it's a module, recurse - case AST::Path::MODULE: { - auto rv = imp.data.bound_module().find_item(needle); + case AST::PathBinding::MODULE: { + auto rv = binding.bound_module().find_item(needle); if( rv.type() != Module::ItemRef::ITEM_none ) { // Don't return RV, return the import (so caller can rewrite path if need be) return ItemRef(imp); @@ -522,8 +523,8 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves } break; } // - If it's an enum, search for this name and then pass to resolve - case AST::Path::ENUM: { - auto& vars = imp.data.bound_enum().variants(); + case AST::PathBinding::ENUM: { + auto& vars = binding.bound_enum().variants(); // Damnit C++ "let it = vars.find(|a| a.name == needle);" auto it = ::std::find_if(vars.begin(), vars.end(), [&needle](const EnumVariant& ev) { return ev.m_name == needle; }); diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 9548730e..2cfd6b98 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -151,8 +151,7 @@ void Path::resolve(const Crate& root_crate) // Make a copy of the path, replace params with it, then replace *this? // - Maybe leave that up to other code? if( is_last ) { - m_binding_type = ALIAS; - m_binding.alias_ = &ta; + m_binding = PathBinding(&ta); goto ret; } else { @@ -165,8 +164,7 @@ void Path::resolve(const Crate& root_crate) const auto& fn = item.unwrap_Function(); DEBUG("Found function"); if( is_last ) { - m_binding_type = FUNCTION; - m_binding.func_ = &fn; + m_binding = PathBinding(&fn); goto ret; } else { @@ -179,13 +177,11 @@ void Path::resolve(const Crate& root_crate) const auto& t = item.unwrap_Trait(); DEBUG("Found trait"); if( is_last ) { - m_binding_type = TRAIT; - m_binding.trait_ = &t; + m_binding = PathBinding(&t); goto ret; } else if( is_sec_last ) { - m_binding_type = TRAIT_METHOD; - m_binding.trait_ = &t; + m_binding = PathBinding(PathBinding::TagItem(), &t); goto ret; } else { @@ -282,7 +278,7 @@ void Path::resolve(const Crate& root_crate) } // We only reach here if the path points to a module - bind_module(*mod); + m_binding = PathBinding(mod); ret: if( slice_from > 0 ) { @@ -291,16 +287,10 @@ ret: } return ; } -void Path::bind_module(const Module& mod) -{ - m_binding_type = MODULE; - m_binding.module_ = &mod; -} void Path::bind_enum(const Enum& ent, const ::std::vector& args) { DEBUG("Bound to enum"); - m_binding_type = ENUM; - m_binding.enum_ = &ent; + m_binding = PathBinding(&ent); //if( args.size() > 0 ) //{ // if( args.size() != ent.params().size() ) @@ -328,8 +318,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std //} DEBUG("Bound to enum variant '" << name << "' (#" << idx << ")"); - m_binding_type = ENUM_VAR; - m_binding.enumvar = {&ent, idx}; + m_binding = PathBinding(&ent, idx); } void Path::bind_struct(const Struct& ent, const ::std::vector& args) { @@ -343,19 +332,16 @@ void Path::bind_struct(const Struct& ent, const ::std::vector& args) //} DEBUG("Bound to struct"); - m_binding_type = STRUCT; - m_binding.struct_ = &ent; + m_binding = PathBinding(&ent); } void Path::bind_struct_member(const Struct& ent, const ::std::vector& args, const PathNode& member_node) { DEBUG("Binding to struct item. This needs to be deferred"); - m_binding_type = STRUCT_METHOD; - m_binding.struct_ = &ent; + m_binding = PathBinding(PathBinding::TagItem(), &ent); } void Path::bind_static(const Static& ent) { - m_binding_type = STATIC; - m_binding.static_ = &ent; + m_binding = PathBinding(&ent); } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 03aeab23..b3af8c52 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -25,6 +25,102 @@ class Trait; class Static; class Function; +//TAGGED_ENUM(Binding, Unbound, +// (BndModule, (const Module* module_; ) ), +// (BndEnum, (const Enum* enum_; ) ), +// (BndStruct, (const Struct* struct_; ) ), +// (BndTrait, (const Trait* trait_; ) ), +// (BndStatic, (const Static* static_; ) ), +// (BndFunction, (const Function* func_; ) ), +// (BndEnumVar, (const Enum* enum_; unsigned int idx; ) ), +// (BndTypeAlias, (const TypeAlias* alias_; ) ), +// (BndStructMethod, (const Struct* struct_; ::std::string name; ) ), +// (BndTraitMethod, (const Trait* struct_; ::std::string name; ) ) +// ); +class PathBinding +{ +public: + enum BindingType { + UNBOUND, + MODULE, + ALIAS, + ENUM, + STRUCT, + TRAIT, + + STRUCT_METHOD, + TRAIT_METHOD, + ENUM_VAR, + FUNCTION, + STATIC, + }; + struct EnumVar { + const Enum* enum_; + unsigned int idx; + }; +private: + BindingType m_binding_type = UNBOUND; + union { + const Module* module_; + const Enum* enum_; + const Struct* struct_; + struct { + const Struct* struct_; + unsigned int idx; + } structitem; + const Trait* trait_; + const Static* static_; + const Function* func_; + EnumVar enumvar_; + const TypeAlias* alias_; + } m_binding; + +public: + PathBinding(): m_binding_type(UNBOUND) {} + + bool is_bound() const { return m_binding_type != UNBOUND; } + BindingType type() const { return m_binding_type; } + #define _(t, n, v)\ + PathBinding(const t* i): m_binding_type(v) { m_binding.n##_ = i; } \ + const t& bound_##n() const { assert(m_binding_type == v); return *m_binding.n##_; } + _(Module, module, MODULE) + _(Trait, trait, TRAIT) + _(Struct, struct, STRUCT) + _(Enum, enum, ENUM) + _(Function, func, FUNCTION) + _(Static, static, STATIC) + _(TypeAlias, alias, ALIAS) + //_(EnumVar, enumvar, ENUM_VAR) + #undef _ + PathBinding(const Enum* enm, unsigned int i): + m_binding_type(ENUM_VAR) + { + m_binding.enumvar_ = {enm, i}; + } + const EnumVar& bound_enumvar() const { assert(m_binding_type == ENUM_VAR); return m_binding.enumvar_; } + + struct TagItem {}; + PathBinding(TagItem, const Trait* t): m_binding_type(TRAIT_METHOD) { m_binding.trait_ = t; } + PathBinding(TagItem, const Struct* i): m_binding_type(STRUCT_METHOD) { m_binding.struct_ = i; } + + friend ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x) { + switch(x.m_binding_type) + { + case UNBOUND: os << "UNBOUND"; break; + case MODULE: os << "Module"; break; + case TRAIT: os << "Trait"; break; + case STRUCT: os << "Struct"; break; + case ENUM: os << "Enum"; break; + case FUNCTION: os << "Function";break; + case STATIC: os << "Static"; break; + case ALIAS: os << "Alias"; break; + case STRUCT_METHOD: os << "StructMethod"; break; + case TRAIT_METHOD: os << "TraitMethod"; break; + case ENUM_VAR: os << "EnumVar(" << x.m_binding.enumvar_.idx << ")"; break; + } + return os; + } +}; class PathNode: public ::Serialisable @@ -48,33 +144,6 @@ public: class Path: public ::Serialisable { -public: - enum BindingType { - UNBOUND, - MODULE, - ALIAS, - ENUM, - STRUCT, - TRAIT, - - STRUCT_METHOD, - TRAIT_METHOD, - ENUM_VAR, - FUNCTION, - STATIC, - }; - //TAGGED_ENUM(Binding, Unbound, - // (BndModule, (const Module* module_; ) ), - // (BndEnum, (const Enum* enum_; ) ), - // (BndStruct, (const Struct* struct_; ) ), - // (BndTrait, (const Trait* trait_; ) ), - // (BndStatic, (const Static* static_; ) ), - // (BndFunction, (const Function* func_; ) ), - // (BndEnumVar, (const Enum* enum_; unsigned int idx; ) ), - // (BndTypeAlias, (const TypeAlias* alias_; ) ), - // (BndStructMethod, (const Struct* struct_; ::std::string name; ) ), - // (BndTraitMethod, (const Trait* struct_; ::std::string name; ) ) - // ); private: enum Class { RELATIVE, @@ -95,24 +164,7 @@ private: ::std::vector m_ufcs; ::std::vector m_nodes; - BindingType m_binding_type = UNBOUND; - union { - const Module* module_; - const Enum* enum_; - const Struct* struct_; - struct { - const Struct* struct_; - unsigned int idx; - } structitem; - const Trait* trait_; - const Static* static_; - const Function* func_; - struct { - const Enum* enum_; - unsigned int idx; - } enumvar; - const TypeAlias* alias_; - } m_binding; + PathBinding m_binding; public: Path(): m_class(RELATIVE) @@ -196,25 +248,7 @@ public: bool is_relative() const { return m_class == RELATIVE; } size_t size() const { return m_nodes.size(); } - bool is_bound() const { return m_binding_type != UNBOUND; } - BindingType binding_type() const { return m_binding_type; } - #define _(t, n, v) const t& bound_##n() const { assert(m_binding_type == v); return *m_binding.n##_; } - _(Module, module, MODULE) - _(Trait, trait, TRAIT) - _(Struct, struct, STRUCT) - //_(Enum, enum, ENUM) - _(Function, func, FUNCTION) - _(Static, static, STATIC) - _(TypeAlias, alias, ALIAS) - #undef _ - const Enum& bound_enum() const { - assert(m_binding_type == ENUM || m_binding_type == ENUM_VAR); // Kinda evil, given that it has its own union entry - return *m_binding.enum_; - } - const unsigned int bound_idx() const { - assert(m_binding_type == ENUM_VAR); - return m_binding.enumvar.idx; - } + const PathBinding& binding() const { return m_binding; } ::std::vector& nodes() { return m_nodes; } const ::std::vector& nodes() const { return m_nodes; } diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index a38bcb9c..405d55df 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -150,20 +150,22 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) { auto& hint_path = type_hint.path(); auto& pat_path = v.path; + const auto& hint_binding = hint_path.binding(); + const auto& pat_binding = pat_path.binding(); DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path()); - switch( hint_path.binding_type() ) + switch( hint_binding.type() ) { - case AST::Path::UNBOUND: + case AST::PathBinding::UNBOUND: throw ::std::runtime_error("Unbound path in pattern"); - case AST::Path::ENUM: { + case AST::PathBinding::ENUM: { // The pattern's path must refer to a variant of the hint path // - Actual type params are checked by the 'handle_pattern_enum' code - if( pat_path.binding_type() != AST::Path::ENUM_VAR ) + if( pat_binding.type() != AST::PathBinding::ENUM_VAR ) throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - if( &pat_path.bound_enum() != &hint_path.bound_enum() ) + if( pat_binding.bound_enumvar().enum_ != &hint_binding.bound_enum() ) throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - auto& enm = pat_path.bound_enum(); - auto idx = pat_path.bound_idx(); + const auto& enm = *pat_binding.bound_enumvar().enum_; + auto idx = pat_binding.bound_enumvar().idx; auto& var = enm.variants().at(idx); handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns); break; } diff --git a/src/convert/render.cpp b/src/convert/render.cpp index ce64e600..5c388d07 100644 --- a/src/convert/render.cpp +++ b/src/convert/render.cpp @@ -42,15 +42,15 @@ void Render_Crate(::std::ostream& os, const AST::Flat& crate) const auto& fcn = item.second; Render_Type(os, fcn.rettype(), nullptr); os << " " << name << "("; - bool is_first = true; - for(const auto& f : fcn.args()) - { - if( !is_first ) - os << ", "; - is_first = false; - // TODO: handle pattern - //Render_Type(os, f.second, f.first.c_str()); - } + //bool is_first = true; + //for(const auto& f : fcn.args()) + //{ + // if( !is_first ) + // os << ", "; + // is_first = false; + // // TODO: handle pattern + // //Render_Type(os, f.second, f.first.c_str()); + //} os << ")\n{\n"; // Dump expression AST os << "}\n"; diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index d0edc165..2e97b11b 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -358,7 +358,7 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) INDENT(); // Already absolute, our job is done // - However, if the path isn't bound, bind it - if( !path.is_bound() ) { + if( !path.binding().is_bound() ) { path.resolve(m_crate); } UNINDENT(); @@ -417,7 +417,7 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) local_path.resolve(m_crate); DEBUG("'super' path is relative to " << local_path); path.nodes().erase( path.nodes().begin() ); // delete the 'super' node - const AST::Module& mod = local_path.bound_module(); + const AST::Module& mod = local_path.binding().bound_module(); if( lookup_path_in_module(m_crate, mod, local_path, path) ) return ; // this should always be an error, as 'super' paths are never MaybeBind @@ -554,13 +554,13 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod // If wildcard, make sure it's sane if( imp.name == "" ) { - switch(imp.data.binding_type()) + switch(imp.data.binding().type()) { - case AST::Path::UNBOUND: + case AST::PathBinding::UNBOUND: throw ParseError::BugCheck("path unbound after calling .resolve()"); - case AST::Path::MODULE: + case AST::PathBinding::MODULE: break; - case AST::Path::ENUM: + case AST::PathBinding::ENUM: break; default: @@ -571,7 +571,7 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod for( auto& new_imp : new_imports ) { - if( not new_imp.is_bound() ) { + if( not new_imp.binding().is_bound() ) { new_imp.resolve(crate); } mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name()); diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp index 3f3e6b8d..4112bf27 100644 --- a/src/convert/typecheck_bounds.cpp +++ b/src/convert/typecheck_bounds.cpp @@ -25,11 +25,12 @@ void CGenericBoundChecker::handle_params(AST::TypeParams& params) if( bound.is_trait() ) { auto& trait = bound.bound(); + assert(trait.binding().is_bound()); DEBUG("trait = " << trait); - if( trait.binding_type() != AST::Path::TRAIT ) + if( trait.binding().type() != AST::PathBinding::TRAIT ) { //throw CompileError::BoundNotTrait( bound.lex_scope(), bound.param(), trait ); - throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait")); + throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait : " << trait.binding())); } else { DEBUG("Bound is a trait, good"); diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index a6a69186..8cb290c3 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -298,14 +298,14 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) if( p.is_absolute() ) { // grab bound item - switch(p.binding_type()) + switch(p.binding().type()) { - case AST::Path::STATIC: - node.get_res_type() = p.bound_static().type(); + case AST::PathBinding::STATIC: + node.get_res_type() = p.binding().bound_static().type(); break; - case AST::Path::ENUM_VAR: { - const AST::Enum& enm = p.bound_enum(); - auto idx = p.bound_idx(); + case AST::PathBinding::ENUM_VAR: { + const AST::Enum& enm = *p.binding().bound_enumvar().enum_; + auto idx = p.binding().bound_enumvar().idx; // Enum variant: // - Check that this variant takes no arguments if( enm.variants()[idx].m_sub_types.size() > 0 ) @@ -413,11 +413,11 @@ void CTC_NodeVisitor::visit(AST::ExprNode_Field& node) // TODO Move this logic to types.cpp? const AST::Path& p = tr->path(); - switch( p.binding_type() ) + switch( p.binding().type() ) { - case AST::Path::STRUCT: { + case AST::PathBinding::STRUCT: { const AST::PathNode& lastnode = p.nodes().back(); - AST::Struct& s = const_cast( p.bound_struct() ); + AST::Struct& s = const_cast( p.binding().bound_struct() ); node.get_res_type().merge_with( s.get_field_type(node.m_name.c_str(), lastnode.args()) ); break; } default: @@ -483,7 +483,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) for( const auto& t : ltype.traits() ) { DEBUG("- Trait " << t.path()); - AST::Trait& trait = const_cast( t.path().bound_trait() ); + AST::Trait& trait = const_cast( t.path().binding().bound_trait() ); // - Find method on one of them for( auto& m : trait.functions() ) { @@ -572,9 +572,9 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) argtypes.push_back( arg->get_res_type() ); } - if(node.m_path.binding_type() == AST::Path::FUNCTION) + if(node.m_path.binding().type() == AST::PathBinding::FUNCTION) { - const AST::Function& fcn = node.m_path.bound_func(); + const AST::Function& fcn = node.m_path.binding().bound_func(); if( fcn.params().n_params() > 0 ) { @@ -584,10 +584,10 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) DEBUG("ExprNode_CallPath - rt = " << fcn.rettype()); node.get_res_type().merge_with( fcn.rettype() ); } - else if(node.m_path.binding_type() == AST::Path::ENUM_VAR) + else if(node.m_path.binding().type() == AST::PathBinding::ENUM_VAR) { - const AST::Enum& enm = node.m_path.bound_enum(); - const unsigned int idx = node.m_path.bound_idx(); + const AST::Enum& enm = *node.m_path.binding().bound_enumvar().enum_; + const unsigned int idx = node.m_path.binding().bound_enumvar().idx; auto& path_node_enum = node.m_path[node.m_path.size()-2]; m_tc.check_enum_variant(path_node_enum.args(), argtypes, enm.params(), enm.variants().at(idx)); diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index b028c55f..3b0a5a93 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -181,27 +181,27 @@ void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode p DEBUG("path = " << path); AST::PathNode& last_node = path[path.size()-1]; const AST::TypeParams* params = nullptr; - switch(path.binding_type()) + switch(path.binding().type()) { - case AST::Path::UNBOUND: + case AST::PathBinding::UNBOUND: throw ::std::runtime_error("CGenericParamChecker::handle_path - Unbound path"); - case AST::Path::MODULE: + case AST::PathBinding::MODULE: DEBUG("WTF - Module path, isn't this invalid at this stage?"); break; - case AST::Path::TRAIT: - params = &path.bound_trait().params(); + case AST::PathBinding::TRAIT: + params = &path.binding().bound_trait().params(); if(0) - case AST::Path::STRUCT: - params = &path.bound_struct().params(); + case AST::PathBinding::STRUCT: + params = &path.binding().bound_struct().params(); if(0) - case AST::Path::ENUM: - params = &path.bound_enum().params(); + case AST::PathBinding::ENUM: + params = &path.binding().bound_enum().params(); if(0) - case AST::Path::ALIAS: - params = &path.bound_alias().params(); + case AST::PathBinding::ALIAS: + params = &path.binding().bound_alias().params(); if(0) - case AST::Path::FUNCTION: - params = &path.bound_func().params(); + case AST::PathBinding::FUNCTION: + params = &path.binding().bound_func().params(); try { check_generic_params(*params, last_node.args(), (m_within_expr > 0)); diff --git a/src/main.cpp b/src/main.cpp index 85224156..e0188012 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,82 +28,38 @@ bool debug_enabled() return ::std::cout << g_cur_phase << "- " << RepeatLitStr { " ", indent } << function << ": "; } +struct ProgramParams +{ + static const unsigned int EMIT_C = 0x1; + static const unsigned int EMIT_AST = 0x2; + + const char *infile = NULL; + ::std::string outfile; + const char *crate_path = "."; + unsigned emit_flags = EMIT_C; + + ProgramParams(int argc, char *argv[]); +}; + /// main! int main(int argc, char *argv[]) { AST_InitProvidedModule(); - // Hacky command-line parsing - 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; - } - } - } + + ProgramParams params(argc, argv); - if( outfile == "" ) - { - outfile = infile; - outfile += ".o"; - } try { g_cur_phase = "Parse"; - AST::Crate crate = Parse_Crate(infile); + AST::Crate crate = Parse_Crate(params.infile); g_cur_phase = "PostParse"; crate.post_parse(); //s << crate; g_cur_phase = "Temp output"; - Dump_Rust( FMT(outfile << ".rs").c_str(), crate ); + Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); // Resolve names to be absolute names (include references to the relevant struct/global/function) g_cur_phase = "Resolve"; @@ -113,7 +69,7 @@ int main(int argc, char *argv[]) // Typecheck / type propagate module (type annotations of all values) // - Check all generic conditions (ensure referenced trait is valid) // > Also mark parameter with applicable traits - #if 0 + #if 1 g_cur_phase = "TypecheckBounds"; Typecheck_GenericBounds(crate); // - Check all generic parameters match required conditions @@ -127,11 +83,11 @@ int main(int argc, char *argv[]) #endif g_cur_phase = "Output"; - Dump_Rust( FMT(outfile << ".rs").c_str(), crate ); + Dump_Rust( FMT(params.outfile << ".rs").c_str(), crate ); - if( strcmp(emit_type, "ast") == 0 ) + if( params.emit_flags == ProgramParams::EMIT_AST ) { - ::std::ofstream os(outfile); + ::std::ofstream os(params.outfile); Serialiser_TextTree os_tt(os); ((Serialiser&)os_tt) << crate; return 0; @@ -155,3 +111,72 @@ int main(int argc, char *argv[]) } return 0; } + +ProgramParams::ProgramParams(int argc, char *argv[]) +{ + // Hacky command-line parsing + for( int i = 1; i < argc; i ++ ) + { + const char* arg = argv[i]; + + if( arg[0] != '-' ) + { + this->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! + exit(1); + } + this->outfile = argv[++i]; + break; + default: + exit(1); + } + } + } + else + { + if( strcmp(arg, "--crate-path") == 0 ) { + if( i == argc - 1 ) { + // TODO: BAIL! + exit(1); + } + this->crate_path = argv[++i]; + } + else if( strcmp(arg, "--emit") == 0 ) { + if( i == argc - 1 ) { + // TODO: BAIL! + exit(1); + } + + arg = argv[++i]; + if( strcmp(arg, "ast") == 0 ) + this->emit_flags = EMIT_AST; + else if( strcmp(arg, "c") == 0 ) + this->emit_flags = EMIT_C; + else { + ::std::cerr << "Unknown argument to --emit : '" << arg << "'" << ::std::endl; + exit(1); + } + } + else { + exit(1); + } + } + } + + if( this->outfile == "" ) + { + this->outfile = (::std::string)this->infile + ".o"; + } +} + -- cgit v1.2.3