summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorubsan <npmazzuca@gmail.com>2016-12-24 19:07:08 -0700
committerubsan <npmazzuca@gmail.com>2016-12-24 19:07:08 -0700
commit0c14c734fa32014fd24297ccdbed927016185ffd (patch)
treeed4bbff4be39c44c57164641f4ed32b5ad4675f0 /src
parentd12a8a886caf2e0edf33c1af831b1df990d2c892 (diff)
downloadmrust-0c14c734fa32014fd24297ccdbed927016185ffd.tar.gz
No more tears!
No more DOS line endings or trailing whitespace either
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp864
-rw-r--r--src/ast/ast.hpp1284
-rw-r--r--src/ast/attrs.hpp22
-rw-r--r--src/ast/crate.cpp12
-rw-r--r--src/ast/crate.hpp16
-rw-r--r--src/ast/dump.cpp82
-rw-r--r--src/ast/expr.cpp8
-rw-r--r--src/ast/expr.hpp86
-rw-r--r--src/ast/expr_ptr.hpp2
-rw-r--r--src/ast/generics.hpp22
-rw-r--r--src/ast/item.hpp4
-rw-r--r--src/ast/macro.hpp8
-rw-r--r--src/ast/path.cpp16
-rw-r--r--src/ast/path.hpp52
-rw-r--r--src/ast/pattern.cpp10
-rw-r--r--src/ast/pattern.hpp28
-rw-r--r--src/ast/types.cpp8
-rw-r--r--src/ast/types.hpp552
-rw-r--r--src/common.hpp10
-rw-r--r--src/coretypes.hpp44
-rw-r--r--src/expand/cfg.cpp16
-rw-r--r--src/expand/concat.cpp8
-rw-r--r--src/expand/crate_tags.cpp4
-rw-r--r--src/expand/derive.cpp414
-rw-r--r--src/expand/env.cpp6
-rw-r--r--src/expand/format_args.cpp114
-rw-r--r--src/expand/include.cpp10
-rw-r--r--src/expand/lang_item.cpp28
-rw-r--r--src/expand/macro_rules.cpp16
-rw-r--r--src/expand/mod.cpp112
-rw-r--r--src/expand/rustc_diagnostics.cpp8
-rw-r--r--src/expand/std_prelude.cpp8
-rw-r--r--src/expand/stringify.cpp4
-rw-r--r--src/expand/test.cpp4
-rw-r--r--src/hir/crate_ptr.hpp4
-rw-r--r--src/hir/deserialise.cpp142
-rw-r--r--src/hir/dump.cpp42
-rw-r--r--src/hir/expr.cpp10
-rw-r--r--src/hir/expr.hpp178
-rw-r--r--src/hir/expr_ptr.hpp14
-rw-r--r--src/hir/from_ast.cpp188
-rw-r--r--src/hir/from_ast_expr.cpp82
-rw-r--r--src/hir/generic_params.cpp2
-rw-r--r--src/hir/generic_params.hpp8
-rw-r--r--src/hir/hir.cpp48
-rw-r--r--src/hir/hir.hpp98
-rw-r--r--src/hir/item_path.hpp16
-rw-r--r--src/hir/path.cpp32
-rw-r--r--src/hir/path.hpp34
-rw-r--r--src/hir/pattern.cpp12
-rw-r--r--src/hir/pattern.hpp14
-rw-r--r--src/hir/serialise.cpp78
-rw-r--r--src/hir/serialise_lowlevel.cpp34
-rw-r--r--src/hir/serialise_lowlevel.hpp10
-rw-r--r--src/hir/type.cpp36
-rw-r--r--src/hir/type.hpp28
-rw-r--r--src/hir/visitor.cpp8
-rw-r--r--src/hir/visitor.hpp14
-rw-r--r--src/hir_conv/bind.cpp66
-rw-r--r--src/hir_conv/constant_evaluation.cpp224
-rw-r--r--src/hir_conv/expand_type.cpp46
-rw-r--r--src/hir_conv/markings.cpp22
-rw-r--r--src/hir_conv/resolve_ufcs.cpp76
-rw-r--r--src/hir_expand/annotate_value_usage.cpp102
-rw-r--r--src/hir_expand/closures.cpp190
-rw-r--r--src/hir_expand/const_eval_full.cpp90
-rw-r--r--src/hir_expand/erased_types.cpp44
-rw-r--r--src/hir_expand/reborrow.cpp22
-rw-r--r--src/hir_expand/ufcs_everything.cpp154
-rw-r--r--src/hir_expand/vtable.cpp42
-rw-r--r--src/hir_typeck/common.cpp20
-rw-r--r--src/hir_typeck/common.hpp4
-rw-r--r--src/hir_typeck/expr_check.cpp196
-rw-r--r--src/hir_typeck/expr_cs.cpp930
-rw-r--r--src/hir_typeck/expr_visit.cpp24
-rw-r--r--src/hir_typeck/expr_visit.hpp10
-rw-r--r--src/hir_typeck/helpers.cpp374
-rw-r--r--src/hir_typeck/helpers.hpp60
-rw-r--r--src/hir_typeck/impl_ref.cpp2
-rw-r--r--src/hir_typeck/impl_ref.hpp20
-rw-r--r--src/hir_typeck/outer.cpp116
-rw-r--r--src/hir_typeck/static.cpp150
-rw-r--r--src/hir_typeck/static.hpp28
-rw-r--r--src/ident.cpp2
-rw-r--r--src/include/debug.hpp2
-rw-r--r--src/include/ident.hpp26
-rw-r--r--src/include/rc_string.hpp10
-rw-r--r--src/include/rustic.hpp16
-rw-r--r--src/include/serialise.hpp14
-rw-r--r--src/include/serialiser_texttree.hpp10
-rw-r--r--src/include/span.hpp10
-rw-r--r--src/include/synext_decorator.hpp10
-rw-r--r--src/include/tagged_union.hpp4
-rw-r--r--src/macro_rules/eval.cpp178
-rw-r--r--src/macro_rules/macro_rules.hpp324
-rw-r--r--src/macro_rules/macro_rules_ptr.hpp4
-rw-r--r--src/macro_rules/mod.cpp606
-rw-r--r--src/macro_rules/parse.cpp64
-rw-r--r--src/main.cpp1226
-rw-r--r--src/mir/check.cpp26
-rw-r--r--src/mir/cleanup.cpp164
-rw-r--r--src/mir/dump.cpp46
-rw-r--r--src/mir/from_hir.cpp310
-rw-r--r--src/mir/from_hir.hpp54
-rw-r--r--src/mir/from_hir_match.cpp454
-rw-r--r--src/mir/helpers.cpp2
-rw-r--r--src/mir/helpers.hpp14
-rw-r--r--src/mir/mir.cpp8
-rw-r--r--src/mir/mir.hpp8
-rw-r--r--src/mir/mir_builder.cpp98
-rw-r--r--src/mir/mir_ptr.hpp8
-rw-r--r--src/mir/optimise.cpp26
-rw-r--r--src/mir/visit_crate_mir.cpp6
-rw-r--r--src/mir/visit_crate_mir.hpp6
-rw-r--r--src/parse/common.hpp140
-rw-r--r--src/parse/expr.cpp2602
-rw-r--r--src/parse/interpolated_fragment.hpp12
-rw-r--r--src/parse/lex.cpp40
-rw-r--r--src/parse/lex.hpp4
-rw-r--r--src/parse/parseerror.cpp182
-rw-r--r--src/parse/parseerror.hpp80
-rw-r--r--src/parse/paths.cpp28
-rw-r--r--src/parse/pattern.cpp68
-rw-r--r--src/parse/root.cpp3758
-rw-r--r--src/parse/token.cpp12
-rw-r--r--src/parse/token.hpp18
-rw-r--r--src/parse/tokenstream.cpp8
-rw-r--r--src/parse/tokenstream.hpp18
-rw-r--r--src/parse/tokentree.hpp122
-rw-r--r--src/parse/ttstream.hpp4
-rw-r--r--src/parse/types.cpp30
-rw-r--r--src/resolve/absolute.cpp228
-rw-r--r--src/resolve/index.cpp58
-rw-r--r--src/resolve/use.cpp50
-rw-r--r--src/serialise.cpp10
-rw-r--r--src/trans/codegen.cpp16
-rw-r--r--src/trans/codegen.hpp12
-rw-r--r--src/trans/codegen_c.cpp110
-rw-r--r--src/trans/enumerate.cpp76
-rw-r--r--src/trans/mangling.cpp2
-rw-r--r--src/trans/monomorphise.cpp20
-rw-r--r--src/trans/trans_list.hpp8
142 files changed, 9739 insertions, 9739 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 15b8c7d7..39250a41 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -1,432 +1,432 @@
-/*
- */
-#include "ast.hpp"
-#include "crate.hpp"
-#include "types.hpp"
-#include "expr.hpp"
-#include "../common.hpp"
-#include <iostream>
-#include "../parse/parseerror.hpp"
-#include <algorithm>
-#include <serialiser_texttree.hpp>
-
-namespace AST {
-
-
-namespace {
- ::std::vector<MetaItem> clone_mivec(const ::std::vector<MetaItem>& v) {
- ::std::vector<MetaItem> ri;
- ri.reserve(v.size());
- for(const auto& i : v)
- ri.push_back( i.clone() );
- return ri;
- }
-}
-
-MetaItems::~MetaItems()
-{
-}
-MetaItems MetaItems::clone() const
-{
- return MetaItems( m_span, clone_mivec(m_items) );
-}
-
-void MetaItems::push_back(MetaItem i)
-{
- m_items.push_back( ::std::move(i) );
-}
-const MetaItem* MetaItems::get(const char *name) const
-{
- for( auto& i : m_items ) {
- if(i.name() == name) {
- //i.mark_used();
- return &i;
- }
- }
- return 0;
-}
-
-MetaItem::~MetaItem()
-{
-}
-MetaItem MetaItem::clone() const
-{
- TU_MATCH(MetaItemData, (m_data), (e),
- (None,
- return MetaItem(m_name);
- ),
- (String,
- return MetaItem(m_name, e.val);
- ),
- (List,
- return MetaItem(m_name, clone_mivec(e.sub_items));
- )
- )
- throw ::std::runtime_error("MetaItem::clone - Fell off end");
-}
-
-StructItem StructItem::clone() const
-{
- return StructItem(m_attrs.clone(), m_is_public, m_name, m_type.clone());
-}
-TupleItem TupleItem::clone() const
-{
- return TupleItem(m_attrs.clone(), m_is_public, m_type.clone());
-}
-
-
-TypeAlias TypeAlias::clone() const
-{
- return TypeAlias( m_params.clone(), m_type.clone() );
-}
-Static Static::clone() const
-{
- return Static( m_class, m_type.clone(), m_value.is_valid() ? AST::Expr( m_value.node().clone() ) : AST::Expr() );
-}
-
-Function::Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args):
- m_span(sp),
- m_params( move(params) ),
- m_rettype( move(ret_type) ),
- m_args( move(args) ),
- m_abi( mv$(abi) ),
- m_is_const(is_const),
- m_is_unsafe(is_unsafe),
- m_is_variadic(is_variadic)
-{
-}
-Function Function::clone() const
-{
- decltype(m_args) new_args;
- for(const auto& arg : m_args)
- new_args.push_back( ::std::make_pair( arg.first.clone(), arg.second.clone() ) );
-
- auto rv = Function( m_span, m_params.clone(), m_abi, m_is_unsafe, m_is_const, m_is_variadic, m_rettype.clone(), mv$(new_args) );
- if( m_code.is_valid() )
- {
- rv.m_code = AST::Expr( m_code.node().clone() );
- }
- return rv;
-}
-
-void Trait::add_type(::std::string name, TypeRef type) {
- m_items.push_back( Named<Item>(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) );
-}
-void Trait::add_function(::std::string name, Function fcn) {
- DEBUG("trait fn " << name);
- m_items.push_back( Named<Item>(mv$(name), Item::make_Function({mv$(fcn)}), true) );
-}
-void Trait::add_static(::std::string name, Static v) {
- m_items.push_back( Named<Item>(mv$(name), Item::make_Static({mv$(v)}), true) );
-}
-void Trait::set_is_marker() {
- m_is_marker = true;
-}
-bool Trait::is_marker() const {
- return m_is_marker;
-}
-bool Trait::has_named_item(const ::std::string& name, bool& out_is_fcn) const
-{
- for( const auto& i : m_items )
- {
- if( i.name == name ) {
- out_is_fcn = i.data.is_Function();
- return true;
- }
- }
- return false;
-}
-
-Trait Trait::clone() const
-{
- auto rv = Trait(m_params.clone(), m_supertraits);
- for(const auto& item : m_items)
- {
- rv.m_items.push_back( Named<Item> { item.name, item.data.clone(), item.is_pub } );
- }
- return rv;
-}
-
-Enum Enum::clone() const
-{
- decltype(m_variants) new_variants;
- for(const auto& var : m_variants)
- {
- TU_MATCHA( (var.m_data), (e),
- (Value,
- new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, e.m_value.clone()) );
- ),
- (Tuple,
- decltype(e.m_sub_types) new_st;
- for(const auto& f : e.m_sub_types)
- new_st.push_back( f.clone() );
- new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_st)) );
- ),
- (Struct,
- decltype(e.m_fields) new_fields;
- for(const auto& f : e.m_fields)
- new_fields.push_back( f.clone() );
- new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_fields)) );
- )
- )
- }
- return Enum(m_params.clone(), mv$(new_variants));
-}
-Struct Struct::clone() const
-{
- TU_MATCHA( (m_data), (e),
- (Tuple,
- decltype(e.ents) new_fields;
- for(const auto& f : e.ents)
- new_fields.push_back( f.clone() );
- return Struct(m_params.clone(), mv$(new_fields));
- ),
- (Struct,
- decltype(e.ents) new_fields;
- for(const auto& f : e.ents)
- new_fields.push_back( f.clone() );
- return Struct(m_params.clone(), mv$(new_fields));
- )
- )
- throw "";
-}
-
-Union Union::clone() const
-{
- decltype(m_variants) new_vars;
- for(const auto& f : m_variants)
- new_vars.push_back( f.clone() );
- return Union(m_params.clone(), mv$(new_vars));
-}
-
-::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl)
-{
- return os << "impl<" << impl.m_params << "> " << impl.m_trait.ent << " for " << impl.m_type << "";
-}
-
-void Impl::add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn)
-{
- DEBUG("impl fn " << name);
- m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Function(mv$(fcn)) ) } );
-}
-void Impl::add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type)
-{
- m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Type(TypeAlias(GenericParams(), mv$(type))) ) } );
-}
-void Impl::add_static(bool is_public, bool is_specialisable, ::std::string name, Static v)
-{
- m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Static(mv$(v)) ) } );
-}
-void Impl::add_macro_invocation(MacroInvocation item) {
- m_items.push_back( ImplItem { false, false, "", box$( Item::make_MacroInv(mv$(item)) ) } );
-}
-
-bool Impl::has_named_item(const ::std::string& name) const
-{
- for( const auto& it : this->items() )
- {
- if( it.name == name ) {
- return true;
- }
- }
- return false;
-}
-
-::std::ostream& operator<<(::std::ostream& os, const Impl& impl)
-{
- return os << impl.m_def;
-}
-
-::rust::option<char> ImplRef::find_named_item(const ::std::string& name) const
-{
- if( this->impl.has_named_item(name) ) {
- return ::rust::Some(' ');
- }
- else {
- return ::rust::None<char>();
- }
-}
-
-::std::ostream& operator<<(::std::ostream& os, const UseStmt& x)
-{
- os << "Use(" << x.path << ")";
- return os;
-}
-
-
-
-MacroInvocation MacroInvocation::clone() const
-{
- return MacroInvocation(m_span, m_macro_name, m_ident, m_input.clone());
-}
-
-
-UseStmt UseStmt::clone() const
-{
- return UseStmt(sp, path);
-}
-
-void ExternBlock::add_item(Named<Item> named_item)
-{
- ASSERT_BUG(named_item.data.span, named_item.data.is_Function() || named_item.data.is_Static(), "Incorrect item type for ExternBlock");
- m_items.push_back( mv$(named_item) );
-}
-ExternBlock ExternBlock::clone() const
-{
- TODO(Span(), "Clone an extern block");
-}
-
-::std::shared_ptr<AST::Module> Module::add_anon() {
- auto rv = ::std::shared_ptr<AST::Module>( new Module(m_my_path + FMT("#" << m_anon_modules.size())) );
- DEBUG("New anon " << rv->m_my_path);
- rv->m_file_info = m_file_info;
-
- m_anon_modules.push_back( rv );
-
- return rv;
-}
-
-void Module::add_item( Named<Item> named_item ) {
- m_items.push_back( mv$(named_item) );
- const auto& i = m_items.back();
- if( i.name == "" ) {
- }
- else {
- DEBUG(m_my_path << "::" << i.name << " = " << i.data.tag_str() << ", attrs = " << i.data.attrs);
- }
-}
-void Module::add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs) {
- it.attrs = mv$(attrs);
- add_item( Named<Item>( mv$(name), mv$(it), is_pub ) );
-}
-void Module::add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, MetaItems attrs) {
- this->add_item( is_public, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) );
-}
-void Module::add_alias(bool is_public, UseStmt us, ::std::string name, MetaItems attrs) {
- this->add_item( is_public, mv$(name), Item(mv$(us)), mv$(attrs) );
-}
-void Module::add_macro_invocation(MacroInvocation item) {
- this->add_item( false, "", Item( mv$(item) ), ::AST::MetaItems {} );
-}
-void Module::add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro) {
- m_macros.push_back( Named<MacroRulesPtr>( mv$(name), mv$(macro), is_exported ) );
-}
-void Module::add_macro_import(::std::string name, const MacroRules& mr) {
- m_macro_import_res.push_back( NamedNS<const MacroRules*>( mv$(name), &mr, false ) );
-}
-
-Item Item::clone() const
-{
- TU_MATCHA( (*this), (e),
- (None,
- return AST::Item(e);
- ),
- (MacroInv,
- TODO(this->span, "Clone on Item::MacroInv");
- ),
- (Use,
- return AST::Item(e.clone());
- ),
- (ExternBlock,
- TODO(this->span, "Clone on Item::" << this->tag_str());
- ),
- (Impl,
- TODO(this->span, "Clone on Item::Impl");
- ),
- (NegImpl,
- TODO(this->span, "Clone on Item::NegImpl");
- ),
- (Module,
- TODO(this->span, "Clone on Item::Module");
- ),
- (Crate,
- return AST::Item(e);
- ),
- (Type,
- return AST::Item(e.clone());
- ),
- (Struct,
- return AST::Item(e.clone());
- ),
- (Enum,
- return AST::Item(e.clone());
- ),
- (Union,
- return AST::Item(e.clone());
- ),
- (Trait,
- return AST::Item(e.clone());
- ),
-
- (Function,
- return AST::Item(e.clone());
- ),
- (Static,
- return AST::Item(e.clone());
- )
- )
- throw "";
-}
-
-
-
-::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp)
-{
- //os << "TypeParam(";
- os << tp.m_name;
- os << " = ";
- os << tp.m_default;
- //os << ")";
- return os;
-}
-
-::std::ostream& operator<<(::std::ostream& os, const GenericBound& x)
-{
- TU_MATCH(GenericBound, (x), (ent),
- (Lifetime,
- os << "'" << ent.test << ": '" << ent.bound;
- ),
- (TypeLifetime,
- os << ent.type << ": '" << ent.bound;
- ),
- (IsTrait,
- if( ! ent.hrls.empty() )
- {
- os << "for<";
- for(const auto& l : ent.hrls)
- os << "'" << l;
- os << ">";
- }
- os << ent.type << ": " << ent.trait;
- ),
- (MaybeTrait,
- os << ent.type << ": ?" << ent.trait;
- ),
- (NotTrait,
- os << ent.type << ": !" << ent.trait;
- ),
- (Equality,
- os << ent.type << " = " << ent.replacement;
- )
- )
- return os;
-}
-
-
-int GenericParams::find_name(const char* name) const
-{
- for( unsigned int i = 0; i < m_type_params.size(); i ++ )
- {
- if( m_type_params[i].name() == name )
- return i;
- }
- DEBUG("Type param '" << name << "' not in list");
- return -1;
-}
-
-::std::ostream& operator<<(::std::ostream& os, const GenericParams& tps)
-{
- return os << "<" << tps.m_lifetime_params << "," << tps.m_type_params << "> where {" << tps.m_bounds << "}";
-}
-
-} // namespace AST
+/*
+ */
+#include "ast.hpp"
+#include "crate.hpp"
+#include "types.hpp"
+#include "expr.hpp"
+#include "../common.hpp"
+#include <iostream>
+#include "../parse/parseerror.hpp"
+#include <algorithm>
+#include <serialiser_texttree.hpp>
+
+namespace AST {
+
+
+namespace {
+ ::std::vector<MetaItem> clone_mivec(const ::std::vector<MetaItem>& v) {
+ ::std::vector<MetaItem> ri;
+ ri.reserve(v.size());
+ for(const auto& i : v)
+ ri.push_back( i.clone() );
+ return ri;
+ }
+}
+
+MetaItems::~MetaItems()
+{
+}
+MetaItems MetaItems::clone() const
+{
+ return MetaItems( m_span, clone_mivec(m_items) );
+}
+
+void MetaItems::push_back(MetaItem i)
+{
+ m_items.push_back( ::std::move(i) );
+}
+const MetaItem* MetaItems::get(const char *name) const
+{
+ for( auto& i : m_items ) {
+ if(i.name() == name) {
+ //i.mark_used();
+ return &i;
+ }
+ }
+ return 0;
+}
+
+MetaItem::~MetaItem()
+{
+}
+MetaItem MetaItem::clone() const
+{
+ TU_MATCH(MetaItemData, (m_data), (e),
+ (None,
+ return MetaItem(m_name);
+ ),
+ (String,
+ return MetaItem(m_name, e.val);
+ ),
+ (List,
+ return MetaItem(m_name, clone_mivec(e.sub_items));
+ )
+ )
+ throw ::std::runtime_error("MetaItem::clone - Fell off end");
+}
+
+StructItem StructItem::clone() const
+{
+ return StructItem(m_attrs.clone(), m_is_public, m_name, m_type.clone());
+}
+TupleItem TupleItem::clone() const
+{
+ return TupleItem(m_attrs.clone(), m_is_public, m_type.clone());
+}
+
+
+TypeAlias TypeAlias::clone() const
+{
+ return TypeAlias( m_params.clone(), m_type.clone() );
+}
+Static Static::clone() const
+{
+ return Static( m_class, m_type.clone(), m_value.is_valid() ? AST::Expr( m_value.node().clone() ) : AST::Expr() );
+}
+
+Function::Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args):
+ m_span(sp),
+ m_params( move(params) ),
+ m_rettype( move(ret_type) ),
+ m_args( move(args) ),
+ m_abi( mv$(abi) ),
+ m_is_const(is_const),
+ m_is_unsafe(is_unsafe),
+ m_is_variadic(is_variadic)
+{
+}
+Function Function::clone() const
+{
+ decltype(m_args) new_args;
+ for(const auto& arg : m_args)
+ new_args.push_back( ::std::make_pair( arg.first.clone(), arg.second.clone() ) );
+
+ auto rv = Function( m_span, m_params.clone(), m_abi, m_is_unsafe, m_is_const, m_is_variadic, m_rettype.clone(), mv$(new_args) );
+ if( m_code.is_valid() )
+ {
+ rv.m_code = AST::Expr( m_code.node().clone() );
+ }
+ return rv;
+}
+
+void Trait::add_type(::std::string name, TypeRef type) {
+ m_items.push_back( Named<Item>(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) );
+}
+void Trait::add_function(::std::string name, Function fcn) {
+ DEBUG("trait fn " << name);
+ m_items.push_back( Named<Item>(mv$(name), Item::make_Function({mv$(fcn)}), true) );
+}
+void Trait::add_static(::std::string name, Static v) {
+ m_items.push_back( Named<Item>(mv$(name), Item::make_Static({mv$(v)}), true) );
+}
+void Trait::set_is_marker() {
+ m_is_marker = true;
+}
+bool Trait::is_marker() const {
+ return m_is_marker;
+}
+bool Trait::has_named_item(const ::std::string& name, bool& out_is_fcn) const
+{
+ for( const auto& i : m_items )
+ {
+ if( i.name == name ) {
+ out_is_fcn = i.data.is_Function();
+ return true;
+ }
+ }
+ return false;
+}
+
+Trait Trait::clone() const
+{
+ auto rv = Trait(m_params.clone(), m_supertraits);
+ for(const auto& item : m_items)
+ {
+ rv.m_items.push_back( Named<Item> { item.name, item.data.clone(), item.is_pub } );
+ }
+ return rv;
+}
+
+Enum Enum::clone() const
+{
+ decltype(m_variants) new_variants;
+ for(const auto& var : m_variants)
+ {
+ TU_MATCHA( (var.m_data), (e),
+ (Value,
+ new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, e.m_value.clone()) );
+ ),
+ (Tuple,
+ decltype(e.m_sub_types) new_st;
+ for(const auto& f : e.m_sub_types)
+ new_st.push_back( f.clone() );
+ new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_st)) );
+ ),
+ (Struct,
+ decltype(e.m_fields) new_fields;
+ for(const auto& f : e.m_fields)
+ new_fields.push_back( f.clone() );
+ new_variants.push_back( EnumVariant(var.m_attrs.clone(), var.m_name, mv$(new_fields)) );
+ )
+ )
+ }
+ return Enum(m_params.clone(), mv$(new_variants));
+}
+Struct Struct::clone() const
+{
+ TU_MATCHA( (m_data), (e),
+ (Tuple,
+ decltype(e.ents) new_fields;
+ for(const auto& f : e.ents)
+ new_fields.push_back( f.clone() );
+ return Struct(m_params.clone(), mv$(new_fields));
+ ),
+ (Struct,
+ decltype(e.ents) new_fields;
+ for(const auto& f : e.ents)
+ new_fields.push_back( f.clone() );
+ return Struct(m_params.clone(), mv$(new_fields));
+ )
+ )
+ throw "";
+}
+
+Union Union::clone() const
+{
+ decltype(m_variants) new_vars;
+ for(const auto& f : m_variants)
+ new_vars.push_back( f.clone() );
+ return Union(m_params.clone(), mv$(new_vars));
+}
+
+::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl)
+{
+ return os << "impl<" << impl.m_params << "> " << impl.m_trait.ent << " for " << impl.m_type << "";
+}
+
+void Impl::add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn)
+{
+ DEBUG("impl fn " << name);
+ m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Function(mv$(fcn)) ) } );
+}
+void Impl::add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type)
+{
+ m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Type(TypeAlias(GenericParams(), mv$(type))) ) } );
+}
+void Impl::add_static(bool is_public, bool is_specialisable, ::std::string name, Static v)
+{
+ m_items.push_back( ImplItem { is_public, is_specialisable, mv$(name), box$( Item::make_Static(mv$(v)) ) } );
+}
+void Impl::add_macro_invocation(MacroInvocation item) {
+ m_items.push_back( ImplItem { false, false, "", box$( Item::make_MacroInv(mv$(item)) ) } );
+}
+
+bool Impl::has_named_item(const ::std::string& name) const
+{
+ for( const auto& it : this->items() )
+ {
+ if( it.name == name ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const Impl& impl)
+{
+ return os << impl.m_def;
+}
+
+::rust::option<char> ImplRef::find_named_item(const ::std::string& name) const
+{
+ if( this->impl.has_named_item(name) ) {
+ return ::rust::Some(' ');
+ }
+ else {
+ return ::rust::None<char>();
+ }
+}
+
+::std::ostream& operator<<(::std::ostream& os, const UseStmt& x)
+{
+ os << "Use(" << x.path << ")";
+ return os;
+}
+
+
+
+MacroInvocation MacroInvocation::clone() const
+{
+ return MacroInvocation(m_span, m_macro_name, m_ident, m_input.clone());
+}
+
+
+UseStmt UseStmt::clone() const
+{
+ return UseStmt(sp, path);
+}
+
+void ExternBlock::add_item(Named<Item> named_item)
+{
+ ASSERT_BUG(named_item.data.span, named_item.data.is_Function() || named_item.data.is_Static(), "Incorrect item type for ExternBlock");
+ m_items.push_back( mv$(named_item) );
+}
+ExternBlock ExternBlock::clone() const
+{
+ TODO(Span(), "Clone an extern block");
+}
+
+::std::shared_ptr<AST::Module> Module::add_anon() {
+ auto rv = ::std::shared_ptr<AST::Module>( new Module(m_my_path + FMT("#" << m_anon_modules.size())) );
+ DEBUG("New anon " << rv->m_my_path);
+ rv->m_file_info = m_file_info;
+
+ m_anon_modules.push_back( rv );
+
+ return rv;
+}
+
+void Module::add_item( Named<Item> named_item ) {
+ m_items.push_back( mv$(named_item) );
+ const auto& i = m_items.back();
+ if( i.name == "" ) {
+ }
+ else {
+ DEBUG(m_my_path << "::" << i.name << " = " << i.data.tag_str() << ", attrs = " << i.data.attrs);
+ }
+}
+void Module::add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs) {
+ it.attrs = mv$(attrs);
+ add_item( Named<Item>( mv$(name), mv$(it), is_pub ) );
+}
+void Module::add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, MetaItems attrs) {
+ this->add_item( is_public, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) );
+}
+void Module::add_alias(bool is_public, UseStmt us, ::std::string name, MetaItems attrs) {
+ this->add_item( is_public, mv$(name), Item(mv$(us)), mv$(attrs) );
+}
+void Module::add_macro_invocation(MacroInvocation item) {
+ this->add_item( false, "", Item( mv$(item) ), ::AST::MetaItems {} );
+}
+void Module::add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro) {
+ m_macros.push_back( Named<MacroRulesPtr>( mv$(name), mv$(macro), is_exported ) );
+}
+void Module::add_macro_import(::std::string name, const MacroRules& mr) {
+ m_macro_import_res.push_back( NamedNS<const MacroRules*>( mv$(name), &mr, false ) );
+}
+
+Item Item::clone() const
+{
+ TU_MATCHA( (*this), (e),
+ (None,
+ return AST::Item(e);
+ ),
+ (MacroInv,
+ TODO(this->span, "Clone on Item::MacroInv");
+ ),
+ (Use,
+ return AST::Item(e.clone());
+ ),
+ (ExternBlock,
+ TODO(this->span, "Clone on Item::" << this->tag_str());
+ ),
+ (Impl,
+ TODO(this->span, "Clone on Item::Impl");
+ ),
+ (NegImpl,
+ TODO(this->span, "Clone on Item::NegImpl");
+ ),
+ (Module,
+ TODO(this->span, "Clone on Item::Module");
+ ),
+ (Crate,
+ return AST::Item(e);
+ ),
+ (Type,
+ return AST::Item(e.clone());
+ ),
+ (Struct,
+ return AST::Item(e.clone());
+ ),
+ (Enum,
+ return AST::Item(e.clone());
+ ),
+ (Union,
+ return AST::Item(e.clone());
+ ),
+ (Trait,
+ return AST::Item(e.clone());
+ ),
+
+ (Function,
+ return AST::Item(e.clone());
+ ),
+ (Static,
+ return AST::Item(e.clone());
+ )
+ )
+ throw "";
+}
+
+
+
+::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp)
+{
+ //os << "TypeParam(";
+ os << tp.m_name;
+ os << " = ";
+ os << tp.m_default;
+ //os << ")";
+ return os;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const GenericBound& x)
+{
+ TU_MATCH(GenericBound, (x), (ent),
+ (Lifetime,
+ os << "'" << ent.test << ": '" << ent.bound;
+ ),
+ (TypeLifetime,
+ os << ent.type << ": '" << ent.bound;
+ ),
+ (IsTrait,
+ if( ! ent.hrls.empty() )
+ {
+ os << "for<";
+ for(const auto& l : ent.hrls)
+ os << "'" << l;
+ os << ">";
+ }
+ os << ent.type << ": " << ent.trait;
+ ),
+ (MaybeTrait,
+ os << ent.type << ": ?" << ent.trait;
+ ),
+ (NotTrait,
+ os << ent.type << ": !" << ent.trait;
+ ),
+ (Equality,
+ os << ent.type << " = " << ent.replacement;
+ )
+ )
+ return os;
+}
+
+
+int GenericParams::find_name(const char* name) const
+{
+ for( unsigned int i = 0; i < m_type_params.size(); i ++ )
+ {
+ if( m_type_params[i].name() == name )
+ return i;
+ }
+ DEBUG("Type param '" << name << "' not in list");
+ return -1;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const GenericParams& tps)
+{
+ return os << "<" << tps.m_lifetime_params << "," << tps.m_type_params << "> where {" << tps.m_bounds << "}";
+}
+
+} // namespace AST
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 4b48aa01..b63cb2e6 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -1,642 +1,642 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * ast/ast.hpp
- * - Core AST header
- */
-#ifndef AST_HPP_INCLUDED
-#define AST_HPP_INCLUDED
-
-#include <string>
-#include <vector>
-#include <stdexcept>
-#include "../coretypes.hpp"
-#include <memory>
-#include <map>
-#include <unordered_map>
-#include <algorithm>
-
-#include "../parse/tokentree.hpp"
-#include "types.hpp"
-#include <serialise.hpp>
-
-#include <ast/pattern.hpp>
-#include <ast/attrs.hpp>
-#include <ast/expr_ptr.hpp>
-#include <ast/item.hpp>
-#include <ast/macro.hpp> // MacroInvocation
-
-#include "generics.hpp"
-
-#include <macro_rules/macro_rules_ptr.hpp>
-
-namespace AST {
-
-class Crate;
-
-class Module;
-class Item;
-
-using ::std::unique_ptr;
-using ::std::move;
-
-enum eItemType
-{
- ITEM_TRAIT,
- ITEM_STRUCT,
- ITEM_FN,
-};
-
-struct StructItem
-{
- ::AST::MetaItems m_attrs;
- bool m_is_public;
- ::std::string m_name;
- TypeRef m_type;
-
- //StructItem() {}
-
- StructItem(::AST::MetaItems attrs, bool is_pub, ::std::string name, TypeRef ty):
- m_attrs( mv$(attrs) ),
- m_is_public(is_pub),
- m_name( mv$(name) ),
- m_type( mv$(ty) )
- {
- }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const StructItem& x) {
- return os << (x.m_is_public ? "pub " : "") << x.m_name << ": " << x.m_type;
- }
-
- StructItem clone() const;
-};
-
-struct TupleItem
-{
- ::AST::MetaItems m_attrs;
- bool m_is_public;
- TypeRef m_type;
-
- //TupleItem() {}
-
- TupleItem(::AST::MetaItems attrs, bool is_pub, TypeRef ty):
- m_attrs( mv$(attrs) ),
- m_is_public(is_pub),
- m_type( mv$(ty) )
- {
- }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const TupleItem& x) {
- return os << (x.m_is_public ? "pub " : "") << x.m_type;
- }
-
- TupleItem clone() const;
-};
-
-class TypeAlias
-{
- GenericParams m_params;
- TypeRef m_type;
-public:
- //TypeAlias() {}
- TypeAlias(GenericParams params, TypeRef type):
- m_params( move(params) ),
- m_type( move(type) )
- {}
-
- const GenericParams& params() const { return m_params; }
- const TypeRef& type() const { return m_type; }
-
- GenericParams& params() { return m_params; }
- TypeRef& type() { return m_type; }
-
- TypeAlias clone() const;
-};
-
-class Static
-{
-public:
- enum Class
- {
- CONST,
- STATIC,
- MUT,
- };
-private:
- Class m_class;
- TypeRef m_type;
- Expr m_value;
-public:
- //Static():
- // m_class(CONST)
- //{}
- Static(Class s_class, TypeRef type, Expr value):
- m_class(s_class),
- m_type( move(type) ),
- m_value( move(value) )
- {}
-
- const Class& s_class() const { return m_class; }
- const TypeRef& type() const { return m_type; }
- const Expr& value() const { return m_value; }
-
- TypeRef& type() { return m_type; }
- Expr& value() { return m_value; }
-
- Static clone() const;
-};
-
-class Function
-{
-public:
- typedef ::std::vector< ::std::pair<AST::Pattern,TypeRef> > Arglist;
-
-private:
- Span m_span;
- //::std::string m_lifetime;
- GenericParams m_params;
- Expr m_code;
- TypeRef m_rettype;
- Arglist m_args;
-
- // TODO: ABI, const, and unsafe
- ::std::string m_abi;
- bool m_is_const;
- bool m_is_unsafe;
- bool m_is_variadic; // extern only
-public:
- Function(const Function&) = delete;
- Function& operator=(const Function&) = delete;
- Function(Function&&) = default;
- Function& operator=(Function&&) = default;
-
- //Function() {}
- Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args);
-
- void set_code(Expr code) { m_code = ::std::move(code); }
-
- const ::std::string& abi() const { return m_abi; };
- bool is_const() const { return m_is_const; }
- bool is_unsafe() const { return m_is_unsafe; }
- bool is_variadic() const { return m_is_variadic; }
-
- const GenericParams& params() const { return m_params; }
- GenericParams& params() { return m_params; }
- const Expr& code() const { return m_code; }
- Expr& code() { return m_code; }
- const TypeRef& rettype() const { return m_rettype; }
- TypeRef& rettype() { return m_rettype; }
- const Arglist& args() const { return m_args; }
- Arglist& args() { return m_args; }
-
- Function clone() const;
-};
-
-class Trait
-{
- GenericParams m_params;
- ::std::vector< Spanned<AST::Path> > m_supertraits;
-
- bool m_is_marker;
- NamedList<Item> m_items;
-public:
- Trait():
- m_is_marker(false)
- {}
- Trait(GenericParams params, ::std::vector< Spanned<Path> > supertraits):
- m_params( mv$(params) ),
- m_supertraits( mv$(supertraits) ),
- m_is_marker(false)
- {
- }
-
- const GenericParams& params() const { return m_params; }
- GenericParams& params() { return m_params; }
- const ::std::vector<Spanned<Path> >& supertraits() const { return m_supertraits; }
- ::std::vector<Spanned<Path> >& supertraits() { return m_supertraits; }
-
- const NamedList<Item>& items() const { return m_items; }
- NamedList<Item>& items() { return m_items; }
-
- void add_type(::std::string name, TypeRef type);
- void add_function(::std::string name, Function fcn);
- void add_static(::std::string name, Static v);
-
- void set_is_marker();
- bool is_marker() const;
-
- bool has_named_item(const ::std::string& name, bool& out_is_fcn) const;
-
- Trait clone() const;
-};
-
-TAGGED_UNION_EX(EnumVariantData, (), Value,
- (
- (Value, struct {
- ::AST::Expr m_value;
- }),
- (Tuple, struct {
- ::std::vector<TypeRef> m_sub_types;
- }),
- (Struct, struct {
- ::std::vector<StructItem> m_fields;
- })
- ),
- (), (),
- (
- public:
- )
- );
-
-struct EnumVariant
-{
- MetaItems m_attrs;
- ::std::string m_name;
- EnumVariantData m_data;
-
- EnumVariant()
- {
- }
-
- EnumVariant(MetaItems attrs, ::std::string name, Expr&& value):
- m_attrs( mv$(attrs) ),
- m_name( mv$(name) ),
- m_data( EnumVariantData::make_Value({mv$(value)}) )
- {
- }
-
- EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<TypeRef> sub_types):
- m_attrs( mv$(attrs) ),
- m_name( ::std::move(name) ),
- m_data( EnumVariantData::make_Tuple( {mv$(sub_types)} ) )
- {
- }
-
- EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<StructItem> fields):
- m_attrs( mv$(attrs) ),
- m_name( ::std::move(name) ),
- m_data( EnumVariantData::make_Struct( {mv$(fields)} ) )
- {
- }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const EnumVariant& x)
- {
- os << "EnumVariant(" << x.m_name;
- TU_MATCH(EnumVariantData, (x.m_data), (e),
- (Value,
- os << " = " << e.m_value;
- ),
- (Tuple,
- os << "(" << e.m_sub_types << ")";
- ),
- (Struct,
- os << " { " << e.m_fields << " }";
- )
- )
- return os << ")";
- }
-};
-
-class Enum
-{
- GenericParams m_params;
- ::std::vector<EnumVariant> m_variants;
-public:
- Enum() {}
- Enum( GenericParams params, ::std::vector<EnumVariant> variants ):
- m_params( move(params) ),
- m_variants( move(variants) )
- {}
-
- const GenericParams& params() const { return m_params; }
- GenericParams& params() { return m_params; }
- const ::std::vector<EnumVariant>& variants() const { return m_variants; }
- ::std::vector<EnumVariant>& variants() { return m_variants; }
-
- Enum clone() const;
-};
-
-TAGGED_UNION_EX(StructData, (), Struct,
- (
- (Tuple, struct {
- ::std::vector<TupleItem> ents;
- }),
- (Struct, struct {
- ::std::vector<StructItem> ents;
- })
- ),
- (),(),
- (
- public:
- )
- );
-
-class Struct
-{
- GenericParams m_params;
-public:
- StructData m_data;
-
- Struct() {}
- Struct( GenericParams params, ::std::vector<StructItem> fields ):
- m_params( move(params) ),
- m_data( StructData::make_Struct({mv$(fields)}) )
- {}
- Struct( GenericParams params, ::std::vector<TupleItem> fields ):
- m_params( move(params) ),
- m_data( StructData::make_Tuple({mv$(fields)}) )
- {}
-
- const GenericParams& params() const { return m_params; }
- GenericParams& params() { return m_params; }
-
- Struct clone() const;
-};
-
-class Union
-{
-public:
- GenericParams m_params;
- ::std::vector<StructItem> m_variants;
-
- Union( GenericParams params, ::std::vector<StructItem> fields ):
- m_params( move(params) ),
- m_variants( mv$(fields) )
- {}
-
- Union clone() const;
-};
-
-class ImplDef
-{
- Span m_span;
- MetaItems m_attrs;
- GenericParams m_params;
- Spanned<Path> m_trait;
- TypeRef m_type;
-public:
- //ImplDef() {}
- ImplDef(ImplDef&&) /*noexcept*/ = default;
- ImplDef(Span sp, MetaItems attrs, GenericParams params, Spanned<Path> trait_type, TypeRef impl_type):
- m_span( mv$(sp) ),
- m_attrs( mv$(attrs) ),
- m_params( mv$(params) ),
- m_trait( mv$(trait_type) ),
- m_type( mv$(impl_type) )
- {}
- ImplDef& operator=(ImplDef&&) = default;
-
- // Accessors
- const Span& span() const { return m_span; }
- const MetaItems& attrs() const { return m_attrs; }
- MetaItems& attrs() { return m_attrs; }
-
- const GenericParams& params() const { return m_params; }
- GenericParams& params() { return m_params; }
- const Spanned<Path>& trait() const { return m_trait; }
- Spanned<Path>& trait() { return m_trait; }
- const TypeRef& type() const { return m_type; }
- TypeRef& type() { return m_type; }
-
-
- friend ::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl);
-};
-
-class Impl
-{
-public:
- struct ImplItem {
- bool is_pub; // Ignored for trait impls
- bool is_specialisable;
- ::std::string name;
-
- ::std::unique_ptr<Item> data;
- };
-
-private:
- ImplDef m_def;
- Span m_span;
-
- ::std::vector< ImplItem > m_items;
- //NamedList<TypeRef> m_types;
- //NamedList<Function> m_functions;
- //NamedList<Static> m_statics;
-
-public:
- //Impl() {}
- Impl(Impl&&) /*noexcept*/ = default;
- Impl(ImplDef def):
- m_def( mv$(def) )
- {}
- Impl& operator=(Impl&&) = default;
-
- void add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn);
- void add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type);
- void add_static(bool is_public, bool is_specialisable, ::std::string name, Static v);
- void add_macro_invocation( MacroInvocation inv );
-
- const ImplDef& def() const { return m_def; }
- ImplDef& def() { return m_def; }
- const ::std::vector<ImplItem>& items() const { return m_items; }
- ::std::vector<ImplItem>& items() { return m_items; }
-
- bool has_named_item(const ::std::string& name) const;
-
- friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl);
-
-private:
-};
-
-struct UseStmt
-{
- Span sp;
- ::AST::Path path;
- ::AST::PathBinding alt_binding;
-
- UseStmt()
- {}
- UseStmt(Span sp, Path p):
- sp(sp),
- path(p)
- {
- }
-
- UseStmt clone() const;
-
- friend ::std::ostream& operator<<(::std::ostream& os, const UseStmt& x);
-};
-
-class ExternBlock
-{
- ::std::string m_abi;
- ::std::vector< Named<Item>> m_items;
-public:
- ExternBlock(::std::string abi):
- m_abi( mv$(abi) )
- {}
-
- const ::std::string& abi() const { return m_abi; }
-
- void add_item(Named<Item> named_item);
-
- // NOTE: Only Function and Static are valid.
- ::std::vector<Named<Item>>& items() { return m_items; }
- const ::std::vector<Named<Item>>& items() const { return m_items; }
-
- ExternBlock clone() const;
-};
-
-/// Representation of a parsed (and being converted) function
-class Module
-{
- ::AST::Path m_my_path;
-
- // Module-level items
- /// General items
- ::std::vector<Named<Item>> m_items;
-
- // --- Runtime caches and state ---
- ::std::vector< ::std::shared_ptr<Module> > m_anon_modules;
-
- ::std::vector< NamedNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
- ::std::vector< Named<MacroRulesPtr> > m_macros;
-
-public:
- struct FileInfo
- {
- bool controls_dir = false;
- ::std::string path = "!";
- };
-
- FileInfo m_file_info;
-
- bool m_insert_prelude = true; // Set to false by `#[no_prelude]` handler
- char m_index_populated = 0; // 0 = no, 1 = partial, 2 = complete
- struct IndexEnt {
- bool is_pub; // Used as part of glob import checking
- bool is_import; // Set if this item has a path that isn't `mod->path() + name`
- ::AST::Path path;
- };
-
- // TODO: Document difference between namespace and Type
- ::std::unordered_map< ::std::string, IndexEnt > m_namespace_items;
- ::std::unordered_map< ::std::string, IndexEnt > m_type_items;
- ::std::unordered_map< ::std::string, IndexEnt > m_value_items;
-
-public:
- Module() {}
- Module(::AST::Path path):
- m_my_path( mv$(path) )
- {
- }
-
- bool is_anon() const {
- return m_my_path.nodes().size() > 0 && m_my_path.nodes().back().name()[0] == '#';
- }
-
- /// Create an anon module (for use inside expressions)
- ::std::shared_ptr<AST::Module> add_anon();
-
- void add_item(Named<Item> item);
- void add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs);
- void add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, MetaItems attrs);
- void add_alias(bool is_public, UseStmt path, ::std::string name, MetaItems attrs);
- void add_macro_invocation(MacroInvocation item);
-
- void add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro);
- void add_macro_import(::std::string name, const MacroRules& mr);
-
-
-
- const ::AST::Path& path() const { return m_my_path; }
-
- ::std::vector<Named<Item>>& items() { return m_items; }
- const ::std::vector<Named<Item>>& items() const { return m_items; }
-
- ::std::vector< ::std::shared_ptr<Module> >& anon_mods() { return m_anon_modules; }
- const ::std::vector< ::std::shared_ptr<Module> >& anon_mods() const { return m_anon_modules; }
-
-
- NamedList<MacroRulesPtr>& macros() { return m_macros; }
- const NamedList<MacroRulesPtr>& macros() const { return m_macros; }
- const ::std::vector<NamedNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
-
-private:
- void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name);
-};
-
-TAGGED_UNION_EX(Item, (), None,
- (
- (None, struct {} ),
- (MacroInv, MacroInvocation),
- (Use, UseStmt),
-
- // Nameless items
- (ExternBlock, ExternBlock),
- (Impl, Impl),
- (NegImpl, ImplDef),
-
- (Module, Module),
- (Crate, struct {
- ::std::string name;
- }),
-
- (Type, TypeAlias),
- (Struct, Struct),
- (Enum, Enum),
- (Union, Union),
- (Trait, Trait),
-
- (Function, Function),
- (Static, Static)
- ),
-
- (, attrs(mv$(x.attrs))), (attrs = mv$(x.attrs);),
- (
- public:
- MetaItems attrs;
- Span span;
-
- Item clone() const;
- )
- );
-
-
-struct ImplRef
-{
- const Impl& impl;
- ::std::vector<TypeRef> params;
-
- ImplRef(const Impl& impl, ::std::vector<TypeRef> params):
- impl(impl),
- params( mv$(params) )
- {}
-
- ::rust::option<char> find_named_item(const ::std::string& name) const;
-};
-
-} // namespace AST
-
-class GenericResolveClosure
-{
- const ::AST::GenericParams& m_params;
- const ::std::vector<TypeRef>& m_args;
-public:
- GenericResolveClosure(const AST::GenericParams& params, const ::std::vector<TypeRef>& args):
- m_params(params),
- m_args(args)
- {}
- const TypeRef& operator()(const char *argname) {
- for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
- {
- if( m_params.ty_params()[i].name() == argname ) {
- return m_args.at(i);
- }
- }
- throw ::std::runtime_error("BUGCHECK - Unknown arg in field type");
- }
-};
-
-
-#endif // AST_HPP_INCLUDED
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * ast/ast.hpp
+ * - Core AST header
+ */
+#ifndef AST_HPP_INCLUDED
+#define AST_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include "../coretypes.hpp"
+#include <memory>
+#include <map>
+#include <unordered_map>
+#include <algorithm>
+
+#include "../parse/tokentree.hpp"
+#include "types.hpp"
+#include <serialise.hpp>
+
+#include <ast/pattern.hpp>
+#include <ast/attrs.hpp>
+#include <ast/expr_ptr.hpp>
+#include <ast/item.hpp>
+#include <ast/macro.hpp> // MacroInvocation
+
+#include "generics.hpp"
+
+#include <macro_rules/macro_rules_ptr.hpp>
+
+namespace AST {
+
+class Crate;
+
+class Module;
+class Item;
+
+using ::std::unique_ptr;
+using ::std::move;
+
+enum eItemType
+{
+ ITEM_TRAIT,
+ ITEM_STRUCT,
+ ITEM_FN,
+};
+
+struct StructItem
+{
+ ::AST::MetaItems m_attrs;
+ bool m_is_public;
+ ::std::string m_name;
+ TypeRef m_type;
+
+ //StructItem() {}
+
+ StructItem(::AST::MetaItems attrs, bool is_pub, ::std::string name, TypeRef ty):
+ m_attrs( mv$(attrs) ),
+ m_is_public(is_pub),
+ m_name( mv$(name) ),
+ m_type( mv$(ty) )
+ {
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const StructItem& x) {
+ return os << (x.m_is_public ? "pub " : "") << x.m_name << ": " << x.m_type;
+ }
+
+ StructItem clone() const;
+};
+
+struct TupleItem
+{
+ ::AST::MetaItems m_attrs;
+ bool m_is_public;
+ TypeRef m_type;
+
+ //TupleItem() {}
+
+ TupleItem(::AST::MetaItems attrs, bool is_pub, TypeRef ty):
+ m_attrs( mv$(attrs) ),
+ m_is_public(is_pub),
+ m_type( mv$(ty) )
+ {
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TupleItem& x) {
+ return os << (x.m_is_public ? "pub " : "") << x.m_type;
+ }
+
+ TupleItem clone() const;
+};
+
+class TypeAlias
+{
+ GenericParams m_params;
+ TypeRef m_type;
+public:
+ //TypeAlias() {}
+ TypeAlias(GenericParams params, TypeRef type):
+ m_params( move(params) ),
+ m_type( move(type) )
+ {}
+
+ const GenericParams& params() const { return m_params; }
+ const TypeRef& type() const { return m_type; }
+
+ GenericParams& params() { return m_params; }
+ TypeRef& type() { return m_type; }
+
+ TypeAlias clone() const;
+};
+
+class Static
+{
+public:
+ enum Class
+ {
+ CONST,
+ STATIC,
+ MUT,
+ };
+private:
+ Class m_class;
+ TypeRef m_type;
+ Expr m_value;
+public:
+ //Static():
+ // m_class(CONST)
+ //{}
+ Static(Class s_class, TypeRef type, Expr value):
+ m_class(s_class),
+ m_type( move(type) ),
+ m_value( move(value) )
+ {}
+
+ const Class& s_class() const { return m_class; }
+ const TypeRef& type() const { return m_type; }
+ const Expr& value() const { return m_value; }
+
+ TypeRef& type() { return m_type; }
+ Expr& value() { return m_value; }
+
+ Static clone() const;
+};
+
+class Function
+{
+public:
+ typedef ::std::vector< ::std::pair<AST::Pattern,TypeRef> > Arglist;
+
+private:
+ Span m_span;
+ //::std::string m_lifetime;
+ GenericParams m_params;
+ Expr m_code;
+ TypeRef m_rettype;
+ Arglist m_args;
+
+ // TODO: ABI, const, and unsafe
+ ::std::string m_abi;
+ bool m_is_const;
+ bool m_is_unsafe;
+ bool m_is_variadic; // extern only
+public:
+ Function(const Function&) = delete;
+ Function& operator=(const Function&) = delete;
+ Function(Function&&) = default;
+ Function& operator=(Function&&) = default;
+
+ //Function() {}
+ Function(Span sp, GenericParams params, ::std::string abi, bool is_unsafe, bool is_const, bool is_variadic, TypeRef ret_type, Arglist args);
+
+ void set_code(Expr code) { m_code = ::std::move(code); }
+
+ const ::std::string& abi() const { return m_abi; };
+ bool is_const() const { return m_is_const; }
+ bool is_unsafe() const { return m_is_unsafe; }
+ bool is_variadic() const { return m_is_variadic; }
+
+ const GenericParams& params() const { return m_params; }
+ GenericParams& params() { return m_params; }
+ const Expr& code() const { return m_code; }
+ Expr& code() { return m_code; }
+ const TypeRef& rettype() const { return m_rettype; }
+ TypeRef& rettype() { return m_rettype; }
+ const Arglist& args() const { return m_args; }
+ Arglist& args() { return m_args; }
+
+ Function clone() const;
+};
+
+class Trait
+{
+ GenericParams m_params;
+ ::std::vector< Spanned<AST::Path> > m_supertraits;
+
+ bool m_is_marker;
+ NamedList<Item> m_items;
+public:
+ Trait():
+ m_is_marker(false)
+ {}
+ Trait(GenericParams params, ::std::vector< Spanned<Path> > supertraits):
+ m_params( mv$(params) ),
+ m_supertraits( mv$(supertraits) ),
+ m_is_marker(false)
+ {
+ }
+
+ const GenericParams& params() const { return m_params; }
+ GenericParams& params() { return m_params; }
+ const ::std::vector<Spanned<Path> >& supertraits() const { return m_supertraits; }
+ ::std::vector<Spanned<Path> >& supertraits() { return m_supertraits; }
+
+ const NamedList<Item>& items() const { return m_items; }
+ NamedList<Item>& items() { return m_items; }
+
+ void add_type(::std::string name, TypeRef type);
+ void add_function(::std::string name, Function fcn);
+ void add_static(::std::string name, Static v);
+
+ void set_is_marker();
+ bool is_marker() const;
+
+ bool has_named_item(const ::std::string& name, bool& out_is_fcn) const;
+
+ Trait clone() const;
+};
+
+TAGGED_UNION_EX(EnumVariantData, (), Value,
+ (
+ (Value, struct {
+ ::AST::Expr m_value;
+ }),
+ (Tuple, struct {
+ ::std::vector<TypeRef> m_sub_types;
+ }),
+ (Struct, struct {
+ ::std::vector<StructItem> m_fields;
+ })
+ ),
+ (), (),
+ (
+ public:
+ )
+ );
+
+struct EnumVariant
+{
+ MetaItems m_attrs;
+ ::std::string m_name;
+ EnumVariantData m_data;
+
+ EnumVariant()
+ {
+ }
+
+ EnumVariant(MetaItems attrs, ::std::string name, Expr&& value):
+ m_attrs( mv$(attrs) ),
+ m_name( mv$(name) ),
+ m_data( EnumVariantData::make_Value({mv$(value)}) )
+ {
+ }
+
+ EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<TypeRef> sub_types):
+ m_attrs( mv$(attrs) ),
+ m_name( ::std::move(name) ),
+ m_data( EnumVariantData::make_Tuple( {mv$(sub_types)} ) )
+ {
+ }
+
+ EnumVariant(MetaItems attrs, ::std::string name, ::std::vector<StructItem> fields):
+ m_attrs( mv$(attrs) ),
+ m_name( ::std::move(name) ),
+ m_data( EnumVariantData::make_Struct( {mv$(fields)} ) )
+ {
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const EnumVariant& x)
+ {
+ os << "EnumVariant(" << x.m_name;
+ TU_MATCH(EnumVariantData, (x.m_data), (e),
+ (Value,
+ os << " = " << e.m_value;
+ ),
+ (Tuple,
+ os << "(" << e.m_sub_types << ")";
+ ),
+ (Struct,
+ os << " { " << e.m_fields << " }";
+ )
+ )
+ return os << ")";
+ }
+};
+
+class Enum
+{
+ GenericParams m_params;
+ ::std::vector<EnumVariant> m_variants;
+public:
+ Enum() {}
+ Enum( GenericParams params, ::std::vector<EnumVariant> variants ):
+ m_params( move(params) ),
+ m_variants( move(variants) )
+ {}
+
+ const GenericParams& params() const { return m_params; }
+ GenericParams& params() { return m_params; }
+ const ::std::vector<EnumVariant>& variants() const { return m_variants; }
+ ::std::vector<EnumVariant>& variants() { return m_variants; }
+
+ Enum clone() const;
+};
+
+TAGGED_UNION_EX(StructData, (), Struct,
+ (
+ (Tuple, struct {
+ ::std::vector<TupleItem> ents;
+ }),
+ (Struct, struct {
+ ::std::vector<StructItem> ents;
+ })
+ ),
+ (),(),
+ (
+ public:
+ )
+ );
+
+class Struct
+{
+ GenericParams m_params;
+public:
+ StructData m_data;
+
+ Struct() {}
+ Struct( GenericParams params, ::std::vector<StructItem> fields ):
+ m_params( move(params) ),
+ m_data( StructData::make_Struct({mv$(fields)}) )
+ {}
+ Struct( GenericParams params, ::std::vector<TupleItem> fields ):
+ m_params( move(params) ),
+ m_data( StructData::make_Tuple({mv$(fields)}) )
+ {}
+
+ const GenericParams& params() const { return m_params; }
+ GenericParams& params() { return m_params; }
+
+ Struct clone() const;
+};
+
+class Union
+{
+public:
+ GenericParams m_params;
+ ::std::vector<StructItem> m_variants;
+
+ Union( GenericParams params, ::std::vector<StructItem> fields ):
+ m_params( move(params) ),
+ m_variants( mv$(fields) )
+ {}
+
+ Union clone() const;
+};
+
+class ImplDef
+{
+ Span m_span;
+ MetaItems m_attrs;
+ GenericParams m_params;
+ Spanned<Path> m_trait;
+ TypeRef m_type;
+public:
+ //ImplDef() {}
+ ImplDef(ImplDef&&) /*noexcept*/ = default;
+ ImplDef(Span sp, MetaItems attrs, GenericParams params, Spanned<Path> trait_type, TypeRef impl_type):
+ m_span( mv$(sp) ),
+ m_attrs( mv$(attrs) ),
+ m_params( mv$(params) ),
+ m_trait( mv$(trait_type) ),
+ m_type( mv$(impl_type) )
+ {}
+ ImplDef& operator=(ImplDef&&) = default;
+
+ // Accessors
+ const Span& span() const { return m_span; }
+ const MetaItems& attrs() const { return m_attrs; }
+ MetaItems& attrs() { return m_attrs; }
+
+ const GenericParams& params() const { return m_params; }
+ GenericParams& params() { return m_params; }
+ const Spanned<Path>& trait() const { return m_trait; }
+ Spanned<Path>& trait() { return m_trait; }
+ const TypeRef& type() const { return m_type; }
+ TypeRef& type() { return m_type; }
+
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl);
+};
+
+class Impl
+{
+public:
+ struct ImplItem {
+ bool is_pub; // Ignored for trait impls
+ bool is_specialisable;
+ ::std::string name;
+
+ ::std::unique_ptr<Item> data;
+ };
+
+private:
+ ImplDef m_def;
+ Span m_span;
+
+ ::std::vector< ImplItem > m_items;
+ //NamedList<TypeRef> m_types;
+ //NamedList<Function> m_functions;
+ //NamedList<Static> m_statics;
+
+public:
+ //Impl() {}
+ Impl(Impl&&) /*noexcept*/ = default;
+ Impl(ImplDef def):
+ m_def( mv$(def) )
+ {}
+ Impl& operator=(Impl&&) = default;
+
+ void add_function(bool is_public, bool is_specialisable, ::std::string name, Function fcn);
+ void add_type(bool is_public, bool is_specialisable, ::std::string name, TypeRef type);
+ void add_static(bool is_public, bool is_specialisable, ::std::string name, Static v);
+ void add_macro_invocation( MacroInvocation inv );
+
+ const ImplDef& def() const { return m_def; }
+ ImplDef& def() { return m_def; }
+ const ::std::vector<ImplItem>& items() const { return m_items; }
+ ::std::vector<ImplItem>& items() { return m_items; }
+
+ bool has_named_item(const ::std::string& name) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl);
+
+private:
+};
+
+struct UseStmt
+{
+ Span sp;
+ ::AST::Path path;
+ ::AST::PathBinding alt_binding;
+
+ UseStmt()
+ {}
+ UseStmt(Span sp, Path p):
+ sp(sp),
+ path(p)
+ {
+ }
+
+ UseStmt clone() const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const UseStmt& x);
+};
+
+class ExternBlock
+{
+ ::std::string m_abi;
+ ::std::vector< Named<Item>> m_items;
+public:
+ ExternBlock(::std::string abi):
+ m_abi( mv$(abi) )
+ {}
+
+ const ::std::string& abi() const { return m_abi; }
+
+ void add_item(Named<Item> named_item);
+
+ // NOTE: Only Function and Static are valid.
+ ::std::vector<Named<Item>>& items() { return m_items; }
+ const ::std::vector<Named<Item>>& items() const { return m_items; }
+
+ ExternBlock clone() const;
+};
+
+/// Representation of a parsed (and being converted) function
+class Module
+{
+ ::AST::Path m_my_path;
+
+ // Module-level items
+ /// General items
+ ::std::vector<Named<Item>> m_items;
+
+ // --- Runtime caches and state ---
+ ::std::vector< ::std::shared_ptr<Module> > m_anon_modules;
+
+ ::std::vector< NamedNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
+ ::std::vector< Named<MacroRulesPtr> > m_macros;
+
+public:
+ struct FileInfo
+ {
+ bool controls_dir = false;
+ ::std::string path = "!";
+ };
+
+ FileInfo m_file_info;
+
+ bool m_insert_prelude = true; // Set to false by `#[no_prelude]` handler
+ char m_index_populated = 0; // 0 = no, 1 = partial, 2 = complete
+ struct IndexEnt {
+ bool is_pub; // Used as part of glob import checking
+ bool is_import; // Set if this item has a path that isn't `mod->path() + name`
+ ::AST::Path path;
+ };
+
+ // TODO: Document difference between namespace and Type
+ ::std::unordered_map< ::std::string, IndexEnt > m_namespace_items;
+ ::std::unordered_map< ::std::string, IndexEnt > m_type_items;
+ ::std::unordered_map< ::std::string, IndexEnt > m_value_items;
+
+public:
+ Module() {}
+ Module(::AST::Path path):
+ m_my_path( mv$(path) )
+ {
+ }
+
+ bool is_anon() const {
+ return m_my_path.nodes().size() > 0 && m_my_path.nodes().back().name()[0] == '#';
+ }
+
+ /// Create an anon module (for use inside expressions)
+ ::std::shared_ptr<AST::Module> add_anon();
+
+ void add_item(Named<Item> item);
+ void add_item(bool is_pub, ::std::string name, Item it, MetaItems attrs);
+ void add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, MetaItems attrs);
+ void add_alias(bool is_public, UseStmt path, ::std::string name, MetaItems attrs);
+ void add_macro_invocation(MacroInvocation item);
+
+ void add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro);
+ void add_macro_import(::std::string name, const MacroRules& mr);
+
+
+
+ const ::AST::Path& path() const { return m_my_path; }
+
+ ::std::vector<Named<Item>>& items() { return m_items; }
+ const ::std::vector<Named<Item>>& items() const { return m_items; }
+
+ ::std::vector< ::std::shared_ptr<Module> >& anon_mods() { return m_anon_modules; }
+ const ::std::vector< ::std::shared_ptr<Module> >& anon_mods() const { return m_anon_modules; }
+
+
+ NamedList<MacroRulesPtr>& macros() { return m_macros; }
+ const NamedList<MacroRulesPtr>& macros() const { return m_macros; }
+ const ::std::vector<NamedNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
+
+private:
+ void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name);
+};
+
+TAGGED_UNION_EX(Item, (), None,
+ (
+ (None, struct {} ),
+ (MacroInv, MacroInvocation),
+ (Use, UseStmt),
+
+ // Nameless items
+ (ExternBlock, ExternBlock),
+ (Impl, Impl),
+ (NegImpl, ImplDef),
+
+ (Module, Module),
+ (Crate, struct {
+ ::std::string name;
+ }),
+
+ (Type, TypeAlias),
+ (Struct, Struct),
+ (Enum, Enum),
+ (Union, Union),
+ (Trait, Trait),
+
+ (Function, Function),
+ (Static, Static)
+ ),
+
+ (, attrs(mv$(x.attrs))), (attrs = mv$(x.attrs);),
+ (
+ public:
+ MetaItems attrs;
+ Span span;
+
+ Item clone() const;
+ )
+ );
+
+
+struct ImplRef
+{
+ const Impl& impl;
+ ::std::vector<TypeRef> params;
+
+ ImplRef(const Impl& impl, ::std::vector<TypeRef> params):
+ impl(impl),
+ params( mv$(params) )
+ {}
+
+ ::rust::option<char> find_named_item(const ::std::string& name) const;
+};
+
+} // namespace AST
+
+class GenericResolveClosure
+{
+ const ::AST::GenericParams& m_params;
+ const ::std::vector<TypeRef>& m_args;
+public:
+ GenericResolveClosure(const AST::GenericParams& params, const ::std::vector<TypeRef>& args):
+ m_params(params),
+ m_args(args)
+ {}
+ const TypeRef& operator()(const char *argname) {
+ for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
+ {
+ if( m_params.ty_params()[i].name() == argname ) {
+ return m_args.at(i);
+ }
+ }
+ throw ::std::runtime_error("BUGCHECK - Unknown arg in field type");
+ }
+};
+
+
+#endif // AST_HPP_INCLUDED
diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp
index 372d888a..28bfec96 100644
--- a/src/ast/attrs.hpp
+++ b/src/ast/attrs.hpp
@@ -12,7 +12,7 @@ class MetaItems
public:
Span m_span;
::std::vector<MetaItem> m_items;
-
+
virtual ~MetaItems();
MetaItems() {}
MetaItems(MetaItems&&) = default;
@@ -23,17 +23,17 @@ public:
m_items( mv$(items) )
{
}
-
+
void push_back(MetaItem i);
-
+
MetaItems clone() const;
-
+
MetaItem* get(const char *name) { return const_cast<MetaItem*>( const_cast<const MetaItems*>(this)->get(name)); }
const MetaItem* get(const char *name) const;
bool has(const char *name) const {
return get(name) != 0;
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const MetaItems& x) {
return os << "[" << x.m_items << "]";
}
@@ -74,21 +74,21 @@ public:
m_data( MetaItemData::make_List({mv$(items)}) )
{
}
-
+
MetaItem clone() const;
-
+
void mark_used() {}
const ::std::string& name() const { return m_name; }
-
+
bool has_noarg() const { return m_data.is_None(); }
-
+
bool has_string() const { return m_data.is_String(); }
const ::std::string& string() const { return m_data.as_String().val; }
-
+
bool has_sub_items() const { return m_data.is_List(); }
const ::std::vector<MetaItem>& items() const { return m_data.as_List().sub_items; }
::std::vector<MetaItem>& items() { return m_data.as_List().sub_items; }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const MetaItem& x) {
os << x.m_name;
TU_MATCH(MetaItemData, (x.m_data), (e),
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp
index b18ca662..58a08980 100644
--- a/src/ast/crate.cpp
+++ b/src/ast/crate.cpp
@@ -61,13 +61,13 @@ void Crate::load_externs()
}
};
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" )
@@ -105,7 +105,7 @@ void Crate::load_extern_crate(Span sp, const ::std::string& name)
::std::string path;
for(const auto& p : paths){
path = p + "lib" + name + ".hir";
-
+
if( ::std::ifstream(path).good() ) {
break ;
}
@@ -113,10 +113,10 @@ void Crate::load_extern_crate(Span sp, const ::std::string& name)
if( !::std::ifstream(path).good() ) {
ERROR(sp, E0000, "Unable to locate crate '" << name << "'");
}
-
+
auto res = m_extern_crates.insert(::std::make_pair( name, ExternCrate { name, path } ));
auto crate_ext_list = mv$( res.first->second.m_hir->m_ext_crates );
-
+
// Load referenced crates
for( const auto& ext : crate_ext_list )
{
@@ -132,7 +132,7 @@ ExternCrate::ExternCrate(const ::std::string& name, const ::std::string& path):
{
TRACE_FUNCTION_F("name=" << name << ", path='" << path << "'");
m_hir = HIR_Deserialise(path, name);
-
+
m_hir->post_load_update(name);
}
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
index 31076c02..c51dacf5 100644
--- a/src/ast/crate.hpp
+++ b/src/ast/crate.hpp
@@ -14,14 +14,14 @@ class Crate
{
public:
::AST::MetaItems m_attrs;
-
+
::std::map< ::std::string, ::AST::Path> m_lang_items;
public:
Module m_root_module;
::std::map< ::std::string, ExternCrate> m_extern_crates;
// Mapping filled by searching for (?visible) macros with is_pub=true
::std::map< ::std::string, const MacroRules*> m_exported_macros;
-
+
enum class Type {
Unknown,
RustLib,
@@ -37,15 +37,15 @@ public:
::std::string m_crate_name;
AST::Path m_prelude_path;
-
+
Crate();
const Module& root_module() const { return m_root_module; }
Module& root_module() { return m_root_module; }
-
+
/// Load referenced crates
void load_externs();
-
+
void load_extern_crate(Span sp, const ::std::string& name);
};
@@ -55,14 +55,14 @@ class ExternCrate
public:
::std::string m_name;
::HIR::CratePtr m_hir;
-
+
ExternCrate(const ::std::string& name, const ::std::string& path);
-
+
ExternCrate(ExternCrate&&) = default;
ExternCrate& operator=(ExternCrate&&) = default;
ExternCrate(const ExternCrate&) = delete;
ExternCrate& operator=(const ExternCrate& ) = delete;
-
+
void with_all_macros(::std::function<void(const ::std::string& , const MacroRules&)> cb) const;
const MacroRules* find_macro_rules(const ::std::string& name) const;
};
diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp
index 4773a845..07343de4 100644
--- a/src/ast/dump.cpp
+++ b/src/ast/dump.cpp
@@ -1,7 +1,7 @@
/*
* MRustC - Mutabah's Rust Compiler
* - By John Hodge (Mutabah/thePowersGang)
- *
+ *
* ast/dump.cpp
* - Dumps the AST of a crate as rust code (annotated)
*/
@@ -30,7 +30,7 @@ public:
m_indent_level(0),
m_expr_root(false)
{}
-
+
void handle_module(const AST::Module& mod);
void handle_struct(const AST::Struct& s);
void handle_enum(const AST::Enum& s);
@@ -170,7 +170,7 @@ public:
virtual void visit(AST::ExprNode_Loop& n) override {
bool expr_root = m_expr_root;
m_expr_root = false;
-
+
switch(n.m_type)
{
case AST::ExprNode_Loop::LOOP:
@@ -193,7 +193,7 @@ public:
AST::NodeVisitor::visit(n.m_cond);
break;
}
-
+
if( expr_root )
{
m_os << "\n";
@@ -211,7 +211,7 @@ public:
m_expr_root = false;
m_os << "match ";
AST::NodeVisitor::visit(n.m_val);
-
+
if(expr_root)
{
m_os << "\n";
@@ -222,7 +222,7 @@ public:
m_os << " {\n";
inc_indent();
}
-
+
for( auto& arm : n.m_arms )
{
m_os << indent();
@@ -245,7 +245,7 @@ public:
dec_indent();
m_os << ",\n";
}
-
+
if(expr_root)
{
m_os << indent() << "}";
@@ -261,7 +261,7 @@ public:
m_expr_root = false;
m_os << "if ";
AST::NodeVisitor::visit(n.m_cond);
-
+
visit_if_common(expr_root, n.m_true, n.m_false);
}
virtual void visit(AST::ExprNode_IfLet& n) override {
@@ -271,7 +271,7 @@ public:
print_pattern(n.m_pattern, true);
m_os << " = ";
AST::NodeVisitor::visit(n.m_value);
-
+
visit_if_common(expr_root, n.m_true, n.m_false);
}
void visit_if_common(bool expr_root, const ::std::unique_ptr<AST::ExprNode>& tv, const ::std::unique_ptr<AST::ExprNode>& fv)
@@ -392,7 +392,7 @@ public:
m_expr_root = false;
m_os << "b\"" << n.m_value << "\"";
}
-
+
virtual void visit(AST::ExprNode_StructLiteral& n) override {
m_expr_root = false;
m_os << n.m_path << " {\n";
@@ -533,7 +533,7 @@ public:
case AST::ExprNode_UniOp::REFMUT: m_os << "&mut "; break;
case AST::ExprNode_UniOp::QMARK: break;
}
-
+
if( IS(*n.m_value, AST::ExprNode_BinOp) )
m_os << "(";
AST::NodeVisitor::visit(n.m_value);
@@ -553,14 +553,14 @@ private:
AST::NodeVisitor::visit(node);
m_os << ")";
}
-
+
void print_attrs(const AST::MetaItems& attrs);
void print_params(const AST::GenericParams& params);
void print_bounds(const AST::GenericParams& params);
void print_pattern_tuple(const AST::Pattern::TuplePat& v, bool is_refutable);
void print_pattern(const AST::Pattern& p, bool is_refutable);
void print_type(const TypeRef& t);
-
+
void inc_indent();
RepeatLitStr indent();
void dec_indent();
@@ -584,7 +584,7 @@ void RustPrinter::print_attrs(const AST::MetaItems& attrs)
void RustPrinter::handle_module(const AST::Module& mod)
{
bool need_nl = true;
-
+
for( const auto& i : mod.items() )
{
if( !i.data.is_Use() ) continue ;
@@ -608,12 +608,12 @@ void RustPrinter::handle_module(const AST::Module& mod)
m_os << ";\n";
}
need_nl = true;
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Module() ) continue ;
const auto& e = item.data.as_Module();
-
+
m_os << "\n";
m_os << indent() << (item.is_pub ? "pub " : "") << "mod " << item.name << "\n";
m_os << indent() << "{\n";
@@ -623,12 +623,12 @@ void RustPrinter::handle_module(const AST::Module& mod)
m_os << indent() << "}\n";
m_os << "\n";
}
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Type() ) continue ;
const auto& e = item.data.as_Type();
-
+
if(need_nl) {
m_os << "\n";
need_nl = false;
@@ -641,45 +641,45 @@ void RustPrinter::handle_module(const AST::Module& mod)
m_os << ";\n";
}
need_nl = true;
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Struct() ) continue ;
const auto& e = item.data.as_Struct();
-
+
m_os << "\n";
print_attrs(item.data.attrs);
m_os << indent() << (item.is_pub ? "pub " : "") << "struct " << item.name;
handle_struct(e);
}
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Enum() ) continue ;
const auto& e = item.data.as_Enum();
-
+
m_os << "\n";
print_attrs(item.data.attrs);
m_os << indent() << (item.is_pub ? "pub " : "") << "enum " << item.name;
handle_enum(e);
}
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Trait() ) continue ;
const auto& e = item.data.as_Trait();
-
+
m_os << "\n";
print_attrs(item.data.attrs);
m_os << indent() << (item.is_pub ? "pub " : "") << "trait " << item.name;
handle_trait(e);
}
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Static() ) continue ;
const auto& e = item.data.as_Static();
-
+
if(need_nl) {
m_os << "\n";
need_nl = false;
@@ -696,12 +696,12 @@ void RustPrinter::handle_module(const AST::Module& mod)
e.value().visit_nodes(*this);
m_os << ";\n";
}
-
+
for( const auto& item : mod.items() )
{
if( !item.data.is_Function() ) continue ;
const auto& e = item.data.as_Function();
-
+
m_os << "\n";
print_attrs(item.data.attrs);
handle_function(item.is_pub, item.name, e);
@@ -711,7 +711,7 @@ void RustPrinter::handle_module(const AST::Module& mod)
{
if( !item.data.is_Impl() ) continue ;
const auto& i = item.data.as_Impl();
-
+
m_os << "\n";
m_os << indent() << "impl";
print_params(i.def().params());
@@ -720,7 +720,7 @@ void RustPrinter::handle_module(const AST::Module& mod)
m_os << " " << i.def().trait().ent << " for";
}
m_os << " " << i.def().type() << "\n";
-
+
print_bounds(i.def().params());
m_os << indent() << "{\n";
inc_indent();
@@ -796,13 +796,13 @@ void RustPrinter::print_bounds(const AST::GenericParams& params)
m_os << indent() << "where\n";
inc_indent();
bool is_first = true;
-
+
for( const auto& b : params.bounds() )
{
if( !is_first )
m_os << ",\n";
is_first = false;
-
+
m_os << indent();
TU_MATCH(AST::GenericBound, (b), (ent),
(Lifetime,
@@ -829,7 +829,7 @@ void RustPrinter::print_bounds(const AST::GenericParams& params)
)
}
m_os << "\n";
-
+
dec_indent();
}
}
@@ -934,7 +934,7 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable)
m_os << v.leading;
m_os << ", ";
}
-
+
if(v.extra_bind.is_valid())
{
const auto& b = v.extra_bind;
@@ -955,7 +955,7 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable)
}
m_os << "..";
needs_comma = true;
-
+
if(v.trailing.size()) {
if( needs_comma ) {
m_os << ", ";
@@ -975,7 +975,7 @@ void RustPrinter::print_type(const TypeRef& t)
void RustPrinter::handle_struct(const AST::Struct& s)
{
print_params(s.params());
-
+
TU_MATCH(AST::StructData, (s.m_data), (e),
(Tuple,
if( e.ents.size() == 0 )
@@ -997,7 +997,7 @@ void RustPrinter::handle_struct(const AST::Struct& s)
(Struct,
m_os << "\n";
print_bounds(s.params());
-
+
m_os << indent() << "{\n";
inc_indent();
for( const auto& i : e.ents )
@@ -1060,7 +1060,7 @@ void RustPrinter::handle_trait(const AST::Trait& s)
m_os << indent() << "{\n";
inc_indent();
-
+
for( const auto& i : s.items() )
{
TU_MATCH_DEF(AST::Item, (i.data), (e),
@@ -1074,7 +1074,7 @@ void RustPrinter::handle_trait(const AST::Trait& s)
)
)
}
-
+
dec_indent();
m_os << indent() << "}\n";
m_os << "\n";
@@ -1107,12 +1107,12 @@ void RustPrinter::handle_function(bool is_pub, const ::std::string& name, const
{
m_os << " -> " << f.rettype().print_pretty();
}
-
+
if( f.code().is_valid() )
{
m_os << "\n";
print_bounds(f.params());
-
+
m_os << indent();
f.code().visit_nodes(*this);
m_os << "\n";
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index d3fa1989..cc6ca98f 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -5,7 +5,7 @@
namespace AST {
-
+
Expr::Expr(unique_ptr<ExprNode> node):
m_node(node.release())
{
@@ -188,7 +188,7 @@ NODE(ExprNode_Match, {
os << " " << pat;
if( arm.m_cond )
os << " if " << *arm.m_cond;
-
+
os << " => " << *arm.m_code << ",";
}
os << "}";
@@ -258,11 +258,11 @@ NODE(ExprNode_StructLiteral, {
os << "/* todo: sl */";
},{
ExprNode_StructLiteral::t_values vals;
-
+
for(const auto& v : m_values) {
vals.push_back( ::std::make_pair(v.first, v.second->clone()) );
}
-
+
return NEWNODE(ExprNode_StructLiteral, AST::Path(m_path), OPT_CLONE(m_base_value), mv$(vals) );
})
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index e955a4a4..4c80bcb5 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -24,11 +24,11 @@ class ExprNode
Position m_pos;
public:
virtual ~ExprNode() = 0;
-
+
virtual void visit(NodeVisitor& nv) = 0;
virtual void print(::std::ostream& os) const = 0;
virtual ::std::unique_ptr<ExprNode> clone() const = 0;
-
+
void set_pos(Position p) { m_pos = ::std::move(p); }
const Position& get_pos() const { return m_pos; }
Span span() const { return m_pos; }
@@ -37,7 +37,7 @@ public:
m_attrs = mv$(mi);
}
MetaItems& attrs() { return m_attrs; }
-
+
static ::std::unique_ptr<ExprNode> from_deserialiser(Deserialiser& d);
};
typedef ::std::unique_ptr<ExprNode> ExprNodeP;
@@ -68,7 +68,7 @@ struct ExprNode_Block:
m_nodes( move(nodes) )
{
}
-
+
NODE_METHODS();
};
@@ -78,13 +78,13 @@ struct ExprNode_Macro:
::std::string m_name;
::std::string m_ident;
::TokenTree m_tokens;
-
+
ExprNode_Macro(::std::string name, ::std::string ident, ::TokenTree&& tokens):
m_name(name),
m_ident(ident),
m_tokens( move(tokens) )
{}
-
+
NODE_METHODS();
};
@@ -106,7 +106,7 @@ struct ExprNode_Flow:
m_value( move(value) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_LetBinding:
@@ -122,7 +122,7 @@ struct ExprNode_LetBinding:
m_value( move(value) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_Assign:
@@ -145,7 +145,7 @@ struct ExprNode_Assign:
m_value( move(value) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_CallPath:
@@ -159,7 +159,7 @@ struct ExprNode_CallPath:
m_args( move(args) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_CallMethod:
@@ -175,7 +175,7 @@ struct ExprNode_CallMethod:
m_args( move(args) )
{
}
-
+
NODE_METHODS();
};
// Call an object (Fn/FnMut/FnOnce)
@@ -234,7 +234,7 @@ struct ExprNode_Match_Arm
MetaItems m_attrs;
::std::vector<Pattern> m_patterns;
unique_ptr<ExprNode> m_cond;
-
+
unique_ptr<ExprNode> m_code;
@@ -246,7 +246,7 @@ struct ExprNode_Match_Arm
m_code( mv$(code) )
{}
};
-
+
struct ExprNode_Match:
public ExprNode
{
@@ -305,7 +305,7 @@ struct ExprNode_Integer:
m_value(value)
{
}
-
+
NODE_METHODS();
};
// Literal float
@@ -320,7 +320,7 @@ struct ExprNode_Float:
m_value(value)
{
}
-
+
NODE_METHODS();
};
// Literal boolean
@@ -333,7 +333,7 @@ struct ExprNode_Bool:
m_value(value)
{
}
-
+
NODE_METHODS();
};
// Literal string
@@ -341,11 +341,11 @@ struct ExprNode_String:
public ExprNode
{
::std::string m_value;
-
+
ExprNode_String(::std::string value):
m_value( ::std::move(value) )
{}
-
+
NODE_METHODS();
};
// Literal byte string
@@ -353,11 +353,11 @@ struct ExprNode_ByteString:
public ExprNode
{
::std::string m_value;
-
+
ExprNode_ByteString(::std::string value):
m_value( ::std::move(value) )
{}
-
+
NODE_METHODS();
};
@@ -366,19 +366,19 @@ struct ExprNode_Closure:
public ExprNode
{
typedef ::std::vector< ::std::pair<AST::Pattern, TypeRef> > args_t;
-
+
args_t m_args;
TypeRef m_return;
unique_ptr<ExprNode> m_code;
bool m_is_move;
-
+
ExprNode_Closure(args_t args, TypeRef rv, unique_ptr<ExprNode> code, bool is_move):
m_args( ::std::move(args) ),
m_return( ::std::move(rv) ),
m_code( ::std::move(code) ),
m_is_move( is_move )
{}
-
+
NODE_METHODS();
};
// Literal structure
@@ -395,7 +395,7 @@ struct ExprNode_StructLiteral:
m_base_value( move(base_value) ),
m_values( move(values) )
{}
-
+
NODE_METHODS();
};
// Array
@@ -404,7 +404,7 @@ struct ExprNode_Array:
{
unique_ptr<ExprNode> m_size; // if non-NULL, it's a sized array
::std::vector< unique_ptr<ExprNode> > m_values;
-
+
ExprNode_Array(::std::vector< unique_ptr<ExprNode> > vals):
m_values( ::std::move(vals) )
{}
@@ -413,7 +413,7 @@ struct ExprNode_Array:
{
m_values.push_back( ::std::move(val) );
}
-
+
NODE_METHODS();
};
// Tuple
@@ -421,11 +421,11 @@ struct ExprNode_Tuple:
public ExprNode
{
::std::vector< unique_ptr<ExprNode> > m_values;
-
+
ExprNode_Tuple(::std::vector< unique_ptr<ExprNode> > vals):
m_values( ::std::move(vals) )
{}
-
+
NODE_METHODS();
};
// Variable / Constant
@@ -459,12 +459,12 @@ struct ExprNode_Index:
{
::std::unique_ptr<ExprNode> m_obj;
::std::unique_ptr<ExprNode> m_idx;
-
+
ExprNode_Index(::std::unique_ptr<ExprNode> obj, ::std::unique_ptr<ExprNode> idx):
m_obj( ::std::move(obj) ),
m_idx( ::std::move(idx) )
{}
-
+
NODE_METHODS();
};
@@ -473,12 +473,12 @@ struct ExprNode_Deref:
public ExprNode
{
::std::unique_ptr<ExprNode> m_value;
-
+
ExprNode_Deref(::std::unique_ptr<ExprNode> value):
m_value( ::std::move(value) )
{
}
-
+
NODE_METHODS();
};
@@ -523,7 +523,7 @@ struct ExprNode_BinOp:
CMPLTE,
CMPGT,
CMPGTE,
-
+
RANGE,
RANGE_INC,
BOOLAND,
@@ -535,13 +535,13 @@ struct ExprNode_BinOp:
SHL,
SHR,
-
+
MULTIPLY,
DIVIDE,
MODULO,
ADD,
SUB,
-
+
PLACE_IN, // `in PLACE { expr }` or `PLACE <- expr`
};
@@ -555,7 +555,7 @@ struct ExprNode_BinOp:
m_right( ::std::move(right) )
{
}
-
+
NODE_METHODS();
};
@@ -570,7 +570,7 @@ struct ExprNode_UniOp:
NEGATE, // '-<expr>'
QMARK, // '<expr>?'
};
-
+
enum Type m_type;
::std::unique_ptr<ExprNode> m_value;
@@ -579,7 +579,7 @@ struct ExprNode_UniOp:
m_value( ::std::move(value) )
{
}
-
+
NODE_METHODS();
};
@@ -593,7 +593,7 @@ public:
cnode->visit(*this);
}
virtual bool is_const() const { return false; }
-
+
#define NT(nt) \
virtual void visit(nt& node) = 0/*; \
virtual void visit(const nt& node) = 0*/
@@ -609,7 +609,7 @@ public:
NT(ExprNode_Match);
NT(ExprNode_If);
NT(ExprNode_IfLet);
-
+
NT(ExprNode_Integer);
NT(ExprNode_Float);
NT(ExprNode_Bool);
@@ -620,7 +620,7 @@ public:
NT(ExprNode_Array);
NT(ExprNode_Tuple);
NT(ExprNode_NamedValue);
-
+
NT(ExprNode_Field);
NT(ExprNode_Index);
NT(ExprNode_Deref);
@@ -653,7 +653,7 @@ public:
NT(ExprNode_Match);
NT(ExprNode_If);
NT(ExprNode_IfLet);
-
+
NT(ExprNode_Integer);
NT(ExprNode_Float);
NT(ExprNode_Bool);
@@ -664,7 +664,7 @@ public:
NT(ExprNode_Array);
NT(ExprNode_Tuple);
NT(ExprNode_NamedValue);
-
+
NT(ExprNode_Field);
NT(ExprNode_Index);
NT(ExprNode_Deref);
diff --git a/src/ast/expr_ptr.hpp b/src/ast/expr_ptr.hpp
index eb60c49f..1d68af15 100644
--- a/src/ast/expr_ptr.hpp
+++ b/src/ast/expr_ptr.hpp
@@ -24,7 +24,7 @@ public:
::std::shared_ptr<ExprNode> take_node() { assert(m_node.get()); return ::std::move(m_node); }
void visit_nodes(NodeVisitor& v);
void visit_nodes(NodeVisitor& v) const;
-
+
Expr clone() const;
friend ::std::ostream& operator<<(::std::ostream& os, const Expr& pat);
diff --git a/src/ast/generics.hpp b/src/ast/generics.hpp
index 7f8858a8..2de5aeaa 100644
--- a/src/ast/generics.hpp
+++ b/src/ast/generics.hpp
@@ -26,12 +26,12 @@ public:
assert(m_default.is_wildcard());
m_default = ::std::move(type);
}
-
+
const ::std::string& name() const { return m_name; }
-
+
const TypeRef& get_default() const { return m_default; }
TypeRef& get_default() { return m_default; }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp);
};
@@ -69,13 +69,13 @@ TAGGED_UNION_EX( GenericBound, (), Lifetime,
TypeRef replacement;
})
),
-
+
(, span(x.span) ), ( span = x.span; ),
(
public:
-
+
Span span;
-
+
GenericBound clone() const {
TU_MATCH(GenericBound, ( (*this) ), (ent),
(Lifetime, return make_Lifetime({ent.test, ent.bound}); ),
@@ -102,7 +102,7 @@ public:
GenericParams(GenericParams&& x) = default;
GenericParams& operator=(GenericParams&& x) = default;
GenericParams(const GenericParams& x) = delete;
-
+
GenericParams clone() const {
GenericParams rv;
rv.m_type_params = ::std::vector<TypeParam>( m_type_params ); // Copy-constructable
@@ -112,23 +112,23 @@ public:
rv.m_bounds.push_back( e.clone() );
return rv;
}
-
+
const ::std::vector<TypeParam>& ty_params() const { return m_type_params; }
::std::vector<TypeParam>& ty_params() { return m_type_params; }
const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; }
const ::std::vector<GenericBound>& bounds() const { return m_bounds; }
::std::vector<GenericBound>& bounds() { return m_bounds; }
-
+
void add_ty_param(TypeParam param) { m_type_params.push_back( ::std::move(param) ); }
void add_lft_param(::std::string name) { m_lifetime_params.push_back( ::std::move(name) ); }
void add_bound(GenericBound bound) {
m_bounds.push_back( ::std::move(bound) );
}
-
+
int find_name(const char* name) const;
bool check_params(Crate& crate, const ::std::vector<TypeRef>& types) const;
bool check_params(Crate& crate, ::std::vector<TypeRef>& types, bool allow_infer) const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const GenericParams& tp);
};
diff --git a/src/ast/item.hpp b/src/ast/item.hpp
index 2d3d1a1b..cc88f3e2 100644
--- a/src/ast/item.hpp
+++ b/src/ast/item.hpp
@@ -12,7 +12,7 @@ struct NamedNS
::std::string name;
T data;
bool is_pub;
-
+
NamedNS():
is_pub(false)
{}
@@ -25,7 +25,7 @@ struct NamedNS
is_pub( is_pub )
{
}
-
+
//friend ::std::ostream& operator<<(::std::ostream& os, const Named& i) {
// return os << (i.is_pub ? "pub " : " ") << i.name << ": " << i.data;
//}
diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp
index 9ae58fb9..84baa5a3 100644
--- a/src/ast/macro.hpp
+++ b/src/ast/macro.hpp
@@ -11,7 +11,7 @@ namespace AST {
class MacroInvocation
{
Span m_span;
-
+
::std::string m_macro_name;
::std::string m_ident;
TokenTree m_input;
@@ -20,11 +20,11 @@ public:
MacroInvocation& operator=(MacroInvocation&&) = default;
MacroInvocation(const MacroInvocation&) = delete;
MacroInvocation& operator=(const MacroInvocation&) = delete;
-
+
MacroInvocation()
{
}
-
+
MacroInvocation(Span span, ::std::string macro, ::std::string ident, TokenTree input):
m_span( mv$(span) ),
m_macro_name( mv$(macro) ),
@@ -32,7 +32,7 @@ public:
m_input( mv$(input) )
{
}
-
+
MacroInvocation clone() const;
void clear() {
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index ac023c8f..f02f48fb 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -27,7 +27,7 @@ namespace AST {
(TypeAlias, os << "TypeAlias";),
(StructMethod, os << "StructMethod"; ),
(TraitMethod, os << "TraitMethod"; ),
-
+
(TypeParameter, os << "TyParam(" << i.level << " # " << i.idx << ")"; ),
(Variable, os << "Var(" << i.slot << ")"; )
)
@@ -49,7 +49,7 @@ PathBinding PathBinding::clone() const
(EnumVar , return PathBinding::make_EnumVar(e); ),
(StructMethod, return PathBinding::make_StructMethod(e); ),
(TraitMethod, return PathBinding::make_TraitMethod(e); ),
-
+
(TypeParameter, return PathBinding::make_TypeParameter(e); ),
(Variable, return PathBinding::make_Variable(e); )
)
@@ -84,7 +84,7 @@ PathParams::PathParams(const PathParams& x):
m_types.reserve( x.m_types.size() );
for(const auto& t : x.m_types)
m_types.push_back(t.clone());
-
+
m_assoc.reserve( x.m_assoc.size() );
for(const auto& t : x.m_assoc)
m_assoc.push_back( ::std::make_pair(t.first, t.second.clone()) );
@@ -180,7 +180,7 @@ AST::Path::Path(const Path& x):
m_class = Class::make_UFCS({ box$(ent.type->clone()), nullptr, ent.nodes });
)
)
-
+
memcpy(&m_binding, &x.m_binding, sizeof(PathBinding));
}
@@ -199,7 +199,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std
}
if( idx == ent.variants().size() )
throw ParseError::Generic("Enum variant not found");
-
+
DEBUG("Bound to enum variant '" << name << "' (#" << idx << ")");
m_binding = PathBinding::make_EnumVar({ &ent, idx });
}
@@ -216,10 +216,10 @@ Path& Path::operator+=(const Path& other)
Ordering Path::ord(const Path& x) const
{
Ordering rv;
-
+
rv = ::ord( (unsigned)m_class.tag(), (unsigned)x.m_class.tag() );
if( rv != OrdEqual ) return rv;
-
+
TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent),
(Invalid,
return OrdEqual;
@@ -249,7 +249,7 @@ Ordering Path::ord(const Path& x) const
return ::ord(ent.nodes, x_ent.nodes);
)
)
-
+
return OrdEqual;
}
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index b45767a2..7a67b93e 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -112,7 +112,7 @@ struct PathParams
::std::vector< ::std::string > m_lifetimes;
::std::vector< TypeRef > m_types;
::std::vector< ::std::pair< ::std::string, TypeRef> > m_assoc;
-
+
PathParams(PathParams&& x) = default;
PathParams(const PathParams& x);
PathParams() {}
@@ -121,16 +121,16 @@ struct PathParams
m_types(mv$(tys)),
m_assoc(mv$(a))
{}
-
+
PathParams& operator=(PathParams&& x) = default;
PathParams& operator=(const PathParams& x) = delete;
-
+
bool is_empty() const {
return m_lifetimes.empty() && m_types.empty() && m_assoc.empty();
}
-
+
Ordering ord(const PathParams& x) const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x);
};
@@ -142,13 +142,13 @@ public:
PathNode() {}
PathNode(::std::string name, PathParams args = {});
const ::std::string& name() const { return m_name; }
-
+
const ::AST::PathParams& args() const { return m_params; }
::AST::PathParams& args() { return m_params; }
-
+
Ordering ord(const PathNode& x) const;
void print_pretty(::std::ostream& os, bool is_type_context) const;
-
+
bool operator==(const PathNode& x) const { return ord(x) == OrdEqual; }
friend ::std::ostream& operator<<(::std::ostream& os, const PathNode& pn);
};
@@ -201,20 +201,20 @@ public:
//DEBUG("Path, " << x);
return *this;
}
-
+
Path(const Path& x);
Path& operator=(const AST::Path&) = delete;
-
+
// ABSOLUTE
Path(::std::string crate, ::std::vector<PathNode> nodes):
m_class( Class::make_Absolute({ mv$(crate), mv$(nodes)}) )
{}
-
+
// UFCS
struct TagUfcs {};
Path(TagUfcs, TypeRef type, ::std::vector<PathNode> nodes={});
Path(TagUfcs, TypeRef type, Path trait, ::std::vector<PathNode> nodes={});
-
+
// VARIABLE
struct TagLocal {};
Path(TagLocal, ::std::string name):
@@ -223,7 +223,7 @@ public:
Path(::std::string name):
m_class( Class::make_Local({ mv$(name) }) )
{}
-
+
// RELATIVE
struct TagRelative {};
Path(TagRelative, Ident::Hygiene hygiene, ::std::vector<PathNode> nodes):
@@ -239,7 +239,7 @@ public:
Path(TagSuper, unsigned int count, ::std::vector<PathNode> nodes):
m_class( Class::make_Super({ count, mv$(nodes) }) )
{}
-
+
//void set_crate(::std::string crate) {
// if( m_crate == "" ) {
// m_crate = crate;
@@ -247,11 +247,11 @@ public:
// }
//}
-
+
Class::Tag class_tag() const {
return m_class.tag();
}
-
+
Path operator+(PathNode pn) const {
Path tmp = Path(*this);
tmp.nodes().push_back( mv$(pn) );
@@ -274,7 +274,7 @@ public:
nodes().push_back( mv$(node) );
m_binding = PathBinding();
}
-
+
bool is_trivial() const {
TU_MATCH_DEF(Class, (m_class), (e),
(
@@ -288,11 +288,11 @@ public:
)
)
}
-
+
bool is_valid() const { return !m_class.is_Invalid(); }
bool is_absolute() const { return m_class.is_Absolute(); }
bool is_relative() const { return m_class.is_Relative() || m_class.is_Super() || m_class.is_Self(); }
-
+
size_t size() const {
TU_MATCH(Class, (m_class), (ent),
(Invalid, assert(!m_class.is_Invalid()); throw ::std::runtime_error("Path::nodes() on Invalid"); ),
@@ -308,11 +308,11 @@ public:
//const ::std::string& crate() const { return m_crate; }
bool is_concrete() const;
-
+
bool is_bound() const { return !m_binding.is_Unbound(); }
const PathBinding& binding() const { return m_binding; }
void bind_variable(unsigned int slot);
-
+
::std::vector<PathNode>& nodes() {
TU_MATCH(Class, (m_class), (ent),
(Invalid, assert(!m_class.is_Invalid()); throw ::std::runtime_error("Path::nodes() on Invalid"); ),
@@ -328,20 +328,20 @@ public:
const ::std::vector<PathNode>& nodes() const {
return ((Path*)this)->nodes();
}
-
+
PathNode& operator[](int idx) { if(idx>=0) return nodes()[idx]; else return nodes()[size()+idx]; }
const PathNode& operator[](int idx) const { return (*(Path*)this)[idx]; }
-
+
Ordering ord(const Path& x) const;
bool operator==(const Path& x) const { return ord(x) == OrdEqual; }
bool operator!=(const Path& x) const { return ord(x) != OrdEqual; }
bool operator<(const Path& x) const { return ord(x) != OrdLess; }
-
+
void print_pretty(::std::ostream& os, bool is_type_context) const;
friend ::std::ostream& operator<<(::std::ostream& os, const Path& path);
private:
static void resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn);
-
+
void check_param_counts(const GenericParams& params, bool expect_params, PathNode& node);
public:
void bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args={});
@@ -349,7 +349,7 @@ public:
(void)args;
m_binding = PathBinding::make_Function({&ent});
}
-
+
void bind(::AST::PathBinding pb) {
m_binding = mv$(pb);
}
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp
index 3128fd91..bfcc6eeb 100644
--- a/src/ast/pattern.cpp
+++ b/src/ast/pattern.cpp
@@ -123,7 +123,7 @@ namespace AST {
os << ent.leading;
needs_comma = true;
}
-
+
if( needs_comma ) {
os << ", ";
}
@@ -131,7 +131,7 @@ namespace AST {
os << ent.extra_bind.m_name;
os << "..";
needs_comma = true;
-
+
if(ent.trailing.size()) {
if( needs_comma ) {
os << ", ";
@@ -167,7 +167,7 @@ AST::Pattern AST::Pattern::clone() const
AST::Pattern rv;
rv.m_span = m_span;
rv.m_binding = PatternBinding(m_binding);
-
+
struct H {
static ::std::unique_ptr<Pattern> clone_sp(const ::std::unique_ptr<Pattern>& p) {
return ::std::make_unique<Pattern>( p->clone() );
@@ -198,7 +198,7 @@ AST::Pattern AST::Pattern::clone() const
throw "";
}
};
-
+
TU_MATCH(Pattern::Data, (m_data), (e),
(Any,
rv.m_data = Data::make_Any(e);
@@ -237,7 +237,7 @@ AST::Pattern AST::Pattern::clone() const
rv.m_data = Data::make_SplitSlice({ H::clone_list(e.leading), e.extra_bind, H::clone_list(e.trailing) });
)
)
-
+
return rv;
}
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index a2df7b59..af6a5adf 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -46,11 +46,11 @@ public:
m_mutable(ismut),
m_slot( ~0u )
{}
-
+
PatternBinding(PatternBinding&& x) = default;
PatternBinding(const PatternBinding& x) = default;
PatternBinding& operator=(PatternBinding&& x) = default;
-
+
bool is_valid() const { return m_name.name != ""; }
};
@@ -78,7 +78,7 @@ public:
bool has_wildcard;
::std::vector<Pattern> end;
};
-
+
TAGGED_UNION(Data, Any,
(MaybeBind, struct { Ident name; } ),
(Macro, struct { unique_ptr<::AST::MacroInvocation> inv; } ),
@@ -96,15 +96,15 @@ private:
Span m_span;
PatternBinding m_binding;
Data m_data;
-
+
public:
virtual ~Pattern();
-
+
Pattern()
{}
Pattern(Pattern&&) = default;
Pattern& operator=(Pattern&&) = default;
-
+
Pattern(Data dat):
m_binding(),
m_data( mv$(dat) )
@@ -135,8 +135,8 @@ public:
Pattern(TagValue, Value val, Value end = Value()):
m_data( Data::make_Value({ ::std::move(val), ::std::move(end) }) )
{}
-
-
+
+
struct TagReference {};
Pattern(TagReference, bool is_mutable, Pattern sub_pattern):
m_data( Data::make_Ref( /*Data::Data_Ref */ {
@@ -163,20 +163,20 @@ public:
struct TagStruct {};
Pattern(TagStruct, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns, bool is_exhaustive):
- m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) )
+ m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) )
{}
-
+
// Mutators
void set_bind(Ident name, PatternBinding::Type type, bool is_mut) {
m_binding = PatternBinding(mv$(name), type, is_mut);
}
-
-
+
+
const Span& span() const { return m_span; }
void set_span(Span sp) { m_span = mv$(sp); }
-
+
Pattern clone() const;
-
+
// Accessors
PatternBinding& binding() { return m_binding; }
const PatternBinding& binding() const { return m_binding; }
diff --git a/src/ast/types.cpp b/src/ast/types.cpp
index c8f373e5..21e47b4b 100644
--- a/src/ast/types.cpp
+++ b/src/ast/types.cpp
@@ -1,7 +1,7 @@
/*
* MRustC - Mutabah's Rust Compiler
* - By John Hodge (Mutabah/thePowersGang)
- *
+ *
* types.cpp
* - Backing code for the TypeRef class
*
@@ -87,7 +87,7 @@ Type_Function::Type_Function(const Type_Function& other):
Ordering Type_Function::ord(const Type_Function& x) const
{
Ordering rv;
-
+
rv = ::ord(m_abi, x.m_abi);
if(rv != OrdEqual) return rv;
rv = ::ord(m_arg_types, x.m_arg_types);
@@ -139,10 +139,10 @@ TypeRef TypeRef::clone() const
Ordering TypeRef::ord(const TypeRef& x) const
{
Ordering rv;
-
+
rv = ::ord( (unsigned)m_data.tag(), (unsigned)x.m_data.tag() );
if(rv != OrdEqual) return rv;
-
+
TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent),
(None, return OrdEqual;),
(Macro, throw CompileError::BugCheck("TypeRef::ord - unexpanded macro");),
diff --git a/src/ast/types.hpp b/src/ast/types.hpp
index 04c1517f..e2114bae 100644
--- a/src/ast/types.hpp
+++ b/src/ast/types.hpp
@@ -1,276 +1,276 @@
-#ifndef TYPES_HPP_INCLUDED
-#define TYPES_HPP_INCLUDED
-
-#include <memory>
-
-#include "common.hpp"
-#include "coretypes.hpp"
-#include "ast/path.hpp"
-#include "ast/macro.hpp"
-#include <serialise.hpp>
-#include <tagged_union.hpp>
-
-namespace AST {
-class ExprNode;
-class Expr;
-}
-
-class PrettyPrintType
-{
- const TypeRef& m_type;
-public:
- PrettyPrintType(const TypeRef& ty):
- m_type(ty)
- {}
-
- void print(::std::ostream& os) const;
-
- friend ::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v);
-};
-
-struct TypeArgRef
-{
- ::std::string name;
- unsigned int level;
- const AST::GenericParams* params;
-};
-
-struct Type_Function
-{
- bool is_unsafe;
- ::std::string m_abi;
- ::std::unique_ptr<TypeRef> m_rettype;
- ::std::vector<TypeRef> m_arg_types;
- bool is_variadic;
-
- Type_Function() {}
- Type_Function(bool is_unsafe, ::std::string abi, ::std::unique_ptr<TypeRef> ret, ::std::vector<TypeRef> args, bool is_variadic):
- is_unsafe(is_unsafe),
- m_abi(mv$(abi)),
- m_rettype(mv$(ret)),
- m_arg_types(mv$(args)),
- is_variadic(is_variadic)
- {}
- Type_Function(Type_Function&& other) = default;
- Type_Function(const Type_Function& other);
-
- Ordering ord(const Type_Function& x) const;
-};
-
-TAGGED_UNION(TypeData, None,
- (None, struct { }),
- (Any, struct { }),
- (Bang, struct { }),
- (Unit, struct { }),
- (Macro, struct {
- ::AST::MacroInvocation inv;
- }),
- (Primitive, struct {
- enum eCoreType core_type;
- }),
- (Function, struct {
- Type_Function info;
- }),
- (Tuple, struct {
- ::std::vector<TypeRef> inner_types;
- }),
- (Borrow, struct {
- bool is_mut;
- ::std::unique_ptr<TypeRef> inner;
- }),
- (Pointer, struct {
- bool is_mut;
- ::std::unique_ptr<TypeRef> inner;
- }),
- (Array, struct {
- ::std::unique_ptr<TypeRef> inner;
- ::std::shared_ptr<AST::ExprNode> size;
- }),
- (Generic, struct {
- ::std::string name;
- unsigned int index;
- }),
- (Path, struct {
- AST::Path path;
- }),
- (TraitObject, struct {
- ::std::vector<::std::string> hrls;
- ::std::vector<AST::Path> traits;
- }),
- (ErasedType, struct {
- ::std::vector<::std::string> hrls;
- ::std::vector<AST::Path> traits;
- })
- );
-
-/// A type
-class TypeRef
-{
- Span m_span;
-public:
- TypeData m_data;
-
- ~TypeRef();
-
- TypeRef(TypeRef&& other) = default;
- TypeRef& operator=(TypeRef&& other) = default;
-
- #if 1
- TypeRef(const TypeRef& other) = delete;
- TypeRef& operator=(const TypeRef& other) = delete;
- #else
- TypeRef(const TypeRef& other): m_span(other.m_span) {
- *this = other.clone();
- }
- TypeRef& operator=(const TypeRef& other) {
- m_data = mv$(other.clone().m_data);
- return *this;
- }
- #endif
-
- TypeRef(Span sp):
- m_span( mv$(sp) ),
- m_data( TypeData::make_Any({}) )
- {}
- TypeRef(Span sp, TypeData data):
- m_span( mv$(sp) ),
- m_data( mv$(data) )
- {}
-
- struct TagInvalid {};
- TypeRef(TagInvalid, Span sp):
- m_span(mv$(sp)),
- m_data(TypeData::make_None({}))
- {}
-
- struct TagMacro {};
- TypeRef(TagMacro, ::AST::MacroInvocation inv):
- m_span(inv.span()),
- m_data(TypeData::make_Macro({mv$(inv)}))
- {}
-
- struct TagUnit {}; // unit maps to a zero-length tuple, just easier to type
- TypeRef(TagUnit, Span sp):
- m_span(mv$(sp)),
- m_data(TypeData::make_Unit({}))
- {}
-
- struct TagPrimitive {};
- TypeRef(TagPrimitive, Span sp, enum eCoreType type):
- m_span(mv$(sp)),
- m_data(TypeData::make_Primitive({type}))
- {}
- TypeRef(Span sp, enum eCoreType type):
- m_span(mv$(sp)),
- m_data(TypeData::make_Primitive({type}))
- {}
-
- struct TagTuple {};
- TypeRef(TagTuple , Span sp, ::std::vector<TypeRef> inner_types):
- m_span(mv$(sp)),
- m_data(TypeData::make_Tuple({::std::move(inner_types)}))
- {}
- struct TagFunction {};
- TypeRef(TagFunction, Span sp, bool is_unsafe, ::std::string abi, ::std::vector<TypeRef> args, bool is_variadic, TypeRef ret):
- m_span(mv$(sp)),
- m_data(TypeData::make_Function({ Type_Function( is_unsafe, abi, box$(ret), mv$(args), is_variadic ) }))
- {}
-
- struct TagReference {};
- TypeRef(TagReference , Span sp, bool is_mut, TypeRef inner_type):
- m_span(mv$(sp)),
- m_data(TypeData::make_Borrow({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
- {}
- struct TagPointer {};
- TypeRef(TagPointer , Span sp, bool is_mut, TypeRef inner_type):
- m_span(mv$(sp)),
- m_data(TypeData::make_Pointer({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
- {}
- struct TagSizedArray {};
- TypeRef(TagSizedArray , Span sp, TypeRef inner_type, ::std::shared_ptr<AST::ExprNode> size):
- m_span(mv$(sp)),
- m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), mv$(size) }))
- {}
- struct TagUnsizedArray {};
- TypeRef(TagUnsizedArray , Span sp, TypeRef inner_type):
- m_span(mv$(sp)),
- m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), ::std::shared_ptr<AST::ExprNode>() }))
- {}
-
- struct TagArg {};
- TypeRef(TagArg, Span sp, ::std::string name, unsigned int binding = ~0u):
- m_span( mv$(sp) ),
- m_data(TypeData::make_Generic({ name, binding }))
- {}
- TypeRef(Span sp, ::std::string name, unsigned int binding = ~0u):
- TypeRef(TagArg(), mv$(sp), mv$(name), binding)
- {}
-
- struct TagPath {};
- TypeRef(TagPath, Span sp, AST::Path path):
- m_span(mv$(sp)),
- m_data(TypeData::make_Path({ ::std::move(path) }))
- {}
- TypeRef(Span sp, AST::Path path):
- TypeRef(TagPath(), mv$(sp), mv$(path))
- {}
-
- TypeRef( Span sp, ::std::vector<::std::string> hrls, ::std::vector<AST::Path> traits ):
- m_span(mv$(sp)),
- m_data(TypeData::make_TraitObject({ mv$(hrls), ::std::move(traits) }))
- {}
-
-
- const Span& span() const { return m_span; }
-
- bool is_valid() const { return ! m_data.is_None(); }
-
- bool is_unbounded() const { return m_data.is_Any(); }
- bool is_wildcard() const { return m_data.is_Any(); }
-
- bool is_unit() const { return m_data.is_Unit(); }
- bool is_primitive() const { return m_data.is_Primitive(); }
-
- bool is_path() const { return m_data.is_Path(); }
- const AST::Path& path() const { return m_data.as_Path().path; }
- AST::Path& path() { return m_data.as_Path().path; }
-
- bool is_type_param() const { return m_data.is_Generic(); }
- const ::std::string& type_param() const { return m_data.as_Generic().name; }
-
- bool is_reference() const { return m_data.is_Borrow(); }
- bool is_pointer() const { return m_data.is_Pointer(); }
- bool is_tuple() const { return m_data.is_Tuple(); }
-
- TypeRef clone() const;
-
- const TypeRef& inner_type() const {
- TU_MATCH_DEF(TypeData, (m_data), (e),
- ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ),
- (Borrow, return *e.inner; ),
- (Pointer, return *e.inner; ),
- (Array, return *e.inner; )
- )
- }
- TypeRef& inner_type() {
- TU_MATCH_DEF(TypeData, (m_data), (e),
- ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ),
- (Borrow, return *e.inner; ),
- (Pointer, return *e.inner; ),
- (Array, return *e.inner; )
- )
- }
-
- Ordering ord(const TypeRef& x) const;
- bool operator==(const TypeRef& x) const { return ord(x) == OrdEqual; }
- bool operator!=(const TypeRef& x) const { return ord(x) != OrdEqual; }
- bool operator<(const TypeRef& x) const { return ord(x) == OrdLess; };
-
- PrettyPrintType print_pretty() const { return PrettyPrintType(*this); }
-
- friend class PrettyPrintType;
-
- friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
-};
-
-#endif // TYPES_HPP_INCLUDED
+#ifndef TYPES_HPP_INCLUDED
+#define TYPES_HPP_INCLUDED
+
+#include <memory>
+
+#include "common.hpp"
+#include "coretypes.hpp"
+#include "ast/path.hpp"
+#include "ast/macro.hpp"
+#include <serialise.hpp>
+#include <tagged_union.hpp>
+
+namespace AST {
+class ExprNode;
+class Expr;
+}
+
+class PrettyPrintType
+{
+ const TypeRef& m_type;
+public:
+ PrettyPrintType(const TypeRef& ty):
+ m_type(ty)
+ {}
+
+ void print(::std::ostream& os) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const PrettyPrintType& v);
+};
+
+struct TypeArgRef
+{
+ ::std::string name;
+ unsigned int level;
+ const AST::GenericParams* params;
+};
+
+struct Type_Function
+{
+ bool is_unsafe;
+ ::std::string m_abi;
+ ::std::unique_ptr<TypeRef> m_rettype;
+ ::std::vector<TypeRef> m_arg_types;
+ bool is_variadic;
+
+ Type_Function() {}
+ Type_Function(bool is_unsafe, ::std::string abi, ::std::unique_ptr<TypeRef> ret, ::std::vector<TypeRef> args, bool is_variadic):
+ is_unsafe(is_unsafe),
+ m_abi(mv$(abi)),
+ m_rettype(mv$(ret)),
+ m_arg_types(mv$(args)),
+ is_variadic(is_variadic)
+ {}
+ Type_Function(Type_Function&& other) = default;
+ Type_Function(const Type_Function& other);
+
+ Ordering ord(const Type_Function& x) const;
+};
+
+TAGGED_UNION(TypeData, None,
+ (None, struct { }),
+ (Any, struct { }),
+ (Bang, struct { }),
+ (Unit, struct { }),
+ (Macro, struct {
+ ::AST::MacroInvocation inv;
+ }),
+ (Primitive, struct {
+ enum eCoreType core_type;
+ }),
+ (Function, struct {
+ Type_Function info;
+ }),
+ (Tuple, struct {
+ ::std::vector<TypeRef> inner_types;
+ }),
+ (Borrow, struct {
+ bool is_mut;
+ ::std::unique_ptr<TypeRef> inner;
+ }),
+ (Pointer, struct {
+ bool is_mut;
+ ::std::unique_ptr<TypeRef> inner;
+ }),
+ (Array, struct {
+ ::std::unique_ptr<TypeRef> inner;
+ ::std::shared_ptr<AST::ExprNode> size;
+ }),
+ (Generic, struct {
+ ::std::string name;
+ unsigned int index;
+ }),
+ (Path, struct {
+ AST::Path path;
+ }),
+ (TraitObject, struct {
+ ::std::vector<::std::string> hrls;
+ ::std::vector<AST::Path> traits;
+ }),
+ (ErasedType, struct {
+ ::std::vector<::std::string> hrls;
+ ::std::vector<AST::Path> traits;
+ })
+ );
+
+/// A type
+class TypeRef
+{
+ Span m_span;
+public:
+ TypeData m_data;
+
+ ~TypeRef();
+
+ TypeRef(TypeRef&& other) = default;
+ TypeRef& operator=(TypeRef&& other) = default;
+
+ #if 1
+ TypeRef(const TypeRef& other) = delete;
+ TypeRef& operator=(const TypeRef& other) = delete;
+ #else
+ TypeRef(const TypeRef& other): m_span(other.m_span) {
+ *this = other.clone();
+ }
+ TypeRef& operator=(const TypeRef& other) {
+ m_data = mv$(other.clone().m_data);
+ return *this;
+ }
+ #endif
+
+ TypeRef(Span sp):
+ m_span( mv$(sp) ),
+ m_data( TypeData::make_Any({}) )
+ {}
+ TypeRef(Span sp, TypeData data):
+ m_span( mv$(sp) ),
+ m_data( mv$(data) )
+ {}
+
+ struct TagInvalid {};
+ TypeRef(TagInvalid, Span sp):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_None({}))
+ {}
+
+ struct TagMacro {};
+ TypeRef(TagMacro, ::AST::MacroInvocation inv):
+ m_span(inv.span()),
+ m_data(TypeData::make_Macro({mv$(inv)}))
+ {}
+
+ struct TagUnit {}; // unit maps to a zero-length tuple, just easier to type
+ TypeRef(TagUnit, Span sp):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Unit({}))
+ {}
+
+ struct TagPrimitive {};
+ TypeRef(TagPrimitive, Span sp, enum eCoreType type):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Primitive({type}))
+ {}
+ TypeRef(Span sp, enum eCoreType type):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Primitive({type}))
+ {}
+
+ struct TagTuple {};
+ TypeRef(TagTuple , Span sp, ::std::vector<TypeRef> inner_types):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Tuple({::std::move(inner_types)}))
+ {}
+ struct TagFunction {};
+ TypeRef(TagFunction, Span sp, bool is_unsafe, ::std::string abi, ::std::vector<TypeRef> args, bool is_variadic, TypeRef ret):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Function({ Type_Function( is_unsafe, abi, box$(ret), mv$(args), is_variadic ) }))
+ {}
+
+ struct TagReference {};
+ TypeRef(TagReference , Span sp, bool is_mut, TypeRef inner_type):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Borrow({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
+ {}
+ struct TagPointer {};
+ TypeRef(TagPointer , Span sp, bool is_mut, TypeRef inner_type):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Pointer({ is_mut, ::make_unique_ptr(mv$(inner_type)) }))
+ {}
+ struct TagSizedArray {};
+ TypeRef(TagSizedArray , Span sp, TypeRef inner_type, ::std::shared_ptr<AST::ExprNode> size):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), mv$(size) }))
+ {}
+ struct TagUnsizedArray {};
+ TypeRef(TagUnsizedArray , Span sp, TypeRef inner_type):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Array({ ::make_unique_ptr(mv$(inner_type)), ::std::shared_ptr<AST::ExprNode>() }))
+ {}
+
+ struct TagArg {};
+ TypeRef(TagArg, Span sp, ::std::string name, unsigned int binding = ~0u):
+ m_span( mv$(sp) ),
+ m_data(TypeData::make_Generic({ name, binding }))
+ {}
+ TypeRef(Span sp, ::std::string name, unsigned int binding = ~0u):
+ TypeRef(TagArg(), mv$(sp), mv$(name), binding)
+ {}
+
+ struct TagPath {};
+ TypeRef(TagPath, Span sp, AST::Path path):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_Path({ ::std::move(path) }))
+ {}
+ TypeRef(Span sp, AST::Path path):
+ TypeRef(TagPath(), mv$(sp), mv$(path))
+ {}
+
+ TypeRef( Span sp, ::std::vector<::std::string> hrls, ::std::vector<AST::Path> traits ):
+ m_span(mv$(sp)),
+ m_data(TypeData::make_TraitObject({ mv$(hrls), ::std::move(traits) }))
+ {}
+
+
+ const Span& span() const { return m_span; }
+
+ bool is_valid() const { return ! m_data.is_None(); }
+
+ bool is_unbounded() const { return m_data.is_Any(); }
+ bool is_wildcard() const { return m_data.is_Any(); }
+
+ bool is_unit() const { return m_data.is_Unit(); }
+ bool is_primitive() const { return m_data.is_Primitive(); }
+
+ bool is_path() const { return m_data.is_Path(); }
+ const AST::Path& path() const { return m_data.as_Path().path; }
+ AST::Path& path() { return m_data.as_Path().path; }
+
+ bool is_type_param() const { return m_data.is_Generic(); }
+ const ::std::string& type_param() const { return m_data.as_Generic().name; }
+
+ bool is_reference() const { return m_data.is_Borrow(); }
+ bool is_pointer() const { return m_data.is_Pointer(); }
+ bool is_tuple() const { return m_data.is_Tuple(); }
+
+ TypeRef clone() const;
+
+ const TypeRef& inner_type() const {
+ TU_MATCH_DEF(TypeData, (m_data), (e),
+ ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ),
+ (Borrow, return *e.inner; ),
+ (Pointer, return *e.inner; ),
+ (Array, return *e.inner; )
+ )
+ }
+ TypeRef& inner_type() {
+ TU_MATCH_DEF(TypeData, (m_data), (e),
+ ( throw ::std::runtime_error("Called inner_type on non-wrapper"); ),
+ (Borrow, return *e.inner; ),
+ (Pointer, return *e.inner; ),
+ (Array, return *e.inner; )
+ )
+ }
+
+ Ordering ord(const TypeRef& x) const;
+ bool operator==(const TypeRef& x) const { return ord(x) == OrdEqual; }
+ bool operator!=(const TypeRef& x) const { return ord(x) != OrdEqual; }
+ bool operator<(const TypeRef& x) const { return ord(x) == OrdLess; };
+
+ PrettyPrintType print_pretty() const { return PrettyPrintType(*this); }
+
+ friend class PrettyPrintType;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
+};
+
+#endif // TYPES_HPP_INCLUDED
diff --git a/src/common.hpp b/src/common.hpp
index 7334be13..d421e368 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -117,14 +117,14 @@ Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r)
{
if( i >= r.size() )
return OrdGreater;
-
+
auto rv = ::ord( it, r[i] );
if( rv != OrdEqual )
return rv;
-
+
i ++;
}
-
+
if( i < r.size() )
return OrdLess;
return OrdEqual;
@@ -152,7 +152,7 @@ struct LList
{
const LList* m_prev;
T m_item;
-
+
LList():
m_prev(nullptr)
{}
@@ -161,7 +161,7 @@ struct LList
m_item( ::std::move(item) )
{
}
-
+
LList end() const {
return LList();
}
diff --git a/src/coretypes.hpp b/src/coretypes.hpp
index f78b1ff2..cfab82c1 100644
--- a/src/coretypes.hpp
+++ b/src/coretypes.hpp
@@ -1,22 +1,22 @@
-#ifndef CORETYPES_HPP_INCLUDED
-#define CORETYPES_HPP_INCLUDED
-
-enum eCoreType
-{
- CORETYPE_INVAL,
- CORETYPE_ANY,
- CORETYPE_BOOL,
- CORETYPE_CHAR, CORETYPE_STR,
- CORETYPE_UINT, CORETYPE_INT,
- CORETYPE_U8, CORETYPE_I8,
- CORETYPE_U16, CORETYPE_I16,
- CORETYPE_U32, CORETYPE_I32,
- CORETYPE_U64, CORETYPE_I64,
- CORETYPE_F32,
- CORETYPE_F64,
-};
-
-extern enum eCoreType coretype_fromstring(const ::std::string& name);
-extern const char* coretype_name(const eCoreType ct);
-
-#endif // CORETYPES_HPP_INCLUDED
+#ifndef CORETYPES_HPP_INCLUDED
+#define CORETYPES_HPP_INCLUDED
+
+enum eCoreType
+{
+ CORETYPE_INVAL,
+ CORETYPE_ANY,
+ CORETYPE_BOOL,
+ CORETYPE_CHAR, CORETYPE_STR,
+ CORETYPE_UINT, CORETYPE_INT,
+ CORETYPE_U8, CORETYPE_I8,
+ CORETYPE_U16, CORETYPE_I16,
+ CORETYPE_U32, CORETYPE_I32,
+ CORETYPE_U64, CORETYPE_I64,
+ CORETYPE_F32,
+ CORETYPE_F64,
+};
+
+extern enum eCoreType coretype_fromstring(const ::std::string& name);
+extern const char* coretype_name(const eCoreType ct);
+
+#endif // CORETYPES_HPP_INCLUDED
diff --git a/src/expand/cfg.cpp b/src/expand/cfg.cpp
index e59da886..fcd31742 100644
--- a/src/expand/cfg.cpp
+++ b/src/expand/cfg.cpp
@@ -31,7 +31,7 @@ void Cfg_SetValueCb(::std::string name, ::std::function<bool(const ::std::string
}
bool check_cfg(Span sp, const ::AST::MetaItem& mi) {
-
+
if( mi.has_sub_items() ) {
// Must be `any`/`not`/`all`
if( mi.name() == "any" || mi.name() == "cfg" ) {
@@ -66,14 +66,14 @@ bool check_cfg(Span sp, const ::AST::MetaItem& mi) {
DEBUG(""<<mi.name()<<": '"<<it->second<<"' == '"<<mi.string()<<"'");
return it->second == mi.string();
}
-
+
auto it2 = g_cfg_value_fcns.find(mi.name());
if(it2 != g_cfg_value_fcns.end() )
{
DEBUG(""<<mi.name()<<": ('"<<mi.string()<<"')?");
return it2->second( mi.string() );
}
-
+
WARNING(sp, W0000, "Unknown cfg() param '" << mi.name() << "'");
return false;
}
@@ -93,11 +93,11 @@ class CCfgExpander:
if( ident != "" ) {
ERROR(sp, E0000, "cfg! doesn't take an identifier");
}
-
+
auto lex = TTStream(tt);
auto attrs = Parse_MetaItem(lex);
DEBUG("cfg!() - " << attrs);
-
+
if( check_cfg(sp, attrs) ) {
return box$( TTStreamO(TokenTree({},TOK_RWORD_TRUE )) );
}
@@ -112,8 +112,8 @@ class CCfgHandler:
public ExpandDecorator
{
AttrStage stage() const override { return AttrStage::Pre; }
-
-
+
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const override {
DEBUG("#[cfg] crate - " << mi);
// Ignore, as #[cfg] on a crate is handled in expand/mod.cpp
@@ -150,7 +150,7 @@ class CCfgHandler:
impl.type() = ::TypeRef(sp);
}
}
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, ::AST::StructItem& si) const override {
DEBUG("#[cfg] struct item - " << mi);
if( !check_cfg(sp, mi) ) {
diff --git a/src/expand/concat.cpp b/src/expand/concat.cpp
index 7475325a..a08e9168 100644
--- a/src/expand/concat.cpp
+++ b/src/expand/concat.cpp
@@ -19,18 +19,18 @@ class CConcatExpander:
::std::unique_ptr<TokenStream> expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override
{
Token tok;
-
+
auto lex = TTStream(tt);
if( ident != "" )
ERROR(sp, E0000, "format_args! doesn't take an ident");
-
+
::std::string rv;
do {
if( LOOK_AHEAD(lex) == TOK_EOF ) {
GET_TOK(tok, lex);
break ;
}
-
+
auto v = Parse_Expr0(lex);
DEBUG("concat - v=" << *v);
Expand_BareExpr(crate, mod, v);
@@ -63,7 +63,7 @@ class CConcatExpander:
} while( GET_TOK(tok, lex) == TOK_COMMA );
if( tok.type() != TOK_EOF )
throw ParseError::Unexpected(lex, tok, {TOK_COMMA, TOK_EOF});
-
+
return box$( TTStreamO(TokenTree(Token(TOK_STRING, mv$(rv)))) );
}
};
diff --git a/src/expand/crate_tags.cpp b/src/expand/crate_tags.cpp
index df6b339b..ca5a98ce 100644
--- a/src/expand/crate_tags.cpp
+++ b/src/expand/crate_tags.cpp
@@ -13,7 +13,7 @@ class Decorator_CrateType:
{
public:
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const override {
if( crate.m_crate_type != AST::Crate::Type::Unknown ) {
//ERROR(sp, E0000, "Multiple #![crate_type] attributes");
@@ -40,7 +40,7 @@ class Decorator_CrateName:
{
public:
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const override {
if( crate.m_crate_name != "" ) {
ERROR(sp, E0000, "Multiple #![crate_name] attributes");
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index f6021a7d..46457784 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -66,16 +66,16 @@ struct Deriver
{
virtual AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0;
virtual AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
-
-
+
+
AST::GenericParams get_params_with_bounds(const Span& sp, const AST::GenericParams& p, const AST::Path& trait_path, ::std::vector<TypeRef> additional_bounded_types) const
{
AST::GenericParams params = p.clone();
-
+
// TODO: Get bounds based on generic (or similar) types used within the type.
// - How would this code (that runs before resolve) know what's a generic and what's a local type?
// - Searches within the type for a Path that starts with that param.
-
+
unsigned int i = 0;
for(const auto& arg : params.ty_params())
{
@@ -84,7 +84,7 @@ struct Deriver
}) );
i ++;
}
-
+
// For each field type
// - Locate used generic parameters in the type (and sub-types that directly use said parameter)
for(auto& ty : additional_bounded_types)
@@ -93,11 +93,11 @@ struct Deriver
mv$(ty), {}, trait_path
}) );
}
-
+
return params;
}
-
-
+
+
::std::vector<TypeRef> get_field_bounds(const AST::Struct& str) const
{
::std::vector<TypeRef> ret;
@@ -140,10 +140,10 @@ struct Deriver
)
)
}
-
+
return ret;
}
-
+
void add_field_bound_from_ty(const AST::GenericParams& params, ::std::vector<TypeRef>& out_list, const TypeRef& ty) const
{
struct H {
@@ -264,14 +264,14 @@ class Deriver_Debug:
//{
// throw CompileError::Todo("derive(Debug) - _try");
//}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path debug_trait = AST::Path(core_name, { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) });
TypeRef f_type(TypeRef::TagReference(), sp, true,
TypeRef(sp, AST::Path(core_name, {AST::PathNode("fmt",{}), AST::PathNode("Formatter", {})}))
);
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -283,19 +283,19 @@ class Deriver_Debug:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, debug_trait, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, debug_trait), type.clone() ) );
rv.add_function(false, false, "fmt", mv$(fcn));
return mv$(rv);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const ::std::string& name = type.path().nodes().back().name();
-
+
// Generate code for Debug
AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
@@ -345,20 +345,20 @@ public:
node = NEWNODE(CallMethod, mv$(node), AST::PathNode("finish",{}), {});
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
}
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back() = base_path.nodes().back().name();
-
+
::std::vector< AST::ExprNode_Match_Arm> arms;
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(CallMethod,
@@ -372,34 +372,34 @@ public:
// TODO: Complete this.
::std::vector<AST::Pattern> pats_a;
//::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
//nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
//code = NEWNODE(Block, mv$(nodes));
code = NEWNODE(CallMethod,
NEWNODE(NamedValue, AST::Path("f")),
AST::PathNode("write_str",{}),
vec$( NEWNODE(String, v.m_name + "(...)") )
);
-
+
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
),
(Struct,
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
//::std::vector<AST::ExprNodeP> nodes;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
//nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
//code = NEWNODE(Block, mv$(nodes) );
code = NEWNODE(CallMethod,
NEWNODE(NamedValue, AST::Path("f")),
@@ -409,10 +409,10 @@ public:
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_a)) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -423,7 +423,7 @@ public:
NEWNODE(NamedValue, AST::Path("self")),
mv$(arms)
);
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), mv$(node));
}
} g_derive_debug;
@@ -434,7 +434,7 @@ class Deriver_PartialEq:
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("PartialEq", {}) });
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -446,9 +446,9 @@ class Deriver_PartialEq:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "eq", mv$(fcn));
return mv$(rv);
@@ -465,7 +465,7 @@ public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
for( const auto& fld : e.ents )
@@ -488,22 +488,22 @@ public:
)
)
nodes.push_back( NEWNODE(Bool, true) );
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
AST::Pattern pat_b;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(Bool, true);
@@ -514,7 +514,7 @@ public:
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::Pattern> pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
@@ -526,7 +526,7 @@ public:
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( NEWNODE(Bool, true) );
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_b));
@@ -536,7 +536,7 @@ public:
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
@@ -548,14 +548,14 @@ public:
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( NEWNODE(Bool, true) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
pat_b = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_b), true);
code = NEWNODE(Block, mv$(nodes));
)
)
-
+
::std::vector< AST::Pattern> pats;
{
::std::vector< AST::Pattern> tuple_pats;
@@ -563,14 +563,14 @@ public:
tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_b)) );
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
}
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
mv$(code)
));
}
-
+
// Default arm
{
arms.push_back(AST::ExprNode_Match_Arm(
@@ -593,7 +593,7 @@ public:
class Deriver_PartialOrd:
public Deriver
{
-
+
AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2) const
{
return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}) });
@@ -602,15 +602,15 @@ class Deriver_PartialOrd:
{
return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}), AST::PathNode(c3, {}) });
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("PartialOrd", {}) });
const AST::Path path_ordering(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ordering", {}) });
-
+
AST::Path path_option_ordering(core_name, { AST::PathNode("option", {}), AST::PathNode("Option", {}) });
path_option_ordering.nodes().back().args().m_types.push_back( TypeRef(sp, path_ordering) );
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -622,14 +622,14 @@ class Deriver_PartialOrd:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "partial_cmp", mv$(fcn));
return mv$(rv);
}
-
+
AST::ExprNodeP make_compare_and_ret(Span sp, const ::std::string& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const
{
return NEWNODE(Match,
@@ -670,7 +670,7 @@ public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
for( const auto& fld : e.ents )
@@ -693,22 +693,22 @@ public:
)
)
nodes.push_back( this->make_ret_equal(core_name) );
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
AST::Pattern pat_b;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = this->make_ret_equal(core_name);
@@ -719,20 +719,20 @@ public:
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::Pattern> pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
auto name_b = FMT("b" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_b, ::AST::PatternBinding::Type::REF) );
-
+
nodes.push_back(this->make_compare_and_ret( sp, core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( this->make_ret_equal(core_name) );
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_b));
@@ -742,27 +742,27 @@ public:
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
auto name_b = FMT("b" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_b, ::AST::PatternBinding::Type::REF)) );
-
+
nodes.push_back(this->make_compare_and_ret( sp, core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( this->make_ret_equal(core_name) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
pat_b = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_b), true);
code = NEWNODE(Block, mv$(nodes));
)
)
-
+
::std::vector< AST::Pattern> pats;
{
::std::vector< AST::Pattern> tuple_pats;
@@ -770,25 +770,25 @@ public:
tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_b)) );
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
}
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
mv$(code)
));
}
-
+
for(unsigned int a = 0; a < enm.variants().size(); a ++ )
{
for(unsigned int b = 0; b < enm.variants().size(); b ++ )
{
if( a == b )
continue ;
-
+
struct H {
static ::AST::Pattern get_pat_nc(const AST::Path& base_path, const AST::EnumVariant& v) {
AST::Path var_path = base_path + v.m_name;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
return AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(var_path));
@@ -805,7 +805,7 @@ public:
};
::AST::Pattern pat_a = H::get_pat_nc(base_path, enm.variants()[a]);
::AST::Pattern pat_b = H::get_pat_nc(base_path, enm.variants()[b]);
-
+
::std::vector< AST::Pattern> pats;
{
::std::vector< AST::Pattern> tuple_pats;
@@ -813,13 +813,13 @@ public:
tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_b)) );
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
}
-
+
auto code = NEWNODE(CallPath, this->get_path(core_name, "option", "Option", "Some"),
::make_vec1(
NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")))
)
);
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -844,11 +844,11 @@ class Deriver_Eq:
AST::Path get_trait_path(const ::std::string& core_name) const {
return AST::Path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Eq", {}) });
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path(core_name);
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -859,9 +859,9 @@ class Deriver_Eq:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "assert_receiver_is_total_eq", mv$(fcn));
return mv$(rv);
@@ -875,13 +875,13 @@ class Deriver_Eq:
AST::ExprNodeP field(const ::std::string& name) const {
return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const AST::Path assert_method_path = this->get_trait_path(core_name) + "assert_receiver_is_total_eq";
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
for( const auto& fld : e.ents )
@@ -896,10 +896,10 @@ public:
}
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
const AST::Path assert_method_path = this->get_trait_path(core_name) + "assert_receiver_is_total_eq";
@@ -907,12 +907,12 @@ public:
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(Block);
@@ -921,36 +921,36 @@ public:
(Tuple,
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
code = NEWNODE(Block, mv$(nodes));
),
(Struct,
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
code = NEWNODE(Block, mv$(nodes));
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_a)) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -968,7 +968,7 @@ public:
class Deriver_Ord:
public Deriver
{
-
+
AST::Path get_path(const ::std::string core_name, ::std::string c1, ::std::string c2) const
{
return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}) });
@@ -977,12 +977,12 @@ class Deriver_Ord:
{
return AST::Path(core_name, { AST::PathNode(c1, {}), AST::PathNode(c2, {}), AST::PathNode(c3, {}) });
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ord", {}) });
const AST::Path path_ordering(core_name, { AST::PathNode("cmp", {}), AST::PathNode("Ordering", {}) });
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -994,14 +994,14 @@ class Deriver_Ord:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "cmp", mv$(fcn));
return mv$(rv);
}
-
+
AST::ExprNodeP make_compare_and_ret(Span sp, const ::std::string& core_name, AST::ExprNodeP v1, AST::ExprNodeP v2) const
{
return NEWNODE(Match,
@@ -1034,7 +1034,7 @@ public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
for( const auto& fld : e.ents )
@@ -1057,22 +1057,22 @@ public:
)
)
nodes.push_back( this->make_ret_equal(core_name) );
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
AST::Pattern pat_b;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = this->make_ret_equal(core_name);
@@ -1083,20 +1083,20 @@ public:
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::Pattern> pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
auto name_b = FMT("b" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
pats_b.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_b, ::AST::PatternBinding::Type::REF) );
-
+
nodes.push_back(this->make_compare_and_ret( sp, core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( this->make_ret_equal(core_name) );
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_b));
@@ -1106,27 +1106,27 @@ public:
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_b;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
auto name_b = FMT("b" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
pats_b.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_b, ::AST::PatternBinding::Type::REF)) );
-
+
nodes.push_back(this->make_compare_and_ret( sp, core_name,
NEWNODE(NamedValue, AST::Path(name_a)),
NEWNODE(NamedValue, AST::Path(name_b))
));
}
-
+
nodes.push_back( this->make_ret_equal(core_name) );
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
pat_b = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_b), true);
code = NEWNODE(Block, mv$(nodes));
)
)
-
+
::std::vector< AST::Pattern> pats;
{
::std::vector< AST::Pattern> tuple_pats;
@@ -1134,25 +1134,25 @@ public:
tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_b)) );
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
}
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
mv$(code)
));
}
-
+
for(unsigned int a = 0; a < enm.variants().size(); a ++ )
{
for(unsigned int b = 0; b < enm.variants().size(); b ++ )
{
if( a == b )
continue ;
-
+
struct H {
static ::AST::Pattern get_pat_nc(const AST::Path& base_path, const AST::EnumVariant& v) {
AST::Path var_path = base_path + v.m_name;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
return AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(var_path));
@@ -1169,7 +1169,7 @@ public:
};
::AST::Pattern pat_a = H::get_pat_nc(base_path, enm.variants()[a]);
::AST::Pattern pat_b = H::get_pat_nc(base_path, enm.variants()[b]);
-
+
::std::vector< AST::Pattern> pats;
{
::std::vector< AST::Pattern> tuple_pats;
@@ -1177,9 +1177,9 @@ public:
tuple_pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_b)) );
pats.push_back( AST::Pattern(AST::Pattern::TagTuple(), mv$(tuple_pats)) );
}
-
+
auto code = NEWNODE(NamedValue, this->get_path(core_name, "cmp", "Ordering", (a < b ? "Less" : "Greater")));
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -1207,11 +1207,11 @@ class Deriver_Clone:
AST::Path get_method_path(const ::std::string& core_name) const {
return get_trait_path(core_name) + "clone";
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path(core_name);
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -1222,9 +1222,9 @@ class Deriver_Clone:
)
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "clone", mv$(fcn));
return mv$(rv);
@@ -1244,13 +1244,13 @@ class Deriver_Clone:
AST::ExprNodeP field(const ::std::string& name) const {
return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const AST::Path& ty_path = type.m_data.as_Path().path;
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP> > vals;
@@ -1276,21 +1276,21 @@ public:
}
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(const auto& v : enm.variants())
{
AST::ExprNodeP code;
AST::Pattern pat_a;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(NamedValue, base_path + v.m_name);
@@ -1299,36 +1299,36 @@ public:
(Tuple,
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
nodes.push_back( this->clone_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
code = NEWNODE(CallPath, base_path + v.m_name, mv$(nodes));
),
(Struct,
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< ::std::pair<std::string, AST::ExprNodeP> > vals;
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
vals.push_back( ::std::make_pair( fld.m_name, this->clone_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) ) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
code = NEWNODE(StructLiteral, base_path + v.m_name, nullptr, mv$(vals));
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_a)) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -1349,23 +1349,23 @@ class Deriver_Copy:
AST::Path get_trait_path(const ::std::string& core_name) const {
return AST::Path(core_name, { AST::PathNode("marker", {}), AST::PathNode("Copy", {}) });
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path(core_name);
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
return mv$(rv);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), nullptr);
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(enm), nullptr);
@@ -1381,11 +1381,11 @@ class Deriver_Default:
AST::Path get_method_path(const ::std::string& core_name) const {
return AST::Path(AST::Path::TagUfcs(), ::TypeRef(Span()), get_trait_path(core_name), { AST::PathNode("default", {}) } );
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path(core_name);
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -1394,9 +1394,9 @@ class Deriver_Default:
{}
);
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "default", mv$(fcn));
return mv$(rv);
@@ -1407,13 +1407,13 @@ class Deriver_Default:
{}
);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const AST::Path& ty_path = type.m_data.as_Path().path;
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP> > vals;
@@ -1439,10 +1439,10 @@ public:
}
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
ERROR(sp, E0000, "Default cannot be derived for enums");
@@ -1461,11 +1461,11 @@ class Deriver_Hash:
AST::Path get_method_path(const ::std::string& core_name) const {
return get_trait_path(core_name) + "hash";
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path(core_name);
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -1483,9 +1483,9 @@ class Deriver_Hash:
this->get_trait_path_Hasher(core_name)
}) );
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "hash", mv$(fcn));
return mv$(rv);
@@ -1502,12 +1502,12 @@ class Deriver_Hash:
AST::ExprNodeP field(const ::std::string& name) const {
return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name);
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
::std::vector<AST::ExprNodeP> nodes;
-
+
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
for( const auto& fld : e.ents )
@@ -1522,24 +1522,24 @@ public:
}
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), NEWNODE(Block, mv$(nodes)));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(unsigned int var_idx = 0; var_idx < enm.variants().size(); var_idx ++)
{
const auto& v = enm.variants()[var_idx];
AST::ExprNodeP code;
AST::Pattern pat_a;
-
+
auto var_idx_hash = this->hash_val_ref( core_name, NEWNODE(Integer, var_idx, CORETYPE_UINT) );
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = mv$(var_idx_hash);
@@ -1549,14 +1549,14 @@ public:
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::ExprNodeP> nodes;
nodes.push_back( mv$(var_idx_hash) );
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
pats_a.push_back( ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF) );
nodes.push_back( this->hash_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a));
code = NEWNODE(Block, mv$(nodes));
),
@@ -1564,22 +1564,22 @@ public:
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< AST::ExprNodeP > nodes;
nodes.push_back( mv$(var_idx_hash) );
-
+
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), name_a, ::AST::PatternBinding::Type::REF)) );
nodes.push_back( this->hash_val_direct(core_name, NEWNODE(NamedValue, AST::Path(name_a))) );
}
-
+
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
code = NEWNODE(Block, mv$(nodes));
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_a)) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -1607,15 +1607,15 @@ class Deriver_RustcEncodable:
AST::Path get_method_path() const {
return get_trait_path() + "encode";
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path();
-
+
AST::Path result_path = AST::Path(core_name, { AST::PathNode("result", {}), AST::PathNode("Result", {}) });
result_path.nodes()[1].args().m_types.push_back( TypeRef(TypeRef::TagUnit(), sp) );
result_path.nodes()[1].args().m_types.push_back(TypeRef( sp, AST::Path(AST::Path::TagUfcs(), TypeRef(sp, "S", 0x100|0), this->get_trait_path_Encoder(), { AST::PathNode("Error",{}) }) ));
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -1633,9 +1633,9 @@ class Deriver_RustcEncodable:
this->get_trait_path_Encoder()
}) );
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "encode", mv$(fcn));
return mv$(rv);
@@ -1649,7 +1649,7 @@ class Deriver_RustcEncodable:
AST::ExprNodeP field(const ::std::string& name) const {
return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name);
}
-
+
AST::ExprNodeP enc_closure(Span sp, AST::ExprNodeP code) const {
return NEWNODE(Closure,
vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "s"), ::TypeRef(sp) ) ), ::TypeRef(sp),
@@ -1659,12 +1659,12 @@ class Deriver_RustcEncodable:
AST::ExprNodeP get_val_ok(const ::std::string& core_name) const {
return NEWNODE(CallPath, AST::Path(core_name, {AST::PathNode("result",{}), AST::PathNode("Result",{}), AST::PathNode("Ok",{})}), vec$( NEWNODE(Tuple, {})) );
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name();
-
+
::std::vector<AST::ExprNodeP> nodes;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
@@ -1691,7 +1691,7 @@ public:
nodes.push_back( this->get_val_ok(core_name) );
auto closure = this->enc_closure( sp, NEWNODE(Block, mv$(nodes)) );
-
+
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
@@ -1707,22 +1707,22 @@ public:
);
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
for(unsigned int var_idx = 0; var_idx < enm.variants().size(); var_idx ++)
{
const auto& v = enm.variants()[var_idx];
AST::ExprNodeP code;
AST::Pattern pat_a;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant",
@@ -1739,7 +1739,7 @@ public:
(Tuple,
::std::vector<AST::Pattern> pats_a;
::std::vector<AST::ExprNodeP> nodes;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
@@ -1753,7 +1753,7 @@ public:
) );
}
nodes.push_back( this->get_val_ok(core_name) );
-
+
code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_variant",
vec$(
NEWNODE(NamedValue, AST::Path("s")),
@@ -1768,13 +1768,13 @@ public:
(Struct,
::std::vector< ::std::pair<std::string, AST::Pattern> > pats_a;
::std::vector< AST::ExprNodeP > nodes;
-
+
unsigned int idx = 0;
for( const auto& fld : e.m_fields )
{
auto name_a = Ident( FMT("a" << fld.m_name) );
pats_a.push_back( ::std::make_pair(fld.m_name, ::AST::Pattern(::AST::Pattern::TagBind(), Ident(name_a), ::AST::PatternBinding::Type::REF)) );
-
+
nodes.push_back( NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_struct_variant_field",
vec$(
NEWNODE(NamedValue, AST::Path("s")),
@@ -1786,7 +1786,7 @@ public:
idx ++;
}
nodes.push_back( this->get_val_ok(core_name) );
-
+
pat_a = AST::Pattern(AST::Pattern::TagStruct(), base_path + v.m_name, mv$(pats_a), true);
code = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum_struct_variant",
vec$(
@@ -1799,19 +1799,19 @@ public:
);
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagReference(), false, mv$(pat_a)) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
mv$(code)
));
}
-
+
auto node_match = NEWNODE(Match, NEWNODE(NamedValue, AST::Path("self")), mv$(arms));
-
+
const ::std::string& enum_name = type.m_data.as_Path().path.nodes().back().name();
auto node = NEWNODE(CallPath, this->get_trait_path_Encoder() + "emit_enum",
vec$( NEWNODE(NamedValue, AST::Path("s")), NEWNODE(String, enum_name), this->enc_closure(sp, mv$(node_match)) )
@@ -1834,15 +1834,15 @@ class Deriver_RustcDecodable:
AST::Path get_method_path() const {
return get_trait_path() + "decode";
}
-
+
AST::Impl make_ret(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, ::std::vector<TypeRef> types_to_bound, AST::ExprNodeP node) const
{
const AST::Path trait_path = this->get_trait_path();
-
+
AST::Path result_path = AST::Path(core_name, { AST::PathNode("result", {}), AST::PathNode("Result", {}) });
result_path.nodes()[1].args().m_types.push_back( TypeRef(sp, "Self", 0xFFFF) );
result_path.nodes()[1].args().m_types.push_back( TypeRef(sp, AST::Path(AST::Path::TagUfcs(), TypeRef(sp, "D", 0x100|0), this->get_trait_path_Decoder(), { AST::PathNode("Error",{}) })) );
-
+
AST::Function fcn(
sp,
AST::GenericParams(),
@@ -1860,9 +1860,9 @@ class Deriver_RustcDecodable:
this->get_trait_path_Decoder()
}) );
fcn.set_code( NEWNODE(Block, vec$(mv$(node))) );
-
+
AST::GenericParams params = get_params_with_bounds(sp, p, trait_path, mv$(types_to_bound));
-
+
AST::Impl rv( AST::ImplDef( sp, AST::MetaItems(), mv$(params), make_spanned(sp, trait_path), type.clone() ) );
rv.add_function(false, false, "decode", mv$(fcn));
return mv$(rv);
@@ -1873,7 +1873,7 @@ class Deriver_RustcDecodable:
AST::ExprNodeP field(const ::std::string& name) const {
return NEWNODE(Field, NEWNODE(NamedValue, AST::Path("self")), name);
}
-
+
AST::ExprNodeP dec_closure(Span sp, AST::ExprNodeP code) const {
return NEWNODE(Closure,
vec$( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "d"), ::TypeRef(sp) ) ), ::TypeRef(sp),
@@ -1895,13 +1895,13 @@ class Deriver_RustcDecodable:
AST::ExprNodeP get_val_ok_unit(const ::std::string& core_name) const {
return get_val_ok(core_name, NEWNODE(Tuple, {}));
}
-
+
public:
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const override
{
AST::Path base_path = type.m_data.as_Path().path;
const ::std::string& struct_name = type.m_data.as_Path().path.nodes().back().name();
-
+
AST::ExprNodeP node_v;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
@@ -1931,9 +1931,9 @@ public:
)
auto closure = this->dec_closure( sp, this->get_val_ok(core_name, mv$(node_v)) );
-
+
auto args = vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, struct_name), AST::ExprNodeP(), mv$(closure) );
-
+
::AST::ExprNodeP node;
TU_MATCH(AST::StructData, (str.m_data), (e),
(Struct,
@@ -1947,32 +1947,32 @@ public:
node = NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_tuple_struct", mv$(args) );
)
)
-
+
return this->make_ret(sp, core_name, p, type, this->get_field_bounds(str), mv$(node));
}
-
+
AST::Impl handle_item(Span sp, const ::std::string& core_name, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const override
{
AST::Path base_path = type.m_data.as_Path().path;
base_path.nodes().back().args() = ::AST::PathParams();
::std::vector<AST::ExprNode_Match_Arm> arms;
-
+
// 1. Variant names
::std::vector< AST::ExprNodeP> var_name_strs;
-
+
// 2. Decoding arms
for(unsigned int var_idx = 0; var_idx < enm.variants().size(); var_idx ++)
{
const auto& v = enm.variants()[var_idx];
AST::ExprNodeP code;
-
+
TU_MATCH(::AST::EnumVariantData, (v.m_data), (e),
(Value,
code = NEWNODE(NamedValue, base_path + v.m_name);
),
(Tuple,
::std::vector<AST::ExprNodeP> args;
-
+
for( unsigned int idx = 0; idx < e.m_sub_types.size(); idx ++ )
{
auto name_a = FMT("a" << idx);
@@ -1988,12 +1988,12 @@ public:
),
(Struct,
::std::vector< ::std::pair< ::std::string, AST::ExprNodeP > > vals;
-
+
unsigned int idx = 0;
for( const auto& fld : e.m_fields )
{
auto name_a = FMT("a" << fld.m_name);
-
+
vals.push_back(::std::make_pair(fld.m_name, NEWNODE(UniOp, ::AST::ExprNode_UniOp::QMARK, NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_enum_struct_variant_field",
vec$(
NEWNODE(NamedValue, AST::Path("d")),
@@ -2004,14 +2004,14 @@ public:
) )));
idx ++;
}
-
+
code = NEWNODE(StructLiteral, base_path + v.m_name, nullptr, mv$(vals) );
)
)
-
+
::std::vector< AST::Pattern> pats;
pats.push_back( AST::Pattern(AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_UINT, var_idx})) );
-
+
arms.push_back(AST::ExprNode_Match_Arm(
mv$(pats),
nullptr,
@@ -2019,7 +2019,7 @@ public:
));
var_name_strs.push_back( NEWNODE(String, v.m_name) );
}
-
+
// Default arm
{
arms.push_back(AST::ExprNode_Match_Arm(
@@ -2028,7 +2028,7 @@ public:
this->get_val_err_str(core_name, "enum value unknown")
));
}
-
+
auto node_match = NEWNODE(Match, NEWNODE(NamedValue, AST::Path("idx")), mv$(arms));
auto node_var_closure = NEWNODE(Closure,
vec$(
@@ -2040,7 +2040,7 @@ public:
false
);
const ::std::string& enum_name = type.m_data.as_Path().path.nodes().back().name();
-
+
auto node_rev = NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_enum_variant",
vec$(
NEWNODE(NamedValue, AST::Path("d")),
@@ -2048,7 +2048,7 @@ public:
mv$( node_var_closure )
)
);
-
+
auto node = NEWNODE(CallPath, this->get_trait_path_Decoder() + "read_enum",
vec$( NEWNODE(NamedValue, AST::Path("d")), NEWNODE(String, enum_name), this->dec_closure(sp, mv$(node_rev)) )
);
@@ -2096,17 +2096,17 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo
//ERROR(sp, E0000, "#[derive()] requires a list of known traits to derive");
return ;
}
-
+
DEBUG("path = " << path);
bool fail = false;
-
+
const auto& params = item.params();
TypeRef type(sp, path);
auto& types_args = type.path().nodes().back().args();
for( const auto& param : params.ty_params() ) {
types_args.m_types.push_back( TypeRef(TypeRef::TagArg(), sp, param.name()) );
}
-
+
::std::vector< ::std::string> missing_handlers;
for( const auto& trait : attr.items() )
{
@@ -2118,10 +2118,10 @@ static void derive_item(const Span& sp, const AST::Crate& crate, AST::Module& mo
fail = true;
continue ;
}
-
+
mod.add_item(false, "", dp->handle_item(sp, (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core"), params, type, item), {} );
}
-
+
if( fail ) {
ERROR(sp, E0000, "Failed to apply #[derive] - Missing handlers for " << missing_handlers);
}
diff --git a/src/expand/env.cpp b/src/expand/env.cpp
index 8e087858..cad2fa7c 100644
--- a/src/expand/env.cpp
+++ b/src/expand/env.cpp
@@ -15,7 +15,7 @@ namespace {
// Read a string out of the input stream
::std::string get_string(const Span& sp, const AST::Crate& crate, AST::Module& mod, const TokenTree& tt) {
auto lex = TTStream(tt);
-
+
auto n = Parse_ExprVal(lex);
ASSERT_BUG(sp, n, "No expression returned");
if( lex.lookahead(0) != TOK_EOF ) {
@@ -39,7 +39,7 @@ class CExpanderEnv:
if( ident != "" )
ERROR(sp, E0000, "env! doesn't take an ident");
::std::string varname = get_string(sp, crate, mod, tt);
-
+
const char* var_val_cstr = getenv(varname.c_str());
if( !var_val_cstr ) {
ERROR(sp, E0000, "Environment variable '" << varname << "' not defined");
@@ -56,7 +56,7 @@ class CExpanderOptionEnv:
if( ident != "" )
ERROR(sp, E0000, "option_env! doesn't take an ident");
::std::string varname = get_string(sp, crate, mod, tt);
-
+
const char* var_val_cstr = getenv(varname.c_str());
if( !var_val_cstr ) {
::std::vector< TokenTree> rv;
diff --git a/src/expand/format_args.cpp b/src/expand/format_args.cpp
index 9f4eaa93..60c92952 100644
--- a/src/expand/format_args.cpp
+++ b/src/expand/format_args.cpp
@@ -16,7 +16,7 @@
#include <ast/expr.hpp> // for ExprNode_*
namespace {
-
+
/// Options for a formatting fragment
struct FmtArgs
{
@@ -31,20 +31,20 @@ namespace {
Plus,
Minus,
};
-
+
Align align = Align::Unspec;
char align_char = ' ';
-
+
Sign sign = Sign::Unspec;
bool alternate = false;
bool zero_pad = false;
-
+
bool width_is_arg = false;
unsigned int width = 0;
-
+
bool prec_is_arg = false;
unsigned int prec = 0;
-
+
bool operator==(const FmtArgs& x) const { return ::std::memcmp(this, &x, sizeof(*this)) == 0; }
bool operator!=(const FmtArgs& x) const {
#define CMP(f) if(f != x.f) return true
@@ -83,25 +83,25 @@ namespace {
return os;
}
};
-
+
/// A single formatting fragment
struct FmtFrag
{
/// Literal text preceding the fragment
::std::string leading_text;
-
+
/// Argument index used
unsigned int arg_index;
-
+
/// Trait to use for formatting
const char* trait_name;
-
+
// TODO: Support case where this hasn't been edited (telling the formatter that it has nothing to apply)
/// Options
FmtArgs args;
};
-
+
class string_view {
const char* s;
const char* e;
@@ -109,16 +109,16 @@ namespace {
string_view(const char* s, const char* e):
s(s), e(e)
{}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const string_view& x) {
for(const char* p = x.s; p != x.e; p++)
os << *p;
return os;
}
};
-
+
/// Parse a format string into a sequence of fragments.
- ///
+ ///
/// Returns a list of fragments, and the remaining free text after the last format sequence
::std::tuple< ::std::vector<FmtFrag>, ::std::string> parse_format_string(
const Span& sp,
@@ -129,10 +129,10 @@ namespace {
{
unsigned int n_named = named.size();
unsigned int next_free = 0;
-
+
::std::vector<FmtFrag> frags;
::std::string cur_literal;
-
+
const char* s = format_string.c_str();
for( ; *s; s ++)
{
@@ -155,17 +155,17 @@ namespace {
cur_literal += '{';
continue ;
}
-
+
// Debugging: A view of the formatting fragment
const char* s2 = s;
while(*s2 && *s2 != '}')
s2 ++;
auto fmt_frag_str = string_view { s, s2 };
-
+
unsigned int index = ~0u;
const char* trait_name;
FmtArgs args;
-
+
// Formatting parameter
if( *s != ':' && *s != '}' ) {
// Parse either an integer or an identifer
@@ -197,11 +197,11 @@ namespace {
// - If index is ~0u at the end of this block, it's set to the next arg
// - This allows {:.*} to format correctly (taking <prec> then <arg>)
}
-
+
// If next character is ':', parse extra information
if( *s == ':' ) {
s ++; // eat ':'
-
+
// Alignment
if( s[0] != '\0' && (s[1] == '<' || s[1] == '^' || s[1] == '>') ) {
args.align_char = s[0];
@@ -222,7 +222,7 @@ namespace {
else {
//args.align = FmtArgs::Align::Unspec;
}
-
+
// Sign
if( *s == '+' ) {
args.sign = FmtArgs::Sign::Plus;
@@ -235,7 +235,7 @@ namespace {
else {
args.sign = FmtArgs::Sign::Unspec;
}
-
+
if( *s == '#' ) {
args.alternate = true;
s ++;
@@ -243,7 +243,7 @@ namespace {
else {
//args.alternate = false;
}
-
+
if( *s == '0' ) {
args.zero_pad = true;
s ++;
@@ -251,7 +251,7 @@ namespace {
else {
//args.zero_pad = false;
}
-
+
// Padded width
if( ::std::isdigit(*s) /*|| *s == '*'*/ ) {
unsigned int val = 0;
@@ -262,7 +262,7 @@ namespace {
s ++;
}
args.width = val;
-
+
if( *s == '$' ) {
args.width_is_arg = true;
s ++;
@@ -287,7 +287,7 @@ namespace {
ERROR(sp, E0000, "Named argument '"<<ident<<"' not found");
args.width = n_free + it->second;
args.width_is_arg = true;
-
+
s ++;
}
else {
@@ -317,7 +317,7 @@ namespace {
s ++;
}
args.prec = val;
-
+
if( *s == '$' ) {
args.prec_is_arg = true;
s ++;
@@ -330,13 +330,13 @@ namespace {
// Wut?
}
}
-
+
// Parse ident?
// - Lazy way is to just handle a single char and ensure that it is just a single char
if( s[0] != '}' && s[0] != '\0' && s[1] != '}' ) {
TODO(sp, "Parse formatting fragment at \"" << fmt_frag_str << "\" (long type)");
}
-
+
switch(s[0])
{
case '\0':
@@ -361,7 +361,7 @@ namespace {
// Otherwise, it's just a trivial Display call
trait_name = "Display";
}
-
+
// Set index if unspecified
if( index == ~0u )
{
@@ -371,7 +371,7 @@ namespace {
index = next_free + n_named;
next_free ++;
}
-
+
frags.push_back( FmtFrag {
mv$(cur_literal),
index, trait_name,
@@ -379,7 +379,7 @@ namespace {
});
}
}
-
+
return ::std::make_tuple( mv$(frags), mv$(cur_literal) );
}
}
@@ -414,11 +414,11 @@ class CFormatArgsExpander:
::std::unique_ptr<TokenStream> expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override
{
Token tok;
-
+
auto lex = TTStream(tt);
if( ident != "" )
ERROR(sp, E0000, "format_args! doesn't take an ident");
-
+
auto n = Parse_ExprVal(lex);
ASSERT_BUG(sp, n, "No expression returned");
Expand_BareExpr(crate, mod, n);
@@ -429,11 +429,11 @@ class CFormatArgsExpander:
}
const auto& format_string_sp = format_string_np->span();
const auto& format_string = format_string_np->m_value;
-
+
::std::map< ::std::string, unsigned int> named_args_index;
::std::vector<TokenTree> named_args;
::std::vector<TokenTree> free_args;
-
+
// - Parse the arguments
while( GET_TOK(tok, lex) == TOK_COMMA )
{
@@ -441,17 +441,17 @@ class CFormatArgsExpander:
GET_TOK(tok, lex);
break;
}
-
+
// - Named parameters
if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_EQUAL )
{
GET_CHECK_TOK(tok, lex, TOK_IDENT);
auto name = mv$(tok.str());
-
+
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
-
+
auto expr_tt = TokenTree(Token( InterpolatedFragment(InterpolatedFragment::EXPR, Parse_Expr0(lex).release()) ));
-
+
auto ins_rv = named_args_index.insert( ::std::make_pair(mv$(name), named_args.size()) );
if( ins_rv.second == false ) {
ERROR(sp, E0000, "Duplicate definition of named argument `" << ins_rv.first->first << "`");
@@ -466,12 +466,12 @@ class CFormatArgsExpander:
}
}
CHECK_TOK(tok, TOK_EOF);
-
+
// - Parse the format string
::std::vector< FmtFrag> fragments;
::std::string tail;
::std::tie( fragments, tail ) = parse_format_string(format_string_sp, format_string, named_args_index, free_args.size());
-
+
bool is_simple = true;
for(unsigned int i = 0; i < fragments.size(); i ++)
{
@@ -484,7 +484,7 @@ class CFormatArgsExpander:
is_simple = false;
}
}
-
+
::std::vector<TokenTree> toks;
// This should expand to a `match (a, b, c) { (ref _0, ref _1, ref _2) => ... }` to ensure that the values live long enough?
// - Also avoids name collisions
@@ -513,7 +513,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_PAREN_CLOSE) );
toks.push_back( TokenTree(TOK_FATARROW) );
toks.push_back( TokenTree(TOK_BRACE_OPEN) );
-
+
// Save fragments into a static
// `static FRAGMENTS: [&'static str; N] = [...];`
// - Contains N+1 entries, where N is the number of fragments
@@ -521,7 +521,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_RWORD_STATIC) );
toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
toks.push_back( TokenTree(TOK_COLON) );
-
+
toks.push_back( TokenTree(TOK_SQUARE_OPEN) );
toks.push_back( Token(TOK_AMP) );
toks.push_back( Token(TOK_LIFETIME, "static") );
@@ -529,9 +529,9 @@ class CFormatArgsExpander:
toks.push_back( Token(TOK_SEMICOLON) );
toks.push_back( Token(fragments.size() + 1, CORETYPE_UINT) );
toks.push_back( TokenTree(TOK_SQUARE_CLOSE) );
-
+
toks.push_back( Token(TOK_EQUAL) );
-
+
toks.push_back( TokenTree(TOK_SQUARE_OPEN) );
for(const auto& frag : fragments ) {
toks.push_back( Token(TOK_STRING, frag.leading_text) );
@@ -539,10 +539,10 @@ class CFormatArgsExpander:
}
toks.push_back( Token(TOK_STRING, tail) );
toks.push_back( TokenTree(TOK_SQUARE_CLOSE) );
-
+
toks.push_back( Token(TOK_SEMICOLON) );
}
-
+
if( is_simple )
{
// ::fmt::Arguments::new_v1
@@ -553,7 +553,7 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_AMP) );
toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
toks.push_back( TokenTree(TOK_COMMA) );
-
+
toks.push_back( TokenTree(TOK_AMP) );
toks.push_back( TokenTree(TOK_SQUARE_OPEN) );
for(const auto& frag : fragments )
@@ -561,9 +561,9 @@ class CFormatArgsExpander:
push_path(toks, crate, {"fmt", "ArgumentV1", "new"});
toks.push_back( Token(TOK_PAREN_OPEN) );
toks.push_back( Token(TOK_IDENT, FMT("a" << frag.arg_index)) );
-
+
toks.push_back( TokenTree(TOK_COMMA) );
-
+
push_path(toks, crate, {"fmt", frag.trait_name, "fmt"});
toks.push_back( TokenTree(TOK_PAREN_CLOSE) );
toks.push_back( TokenTree(TOK_COMMA) );
@@ -585,9 +585,9 @@ class CFormatArgsExpander:
toks.push_back( TokenTree(TOK_AMP) );
toks.push_back( Token(TOK_IDENT, "FRAGMENTS") );
toks.push_back( TokenTree(TOK_COMMA) );
-
+
// 1. Generate a set of arguments+formatters
-
+
// TODO: Fragments to format
// - The format stored by mrustc doesn't quite work with how rustc (and fmt::rt::v1) works
toks.push_back( TokenTree(TOK_AMP) );
@@ -599,10 +599,10 @@ class CFormatArgsExpander:
// )
toks.push_back( TokenTree(TOK_PAREN_CLOSE) );
} // if(is_simple) else
-
+
toks.push_back( TokenTree(TOK_BRACE_CLOSE) );
toks.push_back( TokenTree(TOK_BRACE_CLOSE) );
-
+
return box$( TTStreamO(TokenTree(Ident::Hygiene::new_scope(), mv$(toks))) );
}
};
diff --git a/src/expand/include.cpp b/src/expand/include.cpp
index 83a2aa03..6b1a5508 100644
--- a/src/expand/include.cpp
+++ b/src/expand/include.cpp
@@ -22,7 +22,7 @@ namespace {
return base_path + path;
}
else {
-
+
auto slash = base_path.find_last_of('/');
if( slash == ::std::string::npos )
{
@@ -48,17 +48,17 @@ class CIncludeExpander:
{
if( ident != "" )
ERROR(sp, E0000, "include! doesn't take an ident");
-
+
Token tok;
auto lex = TTStream(tt);
-
+
// TODO: Parse+expand
GET_CHECK_TOK(tok, lex, TOK_STRING);
auto path = mv$(tok.str());
GET_CHECK_TOK(tok, lex, TOK_EOF);
-
+
::std::string file_path = get_path_relative_to(mod.m_file_info.path, mv$(path));
-
+
return box$( Lexer(file_path) );
}
};
diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp
index 1e3564c2..83637bf6 100644
--- a/src/expand/lang_item.cpp
+++ b/src/expand/lang_item.cpp
@@ -37,10 +37,10 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "mul" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "div" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "rem" ) { DEBUG("Bind '"<<name<<"' to " << path); }
-
+
else if( name == "neg" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "not" ) { DEBUG("Bind '"<<name<<"' to " << path); }
-
+
else if( name == "bitand" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "bitor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "bitxor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
@@ -57,7 +57,7 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "bitxor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "shl_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "shr_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
-
+
else if( name == "index" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "deref" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "index_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
@@ -65,16 +65,16 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "fn" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "fn_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }
-
+
else if( name == "eq" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }
-
+
else if( name == "iterator" ) { /* mrustc just desugars? */ }
-
+
else if( name == "debug_trait" ) { /* TODO: Poke derive() with this */ }
-
+
// Structs
else if( name == "non_zero" ) { }
else if( name == "phantom_data" ) { }
@@ -83,12 +83,12 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "range_from" ) { }
else if( name == "range_to" ) { }
else if( name == "unsafe_cell" ) { }
-
+
// Functions
else if( name == "panic" ) { }
else if( name == "panic_bounds_check" ) { }
else if( name == "panic_fmt" ) {
-
+
}
else if( name == "str_eq" ) { }
// - builtin `box` support
@@ -98,9 +98,9 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,
else if( name == "owned_box" ) { }
// - start
else if( name == "start" ) { }
-
+
else if( name == "eh_personality" ) { }
-
+
else {
ERROR(sp, E0000, "Unknown language item '" << name << "'");
}
@@ -145,10 +145,10 @@ public:
)
)
}
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Module& mod, AST::ImplDef& impl) const override {
const ::std::string& name = mi.string();
-
+
if( name == "i8" ) {}
else if( name == "u8" ) {}
else if( name == "i16" ) {}
@@ -172,7 +172,7 @@ public:
else {
ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
}
-
+
// TODO: Somehow annotate these impls to allow them to provide inherents?
// - mrustc is lazy and inefficient, so these don't matter :)
}
diff --git a/src/expand/macro_rules.cpp b/src/expand/macro_rules.cpp
index 638b9ddd..338edd12 100644
--- a/src/expand/macro_rules.cpp
+++ b/src/expand/macro_rules.cpp
@@ -26,12 +26,12 @@ class CMacroRulesExpander:
{
if( ident == "" )
ERROR(sp, E0000, "macro_rules! requires an identifier" );
-
+
DEBUG("Parsing macro_rules! " << ident);
TTStream lex(tt);
auto mac = Parse_MacroRules(lex);
mod.add_macro( false, ident, mv$(mac) );
-
+
return ::std::unique_ptr<TokenStream>( new TTStreamO(TokenTree()) );
}
};
@@ -40,11 +40,11 @@ class CMacroUseHandler:
public ExpandDecorator
{
AttrStage stage() const override { return AttrStage::Post; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
{
TRACE_FUNCTION_F("path=" << path);
-
+
TU_IFLET( ::AST::Item, i, None, e,
// Just ignore
)
@@ -107,14 +107,14 @@ class CMacroUseHandler:
ERROR(sp, E0000, "Use of #[macro_use] on non-module/crate - " << i.tag_str());
}
}
-
+
};
class CMacroExportHandler:
public ExpandDecorator
{
AttrStage stage() const override { return AttrStage::Post; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
{
if( i.is_None() ) {
@@ -125,7 +125,7 @@ class CMacroExportHandler:
ERROR(sp, E0000, "#[macro_export] is only valid on macro_rules!");
}
const auto& name = mac.input_ident();
-
+
// Tag the macro in the module for crate export
auto it = ::std::find_if( mod.macros().begin(), mod.macros().end(), [&](const auto& x){ return x.name == name; } );
ASSERT_BUG(sp, it != mod.macros().end(), "Macro '" << name << "' not defined in this module");
@@ -150,7 +150,7 @@ class CMacroReexportHandler:
const auto& crate_name = i.as_Crate().name;
auto& ext_crate = *crate.m_extern_crates.at(crate_name).m_hir;
-
+
if( mi.has_sub_items() )
{
for( const auto& si : mi.items() )
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index ab016b95..a2537218 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -82,7 +82,7 @@ void Expand_Attrs(::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& crate
if( name == "" ) {
return ::std::unique_ptr<TokenStream>();
}
-
+
for( const auto& m : g_macros )
{
if( name == m.first )
@@ -91,8 +91,8 @@ void Expand_Attrs(::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& crate
return e;
}
}
-
-
+
+
// Iterate up the module tree, using the first located macro
for(const auto* ll = &modstack; ll; ll = ll->m_prev)
{
@@ -104,7 +104,7 @@ void Expand_Attrs(::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& crate
{
if( input_ident != "" )
ERROR(mi_span, E0000, "macro_rules! macros can't take an ident");
-
+
auto e = Macro_Invoke(name.c_str(), *mr.data, mv$(input_tt), mod);
return e;
}
@@ -117,13 +117,13 @@ void Expand_Attrs(::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& crate
{
if( input_ident != "" )
ERROR(mi_span, E0000, "macro_rules! macros can't take an ident");
-
+
auto e = Macro_Invoke(name.c_str(), *mri.data, mv$(input_tt), mod);
return e;
}
}
}
-
+
// Error - Unknown macro name
ERROR(mi_span, E0000, "Unknown macro '" << name << "'");
}
@@ -139,7 +139,7 @@ void Expand_Pattern(::AST::Crate& crate, LList<const AST::Module*> modstack, ::A
),
(Macro,
const auto span = e.inv->span();
-
+
auto tt = Expand_Macro(crate, modstack, mod, *e.inv);
if( ! tt ) {
ERROR(span, E0000, "Macro in pattern didn't expand to anything");
@@ -149,13 +149,13 @@ void Expand_Pattern(::AST::Crate& crate, LList<const AST::Module*> modstack, ::A
if( LOOK_AHEAD(lex) != TOK_EOF ) {
ERROR(span, E0000, "Trailing tokens in macro expansion");
}
-
+
if( pat.binding().is_valid() ) {
- if( newpat.binding().is_valid() )
+ if( newpat.binding().is_valid() )
ERROR(span, E0000, "Macro expansion provided a binding, but one already present");
newpat.binding() = mv$(pat.binding());
}
-
+
pat = mv$(newpat);
),
(Any,
@@ -218,7 +218,7 @@ void Expand_Type(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:
if( tt->lookahead(0) != TOK_EOF )
ERROR(e.inv.span(), E0000, "Extra tokens after parsed type");
ty = mv$(new_ty);
-
+
Expand_Type(crate, modstack, mod, ty);
),
(Primitive,
@@ -263,19 +263,19 @@ struct CExpandExpr:
::AST::Crate& crate;
LList<const AST::Module*> modstack;
::std::unique_ptr<::AST::ExprNode> replacement;
-
+
AST::ExprNode_Block* current_block = nullptr;
-
+
CExpandExpr(::AST::Crate& crate, LList<const AST::Module*> ms):
crate(crate),
modstack(ms)
{
}
-
+
::AST::Module& cur_mod() {
return *const_cast< ::AST::Module*>(modstack.m_item);
}
-
+
void visit(::std::unique_ptr<AST::ExprNode>& cnode) {
if(cnode.get())
Expand_Attrs(cnode->attrs(), AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, cnode); });
@@ -292,7 +292,7 @@ struct CExpandExpr:
cnode = mv$(this->replacement);
}
}
-
+
if(cnode.get())
Expand_Attrs(cnode->attrs(), AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, cnode); });
assert( ! this->replacement );
@@ -320,14 +320,14 @@ struct CExpandExpr:
}
}
}
-
+
void visit(::AST::ExprNode_Macro& node) override
{
TRACE_FUNCTION_F("ExprNode_Macro - name = " << node.m_name);
if( node.m_name == "" ) {
return ;
}
-
+
auto& mod = this->cur_mod();
auto ttl = Expand_Macro(
crate, modstack, mod,
@@ -365,7 +365,7 @@ struct CExpandExpr:
node.m_name = "";
}
}
-
+
void visit(::AST::ExprNode_Block& node) override {
unsigned int mod_item_count = 0;
// TODO: macro_rules! invocations within the expression list influence this.
@@ -374,7 +374,7 @@ struct CExpandExpr:
Expand_Mod(crate, modstack, node.m_local_mod->path(), *node.m_local_mod);
mod_item_count = node.m_local_mod->items().size();
}
-
+
auto saved = this->current_block;
this->current_block = &node;
this->visit_vector(node.m_nodes);
@@ -444,7 +444,7 @@ struct CExpandExpr:
nullptr,
::AST::ExprNodeP(new ::AST::ExprNode_Flow(::AST::ExprNode_Flow::BREAK, node.m_label, nullptr))
) );
-
+
replacement.reset(new ::AST::ExprNode_Match(
::AST::ExprNodeP(new ::AST::ExprNode_CallPath(
::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(node.span()), path_IntoIterator, { ::AST::PathNode("into_iter") } ),
@@ -563,7 +563,7 @@ struct CExpandExpr:
auto path_Err = ::AST::Path(core_crate, {::AST::PathNode("result"), ::AST::PathNode("Result"), ::AST::PathNode("Err")});
auto path_From = ::AST::Path(core_crate, {::AST::PathNode("convert"), ::AST::PathNode("From")});
path_From.nodes().back().args().m_types.push_back( ::TypeRef(node.span()) );
-
+
// Desugars into
// ```
// match `m_value` {
@@ -571,7 +571,7 @@ struct CExpandExpr:
// Err(e) => return Err(From::from(e)),
// }
// ```
-
+
::std::vector< ::AST::ExprNode_Match_Arm> arms;
// `Ok(v) => v,`
arms.push_back(::AST::ExprNode_Match_Arm(
@@ -637,23 +637,23 @@ void Expand_Impl(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:
DEBUG("Deleted");
return ;
}
-
+
Expand_Type(crate, modstack, mod, impl.def().type());
//Expand_Type(crate, modstack, mod, impl.def().trait());
-
+
DEBUG("> Items");
for( unsigned int idx = 0; idx < impl.items().size(); idx ++ )
{
auto& i = impl.items()[idx];
DEBUG(" - " << i.name << " :: " << i.data->attrs);
-
+
// TODO: Make a path from the impl definition? Requires having the impl def resolved to be correct
// - Does it? the namespace is essentially the same. There may be issues with wherever the path is used though
//::AST::Path path = modpath + i.name;
-
+
auto attrs = mv$(i.data->attrs);
Expand_Attrs(attrs, AttrStage::Pre, crate, AST::Path(), mod, *i.data);
-
+
TU_MATCH_DEF(AST::Item, (*i.data), (e),
(
throw ::std::runtime_error("BUG: Unknown item type in impl block");
@@ -665,7 +665,7 @@ void Expand_Impl(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:
TRACE_FUNCTION_F("Macro invoke " << e.name());
// Move out of the module to avoid invalidation if a new macro invocation is added
auto mi_owned = mv$(e);
-
+
auto ttl = Expand_Macro(crate, modstack, mod, mi_owned);
if( ttl.get() )
@@ -697,7 +697,7 @@ void Expand_Impl(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:
Expand_Type(crate, modstack, mod, e.type());
)
)
-
+
// Run post-expansion decorators and restore attributes
{
auto& i = impl.items()[idx];
@@ -717,7 +717,7 @@ void Expand_ImplDef(::AST::Crate& crate, LList<const AST::Module*> modstack, ::A
DEBUG("Deleted");
return ;
}
-
+
Expand_Type(crate, modstack, mod, impl_def.type());
//Expand_Type(crate, modstack, mod, impl_def.trait());
@@ -727,10 +727,10 @@ void Expand_ImplDef(::AST::Crate& crate, LList<const AST::Module*> modstack, ::A
void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Path modpath, ::AST::Module& mod, unsigned int first_item)
{
TRACE_FUNCTION_F("modpath = " << modpath);
-
+
for( const auto& mi: mod.macro_imports_res() )
DEBUG("- Imports '" << mi.name << "'");
-
+
// Insert prelude if: Enabled for this module, present for the crate, and this module is not an anon
if( crate.m_prelude_path != AST::Path() )
{
@@ -738,20 +738,20 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
mod.add_alias(false, ::AST::UseStmt(Span(), crate.m_prelude_path), "", {});
}
}
-
+
DEBUG("Items");
for( unsigned int idx = first_item; idx < mod.items().size(); idx ++ )
{
auto& i = mod.items()[idx];
-
+
DEBUG("- " << i.name << " (" << ::AST::Item::tag_to_str(i.data.tag()) << ") :: " << i.data.attrs);
::AST::Path path = modpath + i.name;
-
+
auto attrs = mv$(i.data.attrs);
Expand_Attrs(attrs, AttrStage::Pre, crate, path, mod, i.data);
-
+
auto dat = mv$(i.data);
-
+
TU_MATCH(::AST::Item, (dat), (e),
(None,
// Skip, nothing
@@ -759,9 +759,9 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
(MacroInv,
// Move out of the module to avoid invalidation if a new macro invocation is added
auto mi_owned = mv$(e);
-
+
TRACE_FUNCTION_F("Macro invoke " << mi_owned.name());
-
+
auto ttl = Expand_Macro(crate, modstack, mod, mi_owned);
assert( mi_owned.name() != "");
@@ -805,7 +805,7 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
(Crate,
// Can't recurse into an `extern crate`
),
-
+
(Struct,
TU_MATCH(AST::StructData, (e.m_data), (sd),
(Struct,
@@ -883,7 +883,7 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
{
auto attrs = mv$(ti.data.attrs);
Expand_Attrs(attrs, AttrStage::Pre, crate, AST::Path(), mod, ti.data);
-
+
TU_MATCH_DEF(AST::Item, (ti.data), (e),
(
throw ::std::runtime_error("BUG: Unknown item type in impl block");
@@ -905,7 +905,7 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
Expand_Type(crate, modstack, mod, e.type());
)
)
-
+
Expand_Attrs(attrs, AttrStage::Post, crate, AST::Path(), mod, ti.data);
if( ti.data.attrs.m_items.size() == 0 )
ti.data.attrs = mv$(attrs);
@@ -914,7 +914,7 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
(Type,
Expand_Type(crate, modstack, mod, e.type());
),
-
+
(Function,
for(auto& arg : e.args()) {
Expand_Pattern(crate, modstack, mod, arg.first, false);
@@ -929,9 +929,9 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
)
)
Expand_Attrs(attrs, AttrStage::Post, crate, path, mod, dat);
-
+
{
-
+
auto& i = mod.items()[idx];
if( i.data.tag() == ::AST::Item::TAGDEAD ) {
i.data = mv$(dat);
@@ -941,26 +941,26 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
i.data.attrs = mv$(attrs);
}
}
-
+
// IGNORE m_anon_modules, handled as part of expressions
-
+
//for( const auto& mi: mod.macro_imports_res() )
// DEBUG("- Imports '" << mi.name << "'");
}
void Expand_Mod_IndexAnon(::AST::Crate& crate, ::AST::Module& mod)
{
TRACE_FUNCTION_F("mod=" << mod.path());
-
+
for(auto& i : mod.items())
{
DEBUG("- " << i.data.tag_str() << " '" << i.name << "'");
TU_IFLET(::AST::Item, (i.data), Module, e,
Expand_Mod_IndexAnon(crate, e);
-
+
// TODO: Also ensure that all #[macro_export] macros end up in parent
)
}
-
+
for( auto& mp : mod.anon_mods() )
{
if( mp.unique() ) {
@@ -975,10 +975,10 @@ void Expand_Mod_IndexAnon(::AST::Crate& crate, ::AST::Module& mod)
void Expand(::AST::Crate& crate)
{
auto modstack = LList<const ::AST::Module*>(nullptr, &crate.m_root_module);
-
+
// 1. Crate attributes
Expand_Attrs(crate.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate); });
-
+
// Insert magic for libstd/libcore
// NOTE: The actual crates are loaded in "LoadCrates" using magic in AST::Crate::load_externs
switch( crate.m_load_std )
@@ -1002,7 +1002,7 @@ void Expand(::AST::Crate& crate)
case ::AST::Crate::LOAD_NONE:
break;
}
-
+
// 2. Module attributes
for( auto& a : crate.m_attrs.m_items )
{
@@ -1012,10 +1012,10 @@ void Expand(::AST::Crate& crate)
}
}
}
-
+
// 3. Module tree
Expand_Mod(crate, modstack, ::AST::Path("",{}), crate.m_root_module);
-
+
// Post-process
Expand_Mod_IndexAnon(crate, crate.m_root_module);
#if 0
diff --git a/src/expand/rustc_diagnostics.cpp b/src/expand/rustc_diagnostics.cpp
index 917a5e4d..f2e436c4 100644
--- a/src/expand/rustc_diagnostics.cpp
+++ b/src/expand/rustc_diagnostics.cpp
@@ -34,16 +34,16 @@ class CExpanderBuildDiagnosticArray:
if( ident != "" )
ERROR(sp, E0000, "__build_diagnostic_array! doesn't take an ident");
auto lex = TTStream(tt);
-
+
Token tok;
-
+
GET_CHECK_TOK(tok, lex, TOK_IDENT);
//auto crate_name = mv$(tok.str());
GET_CHECK_TOK(tok, lex, TOK_COMMA);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
auto item_name = mv$(tok.str());
GET_CHECK_TOK(tok, lex, TOK_EOF);
-
+
::std::vector<TokenTree> toks;
toks.push_back( TOK_RWORD_STATIC );
toks.push_back( Token(TOK_IDENT, item_name) );
@@ -63,7 +63,7 @@ class CExpanderBuildDiagnosticArray:
toks.push_back( TOK_SQUARE_OPEN );
toks.push_back( TOK_SQUARE_CLOSE );
toks.push_back( TOK_SEMICOLON );
-
+
return box$( TTStreamO(TokenTree( lex.getHygiene(), mv$(toks) )) );
}
};
diff --git a/src/expand/std_prelude.cpp b/src/expand/std_prelude.cpp
index 81eecf7f..16c4ce90 100644
--- a/src/expand/std_prelude.cpp
+++ b/src/expand/std_prelude.cpp
@@ -8,7 +8,7 @@ class Decorator_NoStd:
{
public:
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const override {
if( crate.m_load_std != AST::Crate::LOAD_STD ) {
ERROR(sp, E0000, "Invalid use of #![no_std] with itself or #![no_core]");
@@ -21,7 +21,7 @@ class Decorator_NoCore:
{
public:
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const override {
if( crate.m_load_std != AST::Crate::LOAD_STD ) {
ERROR(sp, E0000, "Invalid use of #![no_core] with itself or #![no_std]");
@@ -41,7 +41,7 @@ class Decorator_NoPrelude:
{
public:
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override {
if( i.is_Module() ) {
i.as_Module().m_insert_prelude = false;
@@ -57,7 +57,7 @@ class Decorator_PreludeImport:
{
public:
AttrStage stage() const override { return AttrStage::Post; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override {
if( i.is_Use() ) {
const auto& p = i.as_Use().path;
diff --git a/src/expand/stringify.cpp b/src/expand/stringify.cpp
index ce16847b..f43d896f 100644
--- a/src/expand/stringify.cpp
+++ b/src/expand/stringify.cpp
@@ -16,14 +16,14 @@ class CExpander:
{
Token tok;
::std::string rv;
-
+
auto lex = TTStream(tt);
while( GET_TOK(tok, lex) != TOK_EOF )
{
rv += tok.to_str();
rv += " ";
}
-
+
return box$( TTStreamO(TokenTree(Token(TOK_STRING, mv$(rv)))) );
}
};
diff --git a/src/expand/test.cpp b/src/expand/test.cpp
index ba18fd24..fba6556f 100644
--- a/src/expand/test.cpp
+++ b/src/expand/test.cpp
@@ -12,12 +12,12 @@ class CTestHandler:
public ExpandDecorator
{
AttrStage stage() const override { return AttrStage::Pre; }
-
+
void handle(const Span& sp, const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override {
if( ! i.is_Function() ) {
ERROR(sp, E0000, "#[test] can only be put on functions - found on " << i.tag_str());
}
-
+
// TODO: Proper #[test] support, for now just remove them
i = AST::Item::make_None({});
}
diff --git a/src/hir/crate_ptr.hpp b/src/hir/crate_ptr.hpp
index ad6f374e..c870b1ea 100644
--- a/src/hir/crate_ptr.hpp
+++ b/src/hir/crate_ptr.hpp
@@ -10,7 +10,7 @@ class Crate;
class CratePtr
{
Crate* m_ptr;
-
+
public:
CratePtr();
CratePtr(Crate c);
@@ -27,7 +27,7 @@ public:
return *this;
}
~CratePtr();
-
+
Crate& operator*() { return *m_ptr; }
const Crate& operator*() const { return *m_ptr; }
Crate* operator->() { return m_ptr; }
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp
index 7b821630..de0d13da 100644
--- a/src/hir/deserialise.cpp
+++ b/src/hir/deserialise.cpp
@@ -14,12 +14,12 @@
#include "serialise_lowlevel.hpp"
namespace {
-
+
template<typename T>
struct D
{
};
-
+
class HirDeserialiser
{
const ::std::string& m_crate_name;
@@ -29,10 +29,10 @@ namespace {
m_crate_name( crate_name ),
m_in(in)
{}
-
+
::std::string read_string() { return m_in.read_string(); }
size_t deserialise_count() { return m_in.read_count(); }
-
+
template<typename V>
::std::map< ::std::string,V> deserialise_strmap()
{
@@ -74,7 +74,7 @@ namespace {
}
return rv;
}
-
+
template<typename T>
::std::vector<T> deserialise_vec()
{
@@ -100,13 +100,13 @@ namespace {
{
return ::HIR::VisEnt<T> { m_in.read_bool(), D<T>::des(*this) };
}
-
+
template<typename T>
::std::unique_ptr<T> deserialise_ptr() {
return box$( D<T>::des(*this) );
}
-
-
+
+
::HIR::TypeRef deserialise_type();
::HIR::SimplePath deserialise_simplepath();
::HIR::PathParams deserialise_pathparams();
@@ -117,18 +117,18 @@ namespace {
::HIR::GenericParams deserialise_genericparams();
::HIR::TypeParamDef deserialise_typaramdef();
::HIR::GenericBound deserialise_genericbound();
-
+
::HIR::Crate deserialise_crate();
::HIR::Module deserialise_module();
-
+
::HIR::TypeImpl deserialise_typeimpl()
{
::HIR::TypeImpl rv;
TRACE_FUNCTION_FR("", "impl" << rv.m_params.fmt_args() << " " << rv.m_type);
-
+
rv.m_params = deserialise_genericparams();
rv.m_type = deserialise_type();
-
+
size_t method_count = m_in.read_count();
for(size_t i = 0; i < method_count; i ++)
{
@@ -152,12 +152,12 @@ namespace {
{
::HIR::TraitImpl rv;
TRACE_FUNCTION_FR("", "impl" << rv.m_params.fmt_args() << " ?" << rv.m_trait_args << " for " << rv.m_type);
-
+
rv.m_params = deserialise_genericparams();
rv.m_trait_args = deserialise_pathparams();
rv.m_type = deserialise_type();
-
-
+
+
size_t method_count = m_in.read_count();
for(size_t i = 0; i < method_count; i ++)
{
@@ -190,7 +190,7 @@ namespace {
m_in.read_bool(), deserialise_type()
} ) );
}
-
+
// m_src_module doesn't matter after typeck
return rv;
}
@@ -203,7 +203,7 @@ namespace {
deserialise_type()
};
}
-
+
::MacroRulesPtr deserialise_macrorulesptr()
{
return ::MacroRulesPtr( new MacroRules(deserialise_macrorules()) );
@@ -284,7 +284,7 @@ namespace {
throw "";
}
}
-
+
::Token deserialise_token() {
::Token tok;
// HACK: Hand off to old serialiser code
@@ -298,7 +298,7 @@ namespace {
}
::HIR::Literal deserialise_literal();
-
+
::HIR::ExprPtr deserialise_exprptr()
{
::HIR::ExprPtr rv;
@@ -314,7 +314,7 @@ namespace {
::MIR::Statement deserialise_mir_statement();
::MIR::Terminator deserialise_mir_terminator();
::MIR::CallTarget deserialise_mir_calltarget();
-
+
::MIR::LValue deserialise_mir_lvalue() {
::MIR::LValue rv;
TRACE_FUNCTION_FR("", rv);
@@ -352,7 +352,7 @@ namespace {
::MIR::RValue deserialise_mir_rvalue()
{
TRACE_FUNCTION;
-
+
switch( m_in.read_tag() )
{
#define _(x, ...) case ::MIR::RValue::TAG_##x: return ::MIR::RValue::make_##x( __VA_ARGS__ );
@@ -414,7 +414,7 @@ namespace {
::MIR::Constant deserialise_mir_constant()
{
TRACE_FUNCTION;
-
+
switch( m_in.read_tag() )
{
#define _(x, ...) case ::MIR::Constant::TAG_##x: DEBUG("- " #x); return ::MIR::Constant::make_##x( __VA_ARGS__ );
@@ -436,7 +436,7 @@ namespace {
throw "";
}
}
-
+
::HIR::TypeItem deserialise_typeitem()
{
switch( m_in.read_tag() )
@@ -479,7 +479,7 @@ namespace {
throw "";
}
}
-
+
::HIR::Linkage deserialise_linkage()
{
return ::HIR::Linkage {
@@ -487,12 +487,12 @@ namespace {
m_in.read_string(),
};
}
-
+
// - Value items
::HIR::Function deserialise_function()
{
TRACE_FUNCTION;
-
+
::HIR::Function rv {
deserialise_linkage(),
static_cast< ::HIR::Function::Receiver>( m_in.read_tag() ),
@@ -520,7 +520,7 @@ namespace {
::HIR::Constant deserialise_constant()
{
TRACE_FUNCTION;
-
+
return ::HIR::Constant {
deserialise_genericparams(),
deserialise_type(),
@@ -531,7 +531,7 @@ namespace {
::HIR::Static deserialise_static()
{
TRACE_FUNCTION;
-
+
return ::HIR::Static {
deserialise_linkage(),
m_in.read_bool(),
@@ -540,7 +540,7 @@ namespace {
deserialise_literal()
};
}
-
+
// - Type items
::HIR::TypeAlias deserialise_typealias()
{
@@ -565,14 +565,14 @@ namespace {
// TODO: auto_impls
return m;
}
-
+
::HIR::Enum deserialise_enum();
::HIR::Enum::Variant deserialise_enumvariant();
::HIR::Struct deserialise_struct();
::HIR::Union deserialise_union();
::HIR::Trait deserialise_trait();
-
+
::HIR::TraitValueItem deserialise_traitvalueitem()
{
switch( m_in.read_tag() )
@@ -600,50 +600,50 @@ namespace {
#define DEF_D(ty, ...) \
struct D< ty > { static ty des(HirDeserialiser& d) { __VA_ARGS__ } };
-
+
template<>
DEF_D( ::std::string,
return d.read_string(); );
-
+
template<typename T>
DEF_D( ::std::unique_ptr<T>,
return d.deserialise_ptr<T>(); )
-
+
template<typename T, typename U>
struct D< ::std::pair<T,U> > { static ::std::pair<T,U> des(HirDeserialiser& d) {
auto a = D<T>::des(d);
return ::std::make_pair( mv$(a), D<U>::des(d) );
}};
-
+
template<typename T>
DEF_D( ::HIR::VisEnt<T>,
return d.deserialise_visent<T>(); )
-
+
template<> DEF_D( ::HIR::TypeRef, return d.deserialise_type(); )
template<> DEF_D( ::HIR::SimplePath, return d.deserialise_simplepath(); )
template<> DEF_D( ::HIR::GenericPath, return d.deserialise_genericpath(); )
template<> DEF_D( ::HIR::TraitPath, return d.deserialise_traitpath(); )
-
+
template<> DEF_D( ::HIR::TypeParamDef, return d.deserialise_typaramdef(); )
template<> DEF_D( ::HIR::GenericBound, return d.deserialise_genericbound(); )
-
+
template<> DEF_D( ::HIR::ValueItem, return d.deserialise_valueitem(); )
template<> DEF_D( ::HIR::TypeItem, return d.deserialise_typeitem(); )
-
+
template<> DEF_D( ::HIR::Enum::Variant, return d.deserialise_enumvariant(); )
template<> DEF_D( ::HIR::Literal, return d.deserialise_literal(); )
-
+
template<> DEF_D( ::HIR::AssociatedType, return d.deserialise_associatedtype(); )
template<> DEF_D( ::HIR::TraitValueItem, return d.deserialise_traitvalueitem(); )
-
+
template<> DEF_D( ::MIR::LValue, return d.deserialise_mir_lvalue(); )
template<> DEF_D( ::MIR::Statement, return d.deserialise_mir_statement(); )
template<> DEF_D( ::MIR::BasicBlock, return d.deserialise_mir_basicblock(); )
-
+
template<> DEF_D( ::HIR::TypeImpl, return d.deserialise_typeimpl(); )
template<> DEF_D( ::MacroRulesPtr, return d.deserialise_macrorulesptr(); )
template<> DEF_D( unsigned int, return static_cast<unsigned int>(d.deserialise_count()); )
-
+
::HIR::TypeRef HirDeserialiser::deserialise_type()
{
TRACE_FUNCTION;
@@ -704,7 +704,7 @@ namespace {
throw ::std::runtime_error(FMT("Bad TypeRef tag - " << tag));
}
}
-
+
::HIR::SimplePath HirDeserialiser::deserialise_simplepath()
{
TRACE_FUNCTION;
@@ -733,7 +733,7 @@ namespace {
deserialise_pathparams()
};
}
-
+
::HIR::TraitPath HirDeserialiser::deserialise_traitpath()
{
return ::HIR::TraitPath {
@@ -770,7 +770,7 @@ namespace {
throw "";
}
}
-
+
::HIR::GenericParams HirDeserialiser::deserialise_genericparams()
{
::HIR::GenericParams params;
@@ -810,7 +810,7 @@ namespace {
throw "";
}
}
-
+
::HIR::Enum HirDeserialiser::deserialise_enum()
{
TRACE_FUNCTION;
@@ -847,7 +847,7 @@ namespace {
auto repr = static_cast< ::HIR::Union::Repr>( m_in.read_tag() );
auto variants = deserialise_vec< ::std::pair< ::std::string, ::HIR::VisEnt< ::HIR::TypeRef> > >();
auto markings = deserialise_markings();
-
+
return ::HIR::Union {
mv$(params), repr, mv$(variants), mv$(markings)
};
@@ -858,7 +858,7 @@ namespace {
auto params = deserialise_genericparams();
auto repr = static_cast< ::HIR::Struct::Repr>( m_in.read_tag() );
DEBUG("params = " << params.fmt_args() << params.fmt_bounds());
-
+
switch( m_in.read_tag() )
{
case ::HIR::Struct::Data::TAG_Unit:
@@ -889,7 +889,7 @@ namespace {
::HIR::Trait HirDeserialiser::deserialise_trait()
{
TRACE_FUNCTION;
-
+
::HIR::Trait rv {
deserialise_genericparams(),
"", // TODO: Better type for lifetime
@@ -902,7 +902,7 @@ namespace {
rv.m_type_indexes = deserialise_strumap< unsigned int>();
return rv;
}
-
+
::HIR::Literal HirDeserialiser::deserialise_literal()
{
switch( m_in.read_tag() )
@@ -923,25 +923,25 @@ namespace {
throw "";
}
}
-
+
::MIR::FunctionPointer HirDeserialiser::deserialise_mir()
{
TRACE_FUNCTION;
-
+
::MIR::Function rv;
-
+
rv.named_variables = deserialise_vec< ::HIR::TypeRef>( );
DEBUG("named_variables = " << rv.named_variables);
rv.temporaries = deserialise_vec< ::HIR::TypeRef>( );
DEBUG("temporaries = " << rv.temporaries);
rv.blocks = deserialise_vec< ::MIR::BasicBlock>( );
-
+
return ::MIR::FunctionPointer( new ::MIR::Function(mv$(rv)) );
}
::MIR::BasicBlock HirDeserialiser::deserialise_mir_basicblock()
{
TRACE_FUNCTION;
-
+
return ::MIR::BasicBlock {
deserialise_vec< ::MIR::Statement>(),
deserialise_mir_terminator()
@@ -950,7 +950,7 @@ namespace {
::MIR::Statement HirDeserialiser::deserialise_mir_statement()
{
TRACE_FUNCTION;
-
+
switch( m_in.read_tag() )
{
case 0:
@@ -971,7 +971,7 @@ namespace {
::MIR::Terminator HirDeserialiser::deserialise_mir_terminator()
{
TRACE_FUNCTION;
-
+
switch( m_in.read_tag() )
{
#define _(x, ...) case ::MIR::Terminator::TAG_##x: return ::MIR::Terminator::make_##x( __VA_ARGS__ );
@@ -1001,7 +1001,7 @@ namespace {
throw "";
}
}
-
+
::MIR::CallTarget HirDeserialiser::deserialise_mir_calltarget()
{
switch( m_in.read_tag() )
@@ -1018,27 +1018,27 @@ namespace {
throw "";
}
}
-
+
::HIR::Module HirDeserialiser::deserialise_module()
{
TRACE_FUNCTION;
-
+
::HIR::Module rv;
-
+
// m_traits doesn't need to be serialised
rv.m_value_items = deserialise_strumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::ValueItem> > >();
rv.m_mod_items = deserialise_strumap< ::std::unique_ptr< ::HIR::VisEnt< ::HIR::TypeItem> > >();
-
+
return rv;
}
::HIR::Crate HirDeserialiser::deserialise_crate()
{
::HIR::Crate rv;
-
+
rv.m_root_module = deserialise_module();
-
+
rv.m_type_impls = deserialise_vec< ::HIR::TypeImpl>();
-
+
{
size_t n = m_in.read_count();
for(size_t i = 0; i < n; i ++)
@@ -1055,10 +1055,10 @@ namespace {
rv.m_marker_impls.insert( ::std::make_pair( mv$(p), deserialise_markerimpl() ) );
}
}
-
+
rv.m_exported_macros = deserialise_strumap< ::MacroRulesPtr>();
rv.m_lang_items = deserialise_strumap< ::HIR::SimplePath>();
-
+
{
size_t n = m_in.read_count();
for(size_t i = 0; i < n; i ++)
@@ -1067,7 +1067,7 @@ namespace {
rv.m_ext_crates.insert( ::std::make_pair(ext_crate_name, ::HIR::CratePtr{}) );
}
}
-
+
return rv;
}
}
@@ -1076,11 +1076,11 @@ namespace {
{
::HIR::serialise::Reader in { filename };
HirDeserialiser s { loaded_name, in };
-
+
try
{
::HIR::Crate rv = s.deserialise_crate();
-
+
return ::HIR::CratePtr( mv$(rv) );
}
catch(int)
diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp
index 6838f40b..ea113a00 100644
--- a/src/hir/dump.cpp
+++ b/src/hir/dump.cpp
@@ -12,21 +12,21 @@
#define NODE_IS(valptr, tysuf) ( dynamic_cast<const ::HIR::ExprNode##tysuf*>(&*valptr) != nullptr )
namespace {
-
+
class TreeVisitor:
public ::HIR::Visitor,
public ::HIR::ExprVisitor
{
::std::ostream& m_os;
unsigned int m_indent_level;
-
+
public:
TreeVisitor(::std::ostream& os):
m_os(os),
m_indent_level(0)
{
}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
if( p.get_name()[0] )
@@ -34,17 +34,17 @@ namespace {
m_os << indent() << "mod " << p.get_name() << " {\n";
inc_indent();
}
-
+
// TODO: Print publicitiy.
::HIR::Visitor::visit_module(p, mod);
-
+
if( p.get_name()[0] )
{
dec_indent();
m_os << indent() << "}\n";
}
}
-
+
void visit_type_impl(::HIR::TypeImpl& impl) override
{
m_os << indent() << "impl" << impl.m_params.fmt_args() << " " << impl.m_type << "\n";
@@ -80,7 +80,7 @@ namespace {
}
m_os << indent() << "{ }\n";
}
-
+
// - Type Items
void visit_type_alias(::HIR::ItemPath p, ::HIR::TypeAlias& item) override
{
@@ -165,7 +165,7 @@ namespace {
(Unit,
),
(Value,
- m_os << " = ?";// <<
+ m_os << " = ?";// <<
),
(Tuple,
m_os << "(";
@@ -189,7 +189,7 @@ namespace {
dec_indent();
m_os << indent() << "}\n";
}
-
+
// - Value Items
void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override
{
@@ -210,7 +210,7 @@ namespace {
{
m_os << indent() << " " << item.m_params.fmt_bounds() << "\n";
}
-
+
if( item.m_code )
{
m_os << indent();
@@ -221,9 +221,9 @@ namespace {
m_os << "{\n";
inc_indent();
m_os << indent();
-
+
item.m_code->visit( *this );
-
+
m_os << "\n";
dec_indent();
m_os << indent();
@@ -255,18 +255,18 @@ namespace {
{
m_os << indent() << "const " << p.get_name() << ": " << item.m_type << " = " << item.m_value_res << ";\n";
}
-
+
// - Misc
#if 0
virtual void visit_params(::HIR::GenericParams& params);
virtual void visit_pattern(::HIR::Pattern& pat);
virtual void visit_pattern_val(::HIR::Pattern::Value& val);
virtual void visit_type(::HIR::TypeRef& tr);
-
+
enum class PathContext {
TYPE,
TRAIT,
-
+
VALUE,
};
virtual void visit_trait_path(::HIR::TraitPath& p);
@@ -276,7 +276,7 @@ namespace {
virtual void visit_expr(::HIR::ExprPtr& exp);
#endif
-
+
bool node_is_leaf(const ::HIR::ExprNode& node) {
if( NODE_IS(&node, _PathValue) )
return true;
@@ -290,7 +290,7 @@ namespace {
return true;
return false;
}
-
+
void visit(::HIR::ExprNode_Block& node) override
{
if( node.m_nodes.size() == 0 ) {
@@ -321,7 +321,7 @@ namespace {
m_os << indent() << "}";
}
}
-
+
void visit(::HIR::ExprNode_Return& node) override
{
m_os << "return";
@@ -366,7 +366,7 @@ namespace {
for(unsigned int i = 1; i < arm.m_patterns.size(); i ++ ) {
m_os << " | " << arm.m_patterns[i];
}
-
+
if( arm.m_cond ) {
m_os << " if ";
this->visit_node_ptr(arm.m_cond);
@@ -473,7 +473,7 @@ namespace {
void visit(::HIR::ExprNode_Deref& node) override
{
m_os << "*";
-
+
bool skip_parens = this->node_is_leaf(*node.m_value);
if( !skip_parens ) m_os << "(";
this->visit_node_ptr(node.m_value);
@@ -692,7 +692,7 @@ namespace {
void HIR_Dump(::std::ostream& sink, const ::HIR::Crate& crate)
{
TreeVisitor tv { sink };
-
+
tv.visit_crate( const_cast< ::HIR::Crate&>(crate) );
}
diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp
index 7921cf98..46e7d886 100644
--- a/src/hir/expr.cpp
+++ b/src/hir/expr.cpp
@@ -91,10 +91,10 @@ DEF_VISIT(ExprNode_Emplace, node,
DEF_VISIT(ExprNode_TupleVariant, node,
visit_generic_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
-
+
for(auto& ty : node.m_arg_types)
visit_type(ty);
-
+
for(auto& arg : node.m_args)
visit_node_ptr(arg);
)
@@ -102,7 +102,7 @@ DEF_VISIT(ExprNode_CallPath, node,
TRACE_FUNCTION_F("_CallPath: " << node.m_path);
for(auto& ty : node.m_cache.m_arg_types)
visit_type(ty);
-
+
visit_path(::HIR::Visitor::PathContext::VALUE, node.m_path);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
@@ -111,7 +111,7 @@ DEF_VISIT(ExprNode_CallValue, node,
TRACE_FUNCTION_F("_CallValue:");
for(auto& ty : node.m_arg_types)
visit_type(ty);
-
+
visit_node_ptr(node.m_value);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
@@ -122,7 +122,7 @@ DEF_VISIT(ExprNode_CallMethod, node,
visit_type(ty);
visit_path(::HIR::Visitor::PathContext::VALUE, node.m_method_path);
-
+
visit_node_ptr(node.m_value);
for(auto& arg : node.m_args)
visit_node_ptr(arg);
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index 5bb7f248..b8227aa0 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -46,7 +46,7 @@ public:
ValueUsage m_usage = ValueUsage::Unknown;
const Span& span() const { return m_span; }
-
+
virtual void visit(ExprVisitor& v) = 0;
ExprNode(Span sp):
m_span( mv$(sp) )
@@ -72,7 +72,7 @@ struct ExprNode_Block:
::HIR::SimplePath m_local_mod;
t_trait_list m_traits;
-
+
ExprNode_Block(Span sp):
ExprNode(mv$(sp)),
m_is_unsafe(false),
@@ -84,20 +84,20 @@ struct ExprNode_Block:
m_nodes( mv$(nodes) ),
m_yields_final(false)
{}
-
+
NODE_METHODS();
};
struct ExprNode_Return:
public ExprNode
{
::HIR::ExprNodeP m_value;
-
+
ExprNode_Return(Span sp, ::HIR::ExprNodeP value):
ExprNode(mv$(sp), ::HIR::TypeRef::new_diverge()),
m_value( mv$(value) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_Loop:
@@ -106,14 +106,14 @@ struct ExprNode_Loop:
::std::string m_label;
::HIR::ExprNodeP m_code;
bool m_diverges = false;
-
+
ExprNode_Loop(Span sp, ::std::string label, ::HIR::ExprNodeP code):
//ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()),
ExprNode(mv$(sp), ::HIR::TypeRef()),
m_label( mv$(label) ),
m_code( mv$(code) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_LoopControl:
@@ -128,7 +128,7 @@ struct ExprNode_LoopControl:
m_label( mv$(label) ),
m_continue( cont )
{}
-
+
NODE_METHODS();
};
struct ExprNode_Let:
@@ -137,14 +137,14 @@ struct ExprNode_Let:
::HIR::Pattern m_pattern;
::HIR::TypeRef m_type;
::HIR::ExprNodeP m_value;
-
+
ExprNode_Let(Span sp, ::HIR::Pattern pat, ::HIR::TypeRef ty, ::HIR::ExprNodeP val):
ExprNode(mv$(sp), ::HIR::TypeRef::new_unit()),
m_pattern( mv$(pat) ),
m_type( mv$(ty) ),
m_value( mv$(val) )
{}
-
+
NODE_METHODS();
};
@@ -157,7 +157,7 @@ struct ExprNode_Match:
::HIR::ExprNodeP m_cond;
::HIR::ExprNodeP m_code;
};
-
+
::HIR::ExprNodeP m_value;
::std::vector<Arm> m_arms;
@@ -176,14 +176,14 @@ struct ExprNode_If:
::HIR::ExprNodeP m_cond;
::HIR::ExprNodeP m_true;
::HIR::ExprNodeP m_false;
-
+
ExprNode_If(Span sp, ::HIR::ExprNodeP cond, ::HIR::ExprNodeP true_code, ::HIR::ExprNodeP false_code):
ExprNode( mv$(sp) ),
m_cond( mv$(cond) ),
m_true( mv$(true_code) ),
m_false( mv$(false_code) )
{}
-
+
NODE_METHODS();
};
@@ -206,17 +206,17 @@ struct ExprNode_Assign:
case Op::Mul: return "*";
case Op::Div: return "/";
case Op::Mod: return "%";
-
+
case Op::And: return "&";
case Op::Or: return "|";
case Op::Xor: return "^";
-
+
case Op::Shr: return ">>";
case Op::Shl: return "<<";
}
throw "";
}
-
+
Op m_op;
ExprNodeP m_slot;
ExprNodeP m_value;
@@ -227,7 +227,7 @@ struct ExprNode_Assign:
m_slot( mv$(slot) ),
m_value( mv$(value) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_BinOp:
@@ -240,7 +240,7 @@ struct ExprNode_BinOp:
CmpLtE,
CmpGt,
CmpGtE,
-
+
BoolAnd,
BoolOr,
@@ -258,20 +258,20 @@ struct ExprNode_BinOp:
case Op::CmpLtE: return "<=";
case Op::CmpGt: return ">";
case Op::CmpGtE: return ">=";
-
+
case Op::BoolAnd: return "&&";
case Op::BoolOr: return "||";
-
+
case Op::Add: return "+";
case Op::Sub: return "-";
case Op::Mul: return "*";
case Op::Div: return "/";
case Op::Mod: return "%";
-
+
case Op::And: return "&";
case Op::Or: return "|";
case Op::Xor: return "^";
-
+
case Op::Shr: return ">>";
case Op::Shl: return "<<";
}
@@ -300,7 +300,7 @@ struct ExprNode_BinOp:
break;
}
}
-
+
NODE_METHODS();
};
struct ExprNode_UniOp:
@@ -317,7 +317,7 @@ struct ExprNode_UniOp:
}
throw "";
}
-
+
Op m_op;
::HIR::ExprNodeP m_value;
@@ -326,7 +326,7 @@ struct ExprNode_UniOp:
m_op(op),
m_value( mv$(value) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_Borrow:
@@ -340,7 +340,7 @@ struct ExprNode_Borrow:
m_type(bt),
m_value( mv$(value) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_Cast:
@@ -353,7 +353,7 @@ struct ExprNode_Cast:
ExprNode( mv$(sp), mv$(dst_type) ),
m_value( mv$(value) )
{}
-
+
NODE_METHODS();
};
// Magical pointer unsizing operation:
@@ -369,7 +369,7 @@ struct ExprNode_Unsize:
ExprNode( mv$(sp), mv$(dst_type) ),
m_value( mv$(value) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_Index:
@@ -377,13 +377,13 @@ struct ExprNode_Index:
{
::HIR::ExprNodeP m_value;
::HIR::ExprNodeP m_index;
-
+
ExprNode_Index(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprNodeP index):
ExprNode(mv$(sp)),
m_value( mv$(val) ),
m_index( mv$(index) )
{}
-
+
NODE_METHODS();
};
// unary `*`
@@ -391,12 +391,12 @@ struct ExprNode_Deref:
public ExprNode
{
::HIR::ExprNodeP m_value;
-
+
ExprNode_Deref(Span sp, ::HIR::ExprNodeP val):
ExprNode(mv$(sp)),
m_value( mv$(val) )
{}
-
+
NODE_METHODS();
};
/// `box` and `in`/`<-`
@@ -409,11 +409,11 @@ struct ExprNode_Emplace:
Placer,
Boxer,
};
-
+
Type m_type;
ExprNodeP m_place;
ExprNodeP m_value;
-
+
ExprNode_Emplace(Span sp, Type ty, ::HIR::ExprNodeP place, ::HIR::ExprNodeP val):
ExprNode( mv$(sp) ),
m_type(ty),
@@ -421,7 +421,7 @@ struct ExprNode_Emplace:
m_value( mv$(val) )
{
}
-
+
NODE_METHODS();
};
@@ -432,17 +432,17 @@ struct ExprNode_TupleVariant:
::HIR::GenericPath m_path;
bool m_is_struct;
::std::vector<ExprNodeP> m_args;
-
+
// - Cache for typeck
::std::vector< ::HIR::TypeRef> m_arg_types;
-
+
ExprNode_TupleVariant(Span sp, ::HIR::GenericPath path, bool is_struct, ::std::vector< ::HIR::ExprNodeP> args):
ExprNode(mv$(sp)),
m_path( mv$(path) ),
m_is_struct( is_struct ),
m_args( mv$(args) )
{}
-
+
NODE_METHODS();
};
@@ -452,7 +452,7 @@ struct ExprCallCache
const ::HIR::GenericParams* m_fcn_params;
const ::HIR::GenericParams* m_top_params;
const ::HIR::Function* m_fcn;
-
+
::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> m_monomorph_cb;
};
@@ -461,16 +461,16 @@ struct ExprNode_CallPath:
{
::HIR::Path m_path;
::std::vector<ExprNodeP> m_args;
-
+
// - Cache for typeck
ExprCallCache m_cache;
-
+
ExprNode_CallPath(Span sp, ::HIR::Path path, ::std::vector< ::HIR::ExprNodeP> args):
ExprNode(mv$(sp)),
m_path( mv$(path) ),
m_args( mv$(args) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_CallValue:
@@ -478,13 +478,13 @@ struct ExprNode_CallValue:
{
::HIR::ExprNodeP m_value;
::std::vector<ExprNodeP> m_args;
-
+
// - Argument types used as coercion targets
::std::vector< ::HIR::TypeRef> m_arg_ivars;
-
+
// - Cache for typeck
::std::vector< ::HIR::TypeRef> m_arg_types;
-
+
// Indicates what trait should/is being used for this call
// - Determined by typeck using the present trait bound (also adds borrows etc)
// - If the called value is a closure, this stays a Unknown until closure expansion
@@ -495,13 +495,13 @@ struct ExprNode_CallValue:
FnOnce,
};
TraitUsed m_trait_used = TraitUsed::Unknown;
-
+
ExprNode_CallValue(Span sp, ::HIR::ExprNodeP val, ::std::vector< ::HIR::ExprNodeP> args):
ExprNode(mv$(sp)),
m_value( mv$(val) ),
m_args( mv$(args) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_CallMethod:
@@ -511,12 +511,12 @@ struct ExprNode_CallMethod:
::std::string m_method;
::HIR::PathParams m_params;
::std::vector< ::HIR::ExprNodeP> m_args;
-
+
// - Set during typeck to the real path to the method
::HIR::Path m_method_path;
// - Cache of argument/return types
ExprCallCache m_cache;
-
+
// - List of possible traits (in-scope traits that contain this method)
t_trait_list m_traits;
// - A pool of ivars to use for searching for trait impls
@@ -528,11 +528,11 @@ struct ExprNode_CallMethod:
m_method( mv$(method_name) ),
m_params( mv$(params) ),
m_args( mv$(args) ),
-
+
m_method_path( ::HIR::SimplePath("",{}) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_Field:
@@ -540,13 +540,13 @@ struct ExprNode_Field:
{
::HIR::ExprNodeP m_value;
::std::string m_field;
-
+
ExprNode_Field(Span sp, ::HIR::ExprNodeP val, ::std::string field):
ExprNode(mv$(sp)),
m_value( mv$(val) ),
m_field( mv$(field) )
{}
-
+
NODE_METHODS();
};
@@ -607,7 +607,7 @@ struct ExprNode_Literal:
)
)
}
-
+
NODE_METHODS();
};
struct ExprNode_UnitVariant:
@@ -616,13 +616,13 @@ struct ExprNode_UnitVariant:
// Path to variant/struct
::HIR::GenericPath m_path;
bool m_is_struct;
-
+
ExprNode_UnitVariant(Span sp, ::HIR::GenericPath path, bool is_struct):
ExprNode(mv$(sp)),
m_path( mv$(path) ),
m_is_struct( is_struct )
{}
-
+
NODE_METHODS();
};
struct ExprNode_PathValue:
@@ -638,13 +638,13 @@ struct ExprNode_PathValue:
};
::HIR::Path m_path;
Target m_target;
-
+
ExprNode_PathValue(Span sp, ::HIR::Path path, Target target):
ExprNode(mv$(sp)),
m_path( mv$(path) ),
m_target( target )
{}
-
+
NODE_METHODS();
};
struct ExprNode_Variable:
@@ -652,13 +652,13 @@ struct ExprNode_Variable:
{
::std::string m_name;
unsigned int m_slot;
-
+
ExprNode_Variable(Span sp, ::std::string name, unsigned int slot):
ExprNode(mv$(sp)),
m_name( mv$(name) ),
m_slot( slot )
{}
-
+
NODE_METHODS();
};
@@ -666,15 +666,15 @@ struct ExprNode_StructLiteral:
public ExprNode
{
typedef ::std::vector< ::std::pair< ::std::string, ExprNodeP > > t_values;
-
+
::HIR::GenericPath m_path;
bool m_is_struct;
::HIR::ExprNodeP m_base_value;
t_values m_values;
-
+
/// Monomorphised types of each field.
::std::vector< ::HIR::TypeRef> m_value_types;
-
+
ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, bool is_struct, ::HIR::ExprNodeP base_value, t_values values):
ExprNode( mv$(sp) ),
m_path( mv$(path) ),
@@ -685,7 +685,7 @@ struct ExprNode_StructLiteral:
// TODO: set m_res_type based on path?
// - Defer, because it requires binding ivars between m_path and m_res_type
}
-
+
NODE_METHODS();
};
struct ExprNode_UnionLiteral:
@@ -694,9 +694,9 @@ struct ExprNode_UnionLiteral:
::HIR::GenericPath m_path;
::std::string m_variant_name;
::HIR::ExprNodeP m_value;
-
+
unsigned int m_variant_index = ~0;
-
+
ExprNode_UnionLiteral(Span sp, ::HIR::GenericPath path, ::std::string name, ::HIR::ExprNodeP value):
ExprNode( mv$(sp) ),
m_path( mv$(path) ),
@@ -704,31 +704,31 @@ struct ExprNode_UnionLiteral:
m_value( mv$(value) )
{
}
-
+
NODE_METHODS();
};
struct ExprNode_Tuple:
public ExprNode
{
::std::vector< ::HIR::ExprNodeP> m_vals;
-
+
ExprNode_Tuple(Span sp, ::std::vector< ::HIR::ExprNodeP> vals):
ExprNode(mv$(sp)),
m_vals( mv$(vals) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_ArrayList:
public ExprNode
{
::std::vector< ::HIR::ExprNodeP> m_vals;
-
+
ExprNode_ArrayList(Span sp, ::std::vector< ::HIR::ExprNodeP> vals):
ExprNode( mv$(sp), ::HIR::TypeRef::new_array( ::HIR::TypeRef(), vals.size() ) ),
m_vals( mv$(vals) )
{}
-
+
NODE_METHODS();
};
struct ExprNode_ArraySized:
@@ -737,14 +737,14 @@ struct ExprNode_ArraySized:
::HIR::ExprNodeP m_val;
::HIR::ExprNodeP m_size; // TODO: Has to be constant
size_t m_size_val;
-
+
ExprNode_ArraySized(Span sp, ::HIR::ExprNodeP val, ::HIR::ExprNodeP size):
ExprNode(mv$(sp)),
m_val( mv$(val) ),
m_size( mv$(size) ),
m_size_val( ~0u )
{}
-
+
NODE_METHODS();
};
@@ -752,12 +752,12 @@ struct ExprNode_Closure:
public ExprNode
{
typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > args_t;
-
+
args_t m_args;
::HIR::TypeRef m_return;
::HIR::ExprNodeP m_code;
bool m_is_move = false;
-
+
enum class Class {
Unknown,
NoCapture,
@@ -765,12 +765,12 @@ struct ExprNode_Closure:
Mut,
Once,
} m_class = Class::Unknown;
-
+
// - Path to the generated closure type
::HIR::GenericPath m_obj_path_base;
::HIR::GenericPath m_obj_path;
::std::vector< ::HIR::ExprNodeP> m_captures;
-
+
ExprNode_Closure(Span sp, args_t args, ::HIR::TypeRef rv, ::HIR::ExprNodeP code, bool is_move):
ExprNode(mv$(sp)),
m_args( ::std::move(args) ),
@@ -778,7 +778,7 @@ struct ExprNode_Closure:
m_code( ::std::move(code) ),
m_is_move(is_move)
{}
-
+
NODE_METHODS();
};
@@ -790,7 +790,7 @@ public:
virtual void visit_node_ptr(::std::unique_ptr<ExprNode>& node_ptr);
virtual void visit_node(ExprNode& node);
#define NV(nt) virtual void visit(nt& n) = 0;
-
+
NV(ExprNode_Block)
NV(ExprNode_Return)
NV(ExprNode_Let)
@@ -798,7 +798,7 @@ public:
NV(ExprNode_LoopControl)
NV(ExprNode_Match)
NV(ExprNode_If)
-
+
NV(ExprNode_Assign)
NV(ExprNode_BinOp)
NV(ExprNode_UniOp)
@@ -808,7 +808,7 @@ public:
NV(ExprNode_Index)
NV(ExprNode_Deref)
NV(ExprNode_Emplace)
-
+
NV(ExprNode_TupleVariant);
NV(ExprNode_CallPath);
NV(ExprNode_CallValue);
@@ -819,13 +819,13 @@ public:
NV(ExprNode_UnitVariant);
NV(ExprNode_PathValue);
NV(ExprNode_Variable);
-
+
NV(ExprNode_StructLiteral);
NV(ExprNode_UnionLiteral);
NV(ExprNode_Tuple);
NV(ExprNode_ArrayList);
NV(ExprNode_ArraySized);
-
+
NV(ExprNode_Closure);
#undef NV
};
@@ -835,7 +835,7 @@ class ExprVisitorDef:
{
public:
#define NV(nt) virtual void visit(nt& n);
-
+
NV(ExprNode_Block)
NV(ExprNode_Return)
NV(ExprNode_Let)
@@ -843,7 +843,7 @@ public:
NV(ExprNode_LoopControl)
NV(ExprNode_Match)
NV(ExprNode_If)
-
+
NV(ExprNode_Assign)
NV(ExprNode_BinOp)
NV(ExprNode_UniOp)
@@ -853,7 +853,7 @@ public:
NV(ExprNode_Index)
NV(ExprNode_Deref)
NV(ExprNode_Emplace)
-
+
NV(ExprNode_TupleVariant);
NV(ExprNode_CallPath);
NV(ExprNode_CallValue);
@@ -864,16 +864,16 @@ public:
NV(ExprNode_UnitVariant);
NV(ExprNode_PathValue);
NV(ExprNode_Variable);
-
+
NV(ExprNode_StructLiteral);
NV(ExprNode_UnionLiteral);
NV(ExprNode_Tuple);
NV(ExprNode_ArrayList);
NV(ExprNode_ArraySized);
-
+
NV(ExprNode_Closure);
#undef NV
-
+
virtual void visit_pattern(const Span& sp, ::HIR::Pattern& pat);
virtual void visit_type(::HIR::TypeRef& ty);
virtual void visit_trait_path(::HIR::TraitPath& p);
diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp
index 21bc9e9d..5bedd1da 100644
--- a/src/hir/expr_ptr.hpp
+++ b/src/hir/expr_ptr.hpp
@@ -30,7 +30,7 @@ public:
x.ptr = nullptr;
}
~ExprPtrInner();
-
+
ExprPtrInner& operator=(ExprPtrInner&& x)
{
this->~ExprPtrInner();
@@ -38,7 +38,7 @@ public:
x.ptr = nullptr;
return *this;
}
-
+
::std::unique_ptr< ::HIR::ExprNode> into_unique();
operator bool () const { return ptr != nullptr; }
::HIR::ExprNode* get() const { return ptr; }
@@ -46,7 +46,7 @@ public:
this->~ExprPtrInner();
this->ptr = p;
}
-
+
::HIR::ExprNode& operator*() { return *ptr; }
const ::HIR::ExprNode& operator*() const { return *ptr; }
::HIR::ExprNode* operator->() { return ptr; }
@@ -56,21 +56,21 @@ public:
class ExprPtr
{
::HIR::ExprPtrInner node;
-
+
public:
::std::vector< ::HIR::TypeRef> m_bindings;
::std::vector< ::HIR::TypeRef> m_erased_types;
::MIR::FunctionPointer m_mir;
-
+
public:
ExprPtr() {}
ExprPtr(::std::unique_ptr< ::HIR::ExprNode> _);
-
+
::std::unique_ptr< ::HIR::ExprNode> into_unique();
operator bool () const { return node; }
::HIR::ExprNode* get() const { return node.get(); }
void reset(::HIR::ExprNode* p) { node.reset(p); }
-
+
::HIR::ExprNode& operator*() { return *node; }
const ::HIR::ExprNode& operator*() const { return *node; }
::HIR::ExprNode* operator->() { return &*node; }
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index c4e250a0..e3691f16 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -29,7 +29,7 @@
::HIR::GenericParams LowerHIR_GenericParams(const ::AST::GenericParams& gp, bool* self_is_sized)
{
::HIR::GenericParams rv;
-
+
if( gp.ty_params().size() > 0 )
{
for(const auto& tp : gp.ty_params())
@@ -61,9 +61,9 @@
),
(IsTrait,
auto type = LowerHIR_Type(e.type);
-
+
// TODO: Check for `Sized`
-
+
rv.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ mv$(type), LowerHIR_TraitPath(bound.span, e.trait) }));
rv.m_bounds.back().as_TraitBound().trait.m_hrls = e.hrls;
),
@@ -85,7 +85,7 @@
BUG(bound.span, "MaybeTrait on parameter not in parameter list (#" << ge.index << " " << param_name << ")");
}
}
-
+
// Compare with list of known default traits (just Sized atm) and set a marker
auto trait = LowerHIR_GenericPath(bound.span, e.trait);
if( trait.m_path == path_Sized ) {
@@ -105,7 +105,7 @@
(NotTrait,
TODO(bound.span, "Negative trait bounds");
),
-
+
(Equality,
rv.m_bounds.push_back(::HIR::GenericBound::make_TypeEquality({
LowerHIR_Type(e.type),
@@ -115,14 +115,14 @@
)
}
}
-
+
return rv;
}
::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat)
{
TRACE_FUNCTION_F("@" << pat.span().filename << ":" << pat.span().start_line << " pat = " << pat);
-
+
::HIR::PatternBinding binding;
if( pat.binding().is_valid() )
{
@@ -135,7 +135,7 @@
}
binding = ::HIR::PatternBinding(pat.binding().m_mutable, bt, pat.binding().m_name.name, pat.binding().m_slot);
}
-
+
struct H {
static ::std::vector< ::HIR::Pattern> lowerhir_patternvec(const ::std::vector< ::AST::Pattern>& sub_patterns) {
::std::vector< ::HIR::Pattern> rv;
@@ -144,7 +144,7 @@
return rv;
}
};
-
+
TU_MATCH(::AST::Pattern::Data, (pat.data()), (e),
(MaybeBind,
BUG(pat.span(), "Encountered MaybeBind pattern");
@@ -178,7 +178,7 @@
(Tuple,
auto leading = H::lowerhir_patternvec( e.start );
auto trailing = H::lowerhir_patternvec( e.end );
-
+
if( e.has_wildcard )
{
return ::HIR::Pattern {
@@ -199,7 +199,7 @@
};
}
),
-
+
(StructTuple,
unsigned int leading_count = e.tup_pat.start.size();
unsigned int trailing_count = e.tup_pat.end .size();
@@ -219,7 +219,7 @@
field_count = var.as_Tuple().size();
}
::std::vector<HIR::Pattern> sub_patterns;
-
+
if( e.tup_pat.has_wildcard ) {
sub_patterns.reserve( field_count );
if( leading_count + trailing_count > field_count ) {
@@ -238,13 +238,13 @@
}
else {
assert( trailing_count == 0 );
-
+
if( leading_count != field_count ) {
ERROR(pat.span(), E0000, "Enum variant pattern has a mismatched field count - " << field_count << " exp, got " << leading_count);
}
sub_patterns = H::lowerhir_patternvec( e.tup_pat.start );
}
-
+
return ::HIR::Pattern {
mv$(binding),
::HIR::Pattern::Data::make_EnumTuple({
@@ -268,7 +268,7 @@
field_count = pb.hir->m_data.as_Tuple().size();
}
::std::vector<HIR::Pattern> sub_patterns;
-
+
if( e.tup_pat.has_wildcard ) {
sub_patterns.reserve( field_count );
if( leading_count + trailing_count > field_count ) {
@@ -287,13 +287,13 @@
}
else {
assert( trailing_count == 0 );
-
+
if( leading_count != field_count ) {
ERROR(pat.span(), E0000, "Struct pattern has a mismatched field count - " << field_count << " exp, got " << leading_count);
}
sub_patterns = H::lowerhir_patternvec( e.tup_pat.start );
}
-
+
return ::HIR::Pattern {
mv$(binding),
::HIR::Pattern::Data::make_StructTuple({
@@ -309,8 +309,8 @@
::std::vector< ::std::pair< ::std::string, ::HIR::Pattern> > sub_patterns;
for(const auto& sp : e.sub_patterns)
sub_patterns.push_back( ::std::make_pair(sp.first, LowerHIR_Pattern(sp.second)) );
-
-
+
+
TU_MATCH_DEF(::AST::PathBinding, (e.path.binding()), (pb),
(
BUG(pat.span(), "Encountered Struct pattern not pointing to a enum variant or a struct - " << e.path);
@@ -350,7 +350,7 @@
)
)
),
-
+
(Value,
struct H {
static ::HIR::CoreType get_int_type(const Span& sp, const ::eCoreType ct) {
@@ -369,11 +369,11 @@
case CORETYPE_INT: return ::HIR::CoreType::Isize;
case CORETYPE_UINT: return ::HIR::CoreType::Usize;
-
+
case CORETYPE_CHAR: return ::HIR::CoreType::Char;
-
+
case CORETYPE_BOOL: return ::HIR::CoreType::Bool;
-
+
default:
BUG(sp, "Unknown type for integer literal in pattern - " << ct );
}
@@ -451,17 +451,17 @@
::std::vector< ::HIR::Pattern> leading;
for(const auto& sp : e.leading)
leading.push_back( LowerHIR_Pattern(sp) );
-
+
::std::vector< ::HIR::Pattern> trailing;
for(const auto& sp : e.trailing)
trailing.push_back( LowerHIR_Pattern(sp) );
-
+
auto extra_bind = e.extra_bind.is_valid()
// TODO: Share code with the outer binding code
? ::HIR::PatternBinding(false, ::HIR::PatternBinding::Type::Ref, e.extra_bind.m_name.name, e.extra_bind.m_slot)
: ::HIR::PatternBinding()
;
-
+
return ::HIR::Pattern {
mv$(binding),
::HIR::Pattern::Data::make_SplitSlice({
@@ -509,7 +509,7 @@
throw "BUG: Encountered path with parameters when creating ::HIR::GenericPath";
}
}
-
+
rv.m_components.push_back( node.name() );
}
return rv;
@@ -521,7 +521,7 @@
::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params, bool allow_assoc)
{
::HIR::PathParams params;
-
+
// TODO: Lifetime params (not encoded in ::HIR::PathNode as yet)
//for(const auto& param : src_params.m_lifetimes) {
//}
@@ -529,7 +529,7 @@
for(const auto& param : src_params.m_types) {
params.m_types.push_back( LowerHIR_Type(param) );
}
-
+
// Leave 'm_assoc' alone?
if( !allow_assoc && src_params.m_assoc.size() > 0 )
{
@@ -559,12 +559,12 @@
{},
nullptr
};
-
+
for(const auto& assoc : path.nodes().back().args().m_assoc)
{
rv.m_type_bounds.insert(::std::make_pair( assoc.first, LowerHIR_Type(assoc.second) ));
}
-
+
return rv;
}
::HIR::Path LowerHIR_Path(const Span& sp, const ::AST::Path& path)
@@ -654,7 +654,7 @@
case CORETYPE_STR : return ::HIR::TypeRef( ::HIR::CoreType::Str );
case CORETYPE_F32: return ::HIR::TypeRef( ::HIR::CoreType::F32 );
case CORETYPE_F64: return ::HIR::TypeRef( ::HIR::CoreType::F64 );
-
+
case CORETYPE_I8 : return ::HIR::TypeRef( ::HIR::CoreType::I8 );
case CORETYPE_U8 : return ::HIR::TypeRef( ::HIR::CoreType::U8 );
case CORETYPE_I16: return ::HIR::TypeRef( ::HIR::CoreType::I16 );
@@ -700,14 +700,14 @@
return ::HIR::TypeRef::new_array( mv$(inner), size_val );
}
}
-
+
return ::HIR::TypeRef::new_array( mv$(inner), LowerHIR_Expr(e.size) );
}
else {
return ::HIR::TypeRef::new_slice( mv$(inner) );
}
),
-
+
(Path,
TU_IFLET(::AST::Path::Class, e.path.m_class, Local, l,
unsigned int slot;
@@ -754,7 +754,7 @@
//if( e.hrls.size() > 0 )
// TODO(ty.span(), "ErasedType with HRLS - " << ty);
ASSERT_BUG(ty.span(), e.traits.size() > 0, "ErasedType with no traits");
-
+
::std::vector< ::HIR::TraitPath> traits;
for(const auto& t : e.traits)
{
@@ -810,7 +810,7 @@ namespace {
{
TRACE_FUNCTION_F(path);
::HIR::Struct::Data data;
-
+
TU_MATCH(::AST::StructData, (ent.m_data), (e),
(Tuple,
if( e.ents.size() == 0 ) {
@@ -818,10 +818,10 @@ namespace {
}
else {
::HIR::Struct::Data::Data_Tuple fields;
-
+
for(const auto& field : e.ents)
fields.push_back( { field.m_is_public, LowerHIR_Type(field.m_type) } );
-
+
data = ::HIR::Struct::Data::make_Tuple( mv$(fields) );
}
),
@@ -844,7 +844,7 @@ namespace {
::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& f)
{
::std::vector< ::std::pair< ::std::string, ::HIR::Enum::Variant> > variants;
-
+
for(const auto& var : f.variants())
{
TU_MATCH(::AST::EnumVariantData, (var.m_data), (e),
@@ -875,7 +875,7 @@ namespace {
)
)
}
-
+
return ::HIR::Enum {
LowerHIR_GenericParams(f.params(), nullptr),
// TODO: Get repr from attributes
@@ -886,7 +886,7 @@ namespace {
::HIR::Union LowerHIR_Union(::HIR::ItemPath path, const ::AST::Union& f, const ::AST::MetaItems& attrs)
{
auto repr = ::HIR::Union::Repr::Rust;
-
+
if( const auto* attr_repr = attrs.get("repr") )
{
const auto& repr_str = attr_repr->string();
@@ -897,11 +897,11 @@ namespace {
// TODO: Error?
}
}
-
+
::HIR::Struct::Data::Data_Named variants;
for(const auto& field : f.m_variants)
variants.push_back( ::std::make_pair( field.m_name, new_visent(field.m_is_public, LowerHIR_Type(field.m_type)) ) );
-
+
return ::HIR::Union {
LowerHIR_GenericParams(f.m_params, nullptr),
repr,
@@ -913,7 +913,7 @@ namespace {
TRACE_FUNCTION_F(trait_path);
bool trait_reqires_sized = false;
auto params = LowerHIR_GenericParams(f.params(), &trait_reqires_sized);
-
+
::std::string lifetime;
::std::vector< ::HIR::TraitPath> supertraits;
for(const auto& st : f.supertraits()) {
@@ -939,12 +939,12 @@ namespace {
}
rv.m_params.m_bounds.push_back( ::HIR::GenericBound::make_TraitBound({ ::HIR::TypeRef("Self",0xFFFF), { mv$(this_trait) } }) );
}
-
+
for(const auto& item : f.items())
{
auto trait_ip = ::HIR::ItemPath(trait_path);
auto item_path = ::HIR::ItemPath( trait_ip, item.name.c_str() );
-
+
TU_MATCH_DEF(::AST::Item, (item.data), (i),
(
BUG(item.data.span, "Encountered unexpected item type in trait");
@@ -1003,23 +1003,23 @@ namespace {
)
)
}
-
+
rv.m_is_marker = f.is_marker();
-
+
return rv;
}
::HIR::Function LowerHIR_Function(::HIR::ItemPath p, const ::AST::MetaItems& attrs, const ::AST::Function& f, const ::HIR::TypeRef& self_type)
{
static Span sp;
-
+
TRACE_FUNCTION_F(p);
-
+
::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef > > args;
for(const auto& arg : f.args())
args.push_back( ::std::make_pair( LowerHIR_Pattern(arg.first), LowerHIR_Type(arg.second) ) );
-
+
auto receiver = ::HIR::Function::Receiver::Free;
-
+
if( args.size() > 0 && args.front().first.m_binding.m_name == "self" )
{
const auto& arg_self_ty = args.front().second;
@@ -1051,15 +1051,15 @@ namespace {
)
else {
}
-
+
if( receiver == ::HIR::Function::Receiver::Free )
{
ERROR(sp, E0000, "Unknown receiver type - " << arg_self_ty);
}
}
-
+
::HIR::Linkage linkage;
-
+
// Convert #[link_name/no_mangle] attributes into the name
if( const auto* a = attrs.get("link_name") )
{
@@ -1083,13 +1083,13 @@ namespace {
{
// Leave linkage.name as empty
}
-
+
// If there's no code, demangle the name (TODO: By ABI) and set linkage.
if( linkage.name == "" && ! f.code().is_valid() )
{
linkage.name = p.get_name();
}
-
+
return ::HIR::Function {
mv$(linkage),
receiver,
@@ -1112,19 +1112,19 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
{
TRACE_FUNCTION_F("path = " << path);
::HIR::Module mod { };
-
+
mod.m_traits = mv$(traits);
-
+
// Populate trait list
for(const auto& item : ast_mod.m_type_items)
{
if( item.second.path.binding().is_Trait() ) {
auto sp = LowerHIR_SimplePath(Span(), item.second.path);
if( ::std::find(mod.m_traits.begin(), mod.m_traits.end(), sp) == mod.m_traits.end() )
- mod.m_traits.push_back( mv$(sp) );
+ mod.m_traits.push_back( mv$(sp) );
}
}
-
+
for( unsigned int i = 0; i < ast_mod.anon_mods().size(); i ++ )
{
const auto& submod_ptr = ast_mod.anon_mods()[i];
@@ -1216,7 +1216,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
)
)
}
-
+
Span mod_span;
for( const auto& ie : ast_mod.m_namespace_items )
{
@@ -1243,7 +1243,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
if( ie.second.is_import ) {
auto hir_path = LowerHIR_SimplePath( sp, ie.second.path );
::HIR::ValueItem vi;
-
+
TU_MATCH_DEF( ::AST::PathBinding, (ie.second.path.binding()), (pb),
(
DEBUG("Import VAL " << ie.first << " = " << hir_path);
@@ -1257,14 +1257,14 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
_add_mod_val_item(mod, ie.first, ie.second.is_pub, mv$(vi));
}
}
-
+
return mod;
}
void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crate)
{
DEBUG(ast_mod.path());
-
+
// Sub-modules
for( const auto& item : ast_mod.items() )
{
@@ -1278,16 +1278,16 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
LowerHIR_Module_Impls(*submod_ptr, hir_crate);
}
}
-
- //
+
+ //
for( const auto& i : ast_mod.items() )
{
if( !i.data.is_Impl() ) continue;
const auto& impl = i.data.as_Impl();
auto params = LowerHIR_GenericParams(impl.def().params(), nullptr);
-
+
TRACE_FUNCTION_F("IMPL " << impl.def());
-
+
if( impl.def().trait().ent.is_valid() )
{
const auto& pb = impl.def().trait().ent.binding();
@@ -1297,18 +1297,18 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
auto trait_path = LowerHIR_GenericPath(impl.def().trait().sp, impl.def().trait().ent);
auto trait_name = mv$(trait_path.m_path);
auto trait_args = mv$(trait_path.m_params);
-
+
if( !is_marker )
{
auto type = LowerHIR_Type(impl.def().type());
-
+
::HIR::ItemPath path(type, trait_name, trait_args);
DEBUG(path);
-
+
::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::Function> > methods;
::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::Constant> > constants;
::std::map< ::std::string, ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> > types;
-
+
for(const auto& item : impl.items())
{
::HIR::ItemPath item_path(path, item.name.c_str());
@@ -1343,17 +1343,17 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
)
)
}
-
+
hir_crate.m_trait_impls.insert( ::std::make_pair(mv$(trait_name), ::HIR::TraitImpl {
mv$(params),
mv$(trait_args),
mv$(type),
-
+
mv$(methods),
mv$(constants),
{}, // Statics
mv$(types),
-
+
LowerHIR_SimplePath(Span(), ast_mod.path())
}) );
}
@@ -1369,7 +1369,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
mv$(trait_args),
true,
mv$(type),
-
+
LowerHIR_SimplePath(Span(), ast_mod.path())
} ) );
}
@@ -1379,10 +1379,10 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
// Inherent impls
auto type = LowerHIR_Type(impl.def().type());
::HIR::ItemPath path(type);
-
+
::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> > methods;
::std::map< ::std::string, ::HIR::TypeImpl::VisImplEnt< ::HIR::Constant> > constants;
-
+
for(const auto& item : impl.items())
{
::HIR::ItemPath item_path(path, item.name.c_str());
@@ -1413,13 +1413,13 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
)
)
}
-
+
hir_crate.m_type_impls.push_back( ::HIR::TypeImpl {
mv$(params),
mv$(type),
mv$(methods),
mv$(constants),
-
+
LowerHIR_SimplePath(Span(), ast_mod.path())
} );
}
@@ -1428,19 +1428,19 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
{
if( !i.data.is_NegImpl() ) continue;
const auto& impl = i.data.as_NegImpl();
-
+
auto params = LowerHIR_GenericParams(impl.params(), nullptr);
auto type = LowerHIR_Type(impl.type());
auto trait = LowerHIR_GenericPath(impl.trait().sp, impl.trait().ent);
auto trait_name = mv$(trait.m_path);
auto trait_args = mv$(trait.m_params);
-
+
hir_crate.m_marker_impls.insert( ::std::make_pair( mv$(trait_name), ::HIR::MarkerImpl {
mv$(params),
mv$(trait_args),
false,
mv$(type),
-
+
LowerHIR_SimplePath(Span(), ast_mod.path())
} ) );
}
@@ -1456,7 +1456,7 @@ public:
IndexVisitor(const ::HIR::Crate& crate):
crate(crate)
{}
-
+
void visit_params(::HIR::GenericParams& params) override
{
for( auto& bound : params.m_bounds )
@@ -1478,7 +1478,7 @@ public:
g_crate_ptr = &rv;
g_core_crate = (crate.m_load_std == ::AST::Crate::LOAD_NONE ? "" : "core");
auto& macros = rv.m_exported_macros;
-
+
// - Extract exported macros
{
::std::vector< ::AST::Module*> mods;
@@ -1487,7 +1487,7 @@ public:
{
auto& mod = *mods.back();
mods.pop_back();
-
+
for( /*const*/ auto& mac : mod.macros() ) {
if( mac.data->m_exported ) {
auto res = macros.insert( ::std::make_pair( mac.name, mv$(mac.data) ) );
@@ -1498,13 +1498,13 @@ public:
DEBUG("- Non-exported " << mac.name << "!");
}
}
-
+
for(auto& i : mod.items()) {
if( i.data.is_Module() )
mods.push_back( &i.data.as_Module() );
}
} while( mods.size() > 0 );
-
+
for( auto& mac : crate.m_root_module.macro_imports_res() ) {
if( mac.data->m_exported && mac.name != "" ) {
auto v = ::std::make_pair( mac.name, MacroRulesPtr(new MacroRules( mv$(*const_cast<MacroRules*>(mac.data)) )) );
@@ -1521,7 +1521,7 @@ public:
}
}
}
-
+
auto sp = Span();
// - Store the lang item paths so conversion code can use them.
for( const auto& lang_item_path : crate.m_lang_items )
@@ -1544,14 +1544,14 @@ public:
rv.m_ext_crates.insert( ::std::make_pair( ext_crate.first, mv$(ext_crate.second.m_hir) ) );
}
path_Sized = rv.get_lang_item_path(sp, "sized");
-
+
rv.m_root_module = LowerHIR_Module( crate.m_root_module, ::HIR::ItemPath() );
-
+
LowerHIR_Module_Impls(crate.m_root_module, rv);
-
+
// Set all pointers in the HIR to the correct (now fixed) locations
IndexVisitor(rv).visit_crate( rv );
-
+
g_crate_ptr = nullptr;
return ::HIR::CratePtr( mv$(rv) );
}
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index 273e2b04..39b33e53 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -25,7 +25,7 @@ struct LowerHIR_ExprNode_Visitor:
public ::AST::NodeVisitor
{
::std::unique_ptr< ::HIR::ExprNode> m_rv;
-
+
virtual void visit(::AST::ExprNode_Block& v) override {
auto rv = new ::HIR::ExprNode_Block(v.span());
for(const auto& n : v.m_nodes)
@@ -34,13 +34,13 @@ struct LowerHIR_ExprNode_Visitor:
rv->m_nodes.push_back( LowerHIR_ExprNode_Inner( *n ) );
}
rv->m_yields_final = v.m_yields_final_value;
-
+
if( v.m_local_mod )
{
// TODO: Populate m_traits from the local module's import list
rv->m_local_mod = LowerHIR_SimplePath(v.span(), v.m_local_mod->path());
}
-
+
m_rv.reset( static_cast< ::HIR::ExprNode*>(rv) );
}
virtual void visit(::AST::ExprNode_Macro& v) override {
@@ -78,15 +78,15 @@ struct LowerHIR_ExprNode_Visitor:
case ::AST::ExprNode_Assign::NONE: return ::HIR::ExprNode_Assign::Op::None;
case ::AST::ExprNode_Assign::ADD: return ::HIR::ExprNode_Assign::Op::Add;
case ::AST::ExprNode_Assign::SUB: return ::HIR::ExprNode_Assign::Op::Sub;
-
+
case ::AST::ExprNode_Assign::DIV: return ::HIR::ExprNode_Assign::Op::Mul;
case ::AST::ExprNode_Assign::MUL: return ::HIR::ExprNode_Assign::Op::Div;
case ::AST::ExprNode_Assign::MOD: return ::HIR::ExprNode_Assign::Op::Mod;
-
+
case ::AST::ExprNode_Assign::AND: return ::HIR::ExprNode_Assign::Op::And;
case ::AST::ExprNode_Assign::OR : return ::HIR::ExprNode_Assign::Op::Or ;
case ::AST::ExprNode_Assign::XOR: return ::HIR::ExprNode_Assign::Op::Xor;
-
+
case ::AST::ExprNode_Assign::SHR: return ::HIR::ExprNode_Assign::Op::Shr;
case ::AST::ExprNode_Assign::SHL: return ::HIR::ExprNode_Assign::Op::Shl;
}
@@ -109,13 +109,13 @@ struct LowerHIR_ExprNode_Visitor:
auto path_RangeFrom = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeFrom"}) );
auto path_RangeTo = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeTo"}) );
auto path_RangeFull = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeFull"}) );
-
+
::HIR::ExprNode_StructLiteral::t_values values;
if( v.m_left )
values.push_back( ::std::make_pair( ::std::string("start"), LowerHIR_ExprNode_Inner( *v.m_left ) ) );
if( v.m_right )
values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) );
-
+
if( v.m_left ) {
if( v.m_right ) {
m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_Range), true, nullptr, mv$(values)) );
@@ -137,7 +137,7 @@ struct LowerHIR_ExprNode_Visitor:
// NOTE: Not language items
auto path_RangeInclusive_NonEmpty = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeInclusive", "NonEmpty"}) );
auto path_RangeToInclusive = ::HIR::GenericPath( ::HIR::SimplePath(g_core_crate, {"ops", "RangeToInclusive"}) );
-
+
if( v.m_left )
{
::HIR::ExprNode_StructLiteral::t_values values;
@@ -155,7 +155,7 @@ struct LowerHIR_ExprNode_Visitor:
case ::AST::ExprNode_BinOp::PLACE_IN:
TODO(v.get_pos(), "Desugar placement syntax");
break;
-
+
case ::AST::ExprNode_BinOp::CMPEQU : op = ::HIR::ExprNode_BinOp::Op::CmpEqu ; if(0)
case ::AST::ExprNode_BinOp::CMPNEQU: op = ::HIR::ExprNode_BinOp::Op::CmpNEqu; if(0)
case ::AST::ExprNode_BinOp::CMPLT : op = ::HIR::ExprNode_BinOp::Op::CmpLt ; if(0)
@@ -164,7 +164,7 @@ struct LowerHIR_ExprNode_Visitor:
case ::AST::ExprNode_BinOp::CMPGTE: op = ::HIR::ExprNode_BinOp::Op::CmpGtE; if(0)
case ::AST::ExprNode_BinOp::BOOLAND: op = ::HIR::ExprNode_BinOp::Op::BoolAnd; if(0)
case ::AST::ExprNode_BinOp::BOOLOR : op = ::HIR::ExprNode_BinOp::Op::BoolOr ; if(0)
-
+
case ::AST::ExprNode_BinOp::BITAND: op = ::HIR::ExprNode_BinOp::Op::And; if(0)
case ::AST::ExprNode_BinOp::BITOR : op = ::HIR::ExprNode_BinOp::Op::Or ; if(0)
case ::AST::ExprNode_BinOp::BITXOR: op = ::HIR::ExprNode_BinOp::Op::Xor; if(0)
@@ -175,7 +175,7 @@ struct LowerHIR_ExprNode_Visitor:
case ::AST::ExprNode_BinOp::SUB: op = ::HIR::ExprNode_BinOp::Op::Sub; if(0)
case ::AST::ExprNode_BinOp::SHR: op = ::HIR::ExprNode_BinOp::Op::Shr; if(0)
case ::AST::ExprNode_BinOp::SHL: op = ::HIR::ExprNode_BinOp::Op::Shl;
-
+
m_rv.reset( new ::HIR::ExprNode_BinOp( v.span(),
op,
LowerHIR_ExprNode_Inner( *v.m_left ),
@@ -201,14 +201,14 @@ struct LowerHIR_ExprNode_Visitor:
case ::AST::ExprNode_UniOp::QMARK:
BUG(v.get_pos(), "Encounterd question mark operator (should have been expanded in AST)");
break;
-
+
case ::AST::ExprNode_UniOp::REF:
m_rv.reset(new ::HIR::ExprNode_Borrow(v.span(), ::HIR::BorrowType::Shared, LowerHIR_ExprNode_Inner( *v.m_value ) ));
break;
case ::AST::ExprNode_UniOp::REFMUT:
m_rv.reset(new ::HIR::ExprNode_Borrow(v.span(), ::HIR::BorrowType::Unique, LowerHIR_ExprNode_Inner( *v.m_value ) ));
break;
-
+
case ::AST::ExprNode_UniOp::INVERT: op = ::HIR::ExprNode_UniOp::Op::Invert; if(0)
case ::AST::ExprNode_UniOp::NEGATE: op = ::HIR::ExprNode_UniOp::Op::Negate;
m_rv.reset( new ::HIR::ExprNode_UniOp( v.span(),
@@ -231,12 +231,12 @@ struct LowerHIR_ExprNode_Visitor:
LowerHIR_Type(v.m_type)
) );
}
-
+
virtual void visit(::AST::ExprNode_CallPath& v) override {
::std::vector< ::HIR::ExprNodeP> args;
for(const auto& arg : v.m_args)
args.push_back( LowerHIR_ExprNode_Inner(*arg) );
-
+
TU_IFLET(::AST::Path::Class, v.m_path.m_class, Local, e,
m_rv.reset( new ::HIR::ExprNode_CallValue( v.span(),
::HIR::ExprNodeP(new ::HIR::ExprNode_Variable( v.span(), e.name, v.m_path.binding().as_Variable().slot )),
@@ -274,12 +274,12 @@ struct LowerHIR_ExprNode_Visitor:
::std::vector< ::HIR::ExprNodeP> args;
for(const auto& arg : v.m_args)
args.push_back( LowerHIR_ExprNode_Inner(*arg) );
-
+
// TODO: Should this be abstracted?
::HIR::PathParams params;
for(const auto& param : v.m_method.args().m_types)
params.m_types.push_back( LowerHIR_Type(param) );
-
+
m_rv.reset( new ::HIR::ExprNode_CallMethod( v.span(),
LowerHIR_ExprNode_Inner(*v.m_val),
v.m_method.name(),
@@ -291,7 +291,7 @@ struct LowerHIR_ExprNode_Visitor:
::std::vector< ::HIR::ExprNodeP> args;
for(const auto& arg : v.m_args)
args.push_back( LowerHIR_ExprNode_Inner(*arg) );
-
+
m_rv.reset( new ::HIR::ExprNode_CallValue( v.span(),
LowerHIR_ExprNode_Inner(*v.m_val),
mv$(args)
@@ -315,7 +315,7 @@ struct LowerHIR_ExprNode_Visitor:
::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl(v.span(), v.m_label, false) )
)) );
code.push_back( LowerHIR_ExprNode_Inner(*v.m_code) );
-
+
m_rv.reset( new ::HIR::ExprNode_Loop( v.span(),
v.m_label,
::HIR::ExprNodeP(new ::HIR::ExprNode_Block( v.span(), false, mv$(code)))
@@ -323,7 +323,7 @@ struct LowerHIR_ExprNode_Visitor:
break; }
case ::AST::ExprNode_Loop::WHILELET: {
::std::vector< ::HIR::ExprNode_Match::Arm> arms;
-
+
// - Matches pattern - Run inner code
arms.push_back(::HIR::ExprNode_Match::Arm {
::make_vec1( LowerHIR_Pattern(v.m_pattern) ),
@@ -336,7 +336,7 @@ struct LowerHIR_ExprNode_Visitor:
::HIR::ExprNodeP(),
::HIR::ExprNodeP( new ::HIR::ExprNode_LoopControl( v.span(), v.m_label, false) )
});
-
+
m_rv.reset( new ::HIR::ExprNode_Loop( v.span(),
v.m_label,
::HIR::ExprNodeP(new ::HIR::ExprNode_Match( v.span(),
@@ -350,7 +350,7 @@ struct LowerHIR_ExprNode_Visitor:
BUG(v.get_pos(), "Encountered still-sugared for loop");
break;
}
-
+
// TODO: Iterate the constructed loop and determine if there are any `break` statements pointing to it
{
struct LoopVisitor:
@@ -359,13 +359,13 @@ struct LowerHIR_ExprNode_Visitor:
const ::std::string& top_label;
bool top_is_broken;
::std::vector< const ::std::string*> name_stack;
-
+
LoopVisitor(const ::std::string& top_label):
top_label(top_label),
top_is_broken(false),
name_stack()
{}
-
+
void visit(::HIR::ExprNode_Loop& node) override {
if( node.m_label != "" ) {
this->name_stack.push_back( &node.m_label );
@@ -377,7 +377,7 @@ struct LowerHIR_ExprNode_Visitor:
}
void visit(::HIR::ExprNode_LoopControl& node) override {
::HIR::ExprVisitorDef::visit(node);
-
+
if( node.m_continue ) {
}
else {
@@ -395,7 +395,7 @@ struct LowerHIR_ExprNode_Visitor:
}
}
};
-
+
auto& loop_node = dynamic_cast< ::HIR::ExprNode_Loop&>(*m_rv);;
LoopVisitor lv { loop_node.m_label };
loop_node.m_code->visit(lv);
@@ -407,7 +407,7 @@ struct LowerHIR_ExprNode_Visitor:
}
virtual void visit(::AST::ExprNode_Match& v) override {
::std::vector< ::HIR::ExprNode_Match::Arm> arms;
-
+
for(const auto& arm : v.m_arms)
{
::HIR::ExprNode_Match::Arm new_arm {
@@ -415,13 +415,13 @@ struct LowerHIR_ExprNode_Visitor:
LowerHIR_ExprNode_Inner_Opt(arm.m_cond.get()),
LowerHIR_ExprNode_Inner(*arm.m_code)
};
-
+
for(const auto& pat : arm.m_patterns)
new_arm.m_patterns.push_back( LowerHIR_Pattern(pat) );
-
+
arms.push_back( mv$(new_arm) );
}
-
+
m_rv.reset( new ::HIR::ExprNode_Match( v.span(),
LowerHIR_ExprNode_Inner(*v.m_val),
mv$(arms)
@@ -436,7 +436,7 @@ struct LowerHIR_ExprNode_Visitor:
}
virtual void visit(::AST::ExprNode_IfLet& v) override {
::std::vector< ::HIR::ExprNode_Match::Arm> arms;
-
+
// - Matches pattern - Take true branch
arms.push_back(::HIR::ExprNode_Match::Arm {
::make_vec1( LowerHIR_Pattern(v.m_pattern) ),
@@ -454,7 +454,7 @@ struct LowerHIR_ExprNode_Visitor:
mv$(arms)
));
}
-
+
virtual void visit(::AST::ExprNode_Integer& v) override {
struct H {
static ::HIR::CoreType get_type(Span sp, ::eCoreType ct) {
@@ -473,9 +473,9 @@ struct LowerHIR_ExprNode_Visitor:
case CORETYPE_INT: return ::HIR::CoreType::Isize;
case CORETYPE_UINT: return ::HIR::CoreType::Usize;
-
+
case CORETYPE_CHAR: return ::HIR::CoreType::Char;
-
+
default:
BUG(sp, "Unknown type for integer literal - " << coretype_name(ct));
}
@@ -544,7 +544,7 @@ struct LowerHIR_ExprNode_Visitor:
ERROR(v.span(), E0000, "Union constructors can only specify a single field");
if( v.m_base_value )
ERROR(v.span(), E0000, "Union constructors can't take a base value");
-
+
m_rv.reset( new ::HIR::ExprNode_UnionLiteral( v.span(),
LowerHIR_GenericPath(v.get_pos(), v.m_path),
v.m_values[0].first,
@@ -645,7 +645,7 @@ struct LowerHIR_ExprNode_Visitor:
const auto& enm = *e.enum_;
auto it = ::std::find_if(enm.variants().begin(), enm.variants().end(), [&](const auto& x){ return x.m_name == var_name; });
assert(it != enm.variants().end());
-
+
var_idx = static_cast<unsigned int>(it - enm.variants().begin());
if( it->m_data.is_Struct() ) {
ERROR(v.span(), E0000, "Named value referring to an enum that isn't tuple-like or unit-like - " << v.m_path);
@@ -657,7 +657,7 @@ struct LowerHIR_ExprNode_Visitor:
const auto& enm = *e.hir;
auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
assert(it != enm.m_variants.end());
-
+
var_idx = static_cast<unsigned int>(it - enm.m_variants.begin());
if( it->second.is_Struct() ) {
ERROR(v.span(), E0000, "Named value referring to an enum that isn't tuple-like or unit-like - " << v.m_path);
@@ -698,7 +698,7 @@ struct LowerHIR_ExprNode_Visitor:
)
}
}
-
+
virtual void visit(::AST::ExprNode_Field& v) override {
m_rv.reset( new ::HIR::ExprNode_Field( v.span(),
LowerHIR_ExprNode_Inner(*v.m_obj),
@@ -721,9 +721,9 @@ struct LowerHIR_ExprNode_Visitor:
::std::unique_ptr< ::HIR::ExprNode> LowerHIR_ExprNode_Inner(const ::AST::ExprNode& e)
{
LowerHIR_ExprNode_Visitor v;
-
+
const_cast<::AST::ExprNode*>(&e)->visit( v );
-
+
if( ! v.m_rv ) {
BUG(e.get_pos(), typeid(e).name() << " - Yielded a nullptr HIR node");
}
diff --git a/src/hir/generic_params.cpp b/src/hir/generic_params.cpp
index 54290731..984d8a3a 100644
--- a/src/hir/generic_params.cpp
+++ b/src/hir/generic_params.cpp
@@ -21,7 +21,7 @@ namespace HIR {
)
return os;
}
-
+
::std::ostream& operator<<(::std::ostream& os, const ::HIR::GenericParams::PrintArgs& x)
{
if( x.gp.m_lifetimes.size() > 0 || x.gp.m_types.size() > 0 )
diff --git a/src/hir/generic_params.hpp b/src/hir/generic_params.hpp
index 79ce2cb9..8753ae7e 100644
--- a/src/hir/generic_params.hpp
+++ b/src/hir/generic_params.hpp
@@ -44,13 +44,13 @@ class GenericParams
public:
::std::vector<TypeParamDef> m_types;
::std::vector< ::std::string> m_lifetimes;
-
+
::std::vector<GenericBound> m_bounds;
-
+
//GenericParams() {}
-
+
GenericParams clone() const;
-
+
struct PrintArgs {
const GenericParams& gp;
PrintArgs(const GenericParams& gp): gp(gp) {}
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index 0ae4a786..2ec4d40b 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -45,7 +45,7 @@ namespace HIR {
)
return os;
}
-
+
bool operator==(const Literal& l, const Literal& r)
{
if( l.tag() != r.tag() )
@@ -96,7 +96,7 @@ const ::HIR::Enum::Variant* ::HIR::Enum::get_variant(const ::std::string& name)
namespace {
bool matches_genericpath(const ::HIR::GenericParams& params, const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic);
-
+
bool matches_type_int(const ::HIR::GenericParams& params, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right_in, ::HIR::t_cb_resolve_type ty_res, bool expand_generic)
{
assert(! left.m_data.is_Infer() );
@@ -105,9 +105,9 @@ namespace {
expand_generic = false;
//DEBUG("left = " << left << ", right = " << right);
-
+
// TODO: What indicates what out of ty_res?
-
+
if( right.m_data.is_Infer() ) {
//DEBUG("left = " << left << ", right = " << right);
switch(right.m_data.as_Infer().ty_class)
@@ -135,7 +135,7 @@ namespace {
}
throw "";
}
-
+
// A local generic could match anything, leave that up to the caller
if( left.m_data.is_Generic() ) {
return true;
@@ -150,7 +150,7 @@ namespace {
if( right.m_data.is_Generic() ) {
return left.m_data.is_Generic();
}
-
+
if( left.m_data.tag() != right.m_data.tag() ) {
return false;
}
@@ -247,7 +247,7 @@ namespace {
if( left.m_path.m_components[i] != right.m_path.m_components[i] )
return false;
}
-
+
if( left.m_params.m_types.size() > 0 || right.m_params.m_types.size() > 0 ) {
if( left.m_params.m_types.size() != right.m_params.m_types.size() ) {
return true;
@@ -316,11 +316,11 @@ bool ::HIR::MarkerImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_res
namespace {
::Ordering typelist_ord_specific(const Span& sp, const ::std::vector<::HIR::TypeRef>& left, const ::std::vector<::HIR::TypeRef>& right);
-
+
::Ordering type_ord_specific(const Span& sp, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right)
{
// TODO: What happens if you get `impl<T> Foo<T> for T` vs `impl<T,U> Foo<U> for T`
-
+
// A generic can't be more specific than any other type we can see
// - It's equally as specific as another Generic, so still false
if( left.m_data.is_Generic() ) {
@@ -330,7 +330,7 @@ namespace {
if( right.m_data.is_Generic() ) {
return ::OrdGreater;
}
-
+
TU_MATCH(::HIR::TypeRef::Data, (left.m_data), (le),
(Generic,
throw "";
@@ -436,7 +436,7 @@ namespace {
)
throw "Fell off end of type_ord_specific";
}
-
+
::Ordering typelist_ord_specific(const Span& sp, const ::std::vector<::HIR::TypeRef>& le, const ::std::vector<::HIR::TypeRef>& re)
{
auto rv = ::OrdEqual;
@@ -459,7 +459,7 @@ namespace {
assert( cur_trait.m_trait_ptr );
const auto& tr = *cur_trait.m_trait_ptr;
auto monomorph_cb = monomorphise_type_get_cb(sp, &type, &cur_trait.m_path.m_params, nullptr);
-
+
for(const auto& trait_path_raw : tr.m_parent_traits)
{
// 1. Monomorph
@@ -469,7 +469,7 @@ namespace {
// 3. Add
rv.push_back( ::HIR::GenericBound::make_TraitBound({ type.clone(), mv$(trait_path_mono) }) );
}
-
+
// TODO: Add traits from `Self: Foo` bounds?
}
::std::vector< ::HIR::GenericBound> flatten_bounds(const ::std::vector<::HIR::GenericBound>& bounds)
@@ -501,7 +501,7 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const
{
static const Span _sp;
const Span& sp = _sp;
-
+
// >> https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md#defining-the-precedence-rules
// 1. If this->m_type is less specific than other.m_type: return false
if( type_ord_specific(sp, this->m_type, other.m_type) == ::OrdLess ) {
@@ -511,9 +511,9 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const
if( typelist_ord_specific(sp, this->m_trait_args.m_types, other.m_trait_args.m_types) == ::OrdLess ) {
return false;
}
-
+
//assert(m_params.m_types.size() == other.m_params.m_types.size());
-
+
if( other.m_params.m_bounds.size() == 0 ) {
return m_params.m_bounds.size() > 0;
}
@@ -523,13 +523,13 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const
auto bounds_o = flatten_bounds(other.m_params.m_bounds);
::std::sort(bounds_t.begin(), bounds_t.end(), [](const auto& a, const auto& b){ return ::ord(a,b) == OrdLess; });
::std::sort(bounds_o.begin(), bounds_o.end(), [](const auto& a, const auto& b){ return ::ord(a,b) == OrdLess; });
-
+
DEBUG("bounds_t = " << bounds_t);
DEBUG("bounds_o = " << bounds_o);
-
+
if( bounds_t.size() < bounds_o.size() )
return false;
-
+
auto it_t = bounds_t.begin();
for(auto it_o = bounds_o.begin(); it_o != bounds_o.end(); ++it_o)
{
@@ -569,7 +569,7 @@ const ::HIR::SimplePath& ::HIR::Crate::get_lang_item_path_opt(const char* name)
const ::HIR::TypeItem& ::HIR::Crate::get_typeitem_by_path(const Span& sp, const ::HIR::SimplePath& path, bool ignore_crate_name) const
{
ASSERT_BUG(sp, path.m_components.size() > 0, "get_typeitem_by_path received invalid path - " << path);
-
+
const ::HIR::Module* mod;
if( !ignore_crate_name && path.m_crate_name != "" ) {
ASSERT_BUG(sp, m_ext_crates.count(path.m_crate_name) > 0, "Crate '" << path.m_crate_name << "' not loaded");
@@ -596,14 +596,14 @@ const ::HIR::TypeItem& ::HIR::Crate::get_typeitem_by_path(const Span& sp, const
if( it == mod->m_mod_items.end() ) {
BUG(sp, "Could not find type name in " << path);
}
-
+
return it->second->ent;
}
const ::HIR::Module& ::HIR::Crate::get_mod_by_path(const Span& sp, const ::HIR::SimplePath& path) const
{
if( path.m_components.size() == 0 )
- {
+ {
if( path.m_crate_name != "" )
{
ASSERT_BUG(sp, m_ext_crates.count(path.m_crate_name) > 0, "Crate '" << path.m_crate_name << "' not loaded");
@@ -622,7 +622,7 @@ const ::HIR::Module& ::HIR::Crate::get_mod_by_path(const Span& sp, const ::HIR::
)
else {
BUG(sp, "Module path " << path << " didn't point to a module");
- }
+ }
}
}
const ::HIR::Trait& ::HIR::Crate::get_trait_by_path(const Span& sp, const ::HIR::SimplePath& path) const
@@ -697,7 +697,7 @@ const ::HIR::ValueItem& ::HIR::Crate::get_valitem_by_path(const Span& sp, const
if( it == mod->m_value_items.end() ) {
BUG(sp, "Could not find value name " << path);
}
-
+
return it->second->ent;
}
const ::HIR::Function& ::HIR::Crate::get_function_by_path(const Span& sp, const ::HIR::SimplePath& path) const
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 5f1f55f0..2f8c39bb 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -78,10 +78,10 @@ struct Linkage
Weak, // Weak linkage (multiple definitions are allowed
External, // Force the symbol to be externally visible
};
-
+
// Linkage type
Type type = Type::Auto;
-
+
// External symbol name
::std::string name;
};
@@ -92,16 +92,16 @@ public:
Linkage m_linkage;
bool m_is_mut;
TypeRef m_type;
-
+
ExprPtr m_value;
-
+
Literal m_value_res;
};
struct Constant
{
// NOTE: The generics can't influence the value of this `const`
GenericParams m_params;
-
+
TypeRef m_type;
ExprPtr m_value;
Literal m_value_res;
@@ -119,24 +119,24 @@ public:
//PointerConst,
Box,
};
-
+
typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > args_t;
-
+
Linkage m_linkage;
-
+
Receiver m_receiver;
::std::string m_abi;
bool m_unsafe;
bool m_const;
-
+
GenericParams m_params;
-
+
args_t m_args;
bool m_variadic;
TypeRef m_return;
-
+
ExprPtr m_code;
-
+
//::HIR::TypeRef make_ty(const Span& sp, const ::HIR::PathParams& params) const;
};
@@ -157,17 +157,17 @@ struct TraitMarkings
{
/// There is at least one Unsize impl for this type
bool can_unsize = false;
-
+
/// Indicates that there is at least one Deref impl
bool has_a_deref = false;
-
+
/// Indicates that there is a Drop impl
/// - If there is an impl, there must be an applicable impl to every instance.
bool has_drop_impl = false;
-
+
// If populated, indicates the field that is the coercable pointer.
unsigned int coerce_unsized_index = ~0u;
-
+
// TODO: This would have to be changed for custom DSTs
enum class DstType {
None, // Sized
@@ -176,7 +176,7 @@ struct TraitMarkings
TraitObject, // (Trait)
} dst_type;
unsigned int unsized_field = ~0u;
-
+
/// `true` if there is a Copy impl
bool is_copy = false;
@@ -186,7 +186,7 @@ struct TraitMarkings
// Implementation state
bool is_impled;
};
-
+
// General auto trait impls
mutable ::std::map< ::HIR::SimplePath, AutoMarking> auto_impls;
};
@@ -209,13 +209,13 @@ public:
C,
U8, U16, U32,
};
-
+
GenericParams m_params;
Repr m_repr;
::std::vector< ::std::pair< ::std::string, Variant > > m_variants;
-
+
TraitMarkings m_markings;
-
+
const Variant* get_variant(const ::std::string& ) const;
};
class Struct
@@ -233,11 +233,11 @@ public:
(Tuple, t_tuple_fields),
(Named, t_struct_fields)
);
-
+
GenericParams m_params;
Repr m_repr;
Data m_data;
-
+
TraitMarkings m_markings;
};
class Union
@@ -248,11 +248,11 @@ public:
Rust,
C,
};
-
+
GenericParams m_params;
Repr m_repr;
t_struct_fields m_variants;
-
+
TraitMarkings m_markings;
};
@@ -273,17 +273,17 @@ struct Trait
GenericParams m_params;
::std::string m_lifetime;
::std::vector< ::HIR::TraitPath > m_parent_traits;
-
+
bool m_is_marker; // aka OIBIT
-
+
::std::unordered_map< ::std::string, AssociatedType > m_types;
::std::unordered_map< ::std::string, TraitValueItem > m_values;
-
+
// Indexes into the vtable for each present method and value
::std::unordered_multimap< ::std::string, ::std::pair<unsigned int,::HIR::GenericPath> > m_value_indexes;
// Indexes in the vtable parameter list for each associated type
::std::unordered_map< ::std::string, unsigned int > m_type_indexes;
-
+
Trait( GenericParams gps, ::std::string lifetime, ::std::vector< ::HIR::TraitPath> parents):
m_params( mv$(gps) ),
m_lifetime( mv$(lifetime) ),
@@ -297,12 +297,12 @@ class Module
public:
// List of in-scope traits in this module
::std::vector< ::HIR::SimplePath> m_traits;
-
+
// Contains all values and functions (including type constructors)
::std::unordered_map< ::std::string, ::std::unique_ptr<VisEnt<ValueItem>> > m_value_items;
// Contains types, traits, and modules
::std::unordered_map< ::std::string, ::std::unique_ptr<VisEnt<TypeItem>> > m_mod_items;
-
+
Module() {}
Module(const Module&) = delete;
Module(Module&& x) = default;
@@ -344,12 +344,12 @@ public:
::HIR::GenericParams m_params;
::HIR::TypeRef m_type;
-
+
::std::map< ::std::string, VisImplEnt< ::HIR::Function> > m_methods;
::std::map< ::std::string, VisImplEnt< ::HIR::Constant> > m_constants;
::HIR::SimplePath m_src_module;
-
+
bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
@@ -368,20 +368,20 @@ public:
::HIR::GenericParams m_params;
::HIR::PathParams m_trait_args;
::HIR::TypeRef m_type;
-
+
::std::map< ::std::string, ImplEnt< ::HIR::Function> > m_methods;
::std::map< ::std::string, ImplEnt< ::HIR::Constant> > m_constants;
::std::map< ::std::string, ImplEnt< ::HIR::Static> > m_statics;
-
+
::std::map< ::std::string, ImplEnt< ::HIR::TypeRef> > m_types;
-
+
::HIR::SimplePath m_src_module;
-
+
bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
}
-
+
bool more_specific_than(const TraitImpl& x) const;
};
@@ -392,9 +392,9 @@ public:
::HIR::PathParams m_trait_args;
bool is_positive;
::HIR::TypeRef m_type;
-
+
::HIR::SimplePath m_src_module;
-
+
bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const;
bool matches_type(const ::HIR::TypeRef& tr) const {
return matches_type(tr, [](const auto& x)->const auto&{ return x; });
@@ -405,35 +405,35 @@ class Crate
{
public:
Module m_root_module;
-
+
/// Impl blocks on just a type
::std::vector< ::HIR::TypeImpl > m_type_impls;
/// Impl blocks
::std::multimap< ::HIR::SimplePath, ::HIR::TraitImpl > m_trait_impls;
::std::multimap< ::HIR::SimplePath, ::HIR::MarkerImpl > m_marker_impls;
-
+
/// Macros exported by this crate
::std::unordered_map< ::std::string, ::MacroRulesPtr > m_exported_macros;
-
+
/// Language items avaliable through this crate (includes ones from loaded externs)
::std::unordered_map< ::std::string, ::HIR::SimplePath> m_lang_items;
-
+
::std::unordered_map< ::std::string, ::HIR::CratePtr> m_ext_crates;
-
+
/// Method called to populate runtime state after deserialisation
/// See hir/crate_post_load.cpp
void post_load_update(const ::std::string& loaded_name);
-
+
const ::HIR::SimplePath& get_lang_item_path(const Span& sp, const char* name) const;
const ::HIR::SimplePath& get_lang_item_path_opt(const char* name) const;
-
+
const ::HIR::TypeItem& get_typeitem_by_path(const Span& sp, const ::HIR::SimplePath& path, bool ignore_crate_name=false) const;
const ::HIR::Trait& get_trait_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Struct& get_struct_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Union& get_union_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Enum& get_enum_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Module& get_mod_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
-
+
const ::HIR::ValueItem& get_valitem_by_path(const Span& sp, const ::HIR::SimplePath& path, bool ignore_crate_name=false) const;
const ::HIR::Function& get_function_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Static& get_static_by_path(const Span& sp, const ::HIR::SimplePath& path) const {
@@ -454,7 +454,7 @@ public:
BUG(sp, "`const` path " << path << " didn't point to an enum");
}
}
-
+
bool find_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const;
bool find_auto_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::MarkerImpl&)> callback) const;
bool find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const;
diff --git a/src/hir/item_path.hpp b/src/hir/item_path.hpp
index 8ed140af..606c6817 100644
--- a/src/hir/item_path.hpp
+++ b/src/hir/item_path.hpp
@@ -17,7 +17,7 @@ public:
const ::HIR::SimplePath* trait = nullptr;
const ::HIR::PathParams* trait_params = nullptr;
const char* name = nullptr;
-
+
ItemPath() {}
ItemPath(const ItemPath& p, const char* n):
parent(&p),
@@ -34,10 +34,10 @@ public:
ItemPath(const ::HIR::SimplePath& path):
trait(&path)
{}
-
+
const ::HIR::SimplePath* trait_path() const { return trait; }
const ::HIR::PathParams* trait_args() const { return trait_params; }
-
+
::HIR::SimplePath get_simple_path() const {
if( parent ) {
assert(name);
@@ -51,7 +51,7 @@ public:
::HIR::Path get_full_path() const {
assert(parent);
assert(name);
-
+
if( parent->name ) {
return get_simple_path();
}
@@ -65,14 +65,14 @@ public:
const char* get_name() const {
return name ? name : "";
}
-
+
ItemPath operator+(const ::std::string& name) const {
return ItemPath(*this, name.c_str());
}
-
+
bool operator==(const ::HIR::SimplePath& sp) const {
if( sp.m_crate_name != "" ) return false;
-
+
unsigned int i = sp.m_components.size();
const auto* n = this;
while( n && i -- )
@@ -87,7 +87,7 @@ public:
return false;
return true;
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const ItemPath& x) {
if( x.parent ) {
os << *x.parent;
diff --git a/src/hir/path.cpp b/src/hir/path.cpp
index 73d1b92f..e6dab41f 100644
--- a/src/hir/path.cpp
+++ b/src/hir/path.cpp
@@ -12,9 +12,9 @@
{
::HIR::SimplePath ret(m_crate_name);
ret.m_components = m_components;
-
+
ret.m_components.push_back( s );
-
+
return ret;
}
namespace HIR {
@@ -38,7 +38,7 @@ namespace HIR {
::std::ostream& operator<<(::std::ostream& os, const PathParams& x)
{
bool has_args = ( x.m_types.size() > 0 );
-
+
if(has_args) {
os << "<";
}
@@ -65,7 +65,7 @@ namespace HIR {
}
os << x.m_path.m_path;
bool has_args = ( x.m_path.m_params.m_types.size() > 0 || x.m_type_bounds.size() > 0 );
-
+
if(has_args) {
os << "<";
}
@@ -160,10 +160,10 @@ bool ::HIR::GenericPath::operator==(const GenericPath& x) const
{},
m_trait_ptr
};
-
+
for( const auto& assoc : m_type_bounds )
rv.m_type_bounds.insert(::std::make_pair( assoc.first, assoc.second.clone() ));
-
+
return rv;
}
bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
@@ -172,10 +172,10 @@ bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
return false;
if( m_hrls != x.m_hrls )
return false;
-
+
if( m_type_bounds.size() != x.m_type_bounds.size() )
return false;
-
+
for(auto it_l = m_type_bounds.begin(), it_r = x.m_type_bounds.begin(); it_l != m_type_bounds.end(); it_l++, it_r++ ) {
if( it_l->first != it_r->first )
return false;
@@ -237,7 +237,7 @@ bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
::HIR::Compare HIR::PathParams::compare_with_placeholders(const Span& sp, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder) const
{
using ::HIR::Compare;
-
+
auto rv = Compare::Equal;
if( this->m_types.size() > 0 || x.m_types.size() > 0 ) {
if( this->m_types.size() != x.m_types.size() ) {
@@ -283,7 +283,7 @@ bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
if( this->m_path.m_components[i] != x.m_path.m_components[i] )
return Compare::Unequal;
}
-
+
return this->m_params. compare_with_placeholders(sp, x.m_params, resolve_placeholder);
}
@@ -319,9 +319,9 @@ namespace {
auto rv = m_path .compare_with_placeholders(sp, x.m_path, resolve_placeholder);
if( rv == Compare::Unequal )
return rv;
-
+
// TODO: HRLs
-
+
auto it_l = m_type_bounds.begin();
auto it_r = x.m_type_bounds.begin();
while( it_l != m_type_bounds.end() && it_r != x.m_type_bounds.end() )
@@ -333,12 +333,12 @@ namespace {
++ it_l;
++ it_r;
}
-
+
if( it_l != m_type_bounds.end() || it_r != x.m_type_bounds.end() )
{
return Compare::Unequal;
}
-
+
return rv;
}
@@ -353,7 +353,7 @@ namespace {
(UfcsUnknown,
if( ple.item != pre.item)
return Compare::Unequal;
-
+
TODO(sp, "Path::compare_with_placeholders - UfcsUnknown");
),
(UfcsInherent,
@@ -367,7 +367,7 @@ namespace {
(UfcsKnown,
if( ple.item != pre.item)
return Compare::Unequal;
-
+
::HIR::Compare rv = ::HIR::Compare::Equal;
CMP(rv, ple.type->compare_with_placeholders(sp, *pre.type, resolve_placeholder));
CMP(rv, ::compare_with_placeholders(sp, ple.trait, pre.trait, resolve_placeholder));
diff --git a/src/hir/path.hpp b/src/hir/path.hpp
index e6b4e381..80fb4caa 100644
--- a/src/hir/path.hpp
+++ b/src/hir/path.hpp
@@ -72,7 +72,7 @@ struct SimplePath
}
SimplePath clone() const;
-
+
SimplePath operator+(const ::std::string& s) const;
bool operator==(const SimplePath& x) const {
return m_crate_name == x.m_crate_name && m_components == x.m_components;
@@ -98,7 +98,7 @@ struct SimplePath
struct PathParams
{
::std::vector<TypeRef> m_types;
-
+
PathParams();
PathParams(::HIR::TypeRef );
PathParams clone() const;
@@ -106,10 +106,10 @@ struct PathParams
PathParams& operator=(const PathParams&) = delete;
PathParams(PathParams&&) = default;
PathParams& operator=(PathParams&&) = default;
-
+
Compare compare_with_placeholders(const Span& sp, const PathParams& x, t_cb_resolve_type resolve_placeholder) const;
Compare match_test_generics_fuzz(const Span& sp, const PathParams& x, t_cb_resolve_type resolve_placeholder, t_cb_match_generics) const;
-
+
bool operator==(const PathParams& x) const;
bool operator!=(const PathParams& x) const { return !(*this == x); }
bool operator<(const PathParams& x) const { return ord(x) == OrdLess; }
@@ -130,14 +130,14 @@ public:
GenericPath();
GenericPath(::HIR::SimplePath sp);
GenericPath(::HIR::SimplePath sp, ::HIR::PathParams params);
-
+
GenericPath clone() const;
Compare compare_with_placeholders(const Span& sp, const GenericPath& x, t_cb_resolve_type resolve_placeholder) const;
-
+
bool operator==(const GenericPath& x) const;
bool operator!=(const GenericPath& x) const { return !(*this == x); }
bool operator<(const GenericPath& x) const { return ord(x) == OrdLess; }
-
+
Ordering ord(const GenericPath& x) const {
auto rv = ::ord(m_path, x.m_path);
if(rv != OrdEqual) return rv;
@@ -154,21 +154,21 @@ public:
::std::vector< ::std::string> m_hrls;
// TODO: Each bound should list its origin trait
::std::map< ::std::string, ::HIR::TypeRef> m_type_bounds;
-
+
const ::HIR::Trait* m_trait_ptr;
-
+
TraitPath clone() const;
Compare compare_with_placeholders(const Span& sp, const TraitPath& x, t_cb_resolve_type resolve_placeholder) const;
-
+
bool operator==(const TraitPath& x) const;
bool operator!=(const TraitPath& x) const { return !(*this == x); }
-
+
Ordering ord(const TraitPath& x) const {
ORD(m_path, x.m_path);
ORD(m_hrls, x.m_hrls);
return ::ord(m_type_bounds, x.m_type_bounds);
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const TraitPath& x);
};
@@ -207,19 +207,19 @@ public:
{}
Path(GenericPath _);
Path(SimplePath _);
-
+
Path(TypeRef ty, ::std::string item, PathParams item_params=PathParams());
Path(TypeRef ty, GenericPath trait, ::std::string item, PathParams item_params=PathParams());
-
+
Path clone() const;
Compare compare_with_placeholders(const Span& sp, const Path& x, t_cb_resolve_type resolve_placeholder) const;
-
+
Ordering ord(const Path& x) const;
-
+
bool operator==(const Path& x) const;
bool operator!=(const Path& x) const { return !(*this == x); }
bool operator<(const Path& x) const { return ord(x) == OrdLess; }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Path& x);
};
diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp
index 71b0a9bb..74528aeb 100644
--- a/src/hir/pattern.cpp
+++ b/src/hir/pattern.cpp
@@ -90,14 +90,14 @@ namespace HIR {
os << ns.first << ": " << ns.second << ", ";
os << "}";
),
-
+
(Value,
os << e.val;
),
(Range,
os << e.start << " ... " << e.end;
),
-
+
(EnumValue,
os << e.path;
),
@@ -154,7 +154,7 @@ namespace {
rv.push_back( ::std::make_pair(field.first, field.second.clone()) );
return rv;
}
-
+
::HIR::Pattern::Value clone_patval(const ::HIR::Pattern::Value& val) {
TU_MATCH(::HIR::Pattern::Value, (val), (e),
(Integer,
@@ -225,7 +225,7 @@ namespace {
e.is_exhaustive
}));
),
-
+
(Value,
return Pattern(m_binding, Data::make_Value({
clone_patval(e.val)
@@ -237,7 +237,7 @@ namespace {
clone_patval(e.end)
}));
),
-
+
(EnumValue,
return Pattern(m_binding, Data::make_EnumValue({ e.path.clone(), e.binding_ptr, e.binding_idx }));
),
@@ -271,7 +271,7 @@ namespace {
}));
)
)
-
+
throw "";
}
diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp
index f86907fb..51e20c5c 100644
--- a/src/hir/pattern.hpp
+++ b/src/hir/pattern.hpp
@@ -26,14 +26,14 @@ struct PatternBinding
Ref,
MutRef,
};
-
+
bool m_mutable;
Type m_type;
::std::string m_name;
unsigned int m_slot;
-
+
bool is_valid() const { return m_name != ""; }
-
+
PatternBinding():
m_mutable(false),
m_type(Type::Move),
@@ -67,7 +67,7 @@ struct Pattern
})
);
friend ::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& x);
-
+
enum class GlobPos {
None,
Start,
@@ -136,7 +136,7 @@ struct Pattern
PatternBinding m_binding;
Data m_data;
-
+
Pattern() {}
Pattern(PatternBinding pb, Data d):
m_binding( mv$(pb) ),
@@ -146,9 +146,9 @@ struct Pattern
Pattern(Pattern&&) = default;
Pattern& operator=(const Pattern&) = delete;
Pattern& operator=(Pattern&&) = default;
-
+
Pattern clone() const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& x);
};
diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp
index 0acd95ea..0dfb9b01 100644
--- a/src/hir/serialise.cpp
+++ b/src/hir/serialise.cpp
@@ -20,7 +20,7 @@ namespace {
HirSerialiser(::HIR::serialise::Writer& out):
m_out( out )
{}
-
+
template<typename V>
void serialise_strmap(const ::std::map< ::std::string,V>& map)
{
@@ -77,7 +77,7 @@ namespace {
m_out.write_count(e.first);
serialise(e.second);
}
-
+
void serialise_type(const ::HIR::TypeRef& ty)
{
m_out.write_tag( ty.m_data.tag() );
@@ -107,7 +107,7 @@ namespace {
(ErasedType,
serialise_path(e.m_origin);
m_out.write_count(e.m_index);
-
+
m_out.write_count(e.m_traits.size());
for(const auto& t : e.m_traits)
serialise_traitpath(t);
@@ -233,12 +233,12 @@ namespace {
)
)
}
-
-
+
+
void serialise_crate(const ::HIR::Crate& crate)
{
serialise_module(crate.m_root_module);
-
+
m_out.write_count(crate.m_type_impls.size());
for(const auto& impl : crate.m_type_impls) {
serialise_typeimpl(impl);
@@ -253,10 +253,10 @@ namespace {
serialise_simplepath(tr_impl.first);
serialise_markerimpl(tr_impl.second);
}
-
+
serialise_strmap(crate.m_exported_macros);
serialise_strmap(crate.m_lang_items);
-
+
m_out.write_count(crate.m_ext_crates.size());
for(const auto& ext : crate.m_ext_crates)
m_out.write_string(ext.first);
@@ -264,9 +264,9 @@ namespace {
void serialise_module(const ::HIR::Module& mod)
{
TRACE_FUNCTION;
-
+
// m_traits doesn't need to be serialised
-
+
serialise_strmap(mod.m_value_items);
serialise_strmap(mod.m_mod_items);
}
@@ -275,7 +275,7 @@ namespace {
TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << impl.m_type);
serialise_generics(impl.m_params);
serialise_type(impl.m_type);
-
+
m_out.write_count(impl.m_methods.size());
for(const auto& v : impl.m_methods) {
m_out.write_string(v.first);
@@ -298,7 +298,7 @@ namespace {
serialise_generics(impl.m_params);
serialise_pathparams(impl.m_trait_args);
serialise_type(impl.m_type);
-
+
m_out.write_count(impl.m_methods.size());
for(const auto& v : impl.m_methods) {
DEBUG("fn " << v.first);
@@ -336,7 +336,7 @@ namespace {
m_out.write_bool(impl.is_positive);
serialise_type(impl.m_type);
}
-
+
void serialise(const ::HIR::TypeRef& ty) {
serialise_type(ty);
}
@@ -408,10 +408,10 @@ namespace {
Serialiser_TextTree ser(tmp);
tok.serialise( ser );
}
-
+
m_out.write_string(tmp.str());
}
-
+
void serialise(const ::HIR::Literal& lit)
{
m_out.write_tag(lit.tag());
@@ -440,7 +440,7 @@ namespace {
)
)
}
-
+
void serialise(const ::HIR::ExprPtr& exp)
{
m_out.write_bool( (bool)exp.m_mir );
@@ -659,7 +659,7 @@ namespace {
)
)
}
-
+
void serialise(const ::HIR::TypeItem& item)
{
TU_MATCHA( (item), (e),
@@ -726,27 +726,27 @@ namespace {
)
)
}
-
+
void serialise(unsigned int v) { m_out.write_count(v); };
-
+
void serialise(const ::HIR::Linkage& linkage)
{
//m_out.write_tag( static_cast<int>(linkage.type) );
m_out.write_string( linkage.name );
}
-
+
// - Value items
void serialise(const ::HIR::Function& fcn)
{
TRACE_FUNCTION_F("_function:");
-
+
serialise(fcn.m_linkage);
-
+
m_out.write_tag( static_cast<int>(fcn.m_receiver) );
m_out.write_string(fcn.m_abi);
m_out.write_bool(fcn.m_unsafe);
m_out.write_bool(fcn.m_const);
-
+
serialise_generics(fcn.m_params);
m_out.write_count(fcn.m_args.size());
for(const auto& a : fcn.m_args)
@@ -754,13 +754,13 @@ namespace {
m_out.write_bool(fcn.m_variadic);
serialise(fcn.m_return);
DEBUG("m_args = " << fcn.m_args);
-
+
serialise(fcn.m_code);
}
void serialise(const ::HIR::Constant& item)
{
TRACE_FUNCTION_F("_constant:");
-
+
serialise_generics(item.m_params);
serialise(item.m_type);
serialise(item.m_value);
@@ -769,15 +769,15 @@ namespace {
void serialise(const ::HIR::Static& item)
{
TRACE_FUNCTION_F("_static:");
-
+
serialise(item.m_linkage);
-
+
m_out.write_bool(item.m_is_mut);
serialise(item.m_type);
-
+
serialise(item.m_value_res);
}
-
+
// - Type items
void serialise(const ::HIR::TypeAlias& ta)
{
@@ -788,9 +788,9 @@ namespace {
{
serialise_generics(item.m_params);
m_out.write_tag( static_cast<int>(item.m_repr) );
-
+
serialise_vec( item.m_variants );
-
+
serialise(item.m_markings);
}
void serialise(const ::HIR::Enum::Variant& v)
@@ -811,7 +811,7 @@ namespace {
)
)
}
-
+
void serialise(const ::HIR::TraitMarkings& m)
{
uint8_t bitflag_1 = 0;
@@ -822,7 +822,7 @@ namespace {
BIT(3, m.has_drop_impl)
#undef BIT
m_out.write_u8(bitflag_1);
-
+
m_out.write_tag( static_cast<unsigned int>(m.dst_type) );
m_out.write_count( m.coerce_unsized_index );
m_out.write_count( m.unsized_field );
@@ -832,10 +832,10 @@ namespace {
void serialise(const ::HIR::Struct& item)
{
TRACE_FUNCTION_F("Struct");
-
+
serialise_generics(item.m_params);
m_out.write_tag( static_cast<int>(item.m_repr) );
-
+
m_out.write_tag( item.m_data.tag() );
TU_MATCHA( (item.m_data), (e),
(Unit,
@@ -847,18 +847,18 @@ namespace {
serialise_vec(e);
)
)
-
+
serialise(item.m_markings);
}
void serialise(const ::HIR::Union& item)
{
TRACE_FUNCTION_F("Union");
-
+
serialise_generics(item.m_params);
m_out.write_tag( static_cast<int>(item.m_repr) );
-
+
serialise_vec(item.m_variants);
-
+
serialise(item.m_markings);
}
void serialise(const ::HIR::Trait& item)
diff --git a/src/hir/serialise_lowlevel.cpp b/src/hir/serialise_lowlevel.cpp
index 95a547c8..a3bb3870 100644
--- a/src/hir/serialise_lowlevel.cpp
+++ b/src/hir/serialise_lowlevel.cpp
@@ -19,7 +19,7 @@ class WriterInner
::std::ofstream m_backing;
z_stream m_zstream;
::std::vector<unsigned char> m_buffer;
-
+
unsigned int m_byte_out_count = 0;
unsigned int m_byte_in_count = 0;
public:
@@ -51,7 +51,7 @@ WriterInner::WriterInner(const ::std::string& filename):
m_zstream.zalloc = Z_NULL;
m_zstream.zfree = Z_NULL;
m_zstream.opaque = Z_NULL;
-
+
const int COMPRESSION_LEVEL = Z_BEST_COMPRESSION;
int ret = deflateInit(&m_zstream, COMPRESSION_LEVEL);
if(ret != Z_OK)
@@ -63,7 +63,7 @@ WriterInner::WriterInner(const ::std::string& filename):
WriterInner::~WriterInner()
{
assert( m_zstream.avail_in == 0 );
-
+
// Complete the compression
int ret;
do
@@ -78,7 +78,7 @@ WriterInner::~WriterInner()
size_t rem = m_buffer.size() - m_zstream.avail_out;
m_byte_out_count += rem;
m_backing.write( reinterpret_cast<char*>(m_buffer.data()), rem );
-
+
m_zstream.avail_out = m_buffer.size();
m_zstream.next_out = m_buffer.data();
}
@@ -90,23 +90,23 @@ void WriterInner::write(const void* buf, size_t len)
{
m_zstream.avail_in = len;
m_zstream.next_in = reinterpret_cast<unsigned char*>( const_cast<void*>(buf) );
-
+
size_t last_avail_in = m_zstream.avail_in;
// While there's data to compress
while( m_zstream.avail_in > 0 )
{
assert(m_zstream.avail_out != 0);
-
+
// Compress the data
int ret = deflate(&m_zstream, Z_NO_FLUSH);
if(ret == Z_STREAM_ERROR)
throw ::std::runtime_error("zlib deflate stream error");
-
+
size_t used_this_time = last_avail_in - m_zstream.avail_in;
last_avail_in = m_zstream.avail_in;
m_byte_in_count += used_this_time;
-
+
// If the entire input wasn't consumed, then it was likely due to a lack of output space
// - Flush the output buffer to the file
if( m_zstream.avail_in > 0 )
@@ -114,7 +114,7 @@ void WriterInner::write(const void* buf, size_t len)
size_t bytes = m_buffer.size() - m_zstream.avail_out;
m_backing.write( reinterpret_cast<char*>(m_buffer.data()), bytes );
m_byte_out_count += bytes;
-
+
m_zstream.avail_out = m_buffer.size();
m_zstream.next_out = m_buffer.data();
}
@@ -126,10 +126,10 @@ void WriterInner::write(const void* buf, size_t len)
size_t bytes = m_buffer.size() - m_zstream.avail_out;
m_backing.write( reinterpret_cast<char*>(m_buffer.data()), bytes );
m_byte_out_count += bytes;
-
+
m_zstream.avail_out = m_buffer.size();
m_zstream.next_out = m_buffer.data();
-
+
int ret = deflate(&m_zstream, Z_NO_FLUSH);
if(ret == Z_STREAM_ERROR)
throw ::std::runtime_error("zlib deflate stream error");
@@ -201,7 +201,7 @@ void Reader::read(void* buf, size_t len)
}
buf = reinterpret_cast<uint8_t*>(buf) + used;
len -= used;
-
+
if( len >= m_buffer.capacity() )
{
m_inner->read(buf, len);
@@ -224,7 +224,7 @@ ReaderInner::ReaderInner(const ::std::string& filename):
m_zstream.zalloc = Z_NULL;
m_zstream.zfree = Z_NULL;
m_zstream.opaque = Z_NULL;
-
+
int ret = inflateInit(&m_zstream);
if(ret != Z_OK)
throw ::std::runtime_error("zlib init failure");
@@ -251,10 +251,10 @@ size_t ReaderInner::read(void* buf, size_t len)
return len - m_zstream.avail_out;
}
m_zstream.next_in = const_cast<unsigned char*>(m_buffer.data());
-
+
m_byte_in_count += m_zstream.avail_in;
}
-
+
int ret = inflate(&m_zstream, Z_NO_FLUSH);
if(ret == Z_STREAM_ERROR)
throw ::std::runtime_error("zlib inflate stream error");
@@ -268,10 +268,10 @@ size_t ReaderInner::read(void* buf, size_t len)
default:
break;
}
-
+
} while( m_zstream.avail_out > 0 );
m_byte_out_count += len;
-
+
return len;
}
diff --git a/src/hir/serialise_lowlevel.hpp b/src/hir/serialise_lowlevel.hpp
index 5172e8e9..fb4504e7 100644
--- a/src/hir/serialise_lowlevel.hpp
+++ b/src/hir/serialise_lowlevel.hpp
@@ -26,9 +26,9 @@ public:
Writer(const Writer&) = delete;
Writer(Writer&&) = delete;
~Writer();
-
+
void write(const void* data, size_t count);
-
+
void write_u8(uint8_t v) {
write(reinterpret_cast<const char*>(&v), 1);
}
@@ -134,7 +134,7 @@ class ReadBuffer
unsigned int m_ofs;
public:
ReadBuffer(size_t size);
-
+
size_t capacity() const { return m_backing.capacity(); }
size_t read(void* dst, size_t len);
void populate(ReaderInner& is);
@@ -151,7 +151,7 @@ public:
~Reader();
void read(void* dst, size_t count);
-
+
uint8_t read_u8() {
uint8_t v;
read(&v, sizeof v);
@@ -212,7 +212,7 @@ public:
uint64_t va = read_u64c();
bool sign = (va & 0x1) != 0;
va >>= 1;
-
+
if( va == 0 && sign ) {
return INT64_MIN;
}
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index c5e1984a..f2709a90 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -31,10 +31,10 @@ namespace HIR {
case CoreType::I32: return os << "i32";
case CoreType::U64: return os << "u64";
case CoreType::I64: return os << "i64";
-
+
case CoreType::F32: return os << "f32";
case CoreType::F64: return os << "f64";
-
+
case CoreType::Bool: return os << "bool";
case CoreType::Char: return os << "char";
case CoreType::Str: return os << "str";
@@ -185,7 +185,7 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
{
if( m_data.tag() != x.m_data.tag() )
return false;
-
+
TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe),
(Infer,
// TODO: Should comparing inferrence vars be an error?
@@ -306,9 +306,9 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
Ordering HIR::TypeRef::ord(const ::HIR::TypeRef& x) const
{
Ordering rv;
-
+
ORD( static_cast<unsigned int>(m_data.tag()), static_cast<unsigned int>(x.m_data.tag()) );
-
+
TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe),
(Infer,
// TODO: Should comparing inferrence vars be an error?
@@ -454,7 +454,7 @@ namespace {
if( t.m_types.size() != x.m_types.size() ) {
return ::HIR::Compare::Unequal;
}
-
+
auto rv = ::HIR::Compare::Equal;
for(unsigned int i = 0; i < t.m_types.size(); i ++ )
{
@@ -462,7 +462,7 @@ namespace {
if( rv == ::HIR::Compare::Unequal )
return rv;
}
-
+
return rv;
}
}
@@ -533,11 +533,11 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
break;
}
)
-
+
TU_IFLET(::HIR::TypeRef::Data, v.m_data, Infer, te,
// TODO: Restrict this block with a flag so it panics if an ivar is seen when not expected
ASSERT_BUG(sp, te.index != ~0u, "Encountered ivar for `this` - " << v);
-
+
switch(te.ty_class)
{
case ::HIR::InferClass::None:
@@ -576,7 +576,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
break;
}
)
-
+
if( v.m_data.tag() != x.m_data.tag() ) {
// HACK: If the path is Opaque, return a fuzzy match.
// - This works around an impl selection bug.
@@ -644,7 +644,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
)
)
}
-
+
if( rv == ::HIR::Compare::Unequal ) {
if( te.binding.is_Unbound() || xe.binding.is_Unbound() ) {
rv = ::HIR::Compare::Fuzzy;
@@ -668,7 +668,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
{
cmp &= match_generics_pp(sp, te.m_markers[i].m_params, xe.m_markers[i].m_params, resolve_placeholder, callback);
}
-
+
auto it_l = te.m_trait.m_type_bounds.begin();
auto it_r = xe.m_trait.m_type_bounds.begin();
while( it_l != te.m_trait.m_type_bounds.end() && it_r != xe.m_trait.m_type_bounds.end() )
@@ -680,7 +680,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
++ it_l;
++ it_r;
}
-
+
if( it_l != te.m_trait.m_type_bounds.end() || it_r != xe.m_trait.m_type_bounds.end() ) {
return Compare::Unequal;
}
@@ -859,12 +859,12 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
const auto& left = (m_data.is_Infer() || m_data.is_Generic() ? resolve_placeholder(*this) : *this);
//const auto& left = *this;
const auto& right = (x.m_data.is_Infer() ? resolve_placeholder(x) : (x.m_data.is_Generic() ? resolve_placeholder(x) : x));
-
+
// If the two types are the same ivar, return equal
if( left.m_data.is_Infer() && left == right ) {
return Compare::Equal;
}
-
+
// If left is infer
TU_IFLET(::HIR::TypeRef::Data, left.m_data, Infer, e,
switch(e.ty_class)
@@ -934,7 +934,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
}
throw "";
)
-
+
// If righthand side is infer, it's a fuzzy match (or not a match)
TU_IFLET(::HIR::TypeRef::Data, right.m_data, Infer, e,
switch( e.ty_class )
@@ -982,10 +982,10 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
}
throw "";
)
-
+
// If righthand is a type parameter, it can only match another type parameter
// - See `(Generic,` below
-
+
if( left.m_data.tag() != right.m_data.tag() ) {
if( left.m_data.is_Path() && left.m_data.as_Path().binding.is_Unbound() ) {
return Compare::Fuzzy;
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index d7436607..adb4e82c 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -38,9 +38,9 @@ enum class CoreType
U16, I16,
U32, I32,
U64, I64,
-
+
F32, F64,
-
+
Bool,
Char, Str,
};
@@ -80,7 +80,7 @@ extern ::std::ostream& operator<<(::std::ostream& os, const BorrowType& bt);
struct LifetimeRef
{
::std::string name;
-
+
bool operator==(const LifetimeRef& x) const {
return name == x.name;
}
@@ -101,7 +101,7 @@ public:
// - Primitive
// - Parameter
// - Path
-
+
// - Array
// - Tuple
// - Borrow
@@ -169,15 +169,15 @@ public:
::std::vector<TypeRef> m_arg_types;
})
);
-
+
Data m_data;
-
+
TypeRef() {}
TypeRef(TypeRef&& ) = default;
TypeRef(const TypeRef& ) = delete;
TypeRef& operator=(TypeRef&& ) = default;
TypeRef& operator=(const TypeRef&) = delete;
-
+
struct TagUnit {};
TypeRef(TagUnit ):
m_data( Data::make_Tuple({}) )
@@ -227,27 +227,27 @@ public:
static TypeRef new_closure(::HIR::ExprNode_Closure* node_ptr, ::std::vector< ::HIR::TypeRef> args, ::HIR::TypeRef rv) {
return TypeRef(Data::make_Closure({ node_ptr, box$(mv$(rv)), mv$(args) }));
}
-
+
TypeRef clone() const;
-
+
void fmt(::std::ostream& os) const;
-
+
bool operator==(const ::HIR::TypeRef& x) const;
bool operator!=(const ::HIR::TypeRef& x) const { return !(*this == x); }
bool operator<(const ::HIR::TypeRef& x) const { return ord(x) == OrdLess; }
Ordering ord(const ::HIR::TypeRef& x) const;
bool contains_generics() const;
-
+
// Match generics in `this` with types from `x`
// Raises a bug against `sp` if there is a form mismatch or `this` has an infer
void match_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, t_cb_match_generics) const;
-
+
bool match_test_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, t_cb_match_generics) const;
-
+
// Compares this type with another, calling the first callback to resolve placeholders in the other type, and the second callback for generics in this type
::HIR::Compare match_test_generics_fuzz(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const;
-
+
// Compares this type with another, using `resolve_placeholder` to get replacements for generics/infers in `x`
Compare compare_with_placeholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const;
};
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index 889b3a77..40bc14a4 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -15,7 +15,7 @@
void ::HIR::Visitor::visit_crate(::HIR::Crate& crate)
{
this->visit_module(::HIR::ItemPath(), crate.m_root_module );
-
+
for( auto& ty_impl : crate.m_type_impls )
{
this->visit_type_impl(ty_impl);
@@ -102,7 +102,7 @@ void ::HIR::Visitor::visit_type_impl(::HIR::TypeImpl& impl)
TRACE_FUNCTION_F("impl.m_type=" << impl.m_type);
this->visit_params(impl.m_params);
this->visit_type(impl.m_type);
-
+
for(auto& method : impl.m_methods) {
DEBUG("method " << method.first);
this->visit_function(p + method.first, method.second.data);
@@ -124,7 +124,7 @@ void ::HIR::Visitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR
impl.m_trait_args = mv$(gp.m_params);
}
this->visit_type(impl.m_type);
-
+
for(auto& ent : impl.m_methods) {
DEBUG("method " << ent.first);
this->visit_function(p + ent.first, ent.second.data);
@@ -159,7 +159,7 @@ void ::HIR::Visitor::visit_trait(::HIR::ItemPath p, ::HIR::Trait& item)
::HIR::SimplePath trait_sp = p.get_simple_path();
ItemPath trait_ip(trait_sp);
TRACE_FUNCTION;
-
+
this->visit_params(item.m_params);
for(auto& par : item.m_parent_traits) {
this->visit_trait_path(par);
diff --git a/src/hir/visitor.hpp b/src/hir/visitor.hpp
index dfae710d..dbf759a4 100644
--- a/src/hir/visitor.hpp
+++ b/src/hir/visitor.hpp
@@ -20,15 +20,15 @@ class Visitor
{
public:
virtual ~Visitor();
-
+
virtual void visit_crate(::HIR::Crate& crate);
-
+
virtual void visit_module(ItemPath p, ::HIR::Module& mod);
-
+
virtual void visit_type_impl(::HIR::TypeImpl& impl);
virtual void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl);
virtual void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl);
-
+
// - Type Items
virtual void visit_type_alias(ItemPath p, ::HIR::TypeAlias& item);
virtual void visit_trait(ItemPath p, ::HIR::Trait& item);
@@ -39,17 +39,17 @@ public:
virtual void visit_function(ItemPath p, ::HIR::Function& item);
virtual void visit_static(ItemPath p, ::HIR::Static& item);
virtual void visit_constant(ItemPath p, ::HIR::Constant& item);
-
+
// - Misc
virtual void visit_params(::HIR::GenericParams& params);
virtual void visit_pattern(::HIR::Pattern& pat);
virtual void visit_pattern_val(::HIR::Pattern::Value& val);
virtual void visit_type(::HIR::TypeRef& tr);
-
+
enum class PathContext {
TYPE,
TRAIT,
-
+
VALUE,
};
virtual void visit_trait_path(::HIR::TraitPath& p);
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp
index 198b8ea1..4601b90d 100644
--- a/src/hir_conv/bind.cpp
+++ b/src/hir_conv/bind.cpp
@@ -18,7 +18,7 @@ void ConvertHIR_Bind(::HIR::Crate& crate);
namespace {
-
+
enum class Target {
TypeItem,
Struct,
@@ -36,7 +36,7 @@ namespace {
else {
mod = &crate.m_root_module;
}
-
+
for( unsigned int i = 0; i < path.m_components.size()-1; i ++ )
{
const auto& pc = path.m_components[i];
@@ -44,7 +44,7 @@ namespace {
if( it == mod->m_mod_items.end() ) {
BUG(sp, "Couldn't find component " << i << " of " << path);
}
-
+
// If second-last, and an enum variant is desired, return the pointer to the enum
if( i+1 == path.m_components.size()-1 && t == Target::EnumVariant )
{
@@ -72,12 +72,12 @@ namespace {
if( it == mod->m_mod_items.end() ) {
BUG(sp, "Couldn't find final component of " << path);
}
-
+
switch(t)
{
case Target::TypeItem: return &it->second->ent;
case Target::EnumVariant: throw "";
-
+
case Target::Struct:
TU_IFLET(::HIR::TypeItem, it->second->ent, Struct, e2,
return &e2;
@@ -97,7 +97,7 @@ namespace {
}
throw "";
}
-
+
void fix_type_params(const Span& sp, const ::HIR::GenericParams& params_def, ::HIR::PathParams& params)
{
#if 1
@@ -109,7 +109,7 @@ namespace {
}
#endif
}
-
+
const ::HIR::Struct& get_struct_ptr(const Span& sp, const ::HIR::Crate& crate, ::HIR::GenericPath& path) {
const auto& str = *reinterpret_cast< const ::HIR::Struct*>( get_type_pointer(sp, crate, path.m_path, Target::Struct) );
fix_type_params(sp, str.m_params, path.m_params);
@@ -122,12 +122,12 @@ namespace {
if( idx == enm.m_variants.size() ) {
ERROR(sp, E0000, "Couldn't find enum variant " << path);
}
-
+
fix_type_params(sp, enm.m_params, path.m_params);
return ::std::make_pair( &enm, idx );
}
-
-
+
+
class Visitor:
public ::HIR::Visitor
{
@@ -137,15 +137,15 @@ namespace {
Visitor(const ::HIR::Crate& crate):
m_crate(crate)
{}
-
+
void visit_trait_path(::HIR::TraitPath& p) override
{
static Span sp;
p.m_trait_ptr = &m_crate.get_trait_by_path(sp, p.m_path.m_path);
-
+
::HIR::Visitor::visit_trait_path(p);
}
-
+
void visit_literal(const Span& sp, ::HIR::Literal& lit)
{
TU_MATCH(::HIR::Literal, (lit), (e),
@@ -172,11 +172,11 @@ namespace {
)
)
}
-
+
void visit_pattern_Value(const Span& sp, ::HIR::Pattern& pat, ::HIR::Pattern::Value& val)
{
bool is_single_value = pat.m_data.is_Value();
-
+
TU_IFLET( ::HIR::Pattern::Value, val, Named, ve,
TU_IFLET( ::HIR::Path::Data, ve.path.m_data, Generic, pe,
const ::HIR::Enum* enm = nullptr;
@@ -196,7 +196,7 @@ namespace {
if( it == mod->m_mod_items.end() ) {
BUG(sp, "Couldn't find component " << i << " of " << path);
}
-
+
if( i == path.m_components.size() - 2 ) {
// Here it's allowed to be either a module, or an enum.
TU_IFLET( ::HIR::TypeItem, it->second->ent, Module, e2,
@@ -223,7 +223,7 @@ namespace {
if( !is_single_value ) {
ERROR(sp, E0000, "Enum variant in range pattern - " << pat);
}
-
+
// Enum variant
auto it = ::std::find_if( enm->m_variants.begin(), enm->m_variants.end(), [&](const auto&v){ return v.first == pc; });
if( it == enm->m_variants.end() ) {
@@ -273,15 +273,15 @@ namespace {
}
)
}
-
-
+
+
void visit_pattern(::HIR::Pattern& pat) override
{
static Span _sp = Span();
const Span& sp = _sp;
::HIR::Visitor::visit_pattern(pat);
-
+
TU_MATCH_DEF(::HIR::Pattern::Data, (pat.m_data), (e),
(
),
@@ -340,7 +340,7 @@ namespace {
// Nothing to do, all good
return ;
}
-
+
if( params.m_types.size() == 0 ) {
for(const auto& typ : param_defs.m_types) {
(void)typ;
@@ -368,7 +368,7 @@ namespace {
//TRACE_FUNCTION_F(ty);
static Span _sp = Span();
const Span& sp = _sp;
-
+
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
TU_MATCH( ::HIR::Path::Data, (e.path.m_data), (pe),
(Generic,
@@ -426,10 +426,10 @@ namespace {
)
)
)
-
+
::HIR::Visitor::visit_type(ty);
}
-
+
void visit_static(::HIR::ItemPath p, ::HIR::Static& i) override
{
::HIR::Visitor::visit_static(p, i);
@@ -440,23 +440,23 @@ namespace {
::HIR::Visitor::visit_constant(p, i);
visit_literal(Span(), i.m_value_res);
}
-
+
void visit_expr(::HIR::ExprPtr& expr) override
{
struct ExprVisitor:
public ::HIR::ExprVisitorDef
{
Visitor& upper_visitor;
-
+
ExprVisitor(Visitor& uv):
upper_visitor(uv)
{}
-
+
void visit_generic_path(::HIR::Visitor::PathContext pc, ::HIR::GenericPath& p)
{
upper_visitor.visit_generic_path(p, pc);
}
-
+
void visit_node_ptr(::HIR::ExprNodeP& node_ptr) override
{
upper_visitor.visit_type(node_ptr->m_res_type);
@@ -482,7 +482,7 @@ namespace {
upper_visitor.visit_type(node.m_res_type);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_PathValue& node) override
{
upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
@@ -497,13 +497,13 @@ namespace {
upper_visitor.visit_path_params(node.m_params);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override
{
upper_visitor.visit_generic_path(node.m_path, ::HIR::Visitor::PathContext::TYPE);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
upper_visitor.visit_type(node.m_return);
@@ -514,7 +514,7 @@ namespace {
::HIR::ExprVisitorDef::visit(node);
}
};
-
+
if( expr.get() != nullptr )
{
ExprVisitor v { *this };
@@ -675,7 +675,7 @@ void ConvertHIR_Bind(::HIR::Crate& crate)
{
Visitor exp { crate };
exp.visit_crate( crate );
-
+
// Also visit extern crates to update their pointers
for(auto& ec : crate.m_ext_crates)
{
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 38444b82..35cacbcd 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -16,13 +16,13 @@
namespace {
typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values;
-
+
struct NewvalState {
t_new_values& newval_output;
const ::HIR::ItemPath& mod_path;
::std::string name_prefix;
unsigned int next_item_idx;
-
+
NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix):
newval_output(newval_output),
mod_path(mod_path),
@@ -30,7 +30,7 @@ namespace {
next_item_idx(0)
{
}
-
+
::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value)
{
auto name = FMT(name_prefix << next_item_idx);
@@ -46,9 +46,9 @@ namespace {
return rv;
}
};
-
+
::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args={});
-
+
::HIR::Literal clone_literal(const ::HIR::Literal& v)
{
TU_MATCH(::HIR::Literal, (v), (e),
@@ -84,7 +84,7 @@ namespace {
)
throw "";
}
-
+
TAGGED_UNION(EntPtr, NotFound,
(NotFound, struct{}),
(Function, const ::HIR::Function*),
@@ -106,7 +106,7 @@ namespace {
else {
mod = &crate.m_root_module;
}
-
+
for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
{
const auto& pc = path.m_components[i];
@@ -123,7 +123,7 @@ namespace {
)
)
}
-
+
switch( ns )
{
case EntNS::Value: {
@@ -131,7 +131,7 @@ namespace {
if( it == mod->m_value_items.end() ) {
return EntPtr {};
}
-
+
TU_MATCH( ::HIR::ValueItem, (it->second->ent), (e),
(Import,
),
@@ -156,7 +156,7 @@ namespace {
if( it == mod->m_mod_items.end() ) {
return EntPtr {};
}
-
+
TU_MATCH( ::HIR::TypeItem, (it->second->ent), (e),
(Import,
),
@@ -268,7 +268,7 @@ namespace {
TODO(sp, "Could not find function for " << path << " - " << rv.tag_str());
}
}
-
+
::HIR::Literal evaluate_constant_hir(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprNode& expr, ::HIR::TypeRef exp_type, ::std::vector< ::HIR::Literal> args)
{
struct Visitor:
@@ -276,26 +276,26 @@ namespace {
{
const ::HIR::Crate& m_crate;
NewvalState m_newval_state;
-
+
::std::vector< ::HIR::Literal> m_values;
-
+
::HIR::TypeRef m_exp_type;
::HIR::TypeRef m_rv_type;
::HIR::Literal m_rv;
-
+
Visitor(const ::HIR::Crate& crate, NewvalState newval_state, ::HIR::TypeRef exp_ty):
m_crate(crate),
m_newval_state( mv$(newval_state) ),
m_exp_type( mv$(exp_ty) )
{}
-
+
void badnode(const ::HIR::ExprNode& node) const {
ERROR(node.span(), E0000, "Node " << typeid(node).name() << " not allowed in constant expression");
}
-
+
void visit(::HIR::ExprNode_Block& node) override {
TRACE_FUNCTION_F("_Block");
-
+
for(const auto& e : node.m_nodes)
{
e->visit(*this);
@@ -319,7 +319,7 @@ namespace {
void visit(::HIR::ExprNode_If& node) override {
badnode(node);
}
-
+
void visit(::HIR::ExprNode_Assign& node) override {
badnode(node);
}
@@ -329,11 +329,11 @@ namespace {
auto left = mv$(m_rv);
node.m_right->visit(*this);
auto right = mv$(m_rv);
-
+
if( left.tag() != right.tag() ) {
ERROR(node.span(), E0000, "ExprNode_BinOp - Types mismatched - " << left.tag_str() << " != " << right.tag_str());
}
-
+
// Keep m_rv_type
switch(node.m_op)
{
@@ -421,17 +421,17 @@ namespace {
)
break;
}
-
+
m_rv_type = m_exp_type.clone();
}
void visit(::HIR::ExprNode_UniOp& node) override {
TRACE_FUNCTION_FR("_UniOp", m_rv);
-
+
auto exp_type = m_exp_type.clone();
-
+
node.m_value->visit(*this);
auto val = mv$(m_rv);
-
+
// Keep m_rv_type
switch(node.m_op)
{
@@ -453,12 +453,12 @@ namespace {
m_rv_type = mv$(exp_type);
}
void visit(::HIR::ExprNode_Borrow& node) override {
-
+
//m_rv_type = ::HIR::TypeRef();
//m_rv = ::HIR::Literal::make_BorrowOf( ::HIR::SimplePath() );
//return ;
//badnode(node);
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_exp_type.m_data), (te),
(
ERROR(node.span(), E0000, "Invalid expected type for a &-ptr - " << m_exp_type);
@@ -470,30 +470,30 @@ namespace {
m_exp_type = mv$(inner);
)
)
-
+
node.m_value->visit(*this);
auto val = mv$(m_rv);
-
+
if( node.m_type != ::HIR::BorrowType::Shared ) {
ERROR(node.span(), E0000, "Only shared borrows are allowed in constants");
}
-
+
if( visit_ty_with(m_rv_type, [&](const auto& x){ return x.m_data.is_Infer(); }) ) {
ERROR(node.span(), E0000, "Could not trivially infer type of referenced static - " << m_rv_type << ", lit = " << val);
}
-
+
// Create new static containing borrowed data
//auto path = m_newval_state.new_static( m_rv_type.clone(), mv$(val) );
auto path = m_newval_state.new_static( ::HIR::TypeRef(), mv$(val) );
-
+
m_rv_type = ::HIR::TypeRef::new_borrow( node.m_type, mv$(m_rv_type) );
m_rv = ::HIR::Literal::make_BorrowOf( mv$(path) );
}
void visit(::HIR::ExprNode_Cast& node) override {
TRACE_FUNCTION_F("_Cast");
-
+
m_exp_type = ::HIR::TypeRef(); // Can't know.
-
+
node.m_value->visit(*this);
auto val = mv$(m_rv);
//DEBUG("ExprNode_Cast - val = " << val << " as " << node.m_type);
@@ -548,7 +548,7 @@ namespace {
m_rv_type = node.m_res_type.clone();
}
void visit(::HIR::ExprNode_Index& node) override {
-
+
auto exp_ty = mv$(m_exp_type);
// Index
m_exp_type = ::HIR::TypeRef(::HIR::CoreType::Usize);
@@ -556,19 +556,19 @@ namespace {
if( !m_rv.is_Integer() )
ERROR(node.span(), E0000, "Array index isn't an integer - got " << m_rv.tag_str());
auto idx = m_rv.as_Integer();
-
+
// Value
m_exp_type = ::HIR::TypeRef::new_slice( mv$(exp_ty) );
node.m_value->visit(*this);
if( !m_rv.is_List() )
ERROR(node.span(), E0000, "Indexed value isn't a list - got " << m_rv.tag_str());
auto v = mv$( m_rv.as_List() );
-
+
// -> Perform
if( idx >= v.size() )
ERROR(node.span(), E0000, "Constant array index " << idx << " out of range " << v.size());
m_rv = mv$(v[idx]);
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_rv_type.m_data), (e),
(
ERROR(node.span(), E0000, "Indexing non-array - " << m_rv_type);
@@ -585,23 +585,23 @@ namespace {
void visit(::HIR::ExprNode_Emplace& node) override {
badnode(node);
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override {
m_exp_type = ::HIR::TypeRef();
-
+
::std::vector< ::HIR::Literal> vals;
for(const auto& vn : node.m_args ) {
vn->visit(*this);
assert( !m_rv.is_Invalid() );
vals.push_back( mv$(m_rv) );
}
-
+
if( node.m_is_struct )
{
const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path);
ASSERT_BUG(node.span(), ent.is_Struct(), "_TupleVariant with m_is_struct set pointing to " << ent.tag_str());
const auto& str = ent.as_Struct();
-
+
m_rv = ::HIR::Literal::make_List(mv$(vals));
m_rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) );
}
@@ -613,7 +613,7 @@ namespace {
const auto& ent = m_crate.get_typeitem_by_path(node.span(), tmp_path);
ASSERT_BUG(node.span(), ent.is_Enum(), "_TupleVariant with m_is_struct clear pointing to " << ent.tag_str());
const auto& enm = ent.as_Enum();
-
+
auto it = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == varname; } );
ASSERT_BUG(node.span(), it != enm.m_variants.end(), "_TupleVariant points to unknown variant - " << node.m_path);
unsigned int var_idx = it - enm.m_variants.begin();
@@ -624,20 +624,20 @@ namespace {
}
void visit(::HIR::ExprNode_CallPath& node) override
{
-
+
TRACE_FUNCTION_FR("_CallPath - " << node.m_path, m_rv);
auto& fcn = get_function(node.span(), m_crate, node.m_path);
-
+
// TODO: Set m_const during parse
//if( ! fcn.m_const ) {
// ERROR(node.span(), E0000, "Calling non-const function in const context - " << node.m_path);
//}
-
+
if( fcn.m_args.size() != node.m_args.size() ) {
ERROR(node.span(), E0000, "Incorrect argument count for " << node.m_path << " - expected " << fcn.m_args.size() << ", got " << node.m_args.size());
}
auto exp_ret_type = mv$( m_exp_type );
-
+
::std::vector< ::HIR::Literal> args;
args.reserve( fcn.m_args.size() );
for(unsigned int i = 0; i < fcn.m_args.size(); i ++ )
@@ -655,11 +655,11 @@ namespace {
else {
ERROR(node.span(), E0000, "Constant functions can't have destructuring pattern argments");
}
-
+
node.m_args[i]->visit(*this);
args.push_back( mv$(m_rv) );
}
-
+
// Call by invoking evaluate_constant on the function
{
TRACE_FUNCTION_F("Call const fn " << node.m_path << " args={ " << args << " }");
@@ -676,16 +676,16 @@ namespace {
void visit(::HIR::ExprNode_Field& node) override {
const auto& sp = node.span();
TRACE_FUNCTION_FR("_Field", m_rv);
-
+
m_exp_type = ::HIR::TypeRef();
-
+
node.m_value->visit(*this);
auto val = mv$( m_rv );
-
+
if( !val.is_List() )
ERROR(sp, E0000, "Field access on invalid literal type - " << val.tag_str());
auto& vals = val.as_List();
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_rv_type.m_data), (e),
(
ERROR(sp, E0000, "Field access on invalid type - " << m_rv_type);
@@ -732,7 +732,7 @@ namespace {
unsigned int idx = ::std::atoi( node.m_field.c_str() );
ASSERT_BUG(sp, idx < e.size(), "Index out of range in tuple");
ASSERT_BUG(sp, idx < vals.size(), "Index out of range in literal");
-
+
m_rv = mv$( vals[idx] );
m_rv_type = mv$( e[idx] );
)
@@ -770,7 +770,7 @@ namespace {
const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path);
ASSERT_BUG(node.span(), ent.is_Struct(), "_UnitVariant with m_is_struct set pointing to " << ent.tag_str());
const auto& str = ent.as_Struct();
-
+
m_rv = ::HIR::Literal::make_List({});
m_rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) );
}
@@ -782,7 +782,7 @@ namespace {
const auto& ent = m_crate.get_typeitem_by_path(node.span(), tmp_path);
ASSERT_BUG(node.span(), ent.is_Enum(), "_UnitVariant with m_is_struct clear pointing to " << ent.tag_str());
const auto& enm = ent.as_Enum();
-
+
auto it = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == varname; } );
ASSERT_BUG(node.span(), it != enm.m_variants.end(), "_UnitVariant points to unknown variant - " << node.m_path);
unsigned int var_idx = it - enm.m_variants.begin();
@@ -845,24 +845,24 @@ namespace {
)
m_rv_type = ::HIR::TypeRef(); // TODO:
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override {
TRACE_FUNCTION_FR("_StructLiteral - " << node.m_path, m_rv);
-
+
if( node.m_is_struct )
{
const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path);
ASSERT_BUG(node.span(), ent.is_Struct(), "_StructLiteral with m_is_struct set pointing to a " << ent.tag_str());
const auto& str = ent.as_Struct();
const auto& fields = str.m_data.as_Named();
-
+
auto rv_type = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding(&str) );
-
+
::std::vector< ::HIR::Literal> vals;
if( node.m_base_value )
{
m_exp_type = rv_type.clone();
-
+
node.m_base_value->visit(*this);
auto base_val = mv$(m_rv);
if( !base_val.is_List() || base_val.as_List().size() != fields.size() ) {
@@ -878,14 +878,14 @@ namespace {
if( idx == fields.size() ) {
ERROR(node.span(), E0000, "Field name " << val_set.first << " isn't a member of " << node.m_path);
}
-
+
if( monomorphise_type_needed(fields[idx].second.ent) ) {
m_exp_type = ::HIR::TypeRef();
}
else {
m_exp_type = fields[idx].second.ent.clone();
}
-
+
val_set.second->visit(*this);
vals[idx] = mv$(m_rv);
}
@@ -903,7 +903,7 @@ namespace {
{
const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path);
ASSERT_BUG(node.span(), ent.is_Enum(), "_StructLiteral with m_is_struct clear pointing to a " << ent.tag_str());
-
+
TODO(node.span(), "Handle Enum _UnitVariant - " << node.m_path);
}
}
@@ -925,21 +925,21 @@ namespace {
ASSERT_BUG(node.span(), exp_tys.size() == node.m_vals.size(), "Tuple literal size mismatches with expected type");
)
)
-
+
::std::vector< ::HIR::Literal> vals;
::std::vector< ::HIR::TypeRef> tys;
for(unsigned int i = 0; i < node.m_vals.size(); i ++)
{
if( exp_tys.size() > 0 )
m_exp_type = mv$(exp_tys[i]);
-
+
node.m_vals[i]->visit(*this);
assert( !m_rv.is_Invalid() );
-
+
vals.push_back( mv$(m_rv) );
tys.push_back( mv$(m_rv_type) );
}
-
+
m_rv = ::HIR::Literal::make_List(mv$(vals));
m_rv_type = ::HIR::TypeRef( mv$(tys) );
}
@@ -960,7 +960,7 @@ namespace {
exp_inner_ty = mv$(*te.inner);
)
)
-
+
::std::vector< ::HIR::Literal> vals;
for(const auto& vn : node.m_vals )
{
@@ -969,7 +969,7 @@ namespace {
assert( !m_rv.is_Invalid() );
vals.push_back( mv$(m_rv) );
}
-
+
m_rv_type = ::HIR::TypeRef::new_array( mv$(m_rv_type), vals.size() );
m_rv = ::HIR::Literal::make_List(mv$(vals));
}
@@ -989,12 +989,12 @@ namespace {
exp_inner_ty = mv$(*te.inner);
)
)
-
+
m_exp_type = ::HIR::CoreType::Usize;
node.m_size->visit(*this);
assert( m_rv.is_Integer() );
unsigned int count = static_cast<unsigned int>(m_rv.as_Integer());
-
+
::std::vector< ::HIR::Literal> vals;
vals.reserve( count );
if( count > 0 )
@@ -1011,37 +1011,37 @@ namespace {
m_rv = ::HIR::Literal::make_List(mv$(vals));
m_rv_type = ::HIR::TypeRef::new_array( mv$(m_rv_type), count );
}
-
+
void visit(::HIR::ExprNode_Closure& node) override {
badnode(node);
}
};
-
+
Visitor v { crate, newval_state, mv$(exp_type) };
for(auto& arg : args)
v.m_values.push_back( mv$(arg) );
const_cast<::HIR::ExprNode&>(expr).visit(v);
-
+
if( v.m_rv.is_Invalid() ) {
BUG(sp, "Expression did not yeild a literal");
}
-
+
return mv$(v.m_rv);
}
-
+
::HIR::Literal evaluate_constant_mir(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::MIR::Function& fcn, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)
{
TRACE_FUNCTION;
-
+
StaticTraitResolve resolve { crate };
::MIR::TypeResolve state { sp, resolve, FMT_CB(), exp, {}, fcn };
-
+
::HIR::Literal retval;
::std::vector< ::HIR::Literal> locals;
::std::vector< ::HIR::Literal> temps;
locals.resize( fcn.named_variables.size() );
temps.resize( fcn.temporaries.size() );
-
+
auto get_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal& {
TU_MATCHA( (lv), (e),
(Variable,
@@ -1098,7 +1098,7 @@ namespace {
)
)
};
-
+
unsigned int cur_block = 0;
for(;;)
{
@@ -1107,12 +1107,12 @@ namespace {
for(const auto& stmt : block.statements)
{
state.set_cur_stmt(cur_block, next_stmt_idx++);
-
+
if( ! stmt.is_Assign() ) {
//BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot);
continue ;
}
-
+
::HIR::Literal val;
const auto& sa = stmt.as_Assign();
TU_MATCHA( (sa.src), (e),
@@ -1165,14 +1165,14 @@ namespace {
if( e.type != ::HIR::BorrowType::Shared ) {
MIR_BUG(state, "Only shared borrows are allowed in constants");
}
-
+
auto inner_val = read_lval(e.val);
-
+
::HIR::TypeRef inner_ty;
const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val);
if( &inner_ty_r != &inner_ty )
inner_ty = inner_ty_r.clone();
-
+
// Create new static containing borrowed data
auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) );
val = ::HIR::Literal::make_BorrowOf( mv$(item_path) );
@@ -1206,7 +1206,7 @@ namespace {
case ::HIR::CoreType::Usize:
case ::HIR::CoreType::Isize:
mask = 0xFFFFFFFFFFFFFFFF;
-
+
TU_IFLET( ::HIR::Literal, inval, Integer, i,
val = ::HIR::Literal(i & mask);
)
@@ -1268,7 +1268,7 @@ namespace {
case ::MIR::eBinOp::MUL_OV:
case ::MIR::eBinOp::DIV_OV:
TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
-
+
case ::MIR::eBinOp::BIT_OR :
case ::MIR::eBinOp::BIT_AND:
case ::MIR::eBinOp::BIT_XOR:
@@ -1297,7 +1297,7 @@ namespace {
case ::MIR::eBinOp::MUL_OV:
case ::MIR::eBinOp::DIV_OV:
TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
-
+
case ::MIR::eBinOp::BIT_OR : val = ::HIR::Literal( l | r ); break;
case ::MIR::eBinOp::BIT_AND: val = ::HIR::Literal( l & r ); break;
case ::MIR::eBinOp::BIT_XOR: val = ::HIR::Literal( l ^ r ); break;
@@ -1383,7 +1383,7 @@ namespace {
val = ::HIR::Literal::make_List( mv$(vals) );
)
)
-
+
auto& dst = get_lval(sa.dst);
dst = mv$(val);
}
@@ -1405,25 +1405,25 @@ namespace {
auto& dst = get_lval(e.ret_val);
auto& fcn = get_function(sp, crate, fcnp);
-
+
::std::vector< ::HIR::Literal> call_args;
call_args.reserve( e.args.size() );
for(const auto& a : e.args)
call_args.push_back( read_lval(a) );
// TODO: Set m_const during parse and check here
-
+
// Call by invoking evaluate_constant on the function
{
TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }");
dst = evaluate_constant(sp, crate, newval_state, fcn.m_code, ::HIR::TypeRef(), mv$(call_args));
}
-
+
cur_block = e.ret_block;
)
)
}
}
-
+
::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)
{
if( expr.m_mir ) {
@@ -1436,7 +1436,7 @@ namespace {
BUG(sp, "Attempting to evaluate constant expression with no associated code");
}
}
-
+
void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit)
{
// TODO: Mask down limited size integers
@@ -1455,7 +1455,7 @@ namespace {
),
(Closure,
),
-
+
(Path,
// List
),
@@ -1465,7 +1465,7 @@ namespace {
(Tuple,
// List
),
-
+
(Borrow,
// A whole host of things
),
@@ -1475,7 +1475,7 @@ namespace {
(Function,
// ItemAddr
),
-
+
(Primitive,
switch(te)
{
@@ -1492,7 +1492,7 @@ namespace {
case ::HIR::CoreType::U8: lit.as_Integer() &= (1ull<<8)-1; break;
case ::HIR::CoreType::U16: lit.as_Integer() &= (1ull<<16)-1; break;
case ::HIR::CoreType::U32: lit.as_Integer() &= (1ull<<32)-1; break;
-
+
case ::HIR::CoreType::I8: lit.as_Integer() &= (1ull<<8)-1; break;
case ::HIR::CoreType::I16: lit.as_Integer() &= (1ull<<16)-1; break;
case ::HIR::CoreType::I32: lit.as_Integer() &= (1ull<<32)-1; break;
@@ -1516,15 +1516,15 @@ namespace {
Expander(const ::HIR::Crate& crate):
m_crate(crate)
{}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
auto saved_mp = m_mod_path;
m_mod_path = &p;
auto saved = mv$( m_new_values );
-
+
::HIR::Visitor::visit_module(p, mod);
-
+
for( auto& item : m_new_values )
{
mod.m_value_items.insert( ::std::make_pair(
@@ -1535,11 +1535,11 @@ namespace {
m_new_values = mv$(saved);
m_mod_path = saved_mp;
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
::HIR::Visitor::visit_type(ty);
-
+
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
if( e.size_val == ~0u )
{
@@ -1558,7 +1558,7 @@ namespace {
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override
{
::HIR::Visitor::visit_constant(p, item);
-
+
if( item.m_value )
{
//if( item.m_type.m_data.is_Primitive() )
@@ -1567,12 +1567,12 @@ namespace {
// ;
//else
// return ;
-
+
auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") };
item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, nvs, item.m_value, item.m_type.clone(), {});
-
+
check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
-
+
DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
}
}
@@ -1586,18 +1586,18 @@ namespace {
}
::HIR::Visitor::visit_enum(p, item);
}
-
+
void visit_expr(::HIR::ExprPtr& expr) override
{
struct Visitor:
public ::HIR::ExprVisitorDef
{
Expander& m_exp;
-
+
Visitor(Expander& exp):
m_exp(exp)
{}
-
+
void visit(::HIR::ExprNode_Let& node) override {
::HIR::ExprVisitorDef::visit(node);
m_exp.visit_type(node.m_type);
@@ -1627,7 +1627,7 @@ namespace {
node.m_size_val = val.as_Integer();
DEBUG("Array literal [?; " << node.m_size_val << "]");
}
-
+
void visit(::HIR::ExprNode_CallPath& node) override {
::HIR::ExprVisitorDef::visit(node);
m_exp.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
@@ -1637,7 +1637,7 @@ namespace {
m_exp.visit_path_params(node.m_params);
}
};
-
+
if( expr.get() != nullptr )
{
Visitor v { *this };
diff --git a/src/hir_conv/expand_type.cpp b/src/hir_conv/expand_type.cpp
index 5e95592c..dccccace 100644
--- a/src/hir_conv/expand_type.cpp
+++ b/src/hir_conv/expand_type.cpp
@@ -10,7 +10,7 @@
::HIR::TypeRef ConvertHIR_ExpandAliases_GetExpansion_GP(const Span& sp, const ::HIR::Crate& crate, const ::HIR::GenericPath& path, bool is_expr)
{
::HIR::TypeRef empty_type;
-
+
const auto& ti = crate.get_typeitem_by_path(sp, path.m_path);
TU_MATCH_DEF( ::HIR::TypeItem, (ti), (e2),
(
@@ -79,11 +79,11 @@ public:
Expander(const ::HIR::Crate& crate):
m_crate(crate)
{}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
::HIR::Visitor::visit_type(ty);
-
+
TU_IFLET(::HIR::TypeRef::Data, (ty.m_data), Path, (e),
::HIR::TypeRef new_type = ConvertHIR_ExpandAliases_GetExpansion(m_crate, e.path, m_in_expr);
// Keep trying to expand down the chain
@@ -110,15 +110,15 @@ public:
}
)
}
-
-
+
+
::HIR::GenericPath expand_alias_gp(const Span& sp, const ::HIR::GenericPath& path)
{
const unsigned int MAX_RECURSIVE_TYPE_EXPANSIONS = 100;
-
+
::HIR::GenericPath rv;
const auto* cur = &path;
-
+
unsigned int num_exp = 0;
do {
auto ty = ConvertHIR_ExpandAliases_GetExpansion_GP(sp, m_crate, *cur, m_in_expr);
@@ -130,20 +130,20 @@ public:
if( !ty_p.m_data.is_Generic() )
ERROR(sp, E0000, "Type alias referenced in generic path doesn't point to a generic path");
rv = mv$( ty_p.m_data.as_Generic() );
-
+
this->visit_generic_path(rv, ::HIR::Visitor::PathContext::TYPE);
-
+
cur = &rv;
} while( ++num_exp < MAX_RECURSIVE_TYPE_EXPANSIONS );
ASSERT_BUG(sp, num_exp < MAX_RECURSIVE_TYPE_EXPANSIONS, "Recursion limit expanding " << path << " (currently on " << *cur << ")");
return rv;
}
-
+
void visit_pattern(::HIR::Pattern& pat) override
{
static Span sp;
::HIR::Visitor::visit_pattern(pat);
-
+
TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (e),
(
),
@@ -173,18 +173,18 @@ public:
)
)
}
-
+
void visit_expr(::HIR::ExprPtr& expr) override
{
struct Visitor:
public ::HIR::ExprVisitorDef
{
Expander& upper_visitor;
-
+
Visitor(Expander& uv):
upper_visitor(uv)
{}
-
+
// TODO: Use the other visitors.
void visit_path(::HIR::Visitor::PathContext pc, ::HIR::Path& p)
{
@@ -194,7 +194,7 @@ public:
{
upper_visitor.visit_generic_path(p, pc);
}
-
+
void visit(::HIR::ExprNode_Let& node) override
{
upper_visitor.visit_type(node.m_type);
@@ -206,7 +206,7 @@ public:
upper_visitor.visit_type(node.m_res_type);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_CallPath& node) override
{
upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
@@ -217,7 +217,7 @@ public:
upper_visitor.visit_path_params(node.m_params);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
upper_visitor.visit_type(node.m_return);
@@ -227,7 +227,7 @@ public:
}
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override
{
if( node.m_is_struct )
@@ -239,10 +239,10 @@ public:
node.m_path = mv$(new_path);
}
}
-
+
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Match& node) override
{
for(auto& arm : node.m_arms) {
@@ -253,15 +253,15 @@ public:
::HIR::ExprVisitorDef::visit(node);
}
};
-
+
if( expr.get() != nullptr )
{
auto old = m_in_expr;
m_in_expr = true;
-
+
Visitor v { *this };
(*expr).visit(v);
-
+
m_in_expr = old;
}
}
diff --git a/src/hir_conv/markings.cpp b/src/hir_conv/markings.cpp
index ed49be52..fe17aedc 100644
--- a/src/hir_conv/markings.cpp
+++ b/src/hir_conv/markings.cpp
@@ -33,11 +33,11 @@ public:
m_lang_PhantomData( crate.get_lang_item_path_opt("phantom_data") )
{
}
-
+
void visit_struct(::HIR::ItemPath ip, ::HIR::Struct& str) override
{
::HIR::Visitor::visit_struct(ip, str);
-
+
TU_MATCHA( (str.m_data), (se),
(Unit,
),
@@ -48,7 +48,7 @@ public:
// - If it is Sized, leave as-is (struct is marked as Sized)
// - If it is known unsized, record the type
// - If it is a ?Sized parameter, mark as possible and record index for MIR
-
+
// TODO: Ensure that only the last field is ?Sized
if( se.size() > 0 )
{
@@ -59,7 +59,7 @@ public:
if( last_field.m_data.is_Generic() )
{
const auto& te = last_field.m_data.as_Generic();
-
+
if( str.m_params.m_types.at(te.binding).m_is_sized == false )
{
str.m_markings.unsized_field = se.size() - 1;
@@ -86,9 +86,9 @@ public:
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
{
static Span sp;
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
-
+
if( impl.m_type.m_data.is_Path() )
{
const auto& te = impl.m_type.m_data.as_Path();
@@ -115,7 +115,7 @@ public:
else if( trait_path == m_lang_CoerceUnsized ) {
if( markings_ptr->coerce_unsized_index != ~0u )
ERROR(sp, E0000, "CoerceUnsized can only be implemented once per struct");
-
+
DEBUG("Type " << impl.m_type << " can Coerce");
if( impl.m_trait_args.m_types.size() != 1 )
ERROR(sp, E0000, "Unexpected number of arguments for CoerceUnsized");
@@ -130,18 +130,18 @@ public:
ERROR(sp, E0000, "Cannot implement CoerceUnsized from non-structs");
if( dst_te.binding.as_Struct() != te.binding.as_Struct() )
ERROR(sp, E0000, "CoerceUnsized can only be implemented between variants of the same struct");
-
+
// NOTES: (from IRC: eddyb)
// < eddyb> they're required that T and U are the same struct definition (with different type parameters) and exactly one field differs in type between T and U (ignoring PhantomData)
// < eddyb> Mutabah: I forgot to mention that the field that differs in type must also impl CoerceUnsized
-
+
// Determine the difference in monomorphised variants.
unsigned int field = ~0u;
const auto& str = te.binding.as_Struct();
-
+
auto monomorph_cb_l = monomorphise_type_get_cb(sp, nullptr, &dst_te.path.m_data.as_Generic().m_params, nullptr);
auto monomorph_cb_r = monomorphise_type_get_cb(sp, nullptr, &te.path.m_data.as_Generic().m_params, nullptr);
-
+
TU_MATCHA( (str->m_data), (se),
(Unit,
),
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp
index 671c5be8..03cbd168 100644
--- a/src/hir_conv/resolve_ufcs.cpp
+++ b/src/hir_conv/resolve_ufcs.cpp
@@ -17,27 +17,27 @@ namespace {
public ::HIR::Visitor
{
const ::HIR::Crate& m_crate;
-
+
typedef ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > t_trait_imports;
t_trait_imports m_traits;
-
+
StaticTraitResolve m_resolve;
const ::HIR::TypeRef* m_current_type = nullptr;
const ::HIR::Trait* m_current_trait;
const ::HIR::ItemPath* m_current_trait_path;
bool m_in_expr = false;
-
+
public:
Visitor(const ::HIR::Crate& crate):
m_crate(crate),
m_resolve(crate),
m_current_trait(nullptr)
{}
-
+
struct ModTraitsGuard {
Visitor* v;
t_trait_imports old_imports;
-
+
~ModTraitsGuard() {
this->v->m_traits = mv$(this->old_imports);
}
@@ -89,17 +89,17 @@ namespace {
TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type << " (mod=" << impl.m_src_module << ")");
auto _t = this->push_mod_traits( this->m_crate.get_mod_by_path(Span(), impl.m_src_module) );
auto _g = m_resolve.set_impl_generics(impl.m_params);
-
+
// TODO: Push a bound that `Self: ThisTrait`
m_current_type = &impl.m_type;
m_current_trait = &m_crate.get_trait_by_path(Span(), trait_path);
m_current_trait_path = &p;
-
+
// The implemented trait is always in scope
m_traits.push_back( ::std::make_pair( &trait_path, m_current_trait) );
::HIR::Visitor::visit_trait_impl(trait_path, impl);
m_traits.pop_back( );
-
+
m_current_trait = nullptr;
m_current_type = nullptr;
}
@@ -110,11 +110,11 @@ namespace {
public ::HIR::ExprVisitorDef
{
Visitor& upper_visitor;
-
+
ExprVisitor(Visitor& uv):
upper_visitor(uv)
{}
-
+
void visit(::HIR::ExprNode_Let& node) override
{
upper_visitor.visit_pattern(node.m_pattern);
@@ -126,7 +126,7 @@ namespace {
upper_visitor.visit_type(node.m_res_type);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_CallPath& node) override
{
upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
@@ -137,13 +137,13 @@ namespace {
upper_visitor.visit_path_params(node.m_params);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_PathValue& node) override
{
upper_visitor.visit_path(node.m_path, ::HIR::Visitor::PathContext::VALUE);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Match& node) override
{
for(auto& arm : node.m_arms)
@@ -153,7 +153,7 @@ namespace {
}
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
upper_visitor.visit_type(node.m_return);
@@ -163,7 +163,7 @@ namespace {
}
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Block& node) override
{
if( node.m_traits.size() == 0 && node.m_local_mod.m_components.size() > 0 ) {
@@ -179,7 +179,7 @@ namespace {
upper_visitor.m_traits.pop_back();
}
};
-
+
if( expr.get() != nullptr )
{
m_in_expr = true;
@@ -203,7 +203,7 @@ namespace {
}
}
);
- // -
+ // -
}
return false;
}
@@ -214,7 +214,7 @@ namespace {
static bool locate_item_in_trait(::HIR::Visitor::PathContext pc, const ::HIR::Trait& trait, ::HIR::Path::Data& pd)
{
const auto& e = pd.as_UfcsUnknown();
-
+
switch(pc)
{
case ::HIR::Visitor::PathContext::VALUE:
@@ -305,13 +305,13 @@ namespace {
}
return false;
}
-
+
bool locate_in_trait_impl_and_set(const Span& sp, ::HIR::Visitor::PathContext pc, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd)
{
auto& e = pd.as_UfcsUnknown();
if( this->locate_item_in_trait(pc, trait, pd) ) {
const auto& type = *e.type;
-
+
// TODO: This is VERY arbitary and possibly nowhere near what rustc does.
this->m_resolve.find_impl(sp, trait_path.m_path, nullptr, type, [&](const auto& impl, bool fuzzy){
auto pp = impl.get_trait_params();
@@ -356,8 +356,8 @@ namespace {
else {
DEBUG("- Item " << e.item << " not in trait " << trait_path.m_path);
}
-
-
+
+
// Search supertraits (recursively)
for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ )
{
@@ -371,7 +371,7 @@ namespace {
}
return false;
}
-
+
bool resolve_UfcsUnknown_inherent(const ::HIR::Path& p, ::HIR::Visitor::PathContext pc, ::HIR::Path::Data& pd)
{
auto& e = pd.as_UfcsUnknown();
@@ -394,14 +394,14 @@ namespace {
case ::HIR::Visitor::PathContext::TYPE:
return false;
}
-
+
auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} );
pd = mv$(new_data);
DEBUG("- Resolved, replace with " << p);
return true;
});
}
-
+
bool resolve_UfcsUnknown_trait(const ::HIR::Path& p, ::HIR::Visitor::PathContext pc, ::HIR::Path::Data& pd)
{
static Span sp;
@@ -409,7 +409,7 @@ namespace {
for( const auto& trait_info : m_traits )
{
const auto& trait = *trait_info.second;
-
+
DEBUG( e.item << " in? " << *trait_info.first );
switch(pc)
{
@@ -424,14 +424,14 @@ namespace {
break;
}
DEBUG("- Trying trait " << *trait_info.first);
-
+
auto trait_path = ::HIR::GenericPath( *trait_info.first );
for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++ ) {
trait_path.m_params.m_types.push_back( ::HIR::TypeRef() );
}
-
+
// TODO: If there's only one trait with this name, assume it's the correct one.
-
+
// TODO: Search supertraits
// TODO: Should impls be searched first, or item names?
// - Item names add complexity, but impls are slower
@@ -441,17 +441,17 @@ namespace {
}
return false;
}
-
+
void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override
{
static Span sp;
-
+
TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e,
TRACE_FUNCTION_FR("UfcsUnknown - p=" << p, p);
-
+
this->visit_type( *e.type );
this->visit_path_params( e.params );
-
+
// Search for matching impls in current generic blocks
if( m_resolve.m_item_generics != nullptr && locate_trait_item_in_bounds(pc, *e.type, *m_resolve.m_item_generics, p.m_data) ) {
DEBUG("Found in item params, p = " << p);
@@ -468,7 +468,7 @@ namespace {
return ;
}
assert(p.m_data.is_UfcsUnknown());
-
+
// If processing a trait, and the type is 'Self', search for the type/method on the trait
// - TODO: This could be encoded by a `Self: Trait` bound in the generics, but that may have knock-on issues?
if( *e.type == ::HIR::TypeRef("Self", 0xFFFF) || (m_current_type && *e.type == *m_current_type) )
@@ -497,13 +497,13 @@ namespace {
}
DEBUG("- Item " << e.item << " not found in Self - ty=" << *e.type);
}
-
+
// 2. Search all impls of in-scope traits for this method on this type
if( this->resolve_UfcsUnknown_trait(p, pc, p.m_data) ) {
return ;
}
assert(p.m_data.is_UfcsUnknown());
-
+
// Couldn't find it
ERROR(sp, E0000, "Failed to find impl with '" << e.item << "' for " << *e.type << " (in " << p << ")");
)
@@ -511,14 +511,14 @@ namespace {
::HIR::Visitor::visit_path(p, pc);
}
}
-
+
void visit_pattern(::HIR::Pattern& pat) override
{
static Span _sp = Span();
const Span& sp = _sp;
::HIR::Visitor::visit_pattern(pat);
-
+
TU_MATCH_DEF(::HIR::Pattern::Data, (pat.m_data), (e),
(
),
diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp
index 4aaf1f84..8141f1a6 100644
--- a/src/hir_expand/annotate_value_usage.cpp
+++ b/src/hir_expand/annotate_value_usage.cpp
@@ -12,13 +12,13 @@
#include "main_bindings.hpp"
namespace {
-
+
class ExprVisitor_Mark:
public ::HIR::ExprVisitor//Def
{
const StaticTraitResolve& m_resolve;
::std::vector< ::HIR::ValueUsage> m_usage;
-
+
struct UsageGuard
{
ExprVisitor_Mark& m_parent;
@@ -35,7 +35,7 @@ namespace {
}
}
};
-
+
::HIR::ValueUsage get_usage() const {
return (m_usage.empty() ? ::HIR::ValueUsage::Move : m_usage.back());
}
@@ -48,12 +48,12 @@ namespace {
return UsageGuard(*this, true);
}
}
-
+
public:
ExprVisitor_Mark(const StaticTraitResolve& resolve):
m_resolve(resolve)
{}
-
+
void visit_root(::HIR::ExprPtr& root_ptr)
{
assert(root_ptr);
@@ -65,27 +65,27 @@ namespace {
void visit_node_ptr(::HIR::ExprNodeP& node_ptr) override
{
assert(node_ptr);
-
+
const auto& node_ref = *node_ptr;
const char* node_tyname = typeid(node_ref).name();
TRACE_FUNCTION_FR(&*node_ptr << " " << node_tyname, node_ptr->m_usage);
-
+
node_ptr->m_usage = this->get_usage();
-
+
auto expected_size = m_usage.size();
node_ptr->visit( *this );
assert( m_usage.size() == expected_size );
}
-
+
void visit(::HIR::ExprNode_Block& node) override
{
auto _ = this->push_usage( ::HIR::ValueUsage::Move );
-
+
for( auto& subnode : node.m_nodes ) {
this->visit_node_ptr(subnode);
}
}
-
+
void visit(::HIR::ExprNode_Return& node) override
{
auto _ = this->push_usage( ::HIR::ValueUsage::Move );
@@ -115,13 +115,13 @@ namespace {
::HIR::ValueUsage vu = ::HIR::ValueUsage::Unknown;
for( const auto& arm : node.m_arms )
{
- for( const auto& pat : arm.m_patterns )
+ for( const auto& pat : arm.m_patterns )
vu = ::std::max( vu, this->get_usage_for_pattern(node.span(), pat, val_ty) );
}
auto _ = this->push_usage( vu );
this->visit_node_ptr( node.m_value );
}
-
+
auto _ = this->push_usage( ::HIR::ValueUsage::Move );
for(auto& arm : node.m_arms)
{
@@ -140,7 +140,7 @@ namespace {
this->visit_node_ptr( node.m_false );
}
}
-
+
void visit(::HIR::ExprNode_Assign& node) override
{
{
@@ -155,9 +155,9 @@ namespace {
void visit(::HIR::ExprNode_UniOp& node) override
{
m_usage.push_back( ::HIR::ValueUsage::Move );
-
+
this->visit_node_ptr(node.m_value);
-
+
m_usage.pop_back();
}
void visit(::HIR::ExprNode_Borrow& node) override
@@ -174,12 +174,12 @@ namespace {
m_usage.push_back( ::HIR::ValueUsage::Move );
break;
}
-
+
this->visit_node_ptr(node.m_value);
-
+
m_usage.pop_back();
}
-
+
void visit(::HIR::ExprNode_BinOp& node) override
{
switch(node.m_op)
@@ -196,10 +196,10 @@ namespace {
m_usage.push_back( ::HIR::ValueUsage::Move );
break;
}
-
+
this->visit_node_ptr(node.m_left);
this->visit_node_ptr(node.m_right);
-
+
m_usage.pop_back();
}
void visit(::HIR::ExprNode_Cast& node) override
@@ -222,7 +222,7 @@ namespace {
else {
this->visit_node_ptr(node.m_value);
}
-
+
auto _ = push_usage( ::HIR::ValueUsage::Move );
this->visit_node_ptr(node.m_index);
}
@@ -241,7 +241,7 @@ namespace {
this->visit_node_ptr(node.m_value);
}
}
-
+
void visit(::HIR::ExprNode_Emplace& node) override
{
if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) {
@@ -256,7 +256,7 @@ namespace {
this->visit_node_ptr(node.m_value);
}
}
-
+
void visit(::HIR::ExprNode_Field& node) override
{
bool is_copy = m_resolve.type_is_copy(node.span(), node.m_res_type);
@@ -270,18 +270,18 @@ namespace {
this->visit_node_ptr(node.m_value);
}
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override
{
auto _ = push_usage( ::HIR::ValueUsage::Move );
-
+
for( auto& val : node.m_args )
this->visit_node_ptr(val);
}
void visit(::HIR::ExprNode_CallPath& node) override
{
auto _ = push_usage( ::HIR::ValueUsage::Move );
-
+
for( auto& val : node.m_args )
this->visit_node_ptr(val);
}
@@ -311,7 +311,7 @@ namespace {
auto _ = push_usage( vu );
this->visit_node_ptr(node.m_value);
}
-
+
auto _ = push_usage( ::HIR::ValueUsage::Move );
for( auto& val : node.m_args )
this->visit_node_ptr(val);
@@ -319,12 +319,12 @@ namespace {
void visit(::HIR::ExprNode_CallMethod& node) override
{
auto _ = push_usage( ::HIR::ValueUsage::Move );
-
+
this->visit_node_ptr(node.m_value);
for( auto& val : node.m_args )
this->visit_node_ptr(val);
}
-
+
void visit(::HIR::ExprNode_Literal& node) override
{
}
@@ -358,7 +358,7 @@ namespace {
unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == fld.first; }) - fields.begin();
provided_mask[idx] = true;
}
-
+
const auto monomorph_cb = monomorphise_type_get_cb(node.span(), nullptr, &node.m_path.m_params, nullptr);
for( unsigned int i = 0; i < fields.size(); i ++ ) {
if( ! provided_mask[i] ) {
@@ -372,12 +372,12 @@ namespace {
}
}
}
-
+
// If only Copy fields will be used, set usage to Borrow
auto _ = push_usage( is_moved ? ::HIR::ValueUsage::Move : ::HIR::ValueUsage::Borrow );
this->visit_node_ptr(node.m_base_value);
}
-
+
auto _ = push_usage( ::HIR::ValueUsage::Move );
for( auto& fld_val : node.m_values ) {
this->visit_node_ptr(fld_val.second);
@@ -407,13 +407,13 @@ namespace {
auto _ = push_usage( ::HIR::ValueUsage::Move );
this->visit_node_ptr(node.m_val);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
auto _ = push_usage( ::HIR::ValueUsage::Move );
this->visit_node_ptr(node.m_code);
}
-
+
private:
::HIR::ValueUsage get_usage_for_pattern_binding(const Span& sp, const ::HIR::PatternBinding& pb, const ::HIR::TypeRef& ty) const
{
@@ -431,13 +431,13 @@ namespace {
}
throw "";
}
-
+
::HIR::ValueUsage get_usage_for_pattern(const Span& sp, const ::HIR::Pattern& pat, const ::HIR::TypeRef& ty) const
{
if( pat.m_binding.is_valid() ) {
return get_usage_for_pattern_binding(sp, pat.m_binding, ty);
}
-
+
TU_MATCHA( (pat.m_data), (pe),
(Any,
return ::HIR::ValueUsage::Borrow;
@@ -477,7 +477,7 @@ namespace {
const auto& flds = str.m_data.as_Tuple();
assert(pe.sub_patterns.size() == flds.size());
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
-
+
auto rv = ::HIR::ValueUsage::Borrow;
for(unsigned int i = 0; i < flds.size(); i ++) {
auto sty = monomorphise_type_with(sp, flds[i].ent, monomorph_cb);
@@ -489,13 +489,13 @@ namespace {
const auto& str = *pe.binding;
const auto& flds = str.m_data.as_Named();
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
-
+
auto rv = ::HIR::ValueUsage::Borrow;
for(const auto& fld_pat : pe.sub_patterns)
{
auto fld_it = ::std::find_if(flds.begin(), flds.end(), [&](const auto& x){return x.first == fld_pat.first;});
ASSERT_BUG(sp, fld_it != flds.end(), "");
-
+
auto sty = monomorphise_type_with(sp, fld_it->second.ent, monomorph_cb);
rv = ::std::max(rv, get_usage_for_pattern(sp, fld_pat.second, sty));
}
@@ -516,7 +516,7 @@ namespace {
const auto& flds = var.second.as_Tuple();
assert(pe.sub_patterns.size() == flds.size());
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
-
+
auto rv = ::HIR::ValueUsage::Borrow;
for(unsigned int i = 0; i < flds.size(); i ++) {
auto sty = monomorphise_type_with(sp, flds[i].ent, monomorph_cb);
@@ -529,13 +529,13 @@ namespace {
const auto& var = enm.m_variants.at(pe.binding_idx);
const auto& flds = var.second.as_Struct();
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
-
+
auto rv = ::HIR::ValueUsage::Borrow;
for(const auto& fld_pat : pe.sub_patterns)
{
auto fld_it = ::std::find_if(flds.begin(), flds.end(), [&](const auto& x){return x.first == fld_pat.first;});
ASSERT_BUG(sp, fld_it != flds.end(), "");
-
+
auto sty = monomorphise_type_with(sp, fld_it->second.ent, monomorph_cb);
rv = ::std::max(rv, get_usage_for_pattern(sp, fld_pat.second, sty));
}
@@ -564,7 +564,7 @@ namespace {
}
};
-
+
class OuterVisitor:
public ::HIR::Visitor
{
@@ -573,7 +573,7 @@ namespace {
OuterVisitor(const ::HIR::Crate& crate):
m_resolve(crate)
{}
-
+
void visit_expr(::HIR::ExprPtr& exp) override {
if( exp )
{
@@ -581,7 +581,7 @@ namespace {
ev.visit_root( exp );
}
}
-
+
// ------
// Code-containing items
// ------
@@ -602,25 +602,25 @@ namespace {
auto _ = this->m_resolve.set_item_generics(item.m_params);
::HIR::Visitor::visit_enum(p, item);
}
-
-
+
+
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override {
auto _ = this->m_resolve.set_impl_generics(item.m_params);
::HIR::Visitor::visit_trait(p, item);
}
-
+
void visit_type_impl(::HIR::TypeImpl& impl) override
{
TRACE_FUNCTION_F("impl " << impl.m_type);
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_type_impl(impl);
}
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
{
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type);
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
}
};
diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp
index 71e6a8c2..51b99d5a 100644
--- a/src/hir_expand/closures.cpp
+++ b/src/hir_expand/closures.cpp
@@ -17,10 +17,10 @@ namespace {
#define NEWNODE(TY, CLASS, ...) mk_exprnodep(new HIR::ExprNode_##CLASS(__VA_ARGS__), TY)
namespace {
-
+
typedef ::std::function< ::HIR::SimplePath(::HIR::Struct )> new_type_cb_t;
typedef ::std::vector< ::std::pair< ::HIR::ExprNode_Closure::Class, ::HIR::TraitImpl> > out_impls_t;
-
+
template<typename K, typename V>
::std::map<K,V> make_map1(K k1, V v1) {
::std::map<K,V> rv;
@@ -44,7 +44,7 @@ namespace {
rv.push_back( mv$(v3) );
return rv;
}
-
+
/// Mutate the contents of a closure to update captures, variables, and types
class ExprVisitor_Mutate:
public ::HIR::ExprVisitorDef
@@ -52,10 +52,10 @@ namespace {
const ::HIR::TypeRef& m_closure_type;
const ::std::vector<unsigned int>& m_local_vars;
const ::std::vector< ::std::pair<unsigned int, ::HIR::ValueUsage> >& m_captures;
-
+
typedef ::std::function< const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_monomorph_cb;
t_monomorph_cb m_monomorph_cb;
-
+
::HIR::ExprNodeP m_replacement;
public:
ExprVisitor_Mutate(
@@ -71,7 +71,7 @@ namespace {
m_monomorph_cb(mcb)
{
}
-
+
void visit_pattern(const Span& sp, ::HIR::Pattern& pat) override {
if( pat.m_binding.is_valid() ) {
auto binding_it = ::std::find(m_local_vars.begin(), m_local_vars.end(), pat.m_binding.m_slot);
@@ -83,14 +83,14 @@ namespace {
BUG(sp, "Pattern binds to non-local");
}
}
-
+
TU_IFLET(::HIR::Pattern::Data, (pat.m_data), SplitSlice, e,
TODO(sp, "Fixup binding in split slice");
)
-
+
::HIR::ExprVisitorDef::visit_pattern(sp, pat);
}
-
+
void visit_type(::HIR::TypeRef& ty) override {
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
auto n = m_monomorph_cb(ty).clone();
@@ -101,24 +101,24 @@ namespace {
::HIR::ExprVisitorDef::visit_type(ty);
}
}
-
+
void visit_node_ptr(::HIR::ExprNodeP& node_ptr) override {
assert( node_ptr );
auto& node = *node_ptr;
const char* node_ty = typeid(node).name();
TRACE_FUNCTION_FR(&node << " " << node_ty << " : " << node.m_res_type, node_ty);
node.visit(*this);
-
+
if( m_replacement ) {
node_ptr = mv$(m_replacement);
}
-
+
visit_type( node_ptr->m_res_type );
}
void visit(::HIR::ExprNode_Closure& node) override
{
assert( ! node.m_code );
-
+
// Fix params in path
visit_generic_path( ::HIR::Visitor::PathContext::VALUE, node.m_obj_path );
// Visit captures
@@ -138,7 +138,7 @@ namespace {
return ;
}
}
-
+
// 2. Is it a capture?
{
auto binding_it = ::std::find_if(m_captures.begin(), m_captures.end(), [&](const auto& x){return x.first == node.m_slot;});
@@ -150,7 +150,7 @@ namespace {
);
if( binding_it->second != ::HIR::ValueUsage::Move ) {
auto bt = (binding_it->second == ::HIR::ValueUsage::Mutate ? ::HIR::BorrowType::Unique : ::HIR::BorrowType::Shared);
-
+
m_replacement->m_res_type = ::HIR::TypeRef::new_borrow( bt, mv$(m_replacement->m_res_type) );
m_replacement = NEWNODE(node.m_res_type.clone(), Deref, node.span(), mv$(m_replacement));
}
@@ -158,10 +158,10 @@ namespace {
return ;
}
}
-
+
BUG(node.span(), "Encountered non-captured and unknown-origin variable - " << node.m_name << " #" << node.m_slot);
}
-
+
::HIR::ExprNodeP get_self(const Span& sp) const
{
::HIR::ExprNodeP self;
@@ -187,7 +187,7 @@ namespace {
return self;
}
};
-
+
/// Visitor to replace closure types with actual type
class ExprVisitor_Fixup:
public ::HIR::ExprVisitorDef
@@ -200,7 +200,7 @@ namespace {
m_monomorph_cb( mv$(monomorph_cb) )
{
}
-
+
static void fix_type(const ::HIR::Crate& crate, t_cb_generic monomorph_cb, ::HIR::TypeRef& ty) {
TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Closure, e,
DEBUG("Closure: " << e.node->m_obj_path_base);
@@ -210,28 +210,28 @@ namespace {
ty = ::HIR::TypeRef::new_path( mv$(path), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) );
)
}
-
+
void visit_root(::HIR::ExprPtr& root)
{
TRACE_FUNCTION;
-
+
root->visit(*this);
visit_type(root->m_res_type);
-
+
DEBUG("Locals");
for(auto& ty : root.m_bindings)
visit_type(ty);
-
+
for(auto& ty : root.m_erased_types)
visit_type(ty);
}
-
+
void visit_node_ptr(::HIR::ExprNodeP& node) override
{
node->visit(*this);
visit_type(node->m_res_type);
}
-
+
void visit(::HIR::ExprNode_CallValue& node) override
{
TU_IFLET( ::HIR::TypeRef::Data, node.m_value->m_res_type.m_data, Closure, e,
@@ -251,17 +251,17 @@ namespace {
break;
}
)
-
+
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
fix_type(m_crate, m_monomorph_cb, ty);
::HIR::ExprVisitorDef::visit_type(ty);
}
};
-
+
struct H {
static void fix_fn_params(::HIR::ExprPtr& code, const ::HIR::TypeRef& self_ty, const ::HIR::TypeRef& args_ty)
{
@@ -390,7 +390,7 @@ namespace {
};
}
};
-
+
class ExprVisitor_Extract:
public ::HIR::ExprVisitorDef
{
@@ -399,13 +399,13 @@ namespace {
Mutate,
Move,
};
-
+
struct ClosureScope {
::HIR::ExprNode_Closure& node;
::std::vector<unsigned int> local_vars;
// - Lists captured variables to be stored in autogenerated struct (and how they're used, influencing the borrow type)
::std::vector< ::std::pair<unsigned int, ::HIR::ValueUsage> > captured_vars;
-
+
ClosureScope(::HIR::ExprNode_Closure& node):
node(node)
{
@@ -415,14 +415,14 @@ namespace {
const StaticTraitResolve& m_resolve;
const ::HIR::TypeRef* m_self_type;
::std::vector< ::HIR::TypeRef>& m_variable_types;
-
+
// Outputs
out_impls_t& m_out_impls;
const new_type_cb_t& m_new_type;
-
+
/// Stack of active closures
::std::vector<ClosureScope> m_closure_stack;
-
+
public:
ExprVisitor_Extract(const StaticTraitResolve& resolve, const ::HIR::TypeRef* self_type, ::std::vector< ::HIR::TypeRef>& var_types, out_impls_t& out_impls, const new_type_cb_t& new_type):
m_resolve(resolve),
@@ -432,30 +432,30 @@ namespace {
m_new_type( new_type )
{
}
-
+
void visit_root(::HIR::ExprNode& root)
{
root.visit(*this);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
const auto& sp = node.span();
-
+
TRACE_FUNCTION_F("Extract closure - " << node.m_res_type);
-
+
// --- Determine borrow set ---
m_closure_stack.push_back( ClosureScope(node) );
-
+
for(const auto& arg : node.m_args) {
add_closure_def_from_pattern(node.span(), arg.first);
}
-
+
::HIR::ExprVisitorDef::visit(node);
-
+
auto ent = mv$( m_closure_stack.back() );
m_closure_stack.pop_back();
-
+
// - If this closure is a move closure, mutate `captured_vars` such that all captures are tagged with ValueUsage::Move
if( node.m_is_move )
{
@@ -474,9 +474,9 @@ namespace {
}
}
-
+
// --- Extract and mutate code into a trait impl on the closure type ---
-
+
// 1. Construct closure type (saving path/index in the node)
::HIR::GenericParams params;
::HIR::PathParams constructor_path_params;
@@ -506,7 +506,7 @@ namespace {
params_placeholders.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) );
impl_path_params.m_types.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) );
}
-
+
auto monomorph_cb = [&](const auto& ty)->const auto& {
const auto& ge = ty.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
@@ -537,8 +537,8 @@ namespace {
}
//else if( tpl.m_data.is_ErasedType() ) {
// const auto& e = tpl.m_data.as_ErasedType();
- //
- // // TODO: Share code with
+ //
+ // // TODO: Share code with
// TODO(sp, "Repalce ErasedType with origin " << e.m_origin << " #" << e.m_index);
// //ASSERT_BUG(sp, e.m_index < fcn_ptr->m_code.m_erased_types.size(), "");
// //const auto& erased_type_replacement = fcn_ptr->m_code.m_erased_types.at(e.m_index);
@@ -549,7 +549,7 @@ namespace {
return false;
}
};
-
+
// - Clone the bounds (from both levels)
auto monomorph_bound = [&](const ::HIR::GenericBound& b)->auto {
TU_MATCHA( (b), (e),
@@ -570,13 +570,13 @@ namespace {
for(const auto& bound : m_resolve.item_generics().m_bounds ) {
params.m_bounds.push_back( monomorph_bound(bound) );
}
-
+
DEBUG("--- Mutate inner code");
// 2. Iterate over the nodes and rewrite variable accesses to either renumbered locals, or field accesses
ExprVisitor_Mutate ev { node.m_res_type, ent.local_vars, ent.captured_vars, monomorph_cb };
ev.visit_node_ptr( node.m_code );
// NOTE: `ev` is used down in `Args` to convert the argument destructuring pattern
-
+
// - Types of local variables
DEBUG("--- Build locals and captures");
::std::vector< ::HIR::TypeRef> local_types;
@@ -599,10 +599,10 @@ namespace {
const auto& cap_ty = m_variable_types.at(binding_idx);
auto ty_mono = monomorphise_type_with(sp, cap_ty, monomorph_cb);
-
+
auto val_node = NEWNODE(cap_ty.clone(), Variable, sp, "", binding_idx);
::HIR::BorrowType bt;
-
+
switch(binding_type)
{
case ::HIR::ValueUsage::Unknown:
@@ -624,7 +624,7 @@ namespace {
capture_nodes.push_back( mv$(val_node) );
break;
}
-
+
// - Fix type to replace closure types with known paths
ExprVisitor_Fixup fixup { m_resolve.m_crate, monomorph_cb };
fixup.visit_type(ty_mono);
@@ -638,7 +638,7 @@ namespace {
}
);
const auto& closure_struct_ref = m_resolve.m_crate.get_struct_by_path(sp, closure_struct_path);
-
+
// Mark the object pathname in the closure.
node.m_obj_path = ::HIR::GenericPath( closure_struct_path, mv$(constructor_path_params) );
node.m_obj_path_base = node.m_obj_path.clone();
@@ -647,11 +647,11 @@ namespace {
DEBUG("-- Object name: " << node.m_obj_path);
::HIR::TypeRef closure_type = ::HIR::TypeRef( ::HIR::GenericPath(node.m_obj_path.m_path.clone(), mv$(impl_path_params)) );
closure_type.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Struct({ &closure_struct_ref });
-
+
// - Args
::std::vector< ::HIR::Pattern> args_pat_inner;
::std::vector< ::HIR::TypeRef> args_ty_inner;
-
+
for(const auto& arg : node.m_args) {
args_pat_inner.push_back( arg.first.clone() );
ev.visit_pattern(sp, args_pat_inner.back() );
@@ -660,23 +660,23 @@ namespace {
::HIR::TypeRef args_ty { mv$(args_ty_inner) };
::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ mv$(args_pat_inner) }) };
::HIR::TypeRef ret_type = clone_ty_with(sp, node.m_return, cb_replace);
-
+
DEBUG("args_ty = " << args_ty << ", ret_type = " << ret_type);
-
+
::HIR::ExprPtr body_code { mv$(node.m_code) };
body_code.m_bindings = mv$(local_types);
-
+
{
DEBUG("-- Fixing types in body code");
ExprVisitor_Fixup fixup { m_resolve.m_crate, monomorph_cb };
fixup.visit_root( body_code );
-
+
DEBUG("-- Fixing types in signature");
fixup.visit_type( args_ty );
fixup.visit_type( ret_type );
// TODO: Replace erased types too
}
-
+
// ---
// 3. Create trait impls
// ---
@@ -690,7 +690,7 @@ namespace {
case ::HIR::ExprNode_Closure::Class::Shared: {
const auto& lang_Fn = m_resolve.m_crate.get_lang_item_path(node.span(), "fn");
const auto method_self_ty = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, closure_type.clone() );
-
+
// - FnOnce
{
auto dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp,
@@ -730,7 +730,7 @@ namespace {
H::make_fnmut( params.clone(), trait_params.clone(), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) )
));
}
-
+
// - Fn
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Shared,
@@ -740,7 +740,7 @@ namespace {
case ::HIR::ExprNode_Closure::Class::Mut: {
const auto& lang_FnMut = m_resolve.m_crate.get_lang_item_path(node.span(), "fn_mut");
const auto method_self_ty = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Unique, closure_type.clone() );
-
+
// - FnOnce
{
auto dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp,
@@ -760,7 +760,7 @@ namespace {
H::make_fnonce( params.clone(), trait_params.clone(), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) )
));
}
-
+
// - FnMut (code)
m_out_impls.push_back(::std::make_pair(
::HIR::ExprNode_Closure::Class::Mut,
@@ -776,7 +776,7 @@ namespace {
break;
}
}
-
+
void visit_pattern(const Span& sp, ::HIR::Pattern& pat) override
{
if( !m_closure_stack.empty() )
@@ -792,7 +792,7 @@ namespace {
}
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_CallValue& node) override
{
const auto& fcn_ty = node.m_value->m_res_type;
@@ -844,13 +844,13 @@ namespace {
::HIR::ExprVisitorDef::visit(node);
}
}
-
+
private:
void add_closure_def(unsigned int slot)
{
assert(m_closure_stack.size() > 0);
auto& closure_defs = m_closure_stack.back().local_vars;
-
+
auto it = ::std::lower_bound(closure_defs.begin(), closure_defs.end(), slot);
if( it == closure_defs.end() || *it != slot ) {
closure_defs.insert(it, slot);
@@ -863,7 +863,7 @@ namespace {
const auto& pb = pat.m_binding;
add_closure_def(pb.m_slot);
}
-
+
// Recurse
TU_MATCH(::HIR::Pattern::Data, (pat.m_data), (e),
(Any,
@@ -901,7 +901,7 @@ namespace {
add_closure_def(e.extra_bind.m_slot);
}
),
-
+
// - Enums/Structs
(StructValue,
),
@@ -937,7 +937,7 @@ namespace {
return ;
}
-
+
if( usage == ::HIR::ValueUsage::Move ) {
if( m_resolve.type_is_copy(sp, m_variable_types.at(slot)) ) {
usage = ::HIR::ValueUsage::Borrow;
@@ -948,11 +948,11 @@ namespace {
else {
}
}
-
+
assert(m_closure_stack.size() > 0 );
auto& closure_rec = m_closure_stack.back();
auto& closure = closure_rec.node;
-
+
auto it = ::std::lower_bound(closure_rec.captured_vars.begin(), closure_rec.captured_vars.end(), slot, [](const auto& a, const auto& b){ return a.first < b; });
if( it == closure_rec.captured_vars.end() || it->first != slot ) {
closure_rec.captured_vars.insert( it, ::std::make_pair(slot, usage) );
@@ -960,7 +960,7 @@ namespace {
else {
it->second = ::std::max(it->second, usage);
}
-
+
const char* cap_type_name = "?";
switch( usage )
{
@@ -987,7 +987,7 @@ namespace {
DEBUG("Captured " << slot << " - " << m_variable_types.at(slot) << " :: " << cap_type_name);
}
};
-
+
class OuterVisitor:
public ::HIR::Visitor
{
@@ -1001,11 +1001,11 @@ namespace {
m_resolve(crate),
m_cur_mod_path( nullptr )
{}
-
+
void visit_crate(::HIR::Crate& crate) override
{
Span sp;
-
+
unsigned int closure_count = 0;
::HIR::SimplePath root_mod_path("",{});
m_cur_mod_path = &root_mod_path;
@@ -1016,9 +1016,9 @@ namespace {
crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) );
return ::HIR::SimplePath() + name;
};
-
+
::HIR::Visitor::visit_crate(crate);
-
+
for(auto& impl : m_new_trait_impls)
{
const auto& trait =
@@ -1030,13 +1030,13 @@ namespace {
}
m_new_trait_impls.resize(0);
}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
auto saved = m_cur_mod_path;
auto path = p.get_simple_path();
m_cur_mod_path = &path;
-
+
unsigned int closure_count = 0;
auto saved_nt = mv$(m_new_type);
m_new_type = [&](auto s)->auto {
@@ -1046,18 +1046,18 @@ namespace {
mod.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) );
return (p + name).get_simple_path();
};
-
+
::HIR::Visitor::visit_module(p, mod);
-
+
m_cur_mod_path = saved;
m_new_type = mv$(saved_nt);
}
-
+
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
void visit_expr(::HIR::ExprPtr& exp) override {
BUG(Span(), "visit_expr hit in OuterVisitor");
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
@@ -1083,12 +1083,12 @@ namespace {
{
assert( m_cur_mod_path );
DEBUG("Function code " << p);
-
+
{
ExprVisitor_Extract ev(m_resolve, m_self_type, item.m_code.m_bindings, m_new_trait_impls, m_new_type);
ev.visit_root( *item.m_code );
}
-
+
{
ExprVisitor_Fixup fixup(m_resolve.m_crate, [](const auto& x)->const auto&{ return x; });
fixup.visit_root( item.m_code );
@@ -1129,7 +1129,7 @@ namespace {
)
}
}
-
+
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override
{
auto _ = this->m_resolve.set_impl_generics(item.m_params);
@@ -1138,16 +1138,16 @@ namespace {
::HIR::Visitor::visit_trait(p, item);
m_self_type = nullptr;
}
-
-
+
+
void visit_type_impl(::HIR::TypeImpl& impl) override
{
TRACE_FUNCTION_F("impl " << impl.m_type);
m_self_type = &impl.m_type;
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_type_impl(impl);
-
+
m_self_type = nullptr;
}
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
@@ -1155,9 +1155,9 @@ namespace {
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type);
m_self_type = &impl.m_type;
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
-
+
m_self_type = nullptr;
}
};
diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp
index f385c816..85fdd112 100644
--- a/src/hir_expand/const_eval_full.cpp
+++ b/src/hir_expand/const_eval_full.cpp
@@ -16,13 +16,13 @@
namespace {
typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values;
-
+
struct NewvalState {
t_new_values& newval_output;
const ::HIR::ItemPath& mod_path;
::std::string name_prefix;
unsigned int next_item_idx;
-
+
NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix):
newval_output(newval_output),
mod_path(mod_path),
@@ -30,7 +30,7 @@ namespace {
next_item_idx(0)
{
}
-
+
::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value)
{
auto name = FMT(name_prefix << next_item_idx);
@@ -46,9 +46,9 @@ namespace {
return rv;
}
};
-
+
::HIR::Literal evaluate_constant(const Span& sp, const ::StaticTraitResolve& resolve, NewvalState newval_state, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args);
-
+
::HIR::Literal clone_literal(const ::HIR::Literal& v)
{
TU_MATCH(::HIR::Literal, (v), (e),
@@ -84,7 +84,7 @@ namespace {
)
throw "";
}
-
+
void monomorph_literal_inplace(const Span& sp, ::HIR::Literal& lit, const MonomorphState& ms)
{
TU_MATCH(::HIR::Literal, (lit), (e),
@@ -113,7 +113,7 @@ namespace {
)
)
}
-
+
TAGGED_UNION(EntPtr, NotFound,
(NotFound, struct{}),
(Function, const ::HIR::Function*),
@@ -135,7 +135,7 @@ namespace {
else {
mod = &crate.m_root_module;
}
-
+
for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
{
const auto& pc = path.m_components[i];
@@ -152,7 +152,7 @@ namespace {
)
)
}
-
+
switch( ns )
{
case EntNS::Value: {
@@ -160,7 +160,7 @@ namespace {
if( it == mod->m_value_items.end() ) {
return EntPtr {};
}
-
+
TU_MATCH( ::HIR::ValueItem, (it->second->ent), (e),
(Import,
),
@@ -185,7 +185,7 @@ namespace {
if( it == mod->m_mod_items.end() ) {
return EntPtr {};
}
-
+
TU_MATCH( ::HIR::TypeItem, (it->second->ent), (e),
(Import,
),
@@ -305,19 +305,19 @@ namespace {
TODO(sp, "Could not find function for " << path << " - " << rv.tag_str());
}
}
-
+
::HIR::Literal evaluate_constant_mir(const Span& sp, const StaticTraitResolve& resolve, NewvalState newval_state, const ::MIR::Function& fcn, MonomorphState ms, ::std::vector< ::HIR::Literal> args)
{
TRACE_FUNCTION;
-
+
::MIR::TypeResolve state { sp, resolve, FMT_CB(), ::HIR::TypeRef(), {}, fcn };
-
+
::HIR::Literal retval;
::std::vector< ::HIR::Literal> locals;
::std::vector< ::HIR::Literal> temps;
locals.resize( fcn.named_variables.size() );
temps.resize( fcn.temporaries.size() );
-
+
struct LocalState {
typedef ::std::vector< ::HIR::Literal> t_vec_lit;
::MIR::TypeResolve& state;
@@ -325,7 +325,7 @@ namespace {
::std::vector< ::HIR::Literal>& locals;
::std::vector< ::HIR::Literal>& temps;
::std::vector< ::HIR::Literal>& args;
-
+
LocalState(::MIR::TypeResolve& state, ::HIR::Literal& retval, t_vec_lit& locals, t_vec_lit& temps, t_vec_lit& args):
state(state),
retval(retval),
@@ -333,7 +333,7 @@ namespace {
temps(temps),
args(args)
{}
-
+
::HIR::Literal& get_lval(const ::MIR::LValue& lv)
{
TU_MATCHA( (lv), (e),
@@ -377,7 +377,7 @@ namespace {
}
};
LocalState local_state( state, retval, locals, temps, args );
-
+
auto get_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal& { return local_state.get_lval(lv); };
auto read_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal {
auto& v = get_lval(lv);
@@ -399,7 +399,7 @@ namespace {
)
)
};
-
+
unsigned int cur_block = 0;
for(;;)
{
@@ -408,13 +408,13 @@ namespace {
for(const auto& stmt : block.statements)
{
state.set_cur_stmt(cur_block, next_stmt_idx++);
-
+
if( ! stmt.is_Assign() ) {
//BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot);
continue ;
}
const auto& sa = stmt.as_Assign();
-
+
DEBUG(sa.dst << " = " << sa.src);
::HIR::Literal val;
TU_MATCHA( (sa.src), (e),
@@ -474,19 +474,19 @@ namespace {
if( e.type != ::HIR::BorrowType::Shared ) {
MIR_BUG(state, "Only shared borrows are allowed in constants");
}
-
+
if( e.val.is_Static() ) {
// Borrow of a static, emit BorrowOf with the same path
val = ::HIR::Literal::make_BorrowOf( e.val.as_Static().clone() );
}
else {
auto inner_val = read_lval(e.val);
-
+
::HIR::TypeRef inner_ty;
const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val);
if( &inner_ty_r != &inner_ty )
inner_ty = inner_ty_r.clone();
-
+
// Create new static containing borrowed data
auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) );
val = ::HIR::Literal::make_BorrowOf( mv$(item_path) );
@@ -527,12 +527,12 @@ namespace {
case ::HIR::CoreType::U16: val = cast_to_int(false, 16); break;
case ::HIR::CoreType::I32: val = cast_to_int(true , 32); break;
case ::HIR::CoreType::U32: val = cast_to_int(false, 32); break;
-
+
case ::HIR::CoreType::I64: val = cast_to_int(true , 64); break;
case ::HIR::CoreType::U64: val = cast_to_int(false, 64); break;
case ::HIR::CoreType::Isize: val = cast_to_int(true , 64); break;
case ::HIR::CoreType::Usize: val = cast_to_int(false, 64); break;
-
+
case ::HIR::CoreType::F32:
case ::HIR::CoreType::F64:
TU_IFLET( ::HIR::Literal, inval, Integer, i,
@@ -584,7 +584,7 @@ namespace {
case ::MIR::eBinOp::MUL_OV:
case ::MIR::eBinOp::DIV_OV:
TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
-
+
case ::MIR::eBinOp::BIT_OR :
case ::MIR::eBinOp::BIT_AND:
case ::MIR::eBinOp::BIT_XOR:
@@ -613,7 +613,7 @@ namespace {
case ::MIR::eBinOp::MUL_OV:
case ::MIR::eBinOp::DIV_OV:
TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
-
+
case ::MIR::eBinOp::BIT_OR : val = ::HIR::Literal( l | r ); break;
case ::MIR::eBinOp::BIT_AND: val = ::HIR::Literal( l & r ); break;
case ::MIR::eBinOp::BIT_XOR: val = ::HIR::Literal( l ^ r ); break;
@@ -702,7 +702,7 @@ namespace {
val = ::HIR::Literal::make_Variant({ e.variant_idx, mv$(vals) });
)
)
-
+
auto& dst = get_lval(sa.dst);
DEBUG("= " << val);
dst = mv$(val);
@@ -728,26 +728,26 @@ namespace {
auto& dst = get_lval(e.ret_val);
MonomorphState fcn_ms;
auto& fcn = get_function(sp, resolve.m_crate, fcnp, fcn_ms);
-
+
::std::vector< ::HIR::Literal> call_args;
call_args.reserve( e.args.size() );
for(const auto& a : e.args)
call_args.push_back( read_lval(a) );
// TODO: Set m_const during parse and check here
-
+
// Call by invoking evaluate_constant on the function
{
TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }");
dst = evaluate_constant(sp, resolve, newval_state, fcn.m_code, fcn_ms, mv$(call_args));
}
-
+
DEBUG("= " << dst);
cur_block = e.ret_block;
)
)
}
}
-
+
::HIR::Literal evaluate_constant(const Span& sp, const StaticTraitResolve& resolve, NewvalState newval_state, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args)
{
if( expr.m_mir ) {
@@ -757,7 +757,7 @@ namespace {
BUG(sp, "Attempting to evaluate constant expression with no associated code");
}
}
-
+
void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit)
{
// TODO: Mask down limited size integers
@@ -776,7 +776,7 @@ namespace {
),
(Closure,
),
-
+
(Path,
// List
),
@@ -786,7 +786,7 @@ namespace {
(Tuple,
// List
),
-
+
(Borrow,
// A whole host of things
),
@@ -796,7 +796,7 @@ namespace {
(Function,
// ItemAddr
),
-
+
(Primitive,
switch(te)
{
@@ -813,7 +813,7 @@ namespace {
case ::HIR::CoreType::U8: lit.as_Integer() &= (1ull<<8)-1; break;
case ::HIR::CoreType::U16: lit.as_Integer() &= (1ull<<16)-1; break;
case ::HIR::CoreType::U32: lit.as_Integer() &= (1ull<<32)-1; break;
-
+
//case ::HIR::CoreType::I8: lit.as_Integer() &= (1ull<<8)-1; break;
//case ::HIR::CoreType::I16: lit.as_Integer() &= (1ull<<16)-1; break;
//case ::HIR::CoreType::I32: lit.as_Integer() &= (1ull<<32)-1; break;
@@ -831,7 +831,7 @@ namespace {
{
const ::HIR::Crate& m_crate;
StaticTraitResolve m_resolve;
-
+
const ::HIR::ItemPath* m_mod_path;
t_new_values m_new_values;
@@ -840,15 +840,15 @@ namespace {
m_crate(crate),
m_resolve(crate)
{}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
auto saved_mp = m_mod_path;
m_mod_path = &p;
auto saved = mv$( m_new_values );
-
+
::HIR::Visitor::visit_module(p, mod);
-
+
for( auto& item : m_new_values )
{
auto boxed_ent = box$(::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem(mv$(item.second)) });
@@ -865,11 +865,11 @@ namespace {
m_new_values = mv$(saved);
m_mod_path = saved_mp;
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
::HIR::Visitor::visit_type(ty);
-
+
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
assert( e.size_val != ~0u );
)
@@ -881,7 +881,7 @@ namespace {
{
auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") };
item.m_value_res = evaluate_constant(item.m_value->span(), m_resolve, nvs, item.m_value, {}, {});
-
+
check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
visit_expr(item.m_value);
diff --git a/src/hir_expand/erased_types.cpp b/src/hir_expand/erased_types.cpp
index 5cbb9726..44bb17de 100644
--- a/src/hir_expand/erased_types.cpp
+++ b/src/hir_expand/erased_types.cpp
@@ -52,7 +52,7 @@ const ::HIR::Function& HIR_Expand_ErasedType_GetFunction(const Span& sp, const S
for(const auto& t : impl_params.m_types)
if( t == ::HIR::TypeRef() )
TODO(sp, "Handle ErasedType where an impl parameter comes from a bound - " << origin_path);
-
+
monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &impl_params, &pe.params);
)
)
@@ -61,19 +61,19 @@ const ::HIR::Function& HIR_Expand_ErasedType_GetFunction(const Span& sp, const S
}
namespace {
-
-
+
+
class ExprVisitor_Extract:
public ::HIR::ExprVisitorDef
{
const StaticTraitResolve& m_resolve;
-
+
public:
ExprVisitor_Extract(const StaticTraitResolve& resolve):
m_resolve(resolve)
{
}
-
+
void visit_root(::HIR::ExprPtr& root)
{
root->visit(*this);
@@ -83,31 +83,31 @@ namespace {
for(auto& ty : root.m_erased_types)
visit_type(ty);
}
-
+
void visit_node_ptr(::std::unique_ptr< ::HIR::ExprNode>& node_ptr) override {
assert(node_ptr);
node_ptr->visit(*this);
visit_type(node_ptr->m_res_type);
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
static Span sp;
-
+
if( ty.m_data.is_ErasedType() )
{
TRACE_FUNCTION_FR(ty, ty);
-
+
const auto& e = ty.m_data.as_ErasedType();
-
+
::HIR::PathParams impl_params; // cache.
t_cb_generic monomorph_cb;
const auto& fcn = HIR_Expand_ErasedType_GetFunction(sp, m_resolve, e.m_origin, monomorph_cb, impl_params);
const auto& erased_types = fcn.m_code.m_erased_types;
-
+
ASSERT_BUG(sp, e.m_index < erased_types.size(), "Erased type index out of range for " << e.m_origin << " - " << e.m_index << " >= " << erased_types.size());
const auto& tpl = erased_types[e.m_index];
-
+
auto new_ty = monomorphise_type_with(sp, tpl, monomorph_cb);
DEBUG("> " << ty << " => " << new_ty);
ty = mv$(new_ty);
@@ -120,7 +120,7 @@ namespace {
}
}
};
-
+
class OuterVisitor:
public ::HIR::Visitor
{
@@ -130,7 +130,7 @@ namespace {
OuterVisitor(const ::HIR::Crate& crate):
m_resolve(crate)
{}
-
+
void visit_expr(::HIR::ExprPtr& exp) override
{
if( exp )
@@ -139,23 +139,23 @@ namespace {
ev.visit_root( exp );
}
}
-
+
void visit_function(::HIR::ItemPath p, ::HIR::Function& fcn) override
{
m_fcn_path = p;
::HIR::Visitor::visit_function(p, fcn);
m_fcn_path = ::HIR::ItemPath();
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
static const Span sp;
if( ty.m_data.is_ErasedType() )
{
ASSERT_BUG(sp, m_fcn_path.get_name(), "");
-
+
const auto& e = ty.m_data.as_ErasedType();
-
+
TU_MATCHA( (e.m_origin.m_data), (pe),
(Generic,
if( m_fcn_path == pe.m_path ) {
@@ -176,17 +176,17 @@ namespace {
}
)
)
-
+
TRACE_FUNCTION_FR(ty, ty);
-
+
::HIR::PathParams impl_params;
t_cb_generic monomorph_cb;
const auto& fcn = HIR_Expand_ErasedType_GetFunction(sp, m_resolve, e.m_origin, monomorph_cb, impl_params);
const auto& erased_types = fcn.m_code.m_erased_types;
-
+
ASSERT_BUG(sp, e.m_index < erased_types.size(), "Erased type index out of range for " << e.m_origin << " - " << e.m_index << " >= " << erased_types.size());
const auto& tpl = erased_types[e.m_index];
-
+
auto new_ty = monomorphise_type_with(sp, tpl, monomorph_cb);
DEBUG("> " << ty << " => " << new_ty);
ty = mv$(new_ty);
diff --git a/src/hir_expand/reborrow.cpp b/src/hir_expand/reborrow.cpp
index 8395f340..688dcf97 100644
--- a/src/hir_expand/reborrow.cpp
+++ b/src/hir_expand/reborrow.cpp
@@ -17,12 +17,12 @@ namespace {
#define NEWNODE(TY, CLASS, ...) mk_exprnodep(new HIR::ExprNode_##CLASS(__VA_ARGS__), TY)
namespace {
-
+
class ExprVisitor_Mutate:
public ::HIR::ExprVisitorDef
{
const ::HIR::Crate& m_crate;
-
+
public:
ExprVisitor_Mutate(const ::HIR::Crate& crate):
m_crate(crate)
@@ -32,9 +32,9 @@ namespace {
const auto& node_ref = *root;
const char* node_ty = typeid(node_ref).name();
TRACE_FUNCTION_FR(&*root << " " << node_ty << " : " << root->m_res_type, node_ty);
-
+
root->visit(*this);
-
+
// 1. Convert into an ExprNodeP
auto np = root.into_unique();
// 2. Pass to do_reborrow
@@ -42,7 +42,7 @@ namespace {
// 3. Convert back
root.reset( np.release() );
}
-
+
void visit_node_ptr(::HIR::ExprNodeP& node) override {
const auto& node_ref = *node;
const char* node_ty = typeid(node_ref).name();
@@ -50,7 +50,7 @@ namespace {
assert( node );
node->visit(*this);
}
-
+
::HIR::ExprNodeP do_reborrow(::HIR::ExprNodeP node_ptr)
{
TU_IFLET( ::HIR::TypeRef::Data, node_ptr->m_res_type.m_data, Borrow, e,
@@ -86,7 +86,7 @@ namespace {
)
return node_ptr;
}
-
+
void visit(::HIR::ExprNode_Assign& node) override {
::HIR::ExprVisitorDef::visit(node);
node.m_value = do_reborrow(mv$(node.m_value));
@@ -109,7 +109,7 @@ namespace {
arg = do_reborrow(mv$(arg));
}
}
-
+
void visit(::HIR::ExprNode_ArrayList& node) override {
::HIR::ExprVisitorDef::visit(node);
for(auto& arg : node.m_vals) {
@@ -154,12 +154,12 @@ namespace {
m_crate(crate)
{
}
-
+
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
void visit_expr(::HIR::ExprPtr& exp) override {
BUG(Span(), "visit_expr hit in OuterVisitor");
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
@@ -209,7 +209,7 @@ namespace {
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
DEBUG("Enum value " << p << " - " << var.first);
-
+
ExprVisitor_Mutate ev(m_crate);
ev.visit_node_ptr(e.expr);
)
diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp
index daba3e6a..0562c418 100644
--- a/src/hir_expand/ufcs_everything.cpp
+++ b/src/hir_expand/ufcs_everything.cpp
@@ -18,14 +18,14 @@ namespace {
#define NEWNODE(TY, CLASS, ...) mk_exprnodep(new HIR::ExprNode_##CLASS(__VA_ARGS__), TY)
namespace {
-
+
class ExprVisitor_Mutate:
public ::HIR::ExprVisitorDef
{
const ::HIR::Crate& m_crate;
::HIR::ExprNodeP m_replacement;
::HIR::SimplePath m_lang_Box;
-
+
public:
ExprVisitor_Mutate(const ::HIR::Crate& crate):
m_crate(crate)
@@ -47,7 +47,7 @@ namespace {
root->m_usage = usage;
}
}
-
+
void visit_node_ptr(::HIR::ExprNodeP& node) override {
const auto& node_ref = *node;
const char* node_ty = typeid(node_ref).name();
@@ -62,7 +62,7 @@ namespace {
node->m_usage = usage;
}
}
-
+
// ----------
// _CallValue
// ----------
@@ -70,15 +70,15 @@ namespace {
void visit(::HIR::ExprNode_CallValue& node) override
{
const auto& sp = node.span();
-
+
::HIR::ExprVisitorDef::visit(node);
const auto& ty_val = node.m_value->m_res_type;
-
+
// Calling a `fn` type should be kept as a _CallValue
if( ty_val.m_data.is_Function() ) {
return ;
}
-
+
// 1. Construct tuple type containing argument types for `Args`
::HIR::TypeRef arg_tup_type;
{
@@ -90,7 +90,7 @@ namespace {
// - Make the trait arguments.
::HIR::PathParams trait_args;
trait_args.m_types.push_back( arg_tup_type.clone() );
-
+
// - If the called value is a local closure, figure out how it's being used.
// TODO: You can call via &-ptrs, but that currently isn't handled in typeck
TU_IFLET(::HIR::TypeRef::Data, node.m_value->m_res_type.m_data, Closure, e,
@@ -114,7 +114,7 @@ namespace {
}
}
)
-
+
// Use marking in node to determine trait to use
::HIR::TypeRef self_arg_type;
::HIR::Path method_path(::HIR::SimplePath{});
@@ -147,32 +147,32 @@ namespace {
"call_once"
);
break;
-
+
//case ::HIR::ExprNode_CallValue::TraitUsed::Unknown:
default:
BUG(node.span(), "Encountered CallValue with TraitUsed::Unknown, ty=" << node.m_value->m_res_type);
}
assert(self_arg_type != ::HIR::TypeRef());
-
-
+
+
// Construct argument list for the output
::std::vector< ::HIR::ExprNodeP> args;
args.reserve( 2 );
args.push_back( mv$(node.m_value) );
args.push_back(NEWNODE( arg_tup_type.clone(), Tuple, sp, mv$(node.m_args) ));
-
+
m_replacement = NEWNODE(mv$(node.m_res_type), CallPath, sp,
mv$(method_path),
mv$(args)
);
-
+
// Populate the cache for later passes
auto& arg_types = dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache.m_arg_types;
arg_types.push_back( mv$(self_arg_type) );
arg_types.push_back( mv$(arg_tup_type) );
arg_types.push_back( m_replacement->m_res_type.clone() );
}
-
+
// ----------
// _CallMethod
// ----------
@@ -180,15 +180,15 @@ namespace {
void visit(::HIR::ExprNode_CallMethod& node) override
{
const auto& sp = node.span();
-
+
::HIR::ExprVisitorDef::visit(node);
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.reserve( 1 + node.m_args.size() );
args.push_back( mv$(node.m_value) );
for(auto& arg : node.m_args)
args.push_back( mv$(arg) );
-
+
// Replace using known function path
m_replacement = NEWNODE(mv$(node.m_res_type), CallPath, sp,
mv$(node.m_method_path),
@@ -197,8 +197,8 @@ namespace {
// Populate the cache for later passes
dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache = mv$(node.m_cache);
}
-
-
+
+
static bool is_op_valid_shift(const ::HIR::TypeRef& ty_l, const ::HIR::TypeRef& ty_r)
{
// Integer with any other integer is valid, others go to overload resolution
@@ -226,7 +226,7 @@ namespace {
}
break;
}
-
+
}
return false;
}
@@ -267,7 +267,7 @@ namespace {
}
return false;
}
-
+
// -------
// _Assign
// -------
@@ -276,10 +276,10 @@ namespace {
{
const auto& sp = node.span();
::HIR::ExprVisitorDef::visit(node);
-
+
const auto& ty_slot = node.m_slot->m_res_type;
const auto& ty_val = node.m_value->m_res_type;
-
+
const char* langitem = nullptr;
const char* opname = nullptr;
#define _(opname) case ::HIR::ExprNode_Assign::Op::opname
@@ -295,7 +295,7 @@ namespace {
return ;
}
break;
-
+
_(And): {langitem = "bitand_assign"; opname = "bitand_assign"; } if(0)
_(Or ): {langitem = "bitor_assign" ; opname = "bitor_assign" ; } if(0)
_(Xor): {langitem = "bitxor_assign"; opname = "bitxor_assign"; } if(0)
@@ -320,12 +320,12 @@ namespace {
#undef _
assert( langitem );
assert( opname );
-
+
// Needs replacement, continue
::HIR::PathParams trait_params;
trait_params.m_types.push_back( ty_val.clone() );
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), mv$(trait_params) };
-
+
auto slot_type_refmut = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, ty_slot.clone());
::std::vector< ::HIR::ExprNodeP> args;
args.push_back(NEWNODE( slot_type_refmut.clone(), Borrow, sp, ::HIR::BorrowType::Unique, mv$(node.m_slot) ));
@@ -334,22 +334,22 @@ namespace {
::HIR::Path(ty_slot.clone(), mv$(trait), opname),
mv$(args)
);
-
+
// Populate the cache for later passes
auto& arg_types = dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache.m_arg_types;
arg_types.push_back( mv$(slot_type_refmut) );
arg_types.push_back( ty_val.clone() );
arg_types.push_back( ::HIR::TypeRef::new_unit() );
}
-
+
void visit(::HIR::ExprNode_BinOp& node) override
{
const auto& sp = node.span();
::HIR::ExprVisitorDef::visit(node);
-
+
const auto& ty_l = node.m_left->m_res_type;
const auto& ty_r = node.m_right->m_res_type;
-
+
const char* langitem = nullptr;
const char* method = nullptr;
switch(node.m_op)
@@ -383,19 +383,19 @@ namespace {
::HIR::PathParams trait_params;
trait_params.m_types.push_back( ty_r.clone() );
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), mv$(trait_params) };
-
+
auto ty_l_ref = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ty_l.clone() );
auto ty_r_ref = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ty_r.clone() );
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.push_back(NEWNODE(ty_l_ref.clone(), Borrow, node.m_left ->span(), ::HIR::BorrowType::Shared, mv$(node.m_left ) ));
args.push_back(NEWNODE(ty_r_ref.clone(), Borrow, node.m_right->span(), ::HIR::BorrowType::Shared, mv$(node.m_right) ));
-
+
m_replacement = NEWNODE(mv$(node.m_res_type), CallPath, sp,
::HIR::Path(ty_l.clone(), mv$(trait), method),
mv$(args)
);
-
+
// Populate the cache for later passes
auto& arg_types = dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache.m_arg_types;
arg_types.push_back( mv$(ty_l_ref) );
@@ -403,7 +403,7 @@ namespace {
arg_types.push_back( ::HIR::TypeRef( ::HIR::CoreType::Bool ) );
return ;
} break;
-
+
case ::HIR::ExprNode_BinOp::Op::Xor: langitem = method = "bitxor"; if(0)
case ::HIR::ExprNode_BinOp::Op::Or : langitem = method = "bitor" ; if(0)
case ::HIR::ExprNode_BinOp::Op::And: langitem = method = "bitand"; if(0)
@@ -412,14 +412,14 @@ namespace {
return ;
}
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Shr: langitem = method = "shr"; if(0)
case ::HIR::ExprNode_BinOp::Op::Shl: langitem = method = "shr";
if( is_op_valid_shift(ty_l, ty_r) ) {
return ;
}
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Add: langitem = method = "add"; if(0)
case ::HIR::ExprNode_BinOp::Op::Sub: langitem = method = "sub"; if(0)
case ::HIR::ExprNode_BinOp::Op::Mul: langitem = method = "mul"; if(0)
@@ -429,7 +429,7 @@ namespace {
return ;
}
break;
-
+
case ::HIR::ExprNode_BinOp::Op::BoolAnd:
case ::HIR::ExprNode_BinOp::Op::BoolOr:
ASSERT_BUG(sp, ty_l == ::HIR::TypeRef(::HIR::CoreType::Bool), "&& operator requires bool");
@@ -438,35 +438,35 @@ namespace {
}
assert(langitem);
assert(method);
-
+
// Needs replacement, continue
::HIR::PathParams trait_params;
trait_params.m_types.push_back( ty_r.clone() );
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), mv$(trait_params) };
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.push_back( mv$(node.m_left) );
args.push_back( mv$(node.m_right) );
-
+
m_replacement = NEWNODE(mv$(node.m_res_type), CallPath, sp,
::HIR::Path(ty_l.clone(), mv$(trait), method),
mv$(args)
);
-
+
// Populate the cache for later passes
auto& arg_types = dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache.m_arg_types;
arg_types.push_back( ty_l.clone() );
arg_types.push_back( ty_r.clone() );
arg_types.push_back( m_replacement->m_res_type.clone() );
}
-
+
void visit(::HIR::ExprNode_UniOp& node) override
{
const auto& sp = node.span();
::HIR::ExprVisitorDef::visit(node);
-
+
const auto& ty_val = node.m_value->m_res_type;
-
+
const char* langitem = nullptr;
const char* method = nullptr;
switch(node.m_op)
@@ -518,33 +518,33 @@ namespace {
}
assert(langitem);
assert(method);
-
+
// Needs replacement, continue
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), {} };
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.push_back( mv$(node.m_value) );
-
+
m_replacement = NEWNODE(mv$(node.m_res_type), CallPath, sp,
::HIR::Path(ty_val.clone(), mv$(trait), method),
mv$(args)
);
-
+
// Populate the cache for later passes
auto& arg_types = dynamic_cast< ::HIR::ExprNode_CallPath&>(*m_replacement).m_cache.m_arg_types;
arg_types.push_back( ty_val.clone() );
arg_types.push_back( m_replacement->m_res_type.clone() );
}
-
-
+
+
void visit(::HIR::ExprNode_Index& node) override
{
const auto& sp = node.span();
::HIR::ExprVisitorDef::visit(node);
-
+
const auto& ty_idx = node.m_index->m_res_type;
const auto& ty_val = node.m_value->m_res_type;
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_val.m_data), (val_te),
(
// Unknown? fall down to the method call
@@ -564,7 +564,7 @@ namespace {
// Any other index type goes to the function call
)
)
-
+
// TODO: Which trait should be used?
const char* langitem = nullptr;
const char* method = nullptr;
@@ -589,16 +589,16 @@ namespace {
// Needs replacement, continue
assert(langitem);
assert(method);
-
+
// - Construct trait path - Index*<IdxTy>
::HIR::PathParams pp;
pp.m_types.push_back( ty_idx.clone() );
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), mv$(pp) };
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.push_back( NEWNODE( ::HIR::TypeRef::new_borrow(bt, ty_val.clone()), Borrow, sp, bt, mv$(node.m_value) ) );
args.push_back( mv$(node.m_index) );
-
+
m_replacement = NEWNODE( ::HIR::TypeRef::new_borrow(bt, node.m_res_type.clone()), CallPath, sp,
::HIR::Path(ty_val.clone(), mv$(trait), method),
mv$(args)
@@ -610,19 +610,19 @@ namespace {
arg_types.push_back( ::HIR::TypeRef::new_borrow(bt, ty_val.clone()) );
arg_types.push_back( ty_idx.clone() );
arg_types.push_back( m_replacement->m_res_type.clone() );
-
+
// - Dereference the result (which is an &-ptr)
m_replacement = NEWNODE( mv$(node.m_res_type), Deref, sp, mv$(m_replacement) );
}
-
+
void visit(::HIR::ExprNode_Deref& node) override
{
const auto& sp = node.span();
-
+
::HIR::ExprVisitorDef::visit(node);
-
+
const auto& ty_val = node.m_value->m_res_type;
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_val.m_data), (e),
(
BUG(sp, "Deref on unexpected type - " << ty_val);
@@ -647,7 +647,7 @@ namespace {
return ;
)
)
-
+
const char* langitem = nullptr;
const char* method = nullptr;
::HIR::BorrowType bt;
@@ -672,13 +672,13 @@ namespace {
// Needs replacement, continue
assert(langitem);
assert(method);
-
+
// - Construct trait path - Index*<IdxTy>
::HIR::GenericPath trait { m_crate.get_lang_item_path(node.span(), langitem), {} };
-
+
::std::vector< ::HIR::ExprNodeP> args;
args.push_back( NEWNODE( ::HIR::TypeRef::new_borrow(bt, ty_val.clone()), Borrow, sp, bt, mv$(node.m_value) ) );
-
+
m_replacement = NEWNODE( ::HIR::TypeRef::new_borrow(bt, node.m_res_type.clone()), CallPath, sp,
::HIR::Path(ty_val.clone(), mv$(trait), method),
mv$(args)
@@ -689,23 +689,23 @@ namespace {
auto& arg_types = call_node.m_cache.m_arg_types;
arg_types.push_back( ::HIR::TypeRef::new_borrow(bt, ty_val.clone()) );
arg_types.push_back( m_replacement->m_res_type.clone() );
-
+
// - Dereference the result (which is an &-ptr)
m_replacement = NEWNODE( mv$(node.m_res_type), Deref, sp, mv$(m_replacement) );
}
-
-
-
+
+
+
void visit(::HIR::ExprNode_Unsize& node) override
{
::HIR::ExprVisitorDef::visit(node);
-
+
// HACK: The autoderef code has to run before usage information is avaliable, so emits "invalid" _Unsize nodes
// - Fix that.
if( node.m_value->m_res_type.m_data.is_Array() )
{
const Span& sp = node.span();
-
+
::HIR::BorrowType bt = ::HIR::BorrowType::Shared;
switch( node.m_usage )
{
@@ -722,7 +722,7 @@ namespace {
TODO(sp, "Support moving in _Unsize");
break;
}
-
+
auto ty_src = ::HIR::TypeRef::new_borrow(bt, node.m_value->m_res_type.clone());
auto ty_dst = ::HIR::TypeRef::new_borrow(bt, node.m_res_type.clone());
auto ty_dst2 = ty_dst.clone();
@@ -744,12 +744,12 @@ namespace {
m_crate(crate)
{
}
-
+
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
void visit_expr(::HIR::ExprPtr& exp) override {
BUG(Span(), "visit_expr hit in OuterVisitor");
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
@@ -799,7 +799,7 @@ namespace {
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
DEBUG("Enum value " << p << " - " << var.first);
-
+
ExprVisitor_Mutate ev(m_crate);
ev.visit_node_ptr(e.expr);
)
diff --git a/src/hir_expand/vtable.cpp b/src/hir_expand/vtable.cpp
index f12f8de5..f366a7d4 100644
--- a/src/hir_expand/vtable.cpp
+++ b/src/hir_expand/vtable.cpp
@@ -25,11 +25,11 @@ namespace {
{
m_lang_Sized = crate.get_lang_item_path_opt("sized");
}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
auto saved_nt = mv$(m_new_type);
-
+
::std::vector< decltype(mod.m_mod_items)::value_type> new_types;
m_new_type = [&](bool pub, auto name, auto s)->auto {
auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { pub, ::HIR::TypeItem( mv$(s) ) }) );
@@ -37,19 +37,19 @@ namespace {
new_types.push_back( ::std::make_pair( mv$(name), mv$(boxed)) );
return ret;
};
-
+
::HIR::Visitor::visit_module(p, mod);
for(auto& i : new_types )
mod.m_mod_items.insert( mv$(i) );
-
+
m_new_type = mv$(saved_nt);
}
-
+
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& tr) override
{
static Span sp;
TRACE_FUNCTION_F(p);
-
+
::HIR::GenericPath trait_path( p.get_simple_path() );
{
unsigned int i = 0;
@@ -58,7 +58,7 @@ namespace {
i ++;
}
}
-
+
::std::unordered_map< ::std::string,unsigned int> assoc_type_indexes;
struct Foo {
::HIR::Trait* trait_ptr;
@@ -87,12 +87,12 @@ namespace {
}
visitor.add_types_from_trait(tr);
auto args = mv$(visitor.params);
-
+
struct VtableConstruct {
const OuterVisitor* m_outer;
::HIR::Trait* trait_ptr;
::HIR::t_struct_fields fields;
-
+
bool add_ents_from_trait(const ::HIR::Trait& tr, const ::HIR::GenericPath& trait_path)
{
TRACE_FUNCTION_F(trait_path);
@@ -136,7 +136,7 @@ namespace {
DEBUG("- '" << vi.first << "' NOT object safe (generic), not creating vtable");
return false;
}
-
+
::HIR::FunctionType ft;
ft.is_unsafe = ve.m_unsafe;
ft.m_abi = ve.m_abi;
@@ -147,14 +147,14 @@ namespace {
ft.m_arg_types.push_back( clone_ty_with(sp, ve.m_args[i].second, clone_cb) );
// Clear the first argument (the receiver)
::HIR::TypeRef fcn_type( mv$(ft) );
-
+
// Detect use of `Self` and don't create the vtable if there is.
if( visit_ty_with(fcn_type, [&](const auto& t){ return (t == ::HIR::TypeRef("Self", 0xFFFF)); }) )
{
DEBUG("- '" << vi.first << "' NOT object safe (Self), not creating vtable - " << fcn_type);
return false;
}
-
+
trait_ptr->m_value_indexes.insert( ::std::make_pair(
vi.first,
::std::make_pair(fields.size(), trait_path.clone())
@@ -186,7 +186,7 @@ namespace {
return true;
}
};
-
+
VtableConstruct vtc { this, &tr, {} };
if( ! vtc.add_ents_from_trait(tr, trait_path) )
{
@@ -195,7 +195,7 @@ namespace {
return ;
}
auto fields = mv$(vtc.fields);
-
+
::HIR::PathParams params;
{
unsigned int i = 0;
@@ -217,21 +217,21 @@ namespace {
});
DEBUG("Vtable structure created - " << item_path);
::HIR::GenericPath path( mv$(item_path), mv$(params) );
-
+
tr.m_values.insert( ::std::make_pair(
"#vtable",
::HIR::TraitValueItem(::HIR::Static { ::HIR::Linkage(), false, ::HIR::TypeRef( mv$(path) ), {},{} })
) );
}
-
+
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
{
static Span sp;
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type);
//auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
-
+
#if 0
// Check if the trait has a vtable, and if it does emit an associated static for it.
const auto& tr = m_crate.get_trait_by_path(sp, trait_path);
@@ -239,7 +239,7 @@ namespace {
{
auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &impl.m_type, &impl.m_trait_args, nullptr);
auto trait_gpath = ::HIR::GenericPath(trait_path, impl.m_trait_args.clone());
-
+
::std::vector< ::HIR::Literal> vals;
vals.resize( tr.m_value_indexes.size() );
for(const auto& m : tr.m_value_indexes)
@@ -249,7 +249,7 @@ namespace {
auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false);
vals.at(m.second.first) = ::HIR::Literal::make_BorrowOf( ::HIR::Path(impl.m_type.clone(), mv$(gpath), m.first) );
}
-
+
auto vtable_sp = trait_path;
vtable_sp.m_components.back() += "#vtable";
auto vtable_params = impl.m_trait_args.clone();
@@ -257,7 +257,7 @@ namespace {
::HIR::Path path( impl.m_type.clone(), mv$(trait_gpath), ty.first );
vtable_params.m_types.push_back( ::HIR::TypeRef( mv$(path) ) );
}
-
+
const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_sp);
impl.m_statics.insert(::std::make_pair( "#vtable", ::HIR::TraitImpl::ImplEnt<::HIR::Static> { true, ::HIR::Static {
::HIR::Linkage(),
diff --git a/src/hir_typeck/common.cpp b/src/hir_typeck/common.cpp
index 0751d5a1..96508345 100644
--- a/src/hir_typeck/common.cpp
+++ b/src/hir_typeck/common.cpp
@@ -143,7 +143,7 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
::HIR::PathParams clone_ty_with__path_params(const Span& sp, const ::HIR::PathParams& tpl, t_cb_clone_ty callback) {
::HIR::PathParams rv;
rv.m_types.reserve( tpl.m_types.size() );
- for( const auto& ty : tpl.m_types)
+ for( const auto& ty : tpl.m_types)
rv.m_types.push_back( clone_ty_with(sp, ty, callback) );
return rv;
}
@@ -157,14 +157,14 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
{},
tpl.m_trait_ptr
};
-
+
for(const auto& assoc : tpl.m_type_bounds) {
rv.m_type_bounds.insert(::std::make_pair(
assoc.first,
clone_ty_with(sp, assoc.second, callback)
));
}
-
+
return rv;
}
::HIR::Path clone_ty_with__path(const Span& sp, const ::HIR::Path& tpl, t_cb_clone_ty callback) {
@@ -201,12 +201,12 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
::HIR::TypeRef clone_ty_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_clone_ty callback)
{
::HIR::TypeRef rv;
-
+
if( callback(tpl, rv) ) {
DEBUG(tpl << " => " << rv);
return rv;
}
-
+
TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e),
(Infer,
rv = ::HIR::TypeRef(e);
@@ -235,19 +235,19 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
to.m_trait = clone_ty_with__trait_path(sp, e.m_trait, callback);
for(const auto& trait : e.m_markers)
{
- to.m_markers.push_back( clone_ty_with__generic_path(sp, trait, callback) );
+ to.m_markers.push_back( clone_ty_with__generic_path(sp, trait, callback) );
}
to.m_lifetime = e.m_lifetime;
rv = ::HIR::TypeRef( mv$(to) );
),
(ErasedType,
auto origin = clone_ty_with__path(sp, e.m_origin, callback);
-
+
::std::vector< ::HIR::TraitPath> traits;
traits.reserve( e.m_traits.size() );
for(const auto& trait : e.m_traits)
traits.push_back( clone_ty_with__trait_path(sp, trait, callback) );
-
+
rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_ErasedType {
mv$(origin), e.m_index,
mv$(traits),
@@ -306,12 +306,12 @@ namespace {
return [&sp,&outer_tpl,callback,allow_infer](const auto& tpl, auto& rv) {
if( tpl.m_data.is_Infer() && !allow_infer )
BUG(sp, "_ type found in " << outer_tpl);
-
+
if( tpl.m_data.is_Generic() ) {
rv = callback(tpl).clone();
return true;
}
-
+
return false;
};
}
diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp
index d6bf30c1..40e7e73c 100644
--- a/src/hir_typeck/common.hpp
+++ b/src/hir_typeck/common.hpp
@@ -44,9 +44,9 @@ struct MonomorphState
const ::HIR::TypeRef* self_ty;
const ::HIR::PathParams* pp_impl;
const ::HIR::PathParams* pp_method;
-
+
t_cb_generic get_cb(const Span& sp) const;
-
+
::HIR::TypeRef monomorph(const Span& sp, const ::HIR::TypeRef& ty, bool allow_infer=true) const {
return monomorphise_type_with(sp, ty, this->get_cb(sp), allow_infer);
}
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index 4009a76a..11e895cb 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -13,7 +13,7 @@
namespace {
typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > t_args;
-
+
class ExprVisitor_Validate:
public ::HIR::ExprVisitor
{
@@ -21,7 +21,7 @@ namespace {
//const t_args& m_args;
const ::HIR::TypeRef& ret_type;
::std::vector< const ::HIR::TypeRef*> closure_ret_types;
-
+
public:
ExprVisitor_Validate(const StaticTraitResolve& res, const t_args& args, const ::HIR::TypeRef& ret_type):
m_resolve(res),
@@ -29,12 +29,12 @@ namespace {
ret_type(ret_type)
{
}
-
+
void visit_root(::HIR::ExprPtr& node_ptr)
{
const auto& sp = node_ptr->span();
node_ptr->visit(*this);
-
+
// Monomorphise erased type
::HIR::TypeRef new_ret_type = clone_ty_with(sp, ret_type, [&](const auto& tpl, auto& rv) {
if( tpl.m_data.is_ErasedType() )
@@ -51,7 +51,7 @@ namespace {
check_types_equal(sp, new_ret_type, node_ptr->m_res_type);
}
-
+
void visit(::HIR::ExprNode_Block& node) override
{
TRACE_FUNCTION_F(&node << " { ... }");
@@ -113,7 +113,7 @@ namespace {
void visit(::HIR::ExprNode_Assign& node) override
{
TRACE_FUNCTION_F(&node << "... ?= ...");
-
+
if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) {
check_types_equal(node.span(), node.m_slot->m_res_type, node.m_value->m_res_type);
}
@@ -137,17 +137,17 @@ namespace {
}
assert(lang_item);
const auto& trait_path = this->get_lang_item_path(node.span(), lang_item);
-
+
check_associated_type(node.span(), ::HIR::TypeRef(), trait_path, { node.m_value->m_res_type.clone() }, node.m_slot->m_res_type, "");
}
-
+
node.m_slot->visit( *this );
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_BinOp& node) override
{
TRACE_FUNCTION_F(&node << "... "<<::HIR::ExprNode_BinOp::opname(node.m_op)<<" ...");
-
+
switch(node.m_op)
{
case ::HIR::ExprNode_BinOp::Op::CmpEqu:
@@ -157,7 +157,7 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::CmpGt:
case ::HIR::ExprNode_BinOp::Op::CmpGtE: {
check_types_equal(node.span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_res_type);
-
+
const char* item_name = nullptr;
switch(node.m_op)
{
@@ -171,10 +171,10 @@ namespace {
}
assert(item_name);
const auto& op_trait = this->get_lang_item_path(node.span(), item_name);
-
+
check_associated_type(node.span(), ::HIR::TypeRef(), op_trait, { node.m_right->m_res_type.clone() }, node.m_left->m_res_type, "");
break; }
-
+
case ::HIR::ExprNode_BinOp::Op::BoolAnd:
case ::HIR::ExprNode_BinOp::Op::BoolOr:
// No validation needed, result forced in typeck
@@ -197,25 +197,25 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::Mul: item_name = "mul"; break;
case ::HIR::ExprNode_BinOp::Op::Div: item_name = "div"; break;
case ::HIR::ExprNode_BinOp::Op::Mod: item_name = "rem"; break;
-
+
case ::HIR::ExprNode_BinOp::Op::And: item_name = "bitand"; break;
case ::HIR::ExprNode_BinOp::Op::Or: item_name = "bitor"; break;
case ::HIR::ExprNode_BinOp::Op::Xor: item_name = "bitxor"; break;
-
+
case ::HIR::ExprNode_BinOp::Op::Shr: item_name = "shr"; break;
case ::HIR::ExprNode_BinOp::Op::Shl: item_name = "shl"; break;
}
assert(item_name);
const auto& op_trait = this->get_lang_item_path(node.span(), item_name);
-
+
check_associated_type(node.span(), node.m_res_type, op_trait, { node.m_right->m_res_type.clone() }, node.m_left->m_res_type, "Output");
break; }
}
-
+
node.m_left ->visit( *this );
node.m_right->visit( *this );
}
-
+
void visit(::HIR::ExprNode_UniOp& node) override
{
TRACE_FUNCTION_F(&node << " " << ::HIR::ExprNode_UniOp::opname(node.m_op) << "...");
@@ -243,24 +243,24 @@ namespace {
node.m_res_type,
this->get_lang_item_path(node.span(), "index"), { node.m_index->m_res_type.clone() }, node.m_value->m_res_type, "Target"
);
-
+
node.m_value->visit( *this );
node.m_index->visit( *this );
}
-
+
void visit(::HIR::ExprNode_Cast& node) override
{
TRACE_FUNCTION_F(&node << " ... as " << node.m_res_type);
const Span& sp = node.span();
-
+
const auto& src_ty = node.m_value->m_res_type;
const auto& dst_ty = node.m_res_type;
-
+
if( dst_ty == src_ty ) {
// Would be nice to delete it, but this is a readonly pass
return ;
}
-
+
// Check castability
TU_MATCH_DEF(::HIR::TypeRef::Data, (dst_ty.m_data), (de),
(
@@ -307,17 +307,17 @@ namespace {
// TODO: Check cast to primitive
)
)
-
+
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_Unsize& node) override
{
TRACE_FUNCTION_F(&node << " ... : " << node.m_res_type);
const Span& sp = node.span();
-
+
const auto& src_ty = node.m_value->m_res_type;
const auto& dst_ty = node.m_res_type;
-
+
if( src_ty.m_data.is_Borrow() && dst_ty.m_data.is_Borrow() )
{
const auto& se = src_ty.m_data.as_Borrow();
@@ -327,7 +327,7 @@ namespace {
}
const auto& src_ty = *se.inner;
const auto& dst_ty = *de.inner;
-
+
const auto& lang_Unsize = this->get_lang_item_path(node.span(), "unsize");
// _ == < `src_ty` as Unsize< `dst_ty` >::""
check_associated_type(sp, ::HIR::TypeRef(), lang_Unsize, { dst_ty.clone() }, src_ty, "");
@@ -342,7 +342,7 @@ namespace {
// _ == < `src_ty` as CoerceUnsized< `dst_ty` >::""
check_associated_type(sp, ::HIR::TypeRef(), lang_CoerceUnsized, { dst_ty.clone() }, src_ty, "");
}
-
+
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_Deref& node) override
@@ -361,7 +361,7 @@ namespace {
{
case ::HIR::ExprNode_Emplace::Type::Noop:
assert( !node.m_place );
-
+
check_types_equal(node.span(), node.m_res_type, node.m_value->m_res_type);
break;
case ::HIR::ExprNode_Emplace::Type::Boxer:
@@ -371,7 +371,7 @@ namespace {
// TODO: Check trait
break;
}
-
+
if( node.m_place )
this->visit_node_ptr(node.m_place);
this->visit_node_ptr(node.m_value);
@@ -380,10 +380,10 @@ namespace {
{
TRACE_FUNCTION_F(&node << " " << node.m_path << "(...,) [" << (node.m_is_struct ? "struct" : "enum") << "]");
const auto& sp = node.span();
-
+
// - Create ivars in path, and set result type
const auto& ty = node.m_res_type;
-
+
const ::HIR::t_tuple_fields* fields_ptr = nullptr;
ASSERT_BUG(sp, ty.m_data.is_Path(), "Result type of _TupleVariant isn't Path");
TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
@@ -412,7 +412,7 @@ namespace {
assert(fields_ptr);
const ::HIR::t_tuple_fields& fields = *fields_ptr;
ASSERT_BUG(sp, fields.size() == node.m_args.size(), "");
-
+
// Bind fields with type params (coercable)
// TODO: Remove use of m_arg_types (maybe assert that cache is correct?)
for( unsigned int i = 0; i < node.m_args.size(); i ++ )
@@ -423,10 +423,10 @@ namespace {
assert( node.m_arg_types[i] != ::HIR::TypeRef() );
des_ty = &node.m_arg_types[i];
}
-
+
check_types_equal(*des_ty, node.m_args[i]);
}
-
+
for( auto& val : node.m_args ) {
val->visit( *this );
}
@@ -438,11 +438,11 @@ namespace {
if( node.m_base_value) {
check_types_equal( node.m_base_value->span(), node.m_res_type, node.m_base_value->m_res_type );
}
-
+
// - Create ivars in path, and set result type
const auto& ty = node.m_res_type;
ASSERT_BUG(sp, ty.m_data.is_Path(), "Result type of _StructLiteral isn't Path");
-
+
const ::HIR::t_struct_fields* fields_ptr = nullptr;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
(Unbound, ),
@@ -463,7 +463,7 @@ namespace {
)
ASSERT_BUG(node.span(), fields_ptr, "Didn't get field for path in _StructLiteral - " << ty);
const ::HIR::t_struct_fields& fields = *fields_ptr;
-
+
#if 1
const auto& ty_params = node.m_path.m_params.m_types;
auto monomorph_cb = [&](const auto& gt)->const auto& {
@@ -482,7 +482,7 @@ namespace {
}
};
#endif
-
+
// Bind fields with type params (coercable)
for( auto& val : node.m_values)
{
@@ -492,7 +492,7 @@ namespace {
const auto& des_ty_r = it->second.ent;
auto& des_ty_cache = node.m_value_types[it - fields.begin()];
const auto* des_ty = &des_ty_r;
-
+
if( monomorphise_type_needed(des_ty_r) ) {
assert( des_ty_cache != ::HIR::TypeRef() );
des_ty_cache = monomorphise_type_with(node.span(), des_ty_r, monomorph_cb);
@@ -502,7 +502,7 @@ namespace {
DEBUG("." << name << " : " << *des_ty);
check_types_equal(*des_ty, val.second);
}
-
+
for( auto& val : node.m_values ) {
val.second->visit( *this );
}
@@ -521,7 +521,7 @@ namespace {
const auto& sp = node.span();
const auto& ty = node.m_res_type;
ASSERT_BUG(sp, ty.m_data.is_Path(), "Result type of _UnitVariant isn't Path");
-
+
TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
(Unbound, ),
(Opaque, ),
@@ -545,26 +545,26 @@ namespace {
{
const auto& sp = node.span();
TRACE_FUNCTION_F(&node << " " << node.m_path << "(..., )");
-
+
for( auto& val : node.m_args ) {
val->visit( *this );
}
-
+
// Do function resolution again, this time with concrete types.
const auto& path = node.m_path;
/*const*/ auto& cache = node.m_cache;
-
+
const ::HIR::Function* fcn_ptr = nullptr;
::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> monomorph_cb;
-
+
TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
(Generic,
const auto& path_params = e.m_params;
-
+
const auto& fcn = m_resolve.m_crate.get_function_by_path(sp, e.m_path);
fcn_ptr = &fcn;
cache.m_fcn_params = &fcn.m_params;
-
+
monomorph_cb = [&](const auto& gt)->const auto& {
const auto& e = gt.m_data.as_Generic();
if( e.name == "Self" || e.binding == 0xFFFF )
@@ -587,21 +587,21 @@ namespace {
(UfcsKnown,
const auto& trait_params = e.trait.m_params;
const auto& path_params = e.params;
-
+
const auto& trait = m_resolve.m_crate.get_trait_by_path(sp, e.trait.m_path);
if( trait.m_values.count(e.item) == 0 ) {
BUG(sp, "Method '" << e.item << "' of trait " << e.trait.m_path << " doesn't exist");
}
-
+
const auto& fcn = trait.m_values.at(e.item).as_Function();
cache.m_fcn_params = &fcn.m_params;
cache.m_top_params = &trait.m_params;
-
+
// Add a bound requiring the Self type impl the trait
check_associated_type(sp, ::HIR::TypeRef(), e.trait.m_path, e.trait.m_params, *e.type, "");
-
+
fcn_ptr = &fcn;
-
+
monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
@@ -646,14 +646,14 @@ namespace {
ERROR(sp, E0000, "Failed to locate function " << path);
}
assert(impl_ptr);
-
+
cache.m_fcn_params = &fcn_ptr->m_params;
-
-
+
+
// NOTE: Trusts the existing cache.
ASSERT_BUG(sp, e.impl_params.m_types.size() == impl_ptr->m_params.m_types.size(), "");
auto& impl_params = e.impl_params;
-
+
// Create monomorphise callback
const auto& fcn_params = e.params;
monomorph_cb = [&](const auto& gt)->const auto& {
@@ -684,7 +684,7 @@ namespace {
assert( fcn_ptr );
const auto& fcn = *fcn_ptr;
-
+
// --- Monomorphise the argument/return types (into current context)
cache.m_arg_types.clear();
for(const auto& arg : fcn.m_args) {
@@ -705,7 +705,7 @@ namespace {
}
else if( tpl.m_data.is_ErasedType() ) {
const auto& e = tpl.m_data.as_ErasedType();
-
+
ASSERT_BUG(sp, e.m_index < fcn_ptr->m_code.m_erased_types.size(), "");
const auto& erased_type_replacement = fcn_ptr->m_code.m_erased_types.at(e.m_index);
rv = monomorphise_type_with(sp, erased_type_replacement, monomorph_cb, false);
@@ -717,7 +717,7 @@ namespace {
}) );
m_resolve.expand_associated_types(sp, cache.m_arg_types.back());
DEBUG("= " << cache.m_arg_types.back());
-
+
// Check types
for(unsigned int i = 0; i < fcn.m_args.size(); i ++) {
DEBUG("CHECK ARG " << i << " " << node.m_cache.m_arg_types[i] << " == " << node.m_args[i]->m_res_type);
@@ -729,9 +729,9 @@ namespace {
}
DEBUG("CHECK RV " << node.m_res_type << " == " << node.m_cache.m_arg_types.back());
check_types_equal(node.span(), node.m_res_type, node.m_cache.m_arg_types.back());
-
+
cache.m_monomorph_cb = mv$(monomorph_cb);
-
+
// Bounds
for(const auto& bound : cache.m_fcn_params->m_bounds)
{
@@ -746,17 +746,17 @@ namespace {
DEBUG("Bound " << be.type << ": " << be.trait);
DEBUG("= (" << real_type << ": " << real_trait << ")");
const auto& trait_params = real_trait.m_params;
-
+
const auto& trait_path = be.trait.m_path.m_path;
check_associated_type(sp, ::HIR::TypeRef(), trait_path, trait_params, real_type, "");
-
+
// TODO: Either - Don't include the above impl bound, or change the below trait to the one that has that type
for( const auto& assoc : be.trait.m_type_bounds ) {
::HIR::GenericPath type_trait_path;
m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first, type_trait_path);
-
+
auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true);
-
+
check_associated_type(sp, other_ty, type_trait_path.m_path, type_trait_path.m_params, real_type, assoc.first.c_str());
}
),
@@ -773,9 +773,9 @@ namespace {
void visit(::HIR::ExprNode_CallValue& node) override
{
TRACE_FUNCTION_F(&node << " (...)(..., )");
-
+
const auto& val_ty = node.m_value->m_res_type;
-
+
TU_IFLET( ::HIR::TypeRef::Data, val_ty.m_data, Function, e,
DEBUG("- Function pointer: " << val_ty);
if( node.m_args.size() != e.m_arg_types.size() ) {
@@ -796,14 +796,14 @@ namespace {
: node.m_trait_used == ::HIR::ExprNode_CallValue::TraitUsed::FnOnce ? m_resolve.m_crate.get_lang_item_path(node.span(), "fn_once")
: throw ""
);
-
+
::std::vector< ::HIR::TypeRef> tup_ents;
for(const auto& arg : node.m_args) {
tup_ents.push_back( arg->m_res_type.clone() );
}
::HIR::PathParams params;
params.m_types.push_back( ::HIR::TypeRef( mv$(tup_ents) ) );
-
+
bool found = m_resolve.find_impl(node.span(), trait, &params, val_ty, [&](auto , bool fuzzy){
ASSERT_BUG(node.span(), !fuzzy, "Fuzzy match in check pass");
return true;
@@ -819,7 +819,7 @@ namespace {
m_resolve.expand_associated_types(node.span(), exp_ret);
check_types_equal(node.span(), node.m_res_type, exp_ret);
}
-
+
node.m_value->visit( *this );
for( auto& val : node.m_args ) {
val->visit( *this );
@@ -837,19 +837,19 @@ namespace {
check_types_equal(node.m_cache.m_arg_types[1+i], node.m_args[i]);
}
check_types_equal(node.span(), node.m_res_type, node.m_cache.m_arg_types.back());
-
+
node.m_value->visit( *this );
for( auto& val : node.m_args ) {
val->visit( *this );
}
}
-
+
void visit(::HIR::ExprNode_Field& node) override
{
TRACE_FUNCTION_F(&node << " (...)." << node.m_field);
const auto& sp = node.span();
const auto& str_ty = node.m_value->m_res_type;
-
+
bool is_index = ( '0' <= node.m_field[0] && node.m_field[0] <= '9' );
if( str_ty.m_data.is_Tuple() )
{
@@ -876,20 +876,20 @@ namespace {
ASSERT_BUG(sp, ty_e.binding.is_Struct() || ty_e.binding.is_Union(), "Value type of _Field isn't a Struct or Union - " << str_ty);
}
}
-
+
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_Tuple& node) override
{
TRACE_FUNCTION_F(&node << " (...,)");
const auto& tys = node.m_res_type.m_data.as_Tuple();
-
+
ASSERT_BUG(node.span(), tys.size() == node.m_vals.size(), "Bad element count in tuple literal - " << tys.size() << " != " << node.m_vals.size());
for(unsigned int i = 0; i < node.m_vals.size(); i ++)
{
check_types_equal(node.span(), tys[i], node.m_vals[i]->m_res_type);
}
-
+
for( auto& val : node.m_vals ) {
val->visit( *this );
}
@@ -902,7 +902,7 @@ namespace {
for( auto& val : node.m_vals ) {
check_types_equal(val->span(), inner_ty, val->m_res_type);
}
-
+
for( auto& val : node.m_vals ) {
val->visit( *this );
}
@@ -910,15 +910,15 @@ namespace {
void visit(::HIR::ExprNode_ArraySized& node) override
{
TRACE_FUNCTION_F(&node << " [...; "<<node.m_size_val<<"]");
-
+
//check_types_equal(node.m_size->span(), ::HIR::TypeRef(::HIR::Primitive::Usize), node.m_size->m_res_type);
const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner;
check_types_equal(node.m_val->span(), inner_ty, node.m_val->m_res_type);
-
+
node.m_val->visit( *this );
node.m_size->visit( *this );
}
-
+
void visit(::HIR::ExprNode_Literal& node) override
{
// No validation needed
@@ -927,7 +927,7 @@ namespace {
{
TRACE_FUNCTION_F(&node << " " << node.m_path);
const auto& sp = node.span();
-
+
TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e),
(Generic,
switch(node.m_target)
@@ -953,7 +953,7 @@ namespace {
),
(UfcsKnown,
check_associated_type(sp, ::HIR::TypeRef(), e.trait.m_path, e.trait.m_params, e.type->clone(), "");
-
+
const auto& trait = this->m_resolve.m_crate.get_trait_by_path(sp, e.trait.m_path);
auto it = trait.m_values.find( e.item );
if( it == trait.m_values.end() ) {
@@ -978,16 +978,16 @@ namespace {
)
)
}
-
+
void visit(::HIR::ExprNode_Variable& node) override
{
// TODO: Check against variable slot? Nah.
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
TRACE_FUNCTION_F(&node << " |...| ...");
-
+
if( node.m_code )
{
check_types_equal(node.m_code->span(), node.m_return, node.m_code->m_res_type);
@@ -996,7 +996,7 @@ namespace {
this->closure_ret_types.pop_back( );
}
}
-
+
private:
void check_types_equal(const ::HIR::TypeRef& l, const ::HIR::ExprNodeP& node) const
{
@@ -1023,8 +1023,8 @@ namespace {
// TODO: Actually check.
#if 0
bool found = m_resolve.find_impl(sp, trait, &params, ity, [&](auto impl, bool fuzzy){
-
-
+
+
return true;
});
if( !found )
@@ -1033,14 +1033,14 @@ namespace {
}
#endif
}
-
+
const ::HIR::SimplePath& get_lang_item_path(const Span& sp, const char* name) const
{
return m_resolve.m_crate.get_lang_item_path(sp, name);
}
};
-
-
+
+
class OuterVisitor:
public ::HIR::Visitor
{
@@ -1049,12 +1049,12 @@ namespace {
OuterVisitor(const ::HIR::Crate& crate):
m_resolve(crate)
{}
-
+
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
void visit_expr(::HIR::ExprPtr& exp) override {
BUG(Span(), "visit_expr hit in OuterVisitor");
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
@@ -1107,19 +1107,19 @@ namespace {
//auto _ = this->m_ms.set_item_generics(item.m_params);
// TODO: Use a different type depding on repr()
auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
+
for(auto& var : item.m_variants)
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
DEBUG("Enum value " << p << " - " << var.first);
-
+
t_args tmp;
ExprVisitor_Validate ev(m_resolve, tmp, enum_type);
ev.visit_root(e.expr);
)
}
}
-
+
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override
{
auto _ = this->m_resolve.set_impl_generics(item.m_params);
@@ -1129,14 +1129,14 @@ namespace {
{
TRACE_FUNCTION_F("impl " << impl.m_type);
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_type_impl(impl);
}
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
{
TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << trait_path << " for " << impl.m_type);
auto _ = this->m_resolve.set_impl_generics(impl.m_params);
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
}
};
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 91febcc4..b1ee04bc 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -28,20 +28,20 @@ struct Context
virtual void fmt(::std::ostream& os) const = 0;
virtual bool revisit(Context& context) = 0;
};
-
+
struct Binding
{
::std::string name;
::HIR::TypeRef ty;
//unsigned int ivar;
};
-
+
/// Inferrence variable equalities
struct Coercion
{
::HIR::TypeRef left_ty;
::HIR::ExprNodeP* right_node_ptr;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Coercion& v) {
os << v.left_ty << " := " << v.right_node_ptr << " " << &**v.right_node_ptr << " (" << (*v.right_node_ptr)->m_res_type << ")";
return os;
@@ -51,15 +51,15 @@ struct Context
{
Span span;
::HIR::TypeRef left_ty;
-
+
::HIR::SimplePath trait;
::HIR::PathParams params;
::HIR::TypeRef impl_ty;
::std::string name; // if "", no type is used (and left is ignored) - Just does trait selection
-
+
// HACK: operators are special - the result when both types are primitives is ALWAYS the lefthand side
bool is_operator;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Associated& v) {
if( v.name == "" ) {
os << "req ty " << v.impl_ty << " impl " << v.trait << v.params;
@@ -70,7 +70,7 @@ struct Context
return os;
}
};
-
+
struct IVarPossible
{
bool force_no_to = false;
@@ -80,7 +80,7 @@ struct Context
::std::vector<::HIR::TypeRef> types_coerce_from;
::std::vector<::HIR::TypeRef> types_unsize_from;
//::std::vector<::HIR::TypeRef> types_default;
-
+
void reset() {
//auto tmp = mv$(this->types_default);
*this = IVarPossible();
@@ -90,38 +90,38 @@ struct Context
return !types_unsize_to.empty() || !types_coerce_to.empty() || !types_unsize_from.empty() || !types_coerce_from.empty() /* || !types_default.empty()*/;
}
};
-
+
const ::HIR::Crate& m_crate;
-
+
::std::vector<Binding> m_bindings;
HMTypeInferrence m_ivars;
TraitResolution m_resolve;
-
+
::std::vector<Coercion> link_coerce;
::std::vector<Associated> link_assoc;
/// Nodes that need revisiting (e.g. method calls when the receiver isn't known)
::std::vector< ::HIR::ExprNode*> to_visit;
/// Callback-based revisits (e.g. for slice patterns handling slices/arrays)
::std::vector< ::std::unique_ptr<Revisitor> > adv_revisits;
-
+
::std::vector< IVarPossible> possible_ivar_vals;
-
+
const ::HIR::SimplePath m_lang_Box;
-
+
Context(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params):
m_crate(crate),
m_resolve(m_ivars, crate, impl_params, item_params),
m_lang_Box( crate.get_lang_item_path_opt("owned_box") )
{
}
-
+
void dump() const;
-
+
bool take_changed() { return m_ivars.take_changed(); }
bool has_rules() const {
return !(link_coerce.empty() && link_assoc.empty() && to_visit.empty() && adv_revisits.empty());
}
-
+
inline void add_ivars(::HIR::TypeRef& ty) {
m_ivars.add_ivars(ty);
}
@@ -144,12 +144,12 @@ struct Context
equate_types_assoc(sp, l, trait, mv$(pp), impl_ty, name, is_op);
}
void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::HIR::PathParams params, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op);
-
+
// - Add a trait bound (gets encoded as an associated type bound)
void add_trait_bound(const Span& sp, const ::HIR::TypeRef& impl_ty, const ::HIR::SimplePath& trait, ::HIR::PathParams params) {
equate_types_assoc(sp, ::HIR::TypeRef(), trait, mv$(params), impl_ty, "", false);
}
-
+
/// Disable possibility checking for the type (as if <impossible> was added as a coerce_to)
void equate_types_to_shadow(const Span& sp, const ::HIR::TypeRef& r) {
equate_types_shadow(sp, r, true);
@@ -186,26 +186,26 @@ struct Context
}
/// Default type
//void possible_equate_type_def(unsigned int ivar_index, const ::HIR::TypeRef& t);
-
+
void possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef& t, bool is_to, bool is_borrow);
void possible_equate_type_disable(unsigned int ivar_index, bool is_to);
-
+
// - Add a pattern binding (forcing the type to match)
void add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type);
void add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type);
-
+
void add_var(const Span& sp, unsigned int index, const ::std::string& name, ::HIR::TypeRef type);
const ::HIR::TypeRef& get_var(const Span& sp, unsigned int idx) const;
-
+
// - Add a revisit entry
void add_revisit(::HIR::ExprNode& node);
void add_revisit_adv(::std::unique_ptr<Revisitor> ent);
const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& ty) const { return m_ivars.get_type(ty); }
-
+
/// Create an autoderef operation from val_node->m_res_type to ty_dst (handling implicit unsizing)
::HIR::ExprNodeP create_autoderef(::HIR::ExprNodeP val_node, ::HIR::TypeRef ty_dst) const;
-
+
private:
void add_ivars_params(::HIR::PathParams& params) {
m_ivars.add_ivars_params(params);
@@ -216,7 +216,7 @@ static void fix_param_count(const Span& sp, Context& context, const ::HIR::TypeR
static void fix_param_count(const Span& sp, Context& context, const ::HIR::TypeRef& self_ty, bool use_defaults, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params);
namespace {
-
+
void apply_bounds_as_rules(Context& context, const Span& sp, const ::HIR::GenericParams& params_def, t_cb_generic monomorph_cb)
{
for(const auto& bound : params_def.m_bounds)
@@ -232,7 +232,7 @@ namespace {
DEBUG("Bound " << be.type << ": " << be.trait);
DEBUG("= (" << real_type << ": " << real_trait << ")");
const auto& trait_params = real_trait.m_params;
-
+
const auto& trait_path = be.trait.m_path.m_path;
// If there's no type bounds, emit a trait bound
// - Otherwise, the assocated type bounds will serve the same purpose
@@ -240,15 +240,15 @@ namespace {
{
context.add_trait_bound(sp, real_type, trait_path, trait_params.clone());
}
-
+
for( const auto& assoc : be.trait.m_type_bounds ) {
::HIR::GenericPath type_trait_path;
ASSERT_BUG(sp, be.trait.m_trait_ptr, "Trait pointer not set in " << be.trait.m_path);
// TODO: Store the source trait for this bound in the the bound list?
context.m_resolve.trait_contains_type(sp, real_trait, *be.trait.m_trait_ptr, assoc.first, type_trait_path);
-
+
auto other_ty = monomorphise_type_with(sp, assoc.second, monomorph_cb, true);
-
+
context.equate_types_assoc(sp, other_ty, type_trait_path.m_path, mv$(type_trait_path.m_params.m_types), real_type, assoc.first.c_str());
}
),
@@ -260,26 +260,26 @@ namespace {
)
}
}
-
+
bool visit_call_populate_cache(Context& context, const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache) __attribute__((warn_unused_result));
bool visit_call_populate_cache_UfcsInherent(Context& context, const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache, const ::HIR::Function*& fcn_ptr);
-
+
/// (HELPER) Populate the cache for nodes that use visit_call
/// TODO: If the function has multiple mismatched options, tell the caller to try again later?
bool visit_call_populate_cache(Context& context, const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache)
{
TRACE_FUNCTION_FR(path, path);
assert(cache.m_arg_types.size() == 0);
-
+
const ::HIR::Function* fcn_ptr = nullptr;
-
+
TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
(Generic,
const auto& fcn = context.m_crate.get_function_by_path(sp, e.m_path);
fix_param_count(sp, context, ::HIR::TypeRef(), false, path, fcn.m_params, e.m_params);
fcn_ptr = &fcn;
cache.m_fcn_params = &fcn.m_params;
-
+
//const auto& params_def = fcn.m_params;
const auto& path_params = e.m_params;
cache.m_monomorph_cb = [&](const auto& gt)->const auto& {
@@ -311,12 +311,12 @@ namespace {
fix_param_count(sp, context, *e.type, false, path, fcn.m_params, e.params);
cache.m_fcn_params = &fcn.m_params;
cache.m_top_params = &trait.m_params;
-
+
// Add a bound requiring the Self type impl the trait
context.add_trait_bound(sp, *e.type, e.trait.m_path, e.trait.m_params.clone());
-
+
fcn_ptr = &fcn;
-
+
const auto& trait_params = e.trait.m_params;
const auto& path_params = e.params;
cache.m_monomorph_cb = [&](const auto& gt)->const auto& {
@@ -367,16 +367,16 @@ namespace {
}
DEBUG("Ret " << fcn.m_return);
cache.m_arg_types.push_back( monomorphise_type_with(sp, fcn.m_return, monomorph_cb, false) );
-
+
// --- Apply bounds by adding them to the associated type ruleset
apply_bounds_as_rules(context, sp, *cache.m_fcn_params, cache.m_monomorph_cb);
-
+
return true;
}
bool visit_call_populate_cache_UfcsInherent(Context& context, const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache, const ::HIR::Function*& fcn_ptr)
{
auto& e = path.m_data.as_UfcsInherent();
-
+
const ::HIR::TypeImpl* impl_ptr = nullptr;
// Detect multiple applicable methods and get the caller to try again later if there are multiple
unsigned int count = 0;
@@ -402,8 +402,8 @@ namespace {
DEBUG("Found impl" << impl_ptr->m_params.fmt_args() << " " << impl_ptr->m_type);
fix_param_count(sp, context, *e.type, false, path, fcn_ptr->m_params, e.params);
cache.m_fcn_params = &fcn_ptr->m_params;
-
-
+
+
// If the impl block has parameters, figure out what types they map to
// - The function params are already mapped (from fix_param_count)
auto& impl_params = e.impl_params;
@@ -411,7 +411,7 @@ namespace {
{
// Default-construct entires in the `impl_params` array
impl_params.m_types.resize( impl_ptr->m_params.m_types.size() );
-
+
auto cmp = impl_ptr->m_type.match_test_generics_fuzz(sp, *e.type, context.m_ivars.callback_resolve_infer(), [&](auto idx, const auto& ty) {
assert( idx < impl_params.m_types.size() );
impl_params.m_types[idx] = ty.clone();
@@ -427,8 +427,8 @@ namespace {
ty = context.m_ivars.new_ivar_tr();
}
}
-
-
+
+
// Monomorphise the impl type with the new ivars, and equate to *e.type
auto impl_monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
@@ -448,10 +448,10 @@ namespace {
};
auto impl_ty_mono = monomorphise_type_with(sp, impl_ptr->m_type, impl_monomorph_cb, false);
DEBUG("- impl_ty_mono = " << impl_ty_mono);
-
+
context.equate_types(sp, impl_ty_mono, *e.type);
}
-
+
// Fill unknown parametrs with ivars
for(auto& ty : impl_params.m_types) {
if( ty == ::HIR::TypeRef() ) {
@@ -460,7 +460,7 @@ namespace {
}
}
}
-
+
// Create monomorphise callback
const auto& fcn_params = e.params;
cache.m_monomorph_cb = [&](const auto& gt)->const auto& {
@@ -490,24 +490,24 @@ namespace {
BUG(sp, "Generic bounding out of total range - " << ge.binding);
}
};
-
+
// Add trait bounds for all impl and function bounds
apply_bounds_as_rules(context, sp, impl_ptr->m_params, cache.m_monomorph_cb);
-
+
// Equate `Self` and `impl_ptr->m_type` (after monomorph)
{
::HIR::TypeRef tmp;
const auto& impl_ty_m = (monomorphise_type_needed(impl_ptr->m_type) ? tmp = monomorphise_type_with(sp, impl_ptr->m_type, cache.m_monomorph_cb) : impl_ptr->m_type);
-
+
context.equate_types(sp, *e.type, impl_ty_m);
}
-
+
return true;
}
-
+
// -----------------------------------------------------------------------
// Enumeration visitor
- //
+ //
// Iterates the HIR expression tree and extracts type "equations"
// -----------------------------------------------------------------------
class ExprVisitor_Enum:
@@ -516,11 +516,11 @@ namespace {
Context& context;
const ::HIR::TypeRef& ret_type;
::std::vector< const ::HIR::TypeRef*> closure_ret_types;
-
+
::std::vector<bool> inner_coerce_enabled_stack;
-
+
::std::vector< ::HIR::ExprNode_Loop*> loop_blocks; // Used for `break` type markings
-
+
// TEMP: List of in-scope traits for buildup
::HIR::t_trait_list m_traits;
public:
@@ -530,37 +530,37 @@ namespace {
m_traits( mv$(base_traits) )
{
}
-
+
void visit(::HIR::ExprNode_Block& node) override
{
TRACE_FUNCTION_F(&node << " { ... }");
-
+
const auto is_diverge = [&](const ::HIR::TypeRef& rty)->bool {
const auto& ty = this->context.get_type(rty);
// TODO: Search the entire type for `!`? (What about pointers to it? or Option/Result?)
// - A correct search will search for unconditional (ignoring enums with a non-! variant) non-rawptr instances of ! in the type
return ty.m_data.is_Diverge();// || (ty.m_data.is_Infer() && ty.m_data.as_Infer().ty_class == ::HIR::InferClass::Diverge);
};
-
+
if( node.m_nodes.size() > 0 )
{
bool diverges = false;
this->push_traits( node.m_traits );
-
+
this->push_inner_coerce(false);
for( unsigned int i = 0; i < node.m_nodes.size()-1; i ++ )
{
auto& snp = node.m_nodes[i];
this->context.add_ivars( snp->m_res_type );
snp->visit(*this);
-
+
// If this statement yields !, then mark the block as diverging
if( is_diverge(snp->m_res_type) ) {
diverges = true;
}
}
this->pop_inner_coerce();
-
+
if( node.m_yields_final )
{
auto& snp = node.m_nodes.back();
@@ -575,7 +575,7 @@ namespace {
this->context.add_ivars( snp->m_res_type );
// - Not yielded - so don't equate the return
snp->visit(*this);
-
+
// NOTE: If the final statement in the block diverges, mark this as diverging
bool defer = false;
if( !diverges )
@@ -599,7 +599,7 @@ namespace {
diverges = false;
}
}
-
+
// If a statement in this block diverges
if( defer ) {
DEBUG("Block final node returns _, derfer diverge check");
@@ -614,7 +614,7 @@ namespace {
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
}
}
-
+
this->pop_traits( node.m_traits );
}
else
@@ -631,12 +631,12 @@ namespace {
const auto& ret_ty = ( this->closure_ret_types.size() > 0 ? *this->closure_ret_types.back() : this->ret_type );
this->context.equate_types_coerce(node.span(), ret_ty, node.m_value);
-
+
this->push_inner_coerce( true );
node.m_value->visit( *this );
this->pop_inner_coerce();
}
-
+
void visit(::HIR::ExprNode_Loop& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
@@ -644,16 +644,16 @@ namespace {
// Push this node to a stack so `break` statements can update the yeilded value
this->loop_blocks.push_back( &node );
node.m_diverges = true; // Set to `false` if a break is hit
-
+
// NOTE: This doesn't set the ivar to !, but marks it as a ! ivar (similar to the int/float markers)
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge());
-
+
this->context.add_ivars(node.m_code->m_res_type);
this->context.equate_types(node.span(), node.m_code->m_res_type, ::HIR::TypeRef::new_unit());
node.m_code->visit( *this );
-
+
this->loop_blocks.pop_back( );
-
+
if( node.m_diverges ) {
DEBUG("Loop diverged");
}
@@ -667,10 +667,10 @@ namespace {
if( this->loop_blocks.empty() ) {
ERROR(node.span(), E0000, "Break statement with no acive loop");
}
-
+
// NOTE: There's an RFC proposal (that's on track to be accepted) that allows `break value;`
auto break_type = ::HIR::TypeRef::new_unit();
-
+
::HIR::ExprNode_Loop* loop_node_ptr;
if( node.m_label != "" )
{
@@ -691,14 +691,14 @@ namespace {
this->context.equate_types(node.span(), loop_node.m_res_type, break_type);
}
}
-
+
void visit(::HIR::ExprNode_Let& node) override
{
TRACE_FUNCTION_F(&node << " let " << node.m_pattern << ": " << node.m_type);
-
+
this->context.add_ivars( node.m_type );
this->context.add_binding(node.span(), node.m_pattern, node.m_type);
-
+
if( node.m_value )
{
this->context.add_ivars( node.m_value->m_res_type );
@@ -716,7 +716,7 @@ namespace {
this->context.equate_types_coerce( node.span(), node.m_type, node.m_value );
this->push_inner_coerce(true);
}
-
+
node.m_value->visit( *this );
this->pop_inner_coerce();
}
@@ -724,17 +724,17 @@ namespace {
void visit(::HIR::ExprNode_Match& node) override
{
TRACE_FUNCTION_F(&node << " match ...");
-
+
const auto& val_type = node.m_value->m_res_type;
{
auto _ = this->push_inner_coerce_scoped(true);
this->context.add_ivars(node.m_value->m_res_type);
-
+
// TODO: If a coercion point (and ivar for the value) is placed here, it will allow `match &string { "..." ... }`
node.m_value->visit( *this );
}
-
+
for(auto& arm : node.m_arms)
{
TRACE_FUNCTION_F("ARM " << arm.m_patterns);
@@ -742,7 +742,7 @@ namespace {
{
this->context.add_binding(node.span(), pat, val_type);
}
-
+
if( arm.m_cond )
{
auto _ = this->push_inner_coerce_scoped(false);
@@ -750,29 +750,29 @@ namespace {
this->context.equate_types(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), arm.m_cond->m_res_type);
arm.m_cond->visit( *this );
}
-
+
this->context.add_ivars( arm.m_code->m_res_type );
this->equate_types_inner_coerce(node.span(), node.m_res_type, arm.m_code);
arm.m_code->visit( *this );
}
}
-
+
void visit(::HIR::ExprNode_If& node) override
{
TRACE_FUNCTION_F(&node << " if ...");
-
+
this->context.add_ivars( node.m_cond->m_res_type );
-
+
{
auto _ = this->push_inner_coerce_scoped(false);
this->context.equate_types(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond->m_res_type);
node.m_cond->visit( *this );
}
-
+
this->context.add_ivars( node.m_true->m_res_type );
this->equate_types_inner_coerce(node.span(), node.m_res_type, node.m_true);
node.m_true->visit( *this );
-
+
if( node.m_false ) {
this->context.add_ivars( node.m_false->m_res_type );
this->equate_types_inner_coerce(node.span(), node.m_res_type, node.m_false);
@@ -782,16 +782,16 @@ namespace {
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
}
}
-
-
+
+
void visit(::HIR::ExprNode_Assign& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << "... = ...");
this->context.add_ivars( node.m_slot ->m_res_type );
this->context.add_ivars( node.m_value->m_res_type );
-
+
// Plain assignment can't be overloaded, requires equal types
if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) {
this->context.equate_types_coerce(node.span(), node.m_slot->m_res_type, node.m_value);
@@ -816,29 +816,29 @@ namespace {
}
assert(lang_item);
const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item);
-
+
this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), trait_path, ::make_vec1(node.m_value->m_res_type.clone()), node.m_slot->m_res_type.clone(), "");
}
-
+
node.m_slot->visit( *this );
-
+
auto _2 = this->push_inner_coerce_scoped( node.m_op == ::HIR::ExprNode_Assign::Op::None );
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_BinOp& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << "... "<<::HIR::ExprNode_BinOp::opname(node.m_op)<<" ...");
-
+
this->context.add_ivars( node.m_left ->m_res_type );
this->context.add_ivars( node.m_right->m_res_type );
-
+
const auto& left_ty = node.m_left ->m_res_type;
::HIR::TypeRef right_ty_inner = this->context.m_ivars.new_ivar_tr();
const auto& right_ty = right_ty_inner;//node.m_right->m_res_type;
this->context.equate_types_coerce(node.span(), right_ty_inner, node.m_right);
-
+
switch(node.m_op)
{
case ::HIR::ExprNode_BinOp::Op::CmpEqu:
@@ -848,7 +848,7 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::CmpGt:
case ::HIR::ExprNode_BinOp::Op::CmpGtE: {
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
-
+
const char* item_name = nullptr;
switch(node.m_op)
{
@@ -865,7 +865,7 @@ namespace {
this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), op_trait, ::make_vec1(right_ty.clone()), left_ty.clone(), "");
break; }
-
+
case ::HIR::ExprNode_BinOp::Op::BoolAnd:
case ::HIR::ExprNode_BinOp::Op::BoolOr:
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
@@ -890,17 +890,17 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::Mul: item_name = "mul"; break;
case ::HIR::ExprNode_BinOp::Op::Div: item_name = "div"; break;
case ::HIR::ExprNode_BinOp::Op::Mod: item_name = "rem"; break;
-
+
case ::HIR::ExprNode_BinOp::Op::And: item_name = "bitand"; break;
case ::HIR::ExprNode_BinOp::Op::Or: item_name = "bitor"; break;
case ::HIR::ExprNode_BinOp::Op::Xor: item_name = "bitxor"; break;
-
+
case ::HIR::ExprNode_BinOp::Op::Shr: item_name = "shr"; break;
case ::HIR::ExprNode_BinOp::Op::Shl: item_name = "shl"; break;
}
assert(item_name);
const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
-
+
// NOTE: `true` marks the association as coming from a binary operation, which changes integer handling
this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(right_ty.clone()), left_ty.clone(), "Output", true);
break; }
@@ -912,7 +912,7 @@ namespace {
void visit(::HIR::ExprNode_UniOp& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << " " << ::HIR::ExprNode_UniOp::opname(node.m_op) << "...");
this->context.add_ivars( node.m_value->m_res_type );
const char* item_name = nullptr;
@@ -934,21 +934,21 @@ namespace {
{
TRACE_FUNCTION_F(&node << " &_ ...");
this->context.add_ivars( node.m_value->m_res_type );
-
+
// TODO: Can Ref/RefMut trigger coercions?
this->context.equate_types( node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(node.m_type, node.m_value->m_res_type.clone()) );
-
+
node.m_value->visit( *this );
}
void visit(::HIR::ExprNode_Cast& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << " ... as " << node.m_res_type);
this->context.add_ivars( node.m_value->m_res_type );
-
+
node.m_value->visit( *this );
-
+
// TODO: Only revisit if the cast type requires inferring.
this->context.add_revisit(node);
}
@@ -959,25 +959,25 @@ namespace {
void visit(::HIR::ExprNode_Index& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << " ... [ ... ]");
this->context.add_ivars( node.m_value->m_res_type );
this->context.add_ivars( node.m_index->m_res_type );
-
+
node.m_value->visit( *this );
node.m_index->visit( *this );
-
+
this->context.add_revisit(node);
}
void visit(::HIR::ExprNode_Deref& node) override
{
auto _ = this->push_inner_coerce_scoped(false);
-
+
TRACE_FUNCTION_F(&node << " *...");
this->context.add_ivars( node.m_value->m_res_type );
node.m_value->visit( *this );
-
+
this->context.add_revisit(node);
}
void visit(::HIR::ExprNode_Emplace& node) override
@@ -986,11 +986,11 @@ namespace {
TRACE_FUNCTION_F(&node << " ... <- ... ");
this->context.add_ivars( node.m_place->m_res_type );
this->context.add_ivars( node.m_value->m_res_type );
-
+
node.m_place->visit( *this );
auto _2 = this->push_inner_coerce_scoped(true);
node.m_value->visit( *this );
-
+
this->context.add_revisit(node);
}
@@ -1019,28 +1019,28 @@ namespace {
)
)
}
-
+
::HIR::TypeRef get_structenum_ty(const Span& sp, bool is_struct, ::HIR::GenericPath& gp)
{
if( is_struct )
{
const auto& str = this->context.m_crate.get_struct_by_path(sp, gp.m_path);
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, gp, str.m_params, gp.m_params);
-
+
return ::HIR::TypeRef::new_path( gp.clone(), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) );
}
else
{
auto s_path = gp.m_path;
s_path.m_components.pop_back();
-
+
const auto& enm = this->context.m_crate.get_enum_by_path(sp, s_path);
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, gp, enm.m_params, gp.m_params);
-
+
return ::HIR::TypeRef::new_path( ::HIR::GenericPath(mv$(s_path), gp.m_params.clone()), ::HIR::TypeRef::TypePathBinding::make_Enum(&enm) );
}
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override
{
const auto& sp = node.span();
@@ -1048,11 +1048,11 @@ namespace {
for( auto& val : node.m_args ) {
this->context.add_ivars( val->m_res_type );
}
-
+
// - Create ivars in path, and set result type
const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
this->context.equate_types(node.span(), node.m_res_type, ty);
-
+
const ::HIR::t_tuple_fields* fields_ptr = nullptr;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
(Unbound, ),
@@ -1078,7 +1078,7 @@ namespace {
if( fields.size() != node.m_args.size() ) {
ERROR(node.span(), E0000, "");
}
-
+
const auto& ty_params = node.m_path.m_params.m_types;
auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
@@ -1095,7 +1095,7 @@ namespace {
BUG(sp, "Method-level parameter on struct (#" << ge.binding << " " << ge.name << ")");
}
};
-
+
// Bind fields with type params (coercable)
node.m_arg_types.resize( node.m_args.size() );
for( unsigned int i = 0; i < node.m_args.size(); i ++ )
@@ -1106,10 +1106,10 @@ namespace {
node.m_arg_types[i] = monomorphise_type_with(sp, des_ty_r, monomorph_cb);
des_ty = &node.m_arg_types[i];
}
-
+
this->context.equate_types_coerce(node.span(), *des_ty, node.m_args[i]);
}
-
+
auto _ = this->push_inner_coerce_scoped(true);
for( auto& val : node.m_args ) {
val->visit( *this );
@@ -1124,14 +1124,14 @@ namespace {
if( node.m_base_value ) {
this->context.add_ivars( node.m_base_value->m_res_type );
}
-
+
// - Create ivars in path, and set result type
const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
this->context.equate_types(node.span(), node.m_res_type, ty);
if( node.m_base_value ) {
this->context.equate_types(node.span(), node.m_base_value->m_res_type, ty);
}
-
+
const ::HIR::t_struct_fields* fields_ptr = nullptr;
const ::HIR::GenericParams* generics;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
@@ -1155,7 +1155,7 @@ namespace {
)
ASSERT_BUG(node.span(), fields_ptr, "");
const ::HIR::t_struct_fields& fields = *fields_ptr;
-
+
const auto& ty_params = node.m_path.m_params.m_types;
auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
@@ -1172,9 +1172,9 @@ namespace {
BUG(node.span(), "Method-level parameter on struct (#" << ge.binding << " " << ge.name << ")");
}
};
-
+
node.m_value_types.resize( fields.size() );
-
+
// Bind fields with type params (coercable)
for( auto& val : node.m_values)
{
@@ -1184,7 +1184,7 @@ namespace {
const auto& des_ty_r = it->second.ent;
auto& des_ty_cache = node.m_value_types[it - fields.begin()];
const auto* des_ty = &des_ty_r;
-
+
DEBUG(name << " : " << des_ty_r);
if( monomorphise_type_needed(des_ty_r) ) {
if( des_ty_cache == ::HIR::TypeRef() ) {
@@ -1197,10 +1197,10 @@ namespace {
}
this->equate_types_inner_coerce(node.span(), *des_ty, val.second);
}
-
+
// Convert bounds on the type into rules
apply_bounds_as_rules(context, node.span(), *generics, monomorph_cb);
-
+
auto _ = this->push_inner_coerce_scoped(true);
for( auto& val : node.m_values ) {
val.second->visit( *this );
@@ -1215,13 +1215,13 @@ namespace {
const Span& sp = node.span();
TRACE_FUNCTION_F(&node << " " << node.m_path << "{ " << node.m_variant_name << ": ... }");
this->context.add_ivars( node.m_value->m_res_type );
-
+
const auto& unm = this->context.m_crate.get_union_by_path(sp, node.m_path.m_path);
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, node.m_path, unm.m_params, node.m_path.m_params);
const auto ty = ::HIR::TypeRef::new_path( node.m_path.clone(), ::HIR::TypeRef::TypePathBinding::make_Union(&unm) );
-
+
this->context.equate_types(node.span(), node.m_res_type, ty);
-
+
const auto& ty_params = node.m_path.m_params.m_types;
auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
@@ -1238,7 +1238,7 @@ namespace {
BUG(node.span(), "Method-level parameter on struct (#" << ge.binding << " " << ge.name << ")");
}
};
-
+
// Convert bounds on the type into rules
apply_bounds_as_rules(context, node.span(), unm.m_params, monomorph_cb);
@@ -1257,15 +1257,15 @@ namespace {
des_ty = &des_ty_cache;
}
this->equate_types_inner_coerce(node.span(), *des_ty, node.m_value);
-
+
node.m_value->visit(*this);
}
void visit(::HIR::ExprNode_UnitVariant& node) override
{
TRACE_FUNCTION_F(&node << " " << node.m_path << " [" << (node.m_is_struct ? "struct" : "enum") << "]");
-
+
// TODO: Check?
-
+
// - Create ivars in path, and set result type
const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
this->context.equate_types(node.span(), node.m_res_type, ty);
@@ -1278,7 +1278,7 @@ namespace {
for( auto& val : node.m_args ) {
this->context.add_ivars( val->m_res_type );
}
-
+
// Populate cache
{
if( !visit_call_populate_cache(this->context, node.span(), node.m_path, node.m_cache) ) {
@@ -1286,7 +1286,7 @@ namespace {
}
assert( node.m_cache.m_arg_types.size() >= 1);
unsigned int exp_argc = node.m_cache.m_arg_types.size() - 1;
-
+
if( node.m_args.size() != exp_argc ) {
if( node.m_cache.m_fcn->m_variadic && node.m_args.size() > exp_argc ) {
}
@@ -1296,7 +1296,7 @@ namespace {
}
}
}
-
+
// Link arguments
// - NOTE: Uses the cache for the count because vaargs aren't checked (they're checked for suitability in expr_check.cpp)
for(unsigned int i = 0; i < node.m_cache.m_arg_types.size() - 1; i ++)
@@ -1331,7 +1331,7 @@ namespace {
this->context.equate_types_coerce(val->span(), node.m_arg_ivars[i], val);
val->visit( *this );
}
-
+
// Nothing can be done until type is known
this->context.add_revisit(node);
}
@@ -1345,7 +1345,7 @@ namespace {
for( auto& ty : node.m_params.m_types ) {
this->context.add_ivars( ty );
}
-
+
// - Search in-scope trait list for traits that provide a method of this name
const ::std::string& method_name = node.m_method;
::HIR::t_trait_list possible_traits;
@@ -1354,14 +1354,14 @@ namespace {
{
if( trait_ref.first == nullptr )
break;
-
+
// TODO: Search supertraits too
auto it = trait_ref.second->m_values.find(method_name);
if( it == trait_ref.second->m_values.end() )
continue ;
if( !it->second.is_Function() )
continue ;
-
+
if( ::std::none_of( possible_traits.begin(), possible_traits.end(), [&](const auto&x){return x.second == trait_ref.second;}) ) {
possible_traits.push_back( trait_ref );
if( trait_ref.second->m_params.m_types.size() > max_num_params )
@@ -1374,7 +1374,7 @@ namespace {
{
node.m_trait_param_ivars.push_back( this->context.m_ivars.new_ivar() );
}
-
+
{
auto _ = this->push_inner_coerce_scoped(false);
node.m_value->visit( *this );
@@ -1383,7 +1383,7 @@ namespace {
for( auto& val : node.m_args ) {
val->visit( *this );
}
-
+
// Resolution can't be done until lefthand type is known.
// > Has to be done during iteraton
this->context.add_revisit( node );
@@ -1393,19 +1393,19 @@ namespace {
auto _ = this->push_inner_coerce_scoped(false);
TRACE_FUNCTION_F(&node << " (...)."<<node.m_field);
this->context.add_ivars( node.m_value->m_res_type );
-
+
node.m_value->visit( *this );
-
+
this->context.add_revisit( node );
}
-
+
void visit(::HIR::ExprNode_Tuple& node) override
{
TRACE_FUNCTION_F(&node << " (...,)");
for( auto& val : node.m_vals ) {
this->context.add_ivars( val->m_res_type );
}
-
+
if( can_coerce_inner_result() )
{
const auto& ty = this->context.get_type(node.m_res_type);
@@ -1428,7 +1428,7 @@ namespace {
}
const auto& inner_tys = this->context.get_type(node.m_res_type).m_data.as_Tuple();
assert( inner_tys.size() == node.m_vals.size() );
-
+
for(unsigned int i = 0; i < inner_tys.size(); i ++)
{
this->context.equate_types_coerce(node.span(), inner_tys[i], node.m_vals[i]);
@@ -1443,7 +1443,7 @@ namespace {
}
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(mv$(tuple_tys)));
}
-
+
for( auto& val : node.m_vals ) {
val->visit( *this );
}
@@ -1454,14 +1454,14 @@ namespace {
for( auto& val : node.m_vals ) {
this->context.add_ivars( val->m_res_type );
}
-
+
// Cleanly equate into array (with coercions)
// - Result type already set, just need to extract ivar
const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner;
for( auto& val : node.m_vals ) {
this->equate_types_inner_coerce(node.span(), inner_ty, val);
}
-
+
for( auto& val : node.m_vals ) {
val->visit( *this );
}
@@ -1471,7 +1471,7 @@ namespace {
TRACE_FUNCTION_F(&node << " [...; "<<node.m_size_val<<"]");
this->context.add_ivars( node.m_val->m_res_type );
this->context.add_ivars( node.m_size->m_res_type );
-
+
// Create result type (can't be known until after const expansion)
// - Should it be created in const expansion?
auto ty = ::HIR::TypeRef::new_array( ::HIR::TypeRef(), node.m_size_val );
@@ -1481,11 +1481,11 @@ namespace {
const auto& inner_ty = *ty.m_data.as_Array().inner;
this->equate_types_inner_coerce(node.span(), inner_ty, node.m_val);
this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type);
-
+
node.m_val->visit( *this );
node.m_size->visit( *this );
}
-
+
void visit(::HIR::ExprNode_Literal& node) override
{
TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e),
@@ -1511,9 +1511,9 @@ namespace {
const auto& sp = node.span();
this->visit_path(sp, node.m_path);
TRACE_FUNCTION_F(&node << " " << node.m_path);
-
+
this->add_ivars_path(node.span(), node.m_path);
-
+
TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e),
(Generic,
switch(node.m_target) {
@@ -1522,7 +1522,7 @@ namespace {
case ::HIR::ExprNode_PathValue::FUNCTION: {
const auto& f = this->context.m_crate.get_function_by_path(sp, e.m_path);
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, e, f.m_params, e.m_params);
-
+
const auto& params = e.m_params;
auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& e = gt.m_data.as_Generic();
@@ -1543,7 +1543,7 @@ namespace {
BUG(sp, "Unknown param in free function - " << gt);
}
};
-
+
::HIR::FunctionType ft {
f.m_unsafe,
f.m_abi,
@@ -1554,7 +1554,7 @@ namespace {
{
ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
}
-
+
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
this->context.equate_types(sp, node.m_res_type, ty);
} break;
@@ -1562,7 +1562,7 @@ namespace {
const auto& s = this->context.m_crate.get_struct_by_path(sp, e.m_path);
const auto& se = s.m_data.as_Tuple();
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, e, s.m_params, e.m_params);
-
+
::HIR::FunctionType ft {
false,
ABI_RUST,
@@ -1573,7 +1573,7 @@ namespace {
{
ft.m_arg_types.push_back( monomorphise_type(sp, s.m_params, e.m_params, arg.ent) );
}
-
+
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
this->context.equate_types(sp, node.m_res_type, ty);
} break;
@@ -1585,7 +1585,7 @@ namespace {
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, e, enm.m_params, e.m_params);
const auto& var = *::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == var_name; });
const auto& var_data = var.second.as_Tuple();
-
+
::HIR::FunctionType ft {
false,
ABI_RUST,
@@ -1596,7 +1596,7 @@ namespace {
{
ft.m_arg_types.push_back( monomorphise_type(sp, enm.m_params, e.m_params, arg.ent) );
}
-
+
auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
this->context.equate_types(sp, node.m_res_type, ty);
} break;
@@ -1621,10 +1621,10 @@ namespace {
(UfcsKnown,
const auto& trait = this->context.m_crate.get_trait_by_path(sp, e.trait.m_path);
fix_param_count(sp, this->context, *e.type, true, e.trait, trait.m_params, e.trait.m_params);
-
+
// 1. Add trait bound to be checked.
this->context.add_trait_bound(sp, *e.type, e.trait.m_path, e.trait.m_params.clone());
-
+
// 2. Locate this item in the trait
// - If it's an associated `const`, will have to revisit
auto it = trait.m_values.find( e.item );
@@ -1643,7 +1643,7 @@ namespace {
),
(Function,
fix_param_count(sp, this->context, *e.type, false, node.m_path, ie.m_params, e.params);
-
+
const auto& fcn_params = e.params;
const auto& trait_params = e.trait.m_params;
auto monomorph_cb = [&](const auto& gt)->const auto& {
@@ -1675,14 +1675,14 @@ namespace {
for(const auto& arg : ie.m_args)
ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
auto ty = ::HIR::TypeRef(mv$(ft));
-
+
this->context.equate_types(node.span(), node.m_res_type, ty);
)
)
),
(UfcsInherent,
// TODO: Share code with visit_call_populate_cache
-
+
// - Locate function (and impl block)
const ::HIR::Function* fcn_ptr = nullptr;
const ::HIR::Constant* const_ptr = nullptr;
@@ -1719,17 +1719,17 @@ namespace {
if( count > 1 ) {
TODO(sp, "Revisit _PathValue when UfcsInherent has multiple options - " << node.m_path);
}
-
+
assert(fcn_ptr || const_ptr);
assert(impl_ptr);
-
+
if( fcn_ptr ) {
fix_param_count(sp, this->context, *e.type, false, node.m_path, fcn_ptr->m_params, e.params);
}
else {
fix_param_count(sp, this->context, *e.type, false, node.m_path, const_ptr->m_params, e.params);
}
-
+
// If the impl block has parameters, figure out what types they map to
// - The function params are already mapped (from fix_param_count)
auto& impl_params = e.impl_params;
@@ -1743,8 +1743,8 @@ namespace {
for(const auto& ty : impl_params.m_types)
assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) );
}
-
-
+
+
if( fcn_ptr )
{
// Create monomorphise callback
@@ -1772,9 +1772,9 @@ namespace {
BUG(sp, "Generic bounding out of total range");
}
};
-
+
// TODO: Impl/method type bounds
-
+
::HIR::FunctionType ft {
fcn_ptr->m_unsafe, fcn_ptr->m_abi,
box$( monomorphise_type_with(sp, fcn_ptr->m_return, monomorph_cb) ),
@@ -1783,16 +1783,16 @@ namespace {
for(const auto& arg : fcn_ptr->m_args)
ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
auto ty = ::HIR::TypeRef(mv$(ft));
-
+
this->context.equate_types(node.span(), node.m_res_type, ty);
}
else // !fcn_ptr, ergo const_ptr
{
auto monomorph_cb = monomorphise_type_get_cb(sp, &*e.type, &impl_params, &e.params);
-
+
::HIR::TypeRef tmp;
const auto& ty = ( monomorphise_type_needed(const_ptr->m_type) ? tmp = monomorphise_type_with(sp, const_ptr->m_type, monomorph_cb) : const_ptr->m_type );
-
+
this->context.equate_types(node.span(), node.m_res_type, ty);
}
)
@@ -1801,10 +1801,10 @@ namespace {
void visit(::HIR::ExprNode_Variable& node) override
{
TRACE_FUNCTION_F(&node << " " << node.m_name << "{" << node.m_slot << "}");
-
+
this->context.equate_types(node.span(), node.m_res_type, this->context.get_var(node.span(), node.m_slot));
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
TRACE_FUNCTION_F(&node << " |...| ...");
@@ -1814,7 +1814,7 @@ namespace {
}
this->context.add_ivars( node.m_return );
this->context.add_ivars( node.m_code->m_res_type );
-
+
// Closure result type
::std::vector< ::HIR::TypeRef> arg_types;
for(auto& arg : node.m_args) {
@@ -1823,13 +1823,13 @@ namespace {
this->context.equate_types( node.span(), node.m_res_type, ::HIR::TypeRef::new_closure(&node, mv$(arg_types), node.m_return.clone()) );
this->context.equate_types_coerce( node.span(), node.m_return, node.m_code );
-
+
auto _ = this->push_inner_coerce_scoped(true);
this->closure_ret_types.push_back( &node.m_return );
node.m_code->visit( *this );
this->closure_ret_types.pop_back( );
}
-
+
private:
void push_traits(const ::HIR::t_trait_list& list) {
this->m_traits.insert( this->m_traits.end(), list.begin(), list.end() );
@@ -1862,7 +1862,7 @@ namespace {
)
)
}
-
+
class InnerCoerceGuard {
ExprVisitor_Enum& t;
public:
@@ -1920,23 +1920,23 @@ namespace {
context(context),
m_completed(false)
{}
-
+
bool node_completed() const {
return m_completed;
}
void visit(::HIR::ExprNode_Block& node) override {
-
+
const auto is_diverge = [&](const ::HIR::TypeRef& rty)->bool {
const auto& ty = this->context.get_type(rty);
// TODO: Search the entire type for `!`? (What about pointers to it? or Option/Result?)
// - A correct search will search for unconditional (ignoring enums with a non-! variant) non-rawptr instances of ! in the type
return ty.m_data.is_Diverge();// || (ty.m_data.is_Infer() && ty.m_data.as_Infer().ty_class == ::HIR::InferClass::Diverge);
};
-
+
const auto& last_ty = this->context.get_type( node.m_nodes.back()->m_res_type );
DEBUG("_Block: last_ty = " << last_ty);
-
+
bool diverges = false;
// NOTE: If the final statement in the block diverges, mark this as diverging
TU_IFLET(::HIR::TypeRef::Data, last_ty.m_data, Infer, e,
@@ -1985,7 +1985,7 @@ namespace {
void visit(::HIR::ExprNode_If& node) override {
no_revisit(node);
}
-
+
void visit(::HIR::ExprNode_Assign& node) override {
no_revisit(node);
}
@@ -2003,12 +2003,12 @@ namespace {
const auto& tgt_ty = this->context.get_type(node.m_res_type);
const auto& src_ty = this->context.get_type(node.m_value->m_res_type);
TRACE_FUNCTION_F(src_ty << " as " << tgt_ty);
-
+
if( this->context.m_ivars.types_equal(src_ty, tgt_ty) ) {
this->m_completed = true;
return ;
}
-
+
TU_MATCH( ::HIR::TypeRef::Data, (tgt_ty.m_data), (e),
(Infer,
// Can't know anything
@@ -2123,7 +2123,7 @@ namespace {
ERROR(sp, E0000, "Invalid cast from " << src_ty << " to " << tgt_ty);
}
const auto& src_inner = this->context.get_type(*s_e.inner);
-
+
// NOTE: &mut T -> *mut U where T: Unsize<U> is allowed
// TODO: Wouldn't this be better served by a coercion point?
TU_IFLET( ::HIR::TypeRef::Data, src_inner.m_data, Infer, s_e_i,
@@ -2184,22 +2184,22 @@ namespace {
const auto& val_ty = this->context.get_type(node.m_value->m_res_type);
const auto& idx_ty = this->context.get_type(node.m_index->m_res_type);
TRACE_FUNCTION_F("Index: val=" << val_ty << ", idx=" << idx_ty << "");
-
+
this->context.equate_types_from_shadow(node.span(), node.m_res_type);
-
+
// NOTE: Indexing triggers autoderef
unsigned int deref_count = 0;
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
const auto* current_ty = &node.m_value->m_res_type;
::std::vector< ::HIR::TypeRef> deref_res_types;
-
+
// TODO: (CHECK) rustc doesn't use the index value type when finding the indexable item, mrustc does.
::HIR::PathParams trait_pp;
trait_pp.m_types.push_back( idx_ty.clone() );
do {
const auto& ty = this->context.get_type(*current_ty);
DEBUG("(Index): (: " << ty << ")[: " << trait_pp.m_types[0] << "]");
-
+
::HIR::TypeRef possible_index_type;
::HIR::TypeRef possible_res_type;
unsigned int count = 0;
@@ -2231,13 +2231,13 @@ namespace {
else {
// Either no matches, or multiple fuzzy matches
}
-
+
deref_count += 1;
current_ty = this->context.m_resolve.autoderef(node.span(), ty, tmp_type);
if( current_ty )
deref_res_types.push_back( current_ty->clone() );
} while( current_ty );
-
+
if( current_ty )
{
DEBUG("Found impl on type " << *current_ty << " with " << deref_count << " derefs");
@@ -2245,18 +2245,18 @@ namespace {
for(auto& ty_r : deref_res_types)
{
auto ty = mv$(ty_r);
-
+
node.m_value = this->context.create_autoderef( mv$(node.m_value), mv$(ty) );
context.m_ivars.get_type(node.m_value->m_res_type);
}
-
+
m_completed = true;
}
}
void visit(::HIR::ExprNode_Deref& node) override {
const auto& ty = this->context.get_type(node.m_value->m_res_type);
TRACE_FUNCTION_F("Deref: ty=" << ty);
-
+
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty.m_data), (e),
(
const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "deref");
@@ -2284,7 +2284,7 @@ namespace {
const auto& data_ty = node.m_value->m_res_type;
auto node_ty = node.m_type;
TRACE_FUNCTION_F("_Emplace: exp_ty=" << exp_ty);
-
+
if( exp_ty.m_data.is_Infer() ) {
// If the expected result type is still an ivar, nothing can be done
@@ -2315,7 +2315,7 @@ namespace {
if( gpath.m_params.m_types.size() > 0 )
{
// TODO: If there's only one, check if it's a valid coercion target, if not don't bother making the coercion.
-
+
// Take a copy of the type with all type parameters replaced with new ivars
auto newpath = ::HIR::GenericPath(gpath.m_path);
for( const auto& t : gpath.m_params.m_types )
@@ -2324,7 +2324,7 @@ namespace {
newpath.m_params.m_types.push_back( this->context.m_ivars.new_ivar_tr() );
}
auto newty = ::HIR::TypeRef::new_path( mv$(newpath), exp_ty.m_data.as_Path().binding.clone() );
-
+
// Turn this revisit into a coercion point with the new result type
// - Mangle this node to be a passthrough to a copy of itself.
@@ -2332,14 +2332,14 @@ namespace {
node.m_type = ::HIR::ExprNode_Emplace::Type::Noop;
node.m_value->m_res_type = mv$(newty);
inner_ty = &node.m_value->m_res_type;
-
+
this->context.equate_types_coerce(sp, exp_ty, node.m_value);
}
else
{
inner_ty = &exp_ty;
}
-
+
// Insert a trait bound on the result type to impl `Placer/Boxer`
switch( node_ty )
{
@@ -2354,10 +2354,10 @@ namespace {
this->context.equate_types_assoc(sp, {}, ::HIR::SimplePath("core", { "ops", "Placer" }), ::make_vec1(data_ty.clone()), *inner_ty, "");
break;
}
-
+
this->m_completed = true;
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override {
no_revisit(node);
}
@@ -2368,23 +2368,23 @@ namespace {
//const auto& sp = node.span();
const auto& ty_o = this->context.get_type(node.m_value->m_res_type);
TRACE_FUNCTION_F("CallValue: ty=" << ty_o);
-
+
// - Shadow (prevent ivar guessing) every parameter
this->context.equate_types_from_shadow(node.span(), node.m_res_type);
for( const auto& arg_ty : node.m_arg_ivars ) {
this->context.equate_types_to_shadow(node.span(), arg_ty);
}
-
+
if( ty_o.m_data.is_Infer() ) {
// - Don't even bother
return ;
}
-
+
const auto& lang_FnOnce = this->context.m_crate.get_lang_item_path(node.span(), "fn_once");
const auto& lang_FnMut = this->context.m_crate.get_lang_item_path(node.span(), "fn_mut");
const auto& lang_Fn = this->context.m_crate.get_lang_item_path(node.span(), "fn");
-
-
+
+
// 1. Create a param set with a single tuple (of all argument types)
::HIR::PathParams trait_pp;
{
@@ -2394,37 +2394,37 @@ namespace {
}
trait_pp.m_types.push_back( ::HIR::TypeRef( mv$(arg_types) ) );
}
-
+
unsigned int deref_count = 0;
::HIR::TypeRef tmp_type; // for autoderef
const auto* ty_p = &ty_o;
-
+
bool keep_looping = false;
do // } while( keep_looping );
{
// Reset at the start of each loop
keep_looping = false;
-
+
const auto& ty = *ty_p;
DEBUG("- ty = " << ty);
TU_MATCH_DEF(decltype(ty.m_data), (ty.m_data), (e),
(
::HIR::TypeRef fcn_args_tup;
::HIR::TypeRef fcn_ret;
-
+
// TODO: Use `find_trait_impls` instead of two different calls
// - This will get the TraitObject impl search too
-
+
// Locate an impl of FnOnce (exists for all other Fn* traits)
unsigned int count = 0;
this->context.m_resolve.find_trait_impls(node.span(), lang_FnOnce, trait_pp, ty, [&](auto impl, auto cmp) {
count ++;
-
+
auto tup = impl.get_trait_ty_param(0);
if( !tup.m_data.is_Tuple() )
ERROR(node.span(), E0000, "FnOnce expects a tuple argument, got " << tup);
fcn_args_tup = mv$(tup);
-
+
fcn_ret = impl.get_type("Output");
DEBUG("[visit:_CallValue] fcn_args_tup=" << fcn_args_tup << ", fcn_ret=" << fcn_ret);
return cmp == ::HIR::Compare::Equal;
@@ -2435,7 +2435,7 @@ namespace {
}
if( count == 1 )
{
-
+
// 3. Locate the most permissive implemented Fn* trait (Fn first, then FnMut, then assume just FnOnce)
// NOTE: Borrowing is added by the expansion to CallPath
if( this->context.m_resolve.find_trait_impls(node.span(), lang_Fn, trait_pp, ty, [&](auto impl, auto cmp) {
@@ -2448,7 +2448,7 @@ namespace {
{
DEBUG("-- Using Fn");
node.m_trait_used = ::HIR::ExprNode_CallValue::TraitUsed::Fn;
-
+
this->context.equate_types_assoc(node.span(), node.m_res_type, lang_Fn, ::make_vec1( fcn_args_tup.clone() ), ty, "Output");
}
else if( this->context.m_resolve.find_trait_impls(node.span(), lang_FnMut, trait_pp, ty, [&](auto impl, auto cmp) {
@@ -2461,17 +2461,17 @@ namespace {
{
DEBUG("-- Using FnMut");
node.m_trait_used = ::HIR::ExprNode_CallValue::TraitUsed::FnMut;
-
+
this->context.equate_types_assoc(node.span(), node.m_res_type, lang_FnMut, ::make_vec1( fcn_args_tup.clone() ), ty, "Output");
}
else
{
DEBUG("-- Using FnOnce (default)");
node.m_trait_used = ::HIR::ExprNode_CallValue::TraitUsed::FnOnce;
-
+
this->context.equate_types_assoc(node.span(), node.m_res_type, lang_FnOnce, ::make_vec1( fcn_args_tup.clone() ), ty, "Output");
}
-
+
// If the return type wasn't found in the impls, emit it as a UFCS
if( fcn_ret == ::HIR::TypeRef() )
{
@@ -2498,7 +2498,7 @@ namespace {
bool found = this->context.m_resolve.find_trait_impls_crate(node.span(), lang_FnOnce, trait_pp, ty, [&](auto impl, auto cmp) {
if( cmp == ::HIR::Compare::Fuzzy )
TODO(node.span(), "Handle fuzzy match - " << impl);
-
+
auto tup = impl.get_trait_ty_param(0);
if( !tup.m_data.is_Tuple() )
ERROR(node.span(), E0000, "FnOnce expects a tuple argument, got " << tup);
@@ -2523,11 +2523,11 @@ namespace {
keep_looping = true;
continue ;
}
-
+
// Didn't find anything. Error?
ERROR(node.span(), E0000, "Unable to find an implementation of Fn*"<<trait_pp<<" for " << this->context.m_ivars.fmt_type(ty));
}
-
+
node.m_arg_types = mv$( fcn_args_tup.m_data.as_Tuple() );
node.m_arg_types.push_back( mv$(fcn_ret) );
),
@@ -2549,7 +2549,7 @@ namespace {
)
)
} while( keep_looping );
-
+
if( deref_count > 0 )
{
ty_p = &ty_o;
@@ -2560,7 +2560,7 @@ namespace {
node.m_value = this->context.create_autoderef( mv$(node.m_value), ty_p->clone() );
}
}
-
+
assert( node.m_arg_types.size() == node.m_args.size() + 1 );
for(unsigned int i = 0; i < node.m_args.size(); i ++)
{
@@ -2571,16 +2571,16 @@ namespace {
}
void visit(::HIR::ExprNode_CallMethod& node) override {
const auto& sp = node.span();
-
+
const auto& ty = this->context.get_type(node.m_value->m_res_type);
TRACE_FUNCTION_F("(CallMethod) {" << this->context.m_ivars.fmt_type(ty) << "}." << node.m_method << node.m_params);
-
+
// Make sure that no mentioned types are inferred until this method is known
this->context.equate_types_from_shadow(node.span(), node.m_res_type);
for( const auto& arg_node : node.m_args ) {
this->context.equate_types_to_shadow(node.span(), arg_node->m_res_type);
}
-
+
// Using autoderef, locate this method on the type
::HIR::Path fcn_path { ::HIR::SimplePath() };
TraitResolution::AutoderefBorrow ad_borrow;
@@ -2588,7 +2588,7 @@ namespace {
if( deref_count != ~0u )
{
DEBUG("- deref_count = " << deref_count << ", fcn_path = " << fcn_path);
-
+
node.m_method_path = mv$(fcn_path);
// NOTE: Steals the params from the node
TU_MATCH(::HIR::Path::Data, (node.m_method_path.m_data), (e),
@@ -2610,15 +2610,15 @@ namespace {
return ;
}
DEBUG("> m_method_path = " << node.m_method_path);
-
+
assert( node.m_cache.m_arg_types.size() >= 1);
-
+
if( node.m_args.size()+1 != node.m_cache.m_arg_types.size() - 1 ) {
ERROR(node.span(), E0000, "Incorrect number of arguments to " << node.m_method_path
<< " - exp " << node.m_cache.m_arg_types.size()-2 << " got " << node.m_args.size());
}
DEBUG("- fcn_path=" << node.m_method_path);
-
+
// --- Check and equate self/arguments/return
DEBUG("node.m_cache.m_arg_types = " << node.m_cache.m_arg_types);
// NOTE: `Self` is equated after autoderef and autoref
@@ -2630,7 +2630,7 @@ namespace {
}
DEBUG("> Ret : " << node.m_cache.m_arg_types.back());
this->context.equate_types(sp, node.m_res_type, node.m_cache.m_arg_types.back());
-
+
// Add derefs
if( deref_count > 0 )
{
@@ -2646,11 +2646,11 @@ namespace {
cur_ty = this->context.m_resolve.autoderef(span, *cur_ty, tmp_ty);
assert(cur_ty);
auto ty = cur_ty->clone();
-
+
node.m_value = this->context.create_autoderef( mv$(node.m_value), mv$(ty) );
}
}
-
+
// Autoref
if( ad_borrow != TraitResolution::AutoderefBorrow::None )
{
@@ -2662,7 +2662,7 @@ namespace {
case TraitResolution::AutoderefBorrow::Unique: bt = ::HIR::BorrowType::Unique; break;
case TraitResolution::AutoderefBorrow::Owned : bt = ::HIR::BorrowType::Owned ; break;
}
-
+
auto ty = ::HIR::TypeRef::new_borrow(bt, node.m_value->m_res_type.clone());
DEBUG("- Ref (cmd) " << &*node.m_value << " -> " << ty);
auto span = node.m_value->span();
@@ -2672,7 +2672,7 @@ namespace {
{
auto receiver_class = node.m_cache.m_fcn->m_receiver;
::HIR::BorrowType bt;
-
+
auto& node_ptr = node.m_value;
auto span = node_ptr->span();
switch(receiver_class)
@@ -2697,7 +2697,7 @@ namespace {
ASSERT_BUG(sp, deref_ptr != nullptr, "Calling Box receiver method but no deref happened");
node_ptr = mv$(deref_ptr->m_value);
DEBUG("- Undo deref " << deref_ptr << " -> " << node_ptr->m_res_type);
-
+
// Triple-check that the input to the above Deref was a Box (lang="owned_box")
const auto& box_ty = this->context.get_type(node_ptr->m_res_type);
TU_IFLET(::HIR::TypeRef::Data, box_ty.m_data, Path, e,
@@ -2718,10 +2718,10 @@ namespace {
} break;
}
}
-
+
// Equate the type for `self` (to ensure that Self's type params infer correctly)
this->context.equate_types(sp, node.m_cache.m_arg_types[0], node.m_value->m_res_type);
-
+
this->m_completed = true;
}
}
@@ -2738,7 +2738,7 @@ namespace {
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
const auto* current_ty = &node.m_value->m_res_type;
::std::vector< ::HIR::TypeRef> deref_res_types;
-
+
do {
const auto& ty = this->context.m_ivars.get_type(*current_ty);
if( ty.m_data.is_Infer() ) {
@@ -2753,18 +2753,18 @@ namespace {
this->context.equate_types(node.span(), node.m_res_type, out_type);
break;
}
-
+
deref_count += 1;
current_ty = this->context.m_resolve.autoderef(node.span(), ty, tmp_type);
if( current_ty )
deref_res_types.push_back( current_ty->clone() );
} while(current_ty);
-
+
if( !current_ty )
{
ERROR(node.span(), E0000, "Couldn't find the field " << field_name << " in " << this->context.m_ivars.fmt_type(node.m_value->m_res_type));
}
-
+
assert( deref_count == deref_res_types.size() );
for(unsigned int i = 0; i < deref_res_types.size(); i ++ )
{
@@ -2776,7 +2776,7 @@ namespace {
node.m_value = NEWNODE(mv$(ty), node.span(), _Deref, mv$(node.m_value));
context.m_ivars.get_type(node.m_value->m_res_type);
}
-
+
m_completed = true;
}
@@ -2792,7 +2792,7 @@ namespace {
void visit(::HIR::ExprNode_Variable& node) override {
no_revisit(node);
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override {
no_revisit(node);
}
@@ -2808,7 +2808,7 @@ namespace {
void visit(::HIR::ExprNode_ArraySized& node) override {
no_revisit(node);
}
-
+
void visit(::HIR::ExprNode_Closure& node) override {
no_revisit(node);
}
@@ -2817,7 +2817,7 @@ namespace {
BUG(node.span(), "Node revisit unexpected - " << typeid(node).name());
}
};
-
+
// -----------------------------------------------------------------------
// Post-inferrence visitor
//
@@ -2839,16 +2839,16 @@ namespace {
{
auto& node = *node_ptr;
const char* node_ty = typeid(node).name();
-
+
TRACE_FUNCTION_FR(&node << " " << &node << " " << node_ty << " : " << node.m_res_type, node_ty);
this->check_type_resolved_top(node.span(), node.m_res_type);
DEBUG(node_ty << " : = " << node.m_res_type);
-
+
node_ptr->visit(*this);
-
+
for( auto& ty : node_ptr.m_bindings )
this->check_type_resolved_top(node.span(), ty);
-
+
for( auto& ty : node_ptr.m_erased_types )
this->check_type_resolved_top(node.span(), ty);
}
@@ -2860,7 +2860,7 @@ namespace {
DEBUG(node_ty << " : = " << node.m_res_type);
::HIR::ExprVisitorDef::visit_node_ptr(node_ptr);
}
-
+
void visit_pattern(const Span& sp, ::HIR::Pattern& pat) override {
TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (e),
(
@@ -2899,7 +2899,7 @@ namespace {
)
::HIR::ExprVisitorDef::visit_pattern(sp, pat);
}
-
+
void visit(::HIR::ExprNode_Let& node) override {
this->check_type_resolved_top(node.span(), node.m_type);
::HIR::ExprVisitorDef::visit(node);
@@ -2910,7 +2910,7 @@ namespace {
this->check_type_resolved_top(node.span(), node.m_return);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit_callcache(const Span&sp, ::HIR::ExprCallCache& cache)
{
for(auto& ty : cache.m_arg_types)
@@ -2918,13 +2918,13 @@ namespace {
}
void visit(::HIR::ExprNode_CallPath& node) override {
this->visit_callcache(node.span(), node.m_cache);
-
+
this->check_type_resolved_path(node.span(), node.m_path);
::HIR::ExprVisitorDef::visit(node);
}
void visit(::HIR::ExprNode_CallMethod& node) override {
this->visit_callcache(node.span(), node.m_cache);
-
+
this->check_type_resolved_path(node.span(), node.m_method_path);
::HIR::ExprVisitorDef::visit(node);
}
@@ -2933,7 +2933,7 @@ namespace {
this->check_type_resolved_top(node.span(), ty);
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_PathValue& node) override {
this->check_type_resolved_path(node.span(), node.m_path);
}
@@ -2947,7 +2947,7 @@ namespace {
this->check_type_resolved_top(node.span(), ty);
}
}
-
+
::HIR::ExprVisitorDef::visit(node);
}
void visit(::HIR::ExprNode_TupleVariant& node) override {
@@ -2957,10 +2957,10 @@ namespace {
this->check_type_resolved_top(node.span(), ty);
}
}
-
+
::HIR::ExprVisitorDef::visit(node);
}
-
+
void visit(::HIR::ExprNode_Literal& node) override {
TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e),
(Integer,
@@ -3109,15 +3109,15 @@ void Context::dump() const {
}
void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR::TypeRef& ri) {
-
+
if( li == ri || this->m_ivars.get_type(li) == this->m_ivars.get_type(ri) ) {
DEBUG(li << " == " << ri);
return ;
}
-
+
// Instantly apply equality
TRACE_FUNCTION_F(li << " == " << ri);
-
+
visit_ty_with(ri, [&](const auto& ty) {
if( ty.m_data.is_Generic() && ty.m_data.as_Generic().binding >> 8 == 2 ) {
BUG(sp, "Type contained an impl placeholder parameter - " << ri);
@@ -3135,16 +3135,16 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR
::HIR::TypeRef r_tmp;
const auto& l_t = this->m_resolve.expand_associated_types(sp, this->m_ivars.get_type(li), l_tmp);
const auto& r_t = this->m_resolve.expand_associated_types(sp, this->m_ivars.get_type(ri), r_tmp);
-
+
equate_types_inner(sp, l_t, r_t);
}
void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const ::HIR::TypeRef& ri) {
-
+
if( li == ri || this->m_ivars.get_type(li) == this->m_ivars.get_type(ri) ) {
return ;
}
-
+
// Check if the type contains a replacable associated type
::HIR::TypeRef l_tmp;
::HIR::TypeRef r_tmp;
@@ -3153,7 +3153,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
if( l_t == r_t ) {
return ;
}
-
+
// If either side is still a UfcsUnkonw after `expand_associated_types`, then emit an assoc bound instead of damaging ivars
TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Path, r_e,
TU_IFLET(::HIR::Path::Data, r_e.path.m_data, UfcsKnown, rpe,
@@ -3171,7 +3171,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
}
)
)
-
+
DEBUG("- l_t = " << l_t << ", r_t = " << r_t);
TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Infer, r_e,
TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Infer, l_e,
@@ -3199,7 +3199,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
this->equate_types_inner(sp, l.m_types[i], r.m_types[i]);
}
};
-
+
// If either side is !, return early
// TODO: Should ! end up in an ivar?
#if 1
@@ -3225,7 +3225,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const
return ;
}
#endif
-
+
if( l_t.m_data.tag() != r_t.m_data.tag() ) {
ERROR(sp, E0000, "Type mismatch between " << this->m_ivars.fmt_type(l_t) << " and " << this->m_ivars.fmt_type(r_t));
}
@@ -3392,14 +3392,14 @@ void Context::add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb,
void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type)
{
TRACE_FUNCTION_F("pat = " << pat << ", type = " << type);
-
+
if( pat.m_binding.is_valid() ) {
this->add_binding_inner(sp, pat.m_binding, type.clone());
-
+
// TODO: Bindings aren't allowed within another binding
}
-
-
+
+
struct H {
static void handle_value(Context& context, const Span& sp, const ::HIR::TypeRef& type, const ::HIR::Pattern::Value& val) {
TU_MATCH(::HIR::Pattern::Value, (val), (v),
@@ -3429,8 +3429,8 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
)
}
};
-
- //
+
+ //
TU_MATCH(::HIR::Pattern::Data, (pat.m_data), (e),
(Any,
// Just leave it, the pattern says nothing
@@ -3482,16 +3482,16 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
(Tuple,
const auto& ty = this->get_type(type);
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, te,
-
- if( e.sub_patterns.size() != te.size() ) {
+
+ if( e.sub_patterns.size() != te.size() ) {
ERROR(sp, E0000, "Tuple pattern with an incorrect number of fields, expected " << e.sub_patterns.size() << "-tuple, got " << ty);
}
-
+
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
this->add_binding(sp, e.sub_patterns[i], te[i] );
)
else {
-
+
::std::vector< ::HIR::TypeRef> sub_types;
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) {
sub_types.push_back( this->m_ivars.new_ivar_tr() );
@@ -3505,7 +3505,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, te,
// - Should have been checked in AST resolve
ASSERT_BUG(sp, e.leading.size() + e.trailing.size() <= te.size(), "Invalid field count for split tuple pattern");
-
+
unsigned int tup_idx = 0;
for(auto& subpat : e.leading) {
this->add_binding(sp, subpat, te[tup_idx++]);
@@ -3514,7 +3514,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
for(auto& subpat : e.trailing) {
this->add_binding(sp, subpat, te[tup_idx++]);
}
-
+
// TODO: Should this replace the pattern with a non-split?
// - Changing the address of the pattern means that the below revisit could fail.
e.total_size = te.size();
@@ -3523,7 +3523,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
if( !ty.m_data.is_Infer() ) {
ERROR(sp, E0000, "Tuple pattern on non-tuple");
}
-
+
::std::vector<::HIR::TypeRef> leading_tys;
leading_tys.reserve(e.leading.size());
for(auto& subpat : e.leading) {
@@ -3535,7 +3535,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
trailing_tys.push_back( this->m_ivars.new_ivar_tr() );
this->add_binding(sp, subpat, trailing_tys.back());
}
-
+
struct SplitTuplePatRevisit:
public Revisitor
{
@@ -3544,13 +3544,13 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
::std::vector<::HIR::TypeRef> m_leading_tys;
::std::vector<::HIR::TypeRef> m_trailing_tys;
unsigned int& m_pat_total_size;
-
+
SplitTuplePatRevisit(Span sp, ::HIR::TypeRef outer, ::std::vector<::HIR::TypeRef> leading, ::std::vector<::HIR::TypeRef> trailing, unsigned int& pat_total_size):
sp(mv$(sp)), m_outer_ty(mv$(outer)),
m_leading_tys( mv$(leading) ), m_trailing_tys( mv$(trailing) ),
m_pat_total_size(pat_total_size)
{}
-
+
void fmt(::std::ostream& os) const override {
os << "SplitTuplePatRevisit { " << m_outer_ty << " = (" << m_leading_tys << ", ..., " << m_trailing_tys << ") }";
}
@@ -3575,7 +3575,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
}
}
};
-
+
// Register a revisit and wait until the tuple is known - then bind through.
this->add_revisit_adv( box$(( SplitTuplePatRevisit { sp, ty.clone(), mv$(leading_tys), mv$(trailing_tys), e.total_size } )) );
}
@@ -3594,7 +3594,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
auto inner = this->m_ivars.new_ivar_tr();
for(auto& sub : e.sub_patterns)
this->add_binding(sp, sub, inner);
-
+
struct SlicePatRevisit:
public Revisitor
{
@@ -3602,11 +3602,11 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
::HIR::TypeRef inner;
::HIR::TypeRef type;
unsigned int size;
-
+
SlicePatRevisit(Span sp, ::HIR::TypeRef inner, ::HIR::TypeRef type, unsigned int size):
sp(mv$(sp)), inner(mv$(inner)), type(mv$(type)), size(size)
{}
-
+
void fmt(::std::ostream& os) const override { os << "SlicePatRevisit { " << inner << ", " << type << ", " << size; }
bool revisit(Context& context) override {
const auto& ty = context.get_type(type);
@@ -3653,7 +3653,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
ERROR(sp, E0000, "Slice pattern on an array smaller than the pattern");
}
unsigned extra_len = te.size_val - min_len;
-
+
if( e.extra_bind.is_valid() ) {
this->add_binding_inner( sp, e.extra_bind, ::HIR::TypeRef::new_array(inner.clone(), extra_len) );
}
@@ -3665,7 +3665,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
var_ty = this->m_ivars.new_ivar_tr();
this->add_binding_inner( sp, e.extra_bind, var_ty.clone() );
}
-
+
struct SplitSlicePatRevisit:
public Revisitor
{
@@ -3677,17 +3677,17 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
// Binding type (if not default value)
::HIR::TypeRef var_ty;
unsigned int min_size;
-
+
SplitSlicePatRevisit(Span sp, ::HIR::TypeRef inner, ::HIR::TypeRef type, ::HIR::TypeRef var_ty, unsigned int size):
sp(mv$(sp)), inner(mv$(inner)), type(mv$(type)), var_ty(mv$(var_ty)), min_size(size)
{}
-
+
void fmt(::std::ostream& os) const override { os << "SplitSlice inner=" << inner << ", outer=" << type << ", binding="<<var_ty<<", " << min_size; }
bool revisit(Context& context) override {
const auto& ty = context.get_type(this->type);
if( ty.m_data.is_Infer() )
return false;
-
+
// Slice - Equate inners
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te,
context.equate_types(this->sp, this->inner, *te.inner);
@@ -3702,7 +3702,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
ERROR(sp, E0000, "Slice pattern on an array smaller than the pattern");
}
unsigned extra_len = te.size_val - this->min_size;
-
+
if( this->var_ty != ::HIR::TypeRef() ) {
context.equate_types(this->sp, this->var_ty, ::HIR::TypeRef::new_array(this->inner.clone(), extra_len) );
}
@@ -3725,7 +3725,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
for(auto& sub : e.trailing)
this->add_binding( sp, sub, inner );
),
-
+
// - Enums/Structs
(StructValue,
this->add_ivars_params( e.path.m_params );
@@ -3739,11 +3739,11 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
// - assert check from earlier pass
assert( str.m_data.is_Tuple() );
const auto& sd = str.m_data.as_Tuple();
-
+
const auto& params = e.path.m_params;
assert(e.binding);
this->equate_types( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) );
-
+
for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
/*const*/ auto& sub_pat = e.sub_patterns[i];
@@ -3760,14 +3760,14 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
(Struct,
this->add_ivars_params( e.path.m_params );
this->equate_types( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) );
-
+
assert(e.binding);
const auto& str = *e.binding;
// - assert check from earlier pass
assert( str.m_data.is_Named() );
const auto& sd = str.m_data.as_Named();
const auto& params = e.path.m_params;
-
+
for( auto& field_pat : e.sub_patterns )
{
unsigned int f_idx = ::std::find_if( sd.begin(), sd.end(), [&](const auto& x){ return x.first == field_pat.first; } ) - sd.begin();
@@ -3810,13 +3810,13 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
const auto& var = enm.m_variants[e.binding_idx].second;
assert(var.is_Tuple());
const auto& tup_var = var.as_Tuple();
-
+
const auto& params = e.path.m_params;
-
+
ASSERT_BUG(sp, e.sub_patterns.size() == tup_var.size(),
"Enum pattern with an incorrect number of fields - " << e.path << " - expected " << tup_var.size() << ", got " << e.sub_patterns.size()
);
-
+
for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
if( monomorphise_type_needed(tup_var[i].ent) ) {
@@ -3843,7 +3843,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
assert(var.is_Struct());
const auto& tup_var = var.as_Struct();
const auto& params = e.path.m_params;
-
+
for( auto& field_pat : e.sub_patterns )
{
unsigned int f_idx = ::std::find_if( tup_var.begin(), tup_var.end(), [&](const auto& x){ return x.first == field_pat.first; } ) - tup_var.begin();
@@ -3916,7 +3916,7 @@ void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const
this->link_assoc.push_back(Associated {
sp,
l.clone(),
-
+
trait.clone(),
mv$(pp),
impl_ty.clone(),
@@ -3940,7 +3940,7 @@ void Context::possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef
ty_l.m_data.as_Infer().index = ivar_index;
assert( m_ivars.get_type(ty_l).m_data.is_Infer() );
}
-
+
if( ivar_index >= possible_ivar_vals.size() ) {
possible_ivar_vals.resize( ivar_index + 1 );
}
@@ -3958,7 +3958,7 @@ void Context::possible_equate_type_disable(unsigned int ivar_index, bool is_to)
ty_l.m_data.as_Infer().index = ivar_index;
assert( m_ivars.get_type(ty_l).m_data.is_Infer() );
}
-
+
if( ivar_index >= possible_ivar_vals.size() ) {
possible_ivar_vals.resize( ivar_index + 1 );
}
@@ -4002,7 +4002,7 @@ const ::HIR::TypeRef& Context::get_var(const Span& sp, unsigned int idx) const {
if( get_type(ty_src).m_data.is_Array() )
{
ASSERT_BUG(span, ty_dst.m_data.is_Slice(), "Array should only ever autoderef to Slice");
-
+
// HACK: Emit an invalid _Unsize op that is fixed once usage type is known.
auto ty_dst_c = ty_dst.clone();
val_node = NEWNODE( mv$(ty_dst), span, _Unsize, mv$(val_node), mv$(ty_dst_c) );
@@ -4012,7 +4012,7 @@ const ::HIR::TypeRef& Context::get_var(const Span& sp, unsigned int idx) const {
val_node = NEWNODE( mv$(ty_dst), span, _Deref, mv$(val_node) );
DEBUG("- Deref " << &*val_node << " -> " << val_node->m_res_type);
}
-
+
return val_node;
}
@@ -4024,7 +4024,7 @@ void fix_param_count_(const Span& sp, Context& context, const ::HIR::TypeRef& se
// Nothing to do, all good
return ;
}
-
+
if( params.m_types.size() > param_defs.m_types.size() ) {
ERROR(sp, E0000, "Too many type parameters passed to " << path);
}
@@ -4073,7 +4073,7 @@ namespace {
void add_coerce_borrow(Context& context, ::HIR::ExprNodeP& node_ptr, const ::HIR::TypeRef& des_borrow_inner, ::std::function<void(::HIR::ExprNodeP& n)> cb)
{
const auto& src_type = context.m_ivars.get_type(node_ptr->m_res_type);
-
+
// Since this function operates on destructured &-ptrs, the dereferences have to be added behind a borrow
::HIR::ExprNodeP* node_ptr_ptr = nullptr;
// - If the pointed node is a borrow operation, add the dereferences within its value
@@ -4086,14 +4086,14 @@ namespace {
auto span = node_ptr->span();
const auto& src_inner_ty = *src_type.m_data.as_Borrow().inner;
auto borrow_type = src_type.m_data.as_Borrow().type;
-
+
auto inner_ty_ref = ::HIR::TypeRef::new_borrow(borrow_type, des_borrow_inner.clone());
-
+
// 1. Dereference (resulting in the dereferenced input type)
node_ptr = NEWNODE(src_inner_ty.clone(), span, _Deref, mv$(node_ptr));
// 2. Borrow (resulting in the referenced output type)
node_ptr = NEWNODE(mv$(inner_ty_ref), span, _Borrow, borrow_type, mv$(node_ptr));
-
+
// - Set node pointer reference to point into the new borrow op
node_ptr_ptr = &dynamic_cast< ::HIR::ExprNode_Borrow&>(*node_ptr).m_value;
}
@@ -4102,16 +4102,16 @@ namespace {
// Set the result of the borrow operation to the output type
node_ptr->m_res_type = ::HIR::TypeRef::new_borrow(borrow_type, des_borrow_inner.clone());
}
-
+
cb(*node_ptr_ptr);
-
+
context.m_ivars.mark_change();
}
-
+
bool check_coerce_borrow(Context& context, ::HIR::BorrowType bt, const ::HIR::TypeRef& inner_l, const ::HIR::TypeRef& inner_r, ::HIR::ExprNodeP& node_ptr)
{
const auto& sp = node_ptr->span();
-
+
const auto& ty_dst = context.m_ivars.get_type(inner_l);
const auto& ty_src = context.m_ivars.get_type(inner_r);
@@ -4119,14 +4119,14 @@ namespace {
if( context.m_ivars.types_equal(ty_dst, ty_src) ) {
return true;
}
-
+
// If either side (or both) are ivars, then coercion can't be known yet - but they could be equal
// TODO: Fix and deduplicate the following code for InferClass::Diverge
if( ty_src.m_data.is_Infer() && ty_dst.m_data.is_Infer() ) {
const auto& r_e = ty_src.m_data.as_Infer();
const auto& l_e = ty_dst.m_data.as_Infer();
-
+
// TODO: Commented out - &-ptrs can infer to trait objects, and &-ptrs can infer from deref coercion
//if( r_e.ty_class != ::HIR::InferClass::None ) {
// context.equate_types(sp, ty_dst, ty_src);
@@ -4141,11 +4141,11 @@ namespace {
DEBUG("- Infer, add possibility");
return false;
}
-
+
// If the source is '_', we can't know yet
TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Infer, r_e,
// TODO: If the source is a literal, and the destination isn't a TraitObject, equate.
-
+
// - Except if it's known to be a primitive
//if( r_e.ty_class != ::HIR::InferClass::None ) {
// context.equate_types(sp, ty_dst, ty_src);
@@ -4155,9 +4155,9 @@ namespace {
DEBUG("- Infer, add possibility");
return false;
)
-
+
TU_IFLET(::HIR::TypeRef::Data, ty_dst.m_data, Infer, l_e,
-
+
// If the destination is known to be a primitive (integer or float) and the source is a primitive
// - Equate.
// - NOTE: The source can't be something that could deref coerce into the literal.
@@ -4169,24 +4169,24 @@ namespace {
context.equate_types(sp, ty_dst, ty_src);
return true;
}
-
+
context.possible_equate_type_unsize_from(l_e.index, ty_src);
DEBUG("- Infer, add possibility");
return false;
)
-
+
// Fast hack for slices (avoids going via the Deref impl search)
if( ty_dst.m_data.is_Slice() && !ty_src.m_data.is_Slice() )
{
const auto& dst_slice = ty_dst.m_data.as_Slice();
TU_IFLET(::HIR::TypeRef::Data, ty_src.m_data, Array, src_array,
context.equate_types(sp, *dst_slice.inner, *src_array.inner);
-
+
auto ty_dst_b = ::HIR::TypeRef::new_borrow(bt, ty_dst.clone());
auto ty_dst_b2 = ty_dst_b.clone();
auto span = node_ptr->span();
node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
-
+
context.m_ivars.mark_change();
return true;
)
@@ -4195,7 +4195,7 @@ namespace {
// Apply deref coercions
}
}
-
+
// Deref coercions
// - If right can be dereferenced to left
{
@@ -4206,17 +4206,17 @@ namespace {
while( (out_ty = context.m_resolve.autoderef(sp, *out_ty, tmp_ty)) )
{
count += 1;
-
+
if( out_ty->m_data.is_Infer() && out_ty->m_data.as_Infer().ty_class == ::HIR::InferClass::None ) {
// Hit a _, so can't keep going
break;
}
-
+
types.push_back( out_ty->clone() );
-
+
if( context.m_ivars.types_equal(ty_dst, *out_ty) == false ) {
// Check equivalence
-
+
if( ty_dst.m_data.tag() == out_ty->m_data.tag() ) {
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_dst.m_data, out_ty->m_data), (d_e, s_e),
(
@@ -4238,7 +4238,7 @@ namespace {
continue ;
}
}
-
+
add_coerce_borrow(context, node_ptr, types.back(), [&](auto& node_ptr) {
// node_ptr = node that yeilds ty_src
assert( count == types.size() );
@@ -4254,12 +4254,12 @@ namespace {
context.m_ivars.get_type(node_ptr->m_res_type);
}
});
-
+
return true;
}
// Either ran out of deref, or hit a _
}
-
+
// Desination coercions (Trait objects)
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_dst.m_data), (e),
(
@@ -4290,12 +4290,12 @@ namespace {
DEBUG("Defer as there are multiple applicable impls");
return false;
}
-
+
if( best_impl.has_magic_params() ) {
DEBUG("Defer as there were magic parameters");
return false;
}
-
+
// TODO: Get a better way of equating these that doesn't require getting copies of the impl's types
context.equate_types(sp, ty_src, best_impl.get_impl_type());
auto args = best_impl.get_trait_params();
@@ -4305,7 +4305,7 @@ namespace {
context.equate_types(sp, trait.m_params.m_types[i], args.m_types[i]);
}
}
-
+
for(const auto& marker : e.m_markers)
{
bool found = context.m_resolve.find_trait_impls(sp, marker.m_path, marker.m_params, ty_src, [&](auto impl, auto cmp) {
@@ -4321,17 +4321,17 @@ namespace {
return false;
}
}
-
+
// Add _Unsize operator
auto ty_dst_b = ::HIR::TypeRef::new_borrow(bt, ty_dst.clone());
auto ty_dst_b2 = ty_dst_b.clone();
auto span = node_ptr->span();
node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
-
+
return true;
)
)
-
+
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_src.m_data), (e),
(
),
@@ -4346,7 +4346,7 @@ namespace {
// return true;
)
)
-
+
// Search for Unsize
// - If `right`: ::core::marker::Unsize<`left`>
{
@@ -4363,11 +4363,11 @@ namespace {
auto ty_dst_b2 = ty_dst_b.clone();
auto span = node_ptr->span();
node_ptr = NEWNODE( mv$(ty_dst_b), span, _Unsize, mv$(node_ptr), mv$(ty_dst_b2) );
-
+
return true;
}
}
-
+
if( ty_dst.m_data.is_Path() && ty_dst.m_data.as_Path().binding.is_Unbound() )
{
}
@@ -4376,7 +4376,7 @@ namespace {
context.equate_types(sp, ty_dst, ty_src);
return true;
}
-
+
// Keep trying
// TODO: If both types are fully known, then error.
return false;
@@ -4388,14 +4388,14 @@ namespace {
const auto& ty_dst = context.m_ivars.get_type(v.left_ty);
const auto& ty_src = context.m_ivars.get_type(node_ptr->m_res_type);
TRACE_FUNCTION_F(v << " - " << ty_dst << " := " << ty_src);
-
+
if( context.m_ivars.types_equal(ty_dst, ty_src) ) {
DEBUG("Equal");
return true;
}
-
+
const auto& lang_CoerceUnsized = context.m_crate.get_lang_item_path(sp, "coerce_unsized");
-
+
struct H {
// Check if a path type has or could have a CoerceUnsized impl
static bool type_has_coerce_path(const ::HIR::TypeRef& ty) {
@@ -4421,17 +4421,17 @@ namespace {
return false;
}
};
-
+
// CoerceUnsized trait
// - Only valid for generic or path destination types
if( ty_dst.m_data.is_Generic() || H::type_has_coerce_path(ty_dst) )
{
// `CoerceUnsized<U> for T` means `T -> U`
-
+
::HIR::PathParams pp { ty_dst.clone() };
-
+
// PROBLEM: This can false-negative leading to the types being falsely equated.
-
+
bool fuzzy_match = false;
ImplRef best_impl;
bool found = context.m_resolve.find_trait_impls(sp, lang_CoerceUnsized, pp, ty_src, [&](auto impl, auto cmp) {
@@ -4453,7 +4453,7 @@ namespace {
if( found )
{
DEBUG("- NEWNODE _Unsize " << &*node_ptr << " -> " << ty_dst);
-
+
auto span = node_ptr->span();
node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() );
return true;
@@ -4469,7 +4469,7 @@ namespace {
}
DEBUG("- No CoerceUnsized impl found");
}
-
+
// 1. Check that the source type can coerce
TU_MATCH( ::HIR::TypeRef::Data, (ty_src.m_data), (e),
(Infer,
@@ -4479,20 +4479,20 @@ namespace {
context.equate_types(sp, ty_dst, ty_src);
return true;
}
-
+
TU_IFLET(::HIR::TypeRef::Data, ty_dst.m_data, Infer, e2,
-
+
if( e2.ty_class != ::HIR::InferClass::None ) {
context.equate_types(sp, ty_dst, ty_src);
return true;
}
-
+
DEBUG("Both infer, add possibilities");
context.possible_equate_type_coerce_to(e.index, ty_dst);
context.possible_equate_type_coerce_from(e2.index, ty_src);
return false;
)
-
+
context.possible_equate_type_coerce_to(e.index, ty_dst);
DEBUG("Source infer, add possibility and continue");
),
@@ -4560,7 +4560,7 @@ namespace {
return true;
)
)
-
+
// 2. Check target type is a valid coercion
// - Otherwise - Force equality
TU_MATCH( ::HIR::TypeRef::Data, (ty_dst.m_data), (l_e),
@@ -4631,7 +4631,7 @@ namespace {
// TODO: &move reboorrowing rules?
//if( l_e.type < r_e.type ) {
if( l_e.type == ::HIR::BorrowType::Shared && r_e.type == ::HIR::BorrowType::Unique ) {
-
+
// Add cast down
auto span = node_ptr->span();
// > Goes from `ty_src` -> `*ty_src` -> `&`l_e.type` `&ty_src`
@@ -4646,15 +4646,15 @@ namespace {
DEBUG("- Borrow -> " << new_type);
node_ptr = NEWNODE( mv$(new_type) , span, _Borrow, dst_bt, mv$(node_ptr) );
context.m_ivars.get_type(node_ptr->m_res_type);
-
+
context.m_ivars.mark_change();
-
+
// Continue on with coercion (now that node_ptr is updated)
}
else if( l_e.type != r_e.type ) {
ERROR(sp, E0000, "Type mismatch between " << ty_dst << " and " << ty_src << " - Borrow classes differ");
}
-
+
// - Check for coercions
return check_coerce_borrow(context, l_e.type, *l_e.inner, *r_e.inner, node_ptr);
)
@@ -4665,7 +4665,7 @@ namespace {
context.equate_types(sp, ty_dst, ty_src);
BUG(sp, "Type error expected " << ty_dst << " == " << ty_src);
}
-
+
context.possible_equate_type_coerce_to(r_e.index, ty_dst);
DEBUG("- Infer, add possibility");
return false;
@@ -4687,14 +4687,14 @@ namespace {
if( !(l_e.type <= s_e.type) ) {
ERROR(sp, E0000, "Type mismatch between " << ty_dst << " and " << ty_src << " - Mutability not compatible");
}
-
+
// TODO: Can this can unsize as well as convert to raw?
context.equate_types(sp, *l_e.inner, *s_e.inner);
// Add downcast
auto span = node_ptr->span();
node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst.clone() ));
node_ptr->m_res_type = ty_dst.clone();
-
+
context.m_ivars.mark_change();
return true;
)
@@ -4702,17 +4702,17 @@ namespace {
// If using `*mut T` where `*const T` is expected - add cast
if( l_e.type == ::HIR::BorrowType::Shared && r_e.type == ::HIR::BorrowType::Unique ) {
context.equate_types(sp, *l_e.inner, *r_e.inner);
-
+
// Add cast down
auto span = node_ptr->span();
node_ptr->m_res_type = ty_src.clone();
node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst.clone() ));
node_ptr->m_res_type = ty_dst.clone();
-
+
context.m_ivars.mark_change();
return true;
}
-
+
if( l_e.type != r_e.type ) {
ERROR(sp, E0000, "Type mismatch between " << ty_dst << " and " << ty_src << " - Pointer mutability differs");
}
@@ -4741,17 +4741,17 @@ namespace {
TU_IFLET( ::HIR::TypeRef::Data, ty_src.m_data, Function, r_e,
if(l_e.m_abi != r_e.m_abi && l_e.is_unsafe == true && r_e.is_unsafe == false ) {
// LHS is unsafe, RHS is not - Insert a cast
-
+
auto ty_dst_new = ty_src.clone();
ty_dst_new.m_data.as_Function().is_unsafe = true;
context.equate_types(sp, ty_dst, ty_dst_new);
-
+
// Add cast down
auto span = node_ptr->span();
node_ptr->m_res_type = ty_src.clone();
node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst_new.clone() ));
node_ptr->m_res_type = mv$(ty_dst_new);
-
+
context.m_ivars.mark_change();
return true;
}
@@ -4771,21 +4771,21 @@ namespace {
return true;
)
)
-
+
//TODO(sp, "Typecheck_Code_CS - Coercion " << context.m_ivars.fmt_type(ty) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type));
DEBUG("TODO - Coercion " << context.m_ivars.fmt_type(ty_dst) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type));
return false;
}
-
+
bool check_associated(Context& context, const Context::Associated& v)
{
const auto& sp = v.span;
TRACE_FUNCTION_F(v);
-
+
::HIR::TypeRef possible_impl_ty;
::HIR::PathParams possible_params;
::HIR::TypeRef output_type;
-
+
struct H {
static bool type_is_num(const ::HIR::TypeRef& t) {
TU_MATCH_DEF(::HIR::TypeRef::Data, (t.m_data), (e),
@@ -4806,7 +4806,7 @@ namespace {
)
}
};
-
+
// MAGIC! Have special handling for operator overloads
if( v.is_operator ) {
if( v.params.m_types.size() == 0 )
@@ -4835,14 +4835,14 @@ namespace {
BUG(sp, "Associated type rule with `is_operator` set but an incorrect parameter count");
}
}
-
+
// If the output type is present, prevent it from being guessed
// - This generates an exact equation.
if( v.left_ty != ::HIR::TypeRef() )
{
context.equate_types_from_shadow(sp, v.left_ty);
}
-
+
// HACK! If the trait is `Unsize` then pretend `impl<T> Unsize<T> for T` exists to possibly propagate the type through
// - Also applies to CoerceUnsized (which may not get its impl detected because actually `T: !Unsize<T>`)
// - This is needed because `check_coerce` will emit coercions where they're not actually needed in some cases.
@@ -4854,7 +4854,7 @@ namespace {
ASSERT_BUG(sp, v.params.m_types.size() == 1, "Incorrect number of parameters for Unsize");
const auto& src_ty = context.get_type(v.impl_ty);
const auto& dst_ty = context.get_type(v.params.m_types[0]);
-
+
// - If the two types are equal (for unsizing purposes) then equate them and delete this rule
if( context.m_ivars.types_equal( src_ty, dst_ty ) ) {
// A type cannot unsize to itself, but CoerceUnsize code leads to these requirements when coercion points chain.
@@ -4929,7 +4929,7 @@ namespace {
DEBUG("Found at least one impl of CoerceUnsized, running expensive code");
}
}
-
+
// Locate applicable trait impl
unsigned int count = 0;
DEBUG("Searching for impl " << v.trait << v.params << " for " << context.m_ivars.fmt_type(v.impl_ty));
@@ -4949,7 +4949,7 @@ namespace {
// TODO: if this is an unbound UfcsUnknown, treat as a fuzzy match.
// - Shouldn't compare_with_placeholders do that?
const auto& out_ty = out_ty_o;
-
+
// - If we're looking for an associated type, allow it to eliminate impossible impls
// > This makes `let v: usize = !0;` work without special cases
auto cmp2 = v.left_ty.compare_with_placeholders(sp, out_ty, context.m_ivars.callback_resolve_infer());
@@ -4974,13 +4974,13 @@ namespace {
}
else {
DEBUG("- (possible) " << impl);
-
+
if( possible_impl_ty == ::HIR::TypeRef() ) {
possible_impl_ty = impl.get_impl_type();
possible_params = impl.get_trait_params();
best_impl = mv$(impl);
}
-
+
return false;
}
});
@@ -5009,11 +5009,11 @@ namespace {
else if( v.trait == context.m_crate.get_lang_item_path(sp, "unsize") )
{
// TODO: Detect if this was a compiler-generated bound, or was actually in the code.
-
+
ASSERT_BUG(sp, v.params.m_types.size() == 1, "Incorrect number of parameters for Unsize");
const auto& src_ty = context.get_type(v.impl_ty);
const auto& dst_ty = context.get_type(v.params.m_types[0]);
-
+
context.equate_types(sp, dst_ty, src_ty);
return true;
}
@@ -5081,12 +5081,12 @@ namespace {
return false;
}
}
-
+
bool check_ivar_poss(Context& context, unsigned int i, Context::IVarPossible& ivar_ent)
{
static Span _span;
const auto& sp = _span;
-
+
if( ! ivar_ent.has_rules() ) {
// No idea! (or unused)
// - Clear the `force_no` flag
@@ -5094,18 +5094,18 @@ namespace {
ivar_ent.force_no_from = false;
return false;
}
-
+
::HIR::TypeRef ty_l_ivar;
ty_l_ivar.m_data.as_Infer().index = i;
const auto& ty_l = context.m_ivars.get_type(ty_l_ivar);
-
+
if( ty_l != ty_l_ivar ) {
DEBUG("- IVar " << i << " had possibilities, but was known to be " << ty_l);
// Completely clear by reinitialising
ivar_ent = Context::IVarPossible();
return false;
}
-
+
enum class DedupKeep {
Both,
Left,
@@ -5115,7 +5115,7 @@ namespace {
static void dedup_type_list_with(::std::vector< ::HIR::TypeRef>& list, ::std::function<DedupKeep(const ::HIR::TypeRef& l, const ::HIR::TypeRef& r)> cmp) {
if( list.size() <= 1 )
return ;
-
+
for( auto it = list.begin(); it != list.end(); )
{
bool found = false;
@@ -5147,7 +5147,7 @@ namespace {
static void dedup_type_list(const Context& context, ::std::vector< ::HIR::TypeRef>& list) {
dedup_type_list_with(list, [&context](const auto& l, const auto& r){ return H::equal_to(context, l, r) ? DedupKeep::Left : DedupKeep::Both; });
}
-
+
// Types are equal from the view of being coercion targets
// - Inequality here means that the targets could coexist in the list (e.g. &[u8; N] and &[u8])
// - Equality means that they HAVE to be equal (even if they're not currently due to ivars)
@@ -5224,25 +5224,25 @@ namespace {
return context.m_ivars.types_equal(ia2, ib2);
)
)
- //
+ //
return context.m_ivars.types_equal(a, b);
}
// Types are equal from the view of being coercion sources
static bool equal_from(const Context& context, const ::HIR::TypeRef& a, const ::HIR::TypeRef& b) {
return context.m_ivars.types_equal(a, b);
}
-
+
// TODO: `can_unsize_to`
static bool can_coerce_to(const Context& context, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) {
if( dst.m_data.is_Infer() )
return false;
if( src.m_data.is_Infer() )
return false;
-
+
if( dst.m_data.is_Borrow() && src.m_data.is_Borrow() ) {
const auto& d_e = dst.m_data.as_Borrow();
const auto& s_e = src.m_data.as_Borrow();
-
+
// Higher = more specific (e.g. Unique > Shared)
if( s_e.type < d_e.type ) {
return false;
@@ -5256,7 +5256,7 @@ namespace {
return context.m_ivars.types_equal(*s_e.inner, *d_e.inner);
}
}
-
+
if( dst.m_data.is_Pointer() && src.m_data.is_Pointer() ) {
const auto& d_e = dst.m_data.as_Pointer();
const auto& s_e = src.m_data.as_Pointer();
@@ -5273,7 +5273,7 @@ namespace {
return context.m_ivars.types_equal(*s_e.inner, *d_e.inner);
}
}
-
+
if( dst.m_data.is_Pointer() && src.m_data.is_Borrow() ) {
const auto& d_e = dst.m_data.as_Pointer();
const auto& s_e = src.m_data.as_Borrow();
@@ -5283,7 +5283,7 @@ namespace {
}
return false;
}
-
+
// Returns true if the `src` concretely cannot coerce to `dst`
static bool cannot_coerce_to(const Context& context, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) {
TU_IFLET( ::HIR::TypeRef::Data, src.m_data, Borrow, se,
@@ -5295,7 +5295,7 @@ namespace {
)
return false;
}
-
+
static const ::HIR::TypeRef* find_lowest_type(const Context& context, const ::std::vector< ::HIR::TypeRef>& list)
{
// 1. Locate types that cannot coerce to anything
@@ -5314,7 +5314,7 @@ namespace {
)
)
}
-
+
// 2. Search the list for a type that is a valid coercion target for all other types in the list
// - NOTE: Ivars return `false` nomatter what order
const auto* cur_type = &list[0];
@@ -5336,13 +5336,13 @@ namespace {
// TODO: Replace
//return cur_type;
}
-
+
return nullptr;
}
-
+
/// Returns true if `dst` is found when dereferencing `src`
static bool type_derefs_from(const Span& sp, const Context& context, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) {
-
+
::HIR::TypeRef tmp;
const ::HIR::TypeRef* ty = &src;
do
@@ -5352,7 +5352,7 @@ namespace {
} while( (ty = context.m_resolve.autoderef(sp, *ty, tmp)) );
return false;
}
-
+
static ::std::vector<::HIR::TypeRef>& merge_lists(const Context& context, ::std::vector<::HIR::TypeRef>& list_a, ::std::vector<::HIR::TypeRef>& list_b, ::std::vector<::HIR::TypeRef>& out)
{
if( list_a.size() == 0 )
@@ -5371,7 +5371,7 @@ namespace {
}
}
};
-
+
// If this type has an infer class active, don't allw a non-primitive to coerce over it.
switch( ty_l.m_data.as_Infer().ty_class )
{
@@ -5402,7 +5402,7 @@ namespace {
default:
break;
}
-
+
if( ivar_ent.force_no_to == true || ivar_ent.force_no_from )
{
DEBUG("- IVar " << ty_l << " is forced unknown");
@@ -5411,15 +5411,15 @@ namespace {
else
{
TRACE_FUNCTION_F(i);
-
-
+
+
// TODO: Dedup based on context?
// - The dedup should probably be aware of the way the types are used (for coercions).
H::dedup_type_list(context, ivar_ent.types_coerce_to);
H::dedup_type_list(context, ivar_ent.types_unsize_to);
H::dedup_type_list(context, ivar_ent.types_coerce_from);
H::dedup_type_list(context, ivar_ent.types_unsize_from);
-
+
#if 0
// If there is a default type compatible with all possibilities, use that.
if( ivar_ent.types_default.size() > 0 ) {
@@ -5427,7 +5427,7 @@ namespace {
ASSERT_BUG(Span(), ivar_ent.types_def.size() == 1, "TODO: Multiple default types for an ivar - " << ivar_ent.types_def);
}
#endif
-
+
if( ivar_ent.types_coerce_from.size() == 0 && ivar_ent.types_coerce_to.size() == 0
&& ivar_ent.types_unsize_from.size() == 0 && ivar_ent.types_unsize_to.size() == 0
)
@@ -5436,7 +5436,7 @@ namespace {
}
DEBUG("-- " << ty_l << " FROM=Coerce:{" << ivar_ent.types_coerce_from << "} / Unsize:{" << ivar_ent.types_unsize_from << "},"
<< " TO=Coerce:{" << ivar_ent.types_coerce_to << "} / Unsize:{" << ivar_ent.types_unsize_to << "}");
-
+
// Find an entry in the `types_unsize_from` list that all other entries can unsize to
H::dedup_type_list_with(ivar_ent.types_unsize_from, [&](const auto& l, const auto& r) {
// &T and T
@@ -5462,12 +5462,12 @@ namespace {
H::dedup_type_list_with(ivar_ent.types_coerce_from, [&](const auto& l, const auto& r) {
if( l.m_data.is_Infer() || r.m_data.is_Infer() )
return DedupKeep::Both;
-
+
if( l.m_data.is_Borrow() )
{
const auto& le = l.m_data.as_Borrow();
const auto& re = r.m_data.as_Borrow();
-
+
// Dereference `*re.inner` until it isn't possible or it equals `*le.inner`
// - Repeat going the other direction.
if( H::type_derefs_from(sp, context, *le.inner, *re.inner) )
@@ -5477,8 +5477,8 @@ namespace {
}
return DedupKeep::Both;
});
-
-
+
+
// If there's one option for both desination types, and nothing for the source ...
if( ivar_ent.types_coerce_to.size() == 1 && ivar_ent.types_unsize_to.size() == 1 && ivar_ent.types_coerce_from.empty() && ivar_ent.types_unsize_from.empty() )
{
@@ -5506,18 +5506,18 @@ namespace {
}
}
#endif
-
- //
-
+
+ //
+
// HACK: Merge into a single lists
::std::vector< ::HIR::TypeRef> types_from_o;
auto& types_from = H::merge_lists(context, ivar_ent.types_coerce_from, ivar_ent.types_unsize_from, types_from_o);
::std::vector< ::HIR::TypeRef> types_to_o;
auto& types_to = H::merge_lists(context, ivar_ent.types_coerce_to , ivar_ent.types_unsize_to , types_to_o );
DEBUG(" " << ty_l << " FROM={" << types_from << "}, TO={" << types_to << "}");
-
+
// TODO: If there is only a single option and it's from an Unsize, is it valid?
-
+
// Same type on both sides, pick it.
if( types_from == types_to && types_from.size() == 1 ) {
const auto& new_ty = types_from[0];
@@ -5525,7 +5525,7 @@ namespace {
context.equate_types(sp, ty_l, new_ty);
return true;
}
-
+
// Eliminate possibilities that don't fit known constraints
if( types_to.size() > 0 && types_from.size() > 0 )
{
@@ -5540,7 +5540,7 @@ namespace {
{
if( bound.impl_ty != ty_l )
continue ;
-
+
// TODO: Monomorphise this type replacing mentions of the current ivar with the replacement?
// Search for any trait impl that could match this,
@@ -5553,7 +5553,7 @@ namespace {
}
}
}
-
+
if( remove ) {
it = types_from.erase(it);
}
@@ -5561,7 +5561,7 @@ namespace {
++it;
}
}
-
+
// Eliminate `to` types that can't be coerced from `from` types
if(types_from.size() > 0)
for(auto it = types_to.begin(); it != types_to.end(); )
@@ -5571,7 +5571,7 @@ namespace {
continue;
}
bool remove = false;
-
+
for(const auto& src : types_from)
{
if( H::cannot_coerce_to(context, *it, src) ) {
@@ -5580,7 +5580,7 @@ namespace {
break;
}
}
-
+
if( remove ) {
it = types_to.erase(it);
}
@@ -5589,8 +5589,8 @@ namespace {
}
}
}
-
-
+
+
// Prefer cases where this type is being created from a known type
if( types_from.size() == 1 ) {
const ::HIR::TypeRef& ty_r = types_from[0];
@@ -5608,7 +5608,7 @@ namespace {
}
else {
DEBUG("- IVar " << ty_l << " not concretely known {" << types_from << "} and {" << types_to << "}" );
-
+
// If one side is completely unknown, pick the most liberal of the other side
if( types_to.size() == 0 && types_from.size() > 0 )
{
@@ -5631,7 +5631,7 @@ namespace {
}
}
}
-
+
return false;
}
}
@@ -5641,10 +5641,10 @@ namespace {
void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr)
{
TRACE_FUNCTION;
-
+
auto root_ptr = expr.into_unique();
Context context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics };
-
+
for( auto& arg : args ) {
context.add_binding( Span(), arg.first, arg.second );
}
@@ -5677,22 +5677,22 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
}
return false;
});
-
+
ExprVisitor_Enum visitor(context, ms.m_traits, result_type);
context.add_ivars(root_ptr->m_res_type);
root_ptr->visit(visitor);
-
+
DEBUG("Return type = " << new_res_ty);
context.equate_types_coerce(sp, new_res_ty, root_ptr);
}
-
+
const unsigned int MAX_ITERATIONS = 1000;
unsigned int count = 0;
while( context.take_changed() /*&& context.has_rules()*/ && count < MAX_ITERATIONS )
{
TRACE_FUNCTION_F("=== PASS " << count << " ===");
context.dump();
-
+
// 1. Check coercions for ones that cannot coerce due to RHS type (e.g. `str` which doesn't coerce to anything)
// 2. (???) Locate coercions that cannot coerce (due to being the only way to know a type)
// - Keep a list in the ivar of what types that ivar could be equated to.
@@ -5702,7 +5702,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
it->left_ty = context.m_resolve.expand_associated_types( (*it->right_node_ptr)->span(), mv$(it->left_ty) );
if( check_coerce(context, *it) ) {
DEBUG("- Consumed coercion " << it->left_ty << " := " << src_ty);
-
+
#if 1
unsigned int i = it - context.link_coerce.begin();
if( it != context.link_coerce.end()-1 )
@@ -5725,7 +5725,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
for(unsigned int i = 0; i < context.link_assoc.size(); ) {
// - Move out (and back in later) to avoid holding a bad pointer if the list is updated
auto rule = mv$(context.link_assoc[i]);
-
+
DEBUG("- " << rule);
for( auto& ty : rule.params.m_types ) {
ty = context.m_resolve.expand_associated_types(rule.span, mv$(ty));
@@ -5734,7 +5734,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
rule.left_ty = context.m_resolve.expand_associated_types(rule.span, mv$(rule.left_ty));
}
rule.impl_ty = context.m_resolve.expand_associated_types(rule.span, mv$(rule.impl_ty));
-
+
if( check_associated(context, rule) ) {
DEBUG("- Consumed associated type rule - " << rule);
#if 1
@@ -5778,7 +5778,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
++ it;
}
}
-
+
// If nothing changed this pass, apply ivar possibilities
// - This essentially forces coercions not to happen.
if( ! context.m_ivars.peek_changed() )
@@ -5826,14 +5826,14 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
context.m_ivars.mark_change();
}
}
-
+
count ++;
context.m_resolve.compact_ivars(context.m_ivars);
}
if( count == MAX_ITERATIONS ) {
BUG(root_ptr->span(), "Typecheck ran for too many iterations, max - " << MAX_ITERATIONS);
}
-
+
if( context.has_rules() )
{
for(const auto& coercion : context.link_coerce)
@@ -5869,7 +5869,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
}
BUG(root_ptr->span(), "Spare rules left after typecheck stabilised");
}
-
+
// - Recreate the pointer
expr.reset( root_ptr.release() );
// > Steal the binding types
@@ -5877,12 +5877,12 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
for(auto& binding : context.m_bindings) {
expr.m_bindings.push_back( binding.ty.clone() );
}
-
+
// - Validate typeck
{
DEBUG("==== VALIDATE ==== (" << count << " rounds)");
context.dump();
-
+
ExprVisitor_Apply visitor { context };
visitor.visit_node_ptr( expr );
}
diff --git a/src/hir_typeck/expr_visit.cpp b/src/hir_typeck/expr_visit.cpp
index 83036720..95e0c29c 100644
--- a/src/hir_typeck/expr_visit.cpp
+++ b/src/hir_typeck/expr_visit.cpp
@@ -10,8 +10,8 @@ namespace {
//Typecheck_Code_Simple(ms, args, result_type, expr);
Typecheck_Code_CS(ms, args, result_type, expr);
}
-
-
+
+
class OuterVisitor:
public ::HIR::Visitor
{
@@ -21,8 +21,8 @@ namespace {
m_ms(crate)
{
}
-
-
+
+
public:
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
@@ -30,7 +30,7 @@ namespace {
::HIR::Visitor::visit_module(p, mod);
m_ms.pop_traits(mod);
}
-
+
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
void visit_expr(::HIR::ExprPtr& exp) override {
BUG(exp->m_span, "Reached expression");
@@ -41,12 +41,12 @@ namespace {
auto _ = this->m_ms.set_impl_generics(item.m_params);
::HIR::Visitor::visit_trait(p, item);
}
-
+
void visit_type_impl(::HIR::TypeImpl& impl) override
{
TRACE_FUNCTION_F("impl " << impl.m_type);
auto _ = this->m_ms.set_impl_generics(impl.m_params);
-
+
const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module);
m_ms.push_traits(mod);
::HIR::Visitor::visit_type_impl(impl);
@@ -56,7 +56,7 @@ namespace {
{
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type);
auto _ = this->m_ms.set_impl_generics(impl.m_params);
-
+
const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module);
m_ms.push_traits(mod);
m_ms.m_traits.push_back( ::std::make_pair( &trait_path, &this->m_ms.m_crate.get_trait_by_path(Span(), trait_path) ) );
@@ -68,13 +68,13 @@ namespace {
{
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type << " { }");
auto _ = this->m_ms.set_impl_generics(impl.m_params);
-
+
const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module);
m_ms.push_traits(mod);
::HIR::Visitor::visit_marker_impl(trait_path, impl);
m_ms.pop_traits(mod);
}
-
+
void visit_type(::HIR::TypeRef& ty) override
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
@@ -124,10 +124,10 @@ namespace {
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
auto _ = this->m_ms.set_item_generics(item.m_params);
-
+
// TODO: Use a different type depding on repr()
auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
+
// TODO: Check types too?
for(auto& var : item.m_variants)
{
diff --git a/src/hir_typeck/expr_visit.hpp b/src/hir_typeck/expr_visit.hpp
index 5ef2a838..3fe601e4 100644
--- a/src/hir_typeck/expr_visit.hpp
+++ b/src/hir_typeck/expr_visit.hpp
@@ -3,18 +3,18 @@ namespace typeck {
struct ModuleState
{
::HIR::Crate& m_crate;
-
+
::HIR::GenericParams* m_impl_generics;
::HIR::GenericParams* m_item_generics;
-
+
::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits;
-
+
ModuleState(::HIR::Crate& crate):
m_crate(crate),
m_impl_generics(nullptr),
m_item_generics(nullptr)
{}
-
+
template<typename T>
class NullOnDrop {
T*& ptr;
@@ -36,7 +36,7 @@ namespace typeck {
m_item_generics = &gps;
return NullOnDrop< ::HIR::GenericParams>(m_item_generics);
}
-
+
void push_traits(const ::HIR::Module& mod) {
auto sp = Span();
DEBUG("Module has " << mod.m_traits.size() << " in-scope traits");
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index a9577835..ac94909d 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -41,7 +41,7 @@ void HMTypeInferrence::check_for_loops()
{
struct LoopChecker {
::std::vector<unsigned int> m_indexes;
-
+
void check_pathparams(const HMTypeInferrence& ivars, const ::HIR::PathParams& pp) {
for(const auto& ty : pp.m_types)
this->check_ty(ivars, ty);
@@ -144,25 +144,25 @@ void HMTypeInferrence::check_for_loops()
void HMTypeInferrence::compact_ivars()
{
this->check_for_loops();
-
+
unsigned int i = 0;
for(auto& v : m_ivars)
{
if( !v.is_alias() ) {
//auto nt = this->expand_associated_types(Span(), v.type->clone());
auto nt = v.type->clone();
-
+
DEBUG("- " << i << " " << *v.type << " -> " << nt);
*v.type = mv$(nt);
}
else {
-
+
auto index = v.alias;
unsigned int count = 0;
assert(index < m_ivars.size());
while( m_ivars.at(index).is_alias() ) {
index = m_ivars.at(index).alias;
-
+
if( count >= m_ivars.size() ) {
this->dump();
BUG(Span(), "Loop detected in ivar list when starting at " << v.alias << ", current is " << index);
@@ -206,7 +206,7 @@ bool HMTypeInferrence::apply_defaults()
}
}
return rv;
-}
+}
void HMTypeInferrence::print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const
{
@@ -548,12 +548,12 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
auto sp = Span();
auto& root_ivar = this->get_pointed_ivar(slot);
DEBUG("set_ivar_to(" << slot << " { " << *root_ivar.type << " }, " << type << ")");
-
+
// If the left type was '_', alias the right to it
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Infer, l_e,
assert( l_e.index != slot );
DEBUG("Set IVar " << slot << " = @" << l_e.index);
-
+
if( l_e.ty_class != ::HIR::InferClass::None ) {
TU_MATCH_DEF(::HIR::TypeRef::Data, (root_ivar.type->m_data), (e),
(
@@ -570,7 +570,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
)
)
}
-
+
root_ivar.alias = l_e.index;
root_ivar.type.reset();
)
@@ -607,7 +607,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
else {
BUG(sp, "Overwriting ivar " << slot << " (" << *root_ivar.type << ") with " << type);
}
-
+
#if 1
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Diverge, e,
root_ivar.type->m_data.as_Infer().ty_class = ::HIR::InferClass::Diverge;
@@ -616,7 +616,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
#endif
root_ivar.type = box$( mv$(type) );
}
-
+
this->mark_change();
}
@@ -626,10 +626,10 @@ void HMTypeInferrence::ivar_unify(unsigned int left_slot, unsigned int right_slo
if( left_slot != right_slot )
{
auto& left_ivar = this->get_pointed_ivar(left_slot);
-
+
// TODO: Assert that setting this won't cause a loop.
auto& root_ivar = this->get_pointed_ivar(right_slot);
-
+
TU_IFLET(::HIR::TypeRef::Data, root_ivar.type->m_data, Infer, re,
if( re.ty_class == ::HIR::InferClass::Diverge )
{
@@ -670,11 +670,11 @@ void HMTypeInferrence::ivar_unify(unsigned int left_slot, unsigned int right_slo
else {
BUG(sp, "Unifying over a concrete type - " << *root_ivar.type);
}
-
+
DEBUG("IVar " << root_ivar.type->m_data.as_Infer().index << " = @" << left_slot);
root_ivar.alias = left_slot;
root_ivar.type.reset();
-
+
this->mark_change();
}
}
@@ -685,7 +685,7 @@ HMTypeInferrence::IVar& HMTypeInferrence::get_pointed_ivar(unsigned int slot) co
assert(index < m_ivars.size());
while( m_ivars.at(index).is_alias() ) {
index = m_ivars.at(index).alias;
-
+
if( count >= m_ivars.size() ) {
this->dump();
BUG(Span(), "Loop detected in ivar list when starting at " << slot << ", current is " << index);
@@ -799,7 +799,7 @@ namespace {
{
if( l.size() != r.size() )
return false;
-
+
for( unsigned int i = 0; i < l.size(); i ++ ) {
if( !context.types_equal(l[i], r[i]) )
return false;
@@ -817,7 +817,7 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe
const auto& r = this->get_type(rr);
if( l.m_data.tag() != r.m_data.tag() )
return false;
-
+
struct H {
static bool compare_path(const HMTypeInferrence& self, const ::HIR::Path& l, const ::HIR::Path& r) {
if( l.m_data.tag() != r.m_data.tag() )
@@ -851,7 +851,7 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe
throw "";
}
};
-
+
TU_MATCH(::HIR::TypeRef::Data, (l.m_data, r.m_data), (le, re),
(Infer, return le.index == re.index; ),
(Primitive, return le == re; ),
@@ -923,13 +923,13 @@ void TraitResolution::prep_indexes()
{
static Span sp_AAA;
const Span& sp = sp_AAA;
-
+
auto add_equality = [&](::HIR::TypeRef long_ty, ::HIR::TypeRef short_ty){
DEBUG("[prep_indexes] ADD " << long_ty << " => " << short_ty);
// TODO: Sort the two types by "complexity" (most of the time long >= short)
this->m_type_equalities.insert(::std::make_pair( mv$(long_ty), mv$(short_ty) ));
};
-
+
this->iterate_bounds([&](const auto& b) {
TU_MATCH_DEF(::HIR::GenericBound, (b), (be),
(
@@ -940,10 +940,10 @@ void TraitResolution::prep_indexes()
DEBUG("[prep_indexes] Equality (TB) - <" << be.type << " as " << be.trait.m_path << ">::" << tb.first << " = " << tb.second);
auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), be.trait.m_path.clone(), tb.first ) );
ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
-
+
add_equality( mv$(ty_l), tb.second.clone() );
}
-
+
const auto& trait_params = be.trait.m_path.m_params;
auto cb_mono = [&](const auto& ty)->const auto& {
const auto& ge = ty.m_data.as_Generic();
@@ -959,7 +959,7 @@ void TraitResolution::prep_indexes()
BUG(sp, "Unknown generic binding " << ty);
}
};
-
+
const auto& trait = m_crate.get_trait_by_path(sp, be.trait.m_path.m_path);
for(const auto& a_ty : trait.m_types)
{
@@ -973,10 +973,10 @@ void TraitResolution::prep_indexes()
ty_a.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
}
DEBUG("[prep_indexes] Equality (ATB) - <" << ty_a << " as " << a_ty_b.m_path << ">::" << tb.first << " = " << tb.second);
-
+
auto ty_l = ::HIR::TypeRef( ::HIR::Path( ty_a.clone(), trait_mono.m_path.clone(), tb.first ) );
ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
-
+
add_equality( mv$(ty_l), mv$(tb.second) );
}
}
@@ -1031,7 +1031,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
const auto& type = this->m_ivars.get_type(ty);
TRACE_FUNCTION_F("trait = " << trait << params << ", type = " << type);
-
+
const auto& lang_Sized = this->m_crate.get_lang_item_path(sp, "sized");
const auto& lang_Copy = this->m_crate.get_lang_item_path(sp, "copy");
const auto& lang_Unsize = this->m_crate.get_lang_item_path(sp, "unsize");
@@ -1041,7 +1041,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
const auto& trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once");
const auto& trait_index = this->m_crate.get_lang_item_path(sp, "index");
const auto& trait_indexmut = this->m_crate.get_lang_item_path(sp, "index_mut");
-
+
if( trait == lang_Sized ) {
TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (e),
(
@@ -1063,7 +1063,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
)
return callback( ImplRef(&type, &null_params, &null_assoc), ::HIR::Compare::Equal );
}
-
+
if( trait == lang_Copy ) {
auto cmp = this->type_is_copy(sp, type);
if( cmp != ::HIR::Compare::Unequal ) {
@@ -1073,7 +1073,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return false;
}
}
-
+
// Magic Unsize impls to trait objects
if( trait == lang_Unsize ) {
ASSERT_BUG(sp, params.m_types.size() == 1, "Unsize trait requires a single type param");
@@ -1081,10 +1081,10 @@ bool TraitResolution::find_trait_impls(const Span& sp,
TU_IFLET( ::HIR::TypeRef::Data, dst_ty.m_data, TraitObject, e,
// Magic impl if T: ThisTrait
bool good;
-
+
::HIR::TypeRef::Data::Data_TraitObject tmp_e;
tmp_e.m_trait.m_path = e.m_trait.m_path.m_path;
-
+
::HIR::Compare total_cmp = ::HIR::Compare::Equal;
if( e.m_trait.m_path.m_path == ::HIR::SimplePath() ) {
ASSERT_BUG(sp, e.m_markers.size() > 0, "TraitObject with no traits - " << dst_ty);
@@ -1124,10 +1124,10 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return false;
}
)
-
+
// [T;N] -> [T] is handled down with array indexing
}
-
+
// Magical CoerceUnsized impls for various types
if( trait == lang_CoerceUnsized ) {
const auto& dst_ty = params.m_types.at(0);
@@ -1148,7 +1148,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
)
)
}
-
+
// Magic impls of the Fn* traits for closure types
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Closure, e,
DEBUG("Closure, "<< trait <<" " << trait_fn << " " << trait_fn_mut << " " << trait_fn_once);
@@ -1157,12 +1157,12 @@ bool TraitResolution::find_trait_impls(const Span& sp,
BUG(sp, "Fn* traits require a single tuple argument");
if( !params.m_types[0].m_data.is_Tuple() )
BUG(sp, "Fn* traits require a single tuple argument");
-
+
const auto& args_des = params.m_types[0].m_data.as_Tuple();
if( args_des.size() != e.m_arg_types.size() ) {
return false;
}
-
+
auto cmp = ::HIR::Compare::Equal;
::std::vector< ::HIR::TypeRef> args;
for(unsigned int i = 0; i < e.m_arg_types.size(); i ++)
@@ -1176,9 +1176,9 @@ bool TraitResolution::find_trait_impls(const Span& sp,
// NOTE: This is a conditional "true", we know nothing about the move/mut-ness of this closure yet
// - Could we?
// - Not until after the first stage of typeck
-
+
DEBUG("Closure Fn* impl - cmp = " << cmp);
-
+
::HIR::PathParams pp;
pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) );
::std::map< ::std::string, ::HIR::TypeRef> types;
@@ -1192,7 +1192,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
}
)
-
+
// Magic Fn* trait impls for function pointers
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Function, e,
if( trait == trait_fn || trait == trait_fn_mut || trait == trait_fn_once ) {
@@ -1204,14 +1204,14 @@ bool TraitResolution::find_trait_impls(const Span& sp,
if( args_des.size() != e.m_arg_types.size() ) {
return false;
}
-
+
// NOTE: unsafe or non-rust ABI functions aren't valid
if( e.m_abi != ABI_RUST || e.is_unsafe ) {
DEBUG("- No magic impl, wrong ABI or unsafe in " << type);
return false;
}
DEBUG("- Magic impl of Fn* for " << type);
-
+
auto cmp = ::HIR::Compare::Equal;
::std::vector< ::HIR::TypeRef> args;
for(unsigned int i = 0; i < e.m_arg_types.size(); i ++)
@@ -1220,7 +1220,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
args.push_back( at.clone() );
cmp &= at.compare_with_placeholders(sp, args_des[i], this->m_ivars.callback_resolve_infer());
}
-
+
::HIR::PathParams pp;
pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) );
::std::map< ::std::string, ::HIR::TypeRef> types;
@@ -1229,7 +1229,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
// Continue
)
-
+
// Magic index and unsize impls for Arrays
// NOTE: The index impl for [T] is in libcore.
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Array, e,
@@ -1238,9 +1238,9 @@ bool TraitResolution::find_trait_impls(const Span& sp,
BUG(sp, "Index* traits require a single argument");
DEBUG("- Magic impl of Index* for " << type);
const auto& index_ty = m_ivars.get_type(params.m_types[0]);
-
+
::HIR::Compare cmp;
-
+
// Index<usize> ?
auto ty_usize = ::HIR::TypeRef(::HIR::CoreType::Usize);
cmp = ty_usize.compare_with_placeholders(sp, index_ty, this->m_ivars.callback_resolve_infer());
@@ -1252,7 +1252,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
types.insert( ::std::make_pair( "Output", e.inner->clone() ) );
return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), cmp );
}
-
+
/*
// TODO: Index<Range/RangeFrom/RangeTo/FullRange>? - Requires knowing the path to the range ops (which isn't a lang item)
::HIR::PathParams pp;
@@ -1269,13 +1269,13 @@ bool TraitResolution::find_trait_impls(const Span& sp,
*/
return false;
}
-
+
// Unsize impl for arrays
if( trait == lang_Unsize )
{
ASSERT_BUG(sp, params.m_types.size() == 1, "");
const auto& dst_ty = m_ivars.get_type( params.m_types[0] );
-
+
TU_IFLET(::HIR::TypeRef::Data, dst_ty.m_data, Slice, e2,
auto cmp = e.inner->compare_with_placeholders(sp, *e2.inner, m_ivars.callback_resolve_infer());
if( cmp != ::HIR::Compare::Unequal ) {
@@ -1287,8 +1287,8 @@ bool TraitResolution::find_trait_impls(const Span& sp,
)
}
)
-
-
+
+
// Trait objects automatically implement their own traits
// - IF object safe (TODO)
TU_IFLET(::HIR::TypeRef::Data, type.m_data, TraitObject, e,
@@ -1310,7 +1310,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
}
}
-
+
// - Check if the desired trait is a supertrait of this.
// NOTE: `params` (aka des_params) is not used (TODO)
bool rv = false;
@@ -1334,7 +1334,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
{
return rv;
}
-
+
// Trait objects can unsize to a subset of their traits.
if( trait == lang_Unsize )
{
@@ -1345,9 +1345,9 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return false;
}
const auto& e2 = dst_ty.m_data.as_TraitObject();
-
+
auto cmp = ::HIR::Compare::Equal;
-
+
// TODO: Fuzzy compare
if( e2.m_trait != e.m_trait ) {
return false;
@@ -1370,11 +1370,11 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return false;
}
}
-
+
return callback( ImplRef(&type, &e.m_trait.m_path.m_params, &e.m_trait.m_type_bounds), cmp );
}
)
-
+
TU_IFLET(::HIR::TypeRef::Data, type.m_data, ErasedType, e,
for( const auto& trait_path : e.m_traits )
{
@@ -1385,7 +1385,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return callback( ImplRef(&type, &trait_path.m_path.m_params, &trait_path.m_type_bounds), cmp );
}
}
-
+
// - Check if the desired trait is a supertrait of this.
// NOTE: `params` (aka des_params) is not used (TODO)
bool rv = false;
@@ -1421,19 +1421,19 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return callback( ImplRef(&type, &null_params, &null_assoc), ::HIR::Compare::Fuzzy );
}
)
-
+
// If this type is an opaque UfcsKnown - check bounds
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Path, e,
if( e.binding.is_Opaque() )
{
ASSERT_BUG(sp, e.path.m_data.is_UfcsKnown(), "Opaque bound type wasn't UfcsKnown - " << type);
const auto& pe = e.path.m_data.as_UfcsKnown();
-
+
// If this associated type has a bound of the desired trait, return it.
const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path);
ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item);
const auto& aty_def = trait_ref.m_types.find(pe.item)->second;
-
+
auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr);
for(const auto& bound : aty_def.m_trait_bounds)
@@ -1441,7 +1441,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
const auto& b_params = bound.m_path.m_params;
::HIR::PathParams params_mono_o;
const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params);
-
+
if( bound.m_path.m_path == trait )
{
auto cmp = this->compare_pp(sp, b_params_mono, params);
@@ -1460,7 +1460,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
}
}
-
+
bool ret = this->find_named_trait_in_trait(sp, trait, params, *bound.m_trait_ptr, bound.m_path.m_path, b_params_mono, type,
[&](const auto& i_ty, const auto& i_params, const auto& i_assoc) {
auto cmp = this->compare_pp(sp, i_params, params);
@@ -1475,10 +1475,10 @@ bool TraitResolution::find_trait_impls(const Span& sp,
{
if( ! bound.is_TraitBound() ) continue ;
const auto& be = bound.as_TraitBound();
-
+
if( ! be.type.m_data.is_Path() ) continue ;
if( ! be.type.m_data.as_Path().binding.is_Opaque() ) continue ;
-
+
const auto& be_type_pe = be.type.m_data.as_Path().path.m_data.as_UfcsKnown();
if( *be_type_pe.type != ::HIR::TypeRef("Self", 0xFFFF) )
continue ;
@@ -1486,12 +1486,12 @@ bool TraitResolution::find_trait_impls(const Span& sp,
continue ;
if( be_type_pe.item != pe.item )
continue ;
-
+
// TODO: Merge the below code with the code from the above loop.
const auto& b_params = be.trait.m_path.m_params;
::HIR::PathParams params_mono_o;
const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params);
-
+
if( be.trait.m_path.m_path == trait )
{
auto cmp = this->compare_pp(sp, b_params_mono, params);
@@ -1510,7 +1510,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
}
}
-
+
bool ret = this->find_named_trait_in_trait(sp, trait, params, *be.trait.m_trait_ptr, be.trait.m_path.m_path, b_params_mono, type,
[&](const auto& i_ty, const auto& i_params, const auto& i_assoc) {
auto cmp = this->compare_pp(sp, i_params, params);
@@ -1522,7 +1522,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
}
)
-
+
// 1. Search generic params
if( find_trait_impls_bound(sp, trait, params, type, callback) )
return true;
@@ -1537,7 +1537,7 @@ bool TraitResolution::find_trait_impls(const Span& sp,
void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars)
{
m_ivars.check_for_loops();
-
+
//m_ivars.compact_ivars([&](const ::HIR::TypeRef& t)->auto{ return this->expand_associated_types(Span(), t.clone); });
unsigned int i = 0;
for(auto& v : m_ivars.m_ivars)
@@ -1553,13 +1553,13 @@ void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars)
}
}
else {
-
+
auto index = v.alias;
unsigned int count = 0;
assert(index < m_ivars.m_ivars.size());
while( m_ivars.m_ivars.at(index).is_alias() ) {
index = m_ivars.m_ivars.at(index).alias;
-
+
if( count >= m_ivars.m_ivars.size() ) {
this->m_ivars.dump();
BUG(Span(), "Loop detected in ivar list when starting at " << v.alias << ", current is " << index);
@@ -1768,7 +1768,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
TRACE_FUNCTION_FR("input=" << input, input);
auto& e = input.m_data.as_Path();
auto& pe = e.path.m_data.as_UfcsKnown();
-
+
struct D {
const TraitResolution& m_tr;
D(const TraitResolution& tr, ::HIR::TypeRef v): m_tr(tr) {
@@ -1781,9 +1781,9 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
D _(*this, input.clone());
// State stack to avoid infinite recursion
LList<const ::HIR::TypeRef*> stack(&prev_stack, &m_eat_active_stack.back());
-
+
expand_associated_types_inplace(sp, *pe.type, stack);
-
+
// - If it's a closure, then the only trait impls are those generated by typeck
TU_IFLET(::HIR::TypeRef::Data, pe.type->m_data, Closure, te,
const auto trait_fn = this->m_crate.get_lang_item_path(sp, "fn");
@@ -1799,7 +1799,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
}
}
)
-
+
TU_IFLET(::HIR::TypeRef::Data, pe.type->m_data, Function, te,
if( te.m_abi == ABI_RUST && !te.is_unsafe )
{
@@ -1817,7 +1817,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
}
}
)
-
+
// If it's a TraitObject, then maybe we're asking for a bound
TU_IFLET(::HIR::TypeRef::Data, pe.type->m_data, TraitObject, te,
const auto& data_trait = te.m_trait.m_path;
@@ -1844,12 +1844,12 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
// - Why opaque? It's not bounded, don't even bother
TODO(sp, "Handle unconstrained associate type " << pe.item << " from " << *pe.type);
}
-
+
input = it->second.clone();
return ;
}
}
-
+
// - Check if the desired trait is a supertrait of this.
// NOTE: `params` (aka des_params) is not used (TODO)
bool is_supertrait = this->find_named_trait_in_trait(sp, pe.trait.m_path,pe.trait.m_params, *te.m_trait.m_trait_ptr, data_trait.m_path,data_trait.m_params, *pe.type,
@@ -1877,7 +1877,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
return ;
}
)
-
+
// If it's a ErasedType, then maybe we're asking for a bound
TU_IFLET(::HIR::TypeRef::Data, pe.type->m_data, ErasedType, te,
for( const auto& trait : te.m_traits )
@@ -1906,12 +1906,12 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
// - Why opaque? It's not bounded, don't even bother
TODO(sp, "Handle unconstrained associate type " << pe.item << " from " << *pe.type);
}
-
+
input = it->second.clone();
return ;
}
}
-
+
// - Check if the desired trait is a supertrait of this.
// NOTE: `params` (aka des_params) is not used (TODO)
bool is_supertrait = this->find_named_trait_in_trait(sp, pe.trait.m_path,pe.trait.m_params, *trait.m_trait_ptr, trait_gp.m_path,trait_gp.m_params, *pe.type,
@@ -1940,7 +1940,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
}
}
)
-
+
// 1. Bounds
bool rv;
bool assume_opaque = true;
@@ -1969,7 +1969,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
}
return true;
}
-
+
bool found_supertrait = this->find_named_trait_in_trait(sp,
pe.trait.m_path, pe.trait.m_params,
*be.trait.m_trait_ptr, be.trait.m_path.m_path, be.trait.m_path.m_params, *pe.type,
@@ -1998,7 +1998,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
}
return true;
}
-
+
// - Didn't match
),
(TypeEquality,
@@ -2016,11 +2016,11 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
if( assume_opaque ) {
DEBUG("Assuming that " << input << " is an opaque name");
input.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
-
+
DEBUG("- " << m_type_equalities.size() << " replacements");
for( const auto& v : m_type_equalities )
DEBUG(" > " << v.first << " = " << v.second);
-
+
auto a = m_type_equalities.find(input);
if( a != m_type_equalities.end() ) {
input = a->second.clone();
@@ -2042,7 +2042,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path);
const auto& assoc_ty = trait_ptr.m_types.at(pe_inner.item);
DEBUG("TODO: Search bounds on associated type - " << assoc_ty.m_trait_bounds);
-
+
// Resolve where Self=pe_inner.type (i.e. for the trait this inner UFCS is on)
auto cb_placeholders_trait = [&](const auto& ty)->const auto&{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
@@ -2087,7 +2087,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
if( !this->trait_contains_type(sp, pe.trait, this->m_crate.get_trait_by_path(sp, pe.trait.m_path), pe.item, trait_path) )
BUG(sp, "Cannot find associated type " << pe.item << " anywhere in trait " << pe.trait);
//pe.trait = mv$(trait_path);
-
+
DEBUG("Searching for impl");
bool can_fuzz = true;
unsigned int count = 0;
@@ -2112,7 +2112,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
best_impl = ImplRef();
can_fuzz = false;
}
-
+
// If the type is specialisable
if( impl.type_is_specialisable(pe.item.c_str()) ) {
// Check if this is more specific
@@ -2126,10 +2126,10 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
auto ty = impl.get_type( pe.item.c_str() );
if( ty == ::HIR::TypeRef() )
ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait);
-
+
if( impl.has_magic_params() )
;
-
+
// TODO: What if there's multiple impls?
DEBUG("Converted UfcsKnown - " << e.path << " = " << ty);
input = mv$(ty);
@@ -2149,13 +2149,13 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
auto ty = best_impl.get_type( pe.item.c_str() );
if( ty == ::HIR::TypeRef() )
ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait);
-
+
// Try again later?
if( best_impl.has_magic_params() ) {
DEBUG("- Placeholder parameters present in impl, can't expand");
return ;
}
-
+
DEBUG("Converted UfcsKnown - " << e.path << " = " << ty);
input = mv$(ty);
rv = true;
@@ -2165,7 +2165,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp,
expand_associated_types_inplace(sp, input, stack);
return ;
}
-
+
// If there are no ivars in this path, set its binding to Opaque
if( !this->m_ivars.type_contains_ivars(input) ) {
// TODO: If the type is a generic or an opaque associated, we can't know.
@@ -2195,7 +2195,7 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp,
if( pp.m_types.size() != trait_ptr.m_params.m_types.size() ) {
BUG(sp, "Incorrect number of parameters for trait");
}
-
+
const auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
@@ -2207,7 +2207,7 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp,
return pp.m_types[ge.binding];
}
};
-
+
for( const auto& pt : trait_ptr.m_parent_traits )
{
auto pt_mono = monomorphise_traitpath_with(sp, pt, monomorph_cb, false);
@@ -2222,19 +2222,19 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp,
//}
return true;
}
-
+
const auto& tr = m_crate.get_trait_by_path(sp, pt.m_path.m_path);
if( find_named_trait_in_trait(sp, des, des_params, tr, pt.m_path.m_path, pt_mono.m_path.m_params, target_type, callback) ) {
return true;
}
}
-
+
// Also check bounds for `Self: T` bounds
for(const auto& b : trait_ptr.m_params.m_bounds)
{
if( !b.is_TraitBound() ) continue;
const auto& be = b.as_TraitBound();
-
+
if( be.type == ::HIR::TypeRef("Self", 0xFFFF) )
{
// Something earlier adds a "Self: SelfTrait" bound, prevent that from causing infinite recursion
@@ -2252,14 +2252,14 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp,
//}
return true;
}
-
+
const auto& tr = m_crate.get_trait_by_path(sp, pt_mono.m_path.m_path);
if( find_named_trait_in_trait(sp, des, des_params, tr, pt_mono.m_path.m_path, pt_mono.m_path.m_params, target_type, callback) ) {
return true;
}
}
}
-
+
return false;
}
bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const
@@ -2274,17 +2274,17 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
if( m_ivars.get_type(type).m_data.is_Infer() )
return false;
-
+
// TODO: A bound can imply something via its associated types. How deep can this go?
// E.g. `T: IntoIterator<Item=&u8>` implies `<T as IntoIterator>::IntoIter : Iterator<Item=&u8>`
return this->iterate_bounds([&](const auto& b) {
TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
const auto& b_params = e.trait.m_path.m_params;
-
+
auto cmp = e.type .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer());
if( cmp == ::HIR::Compare::Unequal )
return false;
-
+
if( e.trait.m_path.m_path == trait ) {
// Check against `params`
DEBUG("Checking " << params << " vs " << b_params);
@@ -2301,7 +2301,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
return true;
}
}
-
+
// TODO: Allow fuzzy equality?
if( cmp == ::HIR::Compare::Equal )
{
@@ -2329,7 +2329,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
return true;
}
}
-
+
// If the input type is an associated type controlled by this trait bound, check for added bounds.
// TODO: This just checks a single layer, but it's feasable that there could be multiple layers
if( assoc_info && e.trait.m_path.m_path == assoc_info->trait.m_path && e.type == *assoc_info->type )
@@ -2342,7 +2342,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
if( ord == ::HIR::Compare::Unequal ) {
return false;
}
-
+
const auto& trait_ref = *e.trait.m_trait_ptr;
const auto& at = trait_ref.m_types.at(assoc_info->item);
for(const auto& bound : at.m_trait_bounds) {
@@ -2359,7 +2359,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
return assoc_info->trait.m_params.m_types[ge.binding];
}
};
-
+
DEBUG("- Found an associated type bound for this trait via another bound");
::HIR::Compare ord;
if( monomorphise_pathparams_needed(bound.m_path.m_params) ) {
@@ -2375,7 +2375,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
if( ord == ::HIR::Compare::Fuzzy ) {
DEBUG("Fuzzy match");
}
-
+
auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false);
// - Expand associated types
for(auto& ty : tp_mono.m_type_bounds) {
@@ -2389,7 +2389,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
}
}
}
-
+
return false;
)
return false;
@@ -2403,7 +2403,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
{
static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc;
TRACE_FUNCTION_F(trait << FMT_CB(ss, if(params_ptr) { ss << *params_ptr; } else { ss << "<?>"; }) << " for " << type);
-
+
// Handle auto traits (aka OIBITs)
if( m_crate.get_trait_by_path(sp, trait).m_is_marker )
{
@@ -2416,7 +2416,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
continue ;
if( *::std::get<2>(ent) != type )
continue ;
-
+
return callback( ImplRef(&type, params_ptr, &null_assoc), ::HIR::Compare::Equal );
}
stack.push_back( ::std::make_tuple( &trait, params_ptr, &type ) );
@@ -2424,13 +2424,13 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
~Guard() { stack.pop_back(); }
};
Guard _;
-
+
// NOTE: Expected behavior is for Ivars to return false
// TODO: Should they return Compare::Fuzzy instead?
if( type.m_data.is_Infer() ) {
return false;
}
-
+
const ::HIR::TraitMarkings* markings = nullptr;
TU_IFLET( ::HIR::TypeRef::Data, (type.m_data), Path, e,
if( e.path.m_data.is_Generic() && e.path.m_data.as_Generic().m_params.m_types.size() == 0 )
@@ -2471,7 +2471,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
}
}
}
-
+
// - Search for positive impls for this type
DEBUG("- Search positive impls");
bool positive_found = false;
@@ -2480,9 +2480,9 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
// Skip any negative impls on this pass
if( impl.is_positive != true )
return false;
-
+
DEBUG("[find_trait_impls_crate] - Auto Pos Found impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type << " " << impl.m_params.fmt_bounds());
-
+
// Compare with `params`
::std::vector< const ::HIR::TypeRef*> impl_params;
::std::vector< ::HIR::TypeRef> placeholders;
@@ -2491,7 +2491,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
// If any bound failed, return false (continue searching)
return false;
}
-
+
auto monomorph = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
ASSERT_BUG(sp, ge.binding >> 8 != 2, "");
@@ -2502,11 +2502,11 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
return *impl_params[ge.binding];
};
// TODO: Ensure that there are no-longer any magic params?
-
+
auto ty_mono = monomorphise_type_with(sp, impl.m_type, monomorph, false);
auto args_mono = monomorphise_path_params_with(sp, impl.m_trait_args, monomorph, false);
// NOTE: Auto traits can't have items, so no associated types
-
+
positive_found = true;
DEBUG("[find_trait_impls_crate] Auto Positive callback(args=" << args_mono << ")");
return callback(ImplRef(mv$(ty_mono), mv$(args_mono), {}), match);
@@ -2515,7 +2515,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
// A positive impl was found, so return true (callback should have been called)
return true;
}
-
+
// - Search for negative impls for this type
DEBUG("- Search negative impls");
bool negative_found = this->m_crate.find_auto_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(),
@@ -2524,7 +2524,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
if( impl.is_positive != false )
return false;
DEBUG("[find_trait_impls_crate] - Found auto neg impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type << " " << impl.m_params.fmt_bounds());
-
+
// Compare with `params`
::std::vector< const ::HIR::TypeRef*> impl_params;
::std::vector< ::HIR::TypeRef> placeholders;
@@ -2533,7 +2533,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
// If any bound failed, return false (continue searching)
return false;
}
-
+
DEBUG("[find_trait_impls_crate] - Found neg impl");
return true;
});
@@ -2541,7 +2541,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
// A negative impl _was_ found, so return false
return false;
}
-
+
auto cmp = this->check_auto_trait_impl_destructure(sp, trait, params_ptr, type);
if( cmp != ::HIR::Compare::Unequal )
{
@@ -2559,7 +2559,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
return false;
}
}
-
+
return this->m_crate.find_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(),
[&](const auto& impl) {
DEBUG("[find_trait_impls_crate] Found impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type << " " << impl.m_params.fmt_bounds());
@@ -2588,7 +2588,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
DEBUG("[check_auto_trait_impl_destructure] " << inner_ty << " - " << l_res);
return l_res;
};
-
+
// - If the type is a path (struct/enum/...), search for impls for all contained types.
TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Path, e,
::HIR::Compare res = ::HIR::Compare::Equal;
@@ -2618,7 +2618,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
return ty;
}
};
-
+
TU_MATCH( ::HIR::TypeRef::TypePathBinding, (e.binding), (tpb),
(Opaque,
BUG(sp, "Opaque binding on generic path - " << type);
@@ -2628,7 +2628,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
),
(Struct,
const auto& str = *tpb;
-
+
// TODO: Somehow store a ruleset for auto traits on the type
// - Map of trait->does_impl for local fields?
// - Problems occur with type parameters
@@ -2650,7 +2650,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
{
const auto& fld_ty_mono = monomorph_get(fld.second.ent);
DEBUG("Struct::Named '" << fld.first << "' " << fld_ty_mono);
-
+
res &= type_impls_trait(fld_ty_mono);
if( res == ::HIR::Compare::Unequal )
return ::HIR::Compare::Unequal;
@@ -2660,7 +2660,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
),
(Enum,
const auto& enm = *tpb;
-
+
for(const auto& var : enm.m_variants)
{
TU_MATCH(::HIR::Enum::Variant, (var.second), (ve),
@@ -2683,7 +2683,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
{
const auto& fld_ty_mono = monomorph_get(fld.second.ent);
DEBUG("Enum '" << var.first << "'::Struct '" << fld.first << "' " << fld_ty_mono);
-
+
res &= type_impls_trait(fld_ty_mono);
if( res == ::HIR::Compare::Unequal )
return ::HIR::Compare::Unequal;
@@ -2782,7 +2782,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
return ::HIR::Compare::Unequal;
}
}
-
+
// TODO: Some impl blocks have type params used as part of type bounds.
// - A rough idea is to have monomorph return a third class of generic for params that are not yet bound.
// - compare_with_placeholders gets called on both ivars and generics, so that can be used to replace it once known.
@@ -2794,7 +2794,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
}
}
auto cb_infer = [&](const auto& ty)->const auto& {
- if( ty.m_data.is_Infer() )
+ if( ty.m_data.is_Infer() )
return this->m_ivars.get_type(ty);
else if( ty.m_data.is_Generic() && ty.m_data.as_Generic().binding >> 8 == 2 ) { // Generic group 2 = Placeholders
unsigned int i = ty.m_data.as_Generic().binding % 256;
@@ -2833,7 +2833,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
}
return *impl_params[ge.binding];
};
-
+
// Check bounds for this impl
// - If a bound fails, then this can't be a valid impl
for(const auto& bound : impl_params_def.m_bounds)
@@ -2866,7 +2866,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
for(const auto& assoc_bound : real_trait.m_type_bounds) {
::HIR::TypeRef tmp;
const ::HIR::TypeRef* ty_p;
-
+
tmp = impl.get_type(assoc_bound.first.c_str());
if( tmp == ::HIR::TypeRef() ) {
// This bound isn't from this particular trait, go the slow way of using expand_associated_types
@@ -2929,7 +2929,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
)
)
}
-
+
return match;
}
@@ -2956,7 +2956,7 @@ bool TraitResolution::trait_contains_method(const Span& sp, const ::HIR::Generic
}
}
}
-
+
// TODO: Prevent infinite recursion
for(const auto& st : trait_ptr.m_parent_traits)
{
@@ -2988,7 +2988,7 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa
out_path = trait_path.clone();
return true;
}
-
+
auto monomorph = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
assert(ge.binding < 256);
@@ -3134,9 +3134,9 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
const auto& top_ty_r = this->m_ivars.get_type(top_ty);
const auto* current_ty = &top_ty_r;
-
+
bool unconditional_allow_move = true;
-
+
// If the top is a borrow, search dereferenced first.
TU_IFLET(::HIR::TypeRef::Data, top_ty_r.m_data, Borrow, e,
if( e.type == ::HIR::BorrowType::Owned ) {
@@ -3152,7 +3152,7 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
current_ty = &*e.inner;
deref_count += 1;
)
-
+
// Handle `self: Box<Self>` methods by detecting m_lang_Box and searchig for box receiver methods
TU_IFLET(::HIR::TypeRef::Data, top_ty_r.m_data, Path, e,
TU_IFLET(::HIR::Path::Data, e.path.m_data, Generic, pe,
@@ -3171,10 +3171,10 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
}
)
)
-
+
// TODO: This appears to dereference a &mut to call a `self: Self` method, where it should use the trait impl on &mut Self.
// - Shouldn't deref to get a by-value receiver.// unless it's via a &move.
-
+
do {
// TODO: Update `unconditional_allow_move` based on the current type.
const auto& ty = this->m_ivars.get_type(*current_ty);
@@ -3186,15 +3186,15 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
DEBUG("- Unbound type path " << ty << ", pausing");
return ~0u;
}
-
+
auto allowed_receivers = (unconditional_allow_move || (deref_count == 0) ? AllowedReceivers::All : AllowedReceivers::AnyBorrow);
if( this->find_method(sp, traits, ivars, ty, method_name, allowed_receivers, fcn_path) ) {
DEBUG("FOUND " << deref_count << ", fcn_path = " << fcn_path);
borrow = AutoderefBorrow::None;
return deref_count;
}
-
-
+
+
auto borrow_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone());
if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
DEBUG("FOUND &*" << deref_count << ", fcn_path = " << fcn_path);
@@ -3213,30 +3213,30 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
borrow = AutoderefBorrow::Owned;
return deref_count;
}
-
+
// 3. Dereference and try again
deref_count += 1;
current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
-
- // If the top is a borrow, search for methods on &/&mut
+
+ // If the top is a borrow, search for methods on &/&mut
TU_IFLET(::HIR::TypeRef::Data, top_ty_r.m_data, Borrow, e,
const auto& ty = top_ty_r;
-
+
if( find_method(sp, traits, ivars, ty, method_name, AllowedReceivers::All, fcn_path) ) {
DEBUG("FOUND " << 0 << ", fcn_path = " << fcn_path);
borrow = AutoderefBorrow::None;
return 0;
}
)
-
+
// If there are ivars within the type, don't error (yet)
if( this->m_ivars.type_contains_ivars(top_ty) )
{
DEBUG("- Contains ivars, pausing");
return ~0u;
}
-
+
// Insert a single reference and try again (only allowing by-value methods), returning a magic value (e.g. ~1u)
// - Required for calling `(self[..]: str).into_searcher(haystack)` - Which invokes `<&str as Pattern>::into_searcher(&self[..], haystack)`
// - Have to do several tries, each with different borrow classes.
@@ -3258,7 +3258,7 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
borrow = AutoderefBorrow::Owned;
return 0;
}
-
+
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
//this->m_ivars.dump();
ERROR(sp, E0000, "Could not find method `" << method_name << "` on type `" << top_ty << "`");
@@ -3294,7 +3294,7 @@ bool TraitResolution::find_method(
// TODO: Do a fuzzy match here?
if( e.type != ty )
continue ;
-
+
// - Bound's type matches, check if the bounded trait has the method we're searching for
DEBUG("Bound `" << e.type << " : " << e.trait.m_path << "` - Type match " << ty);
::HIR::GenericPath final_trait_path;
@@ -3306,7 +3306,7 @@ bool TraitResolution::find_method(
DEBUG("- Found trait " << final_trait_path);
// TODO: Re-monomorphise final trait using `ty`?
// - Could collide with legitimate uses of `Self`
-
+
// Found the method, return the UFCS path for it
fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
box$( ty.clone() ),
@@ -3324,13 +3324,13 @@ bool TraitResolution::find_method(
//assert( e.m_trait.m_trait_ptr );
//const auto& trait = *e.m_trait.m_trait_ptr;
const auto& trait = this->m_crate.get_trait_by_path(sp, e.m_trait.m_path.m_path);
-
-
+
+
::HIR::GenericPath final_trait_path;
if( this->trait_contains_method(sp, e.m_trait.m_path, trait, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar, final_trait_path) )
{
DEBUG("- Found trait " << final_trait_path);
-
+
fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({
box$( ty.clone() ),
mv$(final_trait_path),
@@ -3340,18 +3340,18 @@ bool TraitResolution::find_method(
return true;
}
)
-
+
// Erased type - `impl Trait`
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, ErasedType, e,
for(const auto& trait_path : e.m_traits)
{
const auto& trait = this->m_crate.get_trait_by_path(sp, trait_path.m_path.m_path);
-
+
::HIR::GenericPath final_trait_path;
if( this->trait_contains_method(sp, trait_path.m_path, trait, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar, final_trait_path) )
{
DEBUG("- Found trait " << final_trait_path);
-
+
fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({
box$( ty.clone() ),
mv$(final_trait_path),
@@ -3362,7 +3362,7 @@ bool TraitResolution::find_method(
}
}
)
-
+
// Trait object - `(Trait)`
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
// No match, keep trying.
@@ -3371,9 +3371,9 @@ bool TraitResolution::find_method(
{
const auto& e = ty.m_data.as_Path().path.m_data.as_UfcsKnown();
DEBUG("UfcsKnown - Search associated type bounds in trait - " << e.trait);
-
+
// UFCS known - Assuming that it's reached the maximum resolvable level (i.e. a type within is generic), search for trait bounds on the type
-
+
// `Self` = `*e.type`
// `/*I:#*/` := `e.trait.m_params`
auto monomorph_cb = [&](const auto& gt)->const auto& {
@@ -3393,7 +3393,7 @@ bool TraitResolution::find_method(
// `Self` = `*e.type`
// `/*I:#*/` := `e.trait.m_params`
//auto monomorph_cb = monomorphise_type_get_cb(sp, &*e.type, &e.trait.m_params, nullptr);
-
+
const auto& trait = this->m_crate.get_trait_by_path(sp, e.trait.m_path);
const auto& assoc_ty = trait.m_types.at( e.item );
// NOTE: The bounds here have 'Self' = the type
@@ -3404,12 +3404,12 @@ bool TraitResolution::find_method(
if( !this->trait_contains_method(sp, bound.m_path, *bound.m_trait_ptr, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar, final_trait_path) )
continue ;
DEBUG("- Found trait " << final_trait_path);
-
+
if( monomorphise_pathparams_needed(final_trait_path.m_params) ) {
final_trait_path.m_params = monomorphise_path_params_with(sp, final_trait_path.m_params, monomorph_cb, false);
DEBUG("- Monomorph to " << final_trait_path);
}
-
+
// Found the method, return the UFCS path for it
fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
box$( ty.clone() ),
@@ -3419,16 +3419,16 @@ bool TraitResolution::find_method(
}) );
return true;
}
-
+
// Search `<Self as Trait>::Name` bounds on the trait itself
for(const auto& bound : trait.m_params.m_bounds)
{
if( ! bound.is_TraitBound() ) continue ;
const auto& be = bound.as_TraitBound();
-
+
if( ! be.type.m_data.is_Path() ) continue ;
if( ! be.type.m_data.as_Path().binding.is_Opaque() ) continue ;
-
+
const auto& be_type_pe = be.type.m_data.as_Path().path.m_data.as_UfcsKnown();
if( *be_type_pe.type != ::HIR::TypeRef("Self", 0xFFFF) )
continue ;
@@ -3436,17 +3436,17 @@ bool TraitResolution::find_method(
continue ;
if( be_type_pe.item != e.item )
continue ;
-
+
::HIR::GenericPath final_trait_path;
if( !this->trait_contains_method(sp, be.trait.m_path, *be.trait.m_trait_ptr, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar, final_trait_path) )
continue ;
DEBUG("- Found trait " << final_trait_path);
-
+
if( monomorphise_pathparams_needed(final_trait_path.m_params) ) {
final_trait_path.m_params = monomorphise_path_params_with(sp, final_trait_path.m_params, monomorph_cb, false);
DEBUG("- Monomorph to " << final_trait_path);
}
-
+
// Found the method, return the UFCS path for it
fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
box$( ty.clone() ),
@@ -3495,18 +3495,18 @@ bool TraitResolution::find_method(
return true;
}
}
-
+
// 3. Search for trait methods (using currently in-scope traits)
for(const auto& trait_ref : ::reverse(traits))
{
if( trait_ref.first == nullptr )
break;
-
+
//::HIR::GenericPath final_trait_path;
//if( !this->trait_contains_method(sp, *trait_ref.first, *trait_ref.second, method_name, final_trait_path) )
// continue ;
//DEBUG("- Found trait " << final_trait_path);
-
+
// TODO: Shouldn't this use trait_contains_method?
// TODO: Search supertraits too
auto it = trait_ref.second->m_values.find(method_name);
@@ -3531,7 +3531,7 @@ bool TraitResolution::find_method(
if( ar == AllowedReceivers::Value || ar == AllowedReceivers::Box || (v.m_receiver == ::HIR::Function::Receiver::Box && ar != AllowedReceivers::AnyBorrow) )
break;
DEBUG("Search for impl of " << *trait_ref.first);
-
+
// Use the set of ivars we were given to populate the trait parameters
unsigned int n_params = trait_ref.second->m_params.m_types.size();
assert(n_params <= ivars.size());
@@ -3541,7 +3541,7 @@ bool TraitResolution::find_method(
trait_params.m_types.push_back( ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Infer({ ivars[i], ::HIR::InferClass::None }) ) );
ASSERT_BUG(sp, m_ivars.get_type( trait_params.m_types.back() ).m_data.as_Infer().index == ivars[i], "A method selection ivar was bound");
}
-
+
//if( find_trait_impls(sp, *trait_ref.first, trait_params, ty, [](auto , auto ) { return true; }) ) {
if( find_trait_impls_crate(sp, *trait_ref.first, &trait_params, ty, [](auto , auto ) { return true; }) ) {
DEBUG("Found trait impl " << *trait_ref.first << trait_params << " for " << ty << " ("<<m_ivars.fmt_type(ty)<<")");
@@ -3556,7 +3556,7 @@ bool TraitResolution::find_method(
break;
}
}
-
+
return false;
}
@@ -3569,7 +3569,7 @@ unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::
current_ty = &*e.inner;
deref_count += 1;
)
-
+
do {
const auto& ty = this->m_ivars.get_type(*current_ty);
if( ty.m_data.is_Infer() ) {
@@ -3578,24 +3578,24 @@ unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::
if(ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Unbound()) {
return ~0u;
}
-
+
if( this->find_field(sp, ty, field_name, field_type) ) {
return deref_count;
}
-
+
// 3. Dereference and try again
deref_count += 1;
current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
-
+
TU_IFLET(::HIR::TypeRef::Data, this->m_ivars.get_type(top_ty).m_data, Borrow, e,
const auto& ty = this->m_ivars.get_type(top_ty);
-
+
if( find_field(sp, ty, field_name, field_type) ) {
return 0;
}
)
-
+
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
this->m_ivars.dump();
TODO(sp, "Error when no field could be found, but type is known - (: " << top_ty << ")." << field_name);
@@ -3673,7 +3673,7 @@ bool TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const
}
return gt;
};
-
+
for( const auto& fld : unm.m_variants )
{
// TODO: Privacy
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 9bf8d4d9..19235a8e 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -45,22 +45,22 @@ public: // ?? - Needed once, anymore?
{
unsigned int alias; // If not ~0, this points to another ivar
::std::unique_ptr< ::HIR::TypeRef> type; // Type (only nullptr if alias!=0)
-
+
IVar():
alias(~0u),
type(new ::HIR::TypeRef())
{}
bool is_alias() const { return alias != ~0u; }
};
-
+
::std::vector< IVar> m_ivars;
bool m_has_changed;
-
+
public:
HMTypeInferrence():
m_has_changed(false)
{}
-
+
bool peek_changed() const {
return m_has_changed;
}
@@ -75,36 +75,36 @@ public:
m_has_changed = true;
}
}
-
+
void compact_ivars();
bool apply_defaults();
-
+
void dump() const;
-
+
void print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const;
void print_pathparams(::std::ostream& os, const ::HIR::PathParams& pps) const;
-
+
FmtType fmt_type(const ::HIR::TypeRef& tr) const {
return FmtType(*this, tr);
}
FmtPP fmt(const ::HIR::PathParams& v) const {
return FmtPP(*this, v);
}
-
+
/// Add (and bind) all '_' types in `type`
void add_ivars(::HIR::TypeRef& type);
// (helper) Add ivars to path parameters
void add_ivars_params(::HIR::PathParams& params);
-
+
::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> callback_resolve_infer() const {
return [&](const auto& ty)->const auto& {
- if( ty.m_data.is_Infer() )
+ if( ty.m_data.is_Infer() )
return this->get_type(ty);
else
return ty;
};
}
-
+
// Mutation
unsigned int new_ivar();
::HIR::TypeRef new_ivar_tr();
@@ -114,7 +114,7 @@ public:
// Lookup
::HIR::TypeRef& get_type(::HIR::TypeRef& type);
const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const;
-
+
void check_for_loops();
void expand_ivars(::HIR::TypeRef& type);
void expand_ivars_params(::HIR::PathParams& params);
@@ -131,13 +131,13 @@ private:
class TraitResolution
{
const HMTypeInferrence& m_ivars;
-
+
const ::HIR::Crate& m_crate;
const ::HIR::GenericParams* m_impl_params;
const ::HIR::GenericParams* m_item_params;
-
+
::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities;
-
+
::HIR::SimplePath m_lang_Box;
mutable ::std::vector< ::HIR::TypeRef> m_eat_active_stack;
public:
@@ -150,7 +150,7 @@ public:
prep_indexes();
m_lang_Box = crate.get_lang_item_path_opt("owned_box");
}
-
+
const ::HIR::GenericParams& impl_params() const {
static ::HIR::GenericParams empty;
return m_impl_params ? *m_impl_params : empty;
@@ -159,16 +159,16 @@ public:
static ::HIR::GenericParams empty;
return m_item_params ? *m_item_params : empty;
}
-
+
void prep_indexes();
-
+
::HIR::Compare compare_pp(const Span& sp, const ::HIR::PathParams& left, const ::HIR::PathParams& right) const;
-
+
void compact_ivars(HMTypeInferrence& m_ivars);
-
+
/// Check if a trait bound applies, using the passed function to expand Generic/Infer types
bool check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, t_cb_generic placeholder) const;
-
+
bool has_associated_type(const ::HIR::TypeRef& ty) const;
/// Expand any located associated types in the input, operating in-place and returning the result
::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const {
@@ -184,16 +184,16 @@ public:
return input;
}
}
-
+
/// Iterate over in-scope bounds (function then top)
bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const;
typedef ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl;
typedef ::std::function<bool(ImplRef, ::HIR::Compare)> t_cb_trait_impl_r;
-
+
/// Searches for a trait impl that matches the provided trait name and type
bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const;
-
+
/// Locate a named trait in the provied trait (either itself or as a parent trait)
bool find_named_trait_in_trait(const Span& sp,
const ::HIR::SimplePath& des, const ::HIR::PathParams& params,
@@ -209,7 +209,7 @@ public:
}
/// Search for a trait implementation in the crate (allows nullptr to ignore params)
bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const;
-
+
private:
::HIR::Compare check_auto_trait_impl_destructure(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params_ptr, const ::HIR::TypeRef& type) const;
::HIR::Compare ftic_check_params(const Span& sp, const ::HIR::SimplePath& trait,
@@ -218,7 +218,7 @@ private:
/*Out->*/ ::std::vector< const ::HIR::TypeRef*>& impl_params, ::std::vector< ::HIR::TypeRef>& placeholders
) const ;
public:
-
+
enum class AutoderefBorrow {
None,
Shared,
@@ -231,10 +231,10 @@ public:
/// Locate the named field by applying auto-dereferencing.
/// \return Number of times deref was applied (or ~0 if _ was hit)
unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
-
+
/// Apply an automatic dereference
const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const;
-
+
bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
enum class AllowedReceivers {
@@ -245,7 +245,7 @@ public:
};
friend ::std::ostream& operator<<(::std::ostream& os, const AllowedReceivers& x);
bool find_method(const Span& sp, const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, AllowedReceivers ar, /* Out -> */::HIR::Path& fcn_path) const;
-
+
/// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters)
bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, AllowedReceivers ar, ::HIR::GenericPath& out_path) const;
bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp
index abda820e..73472c16 100644
--- a/src/hir_typeck/impl_ref.cpp
+++ b/src/hir_typeck/impl_ref.cpp
@@ -127,7 +127,7 @@ bool ImplRef::type_is_specialisable(const char* name) const
if( e.impl == nullptr ) {
BUG(Span(), "nullptr");
}
-
+
return monomorphise_path_params_with(sp, e.impl->m_trait_args, this->get_cb_monomorph_traitimpl(sp), true);
),
(BoundedPtr,
diff --git a/src/hir_typeck/impl_ref.hpp b/src/hir_typeck/impl_ref.hpp
index bbff0054..dc5378fd 100644
--- a/src/hir_typeck/impl_ref.hpp
+++ b/src/hir_typeck/impl_ref.hpp
@@ -29,9 +29,9 @@ struct ImplRef
::std::map< ::std::string, ::HIR::TypeRef> assoc;
})
);
-
+
Data m_data;
-
+
ImplRef():
m_data(Data::make_TraitImpl({ {}, {}, nullptr, nullptr }))
{}
@@ -45,13 +45,13 @@ struct ImplRef
ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< ::std::string, ::HIR::TypeRef> assoc):
m_data(Data::make_Bounded({ mv$(type), mv$(args), mv$(assoc) }))
{}
-
+
bool is_valid() const {
return !(m_data.is_TraitImpl() && m_data.as_TraitImpl().impl == nullptr);
}
-
+
bool more_specific_than(const ImplRef& other) const;
-
+
bool has_magic_params() const {
TU_IFLET(Data, m_data, TraitImpl, e,
for(const auto& t : e.params_ph)
@@ -60,17 +60,17 @@ struct ImplRef
)
return false;
}
-
+
/// HELPER: Returns callback to monomorphise a type using parameters from Data::TraitImpl
::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> get_cb_monomorph_traitimpl(const Span& sp) const;
-
+
::HIR::TypeRef get_impl_type() const;
::HIR::PathParams get_trait_params() const;
-
+
::HIR::TypeRef get_trait_ty_param(unsigned int) const;
-
+
bool type_is_specialisable(const char* name) const;
::HIR::TypeRef get_type(const char* name) const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x);
};
diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp
index ed2063d4..5f5e5a75 100644
--- a/src/hir_typeck/outer.cpp
+++ b/src/hir_typeck/outer.cpp
@@ -10,14 +10,14 @@
#include <hir_typeck/static.hpp>
namespace {
-
+
const ::HIR::GenericParams& get_params_for_item(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path, ::HIR::Visitor::PathContext pc)
{
switch( pc )
{
case ::HIR::Visitor::PathContext::VALUE: {
const auto& item = crate.get_valitem_by_path(sp, path);
-
+
TU_MATCH( ::HIR::ValueItem, (item), (e),
(Import,
BUG(sp, "Value path pointed to import - " << path << " = " << e.path);
@@ -44,7 +44,7 @@ namespace {
// TODO: treat PathContext::TRAIT differently
case ::HIR::Visitor::PathContext::TYPE: {
const auto& item = crate.get_typeitem_by_path(sp, path);
-
+
TU_MATCH( ::HIR::TypeItem, (item), (e),
(Import,
BUG(sp, "Type path pointed to import - " << path);
@@ -71,25 +71,25 @@ namespace {
} break;
}
throw "";
-
+
}
-
+
class Visitor:
public ::HIR::Visitor
{
::HIR::Crate& crate;
StaticTraitResolve m_resolve;
-
+
const ::HIR::Trait* m_current_trait = nullptr;
const ::HIR::ItemPath* m_current_trait_path = nullptr;
-
-
+
+
::HIR::ItemPath* m_fcn_path = nullptr;
::HIR::Function* m_fcn_ptr = nullptr;
unsigned int m_fcn_erased_count = 0;
-
+
::std::vector< ::HIR::TypeRef* > m_self_types;
-
+
typedef ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > t_trait_imports;
t_trait_imports m_traits;
public:
@@ -98,12 +98,12 @@ namespace {
m_resolve(crate)
{
}
-
+
private:
struct ModTraitsGuard {
Visitor* v;
t_trait_imports old_imports;
-
+
~ModTraitsGuard() {
this->v->m_traits = mv$(this->old_imports);
}
@@ -118,7 +118,7 @@ namespace {
}
return rv;
}
-
+
void update_self_type(const Span& sp, ::HIR::TypeRef& ty) const
{
struct H {
@@ -127,7 +127,7 @@ namespace {
self.update_self_type(sp, typ);
}
};
-
+
TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e),
(Generic,
if(e.name == "Self") {
@@ -139,7 +139,7 @@ namespace {
return;
}
),
-
+
(Infer,
),
(Diverge,
@@ -200,17 +200,17 @@ namespace {
void check_parameters(const Span& sp, const ::HIR::GenericParams& param_def, ::HIR::PathParams& param_vals)
{
while( param_vals.m_types.size() < param_def.m_types.size() ) {
- unsigned int i = param_vals.m_types.size();
+ unsigned int i = param_vals.m_types.size();
if( param_def.m_types[i].m_default.m_data.is_Infer() ) {
ERROR(sp, E0000, "Unspecified parameter with no default");
}
-
+
// Replace and expand
param_vals.m_types.push_back( param_def.m_types[i].m_default.clone() );
auto& ty = param_vals.m_types.back();
update_self_type(sp, ty);
}
-
+
if( param_vals.m_types.size() != param_def.m_types.size() ) {
ERROR(sp, E0000, "Incorrect number of parameters - expected " << param_def.m_types.size() << ", got " << param_vals.m_types.size());
}
@@ -225,7 +225,7 @@ namespace {
update_self_type(sp, param_vals.m_types[i]);
}
}
-
+
// TODO: Check generic bounds
for( const auto& bound : param_def.m_bounds )
{
@@ -246,14 +246,14 @@ namespace {
)
}
}
-
+
public:
void visit_type(::HIR::TypeRef& ty) override
{
static Span _sp;
const Span& sp = _sp;
::HIR::Visitor::visit_type(ty);
-
+
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
TU_MATCH( ::HIR::Path::Data, (e.path.m_data), (pe),
(Generic,
@@ -270,7 +270,7 @@ namespace {
)
)
)
-
+
// If an ErasedType is encountered, check if it has an origin set.
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, ErasedType, e,
if( e.m_origin == ::HIR::SimplePath() )
@@ -278,7 +278,7 @@ namespace {
// If not, ensure taht we're checking a function return type, and error if not
if( ! m_fcn_path )
ERROR(sp, E0000, "Use of an erased type outside of a function return - " << ty);
-
+
::HIR::PathParams params;
for(unsigned int i = 0; i < m_fcn_ptr->m_params.m_types.size(); i ++)
params.m_types.push_back(::HIR::TypeRef(m_fcn_ptr->m_params.m_types[i].m_name, 256+i));
@@ -294,20 +294,20 @@ namespace {
}
)
}
-
+
void visit_generic_path(::HIR::GenericPath& p, PathContext pc) override
{
static Span sp;
TRACE_FUNCTION_F("p = " << p);
const auto& params = get_params_for_item(sp, crate, p.m_path, pc);
auto& args = p.m_params;
-
+
check_parameters(sp, params, args);
DEBUG("p = " << p);
-
+
::HIR::Visitor::visit_generic_path(p, pc);
}
-
+
private:
bool locate_trait_item_in_bounds(const Span& sp, ::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::HIR::GenericParams& params, ::HIR::Path::Data& pd) {
//const auto& name = pd.as_UfcsUnknown().item;
@@ -322,7 +322,7 @@ namespace {
}
}
);
- // -
+ // -
}
return false;
}
@@ -333,7 +333,7 @@ namespace {
static bool locate_item_in_trait(::HIR::Visitor::PathContext pc, const ::HIR::Trait& trait, ::HIR::Path::Data& pd)
{
const auto& e = pd.as_UfcsUnknown();
-
+
switch(pc)
{
case ::HIR::Visitor::PathContext::VALUE:
@@ -370,12 +370,12 @@ namespace {
}
bool locate_in_trait_impl_and_set(::HIR::Visitor::PathContext pc, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) {
static Span sp;
-
+
auto& e = pd.as_UfcsUnknown();
//if( this->m_resolve.trait_contains_type(sp, trait_path, trait, e.item, out_path) )
if( this->locate_item_in_trait(pc, trait, pd) ) {
const auto& type = *e.type;
-
+
return this->crate.find_trait_impls(trait_path.m_path, type, [](const auto& x)->const auto&{return x;}, [&](const auto& impl) {
DEBUG("FOUND impl" << impl.m_params.fmt_args() << " " << trait_path.m_path << impl.m_trait_args << " for " << impl.m_type);
// TODO: Check bounds
@@ -390,8 +390,8 @@ namespace {
else {
DEBUG("- Item " << e.item << " not in trait " << trait_path.m_path);
}
-
-
+
+
// Search supertraits (recursively)
for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ )
{
@@ -417,10 +417,10 @@ namespace {
{
TRACE_FUNCTION_FR("UfcsUnknown - p=" << p, p);
auto& e = p.m_data.as_UfcsUnknown();
-
+
this->visit_type( *e.type );
this->visit_path_params( e.params );
-
+
// Search for matching impls in current generic blocks
if( m_resolve.m_item_generics != nullptr && locate_trait_item_in_bounds(sp, pc, *e.type, *m_resolve.m_item_generics, p.m_data) ) {
return ;
@@ -428,7 +428,7 @@ namespace {
if( m_resolve.m_impl_generics != nullptr && locate_trait_item_in_bounds(sp, pc, *e.type, *m_resolve.m_impl_generics, p.m_data) ) {
return ;
}
-
+
TU_IFLET(::HIR::TypeRef::Data, e.type->m_data, Generic, te,
// If processing a trait, and the type is 'Self', search for the type/method on the trait
// - TODO: This could be encoded by a `Self: Trait` bound in the generics, but that may have knock-on issues?
@@ -466,7 +466,7 @@ namespace {
case ::HIR::Visitor::PathContext::TYPE:
continue ;
}
-
+
auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} );
p.m_data = mv$(new_data);
DEBUG("- Resolved, replace with " << p);
@@ -476,7 +476,7 @@ namespace {
for( const auto& trait_info : m_traits )
{
const auto& trait = *trait_info.second;
-
+
switch(pc)
{
case ::HIR::Visitor::PathContext::VALUE:
@@ -490,12 +490,12 @@ namespace {
break;
}
DEBUG("- Trying trait " << *trait_info.first);
-
+
auto trait_path = ::HIR::GenericPath( *trait_info.first );
for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++ ) {
trait_path.m_params.m_types.push_back( ::HIR::TypeRef() );
}
-
+
// TODO: Search supertraits
// TODO: Should impls be searched first, or item names?
// - Item names add complexity, but impls are slower
@@ -504,11 +504,11 @@ namespace {
}
}
}
-
+
// Couldn't find it
ERROR(sp, E0000, "Failed to find impl with '" << e.item << "' for " << *e.type << " (in " << p << ")");
}
-
+
public:
void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override
{
@@ -533,12 +533,12 @@ namespace {
)
)
}
-
+
void visit_params(::HIR::GenericParams& params) override
{
for(auto& tps : params.m_types)
this->visit_type( tps.m_default );
-
+
for(auto& bound : params.m_bounds )
{
TU_MATCH(::HIR::GenericBound, (bound), (e),
@@ -564,24 +564,24 @@ namespace {
)
}
}
-
+
void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
{
auto _ = this->push_mod_traits( mod );
::HIR::Visitor::visit_module(p, mod);
}
-
+
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override
{
m_current_trait = &item;
m_current_trait_path = &p;
-
+
auto _ = m_resolve.set_impl_generics(item.m_params);
::HIR::TypeRef tr { "Self", 0xFFFF };
m_self_types.push_back(&tr);
::HIR::Visitor::visit_trait(p, item);
m_self_types.pop_back();
-
+
m_current_trait = nullptr;
}
void visit_struct(::HIR::ItemPath p, ::HIR::Struct& item) override
@@ -599,16 +599,16 @@ namespace {
auto _ = m_resolve.set_item_generics(item.m_params);
::HIR::Visitor::visit_enum(p, item);
}
-
+
void visit_type_impl(::HIR::TypeImpl& impl) override
{
TRACE_FUNCTION_F("impl " << impl.m_type);
auto _ = m_resolve.set_impl_generics(impl.m_params);
m_self_types.push_back( &impl.m_type );
-
+
::HIR::Visitor::visit_type_impl(impl);
// Check that the type is valid
-
+
m_self_types.pop_back();
}
void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
@@ -616,10 +616,10 @@ namespace {
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type);
auto _ = m_resolve.set_impl_generics(impl.m_params);
m_self_types.push_back( &impl.m_type );
-
+
::HIR::Visitor::visit_trait_impl(trait_path, impl);
// Check that the type+trait is valid
-
+
m_self_types.pop_back();
}
void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl) override
@@ -627,22 +627,22 @@ namespace {
TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type << " { }");
auto _ = m_resolve.set_impl_generics(impl.m_params);
m_self_types.push_back( &impl.m_type );
-
+
::HIR::Visitor::visit_marker_impl(trait_path, impl);
// Check that the type+trait is valid
-
+
m_self_types.pop_back();
}
-
+
void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override {
auto _ = m_resolve.set_item_generics(item.m_params);
-
+
m_fcn_path = &p;
m_fcn_ptr = &item;
m_fcn_erased_count = 0;
visit_type(item.m_return);
m_fcn_path = nullptr;
-
+
::HIR::Visitor::visit_function(p, item);
}
};
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index fdb1a685..eba58331 100644
--- a/src/hir_typeck/static.cpp
+++ b/src/hir_typeck/static.cpp
@@ -11,15 +11,15 @@ void StaticTraitResolve::prep_indexes()
{
static Span sp_AAA;
const Span& sp = sp_AAA;
-
+
TRACE_FUNCTION_F("");
-
+
auto add_equality = [&](::HIR::TypeRef long_ty, ::HIR::TypeRef short_ty){
DEBUG("[prep_indexes] ADD " << long_ty << " => " << short_ty);
// TODO: Sort the two types by "complexity" (most of the time long >= short)
this->m_type_equalities.insert(::std::make_pair( mv$(long_ty), mv$(short_ty) ));
};
-
+
this->iterate_bounds([&](const auto& b) {
TU_MATCH_DEF(::HIR::GenericBound, (b), (be),
(
@@ -30,10 +30,10 @@ void StaticTraitResolve::prep_indexes()
DEBUG("[prep_indexes] Equality (TB) - <" << be.type << " as " << be.trait.m_path << ">::" << tb.first << " = " << tb.second);
auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), be.trait.m_path.clone(), tb.first ) );
ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
-
+
add_equality( mv$(ty_l), tb.second.clone() );
}
-
+
const auto& trait_params = be.trait.m_path.m_params;
auto cb_mono = [&](const auto& ty)->const auto& {
const auto& ge = ty.m_data.as_Generic();
@@ -49,7 +49,7 @@ void StaticTraitResolve::prep_indexes()
BUG(sp, "Unknown generic binding " << ty);
}
};
-
+
const auto& trait = m_crate.get_trait_by_path(sp, be.trait.m_path.m_path);
for(const auto& a_ty : trait.m_types)
{
@@ -63,10 +63,10 @@ void StaticTraitResolve::prep_indexes()
ty_a.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
}
DEBUG("[prep_indexes] Equality (ATB) - <" << ty_a << " as " << a_ty_b.m_path << ">::" << tb.first << " = " << tb.second);
-
+
auto ty_l = ::HIR::TypeRef( ::HIR::Path( ty_a.clone(), trait_mono.m_path.clone(), tb.first ) );
ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
-
+
add_equality( mv$(ty_l), mv$(tb.second) );
}
}
@@ -91,10 +91,10 @@ bool StaticTraitResolve::find_impl(
{
TRACE_FUNCTION_F(trait_path << FMT_CB(os, if(trait_params) { os << *trait_params; } else { os << "<?>"; }) << " for " << type);
auto cb_ident = [](const auto&ty)->const auto&{return ty;};
-
+
static ::HIR::PathParams null_params;
static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc;
-
+
if( !dont_handoff_to_specialised ) {
if( trait_path == m_lang_Copy ) {
if( this->type_is_copy(sp, type) ) {
@@ -112,7 +112,7 @@ bool StaticTraitResolve::find_impl(
// }
//}
}
-
+
// --- MAGIC IMPLS ---
// TODO: There should be quite a few more here, but laziness
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Function, e,
@@ -139,7 +139,7 @@ bool StaticTraitResolve::find_impl(
return found_cb( ImplRef(type.clone(), trait_params->clone(), mv$(assoc)), false );
}
)
-
+
// ----
// TraitObject traits and supertraits
// ----
@@ -162,7 +162,7 @@ bool StaticTraitResolve::find_impl(
}
}
}
-
+
// - Check if the desired trait is a supertrait of this.
// TODO: What if `trait_params` is nullptr?
bool rv = false;
@@ -193,7 +193,7 @@ bool StaticTraitResolve::find_impl(
{
return found_cb( ImplRef(&type, &trait.m_path.m_params, &trait.m_type_bounds), false );
}
-
+
// TODO: What if `trait_params` is nullptr?
bool rv = false;
bool is_supertrait = trait_params && this->find_named_trait_in_trait(sp, trait_path,*trait_params, *trait.m_trait_ptr, trait.m_path.m_path,trait.m_path.m_params, type,
@@ -216,7 +216,7 @@ bool StaticTraitResolve::find_impl(
}
}
)
-
+
// ---
// If this type is an opaque UfcsKnown - check bounds
// ---
@@ -225,12 +225,12 @@ bool StaticTraitResolve::find_impl(
{
ASSERT_BUG(sp, e.path.m_data.is_UfcsKnown(), "Opaque bound type wasn't UfcsKnown - " << type);
const auto& pe = e.path.m_data.as_UfcsKnown();
-
+
// If this associated type has a bound of the desired trait, return it.
const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path);
ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item);
const auto& aty_def = trait_ref.m_types.find(pe.item)->second;
-
+
auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr);
for(const auto& bound : aty_def.m_trait_bounds)
@@ -238,7 +238,7 @@ bool StaticTraitResolve::find_impl(
const auto& b_params = bound.m_path.m_params;
::HIR::PathParams params_mono_o;
const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params);
-
+
if( bound.m_path.m_path == trait_path )
{
if( !trait_params || b_params_mono == *trait_params )
@@ -256,7 +256,7 @@ bool StaticTraitResolve::find_impl(
}
}
}
-
+
bool ret = trait_params && this->find_named_trait_in_trait(sp, trait_path, *trait_params, *bound.m_trait_ptr, bound.m_path.m_path, b_params_mono, type,
[&](const auto& i_params, const auto& i_assoc) {
if( i_params != *trait_params )
@@ -270,9 +270,9 @@ bool StaticTraitResolve::find_impl(
}
)
// --- /UfcsKnown ---
-
+
bool ret;
-
+
// TODO: A bound can imply something via its associated types. How deep can this go?
// E.g. `T: IntoIterator<Item=&u8>` implies `<T as IntoIterator>::IntoIter : Iterator<Item=&u8>`
ret = this->iterate_bounds([&](const auto& b) {
@@ -280,7 +280,7 @@ bool StaticTraitResolve::find_impl(
});
if(ret)
return true;
-
+
if( m_crate.get_trait_by_path(sp, trait_path).m_is_marker )
{
// Positive/negative impls
@@ -303,7 +303,7 @@ bool StaticTraitResolve::find_impl(
});
if(ret)
return rv;
-
+
// Detect recursion and return true if detected
static ::std::vector< ::std::tuple< const ::HIR::SimplePath*, const ::HIR::PathParams*, const ::HIR::TypeRef*> > stack;
for(const auto& ent : stack ) {
@@ -313,7 +313,7 @@ bool StaticTraitResolve::find_impl(
continue ;
if( *::std::get<2>(ent) != type )
continue ;
-
+
return found_cb( ImplRef(&type, trait_params, &null_assoc), false );
}
stack.push_back( ::std::make_tuple( &trait_path, trait_params, &type ) );
@@ -321,7 +321,7 @@ bool StaticTraitResolve::find_impl(
~Guard() { stack.pop_back(); }
};
Guard _;
-
+
auto cmp = this->check_auto_trait_impl_destructure(sp, trait_path, trait_params, type);
if( cmp != ::HIR::Compare::Unequal )
return found_cb( ImplRef(&type, trait_params, &null_assoc), cmp == ::HIR::Compare::Fuzzy );
@@ -335,7 +335,7 @@ bool StaticTraitResolve::find_impl(
});
if(ret)
return true;
-
+
return false;
}
}
@@ -357,15 +357,15 @@ bool StaticTraitResolve::find_impl__check_bound(
}
}
return true;
- }
+ }
};
-
+
// Can only get good information out of TraitBound
if( !bound.is_TraitBound() ) {
return false;
}
const auto& e = bound.as_TraitBound();
-
+
// Obtain a pointer to UfcsKnown for magic later
const ::HIR::Path::Data::Data_UfcsKnown* assoc_info = nullptr;
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Path, e,
@@ -373,7 +373,7 @@ bool StaticTraitResolve::find_impl__check_bound(
assoc_info = &pe;
)
)
-
+
const auto& b_params = e.trait.m_path.m_params;
DEBUG("(bound) - " << e.type << " : " << e.trait);
if( e.type == type )
@@ -409,17 +409,17 @@ bool StaticTraitResolve::find_impl__check_bound(
return true;
}
}
-
+
// If the input type is an associated type controlled by this trait bound, check for added bounds.
// TODO: This just checks a single layer, but it's feasable that there could be multiple layers
if( assoc_info && e.trait.m_path.m_path == assoc_info->trait.m_path && e.type == *assoc_info->type && H::compare_pp(sp, b_params, assoc_info->trait.m_params) ) {
-
+
const auto& trait_ref = *e.trait.m_trait_ptr;
const auto& at = trait_ref.m_types.at(assoc_info->item);
for(const auto& bound : at.m_trait_bounds) {
if( bound.m_path.m_path == trait_path && (!trait_params || H::compare_pp(sp, bound.m_path.m_params, *trait_params)) ) {
DEBUG("- Found an associated type impl");
-
+
auto tp_mono = monomorphise_traitpath_with(sp, bound, [&assoc_info,&sp](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
@@ -443,7 +443,7 @@ bool StaticTraitResolve::find_impl__check_bound(
}
}
}
-
+
return false;
}
@@ -456,10 +456,10 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
{
auto cb_ident = [](const auto&ty)->const auto&{return ty;};
DEBUG("impl" << impl_params_def.fmt_args() << " " << des_trait_path << impl_trait_params << " for " << impl_type << impl_params_def.fmt_bounds());
-
+
::std::vector< const ::HIR::TypeRef*> impl_params;
impl_params.resize( impl_params_def.m_types.size() );
-
+
auto cb = [&impl_params,&sp,cb_ident](auto idx, const auto& ty) {
assert( idx < impl_params.size() );
if( ! impl_params[idx] ) {
@@ -485,7 +485,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
DEBUG(" > Type mismatch");
return false;
}
-
+
::std::vector< ::HIR::TypeRef> placeholders;
for(unsigned int i = 0; i < impl_params.size(); i ++ ) {
if( !impl_params[i] ) {
@@ -525,7 +525,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
}
return *impl_params[ge.binding];
};
-
+
// Bounds
for(const auto& bound : impl_params_def.m_bounds) {
TU_MATCH_DEF(::HIR::GenericBound, (bound), (e),
@@ -548,17 +548,17 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
if( b_ty_mono.m_data.is_Infer() ) {
continue ;
}
-
+
// TODO: This is extrememly inefficient (looks up the trait impl 1+N times)
if( b_tp_mono.m_type_bounds.size() > 0 ) {
//
for(const auto& assoc_bound : b_tp_mono.m_type_bounds) {
const auto& aty_name = assoc_bound.first;
const ::HIR::TypeRef& exp = assoc_bound.second;
-
+
::HIR::GenericPath aty_src_trait;
trait_contains_type(sp, b_tp_mono.m_path, *e.trait.m_trait_ptr, aty_name, aty_src_trait);
-
+
bool rv = false;
if( b_ty_mono.m_data.is_Generic() && (b_ty_mono.m_data.as_Generic().binding >> 8) == 2 ) {
DEBUG("- Placeholder param " << b_ty_mono << ", magic success");
@@ -568,7 +568,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
rv = this->find_impl(sp, aty_src_trait.m_path, aty_src_trait.m_params, b_ty_mono, [&](const auto& impl, bool) {
::HIR::TypeRef have = impl.get_type(aty_name.c_str());
this->expand_associated_types(sp, have);
-
+
//auto cmp = have .match_test_generics_fuzz(sp, exp, cb_ident, cb_match);
auto cmp = exp .match_test_generics_fuzz(sp, have, cb_ident, cb_match);
ASSERT_BUG(sp, cmp == ::HIR::Compare::Equal, "Assoc ty " << aty_name << " mismatch, " << have << " != des " << exp);
@@ -600,7 +600,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw(
)
)
}
-
+
return found_cb( mv$(impl_params), mv$(placeholders), match );
}
@@ -632,7 +632,7 @@ bool StaticTraitResolve::find_impl__check_crate(
DEBUG("[check_auto_trait_impl_destructure] " << inner_ty << " - " << l_res);
return l_res;
};
-
+
// - If the type is a path (struct/enum/...), search for impls for all contained types.
TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Path, e,
::HIR::Compare res = ::HIR::Compare::Equal;
@@ -662,7 +662,7 @@ bool StaticTraitResolve::find_impl__check_crate(
return ty;
}
};
-
+
TU_MATCH( ::HIR::TypeRef::TypePathBinding, (e.binding), (tpb),
(Opaque,
BUG(sp, "Opaque binding on generic path - " << type);
@@ -672,7 +672,7 @@ bool StaticTraitResolve::find_impl__check_crate(
),
(Struct,
const auto& str = *tpb;
-
+
// TODO: Somehow store a ruleset for auto traits on the type
// - Map of trait->does_impl for local fields?
// - Problems occur with type parameters
@@ -694,7 +694,7 @@ bool StaticTraitResolve::find_impl__check_crate(
{
const auto& fld_ty_mono = monomorph_get(fld.second.ent);
DEBUG("Struct::Named '" << fld.first << "' " << fld_ty_mono);
-
+
res &= type_impls_trait(fld_ty_mono);
if( res == ::HIR::Compare::Unequal )
return ::HIR::Compare::Unequal;
@@ -704,7 +704,7 @@ bool StaticTraitResolve::find_impl__check_crate(
),
(Enum,
const auto& enm = *tpb;
-
+
for(const auto& var : enm.m_variants)
{
TU_MATCH(::HIR::Enum::Variant, (var.second), (ve),
@@ -727,7 +727,7 @@ bool StaticTraitResolve::find_impl__check_crate(
{
const auto& fld_ty_mono = monomorph_get(fld.second.ent);
DEBUG("Enum '" << var.first << "'::Struct '" << fld.first << "' " << fld_ty_mono);
-
+
res &= type_impls_trait(fld_ty_mono);
if( res == ::HIR::Compare::Unequal )
return ::HIR::Compare::Unequal;
@@ -856,13 +856,13 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
{
auto& e = input.m_data.as_Path();
auto& e2 = e.path.m_data.as_UfcsKnown();
-
+
this->expand_associated_types_inner(sp, *e2.type);
for(auto& arg : e2.trait.m_params.m_types)
this->expand_associated_types_inner(sp, arg);
-
+
DEBUG("Locating associated type for " << e.path);
-
+
// - If it's a closure, then the only trait impls are those generated by typeck
TU_IFLET(::HIR::TypeRef::Data, e2.type->m_data, Closure, te,
//if( te.node->m_obj_path == ::HIR::GenericPath() )
@@ -885,7 +885,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
// // TODO: Locate impl _without_ binding params too hard?
//}
)
-
+
// If it's a TraitObject, then maybe we're asking for a bound
TU_IFLET(::HIR::TypeRef::Data, e2.type->m_data, TraitObject, te,
const auto& data_trait = te.m_trait.m_path;
@@ -898,13 +898,13 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
// - Why opaque? It's not bounded, don't even bother
TODO(sp, "Handle unconstrained associate type " << e2.item << " from " << *e2.type);
}
-
+
input = it->second.clone();
return ;
}
}
)
-
+
// 1. Bounds
bool rv;
bool assume_opaque = true;
@@ -933,7 +933,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
}
return true;
}
-
+
bool found_supertrait = this->find_named_trait_in_trait(sp,
e2.trait.m_path, e2.trait.m_params,
*be.trait.m_trait_ptr, be.trait.m_path.m_path, be.trait.m_path.m_params, *e2.type,
@@ -962,7 +962,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
}
return true;
}
-
+
// - Didn't match
),
(TypeEquality,
@@ -979,7 +979,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
if( assume_opaque ) {
input.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
DEBUG("Assuming that " << input << " is an opaque name");
-
+
this->replace_equalities(input);
}
this->expand_associated_types_inner(sp, input);
@@ -994,7 +994,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
// - Does simplification of complex associated types
const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path);
const auto& assoc_ty = trait_ptr.m_types.at(pe_inner.item);
-
+
// Resolve where Self=pe_inner.type (i.e. for the trait this inner UFCS is on)
auto cb_placeholders_trait = [&](const auto& ty)->const auto&{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
@@ -1038,7 +1038,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
if( !this->trait_contains_type(sp, e2.trait, this->m_crate.get_trait_by_path(sp, e2.trait.m_path), e2.item, trait_path) )
BUG(sp, "Cannot find associated type " << e2.item << " anywhere in trait " << e2.trait);
//e2.trait = mv$(trait_path);
-
+
::ImplRef best_impl;
rv = this->find_impl(sp, trait_path.m_path, trait_path.m_params, *e2.type, [&](auto impl, bool fuzzy) {
DEBUG("[expand_associated_types] Found " << impl);
@@ -1047,7 +1047,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
// - TODO: Move this logic into `find_impl`
if( fuzzy ) {
DEBUG("[expand_associated_types] - Fuzzy, monomorph+expand and recheck");
-
+
auto impl_ty = impl.get_impl_type();
this->expand_associated_types(sp, impl_ty);
if(impl_ty != *e2.type) {
@@ -1063,7 +1063,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
}
DEBUG("[expand_associated_types] - Fuzzy - Actually matches");
}
-
+
if( impl.type_is_specialisable(e2.item.c_str()) ) {
if( impl.more_specific_than(best_impl) ) {
best_impl = mv$(impl);
@@ -1095,7 +1095,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI
DEBUG("- Couldn't find a non-specialised impl of " << trait_path << " for " << *e2.type << " - treating as opaque");
return ;
}
-
+
ERROR(sp, E0000, "Cannot find an implementation of " << trait_path << " for " << *e2.type);
}
@@ -1139,7 +1139,7 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp,
if( pp.m_types.size() != trait_ptr.m_params.m_types.size() ) {
BUG(sp, "Incorrect number of parameters for trait");
}
-
+
auto monomorph_cb = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
@@ -1151,7 +1151,7 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp,
return pp.m_types[ge.binding];
}
};
-
+
for( const auto& pt : trait_ptr.m_parent_traits )
{
auto pt_mono = monomorphise_traitpath_with(sp, pt, monomorph_cb, false);
@@ -1161,19 +1161,19 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp,
callback( pt_mono.m_path.m_params, mv$(pt_mono.m_type_bounds) );
return true;
}
-
+
const auto& tr = m_crate.get_trait_by_path(sp, pt.m_path.m_path);
if( find_named_trait_in_trait(sp, des, des_params, tr, pt.m_path.m_path, pt_mono.m_path.m_params, target_type, callback) ) {
return true;
}
}
-
+
// Also check bounds for `Self: T` bounds
for(const auto& b : trait_ptr.m_params.m_bounds)
{
if( !b.is_TraitBound() ) continue;
const auto& be = b.as_TraitBound();
-
+
if( be.type == ::HIR::TypeRef("Self", 0xFFFF) )
{
// Something earlier adds a "Self: SelfTrait" bound, prevent that from causing infinite recursion
@@ -1186,14 +1186,14 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp,
callback( pt_mono.m_path.m_params, mv$(pt_mono.m_type_bounds) );
return true;
}
-
+
const auto& tr = m_crate.get_trait_by_path(sp, pt_mono.m_path.m_path);
if( find_named_trait_in_trait(sp, des, des_params, tr, pt_mono.m_path.m_path, pt_mono.m_path.m_params, target_type, callback) ) {
return true;
}
}
}
-
+
return false;
}
bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const
@@ -1203,7 +1203,7 @@ bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::Generi
out_path = trait_path.clone();
return true;
}
-
+
auto monomorph = [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
assert(ge.binding < 256);
@@ -1375,12 +1375,12 @@ const ::HIR::TypeRef* StaticTraitResolve::is_type_owned_box(const ::HIR::TypeRef
return nullptr;
}
const auto& te = ty.m_data.as_Path();
-
+
if( ! te.path.m_data.is_Generic() ) {
return nullptr;
}
const auto& pe = te.path.m_data.as_Generic();
-
+
if( pe.m_path != m_lang_Box ) {
return nullptr;
}
@@ -1393,12 +1393,12 @@ const ::HIR::TypeRef* StaticTraitResolve::is_type_phantom_data(const ::HIR::Type
return nullptr;
}
const auto& te = ty.m_data.as_Path();
-
+
if( ! te.path.m_data.is_Generic() ) {
return nullptr;
}
const auto& pe = te.path.m_data.as_Generic();
-
+
if( pe.m_path != m_lang_PhantomData ) {
return nullptr;
}
diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp
index a823536e..66a65be5 100644
--- a/src/hir_typeck/static.hpp
+++ b/src/hir_typeck/static.hpp
@@ -15,11 +15,11 @@ class StaticTraitResolve
{
public:
const ::HIR::Crate& m_crate;
-
+
::HIR::GenericParams* m_impl_generics;
::HIR::GenericParams* m_item_generics;
-
-
+
+
::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities;
::HIR::SimplePath m_lang_Copy;
@@ -31,7 +31,7 @@ public:
::HIR::SimplePath m_lang_FnOnce;
::HIR::SimplePath m_lang_Box;
::HIR::SimplePath m_lang_PhantomData;
-
+
public:
StaticTraitResolve(const ::HIR::Crate& crate):
m_crate(crate),
@@ -52,7 +52,7 @@ public:
private:
void prep_indexes();
-
+
public:
bool has_self() const {
return m_impl_generics ? true : false;
@@ -65,7 +65,7 @@ public:
static ::HIR::GenericParams empty;
return m_item_generics ? *m_item_generics : empty;
}
-
+
/// \brief State manipulation
/// \{
template<typename T>
@@ -94,11 +94,11 @@ public:
return NullOnDrop< ::HIR::GenericParams>(m_item_generics);
}
/// \}
-
+
/// \brief Lookups
/// \{
typedef ::std::function<bool(ImplRef, bool is_fuzzed)> t_cb_find_impl;
-
+
bool find_impl(
const Span& sp,
const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& trait_params,
@@ -115,7 +115,7 @@ public:
t_cb_find_impl found_cb,
bool dont_handoff_to_specialised = false
) const;
-
+
private:
bool find_impl__check_bound(
const Span& sp,
@@ -154,7 +154,7 @@ private:
public:
/// \}
-
+
/// Iterate over in-scope bounds (function then top)
bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const;
@@ -165,16 +165,16 @@ public:
const ::HIR::TypeRef& self_type,
::std::function<void(const ::HIR::PathParams&, ::std::map< ::std::string, ::HIR::TypeRef>)> callback
) const;
- ///
+ ///
bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
-
-
+
+
// --------------
// Common bounds
// -------------
bool type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const;
bool type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const;
-
+
const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const;
const ::HIR::TypeRef* is_type_phantom_data(const ::HIR::TypeRef& ty) const;
};
diff --git a/src/ident.cpp b/src/ident.cpp
index 45c96f2e..da029e21 100644
--- a/src/ident.cpp
+++ b/src/ident.cpp
@@ -20,7 +20,7 @@ bool Ident::Hygiene::is_visible(const Hygiene& src) const
if( this->contexts.size() == 0 ) {
return src.contexts.size() == 0;
}
-
+
auto des = this->contexts.back();
for(const auto& c : src.contexts)
if( des == c )
diff --git a/src/include/debug.hpp b/src/include/debug.hpp
index cb258bf5..ce2f89da 100644
--- a/src/include/debug.hpp
+++ b/src/include/debug.hpp
@@ -30,7 +30,7 @@ struct RepeatLitStr
{
const char *s;
int n;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const RepeatLitStr& r) {
for(int i = 0; i < r.n; i ++ )
os << r.s;
diff --git a/src/include/ident.hpp b/src/include/ident.hpp
index 1122a68b..d702385c 100644
--- a/src/include/ident.hpp
+++ b/src/include/ident.hpp
@@ -14,9 +14,9 @@ struct Ident
class Hygiene
{
static unsigned g_next_scope;
-
+
::std::vector<unsigned int> contexts;
-
+
Hygiene(unsigned int index):
contexts({index})
{}
@@ -24,7 +24,7 @@ struct Ident
Hygiene():
contexts({})
{}
-
+
static Hygiene new_scope()
{
return Hygiene(++g_next_scope);
@@ -37,23 +37,23 @@ struct Ident
rv.contexts.push_back( ++g_next_scope );
return rv;
}
-
+
Hygiene(Hygiene&& x) = default;
Hygiene(const Hygiene& x) = default;
Hygiene& operator=(Hygiene&& x) = default;
Hygiene& operator=(const Hygiene& x) = default;
-
+
// Returns true if an ident with hygine `souce` can see an ident with this hygine
bool is_visible(const Hygiene& source) const;
//bool operator==(const Hygiene& x) const { return scope_index == x.scope_index; }
//bool operator!=(const Hygiene& x) const { return scope_index != x.scope_index; }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Hygiene& v);
};
-
+
Hygiene hygiene;
::std::string name;
-
+
Ident(const char* name):
hygiene(),
name(name)
@@ -65,20 +65,20 @@ struct Ident
Ident(Hygiene hygiene, ::std::string name):
hygiene(::std::move(hygiene)), name(::std::move(name))
{ }
-
+
Ident(Ident&& x) = default;
Ident(const Ident& x) = default;
Ident& operator=(Ident&& x) = default;
Ident& operator=(const Ident& x) = default;
-
+
::std::string into_string() {
return ::std::move(name);
}
-
+
bool operator==(const char* s) const {
return this->name == s;
}
-
+
bool operator==(const Ident& x) const {
if( this->name != x.name )
return false;
@@ -90,6 +90,6 @@ struct Ident
return !(*this == x);
}
bool operator<(const Ident& x) const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Ident& x);
};
diff --git a/src/include/rc_string.hpp b/src/include/rc_string.hpp
index 630f8e89..fd230062 100644
--- a/src/include/rc_string.hpp
+++ b/src/include/rc_string.hpp
@@ -23,7 +23,7 @@ public:
RcString(s.data(), s.size())
{
}
-
+
RcString(const RcString& x):
m_ptr(x.m_ptr),
m_len(x.m_len)
@@ -37,9 +37,9 @@ public:
x.m_ptr = nullptr;
x.m_len = 0;
}
-
+
~RcString();
-
+
RcString& operator=(const RcString& x)
{
if( &x != this )
@@ -63,8 +63,8 @@ public:
}
return *this;
}
-
-
+
+
const char* c_str() const {
if( m_len > 0 )
{
diff --git a/src/include/rustic.hpp b/src/include/rustic.hpp
index 5d768152..93992f61 100644
--- a/src/include/rustic.hpp
+++ b/src/include/rustic.hpp
@@ -24,11 +24,11 @@ public:
m_first(ptr),
m_len(len)
{}
-
+
::std::vector<T> to_vec() const {
return ::std::vector<T>(begin(), end());
}
-
+
unsigned int size() const {
return m_len;
}
@@ -42,7 +42,7 @@ public:
assert(ofs + len <= m_len);
return slice { m_first + ofs, len };
}
-
+
T* begin() const { return m_first; }
T* end() const { return m_first + m_len; }
@@ -73,7 +73,7 @@ class option
{
char m_data[ sizeof(T) ];
bool m_set;
-
+
void* data_ptr() { return m_data; }
const void* data_ptr() const { return m_data; }
public:
@@ -90,15 +90,15 @@ public:
reinterpret_cast<T*>(data_ptr())->~T();
}
}
-
+
bool is_none() const { return !m_set; }
bool is_some() const { return m_set; }
-
+
const T& unwrap() const {
assert(is_some());
return *reinterpret_cast<const T*>(m_data);
}
-
+
void if_set(::std::function<void (const T&)> f) const {
if( m_set ) {
return f(m_data);
@@ -125,7 +125,7 @@ public:
option():
m_ptr(nullptr)
{}
-
+
bool is_none() const { return m_ptr == nullptr; }
bool is_some() const { return m_ptr != nullptr; }
T& unwrap() const {
diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp
index db311bb1..6a9abf95 100644
--- a/src/include/serialise.hpp
+++ b/src/include/serialise.hpp
@@ -19,7 +19,7 @@ class Deserialiser;
#define SERIALISE_TYPE(method_prefix, tag_str, body, des_body) \
const char* method_prefix serialise_tag() const { return tag_str; } \
void method_prefix serialise(::Serialiser& s) const { body } \
- void method_prefix deserialise(::Deserialiser& s) { des_body }
+ void method_prefix deserialise(::Deserialiser& s) { des_body }
#define SERIALISE_TYPE_A(method_prefix, tag_str, body) SERIALISE_TYPE(method_prefix, tag_str, body, body)
#define SERIALISE_TYPE_S(class_, body) SERIALISE_TYPE(class_::, #class_, body, body)
#define SERIALISE_TU(class_, tag_str, val_name, ...) SERIALISE_TYPE(class_::, tag_str,\
@@ -74,7 +74,7 @@ protected:
public:
template<typename T>
inline void item(T& v) { *this << v; }
-
+
virtual Serialiser& operator<<(bool val) = 0;
virtual Serialiser& operator<<(uint64_t val) = 0;
virtual Serialiser& operator<<(int64_t val) = 0;
@@ -149,7 +149,7 @@ public:
virtual void start_object(const char *tag) = 0;
virtual void end_object(const char *tag) = 0;
::std::string start_object();
-
+
void item(Serialisable& v);
Deserialiser& operator>>(Serialisable& v) {
this->item(v);
@@ -171,9 +171,9 @@ public:
void item(::std::shared_ptr<T>& v)
{
bool present;
-
+
item(present);
-
+
if(present) {
v.reset(new T);
item(*v);
@@ -186,9 +186,9 @@ public:
void item(::std::unique_ptr<T>& v)
{
bool present;
-
+
item(present);
-
+
if(present) {
v.reset( T::from_deserialiser(*this).release() );
}
diff --git a/src/include/serialiser_texttree.hpp b/src/include/serialiser_texttree.hpp
index bdad7d7a..7c86d326 100644
--- a/src/include/serialiser_texttree.hpp
+++ b/src/include/serialiser_texttree.hpp
@@ -16,13 +16,13 @@ class Serialiser_TextTree:
bool m_array_was_empty;
public:
Serialiser_TextTree(::std::ostream& os);
-
+
virtual Serialiser& operator<<(bool val) override;
virtual Serialiser& operator<<(uint64_t val) override;
virtual Serialiser& operator<<(int64_t val) override;
virtual Serialiser& operator<<(double val) override;
virtual Serialiser& operator<<(const char* s) override;
-
+
protected:
virtual void start_object(const char *tag) override;
virtual void end_object(const char* tag) override;
@@ -39,15 +39,15 @@ class Deserialiser_TextTree:
public Deserialiser
{
::std::istream& m_is;
-
+
static bool is_ws(char c);
char getc();
char peekc();
void eat_ws();
public:
Deserialiser_TextTree(::std::istream& is);
-
-protected:
+
+protected:
virtual size_t start_array() override;
virtual void end_array() override;
virtual ::std::string read_tag() override;
diff --git a/src/include/span.hpp b/src/include/span.hpp
index eafebb0a..11ffc005 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -24,19 +24,19 @@ class Position;
struct ProtoSpan
{
RcString filename;
-
+
unsigned int start_line;
unsigned int start_ofs;
};
struct Span
{
RcString filename;
-
+
unsigned int start_line;
unsigned int start_ofs;
unsigned int end_line;
unsigned int end_ofs;
-
+
Span(RcString filename, unsigned int start_line, unsigned int start_ofs, unsigned int end_line, unsigned int end_ofs):
filename( ::std::move(filename) ),
start_line(start_line),
@@ -47,12 +47,12 @@ struct Span
Span(const Span& x);
Span(const Position& position);
Span();
-
+
void bug(::std::function<void(::std::ostream&)> msg) const;
void error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const;
void warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const;
void note(::std::function<void(::std::ostream&)> msg) const;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Span& sp);
};
diff --git a/src/include/synext_decorator.hpp b/src/include/synext_decorator.hpp
index 0404889f..c3985855 100644
--- a/src/include/synext_decorator.hpp
+++ b/src/include/synext_decorator.hpp
@@ -18,14 +18,14 @@ namespace AST {
struct StructItem;
struct TupleItem;
struct EnumVariant;
-
+
class Module;
class Item;
-
+
class Expr;
class ExprNode;
struct ExprNode_Match_Arm;
-
+
class ImplDef;
}
@@ -40,7 +40,7 @@ class ExpandDecorator
void unexpected(const Span& sp, const AST::MetaItem& mi, const char* loc_str) const;
public:
virtual AttrStage stage() const = 0;
-
+
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate) const { unexpected(sp, mi, "crate"); }
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const { unexpected(sp, mi, "item"); }
// NOTE: To delete, set the type to `_`
@@ -51,7 +51,7 @@ public:
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, ::AST::TupleItem& si) const { unexpected(sp, mi, "tuple item"); }
// NOTE: To delete, clear the name
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, ::AST::EnumVariant& ev) const { unexpected(sp, mi, "enum variant"); }
-
+
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, ::std::unique_ptr<AST::ExprNode>& expr) const { unexpected(sp, mi, "expression"); }
// NOTE: To delete, clear the patterns vector
virtual void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, ::AST::ExprNode_Match_Arm& expr) const { unexpected(sp, mi, "match arm"); }
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 0627b525..bb9c537e 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -19,7 +19,7 @@
#define TU_FIRST(a, ...) a
// Argument iteration
-#define _DISP0(n)
+#define _DISP0(n)
#define _DISP1(n, _1) n _1
#define _DISP2(n, _1, _2) n _1 n _2
#define _DISP3(n, v, v2, v3) n v n v2 n v3
@@ -37,7 +37,7 @@
#define _DISP15(n, a1,a2,a3,a4,a5, b1,b2,b3,b4,b5, c1,c2,c3,c4,c5) _DISP5(n, a1,a2,a3,a4,a5) _DISP5(n, b1,b2,b3,b4,b5) _DISP5(n, c1,c2,c3,c4,c5)
#define _DISP16(n, a1,a2,a3,a4,a5, b1,b2,b3,b4,b5, c1,c2,c3,c4,c5, d1) _DISP5(n, a1,a2,a3,a4,a5) _DISP5(n, b1,b2,b3,b4,b5) _DISP5(n, c1,c2,c3,c4,c5) _DISP1(n, d1)
-#define _DISPO0(n)
+#define _DISPO0(n)
#define _DISPO1(n, _1) n(_1)
#define _DISPO2(n, _1, _2) n(_1) n(_2)
#define _DISPO3(n, v, v2, v3) n(v) n(v2) n(v3)
diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp
index 166dd2cc..11ec74f2 100644
--- a/src/macro_rules/eval.cpp
+++ b/src/macro_rules/eval.cpp
@@ -24,25 +24,25 @@ class ParameterMappings
unsigned int num_used; // Number of times it has been used
InterpolatedFragment frag;
};
-
+
/// A single layer of the capture set
TAGGED_UNION(CaptureLayer, Vals,
(Vals, ::std::vector<CapturedVal>),
(Nested, ::std::vector<CaptureLayer>)
);
-
+
/// Represents the fragments captured for a name
struct CapturedVar
{
CaptureLayer top_layer;
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const CapturedVar& x) {
os << "CapturedVar { top_layer: " << x.top_layer << " }";
return os;
}
-
+
};
-
+
::std::vector<CapturedVar> m_mappings;
unsigned m_layer_count;
public:
@@ -51,28 +51,28 @@ public:
{
}
ParameterMappings(ParameterMappings&&) = default;
-
+
const ::std::vector<CapturedVar>& mappings() const { return m_mappings; }
-
+
void dump() const {
DEBUG("m_mappings = {" << m_mappings << "}");
}
-
+
size_t layer_count() const {
return m_layer_count+1;
}
-
+
void insert(unsigned int name_index, const ::std::vector<unsigned int>& iterations, InterpolatedFragment data);
-
+
InterpolatedFragment* get(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
unsigned int count_in(const ::std::vector<unsigned int>& iterations, unsigned int name_idx) const;
-
+
/// Increment the number of times a particular fragment will be used
void inc_count(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
/// Decrement the number of times a particular fragment is used (returns true if there are still usages remaining)
bool dec_count(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
-
-
+
+
friend ::std::ostream& operator<<(::std::ostream& os, const CapturedVal& x) {
os << x.frag;
return os;
@@ -88,7 +88,7 @@ public:
)
return os;
}
-
+
private:
CapturedVal& get_cap(const ::std::vector<unsigned int>& iterations, unsigned int name_idx);
};
@@ -122,10 +122,10 @@ class MacroPatternStream
::std::vector<unsigned int> m_pos;
// Iteration index of each active loop level
::std::vector<unsigned int> m_loop_iterations;
-
+
::std::vector<SimplePatEnt> m_stack;
unsigned int m_skip_count;
-
+
SimplePatEnt m_peek_cache;
bool m_peek_cache_valid = false;
@@ -137,10 +137,10 @@ public:
m_pos({0})
{
}
-
+
/// Get the next pattern entry
SimplePatEnt next();
-
+
const SimplePatEnt& peek() {
if( !m_peek_cache_valid ) {
m_peek_cache = next();
@@ -148,23 +148,23 @@ public:
}
return m_peek_cache;
}
-
+
/// Inform the stream that the `if` rule that was just returned succeeded
void if_succeeded();
/// Get the current loop iteration count
const ::std::vector<unsigned int>& get_loop_iters() const {
return m_loop_iterations;
}
-
+
private:
SimplePatEnt emit_loop_start(const MacroPatEnt& pat);
-
+
SimplePatEnt emit_seq(SimplePatEnt v1, SimplePatEnt v2) {
assert( m_stack.empty() );
m_stack.push_back( mv$(v2) );
return v1;
}
-
+
void break_loop();
};
@@ -188,7 +188,7 @@ void ParameterMappings::insert(unsigned int name_index, const ::std::vector<unsi
for(unsigned int i = 0; i < iterations.size()-1; i ++ )
{
auto iter = iterations[i];
-
+
if( layer->is_Vals() ) {
assert( layer->as_Vals().size() == 0 );
*layer = CaptureLayer::make_Nested({});
@@ -198,7 +198,7 @@ void ParameterMappings::insert(unsigned int name_index, const ::std::vector<unsi
DEBUG("- Skipped iteration " << e.size());
e.push_back( CaptureLayer::make_Nested({}) );
}
-
+
if(e.size() == iter) {
e.push_back( CaptureLayer::make_Vals({}) );
}
@@ -223,7 +223,7 @@ ParameterMappings::CapturedVal& ParameterMappings::get_cap(const ::std::vector<u
auto& e = m_mappings.at(name_idx);
//DEBUG("- e = " << e);
auto* layer = &e.top_layer;
-
+
// - If the top layer is a 1-sized set of values, unconditionally return it
TU_IFLET(CaptureLayer, (*layer), Vals, e,
if( e.size() == 1 ) {
@@ -233,7 +233,7 @@ ParameterMappings::CapturedVal& ParameterMappings::get_cap(const ::std::vector<u
BUG(Span(), "Attempting to get binding for empty capture - #" << name_idx);
}
)
-
+
for(const auto iter : iterations)
{
TU_MATCH(CaptureLayer, (*layer), (e),
@@ -316,28 +316,28 @@ SimplePatEnt MacroPatternStream::next()
{
TRACE_FUNCTION_F("m_pos=[" << m_pos << "], m_stack.size()=" << m_stack.size());
assert(m_pos.size() >= 1);
-
+
if( m_peek_cache_valid ) {
m_peek_cache_valid = false;
return mv$(m_peek_cache);
}
-
+
// Pop off the generation stack
if( ! m_stack.empty() ) {
auto rv = mv$(m_stack.back());
m_stack.pop_back();
return rv;
}
-
+
if( m_break_if_not && ! m_condition_fired ) {
// Break out of the current loop then continue downwards.
break_loop();
}
-
+
m_skip_count = 0;
m_break_if_not = false;
m_condition_fired = false;
-
+
const MacroPatEnt* parent_pat = nullptr;
decltype(m_pattern) parent_ents = nullptr;
const auto* ents = m_pattern;
@@ -351,18 +351,18 @@ SimplePatEnt MacroPatternStream::next()
parent_ents = ents;
ents = &parent_pat->subpats;
}
-
+
DEBUG( (m_pos.size()-1) << " " << m_pos.back() << " / " << ents->size());
if( m_pos.back() < ents->size() )
{
const auto& pat = ents->at( m_pos.back() );
-
+
if( pat.type == MacroPatEnt::PAT_LOOP ) {
DEBUG("Enter " << pat);
// Increase level, return entry control
m_pos.push_back( 0 );
m_loop_iterations.push_back( 0 );
-
+
if( pat.name == "*" )
{
return emit_loop_start(pat);
@@ -391,7 +391,7 @@ SimplePatEnt MacroPatternStream::next()
// - Reset the loop back to the start
m_pos.back() = 0;
m_loop_iterations.back() += 1;
-
+
// - Emit break conditions
if( parent_pat->tok == TOK_NULL ) {
// Loop separator is TOK_NULL - get the first token of the loop and use it.
@@ -437,17 +437,17 @@ namespace {
void get_loop_entry_pats(const MacroPatEnt& pat, ::std::vector<const MacroPatEnt*>& entry_pats)
{
assert( pat.type == MacroPatEnt::PAT_LOOP );
-
+
// If this pattern is a loop, get the entry concrete patterns for it
- // - Otherwise, just
+ // - Otherwise, just
unsigned int i = 0;
while( i < pat.subpats.size() && pat.subpats[i].type == MacroPatEnt::PAT_LOOP )
{
const auto& cur_pat = pat.subpats[i];
bool is_optional = (cur_pat.name == "*");
-
+
get_loop_entry_pats(cur_pat, entry_pats);
-
+
if( !is_optional )
{
// Non-optional loop, MUST be entered, so return after recursing
@@ -456,7 +456,7 @@ namespace {
// Optional, so continue the loop.
i ++;
}
-
+
// First non-loop pattern
if( i < pat.subpats.size() )
{
@@ -471,10 +471,10 @@ SimplePatEnt MacroPatternStream::emit_loop_start(const MacroPatEnt& pat)
{
// Find the next non-loop pattern to control if this loop should be entered
::std::vector<const MacroPatEnt*> m_entry_pats;
-
+
get_loop_entry_pats(pat, m_entry_pats);
DEBUG("m_entry_pats = [" << FMT_CB(ss, for(const auto* p : m_entry_pats) { ss << *p << ","; }) << "]");
-
+
struct H {
static SimplePatEnt get_if(bool flag, const MacroPatEnt& mpe) {
if( mpe.type == MacroPatEnt::PAT_TOKEN )
@@ -483,7 +483,7 @@ SimplePatEnt MacroPatternStream::emit_loop_start(const MacroPatEnt& pat)
return SimplePatEnt::make_IfPat({ flag, mpe.type });
}
};
-
+
const auto* entry_pat = m_entry_pats.back();
m_entry_pats.pop_back();
if( m_entry_pats.size() > 0 )
@@ -521,13 +521,13 @@ void MacroPatternStream::break_loop()
assert( m_pos.size() >= 1 );
// - This should never be called when on the top level
assert( m_pos.size() != 1 );
-
+
// HACK: Clear the stack if an if succeeded
m_stack.clear();
-
+
m_pos.pop_back();
m_pos.back() += 1 + m_skip_count;
-
+
m_loop_iterations.pop_back();
}
@@ -546,10 +546,10 @@ class MacroExpandState
/// Layer states : Index and Iteration
::std::vector< t_offset > m_offsets;
::std::vector< unsigned int> m_iterations;
-
+
/// Cached pointer to the current layer
const ::std::vector<MacroExpansionEnt>* m_cur_ents; // For faster lookup.
-
+
public:
MacroExpandState(const ::std::vector<MacroExpansionEnt>& contents, const ParameterMappings& mappings):
m_root_contents(contents),
@@ -558,11 +558,11 @@ public:
m_cur_ents(&m_root_contents)
{
}
-
+
// Returns a pointer to the next entry to expand, or nullptr if the end is reached
// - NOTE: When a Loop entry is returned, the separator token should be emitted
const MacroExpansionEnt* next_ent();
-
+
const ::std::vector<unsigned int> iterations() const { return m_iterations; }
unsigned int top_pos() const { return m_offsets[0].read_pos; }
@@ -577,17 +577,17 @@ class MacroExpander:
const RcString m_macro_filename;
const ::std::string m_crate_name;
-
+
ParameterMappings m_mappings;
MacroExpandState m_state;
-
+
Token m_next_token; // used for inserting a single token into the stream
::std::unique_ptr<TTStreamO> m_ttstream;
Ident::Hygiene m_hygiene;
-
+
public:
MacroExpander(const MacroExpander& x) = delete;
-
+
MacroExpander(const ::std::string& macro_name, const Ident::Hygiene& parent_hygiene, const ::std::vector<MacroExpansionEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
m_macro_filename( FMT("Macro:" << macro_name) ),
m_crate_name( mv$(crate_name) ),
@@ -683,7 +683,7 @@ InterpolatedFragment Macro_HandlePatternCap(TokenStream& lex, MacroPatEnt::Type
BUG(lex.getPosition(), "Encountered PAT_TOKEN when handling capture");
case MacroPatEnt::PAT_LOOP:
BUG(lex.getPosition(), "Encountered PAT_LOOP when handling capture");
-
+
case MacroPatEnt::PAT_TT:
if( GET_TOK(tok, lex) == TOK_EOF )
throw ParseError::Unexpected(lex, TOK_EOF);
@@ -725,24 +725,24 @@ InterpolatedFragment Macro_HandlePatternCap(TokenStream& lex, MacroPatEnt::Type
::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input, AST::Module& mod)
{
TRACE_FUNCTION_F("'" << name << "', " << input);
-
+
ParameterMappings bound_tts;
unsigned int rule_index = Macro_InvokeRules_MatchPattern(rules, mv$(input), mod, bound_tts);
-
+
const auto& rule = rules.m_rules.at(rule_index);
-
+
DEBUG( rule.m_contents.size() << " rule contents with " << bound_tts.mappings().size() << " bound values - " << name );
for( unsigned int i = 0; i < ::std::min( bound_tts.mappings().size(), rule.m_param_names.size() ); i ++ )
{
DEBUG("- #" << i << " " << rule.m_param_names.at(i) << " = [" << bound_tts.mappings()[i] << "]");
}
//bound_tts.dump();
-
+
// Run through the expansion counting the number of times each fragment is used
Macro_InvokeRules_CountSubstUses(bound_tts, rule.m_contents);
-
+
TokenStream* ret_ptr = new MacroExpander(name, rules.m_hygiene, rule.m_contents, mv$(bound_tts), rules.m_source_crate);
-
+
return ::std::unique_ptr<TokenStream>( ret_ptr );
}
@@ -750,7 +750,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
TRACE_FUNCTION;
Span sp;// = input.span();
-
+
struct Capture {
unsigned int binding_idx;
::std::vector<unsigned int> iterations;
@@ -768,10 +768,10 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
active_arms.push_back( ActiveArm { i, {}, MacroPatternStream(rules.m_rules[i].m_pattern) } );
}
-
+
// - List of captured values
::std::vector<InterpolatedFragment> captures;
-
+
TTStreamO lex( mv$(input) );
SET_MODULE(lex, mod);
while(true)
@@ -783,7 +783,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
{
auto idx = arm.index;
SimplePatEnt pat;
- // Consume all If* rules
+ // Consume all If* rules
do
{
pat = arm.stream.next();
@@ -809,7 +809,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
break;
}
} while( pat.is_IfPat() || pat.is_IfTok() );
-
+
TU_MATCH( SimplePatEnt, (pat), (e),
(IfPat, BUG(sp, "IfTok unexpected here");),
(IfTok, BUG(sp, "IfTok unexpected here");),
@@ -826,14 +826,14 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
arm_pats.push_back( mv$(pat) );
}
assert( arm_pats.size() == active_arms.size() );
-
+
// 2. Prune imposible arms
for(unsigned int i = 0, j = 0; i < arm_pats.size(); )
{
auto idx = active_arms[i].index;
const auto& pat = arm_pats[i];
bool fail = false;
-
+
TU_MATCH( SimplePatEnt, (pat), (e),
(IfPat, BUG(sp, "IfTok unexpected here");),
(IfTok, BUG(sp, "IfTok unexpected here");),
@@ -862,12 +862,12 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
j ++;
}
-
+
if( arm_pats.size() == 0 ) {
auto tok = lex.getToken();
ERROR(tok.get_pos(), E0000, "No rules expected " << tok);
}
-
+
// 3. If there is a token pattern in the list, take that arm (and any other token arms)
const SimplePatEnt* tok_pat = nullptr;
unsigned int ident_pat_idx = arm_pats.size();
@@ -893,7 +893,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
)
}
-
+
if( tok_pat )
{
auto tok = lex.getToken();
@@ -936,7 +936,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
(End, TODO(sp, "Handle End following a conflicting :ident"); )
)
}
-
+
if( discard ) {
arm_pats.erase( arm_pats.begin() + i );
active_arms.erase( active_arms.begin() + i );
@@ -945,7 +945,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
++ i;
}
}
-
+
// If there are any remaining ident rules, erase the non-ident rules.
if( ident_rule_kept ) {
// If no rules were discarded, remove the non-ident rules
@@ -963,7 +963,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
assert(arm_pats.size() > 0);
assert(arm_pats.size() == active_arms.size());
}
-
+
// 3. Check that all remaining arms are the same pattern.
const auto& active_pat = arm_pats[0];
for(unsigned int i = 1; i < arm_pats.size(); i ++)
@@ -990,7 +990,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
)
)
}
-
+
// 4. Apply patterns.
TU_MATCH( SimplePatEnt, (arm_pats[0]), (e),
(End,
@@ -1025,9 +1025,9 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
}
}
};
-
+
auto cap = Macro_HandlePatternCap(lex, e.type);
-
+
unsigned int cap_idx = captures.size();
captures.push_back( mv$(cap) );
for(unsigned int i = 0; i < active_arms.size(); i ++)
@@ -1039,7 +1039,7 @@ unsigned int Macro_InvokeRules_MatchPattern(const MacroRules& rules, TokenTree i
)
)
}
-
+
// Keep looping - breakout is handled in 'End' above
}
}
@@ -1048,7 +1048,7 @@ void Macro_InvokeRules_CountSubstUses(ParameterMappings& bound_tts, const ::std:
{
TRACE_FUNCTION;
MacroExpandState state(contents, bound_tts);
-
+
while(const auto* ent_ptr = state.next_ent())
{
DEBUG(*ent_ptr);
@@ -1096,7 +1096,7 @@ Token MacroExpander::realGetToken()
return rv;
m_ttstream.reset();
}
-
+
// Loop to handle case where $crate expands to nothing
while( const auto* next_ent_ptr = m_state.next_ent() )
{
@@ -1125,7 +1125,7 @@ Token MacroExpander::realGetToken()
else {
auto* frag = m_mappings.get(m_state.iterations(), e);
ASSERT_BUG(this->getPosition(), frag, "Cannot find '" << e << "' for " << m_state.iterations());
-
+
bool can_steal = ( m_mappings.dec_count(m_state.iterations(), e) == false );
DEBUG("Insert replacement #" << e << " = " << *frag);
if( frag->m_type == InterpolatedFragment::TT )
@@ -1162,7 +1162,7 @@ Token MacroExpander::realGetToken()
throw "";
}
}
-
+
DEBUG("EOF");
return Token(TOK_EOF);
}
@@ -1176,10 +1176,10 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
{
unsigned int layer = m_offsets.size() - 1;
const auto& ents = *m_cur_ents;
-
+
// Obtain current read position in layer, and increment
size_t idx = m_offsets.back().read_pos++;
-
+
// Check if limit has been reached
if( idx < ents.size() )
{
@@ -1230,11 +1230,11 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
if( cur_ofs.loop_index + 1 < cur_ofs.max_index )
{
m_iterations.back() ++;
-
+
DEBUG("Restart layer");
cur_ofs.read_pos = 0;
cur_ofs.loop_index ++;
-
+
auto& loop_layer = getCurLayerEnt();
if( loop_layer.as_Loop().joiner.type() != TOK_NULL ) {
DEBUG("- Separator token = " << loop_layer.as_Loop().joiner);
@@ -1261,14 +1261,14 @@ const MacroExpansionEnt* MacroExpandState::next_ent()
assert( m_offsets.size() == 0 );
}
} // while( m_offsets NONEMPTY )
-
+
return nullptr;
}
const MacroExpansionEnt& MacroExpandState::getCurLayerEnt() const
{
assert( m_offsets.size() > 1 );
-
+
const auto* ents = &m_root_contents;
for( unsigned int i = 0; i < m_offsets.size()-2; i ++ )
{
@@ -1277,7 +1277,7 @@ const MacroExpansionEnt& MacroExpandState::getCurLayerEnt() const
ents = &(*ents)[ofs-1].as_Loop().entries;
}
return (*ents)[m_offsets[m_offsets.size()-2].read_pos-1];
-
+
}
const ::std::vector<MacroExpansionEnt>* MacroExpandState::getCurLayer() const
{
diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp
index 337a4707..aed0e8ce 100644
--- a/src/macro_rules/macro_rules.hpp
+++ b/src/macro_rules/macro_rules.hpp
@@ -1,162 +1,162 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * macro_rules/macro_rules.hpp
- * - Macros by example - `macro_rules!`
- */
-#ifndef MACROS_HPP_INCLUDED
-#define MACROS_HPP_INCLUDED
-
-#include "parse/lex.hpp"
-#include "parse/tokentree.hpp"
-#include <common.hpp>
-#include <map>
-#include <memory>
-#include <cstring>
-#include "macro_rules_ptr.hpp"
-#include <set>
-
-class MacroExpander;
-
-TAGGED_UNION_EX(MacroExpansionEnt, (: public Serialisable), Token, (
- // TODO: have a "raw" stream instead of just tokens
- (Token, Token),
- // TODO: Have a flag on `NamedValue` that indicates that it is the only/last usage of this particular value (at this level)
- // NOTE: This is a 2:30 bitfield - with the high range indicating $crate
- (NamedValue, unsigned int),
- (Loop, struct {
- /// Contained entries
- ::std::vector< MacroExpansionEnt> entries;
- /// Token used to join iterations
- Token joiner;
- /// List of variables within this loop that control its iteration count
- /// Boolean is true if the variable will be unconditionally expanded
- ::std::map< unsigned int, bool> variables;
- })
- ),
- (),
- (),
- (
- public:
- SERIALISABLE_PROTOTYPES();
- )
- );
-extern ::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x);
-
-/// Matching pattern entry
-struct MacroPatEnt:
- public Serialisable
-{
- ::std::string name;
- unsigned int name_index = 0;
- Token tok;
-
- ::std::vector<MacroPatEnt> subpats;
-
- enum Type {
- PAT_TOKEN, // A token
- PAT_LOOP, // $() Enables use of subpats
-
- PAT_TT, // :tt
- PAT_PAT, // :pat
- PAT_IDENT,
- PAT_PATH,
- PAT_TYPE,
- PAT_EXPR,
- PAT_STMT,
- PAT_BLOCK,
- PAT_META,
- PAT_ITEM, // :item
- } type;
-
- MacroPatEnt():
- tok(TOK_NULL),
- type(PAT_TOKEN)
- {
- }
- MacroPatEnt(Token tok):
- tok( mv$(tok) ),
- type(PAT_TOKEN)
- {
- }
-
- MacroPatEnt(::std::string name, unsigned int name_index, Type type):
- name( mv$(name) ),
- name_index( name_index ),
- tok(),
- type(type)
- {
- }
-
- MacroPatEnt(Token sep, bool need_once, ::std::vector<MacroPatEnt> ents):
- name( need_once ? "+" : "*" ),
- tok( mv$(sep) ),
- subpats( move(ents) ),
- type(PAT_LOOP)
- {
- }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x);
- friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x);
-
- SERIALISABLE_PROTOTYPES();
-};
-
-/// An expansion arm within a macro_rules! blcok
-struct MacroRulesArm:
- public Serialisable
-{
- /// Names for the parameters
- ::std::vector< ::std::string> m_param_names;
-
- /// Patterns
- ::std::vector<MacroPatEnt> m_pattern;
-
- /// Rule contents
- ::std::vector<MacroExpansionEnt> m_contents;
-
- MacroRulesArm()
- {}
- MacroRulesArm(::std::vector<MacroPatEnt> pattern, ::std::vector<MacroExpansionEnt> contents):
- m_pattern( mv$(pattern) ),
- m_contents( mv$(contents) )
- {}
- MacroRulesArm(const MacroRulesArm&) = delete;
- MacroRulesArm& operator=(const MacroRulesArm&) = delete;
- MacroRulesArm(MacroRulesArm&&) = default;
- MacroRulesArm& operator=(MacroRulesArm&&) = default;
-
- SERIALISABLE_PROTOTYPES();
-};
-
-/// A sigle 'macro_rules!' block
-class MacroRules:
- public Serialisable
-{
-public:
- /// Marks if this macro should be exported from the defining crate
- bool m_exported = false;
-
- /// Crate that defined this macro
- /// - Populated on deserialise if not already set
- ::std::string m_source_crate;
-
- Ident::Hygiene m_hygiene;
-
- /// Expansion rules
- ::std::vector<MacroRulesArm> m_rules;
-
- MacroRules()
- {
- }
- virtual ~MacroRules();
- MacroRules(MacroRules&&) = default;
-
- SERIALISABLE_PROTOTYPES();
-};
-
-extern ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input, AST::Module& mod);
-extern MacroRulesPtr Parse_MacroRules(TokenStream& lex);
-
-#endif // MACROS_HPP_INCLUDED
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * macro_rules/macro_rules.hpp
+ * - Macros by example - `macro_rules!`
+ */
+#ifndef MACROS_HPP_INCLUDED
+#define MACROS_HPP_INCLUDED
+
+#include "parse/lex.hpp"
+#include "parse/tokentree.hpp"
+#include <common.hpp>
+#include <map>
+#include <memory>
+#include <cstring>
+#include "macro_rules_ptr.hpp"
+#include <set>
+
+class MacroExpander;
+
+TAGGED_UNION_EX(MacroExpansionEnt, (: public Serialisable), Token, (
+ // TODO: have a "raw" stream instead of just tokens
+ (Token, Token),
+ // TODO: Have a flag on `NamedValue` that indicates that it is the only/last usage of this particular value (at this level)
+ // NOTE: This is a 2:30 bitfield - with the high range indicating $crate
+ (NamedValue, unsigned int),
+ (Loop, struct {
+ /// Contained entries
+ ::std::vector< MacroExpansionEnt> entries;
+ /// Token used to join iterations
+ Token joiner;
+ /// List of variables within this loop that control its iteration count
+ /// Boolean is true if the variable will be unconditionally expanded
+ ::std::map< unsigned int, bool> variables;
+ })
+ ),
+ (),
+ (),
+ (
+ public:
+ SERIALISABLE_PROTOTYPES();
+ )
+ );
+extern ::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x);
+
+/// Matching pattern entry
+struct MacroPatEnt:
+ public Serialisable
+{
+ ::std::string name;
+ unsigned int name_index = 0;
+ Token tok;
+
+ ::std::vector<MacroPatEnt> subpats;
+
+ enum Type {
+ PAT_TOKEN, // A token
+ PAT_LOOP, // $() Enables use of subpats
+
+ PAT_TT, // :tt
+ PAT_PAT, // :pat
+ PAT_IDENT,
+ PAT_PATH,
+ PAT_TYPE,
+ PAT_EXPR,
+ PAT_STMT,
+ PAT_BLOCK,
+ PAT_META,
+ PAT_ITEM, // :item
+ } type;
+
+ MacroPatEnt():
+ tok(TOK_NULL),
+ type(PAT_TOKEN)
+ {
+ }
+ MacroPatEnt(Token tok):
+ tok( mv$(tok) ),
+ type(PAT_TOKEN)
+ {
+ }
+
+ MacroPatEnt(::std::string name, unsigned int name_index, Type type):
+ name( mv$(name) ),
+ name_index( name_index ),
+ tok(),
+ type(type)
+ {
+ }
+
+ MacroPatEnt(Token sep, bool need_once, ::std::vector<MacroPatEnt> ents):
+ name( need_once ? "+" : "*" ),
+ tok( mv$(sep) ),
+ subpats( move(ents) ),
+ type(PAT_LOOP)
+ {
+ }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x);
+ friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x);
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+/// An expansion arm within a macro_rules! blcok
+struct MacroRulesArm:
+ public Serialisable
+{
+ /// Names for the parameters
+ ::std::vector< ::std::string> m_param_names;
+
+ /// Patterns
+ ::std::vector<MacroPatEnt> m_pattern;
+
+ /// Rule contents
+ ::std::vector<MacroExpansionEnt> m_contents;
+
+ MacroRulesArm()
+ {}
+ MacroRulesArm(::std::vector<MacroPatEnt> pattern, ::std::vector<MacroExpansionEnt> contents):
+ m_pattern( mv$(pattern) ),
+ m_contents( mv$(contents) )
+ {}
+ MacroRulesArm(const MacroRulesArm&) = delete;
+ MacroRulesArm& operator=(const MacroRulesArm&) = delete;
+ MacroRulesArm(MacroRulesArm&&) = default;
+ MacroRulesArm& operator=(MacroRulesArm&&) = default;
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+/// A sigle 'macro_rules!' block
+class MacroRules:
+ public Serialisable
+{
+public:
+ /// Marks if this macro should be exported from the defining crate
+ bool m_exported = false;
+
+ /// Crate that defined this macro
+ /// - Populated on deserialise if not already set
+ ::std::string m_source_crate;
+
+ Ident::Hygiene m_hygiene;
+
+ /// Expansion rules
+ ::std::vector<MacroRulesArm> m_rules;
+
+ MacroRules()
+ {
+ }
+ virtual ~MacroRules();
+ MacroRules(MacroRules&&) = default;
+
+ SERIALISABLE_PROTOTYPES();
+};
+
+extern ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input, AST::Module& mod);
+extern MacroRulesPtr Parse_MacroRules(TokenStream& lex);
+
+#endif // MACROS_HPP_INCLUDED
diff --git a/src/macro_rules/macro_rules_ptr.hpp b/src/macro_rules/macro_rules_ptr.hpp
index c5c01488..fdb01fbe 100644
--- a/src/macro_rules/macro_rules_ptr.hpp
+++ b/src/macro_rules/macro_rules_ptr.hpp
@@ -25,9 +25,9 @@ public:
m_ptr = x.m_ptr; x.m_ptr = nullptr;
return *this;
}
-
+
~MacroRulesPtr();
-
+
const MacroRules& operator*() const { assert(m_ptr); return *m_ptr; }
MacroRules& operator*() { assert(m_ptr); return *m_ptr; }
const MacroRules* operator->() const { assert(m_ptr); return m_ptr; }
diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp
index 2803b061..f685f6dc 100644
--- a/src/macro_rules/mod.cpp
+++ b/src/macro_rules/mod.cpp
@@ -1,303 +1,303 @@
-/*
- */
-#include <common.hpp>
-#include "macro_rules.hpp"
-#include <parse/parseerror.hpp>
-#include <parse/tokentree.hpp>
-#include <parse/common.hpp>
-#include <limits.h>
-
-#include "pattern_checks.hpp"
-
-bool is_token_path(eTokenType tt) {
- switch(tt)
- {
- case TOK_IDENT:
- case TOK_DOUBLE_COLON:
- case TOK_LT:
- case TOK_DOUBLE_LT:
- case TOK_RWORD_SELF:
- case TOK_RWORD_SUPER:
- case TOK_INTERPOLATED_PATH:
- return true;
- default:
- return false;
- }
-}
-bool is_token_pat(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- case TOK_PAREN_OPEN:
- case TOK_SQUARE_OPEN:
-
- case TOK_UNDERSCORE:
- case TOK_AMP:
- case TOK_RWORD_BOX:
- case TOK_RWORD_REF:
- case TOK_RWORD_MUT:
- case TOK_STRING:
- case TOK_INTEGER:
- case TOK_CHAR:
- case TOK_INTERPOLATED_PATTERN:
- return true;
- default:
- return false;
- }
-}
-bool is_token_type(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- case TOK_PAREN_OPEN:
- case TOK_SQUARE_OPEN:
- case TOK_STAR:
- case TOK_AMP:
- case TOK_RWORD_EXTERN:
- case TOK_RWORD_UNSAFE:
- case TOK_RWORD_FN:
- case TOK_INTERPOLATED_TYPE:
- return true;
- default:
- return false;
- }
-}
-bool is_token_expr(eTokenType tt) {
- if( is_token_path(tt) )
- return true;
- switch( tt )
- {
- // Leading unary operators
- case TOK_AMP: // Borrow
- case TOK_STAR: // Deref
- case TOK_DASH: // Negate
- case TOK_EXCLAM: // Invert
- case TOK_RWORD_BOX: // Box
- // Composite values
- case TOK_MACRO:
- case TOK_PAREN_OPEN: // Parenthesised
- case TOK_SQUARE_OPEN: // Array
-
- // Flow
- case TOK_RWORD_RETURN:
- case TOK_RWORD_BREAK:
- case TOK_RWORD_CONTINUE:
-
- // Blocks
- case TOK_BRACE_OPEN:
- case TOK_RWORD_MATCH:
- case TOK_RWORD_IF:
- case TOK_RWORD_FOR:
- case TOK_RWORD_WHILE:
- case TOK_RWORD_LOOP:
- case TOK_RWORD_UNSAFE:
-
- // Closures
- case TOK_RWORD_MOVE:
- case TOK_PIPE:
- case TOK_DOUBLE_PIPE:
-
- // Literal tokens
- case TOK_INTEGER:
- case TOK_FLOAT:
- case TOK_STRING:
- case TOK_BYTESTRING:
- case TOK_RWORD_TRUE:
- case TOK_RWORD_FALSE:
-
- case TOK_INTERPOLATED_EXPR:
- return true;
- default:
- return false;
- }
-}
-bool is_token_stmt(eTokenType tt) {
- if( is_token_expr(tt) )
- return true;
- switch( tt )
- {
- case TOK_BRACE_OPEN:
- case TOK_RWORD_LET:
- case TOK_INTERPOLATED_STMT:
- return true;
- default:
- return false;
- }
-}
-
-bool is_token_item(eTokenType tt) {
- switch( tt )
- {
- case TOK_ATTR_OPEN:
-
- case TOK_RWORD_PUB:
- case TOK_RWORD_UNSAFE:
- case TOK_RWORD_TYPE:
- case TOK_RWORD_CONST:
- case TOK_RWORD_STATIC:
- case TOK_RWORD_FN:
- case TOK_RWORD_STRUCT:
- case TOK_RWORD_ENUM:
- case TOK_RWORD_TRAIT:
- case TOK_RWORD_MOD:
- case TOK_RWORD_USE:
- case TOK_RWORD_EXTERN:
- case TOK_RWORD_IMPL:
- // TODO: more?
- case TOK_INTERPOLATED_ITEM:
- return true;
- default:
- return false;
- }
-}
-
-MacroRulesPtr::~MacroRulesPtr()
-{
- if(m_ptr)
- {
- delete m_ptr;
- m_ptr = nullptr;
- }
-}
-
-SERIALISE_TYPE_S(MacroRulesArm, {
-})
-
-void operator%(Serialiser& s, MacroPatEnt::Type c) {
- switch(c) {
- #define _(v) case MacroPatEnt::v: s << #v; return
- _(PAT_TOKEN);
- _(PAT_TT);
- _(PAT_PAT);
- _(PAT_TYPE);
- _(PAT_EXPR);
- _(PAT_LOOP);
- _(PAT_STMT);
- _(PAT_PATH);
- _(PAT_BLOCK);
- _(PAT_META);
- _(PAT_ITEM);
- _(PAT_IDENT);
- #undef _
- }
-}
-void operator%(::Deserialiser& s, MacroPatEnt::Type& c) {
- ::std::string n;
- s.item(n);
- #define _(v) else if(n == #v) c = MacroPatEnt::v
- if(0) ;
- _(PAT_TOKEN);
- _(PAT_TT);
- _(PAT_PAT);
- _(PAT_TYPE);
- _(PAT_EXPR);
- _(PAT_LOOP);
- //_(PAT_OPTLOOP);
- _(PAT_STMT);
- _(PAT_PATH);
- _(PAT_BLOCK);
- _(PAT_META);
- _(PAT_IDENT);
- _(PAT_ITEM);
- else
- throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
- #undef _
-}
-SERIALISE_TYPE_S(MacroPatEnt, {
- s % type;
- s.item(name);
- s.item(tok);
- s.item(subpats);
-});
-::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x)
-{
- switch(x.type)
- {
- case MacroPatEnt::PAT_TOKEN: os << "=" << x.tok; break;
- case MacroPatEnt::PAT_LOOP: os << "loop w/ " << x.tok << " [" << x.subpats << "]"; break;
- default:
- os << "$" << x.name << ":";
- switch(x.type)
- {
- case MacroPatEnt::PAT_TOKEN: throw "";
- case MacroPatEnt::PAT_LOOP: throw "";
- case MacroPatEnt::PAT_TT: os << "tt"; break;
- case MacroPatEnt::PAT_PAT: os << "pat"; break;
- case MacroPatEnt::PAT_IDENT: os << "ident"; break;
- case MacroPatEnt::PAT_PATH: os << "path"; break;
- case MacroPatEnt::PAT_TYPE: os << "type"; break;
- case MacroPatEnt::PAT_EXPR: os << "expr"; break;
- case MacroPatEnt::PAT_STMT: os << "stmt"; break;
- case MacroPatEnt::PAT_BLOCK: os << "block"; break;
- case MacroPatEnt::PAT_META: os << "meta"; break;
- case MacroPatEnt::PAT_ITEM: os << "item"; break;
- }
- break;
- }
- return os;
-}
-::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x)
-{
- switch(x)
- {
- case MacroPatEnt::PAT_TOKEN: os << "PAT_TOKEN"; break;
- case MacroPatEnt::PAT_LOOP: os << "PAT_LOOP"; break;
- case MacroPatEnt::PAT_TT: os << "PAT_TT"; break;
- case MacroPatEnt::PAT_PAT: os << "PAT_PAT"; break;
- case MacroPatEnt::PAT_IDENT: os << "PAT_IDENT"; break;
- case MacroPatEnt::PAT_PATH: os << "PAT_PATH"; break;
- case MacroPatEnt::PAT_TYPE: os << "PAT_TYPE"; break;
- case MacroPatEnt::PAT_EXPR: os << "PAT_EXPR"; break;
- case MacroPatEnt::PAT_STMT: os << "PAT_STMT"; break;
- case MacroPatEnt::PAT_BLOCK: os << "PAT_BLOCK"; break;
- case MacroPatEnt::PAT_META: os << "PAT_META"; break;
- case MacroPatEnt::PAT_ITEM: os << "PAT_ITEM"; break;
- }
- return os;
-}
-
-SERIALISE_TU(MacroExpansionEnt, "MacroExpansionEnt", e,
-(Token,
- s.item(e);
- ),
-(NamedValue,
- s.item(e);
- ),
-(Loop,
- s.item(e.entries);
- s.item(e.joiner);
- //s.item(e.variables);
- )
-);
-
-::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x)
-{
- TU_MATCH( MacroExpansionEnt, (x), (e),
- (Token,
- os << "=" << e;
- ),
- (NamedValue,
- if( e >> 30 ) {
- os << "$crate";
- }
- else {
- os << "$" << e;
- }
- ),
- (Loop,
- os << "${" << *e.variables.begin() << "}(" << e.entries << ") " << e.joiner;
- )
- )
- return os;
-}
-
-MacroRules::~MacroRules()
-{
-}
-SERIALISE_TYPE_S(MacroRules, {
- s.item( m_exported );
- s.item( m_rules );
-});
-
+/*
+ */
+#include <common.hpp>
+#include "macro_rules.hpp"
+#include <parse/parseerror.hpp>
+#include <parse/tokentree.hpp>
+#include <parse/common.hpp>
+#include <limits.h>
+
+#include "pattern_checks.hpp"
+
+bool is_token_path(eTokenType tt) {
+ switch(tt)
+ {
+ case TOK_IDENT:
+ case TOK_DOUBLE_COLON:
+ case TOK_LT:
+ case TOK_DOUBLE_LT:
+ case TOK_RWORD_SELF:
+ case TOK_RWORD_SUPER:
+ case TOK_INTERPOLATED_PATH:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_pat(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+
+ case TOK_UNDERSCORE:
+ case TOK_AMP:
+ case TOK_RWORD_BOX:
+ case TOK_RWORD_REF:
+ case TOK_RWORD_MUT:
+ case TOK_STRING:
+ case TOK_INTEGER:
+ case TOK_CHAR:
+ case TOK_INTERPOLATED_PATTERN:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_type(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+ case TOK_STAR:
+ case TOK_AMP:
+ case TOK_RWORD_EXTERN:
+ case TOK_RWORD_UNSAFE:
+ case TOK_RWORD_FN:
+ case TOK_INTERPOLATED_TYPE:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_expr(eTokenType tt) {
+ if( is_token_path(tt) )
+ return true;
+ switch( tt )
+ {
+ // Leading unary operators
+ case TOK_AMP: // Borrow
+ case TOK_STAR: // Deref
+ case TOK_DASH: // Negate
+ case TOK_EXCLAM: // Invert
+ case TOK_RWORD_BOX: // Box
+ // Composite values
+ case TOK_MACRO:
+ case TOK_PAREN_OPEN: // Parenthesised
+ case TOK_SQUARE_OPEN: // Array
+
+ // Flow
+ case TOK_RWORD_RETURN:
+ case TOK_RWORD_BREAK:
+ case TOK_RWORD_CONTINUE:
+
+ // Blocks
+ case TOK_BRACE_OPEN:
+ case TOK_RWORD_MATCH:
+ case TOK_RWORD_IF:
+ case TOK_RWORD_FOR:
+ case TOK_RWORD_WHILE:
+ case TOK_RWORD_LOOP:
+ case TOK_RWORD_UNSAFE:
+
+ // Closures
+ case TOK_RWORD_MOVE:
+ case TOK_PIPE:
+ case TOK_DOUBLE_PIPE:
+
+ // Literal tokens
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_STRING:
+ case TOK_BYTESTRING:
+ case TOK_RWORD_TRUE:
+ case TOK_RWORD_FALSE:
+
+ case TOK_INTERPOLATED_EXPR:
+ return true;
+ default:
+ return false;
+ }
+}
+bool is_token_stmt(eTokenType tt) {
+ if( is_token_expr(tt) )
+ return true;
+ switch( tt )
+ {
+ case TOK_BRACE_OPEN:
+ case TOK_RWORD_LET:
+ case TOK_INTERPOLATED_STMT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool is_token_item(eTokenType tt) {
+ switch( tt )
+ {
+ case TOK_ATTR_OPEN:
+
+ case TOK_RWORD_PUB:
+ case TOK_RWORD_UNSAFE:
+ case TOK_RWORD_TYPE:
+ case TOK_RWORD_CONST:
+ case TOK_RWORD_STATIC:
+ case TOK_RWORD_FN:
+ case TOK_RWORD_STRUCT:
+ case TOK_RWORD_ENUM:
+ case TOK_RWORD_TRAIT:
+ case TOK_RWORD_MOD:
+ case TOK_RWORD_USE:
+ case TOK_RWORD_EXTERN:
+ case TOK_RWORD_IMPL:
+ // TODO: more?
+ case TOK_INTERPOLATED_ITEM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+MacroRulesPtr::~MacroRulesPtr()
+{
+ if(m_ptr)
+ {
+ delete m_ptr;
+ m_ptr = nullptr;
+ }
+}
+
+SERIALISE_TYPE_S(MacroRulesArm, {
+})
+
+void operator%(Serialiser& s, MacroPatEnt::Type c) {
+ switch(c) {
+ #define _(v) case MacroPatEnt::v: s << #v; return
+ _(PAT_TOKEN);
+ _(PAT_TT);
+ _(PAT_PAT);
+ _(PAT_TYPE);
+ _(PAT_EXPR);
+ _(PAT_LOOP);
+ _(PAT_STMT);
+ _(PAT_PATH);
+ _(PAT_BLOCK);
+ _(PAT_META);
+ _(PAT_ITEM);
+ _(PAT_IDENT);
+ #undef _
+ }
+}
+void operator%(::Deserialiser& s, MacroPatEnt::Type& c) {
+ ::std::string n;
+ s.item(n);
+ #define _(v) else if(n == #v) c = MacroPatEnt::v
+ if(0) ;
+ _(PAT_TOKEN);
+ _(PAT_TT);
+ _(PAT_PAT);
+ _(PAT_TYPE);
+ _(PAT_EXPR);
+ _(PAT_LOOP);
+ //_(PAT_OPTLOOP);
+ _(PAT_STMT);
+ _(PAT_PATH);
+ _(PAT_BLOCK);
+ _(PAT_META);
+ _(PAT_IDENT);
+ _(PAT_ITEM);
+ else
+ throw ::std::runtime_error( FMT("No conversion for '" << n << "'") );
+ #undef _
+}
+SERIALISE_TYPE_S(MacroPatEnt, {
+ s % type;
+ s.item(name);
+ s.item(tok);
+ s.item(subpats);
+});
+::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x)
+{
+ switch(x.type)
+ {
+ case MacroPatEnt::PAT_TOKEN: os << "=" << x.tok; break;
+ case MacroPatEnt::PAT_LOOP: os << "loop w/ " << x.tok << " [" << x.subpats << "]"; break;
+ default:
+ os << "$" << x.name << ":";
+ switch(x.type)
+ {
+ case MacroPatEnt::PAT_TOKEN: throw "";
+ case MacroPatEnt::PAT_LOOP: throw "";
+ case MacroPatEnt::PAT_TT: os << "tt"; break;
+ case MacroPatEnt::PAT_PAT: os << "pat"; break;
+ case MacroPatEnt::PAT_IDENT: os << "ident"; break;
+ case MacroPatEnt::PAT_PATH: os << "path"; break;
+ case MacroPatEnt::PAT_TYPE: os << "type"; break;
+ case MacroPatEnt::PAT_EXPR: os << "expr"; break;
+ case MacroPatEnt::PAT_STMT: os << "stmt"; break;
+ case MacroPatEnt::PAT_BLOCK: os << "block"; break;
+ case MacroPatEnt::PAT_META: os << "meta"; break;
+ case MacroPatEnt::PAT_ITEM: os << "item"; break;
+ }
+ break;
+ }
+ return os;
+}
+::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt::Type& x)
+{
+ switch(x)
+ {
+ case MacroPatEnt::PAT_TOKEN: os << "PAT_TOKEN"; break;
+ case MacroPatEnt::PAT_LOOP: os << "PAT_LOOP"; break;
+ case MacroPatEnt::PAT_TT: os << "PAT_TT"; break;
+ case MacroPatEnt::PAT_PAT: os << "PAT_PAT"; break;
+ case MacroPatEnt::PAT_IDENT: os << "PAT_IDENT"; break;
+ case MacroPatEnt::PAT_PATH: os << "PAT_PATH"; break;
+ case MacroPatEnt::PAT_TYPE: os << "PAT_TYPE"; break;
+ case MacroPatEnt::PAT_EXPR: os << "PAT_EXPR"; break;
+ case MacroPatEnt::PAT_STMT: os << "PAT_STMT"; break;
+ case MacroPatEnt::PAT_BLOCK: os << "PAT_BLOCK"; break;
+ case MacroPatEnt::PAT_META: os << "PAT_META"; break;
+ case MacroPatEnt::PAT_ITEM: os << "PAT_ITEM"; break;
+ }
+ return os;
+}
+
+SERIALISE_TU(MacroExpansionEnt, "MacroExpansionEnt", e,
+(Token,
+ s.item(e);
+ ),
+(NamedValue,
+ s.item(e);
+ ),
+(Loop,
+ s.item(e.entries);
+ s.item(e.joiner);
+ //s.item(e.variables);
+ )
+);
+
+::std::ostream& operator<<(::std::ostream& os, const MacroExpansionEnt& x)
+{
+ TU_MATCH( MacroExpansionEnt, (x), (e),
+ (Token,
+ os << "=" << e;
+ ),
+ (NamedValue,
+ if( e >> 30 ) {
+ os << "$crate";
+ }
+ else {
+ os << "$" << e;
+ }
+ ),
+ (Loop,
+ os << "${" << *e.variables.begin() << "}(" << e.entries << ") " << e.joiner;
+ )
+ )
+ return os;
+}
+
+MacroRules::~MacroRules()
+{
+}
+SERIALISE_TYPE_S(MacroRules, {
+ s.item( m_exported );
+ s.item( m_rules );
+});
+
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index 4da91a90..fa82e0e0 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -26,9 +26,9 @@ public:
{
TRACE_FUNCTION;
Token tok;
-
+
::std::vector<MacroPatEnt> ret;
-
+
int depth = 0;
while( GET_TOK(tok, lex) != close || depth > 0 )
{
@@ -42,7 +42,7 @@ public:
throw ParseError::Generic(FMT("Unmatched " << Token(close) << " in macro pattern"));
depth --;
}
-
+
switch(tok.type())
{
case TOK_DOLLAR:
@@ -53,11 +53,11 @@ public:
GET_CHECK_TOK(tok, lex, TOK_COLON);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string type = mv$(tok.str());
-
+
unsigned int idx = ::std::find( names.begin(), names.end(), name ) - names.begin();
if( idx == names.size() )
names.push_back( name );
-
+
if(0)
;
else if( type == "tt" )
@@ -119,7 +119,7 @@ public:
break;
}
}
-
+
return ret;
}
@@ -132,10 +132,10 @@ public:
)
{
TRACE_FUNCTION;
-
+
Token tok;
::std::vector<MacroExpansionEnt> ret;
-
+
int depth = 0;
while( GET_TOK(tok, lex) != close || depth > 0 )
{
@@ -144,7 +144,7 @@ public:
}
if( tok.type() == TOK_NULL )
continue ;
-
+
if( tok.type() == open )
{
DEBUG("depth++");
@@ -157,19 +157,19 @@ public:
ERROR(lex.getPosition(), E0000, "Unmatched " << Token(close) << " in macro content");
depth --;
}
-
+
// `$` - Macro metavars
if( tok.type() == TOK_DOLLAR )
{
GET_TOK(tok, lex);
-
+
// `$(`
if( tok.type() == TOK_PAREN_OPEN )
- {
+ {
::std::map<unsigned int, bool> var_set;
auto content = Parse_MacroRules_Cont(lex, TOK_PAREN_OPEN, TOK_PAREN_CLOSE, var_names, &var_set);
// ^^ The above will eat the PAREN_CLOSE
-
+
GET_TOK(tok, lex);
enum eTokenType joiner = TOK_NULL;
if( tok.type() != TOK_PLUS && tok.type() != TOK_STAR )
@@ -197,7 +197,7 @@ public:
default:
throw ParseError::Unexpected(lex, tok);
}
-
+
}
else if( tok.type() == TOK_IDENT )
{
@@ -225,7 +225,7 @@ public:
ret.push_back( MacroExpansionEnt( mv$(tok) ) );
}
}
-
+
return ret;
}
@@ -234,9 +234,9 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
{
TRACE_FUNCTION;
Token tok;
-
+
MacroRule rule;
-
+
// Pattern
enum eTokenType close;
switch(GET_TOK(tok, lex))
@@ -249,7 +249,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
// - Pattern entries
::std::vector< ::std::string> names;
rule.m_pattern = Parse_MacroRules_Pat(lex, tok.type(), close, names);
-
+
GET_CHECK_TOK(tok, lex, TOK_FATARROW);
// Replacement
@@ -263,7 +263,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
rule.m_contents = Parse_MacroRules_Cont(lex, tok.type(), close, names);
DEBUG("Rule - ["<<rule.m_pattern<<"] => "<<rule.m_contents<<"");
-
+
return rule;
}
@@ -271,11 +271,11 @@ bool patterns_are_same(const Span& sp, const MacroPatEnt& left, const MacroPatEn
{
if( left.type > right.type )
return patterns_are_same(sp, right, left);
-
+
//if( left.name != right.name ) {
// TODO(sp, "Handle different binding names " << left << " != " << right);
//}
-
+
// NOTE: left.type <= right.type
switch(right.type)
{
@@ -295,13 +295,13 @@ bool patterns_are_same(const Span& sp, const MacroPatEnt& left, const MacroPatEn
default:
assert( !"" );
}
-
+
case MacroPatEnt::PAT_TT:
if( left.type == right.type )
return true;
ERROR(sp, E0000, "Incompatible macro fragments - " << right << " used with " << left);
break;
-
+
case MacroPatEnt::PAT_PAT:
switch(left.type)
{
@@ -444,15 +444,15 @@ void enumerate_names(const ::std::vector<MacroPatEnt>& pats, ::std::vector< ::st
MacroRulesPtr Parse_MacroRules(TokenStream& lex)
{
TRACE_FUNCTION_F("");
-
+
Token tok;
-
+
// Parse the patterns and replacements
::std::vector<MacroRule> rules;
while( GET_TOK(tok, lex) != TOK_EOF )
{
lex.putback(tok);
-
+
rules.push_back( Parse_MacroRules_Var(lex) );
if(GET_TOK(tok, lex) != TOK_SEMICOLON) {
CHECK_TOK(tok, TOK_EOF);
@@ -460,22 +460,22 @@ MacroRulesPtr Parse_MacroRules(TokenStream& lex)
}
}
DEBUG("- " << rules.size() << " rules");
-
+
::std::vector<MacroRulesArm> rule_arms;
-
+
// Re-parse the patterns into a unified form
for(auto& rule : rules)
{
MacroRulesArm arm = MacroRulesArm( mv$(rule.m_pattern), mv$(rule.m_contents) );
-
+
enumerate_names(arm.m_pattern, arm.m_param_names);
-
+
rule_arms.push_back( mv$(arm) );
}
-
+
auto rv = new MacroRules( );
rv->m_hygiene = lex.getHygiene();
rv->m_rules = mv$(rule_arms);
-
+
return MacroRulesPtr(rv);
}
diff --git a/src/main.cpp b/src/main.cpp
index affd981f..5acb8545 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,613 +1,613 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * main.cpp
- * - Compiler Entrypoint
- */
-#include <iostream>
-#include <iomanip>
-#include <string>
-#include <set>
-#include "parse/lex.hpp"
-#include "parse/parseerror.hpp"
-#include "ast/ast.hpp"
-#include "ast/crate.hpp"
-#include <serialiser_texttree.hpp>
-#include <cstring>
-#include <main_bindings.hpp>
-#include "resolve/main_bindings.hpp"
-#include "hir/main_bindings.hpp"
-#include "hir_conv/main_bindings.hpp"
-#include "hir_typeck/main_bindings.hpp"
-#include "hir_expand/main_bindings.hpp"
-#include "mir/main_bindings.hpp"
-#include "trans/main_bindings.hpp"
-
-#include "expand/cfg.hpp"
-
-int g_debug_indent_level = 0;
-bool g_debug_enabled = true;
-::std::string g_cur_phase;
-::std::set< ::std::string> g_debug_disable_map;
-
-void init_debug_list()
-{
- g_debug_disable_map.insert( "Parse" );
- g_debug_disable_map.insert( "LoadCrates" );
- g_debug_disable_map.insert( "Expand" );
-
- g_debug_disable_map.insert( "Resolve Use" );
- g_debug_disable_map.insert( "Resolve Index" );
- g_debug_disable_map.insert( "Resolve Absolute" );
-
- g_debug_disable_map.insert( "HIR Lower" );
-
- g_debug_disable_map.insert( "Resolve Type Aliases" );
- g_debug_disable_map.insert( "Resolve Bind" );
- g_debug_disable_map.insert( "Resolve UFCS paths" );
- g_debug_disable_map.insert( "Resolve HIR Markings" );
- g_debug_disable_map.insert( "Constant Evaluate" );
-
- g_debug_disable_map.insert( "Typecheck Outer");
- g_debug_disable_map.insert( "Typecheck Expressions" );
-
- g_debug_disable_map.insert( "Expand HIR Annotate" );
- g_debug_disable_map.insert( "Expand HIR Closures" );
- g_debug_disable_map.insert( "Expand HIR Calls" );
- g_debug_disable_map.insert( "Expand HIR VTables" );
- g_debug_disable_map.insert( "Expand HIR Reborrows" );
- g_debug_disable_map.insert( "Expand HIR ErasedType" );
- g_debug_disable_map.insert( "Typecheck Expressions (validate)" );
-
- g_debug_disable_map.insert( "Dump HIR" );
- g_debug_disable_map.insert( "Lower MIR" );
- g_debug_disable_map.insert( "MIR Validate" );
- g_debug_disable_map.insert( "Dump MIR" );
- g_debug_disable_map.insert( "Constant Evaluate Full" );
- g_debug_disable_map.insert( "MIR Cleanup" );
- g_debug_disable_map.insert( "MIR Optimise" );
-
- g_debug_disable_map.insert( "HIR Serialise" );
- g_debug_disable_map.insert( "Trans Enumerate" );
- g_debug_disable_map.insert( "Trans Codegen" );
-
- // Mutate this map using an environment variable
- const char* debug_string = ::std::getenv("MRUSTC_DEBUG");
- if( debug_string )
- {
- while( debug_string[0] )
- {
- const char* end = strchr(debug_string, ':');
-
- if( end ) {
- ::std::string s { debug_string, end };
- // TODO: Emit a warning when this name wasn't in the map?
- g_debug_disable_map.erase( s );
- debug_string = end + 1;
- }
- else {
- g_debug_disable_map.erase( debug_string );
- break;
- }
- }
- }
-}
-bool debug_enabled_update() {
- if( g_debug_disable_map.count(g_cur_phase) != 0 ) {
- return false;
- }
- else {
- return true;
- }
-}
-bool debug_enabled()
-{
- return g_debug_enabled;
-}
-::std::ostream& debug_output(int indent, const char* function)
-{
- return ::std::cout << g_cur_phase << "- " << RepeatLitStr { " ", indent } << function << ": ";
-}
-
-struct ProgramParams
-{
- enum eLastStage {
- STAGE_PARSE,
- STAGE_EXPAND,
- STAGE_RESOLVE,
- STAGE_TYPECK,
- STAGE_BORROWCK,
- STAGE_MIR,
- STAGE_ALL,
- } last_stage = STAGE_ALL;
-
- ::std::string infile;
- ::std::string outfile;
- ::std::string output_dir = "";
- const char *crate_path = ".";
-
- ::AST::Crate::Type crate_type = ::AST::Crate::Type::Unknown;
-
- ::std::set< ::std::string> features;
-
- ProgramParams(int argc, char *argv[]);
-};
-
-template <typename Rv, typename Fcn>
-Rv CompilePhase(const char *name, Fcn f) {
- ::std::cout << name << ": V V V" << ::std::endl;
- g_cur_phase = name;
- g_debug_enabled = debug_enabled_update();
- auto start = clock();
- auto rv = f();
- auto end = clock();
- g_cur_phase = "";
- g_debug_enabled = debug_enabled_update();
-
- ::std::cout <<"(" << ::std::fixed << ::std::setprecision(2) << static_cast<double>(end - start) / static_cast<double>(CLOCKS_PER_SEC) << " s) ";
- ::std::cout << name << ": DONE";
- ::std::cout << ::std::endl;
- return rv;
-}
-template <typename Fcn>
-void CompilePhaseV(const char *name, Fcn f) {
- CompilePhase<int>(name, [&]() { f(); return 0; });
-}
-
-/// main!
-int main(int argc, char *argv[])
-{
- init_debug_list();
- ProgramParams params(argc, argv);
-
- // Set up cfg values
- // TODO: Target spec
- Cfg_SetFlag("unix");
- Cfg_SetFlag("linux");
- Cfg_SetValue("target_os", "linux");
- Cfg_SetValue("target_pointer_width", "64");
- Cfg_SetValue("target_endian", "little");
- Cfg_SetValue("target_arch", "x86_64");
- Cfg_SetValue("target_env", "gnu");
- Cfg_SetValueCb("target_has_atomic", [](const ::std::string& s) {
- if(s == "8") return true; // Has an atomic byte
- if(s == "ptr") return true; // Has an atomic pointer-sized value
- return false;
- });
- Cfg_SetValueCb("target_feature", [](const ::std::string& s) {
- return false;
- });
- Cfg_SetValueCb("feature", [&params](const ::std::string& s) {
- return params.features.count(s) != 0;
- });
-
-
-
- try
- {
- // Parse the crate into AST
- AST::Crate crate = CompilePhase<AST::Crate>("Parse", [&]() {
- return Parse_Crate(params.infile);
- });
-
- if( params.last_stage == ProgramParams::STAGE_PARSE ) {
- return 0;
- }
-
- // Load external crates.
- CompilePhaseV("LoadCrates", [&]() {
- crate.load_externs();
- });
-
- // Iterate all items in the AST, applying syntax extensions
- CompilePhaseV("Expand", [&]() {
- Expand(crate);
- });
-
- // Extract the crate type and name from the crate attributes
- auto crate_type = params.crate_type;
- if( crate_type == ::AST::Crate::Type::Unknown ) {
- crate_type = crate.m_crate_type;
- }
- if( crate_type == ::AST::Crate::Type::Unknown ) {
- // Assume to be executable
- crate_type = ::AST::Crate::Type::Executable;
- }
- crate.m_crate_type = crate_type;
- auto crate_name = crate.m_crate_name;
- if( crate_name == "" ) {
- auto s = params.infile.find_last_of('/');
- if( s == ::std::string::npos )
- s = 0;
- else
- s += 1;
- auto e = params.infile.find_first_of('.', s);
- if( e == ::std::string::npos )
- e = params.infile.size() - s;
-
- crate_name = ::std::string(params.infile.begin() + s, params.infile.begin() + e);
- for(auto& b : crate_name)
- {
- switch(b)
- {
- case '0' ... '9':
- case 'A' ... 'Z':
- case 'a' ... 'z':
- case '_':
- break;
- case '-':
- b = '_';
- break;
- default:
- break;
- }
- }
- crate.m_crate_name = crate_name;
- }
-
- if( params.outfile == "" ) {
- switch( crate.m_crate_type )
- {
- case ::AST::Crate::Type::RustLib:
- params.outfile = FMT(params.output_dir << "lib" << crate.m_crate_name << ".hir");
- break;
- case ::AST::Crate::Type::Executable:
- params.outfile = FMT(params.output_dir << crate.m_crate_name);
- break;
- default:
- params.outfile = FMT(params.output_dir << crate.m_crate_name << ".o");
- break;
- }
- DEBUG("params.outfile = " << params.outfile);
- }
-
- // XXX: Dump crate before resolve
- CompilePhaseV("Temp output - Parsed", [&]() {
- Dump_Rust( FMT(params.outfile << "_0a_exp.rs").c_str(), crate );
- });
-
- if( params.last_stage == ProgramParams::STAGE_EXPAND ) {
- return 0;
- }
-
- // Allocator and panic strategies
- if( crate.m_crate_type == ::AST::Crate::Type::Executable )
- {
- // TODO: Detect if an allocator crate is already present.
- crate.load_extern_crate(Span(), "alloc_system");
- crate.load_extern_crate(Span(), "panic_abort");
- }
-
- // Resolve names to be absolute names (include references to the relevant struct/global/function)
- // - This does name checking on types and free functions.
- // - Resolves all identifiers/paths to references
- CompilePhaseV("Resolve Use", [&]() {
- Resolve_Use(crate); // - Absolutise and resolve use statements
- });
- CompilePhaseV("Resolve Index", [&]() {
- Resolve_Index(crate); // - Build up a per-module index of avalable names (faster and simpler later resolve)
- });
- CompilePhaseV("Resolve Absolute", [&]() {
- Resolve_Absolutise(crate); // - Convert all paths to Absolute or UFCS, and resolve variables
- });
-
- // XXX: Dump crate before HIR
- CompilePhaseV("Temp output - Resolved", [&]() {
- Dump_Rust( FMT(params.outfile << "_1_res.rs").c_str(), crate );
- });
-
- if( params.last_stage == ProgramParams::STAGE_RESOLVE ) {
- return 0;
- }
-
- // --------------------------------------
- // HIR Section
- // --------------------------------------
- // Construc the HIR from the AST
- ::HIR::CratePtr hir_crate = CompilePhase< ::HIR::CratePtr>("HIR Lower", [&]() {
- return LowerHIR_FromAST(mv$( crate ));
- });
- // Deallocate the original crate
- crate = ::AST::Crate();
-
- // Replace type aliases (`type`) into the actual type
- CompilePhaseV("Resolve Type Aliases", [&]() {
- ConvertHIR_ExpandAliases(*hir_crate);
- });
- // Set up bindings and other useful information.
- CompilePhaseV("Resolve Bind", [&]() {
- ConvertHIR_Bind(*hir_crate);
- });
- CompilePhaseV("Resolve UFCS paths", [&]() {
- ConvertHIR_ResolveUFCS(*hir_crate);
- });
- CompilePhaseV("Resolve HIR Markings", [&]() {
- ConvertHIR_Markings(*hir_crate);
- });
- // Basic constant evalulation (intergers/floats only)
- CompilePhaseV("Constant Evaluate", [&]() {
- ConvertHIR_ConstantEvaluate(*hir_crate);
- });
-
- CompilePhaseV("Dump HIR", [&]() {
- ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
- HIR_Dump( os, *hir_crate );
- });
-
- // === Type checking ===
- // - This can recurse and call the MIR lower to evaluate constants
-
- // Check outer items first (types of constants/functions/statics/impls/...)
- // - Doesn't do any expressions except those in types
- CompilePhaseV("Typecheck Outer", [&]() {
- Typecheck_ModuleLevel(*hir_crate);
- });
- // Check the rest of the expressions (including function bodies)
- CompilePhaseV("Typecheck Expressions", [&]() {
- Typecheck_Expressions(*hir_crate);
- });
- // === HIR Expansion ===
- // Annotate how each node's result is used
- CompilePhaseV("Expand HIR Annotate", [&]() {
- HIR_Expand_AnnotateUsage(*hir_crate);
- });
- // - Now that all types are known, closures can be desugared
- CompilePhaseV("Expand HIR Closures", [&]() {
- HIR_Expand_Closures(*hir_crate);
- });
- // - Construct VTables for all traits and impls.
- CompilePhaseV("Expand HIR VTables", [&]() { HIR_Expand_VTables(*hir_crate); });
- // - And calls can be turned into UFCS
- CompilePhaseV("Expand HIR Calls", [&]() {
- HIR_Expand_UfcsEverything(*hir_crate);
- });
- CompilePhaseV("Expand HIR Reborrows", [&]() {
- HIR_Expand_Reborrows(*hir_crate);
- });
- CompilePhaseV("Expand HIR ErasedType", [&]() {
- HIR_Expand_ErasedType(*hir_crate);
- });
- CompilePhaseV("Dump HIR", [&]() {
- ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
- HIR_Dump( os, *hir_crate );
- });
- // - Ensure that typeck worked (including Fn trait call insertion etc)
- CompilePhaseV("Typecheck Expressions (validate)", [&]() {
- Typecheck_Expressions_Validate(*hir_crate);
- });
-
- if( params.last_stage == ProgramParams::STAGE_TYPECK ) {
- return 0;
- }
-
- // Lower expressions into MIR
- CompilePhaseV("Lower MIR", [&]() {
- HIR_GenerateMIR(*hir_crate);
- });
-
- CompilePhaseV("Dump MIR", [&]() {
- ::std::ofstream os (FMT(params.outfile << "_3_mir.rs"));
- MIR_Dump( os, *hir_crate );
- });
-
- // Validate the MIR
- CompilePhaseV("MIR Validate", [&]() {
- MIR_CheckCrate(*hir_crate);
- });
-
- // Second shot of constant evaluation (with full type information)
- CompilePhaseV("Constant Evaluate Full", [&]() {
- ConvertHIR_ConstantEvaluateFull(*hir_crate);
- });
- CompilePhaseV("Dump HIR", [&]() {
- ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
- HIR_Dump( os, *hir_crate );
- });
-
- // - Expand constants in HIR and virtualise calls
- CompilePhaseV("MIR Cleanup", [&]() {
- MIR_CleanupCrate(*hir_crate);
- });
- // Optimise the MIR
- CompilePhaseV("MIR Optimise", [&]() {
- MIR_OptimiseCrate(*hir_crate);
- });
-
- CompilePhaseV("Dump MIR", [&]() {
- ::std::ofstream os (FMT(params.outfile << "_3_mir.rs"));
- MIR_Dump( os, *hir_crate );
- });
-
- if( params.last_stage == ProgramParams::STAGE_MIR ) {
- return 0;
- }
-
- // TODO: Pass to mark items that are
- // - Signature Exportable (public)
- // - MIR Exportable (public generic, #[inline], or used by a either of those)
- // - Require codegen (public or used by an exported function)
-
- // Generate code for non-generic public items (if requested)
- switch( crate_type )
- {
- case ::AST::Crate::Type::Unknown:
- // ERROR?
- break;
- case ::AST::Crate::Type::RustLib:
- // Save a loadable HIR dump
- CompilePhaseV("HIR Serialise", [&]() {
- //HIR_Serialise(params.outfile + ".meta", *hir_crate);
- HIR_Serialise(params.outfile, *hir_crate);
- });
- //TransList items;
- //CompilePhaseV("Trans Enumerate", [&]() { Trans_Enumerate_Public(*hir_crate); });
- //CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile + ".o", *hir_crate, items); });
- // Generate a .o
- //HIR_Codegen_Lib(params.outfile + ".o", *hir_crate);
- // Link metatdata and object into a .rlib
- break;
- case ::AST::Crate::Type::RustDylib:
- // Save a loadable HIR dump
- CompilePhaseV("HIR Serialise", [&]() { HIR_Serialise(params.outfile, *hir_crate); });
- // - Enumerate codegen for visible and non-generic items
- //TransList items;
- //CompilePhaseV("Trans Enumerate", [&]() { Trans_Enumerate_Public(*hir_crate); });
- //CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile, *hir_crate, items); });
- // Generate a .so/.dll
- // TODO: Codegen and include the metadata in a non-loadable segment
- break;
- case ::AST::Crate::Type::CDylib:
- // Generate a .so/.dll
- break;
- case ::AST::Crate::Type::Executable:
- // Generate a binary
- // - Enumerate items for translation
- TransList items = CompilePhase<TransList>("Trans Enumerate", [&]() { return Trans_Enumerate_Main(*hir_crate); });
- // - Perform codegen
- CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile, *hir_crate, items); });
- // - Invoke linker?
- break;
- }
- }
- catch(unsigned int) {}
- //catch(const CompileError::Base& e)
- //{
- // ::std::cerr << "Parser Error: " << e.what() << ::std::endl;
- // return 2;
- //}
- //catch(const ::std::exception& e)
- //{
- // ::std::cerr << "Misc Error: " << e.what() << ::std::endl;
- // return 2;
- //}
- //catch(const char* e)
- //{
- // ::std::cerr << "Internal Compiler Error: " << e << ::std::endl;
- // return 2;
- //}
- 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] != '-' )
- {
- if( this->infile != "" )
- ;
- this->infile = arg;
-
- if( this->infile == "" )
- ;
- }
- else if( arg[1] != '-' )
- {
- arg ++; // eat '-'
- for( ; *arg; arg ++ )
- {
- switch(*arg)
- {
- // "-o <file>" : 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 ) {
- ::std::cerr << "Flag --crate-path requires an argument" << ::std::endl;
- exit(1);
- }
- this->crate_path = argv[++i];
- }
- else if( strcmp(arg, "--out-dir") == 0 ) {
- if( i == argc - 1 ) {
- ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl;
- exit(1);
- }
- this->output_dir = argv[++i];
- if( this->output_dir == "" )
- ;
- if( this->output_dir.back() != '/' )
- this->output_dir += '/';
- }
- else if( strcmp(arg, "--crate-type") == 0 ) {
- if( i == argc - 1 ) {
- ::std::cerr << "Flag --crate-type requires an argument" << ::std::endl;
- exit(1);
- }
- const char* type_str = argv[++i];
-
- if( strcmp(type_str, "rlib") == 0 ) {
- this->crate_type = ::AST::Crate::Type::RustLib;
- }
- else {
- ::std::cerr << "Unknown value for --crate-type" << ::std::endl;
- exit(1);
- }
- }
- else if( strcmp(arg, "--cfg") == 0 ) {
- if( i == argc - 1 ) {
- ::std::cerr << "Flag --cfg requires an argument" << ::std::endl;
- exit(1);
- }
- char* opt_and_val = argv[++i];
- if( char* p = strchr(opt_and_val, '=') ) {
- *p = '\0';
- const char* opt = opt_and_val;
- const char* val = p + 1;
- if( ::std::strcmp(opt, "feature") == 0 ) {
- this->features.insert( ::std::string(val) );
- }
- else {
- Cfg_SetValue(opt, val);
- }
- }
- else {
- Cfg_SetFlag(opt_and_val);
- }
- }
- else if( strcmp(arg, "--stop-after") == 0 ) {
- if( i == argc - 1 ) {
- ::std::cerr << "Flag --stop-after requires an argument" << ::std::endl;
- exit(1);
- }
-
- arg = argv[++i];
- if( strcmp(arg, "parse") == 0 )
- this->last_stage = STAGE_PARSE;
- else if( strcmp(arg, "expand") == 0 )
- this->last_stage = STAGE_EXPAND;
- else if( strcmp(arg, "resolve") == 0 )
- this->last_stage = STAGE_RESOLVE;
- else if( strcmp(arg, "mir") == 0 )
- this->last_stage = STAGE_MIR;
- else if( strcmp(arg, "ALL") == 0 )
- this->last_stage = STAGE_ALL;
- else {
- ::std::cerr << "Unknown argument to --stop-after : '" << arg << "'" << ::std::endl;
- exit(1);
- }
- }
- else {
- ::std::cerr << "Unknown option '" << arg << "'" << ::std::endl;
- exit(1);
- }
- }
- }
-}
-
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * main.cpp
+ * - Compiler Entrypoint
+ */
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <set>
+#include "parse/lex.hpp"
+#include "parse/parseerror.hpp"
+#include "ast/ast.hpp"
+#include "ast/crate.hpp"
+#include <serialiser_texttree.hpp>
+#include <cstring>
+#include <main_bindings.hpp>
+#include "resolve/main_bindings.hpp"
+#include "hir/main_bindings.hpp"
+#include "hir_conv/main_bindings.hpp"
+#include "hir_typeck/main_bindings.hpp"
+#include "hir_expand/main_bindings.hpp"
+#include "mir/main_bindings.hpp"
+#include "trans/main_bindings.hpp"
+
+#include "expand/cfg.hpp"
+
+int g_debug_indent_level = 0;
+bool g_debug_enabled = true;
+::std::string g_cur_phase;
+::std::set< ::std::string> g_debug_disable_map;
+
+void init_debug_list()
+{
+ g_debug_disable_map.insert( "Parse" );
+ g_debug_disable_map.insert( "LoadCrates" );
+ g_debug_disable_map.insert( "Expand" );
+
+ g_debug_disable_map.insert( "Resolve Use" );
+ g_debug_disable_map.insert( "Resolve Index" );
+ g_debug_disable_map.insert( "Resolve Absolute" );
+
+ g_debug_disable_map.insert( "HIR Lower" );
+
+ g_debug_disable_map.insert( "Resolve Type Aliases" );
+ g_debug_disable_map.insert( "Resolve Bind" );
+ g_debug_disable_map.insert( "Resolve UFCS paths" );
+ g_debug_disable_map.insert( "Resolve HIR Markings" );
+ g_debug_disable_map.insert( "Constant Evaluate" );
+
+ g_debug_disable_map.insert( "Typecheck Outer");
+ g_debug_disable_map.insert( "Typecheck Expressions" );
+
+ g_debug_disable_map.insert( "Expand HIR Annotate" );
+ g_debug_disable_map.insert( "Expand HIR Closures" );
+ g_debug_disable_map.insert( "Expand HIR Calls" );
+ g_debug_disable_map.insert( "Expand HIR VTables" );
+ g_debug_disable_map.insert( "Expand HIR Reborrows" );
+ g_debug_disable_map.insert( "Expand HIR ErasedType" );
+ g_debug_disable_map.insert( "Typecheck Expressions (validate)" );
+
+ g_debug_disable_map.insert( "Dump HIR" );
+ g_debug_disable_map.insert( "Lower MIR" );
+ g_debug_disable_map.insert( "MIR Validate" );
+ g_debug_disable_map.insert( "Dump MIR" );
+ g_debug_disable_map.insert( "Constant Evaluate Full" );
+ g_debug_disable_map.insert( "MIR Cleanup" );
+ g_debug_disable_map.insert( "MIR Optimise" );
+
+ g_debug_disable_map.insert( "HIR Serialise" );
+ g_debug_disable_map.insert( "Trans Enumerate" );
+ g_debug_disable_map.insert( "Trans Codegen" );
+
+ // Mutate this map using an environment variable
+ const char* debug_string = ::std::getenv("MRUSTC_DEBUG");
+ if( debug_string )
+ {
+ while( debug_string[0] )
+ {
+ const char* end = strchr(debug_string, ':');
+
+ if( end ) {
+ ::std::string s { debug_string, end };
+ // TODO: Emit a warning when this name wasn't in the map?
+ g_debug_disable_map.erase( s );
+ debug_string = end + 1;
+ }
+ else {
+ g_debug_disable_map.erase( debug_string );
+ break;
+ }
+ }
+ }
+}
+bool debug_enabled_update() {
+ if( g_debug_disable_map.count(g_cur_phase) != 0 ) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+bool debug_enabled()
+{
+ return g_debug_enabled;
+}
+::std::ostream& debug_output(int indent, const char* function)
+{
+ return ::std::cout << g_cur_phase << "- " << RepeatLitStr { " ", indent } << function << ": ";
+}
+
+struct ProgramParams
+{
+ enum eLastStage {
+ STAGE_PARSE,
+ STAGE_EXPAND,
+ STAGE_RESOLVE,
+ STAGE_TYPECK,
+ STAGE_BORROWCK,
+ STAGE_MIR,
+ STAGE_ALL,
+ } last_stage = STAGE_ALL;
+
+ ::std::string infile;
+ ::std::string outfile;
+ ::std::string output_dir = "";
+ const char *crate_path = ".";
+
+ ::AST::Crate::Type crate_type = ::AST::Crate::Type::Unknown;
+
+ ::std::set< ::std::string> features;
+
+ ProgramParams(int argc, char *argv[]);
+};
+
+template <typename Rv, typename Fcn>
+Rv CompilePhase(const char *name, Fcn f) {
+ ::std::cout << name << ": V V V" << ::std::endl;
+ g_cur_phase = name;
+ g_debug_enabled = debug_enabled_update();
+ auto start = clock();
+ auto rv = f();
+ auto end = clock();
+ g_cur_phase = "";
+ g_debug_enabled = debug_enabled_update();
+
+ ::std::cout <<"(" << ::std::fixed << ::std::setprecision(2) << static_cast<double>(end - start) / static_cast<double>(CLOCKS_PER_SEC) << " s) ";
+ ::std::cout << name << ": DONE";
+ ::std::cout << ::std::endl;
+ return rv;
+}
+template <typename Fcn>
+void CompilePhaseV(const char *name, Fcn f) {
+ CompilePhase<int>(name, [&]() { f(); return 0; });
+}
+
+/// main!
+int main(int argc, char *argv[])
+{
+ init_debug_list();
+ ProgramParams params(argc, argv);
+
+ // Set up cfg values
+ // TODO: Target spec
+ Cfg_SetFlag("unix");
+ Cfg_SetFlag("linux");
+ Cfg_SetValue("target_os", "linux");
+ Cfg_SetValue("target_pointer_width", "64");
+ Cfg_SetValue("target_endian", "little");
+ Cfg_SetValue("target_arch", "x86_64");
+ Cfg_SetValue("target_env", "gnu");
+ Cfg_SetValueCb("target_has_atomic", [](const ::std::string& s) {
+ if(s == "8") return true; // Has an atomic byte
+ if(s == "ptr") return true; // Has an atomic pointer-sized value
+ return false;
+ });
+ Cfg_SetValueCb("target_feature", [](const ::std::string& s) {
+ return false;
+ });
+ Cfg_SetValueCb("feature", [&params](const ::std::string& s) {
+ return params.features.count(s) != 0;
+ });
+
+
+
+ try
+ {
+ // Parse the crate into AST
+ AST::Crate crate = CompilePhase<AST::Crate>("Parse", [&]() {
+ return Parse_Crate(params.infile);
+ });
+
+ if( params.last_stage == ProgramParams::STAGE_PARSE ) {
+ return 0;
+ }
+
+ // Load external crates.
+ CompilePhaseV("LoadCrates", [&]() {
+ crate.load_externs();
+ });
+
+ // Iterate all items in the AST, applying syntax extensions
+ CompilePhaseV("Expand", [&]() {
+ Expand(crate);
+ });
+
+ // Extract the crate type and name from the crate attributes
+ auto crate_type = params.crate_type;
+ if( crate_type == ::AST::Crate::Type::Unknown ) {
+ crate_type = crate.m_crate_type;
+ }
+ if( crate_type == ::AST::Crate::Type::Unknown ) {
+ // Assume to be executable
+ crate_type = ::AST::Crate::Type::Executable;
+ }
+ crate.m_crate_type = crate_type;
+ auto crate_name = crate.m_crate_name;
+ if( crate_name == "" ) {
+ auto s = params.infile.find_last_of('/');
+ if( s == ::std::string::npos )
+ s = 0;
+ else
+ s += 1;
+ auto e = params.infile.find_first_of('.', s);
+ if( e == ::std::string::npos )
+ e = params.infile.size() - s;
+
+ crate_name = ::std::string(params.infile.begin() + s, params.infile.begin() + e);
+ for(auto& b : crate_name)
+ {
+ switch(b)
+ {
+ case '0' ... '9':
+ case 'A' ... 'Z':
+ case 'a' ... 'z':
+ case '_':
+ break;
+ case '-':
+ b = '_';
+ break;
+ default:
+ break;
+ }
+ }
+ crate.m_crate_name = crate_name;
+ }
+
+ if( params.outfile == "" ) {
+ switch( crate.m_crate_type )
+ {
+ case ::AST::Crate::Type::RustLib:
+ params.outfile = FMT(params.output_dir << "lib" << crate.m_crate_name << ".hir");
+ break;
+ case ::AST::Crate::Type::Executable:
+ params.outfile = FMT(params.output_dir << crate.m_crate_name);
+ break;
+ default:
+ params.outfile = FMT(params.output_dir << crate.m_crate_name << ".o");
+ break;
+ }
+ DEBUG("params.outfile = " << params.outfile);
+ }
+
+ // XXX: Dump crate before resolve
+ CompilePhaseV("Temp output - Parsed", [&]() {
+ Dump_Rust( FMT(params.outfile << "_0a_exp.rs").c_str(), crate );
+ });
+
+ if( params.last_stage == ProgramParams::STAGE_EXPAND ) {
+ return 0;
+ }
+
+ // Allocator and panic strategies
+ if( crate.m_crate_type == ::AST::Crate::Type::Executable )
+ {
+ // TODO: Detect if an allocator crate is already present.
+ crate.load_extern_crate(Span(), "alloc_system");
+ crate.load_extern_crate(Span(), "panic_abort");
+ }
+
+ // Resolve names to be absolute names (include references to the relevant struct/global/function)
+ // - This does name checking on types and free functions.
+ // - Resolves all identifiers/paths to references
+ CompilePhaseV("Resolve Use", [&]() {
+ Resolve_Use(crate); // - Absolutise and resolve use statements
+ });
+ CompilePhaseV("Resolve Index", [&]() {
+ Resolve_Index(crate); // - Build up a per-module index of avalable names (faster and simpler later resolve)
+ });
+ CompilePhaseV("Resolve Absolute", [&]() {
+ Resolve_Absolutise(crate); // - Convert all paths to Absolute or UFCS, and resolve variables
+ });
+
+ // XXX: Dump crate before HIR
+ CompilePhaseV("Temp output - Resolved", [&]() {
+ Dump_Rust( FMT(params.outfile << "_1_res.rs").c_str(), crate );
+ });
+
+ if( params.last_stage == ProgramParams::STAGE_RESOLVE ) {
+ return 0;
+ }
+
+ // --------------------------------------
+ // HIR Section
+ // --------------------------------------
+ // Construc the HIR from the AST
+ ::HIR::CratePtr hir_crate = CompilePhase< ::HIR::CratePtr>("HIR Lower", [&]() {
+ return LowerHIR_FromAST(mv$( crate ));
+ });
+ // Deallocate the original crate
+ crate = ::AST::Crate();
+
+ // Replace type aliases (`type`) into the actual type
+ CompilePhaseV("Resolve Type Aliases", [&]() {
+ ConvertHIR_ExpandAliases(*hir_crate);
+ });
+ // Set up bindings and other useful information.
+ CompilePhaseV("Resolve Bind", [&]() {
+ ConvertHIR_Bind(*hir_crate);
+ });
+ CompilePhaseV("Resolve UFCS paths", [&]() {
+ ConvertHIR_ResolveUFCS(*hir_crate);
+ });
+ CompilePhaseV("Resolve HIR Markings", [&]() {
+ ConvertHIR_Markings(*hir_crate);
+ });
+ // Basic constant evalulation (intergers/floats only)
+ CompilePhaseV("Constant Evaluate", [&]() {
+ ConvertHIR_ConstantEvaluate(*hir_crate);
+ });
+
+ CompilePhaseV("Dump HIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
+ HIR_Dump( os, *hir_crate );
+ });
+
+ // === Type checking ===
+ // - This can recurse and call the MIR lower to evaluate constants
+
+ // Check outer items first (types of constants/functions/statics/impls/...)
+ // - Doesn't do any expressions except those in types
+ CompilePhaseV("Typecheck Outer", [&]() {
+ Typecheck_ModuleLevel(*hir_crate);
+ });
+ // Check the rest of the expressions (including function bodies)
+ CompilePhaseV("Typecheck Expressions", [&]() {
+ Typecheck_Expressions(*hir_crate);
+ });
+ // === HIR Expansion ===
+ // Annotate how each node's result is used
+ CompilePhaseV("Expand HIR Annotate", [&]() {
+ HIR_Expand_AnnotateUsage(*hir_crate);
+ });
+ // - Now that all types are known, closures can be desugared
+ CompilePhaseV("Expand HIR Closures", [&]() {
+ HIR_Expand_Closures(*hir_crate);
+ });
+ // - Construct VTables for all traits and impls.
+ CompilePhaseV("Expand HIR VTables", [&]() { HIR_Expand_VTables(*hir_crate); });
+ // - And calls can be turned into UFCS
+ CompilePhaseV("Expand HIR Calls", [&]() {
+ HIR_Expand_UfcsEverything(*hir_crate);
+ });
+ CompilePhaseV("Expand HIR Reborrows", [&]() {
+ HIR_Expand_Reborrows(*hir_crate);
+ });
+ CompilePhaseV("Expand HIR ErasedType", [&]() {
+ HIR_Expand_ErasedType(*hir_crate);
+ });
+ CompilePhaseV("Dump HIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
+ HIR_Dump( os, *hir_crate );
+ });
+ // - Ensure that typeck worked (including Fn trait call insertion etc)
+ CompilePhaseV("Typecheck Expressions (validate)", [&]() {
+ Typecheck_Expressions_Validate(*hir_crate);
+ });
+
+ if( params.last_stage == ProgramParams::STAGE_TYPECK ) {
+ return 0;
+ }
+
+ // Lower expressions into MIR
+ CompilePhaseV("Lower MIR", [&]() {
+ HIR_GenerateMIR(*hir_crate);
+ });
+
+ CompilePhaseV("Dump MIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_3_mir.rs"));
+ MIR_Dump( os, *hir_crate );
+ });
+
+ // Validate the MIR
+ CompilePhaseV("MIR Validate", [&]() {
+ MIR_CheckCrate(*hir_crate);
+ });
+
+ // Second shot of constant evaluation (with full type information)
+ CompilePhaseV("Constant Evaluate Full", [&]() {
+ ConvertHIR_ConstantEvaluateFull(*hir_crate);
+ });
+ CompilePhaseV("Dump HIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
+ HIR_Dump( os, *hir_crate );
+ });
+
+ // - Expand constants in HIR and virtualise calls
+ CompilePhaseV("MIR Cleanup", [&]() {
+ MIR_CleanupCrate(*hir_crate);
+ });
+ // Optimise the MIR
+ CompilePhaseV("MIR Optimise", [&]() {
+ MIR_OptimiseCrate(*hir_crate);
+ });
+
+ CompilePhaseV("Dump MIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_3_mir.rs"));
+ MIR_Dump( os, *hir_crate );
+ });
+
+ if( params.last_stage == ProgramParams::STAGE_MIR ) {
+ return 0;
+ }
+
+ // TODO: Pass to mark items that are
+ // - Signature Exportable (public)
+ // - MIR Exportable (public generic, #[inline], or used by a either of those)
+ // - Require codegen (public or used by an exported function)
+
+ // Generate code for non-generic public items (if requested)
+ switch( crate_type )
+ {
+ case ::AST::Crate::Type::Unknown:
+ // ERROR?
+ break;
+ case ::AST::Crate::Type::RustLib:
+ // Save a loadable HIR dump
+ CompilePhaseV("HIR Serialise", [&]() {
+ //HIR_Serialise(params.outfile + ".meta", *hir_crate);
+ HIR_Serialise(params.outfile, *hir_crate);
+ });
+ //TransList items;
+ //CompilePhaseV("Trans Enumerate", [&]() { Trans_Enumerate_Public(*hir_crate); });
+ //CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile + ".o", *hir_crate, items); });
+ // Generate a .o
+ //HIR_Codegen_Lib(params.outfile + ".o", *hir_crate);
+ // Link metatdata and object into a .rlib
+ break;
+ case ::AST::Crate::Type::RustDylib:
+ // Save a loadable HIR dump
+ CompilePhaseV("HIR Serialise", [&]() { HIR_Serialise(params.outfile, *hir_crate); });
+ // - Enumerate codegen for visible and non-generic items
+ //TransList items;
+ //CompilePhaseV("Trans Enumerate", [&]() { Trans_Enumerate_Public(*hir_crate); });
+ //CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile, *hir_crate, items); });
+ // Generate a .so/.dll
+ // TODO: Codegen and include the metadata in a non-loadable segment
+ break;
+ case ::AST::Crate::Type::CDylib:
+ // Generate a .so/.dll
+ break;
+ case ::AST::Crate::Type::Executable:
+ // Generate a binary
+ // - Enumerate items for translation
+ TransList items = CompilePhase<TransList>("Trans Enumerate", [&]() { return Trans_Enumerate_Main(*hir_crate); });
+ // - Perform codegen
+ CompilePhaseV("Trans Codegen", [&]() { Trans_Codegen(params.outfile, *hir_crate, items); });
+ // - Invoke linker?
+ break;
+ }
+ }
+ catch(unsigned int) {}
+ //catch(const CompileError::Base& e)
+ //{
+ // ::std::cerr << "Parser Error: " << e.what() << ::std::endl;
+ // return 2;
+ //}
+ //catch(const ::std::exception& e)
+ //{
+ // ::std::cerr << "Misc Error: " << e.what() << ::std::endl;
+ // return 2;
+ //}
+ //catch(const char* e)
+ //{
+ // ::std::cerr << "Internal Compiler Error: " << e << ::std::endl;
+ // return 2;
+ //}
+ 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] != '-' )
+ {
+ if( this->infile != "" )
+ ;
+ this->infile = arg;
+
+ if( this->infile == "" )
+ ;
+ }
+ else if( arg[1] != '-' )
+ {
+ arg ++; // eat '-'
+ for( ; *arg; arg ++ )
+ {
+ switch(*arg)
+ {
+ // "-o <file>" : 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 ) {
+ ::std::cerr << "Flag --crate-path requires an argument" << ::std::endl;
+ exit(1);
+ }
+ this->crate_path = argv[++i];
+ }
+ else if( strcmp(arg, "--out-dir") == 0 ) {
+ if( i == argc - 1 ) {
+ ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl;
+ exit(1);
+ }
+ this->output_dir = argv[++i];
+ if( this->output_dir == "" )
+ ;
+ if( this->output_dir.back() != '/' )
+ this->output_dir += '/';
+ }
+ else if( strcmp(arg, "--crate-type") == 0 ) {
+ if( i == argc - 1 ) {
+ ::std::cerr << "Flag --crate-type requires an argument" << ::std::endl;
+ exit(1);
+ }
+ const char* type_str = argv[++i];
+
+ if( strcmp(type_str, "rlib") == 0 ) {
+ this->crate_type = ::AST::Crate::Type::RustLib;
+ }
+ else {
+ ::std::cerr << "Unknown value for --crate-type" << ::std::endl;
+ exit(1);
+ }
+ }
+ else if( strcmp(arg, "--cfg") == 0 ) {
+ if( i == argc - 1 ) {
+ ::std::cerr << "Flag --cfg requires an argument" << ::std::endl;
+ exit(1);
+ }
+ char* opt_and_val = argv[++i];
+ if( char* p = strchr(opt_and_val, '=') ) {
+ *p = '\0';
+ const char* opt = opt_and_val;
+ const char* val = p + 1;
+ if( ::std::strcmp(opt, "feature") == 0 ) {
+ this->features.insert( ::std::string(val) );
+ }
+ else {
+ Cfg_SetValue(opt, val);
+ }
+ }
+ else {
+ Cfg_SetFlag(opt_and_val);
+ }
+ }
+ else if( strcmp(arg, "--stop-after") == 0 ) {
+ if( i == argc - 1 ) {
+ ::std::cerr << "Flag --stop-after requires an argument" << ::std::endl;
+ exit(1);
+ }
+
+ arg = argv[++i];
+ if( strcmp(arg, "parse") == 0 )
+ this->last_stage = STAGE_PARSE;
+ else if( strcmp(arg, "expand") == 0 )
+ this->last_stage = STAGE_EXPAND;
+ else if( strcmp(arg, "resolve") == 0 )
+ this->last_stage = STAGE_RESOLVE;
+ else if( strcmp(arg, "mir") == 0 )
+ this->last_stage = STAGE_MIR;
+ else if( strcmp(arg, "ALL") == 0 )
+ this->last_stage = STAGE_ALL;
+ else {
+ ::std::cerr << "Unknown argument to --stop-after : '" << arg << "'" << ::std::endl;
+ exit(1);
+ }
+ }
+ else {
+ ::std::cerr << "Unknown option '" << arg << "'" << ::std::endl;
+ exit(1);
+ }
+ }
+ }
+}
+
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 65473b50..186e93fb 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -35,10 +35,10 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
continue ;
}
visited_bbs[block] = true;
-
-
+
+
state.set_cur_stmt_term(block);
-
+
#define PUSH_BB(idx, desc) do {\
if( !(idx < fcn.blocks.size() ) ) MIR_BUG(state, "Invalid target block - " << desc << " bb" << idx);\
if( visited_bbs[idx] == false ) {\
@@ -81,7 +81,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
DEBUG("- Function doesn't return.");
}
}
-
+
// [ValState] = Value state tracking (use after move, uninit, ...)
// - [ValState] No drops or usage of uninitalised values (Uninit, Moved, or Dropped)
// - [ValState] Temporaries are write-once.
@@ -98,7 +98,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
::std::vector<State> arguments;
::std::vector<State> temporaries;
::std::vector<State> variables;
-
+
ValStates() {}
ValStates(size_t n_args, size_t n_temps, size_t n_vars):
arguments(n_args, State::Valid),
@@ -106,11 +106,11 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
variables(n_vars)
{
}
-
+
bool empty() const {
return arguments.empty() && temporaries.empty() && variables.empty();
}
-
+
bool merge(ValStates& other)
{
if( this->empty() )
@@ -131,7 +131,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
return rv;
}
}
-
+
void mark_validity(const ::MIR::TypeResolve& state, const ::MIR::LValue& lv, bool is_valid)
{
TU_MATCH_DEF( ::MIR::LValue, (lv), (e),
@@ -228,7 +228,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
auto val_state = mv$( to_visit_blocks.back().second );
to_visit_blocks.pop_back();
assert(block < fcn.blocks.size());
-
+
// 1. Apply current state to `block_start_states` (merging if needed)
// - If no change happened, skip.
if( ! block_start_states.at(block).merge( val_state ) ) {
@@ -241,7 +241,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
{
const auto& stmt = bb.statements[stmt_idx];
state.set_cur_stmt(block, stmt_idx);
-
+
if( stmt.is_Drop() )
{
// Invalidate the slot
@@ -366,14 +366,14 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
{
const auto& stmt = bb.statements[stmt_idx];
state.set_cur_stmt(bb_idx, stmt_idx);
-
+
switch( stmt.tag() )
{
case ::MIR::Statement::TAGDEAD:
throw "";
case ::MIR::Statement::TAG_Assign: {
const auto& a = stmt.as_Assign();
-
+
auto check_type = [&](const auto& src_ty) {
::HIR::TypeRef tmp;
const auto& dst_ty = state.get_lvalue_type(tmp, a.dst);
@@ -528,7 +528,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
break;
}
}
-
+
state.set_cur_stmt_term(bb_idx);
TU_MATCH(::MIR::Terminator, (bb.terminator), (e),
(Incomplete,
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 972914a6..5744a033 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -23,32 +23,32 @@ struct MirMutator
unsigned int cur_block;
unsigned int cur_stmt;
mutable ::std::vector< ::MIR::Statement> new_statements;
-
+
MirMutator(::MIR::Function& fcn, unsigned int bb, unsigned int stmt):
m_fcn(fcn),
cur_block(bb), cur_stmt(stmt)
{
}
-
+
::MIR::LValue new_temporary(::HIR::TypeRef ty)
{
auto rv = ::MIR::LValue::make_Temporary({ static_cast<unsigned int>(m_fcn.temporaries.size()) });
m_fcn.temporaries.push_back( mv$(ty) );
return rv;
}
-
+
void push_statement(::MIR::Statement stmt)
{
new_statements.push_back( mv$(stmt) );
}
-
+
::MIR::LValue in_temporary(::HIR::TypeRef ty, ::MIR::RValue val)
{
auto rv = this->new_temporary( mv$(ty) );
push_statement( ::MIR::Statement::make_Assign({ rv.clone(), mv$(val) }) );
return rv;
}
-
+
decltype(new_statements.begin()) flush()
{
DEBUG("flush - " << cur_block << "/" << cur_stmt);
@@ -101,37 +101,37 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
MIR_ASSERT(state, lit.is_List(), "Non-list literal for Tuple - " << lit);
const auto& vals = lit.as_List();
MIR_ASSERT(state, vals.size() == te.size(), "Literal size mismatched with tuple size");
-
+
::std::vector< ::MIR::LValue> lvals;
lvals.reserve( vals.size() );
-
+
for(unsigned int i = 0; i < vals.size(); i ++)
{
auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, vals[i], te[i].clone(), ::HIR::GenericPath());
lvals.push_back( mutator.in_temporary( mv$(te[i]), mv$(rval)) );
}
-
+
return ::MIR::RValue::make_Tuple({ mv$(lvals) });
),
(Array,
MIR_ASSERT(state, lit.is_List(), "Non-list literal for Array - " << lit);
const auto& vals = lit.as_List();
-
+
MIR_ASSERT(state, vals.size() == te.size_val, "Literal size mismatched with array size");
-
+
bool is_all_same = false;
if( vals.size() > 1 )
{
is_all_same = true;
for(unsigned int i = 1; i < vals.size(); i ++) {
-
+
if( vals[i] != vals[0] ) {
is_all_same = false;
break ;
}
}
}
-
+
if( is_all_same )
{
auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, vals[0], te.inner->clone(), ::HIR::GenericPath());
@@ -142,13 +142,13 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
{
::std::vector< ::MIR::LValue> lvals;
lvals.reserve( vals.size() );
-
+
for(const auto& val: vals)
{
auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, val, te.inner->clone(), ::HIR::GenericPath());
lvals.push_back( mutator.in_temporary(te.inner->clone(), mv$(rval)) );
}
-
+
return ::MIR::RValue::make_Array({ mv$(lvals) });
}
),
@@ -157,9 +157,9 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
{
const auto& str = *te.binding.as_Struct();
const auto& vals = lit.as_List();
-
+
auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, tpl); };
-
+
::std::vector< ::MIR::LValue> lvals;
TU_MATCHA( (str.m_data), (se),
(Unit,
@@ -190,9 +190,9 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
{
const auto& enm = *te.binding.as_Enum();
const auto& lit_var = lit.as_Variant();
-
+
auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, enm.m_params, te.path.m_data.as_Generic().m_params, tpl); };
-
+
::std::vector< ::MIR::LValue> lvals;
MIR_ASSERT(state, lit_var.idx < enm.m_variants.size(), "Variant index out of range");
TU_MATCHA( (enm.m_variants[lit_var.idx].second), (ve),
@@ -254,7 +254,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
),
(Pointer,
if( lit.is_BorrowOf() ) {
- // TODO:
+ // TODO:
MIR_TODO(state, "BorrowOf into pointer - " << lit << " into " << ty);
}
else {
@@ -272,11 +272,11 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
const auto& ty = state.get_static_type(tmp, path);
MIR_ASSERT(state, ty.m_data.is_Array(), "BorrowOf returning slice not of an array, instead " << ty);
unsigned int size = ty.m_data.as_Array().size_val;
-
+
auto ptr_type = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared,
(&ty == &tmp ? mv$(tmp) : ty.clone())
);
-
+
auto ptr_lval = mutator.in_temporary( mv$(ptr_type), ::MIR::Constant::make_ItemAddr(path.clone()) );
auto size_lval = mutator.in_temporary( ::HIR::CoreType::Usize, ::MIR::Constant::make_Uint(size) );
return ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) });
@@ -317,7 +317,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
{
assert( te.m_trait.m_trait_ptr );
const auto& trait = *te.m_trait.m_trait_ptr;
-
+
// 1. Get the vtable index for this function
auto it = trait.m_value_indexes.find( pe.item );
while( it != trait.m_value_indexes.end() )
@@ -333,7 +333,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
if( it == trait.m_value_indexes.end() || it->first != pe.item )
BUG(sp, "Calling method '" << pe.item << "' from " << pe.trait << " through " << te.m_trait.m_path << " which isn't in the vtable");
unsigned int vtable_idx = it->second.first;
-
+
// 2. Load from the vtable
auto vtable_ty_spath = te.m_trait.m_path.m_path;
vtable_ty_spath.m_components.back() += "#vtable";
@@ -351,15 +351,15 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
::HIR::BorrowType::Shared,
::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref )
);
-
+
// Allocate a temporary for the vtable pointer itself
auto vtable_lv = mutator.new_temporary( mv$(vtable_ty) );
// - Load the vtable and store it
auto vtable_rval = ::MIR::RValue::make_DstMeta({ ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }) });
mutator.push_statement( ::MIR::Statement::make_Assign({ vtable_lv.clone(), mv$(vtable_rval) }) );
-
+
auto fcn_lval = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(vtable_lv) })), vtable_idx });
-
+
::HIR::TypeRef tmp;
const auto& ty = state.get_lvalue_type(tmp, fcn_lval);
const auto& receiver = ty.m_data.as_Function().m_arg_types.at(0);
@@ -368,7 +368,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
// TODO: If the receiver is Box, create a Box<()> as the value.
// - Requires de/restructuring the Box same as CoerceUnsized
// - Can use the `coerce_unsized_index` field too
-
+
struct H {
static ::MIR::LValue get_unit_ptr(const ::MIR::TypeResolve& state, MirMutator& mutator, ::HIR::TypeRef ty, ::MIR::LValue lv)
{
@@ -407,7 +407,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
}
)
)
-
+
auto new_path = ty_path.clone();
return mutator.in_temporary( mv$(ty), ::MIR::RValue::make_Struct({ mv$(new_path), ~0u, mv$(vals) }) );
}
@@ -424,18 +424,18 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
}
}
};
-
+
receiver_lvp = H::get_unit_ptr(state,mutator, receiver.clone(), receiver_lvp.clone());
}
else
{
auto ptr_rval = ::MIR::RValue::make_DstPtr({ ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }) });
-
+
auto ptr_lv = mutator.new_temporary( ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit()) );
mutator.push_statement( ::MIR::Statement::make_Assign({ ptr_lv.clone(), mv$(ptr_rval) }) );
receiver_lvp = mv$(ptr_lv);
}
-
+
// Update the terminator with the new information.
return fcn_lval;
}
@@ -457,7 +457,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
// Source must be Path and Unsize
if( de.binding.is_Opaque() )
return false;
-
+
MIR_ASSERT(state, src_ty.m_data.is_Path(), "Unsize to path from non-path - " << src_ty);
const auto& se = src_ty.m_data.as_Path();
MIR_ASSERT(state, de.binding.tag() == se.binding.tag(), "Unsize between mismatched types - " << dst_ty << " and " << src_ty);
@@ -465,10 +465,10 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
MIR_ASSERT(state, de.binding.as_Struct() == se.binding.as_Struct(), "Unsize between mismatched types - " << dst_ty << " and " << src_ty);
const auto& str = *de.binding.as_Struct();
MIR_ASSERT(state, str.m_markings.unsized_field != ~0u, "Unsize on type that doesn't implement have a ?Sized field - " << dst_ty);
-
+
auto monomorph_cb_d = monomorphise_type_get_cb(state.sp, nullptr, &de.path.m_data.as_Generic().m_params, nullptr);
auto monomorph_cb_s = monomorphise_type_get_cb(state.sp, nullptr, &se.path.m_data.as_Generic().m_params, nullptr);
-
+
// Return GetMetadata on the inner type
TU_MATCHA( (str.m_data), (se),
(Unit,
@@ -478,14 +478,14 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
const auto& ty_tpl = se.at( str.m_markings.unsized_field ).ent;
auto ty_d = monomorphise_type_with(state.sp, ty_tpl, monomorph_cb_d, false);
auto ty_s = monomorphise_type_with(state.sp, ty_tpl, monomorph_cb_s, false);
-
+
return MIR_Cleanup_Unsize_GetMetadata(state, mutator, ty_d, ty_s, ptr_value, out_meta_val,out_meta_ty,out_src_is_dst);
),
(Named,
const auto& ty_tpl = se.at( str.m_markings.unsized_field ).second.ent;
auto ty_d = monomorphise_type_with(state.sp, ty_tpl, monomorph_cb_d, false);
auto ty_s = monomorphise_type_with(state.sp, ty_tpl, monomorph_cb_s, false);
-
+
return MIR_Cleanup_Unsize_GetMetadata(state, mutator, ty_d, ty_s, ptr_value, out_meta_val,out_meta_ty,out_src_is_dst);
)
)
@@ -504,9 +504,9 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
{
// HACK: FixedSizeArray uses `A: Unsize<[T]>` which will lead to the above code not working (as the size isn't known).
// - Maybe _Meta on the `&A` would work as a stopgap (since A: Sized, it won't collide with &[T] or similar)
-
+
return false;
-
+
//out_meta_ty = ::HIR::CoreType::Usize;
//out_meta_val = ::MIR::RValue::make_DstMeta({ ptr_value.clone() });
//return true;
@@ -517,9 +517,9 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
}
),
(TraitObject,
-
+
auto ty_unit_ptr = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit());
-
+
// No data trait, vtable is a null unit pointer.
// - Shouldn't the vtable be just unit?
// - Codegen assumes it's a pointer.
@@ -548,9 +548,9 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
vtable_params.m_types[idx] = ty_b.second.clone();
}
auto vtable_type = ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref );
-
+
out_meta_ty = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, mv$(vtable_type));
-
+
// If the data trait hasn't changed, return the vtable pointer
if( src_ty.m_data.is_TraitObject() )
{
@@ -572,7 +572,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
::MIR::RValue MIR_Cleanup_Unsize(const ::MIR::TypeResolve& state, MirMutator& mutator, const ::HIR::TypeRef& dst_ty, const ::HIR::TypeRef& src_ty_inner, ::MIR::LValue ptr_value)
{
const auto& dst_ty_inner = (dst_ty.m_data.is_Borrow() ? *dst_ty.m_data.as_Borrow().inner : *dst_ty.m_data.as_Pointer().inner);
-
+
::HIR::TypeRef meta_type;
::MIR::RValue meta_value;
bool source_is_dst = false;
@@ -585,7 +585,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
auto ty_unit_ptr = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit());
auto deref_ptr_val = ::MIR::LValue::make_Deref({ box$(ptr_value) });
auto thin_ptr_lval = mutator.in_temporary( mv$(ty_unit_ptr), ::MIR::RValue::make_DstPtr({ mv$(deref_ptr_val) }) );
-
+
return ::MIR::RValue::make_MakeDst({ mv$(thin_ptr_lval), mv$(meta_lval) });
}
else
@@ -610,7 +610,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
MIR_ASSERT(state, src_ty.m_data.is_Path(), "CoerceUnsized to Path must have a Path source - " << src_ty << " to " << dst_ty);
const auto& dte = dst_ty.m_data.as_Path();
const auto& ste = src_ty.m_data.as_Path();
-
+
// - Types must differ only by a single field, and be from the same definition
MIR_ASSERT(state, dte.binding.is_Struct(), "Note, can't CoerceUnsized non-structs");
MIR_ASSERT(state, dte.binding.tag() == ste.binding.tag(),
@@ -620,10 +620,10 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
const auto& str = *dte.binding.as_Struct();
MIR_ASSERT(state, str.m_markings.coerce_unsized_index != ~0u,
"Struct " << src_ty << " doesn't impl CoerceUnsized");
-
+
auto monomorph_cb_d = monomorphise_type_get_cb(state.sp, nullptr, &dte.path.m_data.as_Generic().m_params, nullptr);
auto monomorph_cb_s = monomorphise_type_get_cb(state.sp, nullptr, &ste.path.m_data.as_Generic().m_params, nullptr);
-
+
// - Destructure and restrucure with the unsized fields
::std::vector<::MIR::LValue> ents;
TU_MATCHA( (str.m_data), (se),
@@ -638,19 +638,19 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
{
auto ty_d = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_d, false);
auto ty_s = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_s, false);
-
+
auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i }));
auto new_lval = mutator.in_temporary( mv$(ty_d), mv$(new_rval) );
-
+
ents.push_back( mv$(new_lval) );
}
else if( state.m_resolve.is_type_phantom_data( se[i].ent ) )
{
auto ty_d = monomorphise_type_with(state.sp, se[i].ent, monomorph_cb_d, false);
-
+
auto new_rval = ::MIR::RValue::make_Cast({ ::MIR::LValue::make_Field({ box$(value.clone()), i }), ty_d.clone() });
auto new_lval = mutator.in_temporary( mv$(ty_d), mv$(new_rval) );
-
+
ents.push_back( mv$(new_lval) );
}
else
@@ -667,20 +667,20 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
{
auto ty_d = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_d, false);
auto ty_s = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_s, false);
-
+
auto new_rval = MIR_Cleanup_CoerceUnsized(state, mutator, ty_d, ty_s, ::MIR::LValue::make_Field({ box$(value.clone()), i }));
auto new_lval = mutator.new_temporary( mv$(ty_d) );
mutator.push_statement( ::MIR::Statement::make_Assign({ new_lval.clone(), mv$(new_rval) }) );
-
+
ents.push_back( mv$(new_lval) );
}
else if( state.m_resolve.is_type_phantom_data( se[i].second.ent ) )
{
auto ty_d = monomorphise_type_with(state.sp, se[i].second.ent, monomorph_cb_d, false);
-
+
auto new_rval = ::MIR::RValue::make_Cast({ ::MIR::LValue::make_Field({ box$(value.clone()), i }), ty_d.clone() });
auto new_lval = mutator.in_temporary( mv$(ty_d), mv$(new_rval) );
-
+
ents.push_back( mv$(new_lval) );
}
else
@@ -692,22 +692,22 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
)
return ::MIR::RValue::make_Struct({ dte.path.m_data.as_Generic().clone(), ~0u, mv$(ents) });
}
-
+
if( dst_ty.m_data.is_Borrow() )
{
MIR_ASSERT(state, src_ty.m_data.is_Borrow(), "CoerceUnsized to Borrow must have a Borrow source - " << src_ty << " to " << dst_ty);
const auto& ste = src_ty.m_data.as_Borrow();
-
+
return MIR_Cleanup_Unsize(state, mutator, dst_ty, *ste.inner, mv$(value));
}
-
+
// Pointer Coercion - Downcast and unsize
if( dst_ty.m_data.is_Pointer() )
{
MIR_ASSERT(state, src_ty.m_data.is_Pointer(), "CoerceUnsized to Pointer must have a Pointer source - " << src_ty << " to " << dst_ty);
const auto& dte = dst_ty.m_data.as_Pointer();
const auto& ste = src_ty.m_data.as_Pointer();
-
+
if( dte.type == ste.type )
{
// TODO: Use unsize code above
@@ -717,11 +717,11 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
{
MIR_ASSERT(state, *dte.inner == *ste.inner, "TODO: Can pointer CoerceUnsized unsize? " << src_ty << " to " << dst_ty);
MIR_ASSERT(state, dte.type < ste.type, "CoerceUnsize attempting to raise pointer type");
-
+
return ::MIR::RValue::make_Cast({ mv$(value), dst_ty.clone() });
}
}
-
+
MIR_BUG(state, "Unknown CoerceUnsized target " << dst_ty << " from " << src_ty);
throw "";
}
@@ -788,7 +788,7 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::
)
tmp = monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, *ty_tpl);
typ = &tmp;
-
+
auto new_lval = ::MIR::LValue::make_Field({ mv$(le.val), 0 });
le.val = box$(new_lval);
}
@@ -803,7 +803,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
Span sp;
TRACE_FUNCTION_F(path);
::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
-
+
MirMutator mutator { fcn, 0, 0 };
for(auto& block : fcn.blocks)
{
@@ -811,7 +811,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
{
state.set_cur_stmt( mutator.cur_block, mutator.cur_stmt );
auto& stmt = *it;
-
+
// 1. Visit all LValues for box deref hackery
TU_MATCHA( (stmt), (se),
(Drop,
@@ -874,7 +874,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
if( stmt.is_Assign() )
{
auto& se = stmt.as_Assign();
-
+
TU_IFLET( ::MIR::RValue, se.src, Constant, e,
// TODO: Replace `Const` with actual values
TU_IFLET( ::MIR::Constant, e, Const, ce,
@@ -887,14 +887,14 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
}
)
)
-
+
if( se.src.is_Borrow() && se.src.as_Borrow().val.is_Field() )
{
auto& e = se.src.as_Borrow();
// TODO: If borrowing a !Sized value via a field access, create the DST
::HIR::TypeRef tmp;
const auto& src_ty = state.get_lvalue_type(tmp, e.val);
-
+
if( !resolve.type_is_sized(sp, src_ty) && !src_ty.m_data.is_Generic() )
{
auto ty_unit_ptr = ::HIR::TypeRef::new_borrow( e.type, ::HIR::TypeRef::new_unit() );
@@ -909,24 +909,24 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
while( lv->is_Field() )
lv = &*lv->as_Field().val;
MIR_ASSERT(state, lv->is_Deref(), "Access of !Sized field not via a deref");
-
+
const auto& dst_val_lval = *lv;
-
+
auto meta_rval = ::MIR::RValue::make_DstMeta({ dst_val_lval.clone() });
// TODO: How can the thin pointer to the field be obtained without tripping this twice?
auto ptr_rval = mv$( se.src );
-
+
// TODO: Get the metadata type.
auto meta_ty = ::HIR::TypeRef( ::HIR::CoreType::Usize );
auto meta_lval = mutator.in_temporary( mv$(meta_ty), mv$(meta_rval) );
-
+
// HACK: Store the pointer as &()
auto ptr_lval = mutator.in_temporary( mv$(ty_unit_ptr), mv$(ptr_rval) );
se.src = ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(meta_lval) });
}
}
}
-
+
if( se.src.is_Cast() )
{
auto& e = se.src.as_Cast();
@@ -943,7 +943,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
// Casts to PhantomData are only valid from PhandomData, and are added by _CoerceUnsized
else if( state.m_resolve.is_type_phantom_data(e.type) )
{
- // Leave
+ // Leave
MIR_ASSERT(state, state.m_resolve.is_type_phantom_data(src_ty) != nullptr, "PhandomData can only cast from PhantomData");
}
// - CoerceUnsized should re-create the inner type if known.
@@ -966,15 +966,15 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
}
}
}
-
+
DEBUG(it - block.statements.begin());
it = mutator.flush();
DEBUG(it - block.statements.begin());
mutator.cur_stmt += 1;
}
-
+
state.set_cur_stmt_term( mutator.cur_block );
-
+
TU_MATCHA( (block.terminator), (e),
(Incomplete,
),
@@ -1001,9 +1001,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
MIR_Cleanup_LValue(state, mutator, lv);
)
)
-
+
TU_IFLET( ::MIR::Terminator, block.terminator, Call, e,
-
+
TU_IFLET( ::MIR::CallTarget, e.fcn, Path, path,
// Detect calling `<Trait as Trait>::method()` and replace with vtable call
if( path.m_data.is_UfcsKnown() && path.m_data.as_UfcsKnown().type->m_data.is_TraitObject() )
@@ -1024,7 +1024,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
e.fcn = mv$(tgt_lvalue);
}
}
-
+
if( path.m_data.is_UfcsKnown() && path.m_data.as_UfcsKnown().type->m_data.is_Function() )
{
const auto& pe = path.m_data.as_UfcsKnown();
@@ -1034,9 +1034,9 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
MIR_ASSERT(state, e.args.size() == 2, "Fn* call requires two arguments");
auto fcn_lvalue = mv$(e.args[0]);
auto args_lvalue = mv$(e.args[1]);
-
+
DEBUG("Convert function pointer call");
-
+
e.args.clear();
e.args.reserve( fcn_ty.m_arg_types.size() );
for(unsigned int i = 0; i < fcn_ty.m_arg_types.size(); i ++)
@@ -1048,7 +1048,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
}
)
)
-
+
mutator.flush();
mutator.cur_block += 1;
mutator.cur_stmt = 0;
diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp
index d1fdc503..555093f2 100644
--- a/src/mir/dump.cpp
+++ b/src/mir/dump.cpp
@@ -10,14 +10,14 @@
#include "mir.hpp"
namespace {
-
+
class TreeVisitor:
public ::HIR::Visitor
{
::std::ostream& m_os;
unsigned int m_indent_level;
bool m_short_item_name = false;
-
+
public:
TreeVisitor(::std::ostream& os):
m_os(os),
@@ -28,7 +28,7 @@ namespace {
void visit_type_impl(::HIR::TypeImpl& impl) override
{
m_short_item_name = true;
-
+
m_os << indent() << "impl" << impl.m_params.fmt_args() << " " << impl.m_type << "\n";
if( ! impl.m_params.m_bounds.empty() )
{
@@ -39,13 +39,13 @@ namespace {
::HIR::Visitor::visit_type_impl(impl);
dec_indent();
m_os << indent() << "}\n";
-
+
m_short_item_name = false;
}
virtual void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override
{
m_short_item_name = true;
-
+
m_os << indent() << "impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type << "\n";
if( ! impl.m_params.m_bounds.empty() )
{
@@ -56,28 +56,28 @@ namespace {
::HIR::Visitor::visit_trait_impl(trait_path, impl);
dec_indent();
m_os << indent() << "}\n";
-
+
m_short_item_name = false;
}
void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl) override
{
m_short_item_name = true;
-
+
m_os << indent() << "impl" << impl.m_params.fmt_args() << " " << (impl.is_positive ? "" : "!") << trait_path << impl.m_trait_args << " for " << impl.m_type << "\n";
if( ! impl.m_params.m_bounds.empty() )
{
m_os << indent() << " " << impl.m_params.fmt_bounds() << "\n";
}
m_os << indent() << "{ }\n";
-
+
m_short_item_name = false;
}
-
+
// - Type Items
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override
{
m_short_item_name = true;
-
+
m_os << indent() << "trait " << p << item.m_params.fmt_args() << "\n";
if( ! item.m_params.m_bounds.empty() )
{
@@ -88,7 +88,7 @@ namespace {
::HIR::Visitor::visit_trait(p, item);
dec_indent();
m_os << indent() << "}\n";
-
+
m_short_item_name = false;
}
@@ -119,7 +119,7 @@ namespace {
{
m_os << indent() << " " << item.m_params.fmt_bounds() << "\n";
}
-
+
if( item.m_code )
{
m_os << indent() << "{\n";
@@ -133,8 +133,8 @@ namespace {
m_os << indent() << " ;\n";
}
}
-
-
+
+
void dump_mir(const ::MIR::Function& fcn)
{
for(unsigned int i = 0; i < fcn.named_variables.size(); i ++)
@@ -145,19 +145,19 @@ namespace {
{
m_os << indent() << "let tmp$" << i << ": " << fcn.temporaries[i] << ";\n";
}
-
+
#define FMT_M(x) FMT_CB(os, this->fmt_val(os,x);)
for(unsigned int i = 0; i < fcn.blocks.size(); i ++)
{
const auto& block = fcn.blocks[i];
DEBUG("BB" << i);
-
+
m_os << indent() << "bb" << i << ": {\n";
inc_indent();
for(const auto& stmt : block.statements)
{
m_os << indent();
-
+
TU_MATCHA( (stmt), (e),
(Assign,
DEBUG("- Assign " << e.dst << " = " << e.src);
@@ -169,7 +169,7 @@ namespace {
)
)
}
-
+
m_os << indent();
TU_MATCHA( (block.terminator), (e),
(Incomplete,
@@ -217,7 +217,7 @@ namespace {
)
dec_indent();
m_os << indent() << "}\n";
-
+
m_os.flush();
}
#undef FMT
@@ -329,14 +329,14 @@ namespace {
case ::MIR::eBinOp::MUL_OV: os << "MUL_OV"; break;
case ::MIR::eBinOp::DIV_OV: os << "DIV_OV"; break;
//case ::MIR::eBinOp::MOD_OV: os << "MOD_OV"; break;
-
+
case ::MIR::eBinOp::BIT_OR : os << "BIT_OR"; break;
case ::MIR::eBinOp::BIT_AND: os << "BIT_AND"; break;
case ::MIR::eBinOp::BIT_XOR: os << "BIT_XOR"; break;
-
+
case ::MIR::eBinOp::BIT_SHR: os << "BIT_SHR"; break;
case ::MIR::eBinOp::BIT_SHL: os << "BIT_SHL"; break;
-
+
case ::MIR::eBinOp::EQ: os << "EQ"; break;
case ::MIR::eBinOp::NE: os << "NE"; break;
case ::MIR::eBinOp::GT: os << "GT"; break;
@@ -424,7 +424,7 @@ namespace {
void MIR_Dump(::std::ostream& sink, const ::HIR::Crate& crate)
{
TreeVisitor tv { sink };
-
+
tv.visit_crate( const_cast< ::HIR::Crate&>(crate) );
}
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 7218563b..e21ca993 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -20,14 +20,14 @@
namespace {
-
+
class ExprVisitor_Conv:
public MirConverter
{
MirBuilder& m_builder;
-
+
const ::std::vector< ::HIR::TypeRef>& m_variable_types;
-
+
struct LoopDesc {
ScopeHandle scope;
::std::string label;
@@ -35,26 +35,26 @@ namespace {
unsigned int next;
};
::std::vector<LoopDesc> m_loop_stack;
-
+
public:
ExprVisitor_Conv(MirBuilder& builder, const ::std::vector< ::HIR::TypeRef>& var_types):
m_builder(builder),
m_variable_types(var_types)
{
}
-
+
void destructure_from(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, bool allow_refutable=false) override
{
destructure_from_ex(sp, pat, mv$(lval), (allow_refutable ? 1 : 0));
}
-
+
// Brings variables defined in `pat` into scope
void define_vars_from(const Span& sp, const ::HIR::Pattern& pat) override
{
if( pat.m_binding.is_valid() ) {
m_builder.define_variable( pat.m_binding.m_slot );
}
-
+
TU_MATCHA( (pat.m_data), (e),
(Any,
),
@@ -98,7 +98,7 @@ namespace {
),
(EnumValue,
),
-
+
(EnumTuple,
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
@@ -132,7 +132,7 @@ namespace {
)
)
}
-
+
void destructure_from_ex(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, int allow_refutable=0) // 1 : yes, 2 : disallow binding
{
if( allow_refutable != 3 && pat.m_binding.is_valid() ) {
@@ -146,7 +146,7 @@ namespace {
// Refutable and binding allowed
destructure_from_ex(sp, pat, lval.clone(), 3);
}
-
+
switch( pat.m_binding.m_type )
{
case ::HIR::PatternBinding::Type::Move:
@@ -168,7 +168,7 @@ namespace {
if( allow_refutable == 3 ) {
allow_refutable = 2;
}
-
+
TU_MATCHA( (pat.m_data), (e),
(Any,
),
@@ -267,7 +267,7 @@ namespace {
else
{
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
-
+
// TODO: Emit code to triple-check the size? Or just assume that match did that correctly.
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++)
{
@@ -320,7 +320,7 @@ namespace {
)
)
}
-
+
// -- ExprVisitor
void visit(::HIR::ExprNode_Block& node) override
{
@@ -329,38 +329,38 @@ namespace {
if( node.m_nodes.size() > 0 )
{
bool diverged = false;
-
+
auto scope = m_builder.new_scope_var(node.span());
-
+
for(unsigned int i = 0; i < node.m_nodes.size() - (node.m_yields_final ? 1 : 0); i ++)
{
auto& subnode = node.m_nodes[i];
const Span& sp = subnode->span();
-
+
auto stmt_scope = m_builder.new_scope_temp(sp);
this->visit_node_ptr(subnode);
if( m_builder.has_result() ) {
// TODO: Drop.
m_builder.get_result(sp);
}
-
+
if( m_builder.block_active() ) {
m_builder.terminate_scope(sp, mv$(stmt_scope));
}
else {
auto _ = mv$(stmt_scope);
-
+
m_builder.set_cur_block( m_builder.new_bb_unlinked() );
diverged = true;
}
}
-
+
// - For the last node, don't bother with a statement scope
if( node.m_yields_final )
{
auto& subnode = node.m_nodes.back();
const Span& sp = subnode->span();
-
+
auto stmt_scope = m_builder.new_scope_temp(sp);
this->visit_node_ptr(subnode);
if( m_builder.has_result() || m_builder.block_active() )
@@ -368,10 +368,10 @@ namespace {
ASSERT_BUG(sp, m_builder.block_active(), "Result yielded, but no active block");
ASSERT_BUG(sp, m_builder.has_result(), "Active block but no result yeilded");
// PROBLEM: This can drop the result before we want to use it.
-
+
auto res = m_builder.get_result(sp);
m_builder.raise_variables(sp, res);
-
+
m_builder.terminate_scope(sp, mv$(stmt_scope));
m_builder.terminate_scope( node.span(), mv$(scope) );
m_builder.set_result( node.span(), mv$(res) );
@@ -407,7 +407,7 @@ namespace {
{
TRACE_FUNCTION_F("_Return");
this->visit_node_ptr(node.m_value);
-
+
m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) );
m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() );
m_builder.end_block( ::MIR::Terminator::make_Return({}) );
@@ -419,11 +419,11 @@ namespace {
if( node.m_value )
{
this->visit_node_ptr(node.m_value);
-
+
if( ! m_builder.block_active() ) {
return ;
}
-
+
if( node.m_pattern.m_binding.is_valid() && node.m_pattern.m_data.is_Any() && node.m_pattern.m_binding.m_type == ::HIR::PatternBinding::Type::Move )
{
m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Variable(node.m_pattern.m_binding.m_slot), m_builder.get_result(node.span()) );
@@ -441,12 +441,12 @@ namespace {
auto loop_body_scope = m_builder.new_scope_loop(node.span());
auto loop_block = m_builder.new_bb_linked();
auto loop_next = m_builder.new_bb_unlinked();
-
+
m_loop_stack.push_back( LoopDesc { mv$(loop_body_scope), node.m_label, loop_block, loop_next } );
this->visit_node_ptr(node.m_code);
auto loop_scope = mv$(m_loop_stack.back().scope);
m_loop_stack.pop_back();
-
+
// If there's a stray result, drop it
if( m_builder.has_result() ) {
assert( m_builder.block_active() );
@@ -467,7 +467,7 @@ namespace {
// Terminate scope without emitting cleanup (cleanup was handled by `break`)
m_builder.terminate_scope( node.span(), mv$(loop_scope), false );
}
-
+
if( ! node.m_diverges )
{
DEBUG("- Doesn't diverge");
@@ -478,7 +478,7 @@ namespace {
{
DEBUG("- Diverges");
assert( !m_builder.has_result() );
-
+
m_builder.set_cur_block(loop_next);
m_builder.end_split_arm_early(node.span());
assert( !m_builder.has_result() );
@@ -491,7 +491,7 @@ namespace {
if( m_loop_stack.size() == 0 ) {
BUG(node.span(), "Loop control outside of a loop");
}
-
+
const auto* target_block = &m_loop_stack.back();
if( node.m_label != "" ) {
auto it = ::std::find_if(m_loop_stack.rbegin(), m_loop_stack.rend(), [&](const auto& x){ return x.label == node.m_label; });
@@ -500,7 +500,7 @@ namespace {
}
target_block = &*it;
}
-
+
// TODO: Insert drop of all active scopes within the loop
m_builder.terminate_scope_early( node.span(), target_block->scope );
if( node.m_continue ) {
@@ -510,13 +510,13 @@ namespace {
m_builder.end_block( ::MIR::Terminator::make_Goto(target_block->next) );
}
}
-
+
void visit(::HIR::ExprNode_Match& node) override
{
TRACE_FUNCTION_FR("_Match", "_Match");
this->visit_node_ptr(node.m_value);
auto match_val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
if( node.m_arms.size() == 0 ) {
// Nothing
//const auto& ty = node.m_value->m_res_type;
@@ -531,21 +531,21 @@ namespace {
// - Shortcut: Single-arm match
auto& arm = node.m_arms[0];
const auto& pat = arm.m_patterns[0];
-
+
auto scope = m_builder.new_scope_var(arm.m_code->span());
auto tmp_scope = m_builder.new_scope_temp(arm.m_code->span());
this->define_vars_from(node.span(), pat);
// TODO: Do the same shortcut as _Let?
this->destructure_from(node.span(), pat, mv$(match_val));
-
+
// Temp scope.
this->visit_node_ptr(arm.m_code);
-
+
if( m_builder.block_active() ) {
auto res = m_builder.get_result(arm.m_code->span());
m_builder.raise_variables( arm.m_code->span(), res );
m_builder.set_result(arm.m_code->span(), mv$(res));
-
+
m_builder.terminate_scope( node.span(), mv$(tmp_scope) );
m_builder.terminate_scope( node.span(), mv$(scope) );
}
@@ -558,11 +558,11 @@ namespace {
MIR_LowerHIR_Match(m_builder, *this, node, mv$(match_val));
}
} // ExprNode_Match
-
+
void visit(::HIR::ExprNode_If& node) override
{
TRACE_FUNCTION_FR("_If", "_If");
-
+
bool reverse = false;
{
auto* cond_p = &node.m_cond;
@@ -572,11 +572,11 @@ namespace {
cond_p = &cond_uni->m_value;
reverse = !reverse;
}
-
+
this->visit_node_ptr(*cond_p);
}
auto decision_val = m_builder.get_result_in_lvalue(node.m_cond->span(), node.m_cond->m_res_type);
-
+
auto true_branch = m_builder.new_bb_unlinked();
auto false_branch = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
@@ -586,12 +586,12 @@ namespace {
else {
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) );
}
-
+
auto result_val = m_builder.new_temporary(node.m_res_type);
-
+
// Scope handles cases where one arm moves a value but the other doesn't
auto scope = m_builder.new_scope_split( node.m_true->span() );
-
+
// 'true' branch
{
m_builder.set_cur_block(true_branch);
@@ -605,7 +605,7 @@ namespace {
m_builder.end_split_arm(node.span(), scope, false);
}
}
-
+
// 'false' branch
m_builder.set_cur_block(false_branch);
if( node.m_false )
@@ -630,10 +630,10 @@ namespace {
}
m_builder.set_cur_block(next_block);
m_builder.terminate_scope( node.span(), mv$(scope) );
-
+
m_builder.set_result( node.span(), mv$(result_val) );
}
-
+
void generate_checked_binop(const Span& sp, ::MIR::LValue res_slot, ::MIR::eBinOp op, ::MIR::LValue val_l, const ::HIR::TypeRef& ty_l, ::MIR::LValue val_r, const ::HIR::TypeRef& ty_r)
{
switch(op)
@@ -726,29 +726,29 @@ namespace {
break;
}
}
-
+
void visit(::HIR::ExprNode_Assign& node) override
{
TRACE_FUNCTION_F("_Assign");
const auto& sp = node.span();
-
+
this->visit_node_ptr(node.m_value);
::MIR::RValue val = m_builder.get_result(sp);
-
+
this->visit_node_ptr(node.m_slot);
auto dst = m_builder.get_result_unwrap_lvalue(sp);
-
+
const auto& ty_slot = node.m_slot->m_res_type;
const auto& ty_val = node.m_value->m_res_type;
-
+
if( node.m_op != ::HIR::ExprNode_Assign::Op::None )
{
auto dst_clone = dst.clone();
auto val_lv = m_builder.lvalue_or_temp( node.span(), ty_val, mv$(val) );
-
+
ASSERT_BUG(sp, ty_slot.m_data.is_Primitive(), "Assignment operator overloads are only valid on primitives - ty_slot="<<ty_slot);
ASSERT_BUG(sp, ty_val.m_data.is_Primitive(), "Assignment operator overloads are only valid on primitives - ty_val="<<ty_val);
-
+
#define _(v) ::HIR::ExprNode_Assign::Op::v
::MIR::eBinOp op;
switch(node.m_op)
@@ -783,20 +783,20 @@ namespace {
}
m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
-
+
void visit(::HIR::ExprNode_BinOp& node) override
{
const auto& sp = node.span();
TRACE_FUNCTION_F("_BinOp");
-
+
const auto& ty_l = node.m_left->m_res_type;
this->visit_node_ptr(node.m_left);
auto left = m_builder.get_result_in_lvalue(node.m_left->span(), ty_l);
-
+
const auto& ty_r = node.m_right->m_res_type;
this->visit_node_ptr(node.m_right);
auto right = m_builder.get_result_in_lvalue(node.m_right->span(), ty_r);
-
+
auto res = m_builder.new_temporary(node.m_res_type);
::MIR::eBinOp op;
switch(node.m_op)
@@ -809,18 +809,18 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::CmpGtE: op = ::MIR::eBinOp::GE;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Xor: op = ::MIR::eBinOp::BIT_XOR; if(0)
case ::HIR::ExprNode_BinOp::Op::Or : op = ::MIR::eBinOp::BIT_OR ; if(0)
case ::HIR::ExprNode_BinOp::Op::And: op = ::MIR::eBinOp::BIT_AND;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Shr: op = ::MIR::eBinOp::BIT_SHR; if(0)
case ::HIR::ExprNode_BinOp::Op::Shl: op = ::MIR::eBinOp::BIT_SHL;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Add: op = ::MIR::eBinOp::ADD; if(0)
case ::HIR::ExprNode_BinOp::Op::Sub: op = ::MIR::eBinOp::SUB; if(0)
case ::HIR::ExprNode_BinOp::Op::Mul: op = ::MIR::eBinOp::MUL; if(0)
@@ -828,7 +828,7 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::Mod: op = ::MIR::eBinOp::MOD;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::BoolAnd: {
auto bb_next = m_builder.new_bb_unlinked();
auto bb_true = m_builder.new_bb_unlinked();
@@ -838,12 +838,12 @@ namespace {
m_builder.set_cur_block( bb_false );
m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(false) ));
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
-
+
// If left is true, assign result to right
m_builder.set_cur_block( bb_true );
m_builder.push_stmt_assign(node.span(), res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
-
+
m_builder.set_cur_block( bb_next );
} break;
case ::HIR::ExprNode_BinOp::Op::BoolOr: {
@@ -855,26 +855,26 @@ namespace {
m_builder.set_cur_block( bb_true );
m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(true) ));
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
-
+
// If left is false, assign result to right
m_builder.set_cur_block( bb_false );
m_builder.push_stmt_assign(node.span(), res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
-
+
m_builder.set_cur_block( bb_next );
} break;
}
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_UniOp& node) override
{
TRACE_FUNCTION_F("_UniOp");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
-
+
::MIR::RValue res;
switch(node.m_op)
{
@@ -928,11 +928,11 @@ namespace {
void visit(::HIR::ExprNode_Borrow& node) override
{
TRACE_FUNCTION_F("_Borrow");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
-
+
auto res = m_builder.new_temporary(node.m_res_type);
m_builder.push_stmt_assign( node.span(), res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, node.m_type, mv$(val) }));
m_builder.set_result( node.span(), mv$(res) );
@@ -941,16 +941,16 @@ namespace {
{
TRACE_FUNCTION_F("_Cast");
this->visit_node_ptr(node.m_value);
-
+
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
-
+
if( ty_out == ty_in ) {
return ;
}
-
+
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_out.m_data), (de),
(
BUG(node.span(), "Invalid cast to " << ty_out << " from " << ty_in);
@@ -1067,16 +1067,16 @@ namespace {
{
TRACE_FUNCTION_F("_Unsize");
this->visit_node_ptr(node.m_value);
-
+
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
-
+
if( ty_out == ty_in ) {
return ;
}
-
+
auto ptr_lval = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
if( ty_out.m_data.is_Borrow() && ty_in.m_data.is_Borrow() )
{
const auto& oe = ty_out.m_data.as_Borrow();
@@ -1135,14 +1135,14 @@ namespace {
vtable_params.m_types[idx] = ty_b.second.clone();
}
auto vtable_type = ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref );
-
+
::HIR::Path vtable { ty_in.clone(), e.m_trait.m_path.clone(), "#vtable" };
auto vtable_lval = m_builder.lvalue_or_temp(
node.span(),
::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, mv$(vtable_type)),
::MIR::RValue( ::MIR::Constant::make_ItemAddr(mv$(vtable)) )
);
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(vtable_lval) }) );
#else
m_builder.set_result( node.span(), ::MIR::RValue::make_Cast({ mv$(ptr_lval), node.m_res_type.clone() }) );
@@ -1164,16 +1164,16 @@ namespace {
void visit(::HIR::ExprNode_Index& node) override
{
TRACE_FUNCTION_F("_Index");
-
+
// NOTE: Calculate the index first (so if it borrows from the source, it's over by the time that's needed)
const auto& ty_idx = node.m_index->m_res_type;
this->visit_node_ptr(node.m_index);
auto index = m_builder.get_result_in_lvalue(node.m_index->span(), ty_idx);
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
auto value = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
-
+
::MIR::RValue limit_val;
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_val.m_data), (e),
(
@@ -1186,7 +1186,7 @@ namespace {
limit_val = ::MIR::RValue::make_DstMeta({ value.clone() });
)
)
-
+
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_idx.m_data), (e),
(
BUG(node.span(), "Indexing using unsupported index type " << ty_idx);
@@ -1197,38 +1197,38 @@ namespace {
}
)
)
-
+
// Range checking (DISABLED)
if( false )
{
auto limit_lval = m_builder.lvalue_or_temp( node.span(), ty_idx, mv$(limit_val) );
-
+
auto cmp_res = m_builder.new_temporary( ::HIR::CoreType::Bool );
m_builder.push_stmt_assign(node.span(), cmp_res.clone(), ::MIR::RValue::make_BinOp({ index.clone(), ::MIR::eBinOp::GE, mv$(limit_lval) }));
auto arm_panic = m_builder.new_bb_unlinked();
auto arm_continue = m_builder.new_bb_unlinked();
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_res), arm_panic, arm_continue }) );
-
+
m_builder.set_cur_block( arm_panic );
// TODO: Call an "index fail" method which always panics.
//m_builder.end_block( ::MIR::Terminator::make_Panic({}) );
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( arm_continue );
}
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(value), box$(index) }) );
}
-
+
void visit(::HIR::ExprNode_Deref& node) override
{
const Span& sp = node.span();
TRACE_FUNCTION_F("_Deref");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_val.m_data), (te),
(
if( m_builder.is_type_owned_box( ty_val ) )
@@ -1246,10 +1246,10 @@ namespace {
// Deref on a borrow - Always valid... assuming borrowck is there :)
)
)
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) );
}
-
+
void visit(::HIR::ExprNode_Emplace& node) override
{
if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) {
@@ -1260,9 +1260,9 @@ namespace {
auto path_Place = ::HIR::SimplePath("core", {"ops", "Place"});
auto path_Boxed = ::HIR::SimplePath("core", {"ops", "Boxed"});
//auto path_InPlace = ::HIR::SimplePath("core", {"ops", "InPlace"});
-
+
const auto& data_ty = node.m_value->m_res_type;
-
+
// 1. Obtain the type of the `place` variable
::HIR::TypeRef place_type;
switch( node.m_type )
@@ -1277,7 +1277,7 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
// 2. Initialise the place
auto place = m_builder.new_temporary( place_type );
auto place__panic = m_builder.new_bb_unlinked();
@@ -1299,13 +1299,13 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(place__panic);
// TODO: Drop `place`
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(place__ok);
-
+
// 2. Get `place_raw`
auto place_raw__type = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone());
auto place_raw = m_builder.new_temporary( place_raw__type );
@@ -1322,19 +1322,19 @@ namespace {
::make_vec1( mv$(place_refmut) )
}));
}
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(place_raw__panic);
// TODO: Drop `place`
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(place_raw__ok);
-
-
+
+
// 3. Get the value and assign it into `place_raw`
node.m_value->visit(*this);
auto val = m_builder.get_result(node.span());
m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Deref({ box$(place_raw.clone()) }), mv$(val) );
-
+
// 3. Return a call to `finalize`
::HIR::Path finalize_path(::HIR::GenericPath {});
switch( node.m_type )
@@ -1348,7 +1348,7 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
auto res = m_builder.new_temporary( node.m_res_type );
auto res__panic = m_builder.new_bb_unlinked();
auto res__ok = m_builder.new_bb_unlinked();
@@ -1357,17 +1357,17 @@ namespace {
res.clone(), mv$(finalize_path),
::make_vec1( mv$(place) )
}));
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(res__panic);
// TODO: Should this drop the value written to the rawptr?
// - No, becuase it's likely invalid now. Goodbye!
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(res__ok);
-
+
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override
{
const Span& sp = node.span();
@@ -1379,7 +1379,7 @@ namespace {
this->visit_node_ptr(arg);
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
}
-
+
unsigned int variant_index = ~0u;
if( !node.m_is_struct )
{
@@ -1390,17 +1390,17 @@ namespace {
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
-
+
variant_index = var_it - enm.m_variants.begin();
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_path.clone(),
variant_index,
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_CallPath& node) override
{
TRACE_FUNCTION_F("_CallPath " << node.m_path);
@@ -1412,14 +1412,14 @@ namespace {
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
-
-
+
+
auto panic_block = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
auto res = m_builder.new_temporary( node.m_res_type );
-
+
bool unconditional_diverge = false;
-
+
// Emit intrinsics as a special call type
if( node.m_path.m_data.is_Generic() )
{
@@ -1433,13 +1433,13 @@ namespace {
mv$(values)
}));
}
-
+
if( fcn.m_return.m_data.is_Diverge() )
{
unconditional_diverge = true;
}
}
-
+
// If the call wasn't to an intrinsic, emit it as a path
if( m_builder.block_active() )
{
@@ -1449,11 +1449,11 @@ namespace {
mv$(values)
}));
}
-
+
m_builder.set_cur_block(panic_block);
// TODO: Proper panic handling, including scope destruction
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( next_block );
// If the function doesn't return, early-terminate the return block.
@@ -1469,16 +1469,16 @@ namespace {
}
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_CallValue& node) override
{
TRACE_FUNCTION_F("_CallValue " << node.m_value->m_res_type);
-
+
// _CallValue is ONLY valid on function pointers (all others must be desugared)
ASSERT_BUG(node.span(), node.m_value->m_res_type.m_data.is_Function(), "Leftover _CallValue on a non-fn()");
this->visit_node_ptr(node.m_value);
auto fcn_val = m_builder.get_result_in_lvalue( node.m_value->span(), node.m_value->m_res_type );
-
+
::std::vector< ::MIR::LValue> values;
values.reserve( node.m_args.size() );
for(auto& arg : node.m_args)
@@ -1487,8 +1487,8 @@ namespace {
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
-
-
+
+
auto panic_block = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
auto res = m_builder.new_temporary( node.m_res_type );
@@ -1497,11 +1497,11 @@ namespace {
res.clone(), mv$(fcn_val),
mv$(values)
}));
-
+
m_builder.set_cur_block(panic_block);
// TODO: Proper panic handling
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( next_block );
m_builder.set_result( node.span(), mv$(res) );
}
@@ -1515,9 +1515,9 @@ namespace {
TRACE_FUNCTION_F("_Field");
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
const auto& val_ty = node.m_value->m_res_type;
-
+
unsigned int idx;
if( '0' <= node.m_field[0] && node.m_field[0] <= '9' ) {
::std::stringstream(node.m_field) >> idx;
@@ -1533,7 +1533,7 @@ namespace {
const auto& unm = *node.m_value->m_res_type.m_data.as_Path().binding.as_Union();
const auto& fields = unm.m_variants;
idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin();
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) );
}
}
@@ -1595,7 +1595,7 @@ namespace {
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
-
+
variant_index = var_it - enm.m_variants.begin();
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
@@ -1614,13 +1614,13 @@ namespace {
auto enum_path = pe.m_path;
enum_path.m_components.pop_back();
const auto& var_name = pe.m_path.m_components.back();
-
+
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << pe.m_path << " isn't present");
const auto& var = var_it->second;
ASSERT_BUG(sp, var.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple variant");
-
+
// TODO: Ideally, the creation of the wrapper function would happen somewhere before this?
auto tmp = m_builder.new_temporary( node.m_res_type );
m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
@@ -1670,7 +1670,7 @@ namespace {
BUG(sp, "Unknown param in free function - " << gt);
}
};
-
+
// TODO: Obtain function type for this function (i.e. a type that is specifically for this function)
auto fcn_ty_data = ::HIR::FunctionType {
e.m_unsafe,
@@ -1752,7 +1752,7 @@ namespace {
TRACE_FUNCTION_F("_Variable - " << node.m_name << " #" << node.m_slot);
m_builder.set_result( node.span(), ::MIR::LValue::make_Variable(node.m_slot) );
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override
{
TRACE_FUNCTION_F("_StructLiteral");
@@ -1762,7 +1762,7 @@ namespace {
this->visit_node_ptr(node.m_base_value);
base_val = m_builder.get_result_in_lvalue(node.m_base_value->span(), node.m_base_value->m_res_type);
}
-
+
unsigned int variant_index = ~0u;
const ::HIR::t_struct_fields* fields_ptr = nullptr;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e),
@@ -1785,12 +1785,12 @@ namespace {
)
assert(fields_ptr);
const ::HIR::t_struct_fields& fields = *fields_ptr;
-
+
::std::vector<bool> values_set;
::std::vector< ::MIR::LValue> values;
values.resize( fields.size() );
values_set.resize( fields.size() );
-
+
for(auto& ent : node.m_values)
{
auto& valnode = ent.second;
@@ -1812,7 +1812,7 @@ namespace {
// Partial move support will handle dropping the rest?
}
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_path.clone(),
variant_index,
@@ -1822,10 +1822,10 @@ namespace {
void visit(::HIR::ExprNode_UnionLiteral& node) override
{
TRACE_FUNCTION_F("_UnionLiteral " << node.m_path);
-
+
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
const auto& unm = *node.m_res_type.m_data.as_Path().binding.as_Union();
auto it = ::std::find_if(unm.m_variants.begin(), unm.m_variants.end(), [&](const auto&v)->auto{ return v.first == node.m_variant_name; });
assert(it != unm.m_variants.end());
@@ -1837,7 +1837,7 @@ namespace {
mv$(val)
}) );
}
-
+
void visit(::HIR::ExprNode_Tuple& node) override
{
TRACE_FUNCTION_F("_Tuple");
@@ -1848,12 +1848,12 @@ namespace {
this->visit_node_ptr(arg);
values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) );
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_ArrayList& node) override
{
TRACE_FUNCTION_F("_ArrayList");
@@ -1864,28 +1864,28 @@ namespace {
this->visit_node_ptr(arg);
values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) );
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Array({
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_ArraySized& node) override
{
TRACE_FUNCTION_F("_ArraySized");
this->visit_node_ptr( node.m_val );
auto value = m_builder.lvalue_or_temp( node.span(), node.m_val->m_res_type, m_builder.get_result(node.m_val->span()) );
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_SizedArray({
mv$(value),
static_cast<unsigned int>(node.m_size_val)
}) );
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
TRACE_FUNCTION_F("_Closure - " << node.m_obj_path);
-
+
::std::vector< ::MIR::LValue> vals;
vals.reserve( node.m_captures.size() );
for(auto& arg : node.m_captures)
@@ -1893,7 +1893,7 @@ namespace {
this->visit_node_ptr(arg);
vals.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_obj_path.clone(),
~0u,
@@ -1907,17 +1907,17 @@ namespace {
::MIR::FunctionPointer LowerMIR(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::HIR::ExprPtr& ptr, const ::HIR::Function::args_t& args)
{
TRACE_FUNCTION;
-
+
::MIR::Function fcn;
fcn.named_variables.reserve(ptr.m_bindings.size());
for(const auto& t : ptr.m_bindings)
fcn.named_variables.push_back( t.clone() );
-
+
// Scope ensures that builder cleanup happens before `fcn` is moved
{
MirBuilder builder { ptr->span(), resolve, args, fcn };
ExprVisitor_Conv ev { builder, ptr.m_bindings };
-
+
// 1. Apply destructuring to arguments
unsigned int i = 0;
for( const auto& arg : args )
@@ -1926,12 +1926,12 @@ namespace {
ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::make_Argument({i}));
i ++;
}
-
+
// 2. Destructure code
::HIR::ExprNode& root_node = const_cast<::HIR::ExprNode&>(*ptr);
root_node.visit( ev );
}
-
+
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index caeba6ad..7c83b44f 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -16,10 +16,10 @@ class MirBuilder;
class ScopeHandle
{
friend class MirBuilder;
-
+
const MirBuilder& m_builder;
unsigned int idx;
-
+
ScopeHandle(const MirBuilder& builder, unsigned int idx):
m_builder(builder),
idx(idx)
@@ -43,11 +43,11 @@ enum class VarState {
Uninit, // No value assigned yet
Moved, // Definitely moved
Dropped, // Dropped (out of scope)
-
+
InnerMoved, // The inner has been moved, but the container needs to be dropped
//MaybeMovedInner, // Inner possibly has been moved
MaybeMoved, // Possibly has been moved
-
+
Init, // Initialised and valid at this point
};
extern ::std::ostream& operator<<(::std::ostream& os, VarState x);
@@ -57,7 +57,7 @@ struct SplitArm {
bool always_early_terminated = false; // Populated on completion
::std::vector<bool> changed_var_states; // Indexed by binding bumber
::std::vector<VarState> var_states;
-
+
::std::vector<bool> changed_tmp_states;
::std::vector<VarState> tmp_states;
};
@@ -80,31 +80,31 @@ TAGGED_UNION(ScopeType, Variables,
class MirBuilder
{
friend class ScopeHandle;
-
+
const Span& m_root_span;
const StaticTraitResolve& m_resolve;
const ::HIR::Function::args_t& m_args;
::MIR::Function& m_output;
-
+
const ::HIR::SimplePath* m_lang_Box;
-
+
unsigned int m_current_block;
bool m_block_active;
-
+
::MIR::RValue m_result;
bool m_result_valid;
-
+
// TODO: Extra information.
//::std::vector<VarState> m_arg_states;
::std::vector<VarState> m_variable_states;
::std::vector<VarState> m_temporary_states;
-
+
struct ScopeDef
{
const Span& span;
bool complete = false;
ScopeType data;
-
+
ScopeDef(const Span& span):
span(span)
{
@@ -115,27 +115,27 @@ class MirBuilder
{
}
};
-
+
::std::vector<ScopeDef> m_scopes;
::std::vector<unsigned int> m_scope_stack;
ScopeHandle m_fcn_scope;
public:
MirBuilder(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::Function::args_t& args, ::MIR::Function& output);
~MirBuilder();
-
+
const ::HIR::SimplePath* lang_Box() const { return m_lang_Box; }
const ::HIR::Crate& crate() const { return m_resolve.m_crate; }
const StaticTraitResolve& resolve() const { return m_resolve; }
-
+
//::HIR::TypeRef* is_type_owned_box(::HIR::TypeRef& ty) const {
//}
/// Check if the passed type is Box<T> and returns a pointer to the T type if so, otherwise nullptr
const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const;
-
+
// - Values
::MIR::LValue new_temporary(const ::HIR::TypeRef& ty);
::MIR::LValue lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val);
-
+
bool has_result() const {
return m_result_valid;
}
@@ -145,7 +145,7 @@ public:
::MIR::LValue get_result_unwrap_lvalue(const Span& sp);
/// Obtains the result, copying into a temporary if required
::MIR::LValue get_result_in_lvalue(const Span& sp, const ::HIR::TypeRef& ty);
-
+
// - Statements
// Push an assignment. NOTE: This also marks the rvalue as moved
void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val);
@@ -153,26 +153,26 @@ public:
void push_stmt_drop(const Span& sp, ::MIR::LValue val);
// Push a shallow drop (for Box)
void push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val);
-
+
// - Block management
bool block_active() const {
return m_block_active;
}
-
+
// Mark a value as initialised (used for Call, because it has to be done after the panic block is populated)
void mark_value_assigned(const Span& sp, const ::MIR::LValue& val);
-
+
// Moves control of temporaries up to the next scope
void raise_variables(const Span& sp, const ::MIR::LValue& val);
void raise_variables(const Span& sp, const ::MIR::RValue& rval);
-
+
void set_cur_block(unsigned int new_block);
::MIR::BasicBlockId pause_cur_block();
void end_block(::MIR::Terminator term);
-
+
::MIR::BasicBlockId new_bb_linked();
::MIR::BasicBlockId new_bb_unlinked();
-
+
// --- Scopes ---
ScopeHandle new_scope_var(const Span& sp);
ScopeHandle new_scope_temp(const Span& sp);
@@ -182,7 +182,7 @@ public:
void terminate_scope_early(const Span& sp, const ScopeHandle& );
void end_split_arm(const Span& sp, const ScopeHandle& , bool reachable);
void end_split_arm_early(const Span& sp);
-
+
const ScopeHandle& fcn_scope() const {
return m_fcn_scope;
}
@@ -196,10 +196,10 @@ private:
void set_variable_state(const Span& sp, unsigned int idx, VarState state);
VarState get_temp_state(const Span& sp, unsigned int idx) const;
void set_temp_state(const Span& sp, unsigned int idx, VarState state);
-
+
void drop_scope_values(const ScopeDef& sd);
void complete_scope(ScopeDef& sd);
-
+
public:
void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function<void(const ::HIR::TypeRef&)> cb) const;
bool lvalue_is_copy(const Span& sp, const ::MIR::LValue& lv) const;
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index f191f3fa..d3c5a5eb 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -17,14 +17,14 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
struct field_path_t
{
::std::vector<uint8_t> data;
-
+
size_t size() const { return data.size(); }
void push_back(uint8_t v) { data.push_back(v); }
void pop_back() { data.pop_back(); }
uint8_t& back() { return data.back(); }
-
+
bool operator==(const field_path_t& x) const { return data == x.data; }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const field_path_t& x) {
for(const auto idx : x.data)
os << "." << static_cast<unsigned int>(idx);
@@ -61,9 +61,9 @@ struct PatternRuleset
unsigned int pat_idx;
::std::vector<PatternRule> m_rules;
-
+
static ::Ordering rule_is_before(const PatternRule& l, const PatternRule& r);
-
+
bool is_before(const PatternRuleset& other) const;
};
/// Generated code for an arm
@@ -88,7 +88,7 @@ struct PatternRulesetBuilder
bool m_is_impossible;
::std::vector<PatternRule> m_rules;
field_path_t m_field_path;
-
+
PatternRulesetBuilder(const StaticTraitResolve& resolve):
m_resolve(resolve),
m_is_impossible(false)
@@ -97,7 +97,7 @@ struct PatternRulesetBuilder
m_lang_Box = &resolve.m_crate.m_lang_items.at("owned_box");
}
}
-
+
void append_from_lit(const Span& sp, const ::HIR::Literal& lit, const ::HIR::TypeRef& ty);
void append_from(const Span& sp, const ::HIR::Pattern& pat, const ::HIR::TypeRef& ty);
void push_rule(PatternRule r);
@@ -113,17 +113,17 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
{
// TODO: If any arm moves a non-Copy value, then mark `match_val` as moved
TRACE_FUNCTION;
-
+
bool fall_back_on_simple = false;
-
+
auto result_val = builder.new_temporary( node.m_res_type );
auto next_block = builder.new_bb_unlinked();
-
+
// 1. Stop the current block so we can generate code
auto first_cmp_block = builder.new_bb_unlinked();
builder.end_block( ::MIR::Terminator::make_Goto(first_cmp_block) );
-
+
struct H {
static bool is_pattern_move(const Span& sp, const MirBuilder& builder, const ::HIR::Pattern& pat) {
if( pat.m_binding.is_valid() )
@@ -221,7 +221,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
return false;
}
};
-
+
bool has_move_pattern = false;
for(const auto& arm : node.m_arms)
{
@@ -234,7 +234,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
if( has_move_pattern )
break ;
}
-
+
auto match_scope = builder.new_scope_split(node.span());
// Map of arm index to ruleset
@@ -245,12 +245,12 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
DEBUG("ARM " << arm_idx);
/*const*/ auto& arm = node.m_arms[arm_idx];
ArmCode ac;
-
+
// Register introduced bindings to be dropped on return/diverge within this scope
auto drop_scope = builder.new_scope_var( arm.m_code->span() );
// - Define variables from the first pattern
conv.define_vars_from(node.span(), arm.m_patterns.front());
-
+
for( unsigned int pat_idx = 0; pat_idx < arm.m_patterns.size(); pat_idx ++ )
{
const auto& pat = arm.m_patterns[pat_idx];
@@ -266,7 +266,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
DEBUG("ARM PAT (" << arm_idx << "," << pat_idx << ") " << pat << " ==> [" << pat_builder.m_rules << "]");
arm_rules.push_back( PatternRuleset { arm_idx, pat_idx, mv$(pat_builder.m_rules) } );
}
-
+
// - Emit code to destructure the matched pattern
ac.destructures.push_back( builder.new_bb_unlinked() );
builder.set_cur_block( ac.destructures.back() );
@@ -274,14 +274,14 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
builder.pause_cur_block();
// NOTE: Paused block resumed upon successful match
}
-
+
// TODO: If this pattern ignores fields with Drop impls, this will lead to leaks.
// - Ideally, this would trigger a drop of whatever wasn't already taken by the pattern.
if( has_move_pattern )
{
builder.moved_lvalue(node.span(), match_val);
}
-
+
// Condition
// NOTE: Lack of drop due to early exit from this arm isn't an issue. All captures must be Copy
// - The above is rustc E0008 "cannot bind by-move into a pattern guard"
@@ -291,13 +291,13 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
ac.has_condition = true;
ac.cond_start = builder.new_bb_unlinked();
builder.set_cur_block( ac.cond_start );
-
+
// TODO: Temp scope.
conv.visit_node_ptr( arm.m_cond );
ac.cond_lval = builder.get_result_in_lvalue(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool));
ac.cond_end = builder.pause_cur_block();
// NOTE: Paused so that later code (which knows what the false branch will be) can end it correctly
-
+
// TODO: What to do with contidionals in the fast model?
// > Could split the match on each conditional - separating such that if a conditional fails it can fall into the other compatible branches.
fall_back_on_simple = true;
@@ -335,10 +335,10 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
// - Go to the next block
builder.end_block( ::MIR::Terminator::make_Goto(next_block) );
}
-
+
arm_code.push_back( mv$(ac) );
}
-
+
// Sort columns of `arm_rules` to maximise effectiveness
if( arm_rules[0].m_rules.size() > 1 )
{
@@ -354,7 +354,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
}
}
}
-
+
DEBUG("- Column weights = [" << column_weights << "]");
// - Sort columns such that the largest (most specific) comes first
::std::vector<unsigned> columns_sorted(column_weights.size());
@@ -371,12 +371,12 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
arm_rule.m_rules = mv$(sorted);
}
}
-
+
for(const auto& arm_rule : arm_rules)
{
DEBUG("> (" << arm_rule.arm_idx << ", " << arm_rule.pat_idx << ") - " << arm_rule.m_rules);
}
-
+
// TODO: Detect if a rule is ordering-dependent. In this case we currently have to fall back on the simple match code
// - A way would be to search for `_` rules with non _ rules following. Would false-positive in some cases, but shouldn't false negative
// TODO: Merge equal rulesets if there's one with no condition.
@@ -387,7 +387,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
else {
MIR_LowerHIR_Match_DecisionTree( builder, conv, node, mv$(match_val), mv$(arm_rules), mv$(arm_code), first_cmp_block );
}
-
+
builder.set_cur_block( next_block );
builder.set_result( node.span(), mv$(result_val) );
builder.terminate_scope( node.span(), mv$(match_scope) );
@@ -439,7 +439,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
else
return ::OrdLess;
}
-
+
TU_MATCHA( (l,r), (le,re),
(Any,
return ::OrdEqual;
@@ -581,7 +581,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
(Struct,
ASSERT_BUG(sp, lit.is_List(), "Matching struct non-list literal - " << ty << " with " << lit);
const auto& list = lit.as_List();
-
+
auto monomorph = [&](const auto& ty) {
auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty);
this->m_resolve.expand_associated_types(sp, rv);
@@ -600,7 +600,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
{
::HIR::TypeRef tmp;
const auto& sty_mono = (monomorphise_type_needed(sd[i].ent) ? tmp = monomorph(sd[i].ent) : sd[i].ent);
-
+
this->append_from_lit(sp, list[i], sty_mono);
m_field_path.back() ++;
}
@@ -614,7 +614,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
const auto& fld_ty = sd[i].second.ent;
::HIR::TypeRef tmp;
const auto& sty_mono = (monomorphise_type_needed(fld_ty) ? tmp = monomorph(fld_ty) : fld_ty);
-
+
this->append_from_lit(sp, list[i], sty_mono);
m_field_path.back() ++;
}
@@ -633,14 +633,14 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
this->m_resolve.expand_associated_types(sp, rv);
return rv;
};
-
+
ASSERT_BUG(sp, var_idx < pbe->m_variants.size(), "Literal refers to a variant out of range");
const auto& var_def = pbe->m_variants.at(var_idx);
-
+
PatternRulesetBuilder sub_builder { this->m_resolve };
sub_builder.m_field_path = m_field_path;
sub_builder.m_field_path.push_back(0);
-
+
TU_MATCH( ::HIR::Enum::Variant, (var_def.second), (fields_def),
(Unit,
),
@@ -654,10 +654,10 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
sub_builder.m_field_path.back() = i;
const auto& val = list[i];
const auto& ty_tpl = fields_def[i].ent;
-
+
::HIR::TypeRef tmp;
const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl);
-
+
sub_builder.append_from_lit( sp, val, subty );
}
),
@@ -669,15 +669,15 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
sub_builder.m_field_path.back() = i;
const auto& val = list[i];
const auto& ty_tpl = fields_def[i].second.ent;
-
+
::HIR::TypeRef tmp;
const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl);
-
+
sub_builder.append_from_lit( sp, val, subty );
}
)
)
-
+
this->push_rule( PatternRule::make_Variant({ var_idx, mv$(sub_builder.m_rules) }) );
)
)
@@ -697,7 +697,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
ASSERT_BUG(sp, lit.is_List(), "Matching array with non-list literal - " << lit);
const auto& list = lit.as_List();
ASSERT_BUG(sp, e.size_val == list.size(), "Matching array with mismatched literal size - " << e.size_val << " != " << list.size());
-
+
// Sequential match just like tuples.
m_field_path.push_back(0);
for(unsigned int i = 0; i < e.size_val; i ++) {
@@ -709,7 +709,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
(Slice,
ASSERT_BUG(sp, lit.is_List(), "Matching array with non-list literal - " << lit);
const auto& list = lit.as_List();
-
+
PatternRulesetBuilder sub_builder { this->m_resolve };
sub_builder.m_field_path = m_field_path;
sub_builder.m_field_path.push_back(0);
@@ -772,7 +772,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
throw "";
}
};
-
+
// TODO: Outer handling for Value::Named patterns
// - Convert them into either a pattern, or just a variant of this function that operates on ::HIR::Literal
// > It does need a way of handling unknown-value constants (e.g. <GenericT as Foo>::CONST)
@@ -790,7 +790,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
}
)
)
-
+
TU_MATCHA( (ty.m_data), (e),
(Infer, BUG(sp, "Ivar for in match type"); ),
(Diverge,
@@ -939,7 +939,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
return rv;
};
const auto& str_data = pbe->m_data;
-
+
if( m_lang_Box && e.path.m_data.as_Generic().m_path == *m_lang_Box )
{
const auto& inner_ty = e.path.m_data.as_Generic().m_params.m_types.at(0);
@@ -994,7 +994,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
{
const auto& fld = sd[i];
const auto& fld_pat = pe.sub_patterns[i];
-
+
::HIR::TypeRef tmp;
const auto& sty_mono = (monomorphise_type_needed(fld.ent) ? tmp = monomorph(fld.ent) : fld.ent);
this->append_from(sp, fld_pat, sty_mono);
@@ -1025,7 +1025,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
{
::HIR::TypeRef tmp;
const auto& sty_mono = (monomorphise_type_needed(fld.second.ent) ? tmp = monomorph(fld.second.ent) : fld.second.ent);
-
+
auto it = ::std::find_if( pe.sub_patterns.begin(), pe.sub_patterns.end(), [&](const auto& x){ return x.first == fld.first; } );
if( it == pe.sub_patterns.end() )
{
@@ -1070,7 +1070,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
),
(EnumTuple,
const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx);
-
+
const auto& fields_def = var_def.second.as_Tuple();
PatternRulesetBuilder sub_builder { this->m_resolve };
sub_builder.m_field_path = m_field_path;
@@ -1080,10 +1080,10 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
sub_builder.m_field_path.back() = i;
const auto& subpat = pe.sub_patterns[i];
const auto& ty_tpl = fields_def[i].ent;
-
+
::HIR::TypeRef tmp;
const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl);
-
+
sub_builder.append_from( sp, subpat, subty );
}
if( sub_builder.m_is_impossible )
@@ -1111,7 +1111,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
for( unsigned int i = 0; i < tmp.size(); i ++ )
{
sub_builder.m_field_path.back() = i;
-
+
auto subty = monomorph(fields_def[i].second.ent);
if( tmp[i] == ~0u ) {
sub_builder.append_from( sp, ::HIR::Pattern(), subty );
@@ -1194,7 +1194,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
sub_builder.append_from( sp, subpat, *e.inner );
sub_builder.m_field_path.back() ++;
}
-
+
// Encodes length check and sub-pattern rules
this->push_rule( PatternRule::make_Slice({ static_cast<unsigned int>(pe.sub_patterns.size()), mv$(sub_builder.m_rules) }) );
),
@@ -1208,14 +1208,14 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
sub_builder.m_field_path.back() ++;
}
auto leading = mv$(sub_builder.m_rules);
-
+
sub_builder.m_field_path.back() = 0;
if( pe.trailing.size() )
{
TODO(sp, "SplitSlice on [T] with trailing - " << pat);
}
auto trailing = mv$(sub_builder.m_rules);
-
+
this->push_rule( PatternRule::make_SplitSlice({
static_cast<unsigned int>(pe.leading.size() + pe.trailing.size()),
mv$(leading), mv$(trailing)
@@ -1245,7 +1245,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
data.reserve(s.size());
for(auto c : s)
data.push_back(c);
-
+
this->push_rule( PatternRule::make_Value( mv$(data) ) );
}
// TODO: Handle named values
@@ -1291,13 +1291,13 @@ namespace {
::MIR::LValue lval = top_val.clone();
::HIR::TypeRef tmp_ty;
const ::HIR::TypeRef* cur_ty = &top_ty;
-
+
// TODO: Cache the correspondance of path->type (lval can be inferred)
ASSERT_BUG(sp, field_path_ofs <= field_path.size(), "Field path offset " << field_path_ofs << " is larger than the path [" << field_path << "]");
for(unsigned int i = field_path_ofs; i < field_path.size(); i ++ )
{
auto idx = field_path.data[i];
-
+
TU_MATCHA( (cur_ty->m_data), (e),
(Infer, BUG(sp, "Ivar for in match type"); ),
(Diverge, BUG(sp, "Diverge in match type"); ),
@@ -1421,7 +1421,7 @@ namespace {
)
)
}
-
+
out_ty = (cur_ty == &tmp_ty ? mv$(tmp_ty) : cur_ty->clone());
out_val = mv$(lval);
}
@@ -1435,7 +1435,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNode_Match& node, ::MIR::LValue match_val, t_arm_rules arm_rules, ::std::vector<ArmCode> arms_code, ::MIR::BasicBlockId first_cmp_block )
{
TRACE_FUNCTION;
-
+
// 1. Generate pattern matches
unsigned int rule_idx = 0;
builder.set_cur_block( first_cmp_block );
@@ -1443,18 +1443,18 @@ void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR::
{
const auto& arm = node.m_arms[arm_idx];
auto& arm_code = arms_code[arm_idx];
-
+
auto next_arm_bb = builder.new_bb_unlinked();
-
+
for( unsigned int i = 0; i < arm.m_patterns.size(); i ++ )
{
if( arm_code.destructures[i] == 0 )
continue ;
-
+
const auto& pat_rule = arm_rules[rule_idx];
bool is_last_pat = (i+1 == arm.m_patterns.size());
auto next_pattern_bb = (!is_last_pat ? builder.new_bb_unlinked() : next_arm_bb);
-
+
// 1. Check
// - If the ruleset is empty, this is a _ arm over a value
if( pat_rule.m_rules.size() > 0 )
@@ -1463,7 +1463,7 @@ void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR::
}
builder.end_block( ::MIR::Terminator::make_Goto(arm_code.destructures[i]) );
builder.set_cur_block( arm_code.destructures[i] );
-
+
// - Go to code/condition check
if( arm_code.has_condition )
{
@@ -1473,12 +1473,12 @@ void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR::
{
builder.end_block( ::MIR::Terminator::make_Goto(arm_code.code) );
}
-
+
if( !is_last_pat )
{
builder.set_cur_block( next_pattern_bb );
}
-
+
rule_idx ++;
}
if( arm_code.has_condition )
@@ -1499,17 +1499,17 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
{
const auto& rule = rules[rule_idx];
DEBUG("rule = " << rule);
-
+
// Don't emit anything for '_' matches
if( rule.is_Any() )
continue ;
-
+
::MIR::LValue val;
::HIR::TypeRef ity;
-
+
get_ty_and_val(sp, builder.resolve(), top_ty, top_val, rule.field_path, field_path_ofs, ity, val);
DEBUG("ty = " << ity << ", val = " << val);
-
+
const auto& ty = ity;
TU_MATCHA( (ty.m_data), (te),
(Infer,
@@ -1524,9 +1524,9 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
case ::HIR::CoreType::Bool: {
ASSERT_BUG(sp, rule.is_Bool(), "PatternRule for bool isn't _Bool");
bool test_val = rule.as_Bool();
-
+
auto succ_bb = builder.new_bb_unlinked();
-
+
if( test_val ) {
builder.end_block( ::MIR::Terminator::make_If({ val.clone(), succ_bb, fail_bb }) );
}
@@ -1546,7 +1546,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
),
(Value,
auto succ_bb = builder.new_bb_unlinked();
-
+
auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint()));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
@@ -1568,7 +1568,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
),
(Value,
auto succ_bb = builder.new_bb_unlinked();
-
+
auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Int()));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
@@ -1586,7 +1586,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
),
(Value,
auto succ_bb = builder.new_bb_unlinked();
-
+
auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint()));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
@@ -1595,19 +1595,19 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
(ValueRange,
auto succ_bb = builder.new_bb_unlinked();
auto test_bb_2 = builder.new_bb_unlinked();
-
+
// IF `val` < `first` : fail_bb
auto test_lt_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.first.as_Uint()));
auto cmp_lt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::LT, mv$(test_lt_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lt_lval), fail_bb, test_bb_2 }) );
-
+
builder.set_cur_block(test_bb_2);
-
+
// IF `val` > `last` : fail_bb
auto test_gt_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.last.as_Uint()));
auto cmp_gt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::GT, mv$(test_gt_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_gt_lval), fail_bb, succ_bb }) );
-
+
builder.set_cur_block(succ_bb);
)
)
@@ -1619,9 +1619,9 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
case ::HIR::CoreType::Str: {
ASSERT_BUG(sp, rule.is_Value() && rule.as_Value().is_StaticString(), "");
const auto& v = rule.as_Value();
-
+
auto succ_bb = builder.new_bb_unlinked();
-
+
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()), ::MIR::RValue(::MIR::Constant( v.as_StaticString() )));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, ::MIR::LValue::make_Deref({box$(test_lval)}) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
@@ -1659,17 +1659,17 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
ASSERT_BUG(sp, rule.is_Variant(), "Rule for enum isn't Any or Variant");
const auto& re = rule.as_Variant();
unsigned int var_idx = re.idx;
-
+
auto next_bb = builder.new_bb_unlinked();
auto var_count = pbe->m_variants.size();
-
+
// Generate a switch with only one option different.
::std::vector< ::MIR::BasicBlockId> arms(var_count, fail_bb);
arms[var_idx] = next_bb;
builder.end_block( ::MIR::Terminator::make_Switch({ val.clone(), mv$(arms) }) );
-
+
builder.set_cur_block(next_bb);
-
+
if( re.sub_rules.size() > 0 )
{
const auto& var_data = pbe->m_variants.at(re.idx).second;
@@ -1689,7 +1689,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
fake_ty_ents.push_back( monomorph(ve[i].ent) );
}
::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) );
-
+
// Recurse with the new ruleset
MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
re.sub_rules.data(), re.sub_rules.size(),
@@ -1706,7 +1706,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
fake_ty_ents.push_back( monomorph(ve[i].second.ent) );
}
::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) );
-
+
// Recurse with the new ruleset
MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
re.sub_rules.data(), re.sub_rules.size(),
@@ -1752,11 +1752,11 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
if( rule.is_Value() ) {
ASSERT_BUG(sp, *te.inner == ::HIR::CoreType::U8, "Bytes pattern on non-&[u8]");
auto cloned_val = ::MIR::Constant( rule.as_Value().as_Bytes() );
-
+
auto succ_bb = builder.new_bb_unlinked();
-
+
auto inner_val = val.as_Deref().val->clone();
-
+
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()), ::MIR::RValue(mv$(cloned_val)));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(inner_val), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
@@ -1764,16 +1764,16 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
}
else if( rule.is_Slice() ) {
const auto& re = rule.as_Slice();
-
+
// Compare length
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.len) ));
auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::EQ, mv$(test_lval) }));
-
+
auto len_succ_bb = builder.new_bb_unlinked();
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), len_succ_bb, fail_bb }) );
builder.set_cur_block(len_succ_bb);
-
+
// Recurse checking values
MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
re.sub_rules.data(), re.sub_rules.size(),
@@ -1783,22 +1783,22 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
}
else if( rule.is_SplitSlice() ) {
const auto& re = rule.as_SplitSlice();
-
+
// Compare length
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.min_len) ));
auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::LT, mv$(test_lval) }));
-
+
auto len_succ_bb = builder.new_bb_unlinked();
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), fail_bb, len_succ_bb }) ); // if len < test : FAIL
builder.set_cur_block(len_succ_bb);
-
+
MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
re.leading.data(), re.leading.size(),
top_ty, top_val, field_path_ofs,
fail_bb
);
-
+
if( re.trailing.size() > 0 )
{
TODO(sp, "Match over Slice using SplitSlice with trailing - " << rule);
@@ -1841,13 +1841,13 @@ struct DecisionTreeNode
(Subtree, ::std::unique_ptr<DecisionTreeNode>),
(Terminal, unsigned int)
);
-
+
template<typename T>
struct Range
{
T start;
T end;
-
+
// `x` starts after this range ends
bool operator<(const Range<T>& x) const {
return (end < x.start);
@@ -1856,7 +1856,7 @@ struct DecisionTreeNode
bool operator<(const T& x) const {
return (end < x);
}
-
+
// `x` ends before this starts, or overlaps
bool operator>=(const Range<T>& x) const {
return start > x.end || ovelaps(x);
@@ -1865,28 +1865,28 @@ struct DecisionTreeNode
bool operator>=(const T& x) const {
return start > x || contains(x);
}
-
+
bool operator>(const Range<T>& x) const {
return (start > x.end);
}
bool operator>(const T& x) const {
return (start > x);
}
-
+
bool operator==(const Range<T>& x) const {
return start == x.start && end == x.end;
}
bool operator!=(const Range<T>& x) const {
return start != x.start || end != x.end;
}
-
+
bool contains(const T& x) const {
return (start <= x && x <= end);
}
bool overlaps(const Range<T>& x) const {
return (x.start <= start && start <= x.end) || (x.start <= end && end <= x.end);
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Range<T>& x) {
if( x.start == x.end ) {
return os << x.start;
@@ -1896,7 +1896,7 @@ struct DecisionTreeNode
}
}
};
-
+
TAGGED_UNION( Values, Unset,
(Unset, struct {}),
(Bool, struct { Branch false_branch, true_branch; }),
@@ -1910,23 +1910,23 @@ struct DecisionTreeNode
//::std::vector< ::std::pair< unsigned int, Branch> > variable_arms;
})
);
-
+
// TODO: Arm specialisation?
field_path_t m_field_path;
Values m_branches;
Branch m_default;
-
+
DecisionTreeNode( field_path_t field_path ):
// TODO: This is commented out fo a reason, but I don't know why.
//m_field_path( mv$(field_path) ),
m_branches(),
m_default()
{}
-
+
static Branch clone(const Branch& b);
static Values clone(const Values& x);
DecisionTreeNode clone() const;
-
+
void populate_tree_from_rule(const Span& sp, unsigned int arm_index, const PatternRule* first_rule, unsigned int rule_count) {
populate_tree_from_rule(sp, first_rule, rule_count, [sp,arm_index](auto& branch){
TU_MATCHA( (branch), (e),
@@ -1951,14 +1951,14 @@ struct DecisionTreeNode
}
// `and_then` - Closure called after processing the final rule
void populate_tree_from_rule(const Span& sp, const PatternRule* first_rule, unsigned int rule_count, ::std::function<void(Branch&)> and_then);
-
+
/// Simplifies the tree by eliminating nodes that don't make a decision
void simplify();
/// Propagate the m_default arm's contents to value arms, and vice-versa
void propagate_default();
/// HELPER: Unfies the rules from the provided branch with this node
void unify_from(const Branch& b);
-
+
::MIR::LValue get_field(const ::MIR::LValue& base, unsigned int base_depth) const {
::MIR::LValue cur = base.clone();
for(unsigned int i = base_depth; i < m_field_path.size(); i ++ ) {
@@ -1972,7 +1972,7 @@ struct DecisionTreeNode
}
return cur;
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const Branch& x);
friend ::std::ostream& operator<<(::std::ostream& os, const DecisionTreeNode& x);
};
@@ -1981,16 +1981,16 @@ struct DecisionTreeGen
{
MirBuilder& m_builder;
const ::std::vector< ::MIR::BasicBlockId>& m_rule_blocks;
-
+
DecisionTreeGen(MirBuilder& builder, const ::std::vector< ::MIR::BasicBlockId >& rule_blocks):
m_builder( builder ),
m_rule_blocks( rule_blocks )
{}
-
+
::MIR::BasicBlockId get_block_for_rule(unsigned int rule_index) {
return m_rule_blocks.at( rule_index );
}
-
+
void generate_tree_code(const Span& sp, const DecisionTreeNode& node, const ::HIR::TypeRef& ty, const ::MIR::LValue& val) {
generate_tree_code(sp, node, ty, 0, val, [&](const auto& n){
DEBUG("node = " << n);
@@ -2004,9 +2004,9 @@ struct DecisionTreeGen
const ::HIR::TypeRef& ty, unsigned int path_ofs, const ::MIR::LValue& base_val,
::std::function<void(const DecisionTreeNode&)> and_then
);
-
+
void generate_branch(const DecisionTreeNode::Branch& branch, ::std::function<void(const DecisionTreeNode&)> cb);
-
+
void generate_branches_Signed(
const Span& sp,
const DecisionTreeNode::Branch& default_branch,
@@ -2049,7 +2049,7 @@ struct DecisionTreeGen
const ::HIR::TypeRef& ty, ::MIR::LValue val,
::std::function<void(const DecisionTreeNode&)> and_then
);
-
+
void generate_branches_Enum(
const Span& sp,
const DecisionTreeNode::Branch& default_branch,
@@ -2077,7 +2077,7 @@ struct DecisionTreeGen
void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNode_Match& node, ::MIR::LValue match_val, t_arm_rules arm_rules, ::std::vector<ArmCode> arms_code, ::MIR::BasicBlockId first_cmp_block )
{
TRACE_FUNCTION;
-
+
// XXX XXX XXX: The current codegen (below) will generate incorrect code if ordering matters.
// ```
// match ("foo", "bar")
@@ -2091,14 +2091,14 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, :
// TODO: Sort the columns in `arm_rules` to ensure that the most specific rule is parsed first.
// - Ordering within a pattern doesn't matter, only the order of arms matters.
// - This sort could be designed such that the above case would match correctly?
-
+
DEBUG("- Generating rule bindings");
::std::vector< ::MIR::BasicBlockId> rule_blocks;
for(const auto& rule : arm_rules)
{
const auto& arm_code = arms_code[rule.arm_idx];
ASSERT_BUG(node.span(), !arm_code.has_condition, "Decision tree doesn't (yet) support conditionals");
-
+
assert( rule.pat_idx < arm_code.destructures.size() );
// Set the target for when a rule succeeds to the destructuring code for this rule
rule_blocks.push_back( arm_code.destructures[rule.pat_idx] );
@@ -2106,8 +2106,8 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, :
builder.set_cur_block( rule_blocks.back() );
builder.end_block( ::MIR::Terminator::make_Goto(arm_code.code) );
}
-
-
+
+
// - Build tree by running each arm's pattern across it
DEBUG("- Building decision tree");
DecisionTreeNode root_node({});
@@ -2125,7 +2125,7 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, :
root_node.propagate_default();
DEBUG("root_node = " << root_node);
// TODO: Pretty print `root_node`
-
+
// - Convert the above decision tree into MIR
DEBUG("- Emitting decision tree");
DecisionTreeGen gen { builder, rule_blocks };
@@ -2144,7 +2144,7 @@ DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree(const Span& sp, t_arm
rules.push_back( arm_rules[i].m_rules );
indexes.push_back(i);
}
-
+
return MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(sp, indexes, rules);
}
DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(const Span& sp, slice<unsigned int> arm_indexes, slice< slice<PaternRule>> arm_rules)
@@ -2152,13 +2152,13 @@ DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(const Span& sp,
assert( arm_indexes.size() == arm_rules.size() );
assert( arm_rules.size() > 1 );
assert( arm_rules[0].size() > 0 );
-
+
// 1. Sort list (should it already be sorted?)
for(const auto& rules : arm_rules)
{
ASSERT_BUG(sp, rules.size() != arm_rules[0].size(), "");
}
-
+
// 2. Detect all arms being `_` and move on to the next condition
while( ::std::all_of(arm_rules.begin(), arm_rules.end(), [](const auto& r){ return r.m_rules[0].is_Any(); }) )
{
@@ -2167,27 +2167,27 @@ DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(const Span& sp,
// No rules left?
BUG(sp, "Duplicate match arms");
}
-
+
for(auto& rules : arm_rules)
{
rules = rules.subslice_from(1);
}
}
-
+
// We have a codition.
for(const auto& rules : arm_rules)
{
ASSERT_BUG(sp, rules[0].is_Any() || rules[0].tag() == arm_rules[0][0].tag(), "Mismatched rules in match");
}
-
+
bool has_any = arm_rules.back()[0].is_Any();
-
+
// All rules must either be _ or the same type, and can't all be _
switch( arm_rules[0][0].tag() )
{
case PatternRule::TAGDEAD: throw "";
case PatternRule::TAG_Any: throw "";
-
+
case PatternRule::TAG_Variant:
break;
// TODO: Value and ValueRange can appear together.
@@ -2273,7 +2273,7 @@ namespace
{
return DecisionTreeNode::Branch( box$(DecisionTreeNode( mv$(path) )) );
}
-
+
// Common code for numerics (Int, Uint, and Float)
template<typename T>
static void from_rule_valuerange(
@@ -2284,7 +2284,7 @@ namespace
{
ASSERT_BUG(sp, ve_start != ve_end, "Range pattern with one value - " << ve_start);
ASSERT_BUG(sp, ve_start < ve_end, "Range pattern with a start after the end - " << ve_start << "..." << ve_end);
-
+
TRACE_FUNCTION_F("[" << FMT_CB(os, for(const auto& i:be) os << i.first <<" , ";) << "]");
// - Find the first entry that ends after the new one starts.
auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first.end >= ve_start; });
@@ -2332,7 +2332,7 @@ namespace
DEBUG("- Shared head, continue");
//assert(it->first.start == ve_start);
assert((it->first.end) < ve_end);
-
+
if( it->first.start != it->first.end )
and_then(it->second);
ve_start = it->first.end + 1;
@@ -2340,7 +2340,7 @@ namespace
}
}
}
-
+
template<typename T>
static void from_rule_value(
const Span& sp,
@@ -2366,14 +2366,14 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
{
assert( rule_count > 0 );
const auto& rule = *first_rule;
-
+
if( m_field_path.size() == 0 ) {
m_field_path = rule.field_path;
}
else {
ASSERT_BUG(sp, m_field_path == rule.field_path, "Patterns with mismatched field paths - " << m_field_path << " != " << rule.field_path);
}
-
+
#define GET_BRANCHES(fld, var) (({if( fld.is_Unset() ) {\
fld = Values::make_##var({}); \
} \
@@ -2382,7 +2382,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
}}), \
fld.as_##var())
-
+
TU_MATCHA( (rule), (e),
(Any, {
if( rule_count == 1 )
@@ -2408,7 +2408,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
}),
(Variant, {
auto& be = GET_BRANCHES(m_branches, Variant);
-
+
auto it = ::std::find_if( be.begin(), be.end(), [&](const auto& x){ return x.first >= e.idx; });
// If this variant isn't yet processed, add a new subtree for it
if( it == be.end() || it->first != e.idx ) {
@@ -2423,7 +2423,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
assert( it->second.is_Subtree() );
}
auto& subtree = *it->second.as_Subtree();
-
+
if( e.sub_rules.size() > 0 && rule_count > 1 )
{
subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), [&](auto& branch){
@@ -2455,7 +2455,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
}),
(Slice,
auto& be = GET_BRANCHES(m_branches, Slice);
-
+
auto it = ::std::find_if( be.fixed_arms.begin(), be.fixed_arms.end(), [&](const auto& x){ return x.first >= e.len; } );
if( it == be.fixed_arms.end() || it->first != e.len ) {
it = be.fixed_arms.insert(it, ::std::make_pair(e.len, new_branch_subtree(rule.field_path)));
@@ -2468,7 +2468,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
}
assert( it->second.is_Subtree() );
auto& subtree = *it->second.as_Subtree();
-
+
if( e.sub_rules.size() > 0 && rule_count > 1 )
{
subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), [&](auto& branch){
@@ -2504,7 +2504,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
),
(Bool,
auto& be = GET_BRANCHES(m_branches, Bool);
-
+
auto& branch = (e ? be.true_branch : be.false_branch);
if( branch.is_Unset() ) {
branch = new_branch_subtree( rule.field_path );
@@ -2529,7 +2529,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
TU_MATCHA( (e), (ve),
(Int,
auto& be = GET_BRANCHES(m_branches, Signed);
-
+
// TODO: De-duplicate this code between Uint and Float
from_rule_value(sp, be, ve, "Signed", rule.field_path,
[&](auto& branch) {
@@ -2546,7 +2546,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
),
(Uint,
auto& be = GET_BRANCHES(m_branches, Unsigned);
-
+
from_rule_value(sp, be, ve, "Unsigned", rule.field_path,
[&](auto& branch) {
if( rule_count > 1 ) {
@@ -2562,7 +2562,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
),
(Float,
auto& be = GET_BRANCHES(m_branches, Float);
-
+
from_rule_value(sp, be, ve, "Float", rule.field_path,
[&](auto& branch) {
if( rule_count > 1 ) {
@@ -2583,7 +2583,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
),
(StaticString,
auto& be = GET_BRANCHES(m_branches, String);
-
+
auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first >= ve; });
if( it == be.end() || it->first != ve ) {
it = be.insert( it, ::std::make_pair(ve, new_branch_subtree(rule.field_path) ) );
@@ -2609,7 +2609,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule
)
),
(ValueRange,
-
+
ASSERT_BUG(sp, e.first.tag() == e.last.tag(), "");
TU_MATCHA( (e.first, e.last), (ve_start, ve_end),
(Int,
@@ -2695,7 +2695,7 @@ void DecisionTreeNode::simplify()
)
}
};
-
+
TU_MATCHA( (m_branches), (e),
(Unset,
H::simplify_branch(m_default);
@@ -2742,7 +2742,7 @@ void DecisionTreeNode::simplify()
}
)
)
-
+
H::simplify_branch(m_default);
}
@@ -2762,7 +2762,7 @@ void DecisionTreeNode::propagate_default()
)
}
};
-
+
TU_MATCHA( (m_branches), (e),
(Unset,
),
@@ -2812,7 +2812,7 @@ void DecisionTreeNode::propagate_default()
DEBUG("- default");
TU_IFLET(Branch, m_default, Subtree, be,
be->propagate_default();
-
+
if( be->m_default.is_Unset() ) {
// Propagate default from value branches
TU_MATCHA( (m_branches), (e),
@@ -2869,7 +2869,7 @@ namespace {
// Terminal, no unify
}
}
-
+
template<typename T>
void unify_from_vals_range(::std::vector< ::std::pair<T, DecisionTreeNode::Branch>>& dst, const ::std::vector< ::std::pair<T, DecisionTreeNode::Branch>>& src)
{
@@ -2893,7 +2893,7 @@ namespace {
}
}
}
-
+
template<typename T>
void unify_from_vals_pt(::std::vector< ::std::pair<T, DecisionTreeNode::Branch>>& dst, const ::std::vector< ::std::pair<T, DecisionTreeNode::Branch>>& src)
{
@@ -2915,9 +2915,9 @@ namespace {
void DecisionTreeNode::unify_from(const Branch& b)
{
TRACE_FUNCTION_FR(*this << " with " << b, *this);
-
+
assert( b.is_Terminal() || b.is_Subtree() );
-
+
if( m_default.is_Unset() ) {
if( b.is_Terminal() ) {
m_default = clone(b);
@@ -2926,7 +2926,7 @@ void DecisionTreeNode::unify_from(const Branch& b)
m_default = clone(b.as_Subtree()->m_default);
}
}
-
+
if( b.is_Subtree() && b.as_Subtree()->m_branches.tag() != m_branches.tag() ) {
// Is this a bug, or expected (and don't unify in?)
DEBUG("TODO - Unify mismatched arms? - " << b.as_Subtree()->m_branches.tag_str() << " and " << m_branches.tag_str());
@@ -2936,7 +2936,7 @@ void DecisionTreeNode::unify_from(const Branch& b)
//if( b.is_Subtree() ) {
// ASSERT_BUG(Span(), this->m_field_path == b.as_Subtree()->m_field_path, "Unifiying DTNs with mismatched paths - " << this->m_field_path << " != " << b.as_Subtree()->m_field_path);
//}
-
+
TU_MATCHA( (m_branches), (dst),
(Unset,
if( b.is_Subtree() ) {
@@ -2948,7 +2948,7 @@ void DecisionTreeNode::unify_from(const Branch& b)
),
(Bool,
auto* src = (b.is_Subtree() ? &b.as_Subtree()->m_branches.as_Bool() : nullptr);
-
+
unify_branch( dst.false_branch, (src ? src->false_branch : b) );
unify_branch( dst.true_branch , (src ? src->true_branch : b) );
),
@@ -3020,7 +3020,7 @@ void DecisionTreeNode::unify_from(const Branch& b)
if( should_unify_subtree ) {
auto& sb = b.as_Subtree()->m_branches;
ASSERT_BUG(Span(), sb.is_Slice(), "Unifying Slice with " << sb.tag_str());
-
+
const auto& src = sb.as_Slice();
unify_from_vals_pt(dst.fixed_arms, src.fixed_arms);
}
@@ -3113,7 +3113,7 @@ void DecisionTreeNode::unify_from(const Branch& b)
}
)
)
-
+
os << "* = " << x.m_default;
os << " }";
return os;
@@ -3132,13 +3132,13 @@ void DecisionTreeGen::generate_tree_code(
)
{
TRACE_FUNCTION_F("top_ty=" << top_ty << ", field_path_ofs=" << field_path_ofs << ", top_val=" << top_val << ", node=" << node);
-
+
::MIR::LValue val;
::HIR::TypeRef ty;
-
+
get_ty_and_val(sp, m_builder.resolve(), top_ty, top_val, node.m_field_path, field_path_ofs, ty, val);
DEBUG("ty = " << ty << ", val = " << val);
-
+
TU_MATCHA( (ty.m_data), (e),
(Infer, BUG(sp, "Ivar for in match type"); ),
(Diverge, BUG(sp, "Diverge in match type"); ),
@@ -3265,7 +3265,7 @@ void DecisionTreeGen::generate_branch(const DecisionTreeNode::Branch& branch, ::
else {
assert( branch.is_Subtree() );
const auto& subnode = *branch.as_Subtree();
-
+
cb(subnode);
}
}
@@ -3279,16 +3279,16 @@ void DecisionTreeGen::generate_branches_Signed(
)
{
auto default_block = m_builder.new_bb_unlinked();
-
+
// TODO: Convert into an integer switch w/ offset instead of chained comparisons
-
+
for( const auto& branch : branches )
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
-
+
auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
-
+
auto cmp_gt_block = m_builder.new_bb_unlinked();
auto val_cmp_lt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
@@ -3300,14 +3300,14 @@ void DecisionTreeGen::generate_branches_Signed(
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( next_block );
}
assert( m_builder.block_active() );
-
+
if( default_branch.is_Unset() ) {
// TODO: Emit error if non-exhaustive
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
@@ -3326,16 +3326,16 @@ void DecisionTreeGen::generate_branches_Unsigned(
)
{
auto default_block = m_builder.new_bb_unlinked();
-
+
// TODO: Convert into an integer switch w/ offset instead of chained comparisons
-
+
for( const auto& branch : branches )
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
-
+
auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
-
+
auto cmp_gt_block = m_builder.new_bb_unlinked();
auto val_cmp_lt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
@@ -3347,14 +3347,14 @@ void DecisionTreeGen::generate_branches_Unsigned(
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( next_block );
}
assert( m_builder.block_active() );
-
+
if( default_branch.is_Unset() ) {
// TODO: Emit error if non-exhaustive
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
@@ -3373,14 +3373,14 @@ void DecisionTreeGen::generate_branches_Float(
)
{
auto default_block = m_builder.new_bb_unlinked();
-
+
for( const auto& branch : branches )
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
-
+
auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
-
+
auto cmp_gt_block = m_builder.new_bb_unlinked();
auto val_cmp_lt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
@@ -3392,14 +3392,14 @@ void DecisionTreeGen::generate_branches_Float(
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( next_block );
}
assert( m_builder.block_active() );
-
+
if( default_branch.is_Unset() ) {
ERROR(sp, E0000, "Match over floating point with no `_` arm");
}
@@ -3417,16 +3417,16 @@ void DecisionTreeGen::generate_branches_Char(
)
{
auto default_block = m_builder.new_bb_unlinked();
-
+
// TODO: Convert into an integer switch w/ offset instead of chained comparisons
-
+
for( const auto& branch : branches )
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
-
+
auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
-
+
auto cmp_gt_block = m_builder.new_bb_unlinked();
auto val_cmp_lt = m_builder.lvalue_or_temp( sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
@@ -3438,14 +3438,14 @@ void DecisionTreeGen::generate_branches_Char(
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( next_block );
}
assert( m_builder.block_active() );
-
+
if( default_branch.is_Unset() ) {
// TODO: Error if not exhaustive.
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
@@ -3463,7 +3463,7 @@ void DecisionTreeGen::generate_branches_Bool(
)
{
//assert( ty.m_data.is_Boolean() );
-
+
if( default_branch.is_Unset() )
{
if( branches.false_branch.is_Unset() || branches.true_branch.is_Unset() ) {
@@ -3476,16 +3476,16 @@ void DecisionTreeGen::generate_branches_Bool(
// Unreachable default (NOTE: Not an error here)
}
}
-
+
// Emit an if based on the route taken
auto bb_false = m_builder.new_bb_unlinked();
auto bb_true = m_builder.new_bb_unlinked();
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val), bb_true, bb_false }) );
-
+
// Recurse into sub-patterns
const auto& branch_false = ( !branches.false_branch.is_Unset() ? branches.false_branch : default_branch );
const auto& branch_true = ( !branches. true_branch.is_Unset() ? branches. true_branch : default_branch );
-
+
m_builder.set_cur_block(bb_true );
this->generate_branch(branch_true , and_then);
m_builder.set_cur_block(bb_false);
@@ -3505,35 +3505,35 @@ void DecisionTreeGen::generate_branches_Borrow_str(
// - rustc emits calls to PartialEq::eq for this and for slices. mrustc could use PartialOrd and fall back to PartialEq if unavaliable?
// > Requires crate access here! - A memcmp call is probably better, probably via a binop
// NOTE: The below implementation gets the final codegen to call memcmp on the strings by emitting eBinOp::{LT,GT}
-
+
// - Remove the wrapping Deref (which must be there)
ASSERT_BUG(sp, val.is_Deref(), "Match over str without a deref - " << val);
auto tmp = mv$( *val.as_Deref().val );
val = mv$(tmp);
-
+
auto default_bb = m_builder.new_bb_unlinked();
-
+
assert( !branches.empty() );
for(const auto& branch : branches)
{
auto have_val = val.clone();
-
+
auto next_bb = (&branch == &branches.back() ? default_bb : m_builder.new_bb_unlinked());
-
+
auto test_val = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ::HIR::CoreType::Str), ::MIR::Constant(branch.first) );
auto cmp_gt_bb = m_builder.new_bb_unlinked();
-
+
auto lt_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ have_val.clone(), ::MIR::eBinOp::LT, test_val.clone() }) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(lt_val), default_bb, cmp_gt_bb }) );
m_builder.set_cur_block(cmp_gt_bb);
-
+
auto eq_bb = m_builder.new_bb_unlinked();
auto gt_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(have_val), ::MIR::eBinOp::GT, test_val.clone() }) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(gt_val), next_bb, eq_bb }) );
m_builder.set_cur_block(eq_bb);
-
+
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block(next_bb);
}
this->generate_branch(default_branch, and_then);
@@ -3553,7 +3553,7 @@ void DecisionTreeGen::generate_branches_Enum(
const auto& variants = enum_ref.m_variants;
auto variant_count = variants.size();
bool has_any = ! default_branch.is_Unset();
-
+
if( branches.size() < variant_count && ! has_any ) {
ERROR(sp, E0000, "Non-exhaustive match over " << ty << " - " << branches.size() << " out of " << variant_count << " present");
}
@@ -3561,9 +3561,9 @@ void DecisionTreeGen::generate_branches_Enum(
//if( branches.size() == variant_count && has_any ) {
// ERROR(sp, E0000, "Unreachable _ arm - " << branches.size() << " variants in " << enum_path);
//}
-
+
auto any_block = (has_any ? m_builder.new_bb_unlinked() : 0);
-
+
// Emit a switch over the variant
::std::vector< ::MIR::BasicBlockId> variant_blocks;
variant_blocks.reserve( variant_count );
@@ -3583,22 +3583,22 @@ void DecisionTreeGen::generate_branches_Enum(
variant_blocks.resize( variant_count, any_block );
}
bool any_arm_used = ::std::any_of( variant_blocks.begin(), variant_blocks.end(), [any_block](const auto& blk){ return blk == any_block; } );
-
+
m_builder.end_block( ::MIR::Terminator::make_Switch({
val.clone(), variant_blocks // NOTE: Copies the list, so it can be used lower down
}) );
-
+
// Emit sub-patterns, looping over variants
for( const auto& branch : branches )
{
auto bb = variant_blocks[branch.first];
const auto& var = variants[branch.first];
DEBUG(branch.first << " " << var.first << " = " << branch.second);
-
+
auto var_lval = ::MIR::LValue::make_Downcast({ box$(val.clone()), branch.first });
-
+
::HIR::TypeRef fake_ty;
-
+
TU_MATCHA( (var.second), (e),
(Unit,
DEBUG("- Unit");
@@ -3628,7 +3628,7 @@ void DecisionTreeGen::generate_branches_Enum(
DEBUG("- Struct - " << fake_ty);
)
)
-
+
m_builder.set_cur_block( bb );
if( fake_ty == ::HIR::TypeRef() || fake_ty.m_data.as_Tuple().size() == 0 ) {
this->generate_branch(branch.second, and_then);
@@ -3640,7 +3640,7 @@ void DecisionTreeGen::generate_branches_Enum(
});
}
}
-
+
if( any_arm_used )
{
DEBUG("_ = " << default_branch);
@@ -3668,46 +3668,46 @@ void DecisionTreeGen::generate_branches_Slice(
if( default_branch.is_Unset() ) {
ERROR(sp, E0000, "Non-exhaustive match over " << ty);
}
-
+
// NOTE: Un-deref the slice
ASSERT_BUG(sp, val.is_Deref(), "slice matches must be passed a deref");
auto tmp = mv$( *val.as_Deref().val );
val = mv$(tmp);
-
+
auto any_block = m_builder.new_bb_unlinked();
-
+
// TODO: Select one of three ways of picking the arm:
// - Integer switch (unimplemented)
// - Binary search
// - Sequential comparisons
-
+
auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
-
+
// TODO: Binary search instead.
for( const auto& branch : branches.fixed_arms )
{
auto val_des = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::Constant(static_cast<uint64_t>(branch.first)));
-
+
// Special case - final just does equality
if( &branch == &branches.fixed_arms.back() )
{
auto val_cmp_eq = m_builder.lvalue_or_temp( sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val_len.clone(), ::MIR::eBinOp::EQ, mv$(val_des)
}) );
-
+
auto success_block = m_builder.new_bb_unlinked();
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_eq), any_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( any_block );
}
// TODO: Special case for zero (which can't have a LT)
else
{
auto next_block = m_builder.new_bb_unlinked();
-
+
auto cmp_gt_block = m_builder.new_bb_unlinked();
auto val_cmp_lt = m_builder.lvalue_or_temp( sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val_len.clone(), ::MIR::eBinOp::LT, val_des.clone()
@@ -3719,15 +3719,15 @@ void DecisionTreeGen::generate_branches_Slice(
val_len.clone(), ::MIR::eBinOp::GT, mv$(val_des)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
-
+
m_builder.set_cur_block( success_block );
this->generate_branch(branch.second, and_then);
-
+
m_builder.set_cur_block( next_block );
}
}
assert( m_builder.block_active() );
-
+
if( default_branch.is_Unset() ) {
// TODO: Emit error if non-exhaustive
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp
index dc149cd2..027c68b7 100644
--- a/src/mir/helpers.cpp
+++ b/src/mir/helpers.cpp
@@ -206,7 +206,7 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c
MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range");
const auto& variant = unm.m_variants[e.variant_index];
const auto& var_ty = variant.second.ent;
-
+
if( monomorphise_type_needed(var_ty) ) {
tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent);
m_resolve.expand_associated_types(sp, tmp);
diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp
index b0499ec8..40dbd4a3 100644
--- a/src/mir/helpers.hpp
+++ b/src/mir/helpers.hpp
@@ -40,7 +40,7 @@ public:
typedef ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> > args_t;
private:
const unsigned int STMT_TERM = ~0u;
-
+
public:
const Span& sp;
const ::StaticTraitResolve& m_resolve;
@@ -51,7 +51,7 @@ private:
const args_t& m_args;
const ::MIR::Function& m_fcn;
const ::HIR::SimplePath* m_lang_Box = nullptr;
-
+
unsigned int bb_idx = 0;
unsigned int stmt_idx = 0;
@@ -69,7 +69,7 @@ public:
m_lang_Box = &m_crate.m_lang_items.at("owned_box");
}
}
-
+
void set_cur_stmt(unsigned int bb_idx, unsigned int stmt_idx) {
this->bb_idx = bb_idx;
this->stmt_idx = stmt_idx;
@@ -78,7 +78,7 @@ public:
this->bb_idx = bb_idx;
this->stmt_idx = STMT_TERM;
}
-
+
void print_bug(::std::function<void(::std::ostream& os)> cb) const {
print_msg("ERROR", cb);
}
@@ -86,12 +86,12 @@ public:
print_msg("TODO", cb);
}
void print_msg(const char* tag, ::std::function<void(::std::ostream& os)> cb) const;
-
+
const ::MIR::BasicBlock& get_block(::MIR::BasicBlockId id) const;
-
+
const ::HIR::TypeRef& get_static_type(::HIR::TypeRef& tmp, const ::HIR::Path& path) const;
const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const;
-
+
const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const;
};
diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp
index d7ae41cc..f7a5f3e8 100644
--- a/src/mir/mir.cpp
+++ b/src/mir/mir.cpp
@@ -50,7 +50,7 @@ namespace MIR {
)
return os;
}
-
+
::std::ostream& operator<<(::std::ostream& os, const LValue& x)
{
TU_MATCHA( (x), (e),
@@ -116,13 +116,13 @@ namespace MIR {
case ::MIR::eBinOp::SUB_OV: os << "SUB_OV"; break;
case ::MIR::eBinOp::MUL_OV: os << "MUL_OV"; break;
case ::MIR::eBinOp::DIV_OV: os << "DIV_OV"; break;
-
+
case ::MIR::eBinOp::BIT_OR : os << "BIT_OR" ; break;
case ::MIR::eBinOp::BIT_AND: os << "BIT_AND"; break;
case ::MIR::eBinOp::BIT_XOR: os << "BIT_XOR"; break;
case ::MIR::eBinOp::BIT_SHL: os << "BIT_SHL"; break;
case ::MIR::eBinOp::BIT_SHR: os << "BIT_SHR"; break;
-
+
case ::MIR::eBinOp::EQ: os << "EQ"; break;
case ::MIR::eBinOp::NE: os << "NE"; break;
case ::MIR::eBinOp::GT: os << "GT"; break;
@@ -159,7 +159,7 @@ namespace MIR {
)
return os;
}
-
+
::std::ostream& operator<<(::std::ostream& os, const Terminator& x)
{
TU_MATCHA( (x), (e),
diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp
index 1ac8ff78..5a6b83de 100644
--- a/src/mir/mir.hpp
+++ b/src/mir/mir.hpp
@@ -66,14 +66,14 @@ enum class eBinOp
MUL, MUL_OV,
DIV, DIV_OV,
MOD,// MOD_OV,
-
+
BIT_OR,
BIT_AND,
BIT_XOR,
-
+
BIT_SHR,
BIT_SHL,
-
+
EQ, NE,
GT, GE,
LT, LE,
@@ -222,7 +222,7 @@ class Function
public:
::std::vector< ::HIR::TypeRef> named_variables;
::std::vector< ::HIR::TypeRef> temporaries;
-
+
::std::vector<BasicBlock> blocks;
};
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index 367c4aa1..cd7ddbcd 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -24,14 +24,14 @@ MirBuilder::MirBuilder(const Span& sp, const StaticTraitResolve& resolve, const
if( resolve.m_crate.m_lang_items.count("owned_box") > 0 ) {
m_lang_Box = &resolve.m_crate.m_lang_items.at("owned_box");
}
-
+
set_cur_block( new_bb_unlinked() );
m_scopes.push_back( ScopeDef { sp } );
m_scope_stack.push_back( 0 );
-
+
m_scopes.push_back( ScopeDef { sp, ScopeType::make_Temporaries({}) } );
m_scope_stack.push_back( 1 );
-
+
m_variable_states.resize( output.named_variables.size(), VarState::Uninit );
}
MirBuilder::~MirBuilder()
@@ -57,12 +57,12 @@ const ::HIR::TypeRef* MirBuilder::is_type_owned_box(const ::HIR::TypeRef& ty) co
return nullptr;
}
const auto& te = ty.m_data.as_Path();
-
+
if( ! te.path.m_data.is_Generic() ) {
return nullptr;
}
const auto& pe = te.path.m_data.as_Generic();
-
+
if( pe.m_path != *m_lang_Box ) {
return nullptr;
}
@@ -101,11 +101,11 @@ void MirBuilder::define_variable(unsigned int idx)
{
unsigned int rv = m_output.temporaries.size();
DEBUG("DEFINE tmp" << rv << ": " << ty);
-
+
m_output.temporaries.push_back( ty.clone() );
m_temporary_states.push_back( VarState::Uninit );
assert(m_output.temporaries.size() == m_temporary_states.size());
-
+
ScopeDef* top_scope = nullptr;
for(unsigned int i = m_scope_stack.size(); i --; )
{
@@ -179,7 +179,7 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
ASSERT_BUG(sp, dst.tag() != ::MIR::LValue::TAGDEAD, "");
ASSERT_BUG(sp, val.tag() != ::MIR::RValue::TAGDEAD, "");
-
+
TU_MATCHA( (val), (e),
(Use,
this->moved_lvalue(sp, e);
@@ -248,7 +248,7 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
this->moved_lvalue(sp, val);
)
)
-
+
// Drop target if populated
mark_value_assigned(sp, dst);
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) );
@@ -257,25 +257,25 @@ void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val)
{
ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, "");
-
+
if( lvalue_is_copy(sp, val) ) {
// Don't emit a drop for Copy values
return ;
}
-
+
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val) }) );
}
void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val)
{
ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, "");
-
+
// TODO: Ensure that the type is a Box
//if( lvalue_is_copy(sp, val) ) {
// // Don't emit a drop for Copy values
// return ;
//}
-
+
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::SHALLOW, mv$(val) }) );
}
@@ -353,7 +353,7 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
while( scope_it != m_scope_stack.rend() )
{
auto& scope_def = m_scopes.at(*scope_it);
-
+
TU_IFLET( ScopeType, scope_def.data, Variables, e,
auto tmp_it = ::std::find( e.vars.begin(), e.vars.end(), idx );
if( tmp_it != e.vars.end() )
@@ -371,11 +371,11 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
return ;
}
++scope_it;
-
+
while( scope_it != m_scope_stack.rend() )
{
auto& scope_def = m_scopes.at(*scope_it);
-
+
TU_IFLET( ScopeType, scope_def.data, Variables, e,
e.vars.push_back( idx );
DEBUG("- to " << *scope_it);
@@ -383,7 +383,7 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
)
++scope_it;
}
-
+
DEBUG("- top");
),
(Temporary,
@@ -392,7 +392,7 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
while( scope_it != m_scope_stack.rend() )
{
auto& scope_def = m_scopes.at(*scope_it);
-
+
TU_IFLET( ScopeType, scope_def.data, Temporaries, e,
auto tmp_it = ::std::find( e.temporaries.begin(), e.temporaries.end(), idx );
if( tmp_it != e.temporaries.end() )
@@ -410,11 +410,11 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
return ;
}
++scope_it;
-
+
while( scope_it != m_scope_stack.rend() )
{
auto& scope_def = m_scopes.at(*scope_it);
-
+
TU_IFLET( ScopeType, scope_def.data, Temporaries, e,
e.temporaries.push_back( idx );
DEBUG("- to " << *scope_it);
@@ -422,7 +422,7 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val)
)
++scope_it;
}
-
+
DEBUG("- top");
)
)
@@ -571,42 +571,42 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl
BUG(sp, "Terminating scope not on the stack - scope " << scope.idx);
BUG(sp, "Terminating scope " << scope.idx << " when not at top of stack, " << (m_scope_stack.end() - it - 1) << " scopes in the way");
}
-
+
auto& scope_def = m_scopes.at(scope.idx);
ASSERT_BUG( sp, scope_def.complete == false, "Terminating scope which is already terminated" );
-
+
if( emit_cleanup )
{
// 2. Emit drops for all non-moved variables (share with below)
drop_scope_values(scope_def);
}
-
+
// 3. Pop scope (last because `drop_scope_values` uses the stack)
m_scope_stack.pop_back();
-
+
complete_scope(scope_def);
}
void MirBuilder::terminate_scope_early(const Span& sp, const ScopeHandle& scope)
{
DEBUG("EARLY scope " << scope.idx);
-
+
// 1. Ensure that this block is in the stack
auto it = ::std::find( m_scope_stack.begin(), m_scope_stack.end(), scope.idx );
if( it == m_scope_stack.end() ) {
BUG(sp, "Early-terminating scope not on the stack");
}
unsigned int slot = it - m_scope_stack.begin();
-
+
bool is_conditional = false;
for(unsigned int i = m_scope_stack.size(); i-- > slot; )
{
auto idx = m_scope_stack[i];
auto& scope_def = m_scopes.at( idx );
-
+
// If a conditional block is hit, prevent full termination of the rest
if( scope_def.data.is_Split() || scope_def.data.is_Loop() )
is_conditional = true;
-
+
if( !is_conditional ) {
DEBUG("Complete scope " << idx);
drop_scope_values(scope_def);
@@ -616,7 +616,7 @@ void MirBuilder::terminate_scope_early(const Span& sp, const ScopeHandle& scope)
else {
// Mark patial within this scope?
DEBUG("Drop part of scope " << idx);
-
+
// Emit drops for dropped values within this scope
drop_scope_values(scope_def);
// Inform the scope that it's been early-exited
@@ -633,9 +633,9 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r
ASSERT_BUG(sp, sd.data.is_Split(), "");
auto& sd_split = sd.data.as_Split();
ASSERT_BUG(sp, !sd_split.arms.empty(), "");
-
+
sd_split.arms.back().always_early_terminated = /*sd_split.arms.back().has_early_terminated &&*/ !reachable;
-
+
// HACK: If this arm's end is reachable, convert InnerMoved (shallow drop) variable states to Moved
// - I'm not 100% sure this is the correct place for calling drop.
if( reachable )
@@ -651,7 +651,7 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r
}
}
}
-
+
sd_split.arms.push_back( {} );
}
void MirBuilder::end_split_arm_early(const Span& sp)
@@ -666,13 +666,13 @@ void MirBuilder::end_split_arm_early(const Span& sp)
m_scope_stack.pop_back();
complete_scope(scope_def);
}
-
+
if( !m_scope_stack.empty() && m_scopes.at( m_scope_stack.back() ).data.is_Split() )
{
auto& sd = m_scopes[ m_scope_stack.back() ];
auto& sd_split = sd.data.as_Split();
sd_split.arms.back().has_early_terminated = true;
-
+
const auto& vss = sd_split.arms.back().var_states;
for(unsigned int i = 0; i < vss.size(); i ++ )
{
@@ -688,7 +688,7 @@ void MirBuilder::end_split_arm_early(const Span& sp)
void MirBuilder::complete_scope(ScopeDef& sd)
{
sd.complete = true;
-
+
TU_MATCHA( (sd.data), (e),
(Temporaries,
DEBUG("Temporaries " << e.temporaries);
@@ -702,16 +702,16 @@ void MirBuilder::complete_scope(ScopeDef& sd)
(Split,
)
)
-
+
// No macro for better debug output.
if( sd.data.is_Split() )
{
auto& e = sd.data.as_Split();
-
+
assert( e.arms.size() > 1 );
TRACE_FUNCTION_F("Split - " << (e.arms.size() - 1) << " arms");
e.arms.pop_back();
-
+
// Merge all arms and apply upwards
size_t var_count = 0;
size_t tmp_count = 0;
@@ -720,18 +720,18 @@ void MirBuilder::complete_scope(ScopeDef& sd)
var_count = ::std::max(var_count, arm.var_states.size());
tmp_count = ::std::max(tmp_count, arm.tmp_states.size());
}
-
+
struct StateMerger
{
::std::vector<bool> m_changed;
::std::vector<VarState> m_new_states;
-
+
StateMerger(size_t var_count):
m_changed(var_count),
m_new_states(var_count)
{
}
-
+
void merge_arm_state(const Span& sp, unsigned int i, bool has_changed, VarState new_state)
{
assert(i < this->m_new_states.size());
@@ -828,7 +828,7 @@ void MirBuilder::complete_scope(ScopeDef& sd)
}
}
};
-
+
StateMerger sm_var { var_count };
StateMerger sm_tmp { tmp_count };
for(const auto& arm : e.arms)
@@ -841,7 +841,7 @@ void MirBuilder::complete_scope(ScopeDef& sd)
{
sm_var.merge_arm_state(sd.span, i, arm.changed_var_states[i], arm.var_states[i]);
}
-
+
DEBUG(">TMP<");
assert( arm.changed_tmp_states.size() == arm.tmp_states.size() );
for(unsigned int i = 0; i < arm.tmp_states.size(); i ++ )
@@ -849,7 +849,7 @@ void MirBuilder::complete_scope(ScopeDef& sd)
sm_tmp.merge_arm_state(sd.span, i, arm.changed_tmp_states[i], arm.tmp_states[i]);
}
}
-
+
for(unsigned int i = 0; i < var_count; i ++ )
{
if( sm_var.m_changed[i] )
@@ -1083,7 +1083,7 @@ VarState MirBuilder::get_variable_state(const Span& sp, unsigned int idx) const
)
)
}
-
+
ASSERT_BUG(sp, idx < m_variable_states.size(), "Variable " << idx << " out of range for state table");
return m_variable_states[idx];
}
@@ -1114,7 +1114,7 @@ void MirBuilder::set_variable_state(const Span& sp, unsigned int idx, VarState s
)
)
}
-
+
ASSERT_BUG(sp, idx < m_variable_states.size(), "Variable " << idx << " out of range for state table");
m_variable_states[idx] = state;
}
@@ -1142,7 +1142,7 @@ VarState MirBuilder::get_temp_state(const Span& sp, unsigned int idx) const
}
}
}
-
+
ASSERT_BUG(sp, idx < m_temporary_states.size(), "Temporary " << idx << " out of range for state table");
return m_temporary_states[idx];
}
@@ -1173,7 +1173,7 @@ void MirBuilder::set_temp_state(const Span& sp, unsigned int idx, VarState state
return ;
}
}
-
+
ASSERT_BUG(sp, idx < m_temporary_states.size(), "Temporary " << idx << " out of range for state table");
m_temporary_states[idx] = state;
}
diff --git a/src/mir/mir_ptr.hpp b/src/mir/mir_ptr.hpp
index 583b155b..9133dd44 100644
--- a/src/mir/mir_ptr.hpp
+++ b/src/mir/mir_ptr.hpp
@@ -19,7 +19,7 @@ public:
FunctionPointer(): ptr(nullptr) {}
FunctionPointer(::MIR::Function* p): ptr(p) {}
FunctionPointer(FunctionPointer&& x): ptr(x.ptr) { x.ptr = nullptr; }
-
+
~FunctionPointer() {
reset();
}
@@ -29,14 +29,14 @@ public:
x.ptr = nullptr;
return *this;
}
-
+
void reset();
-
+
::MIR::Function* operator->() { return ptr; }
::MIR::Function& operator*() { return *ptr; }
const ::MIR::Function* operator->() const { return ptr; }
const ::MIR::Function& operator*() const { return *ptr; }
-
+
operator bool() const { return ptr != nullptr; }
};
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index 601b1b18..bb9536b0 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -31,7 +31,7 @@ namespace {
// Make sure we don't infinite loop
if( bb == target.terminator.as_Goto() )
return bb;
-
+
auto rv = get_new_target(state, target.terminator.as_Goto());
DEBUG(bb << " => " << rv);
return rv;
@@ -44,7 +44,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
static Span sp;
TRACE_FUNCTION_F(path);
::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
-
+
// >> Replace targets that point to a block that is just a goto
for(auto& block : fcn.blocks)
{
@@ -74,7 +74,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
)
)
}
-
+
// >> Merge blocks where a block goto-s to a single-use block.
{
::std::vector<unsigned int> uses( fcn.blocks.size() );
@@ -106,7 +106,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
)
)
}
-
+
unsigned int i = 0;
for(auto& block : fcn.blocks)
{
@@ -116,9 +116,9 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
if( uses[tgt] != 1 )
break ;
DEBUG("Append bb " << tgt << " to bb" << i);
-
+
assert( &fcn.blocks[tgt] != &block );
-
+
for(auto& stmt : fcn.blocks[tgt].statements)
block.statements.push_back( mv$(stmt) );
block.terminator = mv$( fcn.blocks[tgt].terminator );
@@ -126,17 +126,17 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
i ++;
}
}
-
+
// >> Combine Duplicate Blocks
// TODO:
-
+
// >> Propagate dead assignments
// TODO: This requires kowing that doing so has no effect.
// - Can use little heristics like a Call pointing to an assignment of its RV
// - Count the read/write count of a variable, if it's 1,1 then this optimisation is correct.
// - If the count is read=*,write=1 and the write is of an argument, replace with the argument.
-
+
// GC pass on blocks and variables
// - Find unused blocks, then delete and rewrite all references.
{
@@ -147,7 +147,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
{
auto bb = to_visit.back(); to_visit.pop_back();
visited[bb] = true;
-
+
const auto& block = fcn.blocks[bb];
TU_MATCHA( (block.terminator), (e),
(Incomplete,
@@ -181,7 +181,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
)
)
}
-
+
::std::vector<unsigned int> rewrite_table;
for(unsigned int i = 0, j = 0; i < fcn.blocks.size(); i ++)
{
@@ -192,7 +192,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
rewrite_table.push_back(~0u);
}
}
-
+
auto it = fcn.blocks.begin();
for(unsigned int i = 0; i < visited.size(); i ++)
{
@@ -230,7 +230,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
e.panic_block = rewrite_table[e.panic_block];
)
)
-
+
++it;
}
}
diff --git a/src/mir/visit_crate_mir.cpp b/src/mir/visit_crate_mir.cpp
index 4cd1fddc..ba4acf8e 100644
--- a/src/mir/visit_crate_mir.cpp
+++ b/src/mir/visit_crate_mir.cpp
@@ -36,7 +36,7 @@ void MIR::OuterVisitor::visit_function(::HIR::ItemPath p, ::HIR::Function& item)
DEBUG("Function code " << p);
// TODO: Get span without needing hir/expr.hpp
static Span sp;
-
+
// Replace ErasedType instances in `ret_type`
const auto& ret_type = item.m_return;
auto ret_type_v = clone_ty_with(sp, ret_type, [&](const auto& tpl, auto& rv) {
@@ -71,10 +71,10 @@ void MIR::OuterVisitor::visit_constant(::HIR::ItemPath p, ::HIR::Constant& item)
void MIR::OuterVisitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item)
{
auto _ = this->m_resolve.set_item_generics(item.m_params);
-
+
// TODO: Use a different type depding on repr()
auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
+
for(auto& var : item.m_variants)
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
diff --git a/src/mir/visit_crate_mir.hpp b/src/mir/visit_crate_mir.hpp
index e6964545..d01f5ab3 100644
--- a/src/mir/visit_crate_mir.hpp
+++ b/src/mir/visit_crate_mir.hpp
@@ -24,9 +24,9 @@ public:
m_resolve(crate),
m_cb(cb)
{}
-
+
void visit_expr(::HIR::ExprPtr& exp) override;
-
+
void visit_type(::HIR::TypeRef& ty) override;
// ------
@@ -36,7 +36,7 @@ public:
void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override;
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override;
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override;
-
+
// Boilerplate
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override;
void visit_type_impl(::HIR::TypeImpl& impl) override;
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index 57d6f24d..613290f2 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -1,70 +1,70 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * parse/common.hpp
- * - Common definitions used by the parser
- */
-#ifndef PARSE_COMMON_HPP_INCLUDED
-#define PARSE_COMMON_HPP_INCLUDED
-#include <iostream>
-#include "tokenstream.hpp"
-#include "../ast/ast.hpp"
-
-#define GET_TOK(tok, lex) ((tok = lex.getToken()).type())
-#define PUTBACK(tok, lex) lex.putback( ::std::move(tok) )
-#define LOOK_AHEAD(lex) (lex.lookahead(0))
-#define GET_CHECK_TOK(tok, lex, exp) do {\
- if((tok = lex.getToken()).type() != exp) { \
- DEBUG("GET_CHECK_TOK " << __FILE__ << ":" << __LINE__); \
- throw ParseError::Unexpected(lex, tok, Token(exp));\
- }\
-} while(0)
-#define CHECK_TOK(tok, exp) do {\
- if(tok.type() != exp) { \
- DEBUG("CHECK_TOK " << __FILE__ << ":" << __LINE__); \
- throw ParseError::Unexpected(lex, tok, Token(exp));\
- } \
-} while(0)
-
-// --- path.cpp
-enum eParsePathGenericMode
-{
- PATH_GENERIC_NONE,
- PATH_GENERIC_EXPR,
- PATH_GENERIC_TYPE
-};
-extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines
-extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
-extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode);
-extern AST::PathParams Parse_Path_GenericList(TokenStream& lex);
-
-
-extern ::std::vector< ::std::string> Parse_HRB(TokenStream& lex);
-extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
-extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::std::string name, TokenStream& lex);
-extern TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list = true);
-extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable);
-
-extern void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl);
-extern void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items);
-extern ::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::MetaItems meta_items);
-extern void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod);
-
-
-extern AST::Expr Parse_Expr(TokenStream& lex);
-extern AST::Expr Parse_ExprBlock(TokenStream& lex);
-extern AST::ExprNodeP Parse_Expr0(TokenStream& lex);
-extern AST::ExprNodeP Parse_ExprVal(TokenStream& lex);
-extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false);
-extern AST::ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
-extern AST::ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end);
-extern AST::ExprNodeP Parse_Stmt(TokenStream& lex);
-
-// unwrapped = Exclude the enclosing brackets (used by macro parse code)
-extern TokenTree Parse_TT(TokenStream& lex, bool unwrapped);
-
-
-extern bool Parse_IsTokValue(eTokenType tok_type);
-
-#endif // PARSE_COMMON_HPP_INCLUDED
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/common.hpp
+ * - Common definitions used by the parser
+ */
+#ifndef PARSE_COMMON_HPP_INCLUDED
+#define PARSE_COMMON_HPP_INCLUDED
+#include <iostream>
+#include "tokenstream.hpp"
+#include "../ast/ast.hpp"
+
+#define GET_TOK(tok, lex) ((tok = lex.getToken()).type())
+#define PUTBACK(tok, lex) lex.putback( ::std::move(tok) )
+#define LOOK_AHEAD(lex) (lex.lookahead(0))
+#define GET_CHECK_TOK(tok, lex, exp) do {\
+ if((tok = lex.getToken()).type() != exp) { \
+ DEBUG("GET_CHECK_TOK " << __FILE__ << ":" << __LINE__); \
+ throw ParseError::Unexpected(lex, tok, Token(exp));\
+ }\
+} while(0)
+#define CHECK_TOK(tok, exp) do {\
+ if(tok.type() != exp) { \
+ DEBUG("CHECK_TOK " << __FILE__ << ":" << __LINE__); \
+ throw ParseError::Unexpected(lex, tok, Token(exp));\
+ } \
+} while(0)
+
+// --- path.cpp
+enum eParsePathGenericMode
+{
+ PATH_GENERIC_NONE,
+ PATH_GENERIC_EXPR,
+ PATH_GENERIC_TYPE
+};
+extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines
+extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
+extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode);
+extern AST::PathParams Parse_Path_GenericList(TokenStream& lex);
+
+
+extern ::std::vector< ::std::string> Parse_HRB(TokenStream& lex);
+extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
+extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::std::string name, TokenStream& lex);
+extern TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list = true);
+extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable);
+
+extern void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl);
+extern void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items);
+extern ::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::MetaItems meta_items);
+extern void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod);
+
+
+extern AST::Expr Parse_Expr(TokenStream& lex);
+extern AST::Expr Parse_ExprBlock(TokenStream& lex);
+extern AST::ExprNodeP Parse_Expr0(TokenStream& lex);
+extern AST::ExprNodeP Parse_ExprVal(TokenStream& lex);
+extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false);
+extern AST::ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
+extern AST::ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end);
+extern AST::ExprNodeP Parse_Stmt(TokenStream& lex);
+
+// unwrapped = Exclude the enclosing brackets (used by macro parse code)
+extern TokenTree Parse_TT(TokenStream& lex, bool unwrapped);
+
+
+extern bool Parse_IsTokValue(eTokenType tok_type);
+
+#endif // PARSE_COMMON_HPP_INCLUDED
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index c71d2b4a..eb82bae7 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -1,1301 +1,1301 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * parse/expr.cpp
- * - Expression (i.e. code) parsing
- *
- * Start points:
- * - Parse_ExprBlockNode : Parses a block
- * - Parse_Stmt : Parse a single statement
- * - Parse_Expr0 : Parse a single expression
- */
-#include "parseerror.hpp"
-#include <ast/ast.hpp>
-#include <ast/expr.hpp>
-#include "common.hpp"
-#include <iostream>
-#include "tokentree.hpp"
-#include "interpolated_fragment.hpp"
-
-using AST::ExprNode;
-using AST::ExprNodeP;
-static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_pos(lex.getPosition()); return ExprNodeP(en); }
-#define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__))
-
-//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); // common.hpp
-//ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end);
-//ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
-ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon);
-//ExprNodeP Parse_Stmt(TokenStream& lex); // common.hpp
-ExprNodeP Parse_Stmt_Let(TokenStream& lex);
-ExprNodeP Parse_Expr0(TokenStream& lex);
-ExprNodeP Parse_IfStmt(TokenStream& lex);
-ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime);
-ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime);
-ExprNodeP Parse_Expr_Match(TokenStream& lex);
-ExprNodeP Parse_Expr1(TokenStream& lex);
-ExprNodeP Parse_ExprMacro(TokenStream& lex, Token tok);
-
-AST::Expr Parse_Expr(TokenStream& lex)
-{
- return ::AST::Expr( Parse_Expr0(lex) );
-}
-
-AST::Expr Parse_ExprBlock(TokenStream& lex)
-{
- return ::AST::Expr( Parse_ExprBlockNode(lex) );
-}
-
-ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/)
-{
- TRACE_FUNCTION;
- Token tok;
-
- bool yields_final_value = true;
- ::std::vector<ExprNodeP> nodes;
-
- ::std::shared_ptr<AST::Module> local_mod;
-
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
-
- while( LOOK_AHEAD(lex) != TOK_BRACE_CLOSE )
- {
- DEBUG("tok = " << tok);
-
- // NOTE: Doc comments can appear within a function and apply to the function
- // TODO: Use these attributes
- while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
- {
- /*node_attrs.push_back(*/ Parse_MetaItem(lex) /*)*/;
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
- PUTBACK(tok, lex);
- if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE )
- break;
-
- bool add_silence_if_end = false;
- auto rv = Parse_ExprBlockLine_WithItems(lex, local_mod, add_silence_if_end);
- if( rv )
- {
- // Set to TRUE if there was no semicolon after a statement
- if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE && add_silence_if_end )
- {
- DEBUG("End of block, and add_silence_if_end == true - doesn't yeild");
- yields_final_value = false;
- // Since the next token is TOK_BRACE_CLOSE, the loop will terminate
- }
- nodes.push_back( mv$(rv) );
- }
- else {
- assert( !add_silence_if_end );
- }
- }
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
-
- return NEWNODE( AST::ExprNode_Block, is_unsafe, yields_final_value, mv$(nodes), mv$(local_mod) );
-}
-
-/// Parse a single line in a block, handling items added to the local module
-///
-/// - If an item was parsed, this returns an empty ExprNodeP
-ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end)
-{
- Token tok;
-
- AST::MetaItems item_attrs;
- while( GET_TOK(tok, lex) == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- switch(tok.type())
- {
- // Items:
- case TOK_RWORD_PUB:
- // NOTE: Allowed, but doesn't do much
- case TOK_RWORD_TYPE:
- case TOK_RWORD_USE:
- case TOK_RWORD_EXTERN:
- case TOK_RWORD_CONST:
- case TOK_RWORD_STATIC:
- case TOK_RWORD_STRUCT:
- case TOK_RWORD_ENUM:
- case TOK_RWORD_TRAIT:
- case TOK_RWORD_IMPL:
- case TOK_RWORD_FN:
- case TOK_RWORD_MOD:
- PUTBACK(tok, lex);
- if( !local_mod ) {
- local_mod = lex.parse_state().get_current_mod().add_anon();
- }
- Parse_Mod_Item(lex, *local_mod, mv$(item_attrs));
- return ExprNodeP();
- // 'unsafe' - Check if the next token isn't a `{`, if so it's an item. Otherwise, fall through
- case TOK_RWORD_UNSAFE:
- if( LOOK_AHEAD(lex) != TOK_BRACE_OPEN )
- {
- PUTBACK(tok, lex);
- if( !local_mod ) {
- local_mod = lex.parse_state().get_current_mod().add_anon();
- }
- Parse_Mod_Item(lex, *local_mod, mv$(item_attrs));
- return ExprNodeP();
- }
- // fall
- default: {
- PUTBACK(tok, lex);
- auto rv = Parse_ExprBlockLine(lex, &add_silence_if_end);
- if( rv ) {
- rv->set_attrs( mv$(item_attrs) );
- }
- else if( item_attrs.m_items.size() > 0 ) {
- // TODO: Is this an error? - Attributes on a expression that didn't yeild a node.
- }
- else {
- }
- return rv;
- } break;
- }
-}
-
-/// Parse a single line from a block
-///
-/// Handles:
-/// - Block-level constructs (with lifetime annotations)
-/// - use/extern/const/let
-ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
-{
- Token tok;
- ExprNodeP ret;
-
- if( GET_TOK(tok, lex) == TOK_LIFETIME )
- {
- // Lifetimes can only precede loops... and blocks?
- ::std::string lifetime = tok.str();
- GET_CHECK_TOK(tok, lex, TOK_COLON);
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_RWORD_LOOP:
- return NEWNODE( AST::ExprNode_Loop, lifetime, Parse_ExprBlockNode(lex) );
- case TOK_RWORD_WHILE:
- return Parse_WhileStmt(lex, lifetime);
- case TOK_RWORD_FOR:
- return Parse_ForStmt(lex, lifetime);
- //case TOK_RWORD_IF:
- // return Parse_IfStmt(lex);
- //case TOK_RWORD_MATCH:
- // return Parse_Expr_Match(lex);
- //case TOK_BRACE_OPEN:
- // PUTBACK(tok, lex);
- // return Parse_ExprBlockNode(lex);
-
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- }
- else
- {
- switch( tok.type() )
- {
- case TOK_INTERPOLATED_BLOCK:
- return tok.take_frag_node();
- case TOK_SEMICOLON:
- // Return a NULL expression, nothing here.
- return nullptr;
-
- // let binding
- case TOK_RWORD_LET:
- ret = Parse_Stmt_Let(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- return ret;
-
- // Blocks that don't need semicolons
- // NOTE: If these are followed by a small set of tokens (`.` and `?`) then they are actually the start of an expression
- // HACK: Parse here, but if the next token is one of the set store in a TOK_INTERPOLATED_EXPR and invoke the statement parser
- case TOK_RWORD_LOOP:
- ret = NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
- if(0)
- case TOK_RWORD_WHILE:
- ret = Parse_WhileStmt(lex, "");
- if(0)
- case TOK_RWORD_FOR:
- ret = Parse_ForStmt(lex, "");
- if(0)
- case TOK_RWORD_IF:
- ret = Parse_IfStmt(lex);
- if(0)
- case TOK_RWORD_MATCH:
- ret = Parse_Expr_Match(lex);
- if(0)
- case TOK_RWORD_UNSAFE:
- ret = Parse_ExprBlockNode(lex, true);
- if(0)
- case TOK_BRACE_OPEN:
- { PUTBACK(tok, lex); ret = Parse_ExprBlockNode(lex); }
-
- if( lex.lookahead(0) == TOK_DOT || lex.lookahead(0) == TOK_QMARK ) {
- lex.putback( Token(Token::TagTakeIP(), InterpolatedFragment(InterpolatedFragment::EXPR, ret.release())) );
- return Parse_ExprBlockLine_Stmt(lex, *add_silence);
- }
-
- if( LOOK_AHEAD(lex) == TOK_SEMICOLON ) {
- GET_TOK(tok, lex);
- *add_silence = true;
- }
-
- return ret;
-
- // Flow control
- case TOK_RWORD_RETURN:
- case TOK_RWORD_CONTINUE:
- case TOK_RWORD_BREAK: {
- PUTBACK(tok, lex);
- auto ret = Parse_Stmt(lex);
- if( LOOK_AHEAD(lex) == TOK_EOF ) {
- }
- else if( GET_TOK(tok, lex) != TOK_SEMICOLON ) {
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- PUTBACK(tok, lex);
- }
- else {
- // return/continue/break don't need silencing
- }
- return ret;
- }
-
- case TOK_MACRO:
- // If a braced macro invocation is the first part of a statement, don't expect a semicolon
- if( LOOK_AHEAD(lex) == TOK_BRACE_OPEN || (lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_BRACE_OPEN) ) {
- return Parse_ExprMacro(lex, tok);
- }
- // Fall through to the statement code
- default:
- PUTBACK(tok, lex);
- return Parse_ExprBlockLine_Stmt(lex, *add_silence);
- }
- }
-}
-
-ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon)
-{
- Token tok;
- auto ret = Parse_Stmt(lex);
- // If this expression statement wasn't followed by a semicolon, then it's yielding its value out of the block.
- // - I.e. The block should be ending
- if( GET_TOK(tok, lex) != TOK_SEMICOLON ) {
- // - Allow TOK_EOF for macro expansion.
- if( tok.type() == TOK_EOF )
- ;
- else
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- PUTBACK(tok, lex);
- }
- else {
- has_semicolon = true;
- }
- return ret;
-}
-
-/// While loop (either as a statement, or as part of an expression)
-ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime)
-{
- Token tok;
-
- if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
- auto pat = Parse_Pattern(lex, true); // Refutable pattern
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- ExprNodeP val;
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- val = Parse_Expr0(lex);
- }
- return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::WHILELET,
- ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) );
- }
- else {
- PUTBACK(tok, lex);
- ExprNodeP cnd;
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- cnd = Parse_Expr1(lex);
- }
- return NEWNODE( AST::ExprNode_Loop, lifetime, ::std::move(cnd), Parse_ExprBlockNode(lex) );
- }
-}
-/// For loop (either as a statement, or as part of an expression)
-ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime)
-{
- Token tok;
-
- // Irrefutable pattern
- AST::Pattern pat = Parse_Pattern(lex, false);
- GET_CHECK_TOK(tok, lex, TOK_RWORD_IN);
- ExprNodeP val;
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- val = Parse_Expr0(lex);
- }
- return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::FOR,
- ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) );
-}
-/// Parse an 'if' statement
-// Note: TOK_RWORD_IF has already been eaten
-ExprNodeP Parse_IfStmt(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- Token tok;
- ExprNodeP cond;
- AST::Pattern pat;
- bool if_let = false;
-
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
- if_let = true;
- // Refutable pattern
- pat = Parse_Pattern(lex, true);
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- cond = Parse_Expr0(lex);
- }
- else {
- PUTBACK(tok, lex);
- cond = Parse_Expr0(lex);
- }
- }
-
- // Contents
- ExprNodeP code = Parse_ExprBlockNode(lex);
-
- // Handle else:
- ExprNodeP 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 {
- PUTBACK(tok, lex);
- altcode = Parse_ExprBlockNode(lex);
- }
- }
- // - or nothing
- else {
- PUTBACK(tok, lex);
- }
-
- if( if_let )
- return NEWNODE( AST::ExprNode_IfLet, ::std::move(pat), ::std::move(cond), ::std::move(code), ::std::move(altcode) );
- else
- return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
-}
-/// "match" block
-ExprNodeP Parse_Expr_Match(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
- // 1. Get expression
- ExprNodeP switch_val;
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- switch_val = Parse_Expr1(lex);
- }
- //ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) );
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
-
- ::std::vector< AST::ExprNode_Match_Arm > arms;
- do {
- if( GET_TOK(tok, lex) == TOK_BRACE_CLOSE )
- break;
- PUTBACK(tok, lex);
- AST::ExprNode_Match_Arm arm;
-
- ::AST::MetaItems arm_attrs;
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN ) {
- GET_TOK(tok, lex);
- arm_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
- arm.m_attrs = mv$(arm_attrs);
-
- do {
- // Refutable pattern
- arm.m_patterns.push_back( Parse_Pattern(lex, true) );
- } while( GET_TOK(tok, lex) == TOK_PIPE );
-
- if( tok.type() == TOK_RWORD_IF )
- {
- arm.m_cond = Parse_Expr1(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_FATARROW);
-
- arm.m_code = Parse_Stmt(lex);
-
- arms.push_back( ::std::move(arm) );
-
- if( GET_TOK(tok, lex) == TOK_COMMA )
- continue;
- PUTBACK(tok, lex);
-
- } while( 1 );
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
- return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) );
-}
-
-/// Parses the 'stmt' fragment specifier
-/// - Flow control
-/// - Expressions
-ExprNodeP Parse_Stmt(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- switch(GET_TOK(tok, lex))
- {
- case TOK_INTERPOLATED_STMT:
- return tok.take_frag_node();
- // Duplicated here for the :stmt pattern fragment.
- case TOK_RWORD_LET:
- return Parse_Stmt_Let(lex);
- case TOK_RWORD_RETURN: {
- ExprNodeP val;
- switch(LOOK_AHEAD(lex))
- {
- case TOK_SEMICOLON:
- case TOK_COMMA:
- case TOK_BRACE_CLOSE:
- case TOK_PAREN_CLOSE:
- case TOK_SQUARE_CLOSE:
- break;
- default:
- val = Parse_Expr0(lex);
- break;
- }
- return NEWNODE( AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", ::std::move(val) );
- }
- case TOK_RWORD_CONTINUE:
- case TOK_RWORD_BREAK:
- {
- AST::ExprNode_Flow::Type type;
- switch(tok.type())
- {
- case TOK_RWORD_CONTINUE: type = AST::ExprNode_Flow::CONTINUE; break;
- case TOK_RWORD_BREAK: type = AST::ExprNode_Flow::BREAK; break;
- default: throw ParseError::BugCheck(/*lex,*/ "continue/break");
- }
- ::std::string lifetime;
- if( GET_TOK(tok, lex) == TOK_LIFETIME )
- {
- lifetime = tok.str();
- GET_TOK(tok, lex);
- }
- ExprNodeP val;
- switch(tok.type())
- {
- case TOK_SEMICOLON:
- case TOK_COMMA:
- case TOK_BRACE_OPEN:
- case TOK_BRACE_CLOSE:
- case TOK_PAREN_CLOSE:
- case TOK_SQUARE_CLOSE:
- PUTBACK(tok, lex);
- break;
- default:
- PUTBACK(tok, lex);
- val = Parse_Expr1(lex);
- break;
- }
- return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) );
- }
- case TOK_BRACE_OPEN:
- PUTBACK(tok, lex);
- return Parse_ExprBlockNode(lex);
- default:
- PUTBACK(tok, lex);
- return Parse_Expr0(lex);
- }
-}
-
-ExprNodeP Parse_Stmt_Let(TokenStream& lex)
-{
- Token tok;
- AST::Pattern pat = Parse_Pattern(lex, false); // irrefutable
- TypeRef type { lex.getPosition() };
- if( GET_TOK(tok, lex) == TOK_COLON ) {
- type = Parse_Type(lex);
- GET_TOK(tok, lex);
- }
- ExprNodeP val;
- if( tok.type() == TOK_EQUAL ) {
- val = Parse_Expr0(lex);
- }
- else {
- PUTBACK(tok, lex);
- }
- return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), mv$(type), ::std::move(val) );
-}
-
-::std::vector<ExprNodeP> Parse_ParenList(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
-
- ::std::vector<ExprNodeP> rv;
- GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
- if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE )
- {
- PUTBACK(tok, lex);
- do {
- if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) {
- GET_TOK(tok, lex);
- break;
- }
- rv.push_back( Parse_Expr0(lex) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- }
- return rv;
-}
-
-// 0: Assign
-ExprNodeP Parse_Expr0(TokenStream& lex)
-{
- //TRACE_FUNCTION;
- Token tok;
-
- ::AST::MetaItems expr_attrs;
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
- {
- GET_TOK(tok, lex);
- expr_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- ExprNodeP rv = Parse_Expr1(lex);
- auto op = AST::ExprNode_Assign::NONE;
- switch( GET_TOK(tok, lex) )
- {
- case TOK_PLUS_EQUAL:
- op = AST::ExprNode_Assign::ADD; if(0)
- case TOK_DASH_EQUAL:
- op = AST::ExprNode_Assign::SUB; if(0)
- case TOK_STAR_EQUAL:
- op = AST::ExprNode_Assign::MUL; if(0)
- case TOK_SLASH_EQUAL:
- op = AST::ExprNode_Assign::DIV; if(0)
- case TOK_PERCENT_EQUAL:
- op = AST::ExprNode_Assign::MOD; if(0)
-
- case TOK_AMP_EQUAL:
- op = AST::ExprNode_Assign::AND; if(0)
- case TOK_PIPE_EQUAL:
- op = AST::ExprNode_Assign::OR ; if(0)
- case TOK_CARET_EQUAL:
- op = AST::ExprNode_Assign::XOR; if(0)
-
- case TOK_DOUBLE_GT_EQUAL:
- op = AST::ExprNode_Assign::SHR; if(0)
- case TOK_DOUBLE_LT_EQUAL:
- op = AST::ExprNode_Assign::SHL; if(0)
-
- case TOK_EQUAL:
- op = AST::ExprNode_Assign::NONE;
- rv = NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr0(lex) );
- rv->set_attrs(mv$(expr_attrs));
- return rv;
-
- default:
- PUTBACK(tok, lex);
- rv->set_attrs(mv$(expr_attrs));
- return rv;
- }
-}
-
-
-#define LEFTASSOC(cur, _next, cases) \
-ExprNodeP _next(TokenStream& lex); \
-ExprNodeP cur(TokenStream& lex) \
-{ \
- ExprNodeP (*next)(TokenStream&) = _next;\
- ExprNodeP rv = next(lex); \
- while(true) \
- { \
- Token tok; \
- switch((tok = lex.getToken()).type()) \
- { \
- cases \
- default: \
- /*::std::cout << "<<" << #cur << ::std::endl; */\
- PUTBACK(tok, lex); \
- return rv; \
- } \
- } \
-}
-bool Parse_IsTokValue(eTokenType tok_type)
-{
- switch( tok_type )
- {
- case TOK_DOUBLE_COLON:
- case TOK_IDENT:
- case TOK_INTEGER:
- case TOK_FLOAT:
- case TOK_STRING:
- case TOK_RWORD_TRUE:
- case TOK_RWORD_FALSE:
- case TOK_RWORD_SELF:
- case TOK_RWORD_SUPER:
- case TOK_RWORD_BOX:
- case TOK_RWORD_IN:
- case TOK_PAREN_OPEN:
- case TOK_SQUARE_OPEN:
-
- case TOK_MACRO:
-
- case TOK_PIPE:
- case TOK_EXCLAM:
- case TOK_DASH:
- case TOK_STAR:
- case TOK_AMP:
- return true;
- default:
- return false;
- }
-
-}
-ExprNodeP Parse_Expr1_1(TokenStream& lex);
-// Very evil handling for '..'
-ExprNodeP Parse_Expr1(TokenStream& lex)
-{
- Token tok;
- ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1;
- ExprNodeP left, right;
-
- // Inclusive range to a value
- if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) {
- right = next(lex);
- return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, nullptr, mv$(right) );
- }
- else {
- PUTBACK(tok, lex);
- }
-
- // Exclusive ranges
- // - If NOT `.. <VAL>`, parse a leading value
- if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
- {
- PUTBACK(tok, lex);
-
- left = next(lex);
-
- // - If NOT `<VAL> ..`, return the value
- if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
- {
- PUTBACK(tok, lex);
- return ::std::move(left);
- }
- }
- assert( tok.type() == TOK_DOUBLE_DOT );
- // If the next token is part of a value, parse that value
- if( Parse_IsTokValue( LOOK_AHEAD(lex) ) )
- {
- right = next(lex);
- }
- else
- {
- // Otherwise, leave `right` as nullptr
- }
-
- return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) );
-}
-// TODO: Is this left associative?
-LEFTASSOC(Parse_Expr1_1, Parse_Expr1_5,
- case TOK_TRIPLE_DOT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) );
- break;
-)
-// 1: Bool OR
-LEFTASSOC(Parse_Expr1_5, Parse_Expr2,
- case TOK_DOUBLE_PIPE:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLOR, ::std::move(rv), next(lex));
- break;
-)
-// 2: Bool AND
-LEFTASSOC(Parse_Expr2, Parse_Expr3,
- case TOK_DOUBLE_AMP:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLAND, ::std::move(rv), next(lex));
- break;
-)
-// 3: (In)Equality
-LEFTASSOC(Parse_Expr3, Parse_Expr4,
- case TOK_DOUBLE_EQUAL:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPEQU, ::std::move(rv), next(lex));
- break;
- case TOK_EXCLAM_EQUAL:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPNEQU, ::std::move(rv), next(lex));
- break;
-)
-// 4: Comparisons
-LEFTASSOC(Parse_Expr4, Parse_Expr5,
- case TOK_LT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLT, ::std::move(rv), next(lex));
- break;
- case TOK_GT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGT, ::std::move(rv), next(lex));
- break;
- case TOK_LTE:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLTE, ::std::move(rv), next(lex));
- break;
- case TOK_GTE:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGTE, ::std::move(rv), next(lex));
- break;
-)
-// 5: Bit OR
-LEFTASSOC(Parse_Expr5, Parse_Expr6,
- case TOK_PIPE:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITOR, ::std::move(rv), next(lex));
- break;
-)
-// 6: Bit XOR
-LEFTASSOC(Parse_Expr6, Parse_Expr7,
- case TOK_CARET:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITXOR, ::std::move(rv), next(lex));
- break;
-)
-// 7: Bit AND
-LEFTASSOC(Parse_Expr7, Parse_Expr8,
- case TOK_AMP:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITAND, ::std::move(rv), next(lex));
- break;
-)
-// 8: Bit Shifts
-LEFTASSOC(Parse_Expr8, Parse_Expr9,
- case TOK_DOUBLE_LT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHL, ::std::move(rv), next(lex));
- break;
- case TOK_DOUBLE_GT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHR, ::std::move(rv), next(lex));
- break;
-)
-// 9: Add / Subtract
-LEFTASSOC(Parse_Expr9, Parse_Expr10,
- case TOK_PLUS:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::ADD, ::std::move(rv), next(lex));
- break;
- case TOK_DASH:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex));
- break;
-)
-// 10: Times / Divide / Modulo
-LEFTASSOC(Parse_Expr10, Parse_Expr11,
- case TOK_STAR:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MULTIPLY, ::std::move(rv), next(lex));
- break;
- case TOK_SLASH:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::DIVIDE, ::std::move(rv), next(lex));
- break;
- case TOK_PERCENT:
- rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MODULO, ::std::move(rv), next(lex));
- break;
-)
-// 11: Cast
-LEFTASSOC(Parse_Expr11, Parse_Expr12,
- case TOK_RWORD_AS:
- rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex, false) );
- break;
-)
-// 12: Type Ascription
-ExprNodeP Parse_Expr13(TokenStream& lex);
-ExprNodeP Parse_Expr12(TokenStream& lex)
-{
- Token tok;
- auto rv = Parse_Expr13(lex);
- if(GET_TOK(tok, lex) == TOK_COLON)
- {
- rv = NEWNODE( AST::ExprNode_TypeAnnotation, mv$(rv), Parse_Type(lex) );
- }
- else
- {
- PUTBACK(tok, lex);
- }
- return rv;
-}
-// 13: Unaries
-ExprNodeP Parse_ExprFC(TokenStream& lex);
-ExprNodeP Parse_Expr13(TokenStream& lex)
-{
- Token tok;
- switch(GET_TOK(tok, lex))
- {
- case TOK_DASH:
- return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::NEGATE, Parse_Expr12(lex) );
- case TOK_EXCLAM:
- return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::INVERT, Parse_Expr12(lex) );
- case TOK_STAR:
- return NEWNODE( AST::ExprNode_Deref, Parse_Expr12(lex) );
- case TOK_RWORD_BOX:
- return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::BOX, Parse_Expr12(lex) );
- case TOK_RWORD_IN: {
- ExprNodeP dest;
- {
- SET_PARSE_FLAG(lex, disallow_struct_literal);
- dest = Parse_Expr1(lex);
- }
- auto val = Parse_ExprBlockNode(lex);
- return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::PLACE_IN, mv$(dest), mv$(val));
- }
- case TOK_DOUBLE_AMP:
- // HACK: Split && into & &
- lex.putback( Token(TOK_AMP) );
- case TOK_AMP:
- if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
- return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REFMUT, Parse_Expr12(lex) );
- else {
- PUTBACK(tok, lex);
- return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, Parse_Expr12(lex) );
- }
- default:
- PUTBACK(tok, lex);
- return Parse_ExprFC(lex);
- }
-}
-
-ExprNodeP Parse_ExprVal(TokenStream& lex);
-ExprNodeP Parse_ExprFC(TokenStream& lex)
-{
- ExprNodeP val = Parse_ExprVal(lex);
- while(true)
- {
- Token tok;
- switch(GET_TOK(tok, lex))
- {
- case TOK_QMARK:
- val = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::QMARK, mv$(val) );
- break;
-
- case TOK_PAREN_OPEN:
- // Expression method call
- PUTBACK(tok, lex);
- val = NEWNODE( AST::ExprNode_CallObject, ::std::move(val), Parse_ParenList(lex) );
- break;
- case TOK_SQUARE_OPEN:
- val = NEWNODE( AST::ExprNode_Index, ::std::move(val), Parse_Expr0(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- break;
- case TOK_DOT:
- // Field access / method call
- // TODO: What about tuple indexing?
- switch(GET_TOK(tok, lex))
- {
- case TOK_IDENT: {
- AST::PathNode path( mv$(tok.str()) , {});
- switch( GET_TOK(tok, lex) )
- {
- case TOK_PAREN_OPEN:
- PUTBACK(tok, lex);
- val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
- break;
- case TOK_DOUBLE_COLON:
- GET_CHECK_TOK(tok, lex, TOK_LT);
- path.args() = Parse_Path_GenericList(lex);
- val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
- break;
- default:
- val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(path.name()) );
- PUTBACK(tok, lex);
- break;
- }
- break; }
- case TOK_INTEGER:
- val = NEWNODE( AST::ExprNode_Field, ::std::move(val), FMT(tok.intval()) );
- break;
- default:
- throw ParseError::Unexpected(lex, mv$(tok));
- }
- break;
- default:
- PUTBACK(tok, lex);
- return val;
- }
- }
-}
-
-ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
-{
- TRACE_FUNCTION;
- Token tok;
-
- // #![feature(relaxed_adts)]
- if( LOOK_AHEAD(lex) == TOK_INTEGER )
- {
- ::std::map<unsigned int, ExprNodeP> nodes;
- while( GET_TOK(tok, lex) == TOK_INTEGER )
- {
- unsigned int ofs = tok.intval();
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- ExprNodeP val = Parse_Stmt(lex);
- if( ! nodes.insert( ::std::make_pair(ofs, mv$(val)) ).second ) {
- ERROR(lex.getPosition(), E0000, "Duplicate index");
- }
-
- if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
- break;
- CHECK_TOK(tok, TOK_COMMA);
- }
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
- ::std::vector<ExprNodeP> items;
- unsigned int i = 0;
- for(auto& p : nodes)
- {
- if( p.first != i ) {
- ERROR(lex.getPosition(), E0000, "Missing index " << i);
- }
- items.push_back( mv$(p.second) );
- i ++;
- }
-
- return NEWNODE( AST::ExprNode_CallPath, mv$(path), mv$(items) );
- }
-
- // Braced structure literal
- // - A series of 0 or more pairs of <ident>: <expr>,
- // - '..' <expr>
- ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
- while( GET_TOK(tok, lex) == TOK_IDENT )
- {
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- ExprNodeP val = Parse_Stmt(lex);
- items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
-
- if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
- break;
- CHECK_TOK(tok, TOK_COMMA);
- }
- ExprNodeP base_val;
- if( tok.type() == TOK_DOUBLE_DOT )
- {
- // default
- base_val = Parse_Expr0(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
- return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
-}
-
-ExprNodeP Parse_ExprVal_Closure(TokenStream& lex, bool is_move)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector< ::std::pair<AST::Pattern, TypeRef> > args;
-
- while( GET_TOK(tok, lex) != TOK_PIPE )
- {
- PUTBACK(tok, lex);
- // Irrefutable pattern
- AST::Pattern pat = Parse_Pattern(lex, false);
-
- TypeRef type { lex.getPosition() };
- if( GET_TOK(tok, lex) == TOK_COLON )
- type = Parse_Type(lex);
- else
- PUTBACK(tok, lex);
-
- args.push_back( ::std::make_pair( ::std::move(pat), ::std::move(type) ) );
-
- if( GET_TOK(tok, lex) != TOK_COMMA )
- break;
- }
- CHECK_TOK(tok, TOK_PIPE);
-
- auto rt = TypeRef(lex.getPosition());
- if( GET_TOK(tok, lex) == TOK_THINARROW ) {
-
- if( GET_TOK(tok, lex) == TOK_EXCLAM ) {
- rt = TypeRef(TypeRef::TagInvalid(), Span(tok.get_pos()));
- }
- else {
- PUTBACK(tok, lex);
- rt = Parse_Type(lex);
- }
- }
- else
- PUTBACK(tok, lex);
-
- auto code = Parse_Expr0(lex);
-
- return NEWNODE( AST::ExprNode_Closure, ::std::move(args), ::std::move(rt), ::std::move(code), is_move );
-}
-
-ExprNodeP Parse_ExprVal(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- Token tok;
- AST::Path path;
- switch( GET_TOK(tok, lex) )
- {
- case TOK_BRACE_OPEN:
- PUTBACK(tok, lex);
- return Parse_ExprBlockNode(lex);
-
- case TOK_INTERPOLATED_EXPR:
- case TOK_INTERPOLATED_BLOCK:
- return tok.take_frag_node();
-
-
- // TODO: Return/break/continue/... here?
- case TOK_RWORD_RETURN:
- case TOK_RWORD_CONTINUE:
- case TOK_RWORD_BREAK:
- PUTBACK(tok, lex);
- return Parse_Stmt(lex);
-
- case TOK_RWORD_LOOP:
- return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
- case TOK_RWORD_WHILE:
- return Parse_WhileStmt(lex, "");
- case TOK_RWORD_FOR:
- return Parse_ForStmt(lex, "");
- case TOK_RWORD_MATCH:
- return Parse_Expr_Match(lex);
- case TOK_RWORD_IF:
- return Parse_IfStmt(lex);
- case TOK_RWORD_UNSAFE:
- return Parse_ExprBlockNode(lex, true);
-
- // UFCS
- case TOK_DOUBLE_LT:
- case TOK_LT:
- PUTBACK(tok, lex);
- path = Parse_Path(lex, PATH_GENERIC_EXPR);
- // Skip down to method
- if(0)
- case TOK_RWORD_SELF:
- {
- if( LOOK_AHEAD(lex) != TOK_DOUBLE_COLON ) {
- return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") );
- }
- else
- {
- PUTBACK(tok, lex);
- path = Parse_Path(lex, PATH_GENERIC_EXPR);
- }
- }
- if(0)
- case TOK_RWORD_SUPER:
- {
- PUTBACK(tok, lex);
- path = Parse_Path(lex, PATH_GENERIC_EXPR);
- }
- if(0)
- case TOK_IDENT:
- // Get path
- {
- PUTBACK(tok, lex);
- path = Parse_Path(lex, false, PATH_GENERIC_EXPR);
- }
- if(0)
- case TOK_INTERPOLATED_PATH:
- {
- path = mv$(tok.frag_path());
- }
- if(0)
- case TOK_DOUBLE_COLON:
- path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
- // SKIP TARGET
- switch( GET_TOK(tok, lex) )
- {
- case TOK_PAREN_OPEN:
- // Function call
- PUTBACK(tok, lex);
- return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), Parse_ParenList(lex) );
- case TOK_BRACE_OPEN:
- if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) )
- return Parse_ExprVal_StructLiteral(lex, ::std::move(path));
- else
- DEBUG("Not parsing struct literal");
- default:
- // Value
- PUTBACK(tok, lex);
- return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) );
- }
- case TOK_RWORD_MOVE:
- // TODO: Annotate closure as move
- GET_TOK(tok, lex);
- if(tok.type() == TOK_PIPE)
- return Parse_ExprVal_Closure(lex, true);
- else if(tok.type() == TOK_DOUBLE_PIPE) {
- lex.putback(Token(TOK_PIPE));
- return Parse_ExprVal_Closure(lex, true);
- }
- else {
- CHECK_TOK(tok, TOK_PIPE);
- }
- case TOK_DOUBLE_PIPE:
- lex.putback(Token(TOK_PIPE));
- case TOK_PIPE:
- return Parse_ExprVal_Closure(lex, false);
- case TOK_INTEGER:
- return NEWNODE( AST::ExprNode_Integer, tok.intval(), tok.datatype() );
- case TOK_FLOAT:
- return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() );
- case TOK_STRING:
- return NEWNODE( AST::ExprNode_String, tok.str() );
- case TOK_BYTESTRING:
- return NEWNODE( AST::ExprNode_ByteString, tok.str() );
- case TOK_RWORD_TRUE:
- return NEWNODE( AST::ExprNode_Bool, true );
- case TOK_RWORD_FALSE:
- return NEWNODE( AST::ExprNode_Bool, false );
- case TOK_PAREN_OPEN:
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- {
- DEBUG("Unit");
- return NEWNODE( AST::ExprNode_Tuple, ::std::vector<ExprNodeP>() );
- }
- else
- {
- CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
- PUTBACK(tok, lex);
-
- ExprNodeP rv = Parse_Expr0(lex);
- if( GET_TOK(tok, lex) == TOK_COMMA ) {
- ::std::vector<ExprNodeP> ents;
- ents.push_back( ::std::move(rv) );
- do {
- if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
- break;
- PUTBACK(tok, lex);
- ents.push_back( Parse_Expr0(lex) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
- }
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return rv;
- }
- case TOK_SQUARE_OPEN:
- if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE )
- {
- // Empty literal
- return NEWNODE( AST::ExprNode_Array, ::std::vector<ExprNodeP>() );
- }
- else
- {
- PUTBACK(tok, lex);
- auto first = Parse_Expr0(lex);
- if( GET_TOK(tok, lex) == TOK_SEMICOLON )
- {
- // Repetiion
- auto count = Parse_Expr0(lex);
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- return NEWNODE( AST::ExprNode_Array, ::std::move(first), ::std::move(count) );
- }
- else
- {
- ::std::vector<ExprNodeP> items;
- items.push_back( ::std::move(first) );
- while( tok.type() == TOK_COMMA )
- {
- if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE )
- break;
- else
- PUTBACK(tok, lex);
- items.push_back( Parse_Expr0(lex) );
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_SQUARE_CLOSE);
- return NEWNODE( AST::ExprNode_Array, ::std::move(items) );
- }
- }
- throw ParseError::BugCheck(lex, "Array literal fell");
- case TOK_MACRO:
- return Parse_ExprMacro(lex, mv$(tok));
- default:
- throw ParseError::Unexpected(lex, tok);
- }
-}
-ExprNodeP Parse_ExprMacro(TokenStream& lex, Token tok)
-{
- ::std::string name = tok.str();
- ::std::string ident;
- if( GET_TOK(tok, lex) == TOK_IDENT ) {
- ident = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
- }
- TokenTree tt = Parse_TT(lex, true);
- if( tt.is_token() ) {
- throw ParseError::Unexpected(lex, tt.tok());
- }
- return NEWNODE(AST::ExprNode_Macro, mv$(name), mv$(ident), mv$(tt));
-}
-
-// Token Tree Parsing
-TokenTree Parse_TT(TokenStream& lex, bool unwrapped)
-{
- TokenTree rv;
- TRACE_FUNCTION_FR("", rv);
-
- Token tok = lex.getToken();
- eTokenType closer = TOK_PAREN_CLOSE;
- switch(tok.type())
- {
- case TOK_PAREN_OPEN:
- closer = TOK_PAREN_CLOSE;
- break;
- case TOK_SQUARE_OPEN:
- closer = TOK_SQUARE_CLOSE;
- break;
- case TOK_BRACE_OPEN:
- closer = TOK_BRACE_CLOSE;
- break;
- // HACK! mrustc parses #[ and #![ as composite tokens
- // TODO: Split these into their component tokens.
- case TOK_ATTR_OPEN:
- case TOK_CATTR_OPEN:
- if( unwrapped )
- throw ParseError::Unexpected(lex, tok);
- closer = TOK_SQUARE_CLOSE;
- break;
-
- case TOK_EOF:
- case TOK_NULL:
- case TOK_PAREN_CLOSE:
- case TOK_SQUARE_CLOSE:
- case TOK_BRACE_CLOSE:
- throw ParseError::Unexpected(lex, tok);
- default:
- rv = TokenTree(lex.getHygiene(), mv$(tok) );
- return rv;
- }
-
- ::std::vector<TokenTree> items;
- if( !unwrapped )
- items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) );
- while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF)
- {
- if( tok.type() == TOK_NULL )
- throw ParseError::Unexpected(lex, tok);
- PUTBACK(tok, lex);
- items.push_back(Parse_TT(lex, false));
- }
- if( !unwrapped )
- items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) );
- rv = TokenTree(lex.getHygiene(), mv$(items));
- return rv;
-}
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/expr.cpp
+ * - Expression (i.e. code) parsing
+ *
+ * Start points:
+ * - Parse_ExprBlockNode : Parses a block
+ * - Parse_Stmt : Parse a single statement
+ * - Parse_Expr0 : Parse a single expression
+ */
+#include "parseerror.hpp"
+#include <ast/ast.hpp>
+#include <ast/expr.hpp>
+#include "common.hpp"
+#include <iostream>
+#include "tokentree.hpp"
+#include "interpolated_fragment.hpp"
+
+using AST::ExprNode;
+using AST::ExprNodeP;
+static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_pos(lex.getPosition()); return ExprNodeP(en); }
+#define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__))
+
+//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false); // common.hpp
+//ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end);
+//ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence);
+ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon);
+//ExprNodeP Parse_Stmt(TokenStream& lex); // common.hpp
+ExprNodeP Parse_Stmt_Let(TokenStream& lex);
+ExprNodeP Parse_Expr0(TokenStream& lex);
+ExprNodeP Parse_IfStmt(TokenStream& lex);
+ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime);
+ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime);
+ExprNodeP Parse_Expr_Match(TokenStream& lex);
+ExprNodeP Parse_Expr1(TokenStream& lex);
+ExprNodeP Parse_ExprMacro(TokenStream& lex, Token tok);
+
+AST::Expr Parse_Expr(TokenStream& lex)
+{
+ return ::AST::Expr( Parse_Expr0(lex) );
+}
+
+AST::Expr Parse_ExprBlock(TokenStream& lex)
+{
+ return ::AST::Expr( Parse_ExprBlockNode(lex) );
+}
+
+ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ bool yields_final_value = true;
+ ::std::vector<ExprNodeP> nodes;
+
+ ::std::shared_ptr<AST::Module> local_mod;
+
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+
+ while( LOOK_AHEAD(lex) != TOK_BRACE_CLOSE )
+ {
+ DEBUG("tok = " << tok);
+
+ // NOTE: Doc comments can appear within a function and apply to the function
+ // TODO: Use these attributes
+ while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
+ {
+ /*node_attrs.push_back(*/ Parse_MetaItem(lex) /*)*/;
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+ PUTBACK(tok, lex);
+ if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE )
+ break;
+
+ bool add_silence_if_end = false;
+ auto rv = Parse_ExprBlockLine_WithItems(lex, local_mod, add_silence_if_end);
+ if( rv )
+ {
+ // Set to TRUE if there was no semicolon after a statement
+ if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE && add_silence_if_end )
+ {
+ DEBUG("End of block, and add_silence_if_end == true - doesn't yeild");
+ yields_final_value = false;
+ // Since the next token is TOK_BRACE_CLOSE, the loop will terminate
+ }
+ nodes.push_back( mv$(rv) );
+ }
+ else {
+ assert( !add_silence_if_end );
+ }
+ }
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_Block, is_unsafe, yields_final_value, mv$(nodes), mv$(local_mod) );
+}
+
+/// Parse a single line in a block, handling items added to the local module
+///
+/// - If an item was parsed, this returns an empty ExprNodeP
+ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST::Module>& local_mod, bool& add_silence_if_end)
+{
+ Token tok;
+
+ AST::MetaItems item_attrs;
+ while( GET_TOK(tok, lex) == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ switch(tok.type())
+ {
+ // Items:
+ case TOK_RWORD_PUB:
+ // NOTE: Allowed, but doesn't do much
+ case TOK_RWORD_TYPE:
+ case TOK_RWORD_USE:
+ case TOK_RWORD_EXTERN:
+ case TOK_RWORD_CONST:
+ case TOK_RWORD_STATIC:
+ case TOK_RWORD_STRUCT:
+ case TOK_RWORD_ENUM:
+ case TOK_RWORD_TRAIT:
+ case TOK_RWORD_IMPL:
+ case TOK_RWORD_FN:
+ case TOK_RWORD_MOD:
+ PUTBACK(tok, lex);
+ if( !local_mod ) {
+ local_mod = lex.parse_state().get_current_mod().add_anon();
+ }
+ Parse_Mod_Item(lex, *local_mod, mv$(item_attrs));
+ return ExprNodeP();
+ // 'unsafe' - Check if the next token isn't a `{`, if so it's an item. Otherwise, fall through
+ case TOK_RWORD_UNSAFE:
+ if( LOOK_AHEAD(lex) != TOK_BRACE_OPEN )
+ {
+ PUTBACK(tok, lex);
+ if( !local_mod ) {
+ local_mod = lex.parse_state().get_current_mod().add_anon();
+ }
+ Parse_Mod_Item(lex, *local_mod, mv$(item_attrs));
+ return ExprNodeP();
+ }
+ // fall
+ default: {
+ PUTBACK(tok, lex);
+ auto rv = Parse_ExprBlockLine(lex, &add_silence_if_end);
+ if( rv ) {
+ rv->set_attrs( mv$(item_attrs) );
+ }
+ else if( item_attrs.m_items.size() > 0 ) {
+ // TODO: Is this an error? - Attributes on a expression that didn't yeild a node.
+ }
+ else {
+ }
+ return rv;
+ } break;
+ }
+}
+
+/// Parse a single line from a block
+///
+/// Handles:
+/// - Block-level constructs (with lifetime annotations)
+/// - use/extern/const/let
+ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence)
+{
+ Token tok;
+ ExprNodeP ret;
+
+ if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ {
+ // Lifetimes can only precede loops... and blocks?
+ ::std::string lifetime = tok.str();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_LOOP:
+ return NEWNODE( AST::ExprNode_Loop, lifetime, Parse_ExprBlockNode(lex) );
+ case TOK_RWORD_WHILE:
+ return Parse_WhileStmt(lex, lifetime);
+ case TOK_RWORD_FOR:
+ return Parse_ForStmt(lex, lifetime);
+ //case TOK_RWORD_IF:
+ // return Parse_IfStmt(lex);
+ //case TOK_RWORD_MATCH:
+ // return Parse_Expr_Match(lex);
+ //case TOK_BRACE_OPEN:
+ // PUTBACK(tok, lex);
+ // return Parse_ExprBlockNode(lex);
+
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ }
+ else
+ {
+ switch( tok.type() )
+ {
+ case TOK_INTERPOLATED_BLOCK:
+ return tok.take_frag_node();
+ case TOK_SEMICOLON:
+ // Return a NULL expression, nothing here.
+ return nullptr;
+
+ // let binding
+ case TOK_RWORD_LET:
+ ret = Parse_Stmt_Let(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ return ret;
+
+ // Blocks that don't need semicolons
+ // NOTE: If these are followed by a small set of tokens (`.` and `?`) then they are actually the start of an expression
+ // HACK: Parse here, but if the next token is one of the set store in a TOK_INTERPOLATED_EXPR and invoke the statement parser
+ case TOK_RWORD_LOOP:
+ ret = NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
+ if(0)
+ case TOK_RWORD_WHILE:
+ ret = Parse_WhileStmt(lex, "");
+ if(0)
+ case TOK_RWORD_FOR:
+ ret = Parse_ForStmt(lex, "");
+ if(0)
+ case TOK_RWORD_IF:
+ ret = Parse_IfStmt(lex);
+ if(0)
+ case TOK_RWORD_MATCH:
+ ret = Parse_Expr_Match(lex);
+ if(0)
+ case TOK_RWORD_UNSAFE:
+ ret = Parse_ExprBlockNode(lex, true);
+ if(0)
+ case TOK_BRACE_OPEN:
+ { PUTBACK(tok, lex); ret = Parse_ExprBlockNode(lex); }
+
+ if( lex.lookahead(0) == TOK_DOT || lex.lookahead(0) == TOK_QMARK ) {
+ lex.putback( Token(Token::TagTakeIP(), InterpolatedFragment(InterpolatedFragment::EXPR, ret.release())) );
+ return Parse_ExprBlockLine_Stmt(lex, *add_silence);
+ }
+
+ if( LOOK_AHEAD(lex) == TOK_SEMICOLON ) {
+ GET_TOK(tok, lex);
+ *add_silence = true;
+ }
+
+ return ret;
+
+ // Flow control
+ case TOK_RWORD_RETURN:
+ case TOK_RWORD_CONTINUE:
+ case TOK_RWORD_BREAK: {
+ PUTBACK(tok, lex);
+ auto ret = Parse_Stmt(lex);
+ if( LOOK_AHEAD(lex) == TOK_EOF ) {
+ }
+ else if( GET_TOK(tok, lex) != TOK_SEMICOLON ) {
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ PUTBACK(tok, lex);
+ }
+ else {
+ // return/continue/break don't need silencing
+ }
+ return ret;
+ }
+
+ case TOK_MACRO:
+ // If a braced macro invocation is the first part of a statement, don't expect a semicolon
+ if( LOOK_AHEAD(lex) == TOK_BRACE_OPEN || (lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_BRACE_OPEN) ) {
+ return Parse_ExprMacro(lex, tok);
+ }
+ // Fall through to the statement code
+ default:
+ PUTBACK(tok, lex);
+ return Parse_ExprBlockLine_Stmt(lex, *add_silence);
+ }
+ }
+}
+
+ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon)
+{
+ Token tok;
+ auto ret = Parse_Stmt(lex);
+ // If this expression statement wasn't followed by a semicolon, then it's yielding its value out of the block.
+ // - I.e. The block should be ending
+ if( GET_TOK(tok, lex) != TOK_SEMICOLON ) {
+ // - Allow TOK_EOF for macro expansion.
+ if( tok.type() == TOK_EOF )
+ ;
+ else
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ PUTBACK(tok, lex);
+ }
+ else {
+ has_semicolon = true;
+ }
+ return ret;
+}
+
+/// While loop (either as a statement, or as part of an expression)
+ExprNodeP Parse_WhileStmt(TokenStream& lex, ::std::string lifetime)
+{
+ Token tok;
+
+ if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
+ auto pat = Parse_Pattern(lex, true); // Refutable pattern
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ ExprNodeP val;
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ val = Parse_Expr0(lex);
+ }
+ return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::WHILELET,
+ ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) );
+ }
+ else {
+ PUTBACK(tok, lex);
+ ExprNodeP cnd;
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ cnd = Parse_Expr1(lex);
+ }
+ return NEWNODE( AST::ExprNode_Loop, lifetime, ::std::move(cnd), Parse_ExprBlockNode(lex) );
+ }
+}
+/// For loop (either as a statement, or as part of an expression)
+ExprNodeP Parse_ForStmt(TokenStream& lex, ::std::string lifetime)
+{
+ Token tok;
+
+ // Irrefutable pattern
+ AST::Pattern pat = Parse_Pattern(lex, false);
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_IN);
+ ExprNodeP val;
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ val = Parse_Expr0(lex);
+ }
+ return NEWNODE( AST::ExprNode_Loop, lifetime, AST::ExprNode_Loop::FOR,
+ ::std::move(pat), ::std::move(val), Parse_ExprBlockNode(lex) );
+}
+/// Parse an 'if' statement
+// Note: TOK_RWORD_IF has already been eaten
+ExprNodeP Parse_IfStmt(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ ExprNodeP cond;
+ AST::Pattern pat;
+ bool if_let = false;
+
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ if( GET_TOK(tok, lex) == TOK_RWORD_LET ) {
+ if_let = true;
+ // Refutable pattern
+ pat = Parse_Pattern(lex, true);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ cond = Parse_Expr0(lex);
+ }
+ else {
+ PUTBACK(tok, lex);
+ cond = Parse_Expr0(lex);
+ }
+ }
+
+ // Contents
+ ExprNodeP code = Parse_ExprBlockNode(lex);
+
+ // Handle else:
+ ExprNodeP 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 {
+ PUTBACK(tok, lex);
+ altcode = Parse_ExprBlockNode(lex);
+ }
+ }
+ // - or nothing
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ if( if_let )
+ return NEWNODE( AST::ExprNode_IfLet, ::std::move(pat), ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+ else
+ return NEWNODE( AST::ExprNode_If, ::std::move(cond), ::std::move(code), ::std::move(altcode) );
+}
+/// "match" block
+ExprNodeP Parse_Expr_Match(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
+ // 1. Get expression
+ ExprNodeP switch_val;
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ switch_val = Parse_Expr1(lex);
+ }
+ //ASSERT(lex, !CHECK_PARSE_FLAG(lex, disallow_struct_literal) );
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+
+ ::std::vector< AST::ExprNode_Match_Arm > arms;
+ do {
+ if( GET_TOK(tok, lex) == TOK_BRACE_CLOSE )
+ break;
+ PUTBACK(tok, lex);
+ AST::ExprNode_Match_Arm arm;
+
+ ::AST::MetaItems arm_attrs;
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN ) {
+ GET_TOK(tok, lex);
+ arm_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+ arm.m_attrs = mv$(arm_attrs);
+
+ do {
+ // Refutable pattern
+ arm.m_patterns.push_back( Parse_Pattern(lex, true) );
+ } while( GET_TOK(tok, lex) == TOK_PIPE );
+
+ if( tok.type() == TOK_RWORD_IF )
+ {
+ arm.m_cond = Parse_Expr1(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_FATARROW);
+
+ arm.m_code = Parse_Stmt(lex);
+
+ arms.push_back( ::std::move(arm) );
+
+ if( GET_TOK(tok, lex) == TOK_COMMA )
+ continue;
+ PUTBACK(tok, lex);
+
+ } while( 1 );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_Match, ::std::move(switch_val), ::std::move(arms) );
+}
+
+/// Parses the 'stmt' fragment specifier
+/// - Flow control
+/// - Expressions
+ExprNodeP Parse_Stmt(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_INTERPOLATED_STMT:
+ return tok.take_frag_node();
+ // Duplicated here for the :stmt pattern fragment.
+ case TOK_RWORD_LET:
+ return Parse_Stmt_Let(lex);
+ case TOK_RWORD_RETURN: {
+ ExprNodeP val;
+ switch(LOOK_AHEAD(lex))
+ {
+ case TOK_SEMICOLON:
+ case TOK_COMMA:
+ case TOK_BRACE_CLOSE:
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ break;
+ default:
+ val = Parse_Expr0(lex);
+ break;
+ }
+ return NEWNODE( AST::ExprNode_Flow, AST::ExprNode_Flow::RETURN, "", ::std::move(val) );
+ }
+ case TOK_RWORD_CONTINUE:
+ case TOK_RWORD_BREAK:
+ {
+ AST::ExprNode_Flow::Type type;
+ switch(tok.type())
+ {
+ case TOK_RWORD_CONTINUE: type = AST::ExprNode_Flow::CONTINUE; break;
+ case TOK_RWORD_BREAK: type = AST::ExprNode_Flow::BREAK; break;
+ default: throw ParseError::BugCheck(/*lex,*/ "continue/break");
+ }
+ ::std::string lifetime;
+ if( GET_TOK(tok, lex) == TOK_LIFETIME )
+ {
+ lifetime = tok.str();
+ GET_TOK(tok, lex);
+ }
+ ExprNodeP val;
+ switch(tok.type())
+ {
+ case TOK_SEMICOLON:
+ case TOK_COMMA:
+ case TOK_BRACE_OPEN:
+ case TOK_BRACE_CLOSE:
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ PUTBACK(tok, lex);
+ break;
+ default:
+ PUTBACK(tok, lex);
+ val = Parse_Expr1(lex);
+ break;
+ }
+ return NEWNODE( AST::ExprNode_Flow, type, lifetime, ::std::move(val) );
+ }
+ case TOK_BRACE_OPEN:
+ PUTBACK(tok, lex);
+ return Parse_ExprBlockNode(lex);
+ default:
+ PUTBACK(tok, lex);
+ return Parse_Expr0(lex);
+ }
+}
+
+ExprNodeP Parse_Stmt_Let(TokenStream& lex)
+{
+ Token tok;
+ AST::Pattern pat = Parse_Pattern(lex, false); // irrefutable
+ TypeRef type { lex.getPosition() };
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ type = Parse_Type(lex);
+ GET_TOK(tok, lex);
+ }
+ ExprNodeP val;
+ if( tok.type() == TOK_EQUAL ) {
+ val = Parse_Expr0(lex);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ return NEWNODE( AST::ExprNode_LetBinding, ::std::move(pat), mv$(type), ::std::move(val) );
+}
+
+::std::vector<ExprNodeP> Parse_ParenList(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
+
+ ::std::vector<ExprNodeP> rv;
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ if( GET_TOK(tok, lex) != TOK_PAREN_CLOSE )
+ {
+ PUTBACK(tok, lex);
+ do {
+ if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) {
+ GET_TOK(tok, lex);
+ break;
+ }
+ rv.push_back( Parse_Expr0(lex) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ }
+ return rv;
+}
+
+// 0: Assign
+ExprNodeP Parse_Expr0(TokenStream& lex)
+{
+ //TRACE_FUNCTION;
+ Token tok;
+
+ ::AST::MetaItems expr_attrs;
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
+ {
+ GET_TOK(tok, lex);
+ expr_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ ExprNodeP rv = Parse_Expr1(lex);
+ auto op = AST::ExprNode_Assign::NONE;
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_PLUS_EQUAL:
+ op = AST::ExprNode_Assign::ADD; if(0)
+ case TOK_DASH_EQUAL:
+ op = AST::ExprNode_Assign::SUB; if(0)
+ case TOK_STAR_EQUAL:
+ op = AST::ExprNode_Assign::MUL; if(0)
+ case TOK_SLASH_EQUAL:
+ op = AST::ExprNode_Assign::DIV; if(0)
+ case TOK_PERCENT_EQUAL:
+ op = AST::ExprNode_Assign::MOD; if(0)
+
+ case TOK_AMP_EQUAL:
+ op = AST::ExprNode_Assign::AND; if(0)
+ case TOK_PIPE_EQUAL:
+ op = AST::ExprNode_Assign::OR ; if(0)
+ case TOK_CARET_EQUAL:
+ op = AST::ExprNode_Assign::XOR; if(0)
+
+ case TOK_DOUBLE_GT_EQUAL:
+ op = AST::ExprNode_Assign::SHR; if(0)
+ case TOK_DOUBLE_LT_EQUAL:
+ op = AST::ExprNode_Assign::SHL; if(0)
+
+ case TOK_EQUAL:
+ op = AST::ExprNode_Assign::NONE;
+ rv = NEWNODE( AST::ExprNode_Assign, op, ::std::move(rv), Parse_Expr0(lex) );
+ rv->set_attrs(mv$(expr_attrs));
+ return rv;
+
+ default:
+ PUTBACK(tok, lex);
+ rv->set_attrs(mv$(expr_attrs));
+ return rv;
+ }
+}
+
+
+#define LEFTASSOC(cur, _next, cases) \
+ExprNodeP _next(TokenStream& lex); \
+ExprNodeP cur(TokenStream& lex) \
+{ \
+ ExprNodeP (*next)(TokenStream&) = _next;\
+ ExprNodeP rv = next(lex); \
+ while(true) \
+ { \
+ Token tok; \
+ switch((tok = lex.getToken()).type()) \
+ { \
+ cases \
+ default: \
+ /*::std::cout << "<<" << #cur << ::std::endl; */\
+ PUTBACK(tok, lex); \
+ return rv; \
+ } \
+ } \
+}
+bool Parse_IsTokValue(eTokenType tok_type)
+{
+ switch( tok_type )
+ {
+ case TOK_DOUBLE_COLON:
+ case TOK_IDENT:
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_STRING:
+ case TOK_RWORD_TRUE:
+ case TOK_RWORD_FALSE:
+ case TOK_RWORD_SELF:
+ case TOK_RWORD_SUPER:
+ case TOK_RWORD_BOX:
+ case TOK_RWORD_IN:
+ case TOK_PAREN_OPEN:
+ case TOK_SQUARE_OPEN:
+
+ case TOK_MACRO:
+
+ case TOK_PIPE:
+ case TOK_EXCLAM:
+ case TOK_DASH:
+ case TOK_STAR:
+ case TOK_AMP:
+ return true;
+ default:
+ return false;
+ }
+
+}
+ExprNodeP Parse_Expr1_1(TokenStream& lex);
+// Very evil handling for '..'
+ExprNodeP Parse_Expr1(TokenStream& lex)
+{
+ Token tok;
+ ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1;
+ ExprNodeP left, right;
+
+ // Inclusive range to a value
+ if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) {
+ right = next(lex);
+ return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, nullptr, mv$(right) );
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ // Exclusive ranges
+ // - If NOT `.. <VAL>`, parse a leading value
+ if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
+ {
+ PUTBACK(tok, lex);
+
+ left = next(lex);
+
+ // - If NOT `<VAL> ..`, return the value
+ if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
+ {
+ PUTBACK(tok, lex);
+ return ::std::move(left);
+ }
+ }
+ assert( tok.type() == TOK_DOUBLE_DOT );
+ // If the next token is part of a value, parse that value
+ if( Parse_IsTokValue( LOOK_AHEAD(lex) ) )
+ {
+ right = next(lex);
+ }
+ else
+ {
+ // Otherwise, leave `right` as nullptr
+ }
+
+ return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) );
+}
+// TODO: Is this left associative?
+LEFTASSOC(Parse_Expr1_1, Parse_Expr1_5,
+ case TOK_TRIPLE_DOT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) );
+ break;
+)
+// 1: Bool OR
+LEFTASSOC(Parse_Expr1_5, Parse_Expr2,
+ case TOK_DOUBLE_PIPE:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLOR, ::std::move(rv), next(lex));
+ break;
+)
+// 2: Bool AND
+LEFTASSOC(Parse_Expr2, Parse_Expr3,
+ case TOK_DOUBLE_AMP:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BOOLAND, ::std::move(rv), next(lex));
+ break;
+)
+// 3: (In)Equality
+LEFTASSOC(Parse_Expr3, Parse_Expr4,
+ case TOK_DOUBLE_EQUAL:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPEQU, ::std::move(rv), next(lex));
+ break;
+ case TOK_EXCLAM_EQUAL:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPNEQU, ::std::move(rv), next(lex));
+ break;
+)
+// 4: Comparisons
+LEFTASSOC(Parse_Expr4, Parse_Expr5,
+ case TOK_LT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLT, ::std::move(rv), next(lex));
+ break;
+ case TOK_GT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGT, ::std::move(rv), next(lex));
+ break;
+ case TOK_LTE:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPLTE, ::std::move(rv), next(lex));
+ break;
+ case TOK_GTE:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::CMPGTE, ::std::move(rv), next(lex));
+ break;
+)
+// 5: Bit OR
+LEFTASSOC(Parse_Expr5, Parse_Expr6,
+ case TOK_PIPE:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITOR, ::std::move(rv), next(lex));
+ break;
+)
+// 6: Bit XOR
+LEFTASSOC(Parse_Expr6, Parse_Expr7,
+ case TOK_CARET:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITXOR, ::std::move(rv), next(lex));
+ break;
+)
+// 7: Bit AND
+LEFTASSOC(Parse_Expr7, Parse_Expr8,
+ case TOK_AMP:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::BITAND, ::std::move(rv), next(lex));
+ break;
+)
+// 8: Bit Shifts
+LEFTASSOC(Parse_Expr8, Parse_Expr9,
+ case TOK_DOUBLE_LT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHL, ::std::move(rv), next(lex));
+ break;
+ case TOK_DOUBLE_GT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SHR, ::std::move(rv), next(lex));
+ break;
+)
+// 9: Add / Subtract
+LEFTASSOC(Parse_Expr9, Parse_Expr10,
+ case TOK_PLUS:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::ADD, ::std::move(rv), next(lex));
+ break;
+ case TOK_DASH:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::SUB, ::std::move(rv), next(lex));
+ break;
+)
+// 10: Times / Divide / Modulo
+LEFTASSOC(Parse_Expr10, Parse_Expr11,
+ case TOK_STAR:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MULTIPLY, ::std::move(rv), next(lex));
+ break;
+ case TOK_SLASH:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::DIVIDE, ::std::move(rv), next(lex));
+ break;
+ case TOK_PERCENT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::MODULO, ::std::move(rv), next(lex));
+ break;
+)
+// 11: Cast
+LEFTASSOC(Parse_Expr11, Parse_Expr12,
+ case TOK_RWORD_AS:
+ rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex, false) );
+ break;
+)
+// 12: Type Ascription
+ExprNodeP Parse_Expr13(TokenStream& lex);
+ExprNodeP Parse_Expr12(TokenStream& lex)
+{
+ Token tok;
+ auto rv = Parse_Expr13(lex);
+ if(GET_TOK(tok, lex) == TOK_COLON)
+ {
+ rv = NEWNODE( AST::ExprNode_TypeAnnotation, mv$(rv), Parse_Type(lex) );
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ }
+ return rv;
+}
+// 13: Unaries
+ExprNodeP Parse_ExprFC(TokenStream& lex);
+ExprNodeP Parse_Expr13(TokenStream& lex)
+{
+ Token tok;
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_DASH:
+ return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::NEGATE, Parse_Expr12(lex) );
+ case TOK_EXCLAM:
+ return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::INVERT, Parse_Expr12(lex) );
+ case TOK_STAR:
+ return NEWNODE( AST::ExprNode_Deref, Parse_Expr12(lex) );
+ case TOK_RWORD_BOX:
+ return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::BOX, Parse_Expr12(lex) );
+ case TOK_RWORD_IN: {
+ ExprNodeP dest;
+ {
+ SET_PARSE_FLAG(lex, disallow_struct_literal);
+ dest = Parse_Expr1(lex);
+ }
+ auto val = Parse_ExprBlockNode(lex);
+ return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::PLACE_IN, mv$(dest), mv$(val));
+ }
+ case TOK_DOUBLE_AMP:
+ // HACK: Split && into & &
+ lex.putback( Token(TOK_AMP) );
+ case TOK_AMP:
+ if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
+ return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REFMUT, Parse_Expr12(lex) );
+ else {
+ PUTBACK(tok, lex);
+ return NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::REF, Parse_Expr12(lex) );
+ }
+ default:
+ PUTBACK(tok, lex);
+ return Parse_ExprFC(lex);
+ }
+}
+
+ExprNodeP Parse_ExprVal(TokenStream& lex);
+ExprNodeP Parse_ExprFC(TokenStream& lex)
+{
+ ExprNodeP val = Parse_ExprVal(lex);
+ while(true)
+ {
+ Token tok;
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_QMARK:
+ val = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::QMARK, mv$(val) );
+ break;
+
+ case TOK_PAREN_OPEN:
+ // Expression method call
+ PUTBACK(tok, lex);
+ val = NEWNODE( AST::ExprNode_CallObject, ::std::move(val), Parse_ParenList(lex) );
+ break;
+ case TOK_SQUARE_OPEN:
+ val = NEWNODE( AST::ExprNode_Index, ::std::move(val), Parse_Expr0(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ break;
+ case TOK_DOT:
+ // Field access / method call
+ // TODO: What about tuple indexing?
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_IDENT: {
+ AST::PathNode path( mv$(tok.str()) , {});
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_PAREN_OPEN:
+ PUTBACK(tok, lex);
+ val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
+ break;
+ case TOK_DOUBLE_COLON:
+ GET_CHECK_TOK(tok, lex, TOK_LT);
+ path.args() = Parse_Path_GenericList(lex);
+ val = NEWNODE( AST::ExprNode_CallMethod, ::std::move(val), ::std::move(path), Parse_ParenList(lex) );
+ break;
+ default:
+ val = NEWNODE( AST::ExprNode_Field, ::std::move(val), ::std::string(path.name()) );
+ PUTBACK(tok, lex);
+ break;
+ }
+ break; }
+ case TOK_INTEGER:
+ val = NEWNODE( AST::ExprNode_Field, ::std::move(val), FMT(tok.intval()) );
+ break;
+ default:
+ throw ParseError::Unexpected(lex, mv$(tok));
+ }
+ break;
+ default:
+ PUTBACK(tok, lex);
+ return val;
+ }
+ }
+}
+
+ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ // #![feature(relaxed_adts)]
+ if( LOOK_AHEAD(lex) == TOK_INTEGER )
+ {
+ ::std::map<unsigned int, ExprNodeP> nodes;
+ while( GET_TOK(tok, lex) == TOK_INTEGER )
+ {
+ unsigned int ofs = tok.intval();
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ ExprNodeP val = Parse_Stmt(lex);
+ if( ! nodes.insert( ::std::make_pair(ofs, mv$(val)) ).second ) {
+ ERROR(lex.getPosition(), E0000, "Duplicate index");
+ }
+
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ ::std::vector<ExprNodeP> items;
+ unsigned int i = 0;
+ for(auto& p : nodes)
+ {
+ if( p.first != i ) {
+ ERROR(lex.getPosition(), E0000, "Missing index " << i);
+ }
+ items.push_back( mv$(p.second) );
+ i ++;
+ }
+
+ return NEWNODE( AST::ExprNode_CallPath, mv$(path), mv$(items) );
+ }
+
+ // Braced structure literal
+ // - A series of 0 or more pairs of <ident>: <expr>,
+ // - '..' <expr>
+ ::std::vector< ::std::pair< ::std::string, ::std::unique_ptr<AST::ExprNode>> > items;
+ while( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ ExprNodeP val = Parse_Stmt(lex);
+ items.push_back( ::std::make_pair(::std::move(name), ::std::move(val)) );
+
+ if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ ExprNodeP base_val;
+ if( tok.type() == TOK_DOUBLE_DOT )
+ {
+ // default
+ base_val = Parse_Expr0(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return NEWNODE( AST::ExprNode_StructLiteral, path, ::std::move(base_val), ::std::move(items) );
+}
+
+ExprNodeP Parse_ExprVal_Closure(TokenStream& lex, bool is_move)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ ::std::vector< ::std::pair<AST::Pattern, TypeRef> > args;
+
+ while( GET_TOK(tok, lex) != TOK_PIPE )
+ {
+ PUTBACK(tok, lex);
+ // Irrefutable pattern
+ AST::Pattern pat = Parse_Pattern(lex, false);
+
+ TypeRef type { lex.getPosition() };
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ type = Parse_Type(lex);
+ else
+ PUTBACK(tok, lex);
+
+ args.push_back( ::std::make_pair( ::std::move(pat), ::std::move(type) ) );
+
+ if( GET_TOK(tok, lex) != TOK_COMMA )
+ break;
+ }
+ CHECK_TOK(tok, TOK_PIPE);
+
+ auto rt = TypeRef(lex.getPosition());
+ if( GET_TOK(tok, lex) == TOK_THINARROW ) {
+
+ if( GET_TOK(tok, lex) == TOK_EXCLAM ) {
+ rt = TypeRef(TypeRef::TagInvalid(), Span(tok.get_pos()));
+ }
+ else {
+ PUTBACK(tok, lex);
+ rt = Parse_Type(lex);
+ }
+ }
+ else
+ PUTBACK(tok, lex);
+
+ auto code = Parse_Expr0(lex);
+
+ return NEWNODE( AST::ExprNode_Closure, ::std::move(args), ::std::move(rt), ::std::move(code), is_move );
+}
+
+ExprNodeP Parse_ExprVal(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ AST::Path path;
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_BRACE_OPEN:
+ PUTBACK(tok, lex);
+ return Parse_ExprBlockNode(lex);
+
+ case TOK_INTERPOLATED_EXPR:
+ case TOK_INTERPOLATED_BLOCK:
+ return tok.take_frag_node();
+
+
+ // TODO: Return/break/continue/... here?
+ case TOK_RWORD_RETURN:
+ case TOK_RWORD_CONTINUE:
+ case TOK_RWORD_BREAK:
+ PUTBACK(tok, lex);
+ return Parse_Stmt(lex);
+
+ case TOK_RWORD_LOOP:
+ return NEWNODE( AST::ExprNode_Loop, "", Parse_ExprBlockNode(lex) );
+ case TOK_RWORD_WHILE:
+ return Parse_WhileStmt(lex, "");
+ case TOK_RWORD_FOR:
+ return Parse_ForStmt(lex, "");
+ case TOK_RWORD_MATCH:
+ return Parse_Expr_Match(lex);
+ case TOK_RWORD_IF:
+ return Parse_IfStmt(lex);
+ case TOK_RWORD_UNSAFE:
+ return Parse_ExprBlockNode(lex, true);
+
+ // UFCS
+ case TOK_DOUBLE_LT:
+ case TOK_LT:
+ PUTBACK(tok, lex);
+ path = Parse_Path(lex, PATH_GENERIC_EXPR);
+ // Skip down to method
+ if(0)
+ case TOK_RWORD_SELF:
+ {
+ if( LOOK_AHEAD(lex) != TOK_DOUBLE_COLON ) {
+ return NEWNODE( AST::ExprNode_NamedValue, AST::Path(AST::Path::TagLocal(), "self") );
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ path = Parse_Path(lex, PATH_GENERIC_EXPR);
+ }
+ }
+ if(0)
+ case TOK_RWORD_SUPER:
+ {
+ PUTBACK(tok, lex);
+ path = Parse_Path(lex, PATH_GENERIC_EXPR);
+ }
+ if(0)
+ case TOK_IDENT:
+ // Get path
+ {
+ PUTBACK(tok, lex);
+ path = Parse_Path(lex, false, PATH_GENERIC_EXPR);
+ }
+ if(0)
+ case TOK_INTERPOLATED_PATH:
+ {
+ path = mv$(tok.frag_path());
+ }
+ if(0)
+ case TOK_DOUBLE_COLON:
+ path = Parse_Path(lex, true, PATH_GENERIC_EXPR);
+ // SKIP TARGET
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_PAREN_OPEN:
+ // Function call
+ PUTBACK(tok, lex);
+ return NEWNODE( AST::ExprNode_CallPath, ::std::move(path), Parse_ParenList(lex) );
+ case TOK_BRACE_OPEN:
+ if( !CHECK_PARSE_FLAG(lex, disallow_struct_literal) )
+ return Parse_ExprVal_StructLiteral(lex, ::std::move(path));
+ else
+ DEBUG("Not parsing struct literal");
+ default:
+ // Value
+ PUTBACK(tok, lex);
+ return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) );
+ }
+ case TOK_RWORD_MOVE:
+ // TODO: Annotate closure as move
+ GET_TOK(tok, lex);
+ if(tok.type() == TOK_PIPE)
+ return Parse_ExprVal_Closure(lex, true);
+ else if(tok.type() == TOK_DOUBLE_PIPE) {
+ lex.putback(Token(TOK_PIPE));
+ return Parse_ExprVal_Closure(lex, true);
+ }
+ else {
+ CHECK_TOK(tok, TOK_PIPE);
+ }
+ case TOK_DOUBLE_PIPE:
+ lex.putback(Token(TOK_PIPE));
+ case TOK_PIPE:
+ return Parse_ExprVal_Closure(lex, false);
+ case TOK_INTEGER:
+ return NEWNODE( AST::ExprNode_Integer, tok.intval(), tok.datatype() );
+ case TOK_FLOAT:
+ return NEWNODE( AST::ExprNode_Float, tok.floatval(), tok.datatype() );
+ case TOK_STRING:
+ return NEWNODE( AST::ExprNode_String, tok.str() );
+ case TOK_BYTESTRING:
+ return NEWNODE( AST::ExprNode_ByteString, tok.str() );
+ case TOK_RWORD_TRUE:
+ return NEWNODE( AST::ExprNode_Bool, true );
+ case TOK_RWORD_FALSE:
+ return NEWNODE( AST::ExprNode_Bool, false );
+ case TOK_PAREN_OPEN:
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ {
+ DEBUG("Unit");
+ return NEWNODE( AST::ExprNode_Tuple, ::std::vector<ExprNodeP>() );
+ }
+ else
+ {
+ CLEAR_PARSE_FLAG(lex, disallow_struct_literal);
+ PUTBACK(tok, lex);
+
+ ExprNodeP rv = Parse_Expr0(lex);
+ if( GET_TOK(tok, lex) == TOK_COMMA ) {
+ ::std::vector<ExprNodeP> ents;
+ ents.push_back( ::std::move(rv) );
+ do {
+ if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
+ break;
+ PUTBACK(tok, lex);
+ ents.push_back( Parse_Expr0(lex) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ rv = NEWNODE( AST::ExprNode_Tuple, ::std::move(ents) );
+ }
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ return rv;
+ }
+ case TOK_SQUARE_OPEN:
+ if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE )
+ {
+ // Empty literal
+ return NEWNODE( AST::ExprNode_Array, ::std::vector<ExprNodeP>() );
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ auto first = Parse_Expr0(lex);
+ if( GET_TOK(tok, lex) == TOK_SEMICOLON )
+ {
+ // Repetiion
+ auto count = Parse_Expr0(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ return NEWNODE( AST::ExprNode_Array, ::std::move(first), ::std::move(count) );
+ }
+ else
+ {
+ ::std::vector<ExprNodeP> items;
+ items.push_back( ::std::move(first) );
+ while( tok.type() == TOK_COMMA )
+ {
+ if( GET_TOK(tok, lex) == TOK_SQUARE_CLOSE )
+ break;
+ else
+ PUTBACK(tok, lex);
+ items.push_back( Parse_Expr0(lex) );
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SQUARE_CLOSE);
+ return NEWNODE( AST::ExprNode_Array, ::std::move(items) );
+ }
+ }
+ throw ParseError::BugCheck(lex, "Array literal fell");
+ case TOK_MACRO:
+ return Parse_ExprMacro(lex, mv$(tok));
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+}
+ExprNodeP Parse_ExprMacro(TokenStream& lex, Token tok)
+{
+ ::std::string name = tok.str();
+ ::std::string ident;
+ if( GET_TOK(tok, lex) == TOK_IDENT ) {
+ ident = mv$(tok.str());
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ TokenTree tt = Parse_TT(lex, true);
+ if( tt.is_token() ) {
+ throw ParseError::Unexpected(lex, tt.tok());
+ }
+ return NEWNODE(AST::ExprNode_Macro, mv$(name), mv$(ident), mv$(tt));
+}
+
+// Token Tree Parsing
+TokenTree Parse_TT(TokenStream& lex, bool unwrapped)
+{
+ TokenTree rv;
+ TRACE_FUNCTION_FR("", rv);
+
+ Token tok = lex.getToken();
+ eTokenType closer = TOK_PAREN_CLOSE;
+ switch(tok.type())
+ {
+ case TOK_PAREN_OPEN:
+ closer = TOK_PAREN_CLOSE;
+ break;
+ case TOK_SQUARE_OPEN:
+ closer = TOK_SQUARE_CLOSE;
+ break;
+ case TOK_BRACE_OPEN:
+ closer = TOK_BRACE_CLOSE;
+ break;
+ // HACK! mrustc parses #[ and #![ as composite tokens
+ // TODO: Split these into their component tokens.
+ case TOK_ATTR_OPEN:
+ case TOK_CATTR_OPEN:
+ if( unwrapped )
+ throw ParseError::Unexpected(lex, tok);
+ closer = TOK_SQUARE_CLOSE;
+ break;
+
+ case TOK_EOF:
+ case TOK_NULL:
+ case TOK_PAREN_CLOSE:
+ case TOK_SQUARE_CLOSE:
+ case TOK_BRACE_CLOSE:
+ throw ParseError::Unexpected(lex, tok);
+ default:
+ rv = TokenTree(lex.getHygiene(), mv$(tok) );
+ return rv;
+ }
+
+ ::std::vector<TokenTree> items;
+ if( !unwrapped )
+ items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) );
+ while(GET_TOK(tok, lex) != closer && tok.type() != TOK_EOF)
+ {
+ if( tok.type() == TOK_NULL )
+ throw ParseError::Unexpected(lex, tok);
+ PUTBACK(tok, lex);
+ items.push_back(Parse_TT(lex, false));
+ }
+ if( !unwrapped )
+ items.push_back( TokenTree(lex.getHygiene(), mv$(tok)) );
+ rv = TokenTree(lex.getHygiene(), mv$(items));
+ return rv;
+}
diff --git a/src/parse/interpolated_fragment.hpp b/src/parse/interpolated_fragment.hpp
index b0be2efe..a3e72816 100644
--- a/src/parse/interpolated_fragment.hpp
+++ b/src/parse/interpolated_fragment.hpp
@@ -25,18 +25,18 @@ public:
PAT,
PATH,
TYPE,
-
+
EXPR,
STMT,
BLOCK,
-
+
META,
ITEM,
} m_type;
-
+
// Owned type-pruned pointer
void* m_ptr;
-
+
InterpolatedFragment(InterpolatedFragment&& );
InterpolatedFragment& operator=(InterpolatedFragment&& );
//InterpolatedFragment(const InterpolatedFragment& );
@@ -48,9 +48,9 @@ public:
InterpolatedFragment(::AST::Named<AST::Item> );
~InterpolatedFragment();
InterpolatedFragment(Type , ::AST::ExprNode*);
-
+
TokenTree& as_tt() { assert(m_type == TT); return *reinterpret_cast<TokenTree*>(m_ptr); }
const TokenTree& as_tt() const { assert(m_type == TT); return *reinterpret_cast<TokenTree*>(m_ptr); }
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const InterpolatedFragment& x);
};
diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp
index dfd2a2d3..9b09b1d4 100644
--- a/src/parse/lex.cpp
+++ b/src/parse/lex.cpp
@@ -275,7 +275,7 @@ Token Lexer::getTokenInt()
try
{
Codepoint ch = this->getc();
-
+
if( ch == '#' && m_line == 1 && m_line_ofs == 1 ) {
switch( (ch = this->getc()).v )
{
@@ -326,8 +326,8 @@ Token Lexer::getTokenInt()
DEC,
HEX,
} num_mode = DEC;
-
-
+
+
// Handle integers/floats
uint64_t val = 0;
if( ch == '0' ) {
@@ -390,7 +390,7 @@ Token Lexer::getTokenInt()
if( ch == '.' )
{
ch = this->getc();
-
+
// Double/Triple Dot
if( ch == '.' )
{
@@ -403,7 +403,7 @@ Token Lexer::getTokenInt()
}
return Token(val, CORETYPE_ANY);
}
-
+
// Single dot followed by a non-digit, could be a float or an integer with a method/field access
if( !ch.isdigit() )
{
@@ -428,8 +428,8 @@ Token Lexer::getTokenInt()
}
if( num_mode != DEC )
TODO(this->getPosition(), "Non-decimal floats");
-
-
+
+
this->ungetc();
double fval = this->parseFloat(val);
if( issym(ch = this->getc()) )
@@ -441,7 +441,7 @@ Token Lexer::getTokenInt()
ch = this->getc();
}
this->ungetc();
-
+
if(0) ;
else if(suffix == "f32") num_type = CORETYPE_F32;
else if(suffix == "f64") num_type = CORETYPE_F64;
@@ -464,7 +464,7 @@ Token Lexer::getTokenInt()
ch = this->getc();
}
this->ungetc();
-
+
if(0) ;
else if(suffix == "i8") num_type = CORETYPE_I8;
else if(suffix == "i16") num_type = CORETYPE_I16;
@@ -495,13 +495,13 @@ Token Lexer::getTokenInt()
is_byte = true;
ch = this->getc();
}
-
+
if(ch == 'r') {
return this->getTokenInt_RawString(is_byte);
}
else {
assert(is_byte);
-
+
// Byte string
if( ch == '"' ) {
::std::string str;
@@ -579,7 +579,7 @@ Token Lexer::getTokenInt()
while(true)
{
ch = this->getc();
-
+
if( ch == '/' ) {
str += ch;
ch = this->getc();
@@ -704,7 +704,7 @@ Token Lexer::getTokenInt_RawString(bool is_byte)
catch( Lexer::EndOfFile e ) {
throw ParseError::Generic(*this, "EOF reached in raw string");
}
-
+
if( terminating_hashes > 0 )
{
assert(terminating_hashes > 0);
@@ -715,7 +715,7 @@ Token Lexer::getTokenInt_RawString(bool is_byte)
terminating_hashes += 1;
}
terminating_hashes = 0;
-
+
this->ungetc();
}
else {
@@ -800,9 +800,9 @@ double Lexer::parseFloat(uint64_t whole)
}
this->ungetc();
buf[ofs] = 0;
-
+
DEBUG("buf = " << buf << ", ch = '" << ch << "'");
-
+
return ::std::strtod(buf, NULL);
}
@@ -920,7 +920,7 @@ Codepoint Lexer::getc_cp()
// Two bytes
uint8_t e1 = this->getc_byte();
if( (e1 & 0xC0) != 0x80 ) return {0xFFFE};
-
+
uint32_t outval
= ((v1 & 0x1F) << 6)
| ((e1 & 0x3F) <<0)
@@ -933,7 +933,7 @@ Codepoint Lexer::getc_cp()
if( (e1 & 0xC0) != 0x80 ) return {0xFFFE};
uint8_t e2 = this->getc_byte();
if( (e2 & 0xC0) != 0x80 ) return {0xFFFE};
-
+
uint32_t outval
= ((v1 & 0x0F) << 12)
| ((e1 & 0x3F) << 6)
@@ -949,7 +949,7 @@ Codepoint Lexer::getc_cp()
if( (e2 & 0xC0) != 0x80 ) return {0xFFFE};
uint8_t e3 = this->getc_byte();
if( (e3 & 0xC0) != 0x80 ) return {0xFFFE};
-
+
uint32_t outval
= ((v1 & 0x07) << 18)
| ((e1 & 0x3F) << 12)
@@ -1004,7 +1004,7 @@ bool Codepoint::isxdigit() const {
s += (char)cp.v;
}
else if( cp.v < (0x1F+1)<<(1*6) ) {
-
+
s += (char)(0xC0 | ((cp.v >> 6) & 0x1F));
s += (char)(0x80 | ((cp.v >> 0) & 0x3F));
}
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index 572846da..871ab29a 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -40,7 +40,7 @@ class Lexer:
bool m_last_char_valid;
Codepoint m_last_char;
Token m_next_token; // Used when lexing generated two tokens
-
+
Ident::Hygiene m_hygiene;
public:
Lexer(const ::std::string& filename);
@@ -51,7 +51,7 @@ public:
private:
Token getTokenInt();
-
+
signed int getSymbol();
Token getTokenInt_RawString(bool is_byte);
Token getTokenInt_Identifier(Codepoint ch, Codepoint ch2='\0');
diff --git a/src/parse/parseerror.cpp b/src/parse/parseerror.cpp
index 116776a5..3c5d41fe 100644
--- a/src/parse/parseerror.cpp
+++ b/src/parse/parseerror.cpp
@@ -1,91 +1,91 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * parse/parseerror.cpp
- * - Exceptions thrown for different types of parsing errors
- */
-#include "parseerror.hpp"
-#include <iostream>
-
-CompileError::Base::~Base() throw()
-{
-}
-
-CompileError::Generic::Generic(::std::string message):
- m_message(message)
-{
- ::std::cout << "Generic(" << message << ")" << ::std::endl;
-}
-CompileError::Generic::Generic(const TokenStream& lex, ::std::string message)
-{
- ::std::cout << lex.getPosition() << ": Generic(" << message << ")" << ::std::endl;
-}
-
-CompileError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message):
- m_message(message)
-{
- ::std::cout << lex.getPosition() << "BugCheck(" << message << ")" << ::std::endl;
-}
-CompileError::BugCheck::BugCheck(::std::string message):
- m_message(message)
-{
- ::std::cout << "BugCheck(" << message << ")" << ::std::endl;
-}
-
-CompileError::Todo::Todo(::std::string message):
- m_message(message)
-{
- ::std::cout << "Todo(" << message << ")" << ::std::endl;
-}
-CompileError::Todo::Todo(const TokenStream& lex, ::std::string message):
- m_message(message)
-{
- ::std::cout << lex.getPosition() << ": Todo(" << message << ")" << ::std::endl;
-}
-CompileError::Todo::~Todo() throw()
-{
-}
-
-ParseError::BadChar::BadChar(const TokenStream& lex, char character)
-{
- ::std::cout << lex.getPosition() << ": BadChar(" << character << ")" << ::std::endl;
-}
-ParseError::BadChar::~BadChar() throw()
-{
-}
-
-ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok)//:
-// m_tok( mv$(tok) )
-{
- auto pos = tok.get_pos();
- if(pos.filename == "")
- pos = lex.getPosition();
- ::std::cout << pos << ": Unexpected(" << tok << ")" << ::std::endl;
-}
-ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, Token exp)//:
-// m_tok( mv$(tok) )
-{
- auto pos = tok.get_pos();
- if(pos.filename == "")
- pos = lex.getPosition();
- ::std::cout << pos << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl;
-}
-ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, ::std::vector<eTokenType> exp)
-{
- auto pos = tok.get_pos();
- if(pos.filename == "")
- pos = lex.getPosition();
- ::std::cout << pos << ": Unexpected " << tok << ", expected ";
- bool f = true;
- for(auto v: exp) {
- if(!f)
- ::std::cout << " or ";
- f = false;
- ::std::cout << Token::typestr(v);
- }
- ::std::cout << ::std::endl;
-}
-ParseError::Unexpected::~Unexpected() throw()
-{
-}
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/parseerror.cpp
+ * - Exceptions thrown for different types of parsing errors
+ */
+#include "parseerror.hpp"
+#include <iostream>
+
+CompileError::Base::~Base() throw()
+{
+}
+
+CompileError::Generic::Generic(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "Generic(" << message << ")" << ::std::endl;
+}
+CompileError::Generic::Generic(const TokenStream& lex, ::std::string message)
+{
+ ::std::cout << lex.getPosition() << ": Generic(" << message << ")" << ::std::endl;
+}
+
+CompileError::BugCheck::BugCheck(const TokenStream& lex, ::std::string message):
+ m_message(message)
+{
+ ::std::cout << lex.getPosition() << "BugCheck(" << message << ")" << ::std::endl;
+}
+CompileError::BugCheck::BugCheck(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "BugCheck(" << message << ")" << ::std::endl;
+}
+
+CompileError::Todo::Todo(::std::string message):
+ m_message(message)
+{
+ ::std::cout << "Todo(" << message << ")" << ::std::endl;
+}
+CompileError::Todo::Todo(const TokenStream& lex, ::std::string message):
+ m_message(message)
+{
+ ::std::cout << lex.getPosition() << ": Todo(" << message << ")" << ::std::endl;
+}
+CompileError::Todo::~Todo() throw()
+{
+}
+
+ParseError::BadChar::BadChar(const TokenStream& lex, char character)
+{
+ ::std::cout << lex.getPosition() << ": BadChar(" << character << ")" << ::std::endl;
+}
+ParseError::BadChar::~BadChar() throw()
+{
+}
+
+ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok)//:
+// m_tok( mv$(tok) )
+{
+ auto pos = tok.get_pos();
+ if(pos.filename == "")
+ pos = lex.getPosition();
+ ::std::cout << pos << ": Unexpected(" << tok << ")" << ::std::endl;
+}
+ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, Token exp)//:
+// m_tok( mv$(tok) )
+{
+ auto pos = tok.get_pos();
+ if(pos.filename == "")
+ pos = lex.getPosition();
+ ::std::cout << pos << ": Unexpected(" << tok << ", " << exp << ")" << ::std::endl;
+}
+ParseError::Unexpected::Unexpected(const TokenStream& lex, const Token& tok, ::std::vector<eTokenType> exp)
+{
+ auto pos = tok.get_pos();
+ if(pos.filename == "")
+ pos = lex.getPosition();
+ ::std::cout << pos << ": Unexpected " << tok << ", expected ";
+ bool f = true;
+ for(auto v: exp) {
+ if(!f)
+ ::std::cout << " or ";
+ f = false;
+ ::std::cout << Token::typestr(v);
+ }
+ ::std::cout << ::std::endl;
+}
+ParseError::Unexpected::~Unexpected() throw()
+{
+}
diff --git a/src/parse/parseerror.hpp b/src/parse/parseerror.hpp
index 0a00f60a..d6bcab6b 100644
--- a/src/parse/parseerror.hpp
+++ b/src/parse/parseerror.hpp
@@ -1,40 +1,40 @@
-#ifndef PARSEERROR_HPP_INCLUDED
-#define PARSEERROR_HPP_INCLUDED
-
-#include <stdexcept>
-#include "tokenstream.hpp"
-#include <compile_error.hpp>
-
-namespace ParseError {
-
-using CompileError::Generic;
-using CompileError::BugCheck;
-using CompileError::Todo;
-
-class BadChar:
- public CompileError::Base
-{
- //char m_char;
-public:
- BadChar(const TokenStream& lex, char character);
- virtual ~BadChar() throw ();
-
-};
-
-class Unexpected:
- public CompileError::Base
-{
- Token m_tok;
-public:
- Unexpected(const TokenStream& lex, const Token& tok);
- Unexpected(const TokenStream& lex, const Token& tok, Token exp);
- Unexpected(const TokenStream& lex, const Token& tok, ::std::vector<eTokenType> exp);
- virtual ~Unexpected() throw ();
-
-};
-
-#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: " __FILE__ " - " #cnd); } while(0)
-
-}
-
-#endif // PARSEERROR_HPP_INCLUDED
+#ifndef PARSEERROR_HPP_INCLUDED
+#define PARSEERROR_HPP_INCLUDED
+
+#include <stdexcept>
+#include "tokenstream.hpp"
+#include <compile_error.hpp>
+
+namespace ParseError {
+
+using CompileError::Generic;
+using CompileError::BugCheck;
+using CompileError::Todo;
+
+class BadChar:
+ public CompileError::Base
+{
+ //char m_char;
+public:
+ BadChar(const TokenStream& lex, char character);
+ virtual ~BadChar() throw ();
+
+};
+
+class Unexpected:
+ public CompileError::Base
+{
+ Token m_tok;
+public:
+ Unexpected(const TokenStream& lex, const Token& tok);
+ Unexpected(const TokenStream& lex, const Token& tok, Token exp);
+ Unexpected(const TokenStream& lex, const Token& tok, ::std::vector<eTokenType> exp);
+ virtual ~Unexpected() throw ();
+
+};
+
+#define ASSERT(lex, cnd) do { if( !(cnd) ) throw CompileError::BugCheck(lex, "Assertion failed: " __FILE__ " - " #cnd); } while(0)
+
+}
+
+#endif // PARSEERROR_HPP_INCLUDED
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp
index e600e51e..360c630f 100644
--- a/src/parse/paths.cpp
+++ b/src/parse/paths.cpp
@@ -17,17 +17,17 @@ AST::PathParams Parse_Path_GenericList(TokenStream& lex);
AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
{
TRACE_FUNCTION_F("generic_mode="<<generic_mode);
-
+
Token tok;
switch( GET_TOK(tok, lex) )
{
case TOK_INTERPOLATED_PATH:
return mv$(tok.frag_path());
-
+
case TOK_RWORD_SELF:
GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
return Parse_Path(lex, false, generic_mode);
-
+
case TOK_RWORD_SUPER: {
GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
unsigned int count = 1;
@@ -38,10 +38,10 @@ AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
}
return AST::Path(AST::Path::TagSuper(), count, Parse_PathNodes(lex, generic_mode));
}
-
+
case TOK_DOUBLE_COLON:
return Parse_Path(lex, true, generic_mode);
-
+
case TOK_DOUBLE_LT:
lex.putback( Token(TOK_LT) );
case TOK_LT: {
@@ -69,7 +69,7 @@ AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
return AST::Path(AST::Path::TagUfcs(), mv$(ty), AST::Path(), Parse_PathNodes(lex, generic_mode));
}
throw ""; }
-
+
default:
PUTBACK(tok, lex);
return Parse_Path(lex, false, generic_mode);
@@ -102,7 +102,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode)
{
TRACE_FUNCTION_F("generic_mode="<<generic_mode);
-
+
Token tok;
::std::vector<AST::PathNode> ret;
@@ -122,7 +122,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
// HACK! Handle breaking << into < <
if( tok.type() == TOK_DOUBLE_LT )
lex.putback( Token(TOK_LT) );
-
+
// Type-mode generics "::path::to::Type<A,B>"
params = Parse_Path_GenericList(lex);
GET_TOK(tok, lex);
@@ -146,7 +146,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
} while( GET_TOK(tok, lex) == TOK_COMMA );
}
CHECK_TOK(tok, TOK_PAREN_CLOSE);
-
+
TypeRef ret_type = TypeRef( TypeRef::TagUnit(), Span(tok.get_pos()) );
if( GET_TOK(tok, lex) == TOK_THINARROW ) {
ret_type = Parse_Type(lex, false);
@@ -155,14 +155,14 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
PUTBACK(tok, lex);
}
DEBUG("- Fn("<<args<<")->"<<ret_type<<"");
-
+
// Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C>
params = ::AST::PathParams {
{},
::make_vec1( TypeRef(TypeRef::TagTuple(), lex.end_span(ps), mv$(args)) ),
::make_vec1( ::std::make_pair( ::std::string("Output"), mv$(ret_type) ) )
};
-
+
GET_TOK(tok, lex);
}
else
@@ -179,7 +179,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
// HACK! Handle breaking << into < <
if( tok.type() == TOK_DOUBLE_LT )
lex.putback( Token(TOK_LT) );
-
+
// Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"
params = Parse_Path_GenericList(lex);
if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) {
@@ -205,7 +205,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
::std::vector<TypeRef> types;
::std::vector< ::std::string> lifetimes;
::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds;
-
+
do {
if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT || LOOK_AHEAD(lex) == TOK_GTE || LOOK_AHEAD(lex) == TOK_DOUBLE_GT_EQUAL ) {
GET_TOK(tok, lex);
@@ -244,7 +244,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
else {
CHECK_TOK(tok, TOK_GT);
}
-
+
return ::AST::PathParams {
mv$( lifetimes ),
mv$( types ),
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
index b0149ddb..699e7fae 100644
--- a/src/parse/pattern.cpp
+++ b/src/parse/pattern.cpp
@@ -42,7 +42,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
Token tok;
tok = lex.getToken();
-
+
if( tok.type() == TOK_MACRO )
{
return AST::Pattern( AST::Pattern::TagMacro(), box$(Parse_MacroInvocation(ps, tok.str(), lex)));
@@ -51,7 +51,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
{
return mv$(tok.frag_pattern());
}
-
+
bool expect_bind = false;
auto bind_type = AST::PatternBinding::Type::MOVE;
bool is_mut = false;
@@ -80,7 +80,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
{
// Fall through
}
-
+
AST::PatternBinding binding;
// If a 'ref' or 'mut' annotation was seen, the next name must be a binding name
if( expect_bind )
@@ -94,7 +94,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
return AST::Pattern(AST::Pattern::TagBind(), mv$(bind_name), bind_type, is_mut);
}
binding = AST::PatternBinding( mv$(bind_name), bind_type, is_mut );
-
+
// '@' consumed, move on to next token
GET_TOK(tok, lex);
}
@@ -138,7 +138,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
{
// Otherwise, fall through
}
-
+
PUTBACK(tok, lex);
auto pat = Parse_PatternReal(lex, is_refutable);
pat.binding() = mv$(binding);
@@ -159,13 +159,13 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable)
if( !ret.data().is_Value() )
throw ParseError::Generic(lex, "Using '...' with a non-value on left");
auto& ret_v = ret.data().as_Value();
-
+
auto right_pat = Parse_PatternReal1(lex, is_refutable);
if( !right_pat.data().is_Value() )
throw ParseError::Generic(lex, "Using '...' with a non-value on right");
auto rightval = mv$( right_pat.data().as_Value().start );
ret_v.end = mv$(rightval);
-
+
return ret;
}
else
@@ -177,10 +177,10 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable)
AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable)
{
TRACE_FUNCTION;
-
+
Token tok;
AST::Path path;
-
+
switch( GET_TOK(tok, lex) )
{
case TOK_UNDERSCORE:
@@ -260,7 +260,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable)
TODO(lex.getPosition(), "Convert :expr into a pattern value - " << *e);
}
} break;
-
+
case TOK_PAREN_OPEN:
return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternTuple(lex, is_refutable) );
case TOK_SQUARE_OPEN:
@@ -272,7 +272,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable)
AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable)
{
Token tok;
-
+
switch( GET_TOK(tok, lex) )
{
case TOK_PAREN_OPEN:
@@ -289,12 +289,12 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
{
auto sp = lex.start_span();
Token tok;
-
+
::std::vector< ::AST::Pattern> leading;
::std::vector< ::AST::Pattern> trailing;
::AST::PatternBinding inner_binding;
bool is_split = false;
-
+
while(GET_TOK(tok, lex) != TOK_SQUARE_CLOSE)
{
bool has_binding = true;
@@ -316,11 +316,11 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
else {
has_binding = false;
}
-
+
if( has_binding ) {
if(is_split)
ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in a slice pattern");
-
+
inner_binding = mv$(binding);
is_split = true;
GET_TOK(tok, lex); // TOK_DOUBLE_DOT
@@ -334,12 +334,12 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
trailing.push_back( Parse_Pattern(lex, is_refutable) );
}
}
-
+
if( GET_TOK(tok, lex) != TOK_COMMA )
break;
}
CHECK_TOK(tok, TOK_SQUARE_CLOSE);
-
+
if( is_split )
{
return ::AST::Pattern( ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) );
@@ -357,34 +357,34 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
TRACE_FUNCTION;
auto sp = lex.start_span();
Token tok;
-
+
::std::vector<AST::Pattern> leading;
while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE && LOOK_AHEAD(lex) != TOK_DOUBLE_DOT )
{
leading.push_back( Parse_Pattern(lex, is_refutable) );
-
+
if( GET_TOK(tok, lex) != TOK_COMMA ) {
CHECK_TOK(tok, TOK_PAREN_CLOSE);
return AST::Pattern::TuplePat { mv$(leading), false, {} };
}
}
-
+
if( LOOK_AHEAD(lex) != TOK_DOUBLE_DOT )
{
GET_TOK(tok, lex);
-
+
CHECK_TOK(tok, TOK_PAREN_CLOSE);
return AST::Pattern::TuplePat { mv$(leading), false, {} };
}
GET_CHECK_TOK(tok, lex, TOK_DOUBLE_DOT);
-
+
::std::vector<AST::Pattern> trailing;
if( GET_TOK(tok, lex) == TOK_COMMA )
{
while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE )
{
trailing.push_back( Parse_Pattern(lex, is_refutable) );
-
+
if( GET_TOK(tok, lex) != TOK_COMMA ) {
PUTBACK(tok, lex);
break;
@@ -392,7 +392,7 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable)
}
GET_TOK(tok, lex);
}
-
+
CHECK_TOK(tok, TOK_PAREN_CLOSE);
return ::AST::Pattern::TuplePat { mv$(leading), true, mv$(trailing) };
}
@@ -401,7 +401,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
{
TRACE_FUNCTION;
Token tok;
-
+
// #![feature(relaxed_adts)]
if( LOOK_AHEAD(lex) == TOK_INTEGER )
{
@@ -415,7 +415,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
if( ! pats.insert( ::std::make_pair(ofs, mv$(val)) ).second ) {
ERROR(lex.getPosition(), E0000, "Duplicate index");
}
-
+
if( GET_TOK(tok,lex) == TOK_BRACE_CLOSE )
break;
CHECK_TOK(tok, TOK_COMMA);
@@ -425,7 +425,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
GET_TOK(tok, lex);
}
CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
+
bool has_split = false;
::std::vector<AST::Pattern> leading;
::std::vector<AST::Pattern> trailing;
@@ -447,10 +447,10 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
}
i ++;
}
-
+
return AST::Pattern(AST::Pattern::TagNamedTuple(), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) });
}
-
+
bool is_exhaustive = true;
::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats;
do {
@@ -463,7 +463,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
GET_TOK(tok, lex);
break;
}
-
+
bool is_short_bind = false;
bool is_box = false;
auto bind_type = AST::PatternBinding::Type::MOVE;
@@ -489,12 +489,12 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
is_short_bind = true;
GET_TOK(tok, lex);
}
-
+
CHECK_TOK(tok, TOK_IDENT);
auto field_ident = lex.get_ident(mv$(tok));
::std::string field_name;
GET_TOK(tok, lex);
-
+
AST::Pattern pat;
if( is_short_bind || tok.type() != TOK_COLON ) {
PUTBACK(tok, lex);
@@ -511,11 +511,11 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
field_name = mv$(field_ident.name);
pat = Parse_Pattern(lex, is_refutable);
}
-
+
subpats.push_back( ::std::make_pair(mv$(field_name), mv$(pat)) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
+
return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats), is_exhaustive);
}
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 5a244543..e5f5b5f4 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -1,1879 +1,1879 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * parse/root.cpp
- * - Parsing at the module level (highest-level parsing)
- *
- * Entrypoint:
- * - Parse_Crate : Handles crate attrbutes, and passes on to Parse_ModRoot
- * - Parse_ModRoot
- */
-#include <ast/ast.hpp>
-#include <ast/crate.hpp>
-#include "parseerror.hpp"
-#include "common.hpp"
-#include <cassert>
-#include <hir/hir.hpp> // ABI_RUST - TODO: Move elsewhere?
-#include <expand/cfg.hpp> // check_cfg - for `mod nonexistant;`
-#include <fstream> // Used by directory path
-#include "lex.hpp" // New file lexer
-
-template<typename T>
-Spanned<T> get_spanned(TokenStream& lex, ::std::function<T()> f) {
- auto ps = lex.start_span();
- auto v = f();
- return Spanned<T> {
- lex.end_span(ps),
- mv$(v)
- };
-}
-#define GET_SPANNED(type, lex, val) get_spanned< type >(lex, [&](){ return val; })
-
-// Check the next two tokens
-#define LOOKAHEAD2(lex, tok1, tok2) ((lex).lookahead(0) == (tok1) && (lex).lookahead(1) == (tok2))
-
-::std::string dirname(::std::string input) {
- while( input.size() > 0 && input.back() != '/' ) {
- input.pop_back();
- }
- return input;
-}
-
-AST::MetaItem Parse_MetaItem(TokenStream& lex);
-void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs);
-
-::std::vector< ::std::string> Parse_HRB(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
-
- ::std::vector< ::std::string> lifetimes;
- GET_CHECK_TOK(tok, lex, TOK_LT);
- do {
- GET_TOK(tok, lex);
-
- ::AST::MetaItems attrs;
- while(tok.type() == TOK_ATTR_OPEN)
- {
- attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- (void)attrs; // TODO: Attributes on generic params
-
- switch(tok.type())
- {
- case TOK_LIFETIME:
- lifetimes.push_back(tok.str());
- break;
- default:
- throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME));
- }
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_GT);
- return lifetimes;
-}
-/// Parse type parameters in a definition
-void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, ::std::vector< ::std::string> lifetimes = {})
-{
- TRACE_FUNCTION;
- Token tok;
-
- do
- {
- ::std::vector< ::std::string> hrls;
- if(GET_TOK(tok, lex) == TOK_LIFETIME) {
- ret.add_bound(AST::GenericBound::make_TypeLifetime( {
- checked_type.clone(), tok.str()
- } ));
- }
- else if( tok.type() == TOK_QMARK ) {
- ret.add_bound(AST::GenericBound::make_MaybeTrait( {
- checked_type.clone(), Parse_Path(lex, PATH_GENERIC_TYPE)
- } ));
- }
- else {
- if( tok.type() == TOK_RWORD_FOR )
- {
- hrls = Parse_HRB(lex);
- }
- else {
- PUTBACK(tok, lex);
- }
- (void)hrls; // TODO: HRLs
-
- ret.add_bound( AST::GenericBound::make_IsTrait({
- checked_type.clone(), mv$(lifetimes), Parse_Path(lex, PATH_GENERIC_TYPE)
- }) );
- }
- } while( GET_TOK(tok, lex) == TOK_PLUS );
- PUTBACK(tok, lex);
-}
-
-/// Parse type parameters within '<' and '>' (definition)
-AST::GenericParams Parse_GenericParams(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- AST::GenericParams ret;
- Token tok;
- do {
- if( GET_TOK(tok, lex) == TOK_GT ) {
- break ;
- }
-
- ::AST::MetaItems attrs;
- while(tok.type() == TOK_ATTR_OPEN)
- {
- attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- (void)attrs; // TODO: Attributes on generic params
-
- if( tok.type() == TOK_IDENT )
- {
- // TODO: Hygine
- ::std::string param_name = mv$(tok.str());
- ret.add_ty_param( AST::TypeParam( param_name ) );
-
- auto param_ty = TypeRef(lex.getPosition(), param_name);
- if( GET_TOK(tok, lex) == TOK_COLON )
- {
- Parse_TypeBound(lex, ret, mv$(param_ty));
- GET_TOK(tok, lex);
- }
-
- if( tok.type() == TOK_EQUAL )
- {
- ret.ty_params().back().setDefault( Parse_Type(lex) );
- GET_TOK(tok, lex);
- }
- }
- else if( tok.type() == TOK_LIFETIME )
- {
- // TODO: Should lifetimes have hygine?
- ::std::string param_name = tok.str();
- ret.add_lft_param( param_name );
- if( GET_TOK(tok, lex) == TOK_COLON )
- {
- do {
- GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
- ret.add_bound(AST::GenericBound::make_Lifetime( {param_name, tok.str()} ));
- } while( GET_TOK(tok, lex) == TOK_PLUS );
- }
- }
- else
- {
- throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_LIFETIME});
- }
- } while( tok.type() == TOK_COMMA );
- PUTBACK(tok, lex);
- return ret;
-}
-
-
-/// Parse the contents of a 'where' clause
-void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params)
-{
- TRACE_FUNCTION;
- Token tok;
-
- do {
- GET_TOK(tok, lex);
- if( tok.type() == TOK_BRACE_OPEN ) {
- break;
- }
-
- if( tok.type() == TOK_LIFETIME )
- {
- auto lhs = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- do {
- GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
- auto rhs = mv$(tok.str());
- params.add_bound( AST::GenericBound::make_Lifetime({lhs, rhs}) );
- } while( GET_TOK(tok, lex) == TOK_PLUS );
- PUTBACK(tok, lex);
- }
- // Higher-ranked types/lifetimes
- else if( tok.type() == TOK_RWORD_FOR )
- {
- ::std::vector< ::std::string> lifetimes = Parse_HRB(lex);
-
- TypeRef type = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- Parse_TypeBound(lex,params, mv$(type), mv$(lifetimes));
- }
- else
- {
- PUTBACK(tok, lex);
- TypeRef type = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- Parse_TypeBound(lex, params, mv$(type));
- }
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- PUTBACK(tok, lex);
-}
-
-// Parse a single function argument
-::std::pair< AST::Pattern, TypeRef> Parse_Function_Arg(TokenStream& lex, bool expect_named)
-{
- TRACE_FUNCTION_F("expect_named = " << expect_named);
- Token tok;
-
- AST::Pattern pat;
-
- // If any of the following
- // - Expecting a named parameter (i.e. defining a function in root or impl)
- // - Next token is an underscore (only valid as a pattern here)
- // - Next token is 'mut' (a mutable parameter slot)
- // - Next two are <ident> ':' (a trivial named parameter)
- // NOTE: When not expecting a named param, destructuring patterns are not allowed
- if( expect_named
- || LOOK_AHEAD(lex) == TOK_UNDERSCORE
- || LOOK_AHEAD(lex) == TOK_RWORD_MUT
- || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON)
- )
- {
- // Function args can't be refuted
- pat = Parse_Pattern(lex, false);
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- }
-
- TypeRef type = Parse_Type(lex);
-
-
- return ::std::make_pair( ::std::move(pat), ::std::move(type) );
-}
-
-/// Parse a function definition (after the 'fn <name>')
-AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_self, bool can_be_prototype, bool is_unsafe, bool is_const)
-{
- TRACE_FUNCTION;
- ProtoSpan ps = lex.start_span();
-
- Token tok;
-
- // Parameters
- AST::GenericParams params;
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- }
- else {
- PUTBACK(tok, lex);
- }
-
- AST::Function::Arglist args;
-
- GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
- GET_TOK(tok, lex);
-
- // Handle self
- if( tok.type() == TOK_AMP )
- {
- // By-reference method?
- // TODO: If a lifetime is seen (and not a prototype), it is definitely a self binding
-
- unsigned int ofs = 0;
- if( lex.lookahead(0) == TOK_LIFETIME )
- ofs ++;
-
- if( lex.lookahead(ofs) == TOK_RWORD_SELF || (lex.lookahead(ofs) == TOK_RWORD_MUT && lex.lookahead(ofs+1) == TOK_RWORD_SELF) )
- {
- auto ps = lex.start_span();
- ::std::string lifetime;
- if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
- lifetime = tok.str();
- GET_TOK(tok, lex);
- }
- auto ty_sp = lex.end_span(ps);
-
- if( tok.type() == TOK_RWORD_MUT )
- {
- GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, true, TypeRef(ty_sp, "Self", 0xFFFF))) );
- }
- else
- {
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, false, TypeRef(ty_sp, "Self", 0xFFFF))) );
- }
- DEBUG("TODO: UFCS / self lifetimes");
- if( allow_self == false )
- throw ParseError::Generic(lex, "Self binding not expected");
- //args.push_back( ::std::make_pair(
- // AST::Pattern(),
- // TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), )
- //) );
-
- // Prime tok for next step
- GET_TOK(tok, lex);
- }
- else
- {
- // Unbound method
- }
- }
- else if( tok.type() == TOK_RWORD_MUT )
- {
- if( LOOK_AHEAD(lex) == TOK_RWORD_SELF )
- {
- GET_TOK(tok, lex);
- if( allow_self == false )
- throw ParseError::Generic(lex, "Self binding not expected");
- TypeRef ty = TypeRef( lex.getPosition(), "Self", 0xFFFF );
- if( GET_TOK(tok, lex) == TOK_COLON ) {
- // Typed mut self
- ty = Parse_Type(lex);
- }
- else {
- PUTBACK(tok, lex);
- }
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
- GET_TOK(tok, lex);
- }
- }
- else if( tok.type() == TOK_RWORD_SELF )
- {
- // By-value method
- if( allow_self == false )
- throw ParseError::Generic(lex, "Self binding not expected");
- TypeRef ty = TypeRef( lex.getPosition(), "Self", 0xFFFF );
- if( GET_TOK(tok, lex) == TOK_COLON ) {
- // Typed mut self
- ty = Parse_Type(lex);
- }
- else {
- PUTBACK(tok, lex);
- }
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
- GET_TOK(tok, lex);
- }
- else
- {
- // Unbound method
- }
-
- bool is_variadic = false;
- if( tok.type() != TOK_PAREN_CLOSE )
- {
- // Comma after self
- if( args.size() )
- {
- CHECK_TOK(tok, TOK_COMMA);
- }
- else {
- PUTBACK(tok, lex);
- }
-
- // Argument list
- do {
- if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) {
- GET_TOK(tok, lex);
- break;
- }
- if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) {
- GET_TOK(tok, lex);
- is_variadic = true;
- GET_TOK(tok, lex);
- break;
- }
- args.push_back( Parse_Function_Arg(lex, !can_be_prototype) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- }
- else {
- // Eat 'tok', negative comparison
- }
-
- TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos()));
- if( GET_TOK(tok, lex) == TOK_THINARROW )
- {
- // Return type
- ret_type = Parse_Type(lex);
- }
- else
- {
- PUTBACK(tok, lex);
- }
-
- if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
- {
- Parse_WhereClause(lex, params);
- }
- else {
- PUTBACK(tok, lex);
- }
-
- return AST::Function(lex.end_span(ps), mv$(params), mv$(abi), is_unsafe, is_const, is_variadic, mv$(ret_type), mv$(args));
-}
-
-AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, bool allow_self, bool is_unsafe, bool is_const)
-{
- Token tok;
- auto ret = Parse_FunctionDef(lex, abi, allow_self, false, is_unsafe, is_const);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
- PUTBACK(tok, lex);
- ret.set_code( Parse_ExprBlock(lex) );
- return ret;
-}
-
-AST::TypeAlias Parse_TypeAlias(TokenStream& lex)
-{
- TRACE_FUNCTION;
-
- Token tok;
-
- // Params
- AST::GenericParams params;
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- GET_TOK(tok, lex);
- }
-
- if( tok.type() == TOK_RWORD_WHERE )
- {
- Parse_WhereClause(lex, params);
- GET_TOK(tok, lex);
- }
- 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) );
-}
-
-AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
-{
- TRACE_FUNCTION;
-
- Token tok;
-
- tok = lex.getToken();
- AST::GenericParams params;
- if( tok.type() == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
- {
- Parse_WhereClause(lex, params);
- tok = lex.getToken();
- }
- }
- if(tok.type() == TOK_PAREN_OPEN)
- {
- // Tuple structs
- ::std::vector<AST::TupleItem> refs;
- while(GET_TOK(tok, lex) != TOK_PAREN_CLOSE)
- {
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, item_attrs);
-
- bool is_pub = false;
- if(tok.type() == TOK_RWORD_PUB)
- is_pub = true;
- else
- PUTBACK(tok, lex);
-
- refs.push_back( AST::TupleItem( mv$(item_attrs), is_pub, Parse_Type(lex) ) );
- if( GET_TOK(tok, lex) != TOK_COMMA )
- break;
- }
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
-
- if(LOOK_AHEAD(lex) == TOK_RWORD_WHERE)
- {
- GET_TOK(tok, lex);
- Parse_WhereClause(lex, params);
- }
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- //if( refs.size() == 0 )
- // WARNING( , W000, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
- return AST::Struct(mv$(params), mv$(refs));
- }
- else if(tok.type() == TOK_SEMICOLON)
- {
- // Unit-like struct
- return AST::Struct(mv$(params), ::std::vector<AST::TupleItem>());
- }
- else if(tok.type() == TOK_BRACE_OPEN)
- {
- ::std::vector<AST::StructItem> items;
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
- {
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, item_attrs);
-
- bool is_pub = false;
- if(tok.type() == TOK_RWORD_PUB) {
- is_pub = true;
- GET_TOK(tok, lex);
- }
-
- CHECK_TOK(tok, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- TypeRef type = Parse_Type(lex);
-
- items.push_back( AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(type) ) );
- if(GET_TOK(tok, lex) == TOK_BRACE_CLOSE)
- break;
- CHECK_TOK(tok, TOK_COMMA);
- }
- //if( items.size() == 0 )
- // WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong");
- return AST::Struct(::std::move(params), ::std::move(items));
- }
- else
- {
- throw ParseError::Unexpected(lex, tok);
- }
-}
-
-AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
-{
- TRACE_FUNCTION;
-
- Token tok;
-
- AST::GenericParams params;
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- tok = lex.getToken();
- }
-
- // Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2"
- ::std::vector<Spanned<AST::Path> > supertraits;
- if(tok.type() == TOK_COLON)
- {
- do {
- if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
- // TODO: Need a better way of indiciating 'static than just an invalid path
- supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::Path() ) );
- }
- else {
- PUTBACK(tok, lex);
- supertraits.push_back( GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE)) );
- }
- } while( GET_TOK(tok, lex) == TOK_PLUS );
- }
-
- // TODO: Support "for Sized?"
- if(tok.type() == TOK_RWORD_WHERE)
- {
- //if( params.ty_params().size() == 0 )
- // throw ParseError::Generic("Where clause with no generic params");
- Parse_WhereClause(lex, params);
- tok = lex.getToken();
- }
-
-
- AST::Trait trait( mv$(params), mv$(supertraits) );
-
- CHECK_TOK(tok, TOK_BRACE_OPEN);
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
- {
-
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, item_attrs);
-
- auto ps = lex.start_span();
- if( tok.type() == TOK_MACRO ) {
- auto inv = Parse_MacroInvocation( ps, mv$(tok.str()), lex );
- // - Silently consume ';' after the macro
- if( GET_TOK(tok, lex) != TOK_SEMICOLON )
- PUTBACK(tok, lex);
-
- trait.items().push_back( AST::Named<AST::Item>("", AST::Item(mv$(inv)), false) );
- continue ;
- }
-
- bool is_specialisable = false;
- if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
- is_specialisable = true;
- GET_TOK(tok, lex);
- }
- // TODO: Mark specialisation
- (void)is_specialisable;
-
- bool fn_is_const = false;
- bool fn_is_unsafe = false;
- ::std::string abi = ABI_RUST;
- switch(tok.type())
- {
- case TOK_RWORD_STATIC: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
-
- ::AST::Expr val;
- if(GET_TOK(tok, lex) == TOK_EQUAL) {
- val = Parse_Expr(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_SEMICOLON);
-
- // TODO: Attributes on associated statics
- trait.add_static( mv$(name), ::AST::Static(AST::Static::STATIC, mv$(ty), val)/*, mv$(item_attrs)*/ );
- break; }
- case TOK_RWORD_CONST: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
-
- ::AST::Expr val;
- if(GET_TOK(tok, lex) == TOK_EQUAL) {
- val = Parse_Expr(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_SEMICOLON);
-
- // TODO: Attributes on associated constants
- trait.add_static( mv$(name), ::AST::Static(AST::Static::CONST, mv$(ty), val)/*, mv$(item_attrs)*/ );
- break; }
- // Associated type
- case TOK_RWORD_TYPE: {
- auto atype_params = ::AST::GenericParams { };
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- if( GET_TOK(tok, lex) == TOK_COLON )
- {
- // Bounded associated type
- Parse_TypeBound(lex, atype_params, TypeRef(lex.getPosition(), "Self", 0xFFFF));
- GET_TOK(tok, lex);
- }
- if( tok.type() == TOK_RWORD_WHERE ) {
- throw ParseError::Todo(lex, "Where clause on associated type");
- }
-
- TypeRef default_type = TypeRef( lex.getPosition() );
- if( tok.type() == TOK_EQUAL ) {
- default_type = Parse_Type(lex);
- GET_TOK(tok, lex);
- }
-
- CHECK_TOK(tok, TOK_SEMICOLON);
- trait.add_type( ::std::move(name), ::std::move(default_type) );
- trait.items().back().data.as_Type().params() = mv$(atype_params);
- break; }
-
- // Functions (possibly unsafe)
- // TODO: Const?
- case TOK_RWORD_UNSAFE:
- fn_is_unsafe = true;
- if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
- case TOK_RWORD_EXTERN:
- {
- abi = "C";
- if( GET_TOK(tok, lex) == TOK_STRING )
- abi = tok.str();
- else
- PUTBACK(tok, lex);
-
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_RWORD_FN);
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = mv$(tok.str());
- // Self allowed, prototype-form allowed (optional names and no code)
- auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const);
- if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
- {
- PUTBACK(tok, lex);
- fcn.set_code( Parse_ExprBlock(lex) );
- }
- else if( tok.type() == TOK_SEMICOLON )
- {
- // Accept it
- }
- else
- {
- throw ParseError::Unexpected(lex, tok);
- }
- // TODO: Store `item_attrs`
- trait.add_function( ::std::move(name), /*mv$(item_attrs),*/ ::std::move(fcn) );
- break; }
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- }
-
- return trait;
-}
-
-AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
-{
- TRACE_FUNCTION;
-
- Token tok;
-
- tok = lex.getToken();
- // Type params supporting "where"
- AST::GenericParams params;
- if( tok.type() == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
- {
- Parse_WhereClause(lex, params);
- tok = lex.getToken();
- }
- }
-
- // Body
- CHECK_TOK(tok, TOK_BRACE_OPEN);
- ::std::vector<AST::EnumVariant> variants;
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
- {
- auto sp = lex.start_span();
-
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, item_attrs);
-
- CHECK_TOK(tok, TOK_IDENT);
- ::std::string name = mv$(tok.str());
- if( GET_TOK(tok, lex) == TOK_PAREN_OPEN )
- {
- ::std::vector<TypeRef> types;
- // Get type list
- do
- {
- if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE)
- {
- GET_TOK(tok, lex);
- break;
- }
-
- AST::MetaItems field_attrs;
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
- {
- GET_TOK(tok, lex);
- field_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- 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::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) );
- }
- else if( tok.type() == TOK_BRACE_OPEN )
- {
- ::std::vector<::AST::StructItem> fields;
- do
- {
- if(LOOK_AHEAD(lex) == TOK_BRACE_CLOSE)
- {
- GET_TOK(tok, lex);
- break;
- }
-
- AST::MetaItems field_attrs;
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
- {
- GET_TOK(tok, lex);
- field_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
- fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) );
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
- GET_TOK(tok, lex);
-
- variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) );
- }
- else if( tok.type() == TOK_EQUAL )
- {
- auto node = Parse_Expr(lex);
- variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) );
- GET_TOK(tok, lex);
- }
- else
- {
- variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), ::AST::Expr()) );
- }
-
- if( tok.type() != TOK_COMMA )
- break;
- }
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
-
- return AST::Enum( mv$(params), mv$(variants) );
-}
-
-::AST::Union Parse_Union(TokenStream& lex, AST::MetaItems& meta_items)
-{
- Token tok;
-
- TRACE_FUNCTION;
-
- AST::GenericParams params;
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
- {
- Parse_WhereClause(lex, params);
- tok = lex.getToken();
- }
- }
-
- ::std::vector< ::AST::StructItem> variants;
-
- CHECK_TOK(tok, TOK_BRACE_OPEN);
- do {
- if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) {
- GET_TOK(tok, lex);
- break ;
- }
-
- AST::MetaItems item_attrs;
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
- {
- GET_TOK(tok, lex);
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
- SET_ATTRS(lex, item_attrs);
-
- bool is_pub = false;
- if( LOOK_AHEAD(lex) == TOK_RWORD_PUB ) {
- is_pub = true;
- GET_TOK(tok, lex);
- }
-
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
-
- auto ty = Parse_Type(lex);
-
- variants.push_back( ::AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(ty) ) );
-
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- CHECK_TOK(tok, TOK_BRACE_CLOSE);
-
- return ::AST::Union( mv$(params), mv$(variants) );
-}
-
-/// Parse a meta-item declaration (either #![ or #[)
-AST::MetaItem Parse_MetaItem(TokenStream& lex)
-{
- TRACE_FUNCTION;
- Token tok;
- GET_TOK(tok, lex);
-
- if( tok.type() == TOK_INTERPOLATED_META ) {
- return mv$(tok.frag_meta());
- }
-
- CHECK_TOK(tok, TOK_IDENT);
- ::std::string name = mv$(tok.str());
- switch(GET_TOK(tok, lex))
- {
- case TOK_EQUAL:
- GET_CHECK_TOK(tok, lex, TOK_STRING);
- return AST::MetaItem(name, tok.str());
- case TOK_PAREN_OPEN: {
- ::std::vector<AST::MetaItem> items;
- do {
- if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE) {
- GET_TOK(tok, lex);
- break;
- }
- items.push_back(Parse_MetaItem(lex));
- } while(GET_TOK(tok, lex) == TOK_COMMA);
- CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return AST::MetaItem(name, mv$(items)); }
- default:
- PUTBACK(tok, lex);
- return AST::MetaItem(name);
- }
-}
-
-::AST::Item Parse_Impl(TokenStream& lex, AST::MetaItems attrs, bool is_unsafe=false)
-{
- TRACE_FUNCTION;
- Token tok;
- auto ps = lex.start_span();
-
- AST::GenericParams params;
- // 1. (optional) type parameters
- if( GET_TOK(tok, lex) == TOK_LT )
- {
- params = Parse_GenericParams(lex);
- GET_CHECK_TOK(tok, lex, TOK_GT);
- }
- else {
- PUTBACK(tok, lex);
- }
- // 2. Either a trait name (with type params), or the type to impl
-
- Spanned<AST::Path> trait_path;
-
- // - Handle negative impls specially, which must be a trait
- // "impl !Trait for Type {}"
- if( GET_TOK(tok, lex) == TOK_EXCLAM )
- {
- trait_path = GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE));
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FOR);
- auto impl_type = Parse_Type(lex, true);
-
- if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
- {
- Parse_WhereClause(lex, params);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_BRACE_OPEN);
- // negative impls can't have any content
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
-
- return ::AST::Item::make_NegImpl( AST::ImplDef(lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
- }
-
- // - Don't care which at this stage
- PUTBACK(tok, lex);
-
- auto impl_type = Parse_Type(lex, true);
-
- if( GET_TOK(tok, lex) == TOK_RWORD_FOR )
- {
- // Trickery! All traits parse as valid types, so this works.
- if( !impl_type.is_path() )
- throw ParseError::Generic(lex, "Trait was not a path");
- trait_path = Spanned< AST::Path> {
- impl_type.span(),
- mv$(impl_type.path())
- };
- // Implementing a trait for another type, get the target type
- if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT )
- {
- // Default impl
- impl_type = TypeRef(TypeRef::TagInvalid(), lex.getPosition());
- }
- else
- {
- PUTBACK(tok, lex);
- impl_type = Parse_Type(lex, true);
- }
- }
- else {
- PUTBACK(tok, lex);
- }
-
- // Where clause
- if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
- {
- Parse_WhereClause(lex, params);
- }
- else {
- PUTBACK(tok, lex);
- }
- GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
-
- while( LOOK_AHEAD(lex) == TOK_CATTR_OPEN )
- {
- GET_TOK(tok, lex);
- attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- AST::Impl impl( AST::ImplDef( lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
-
- // A sequence of method implementations
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
- {
- auto ps = lex.start_span();
- if( tok.type() == TOK_MACRO )
- {
- impl.add_macro_invocation( Parse_MacroInvocation( ps, mv$(tok.str()), lex ) );
- // - Silently consume ';' after the macro
- if( GET_TOK(tok, lex) != TOK_SEMICOLON )
- PUTBACK(tok, lex);
- }
- else
- {
- PUTBACK(tok, lex);
- Parse_Impl_Item(lex, impl);
- }
- }
-
- return ::AST::Item::make_Impl( mv$(impl) );
-}
-
-void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
-{
- TRACE_FUNCTION;
- Token tok;
-
- GET_TOK(tok, lex);
-
- AST::MetaItems item_attrs;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- item_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, item_attrs);
-
- auto ps = lex.start_span();
-
- bool is_public = false;
- if(tok.type() == TOK_RWORD_PUB) {
- is_public = true;
- GET_TOK(tok, lex);
- }
-
- bool is_specialisable = false;
- if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
- is_specialisable = true;
- GET_TOK(tok, lex);
- }
-
- ::std::string abi = ABI_RUST;
- bool fn_is_unsafe = false;
- bool fn_is_const = false;
- switch(tok.type())
- {
- case TOK_RWORD_TYPE: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- impl.add_type(is_public, is_specialisable, name, Parse_Type(lex));
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break; }
- case TOK_RWORD_UNSAFE:
- fn_is_unsafe = true;
- GET_TOK(tok, lex);
- if( tok.type() == TOK_RWORD_CONST )
- case TOK_RWORD_CONST:
- {
- GET_TOK(tok, lex);
- if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE && !fn_is_unsafe )
- {
- CHECK_TOK(tok, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- auto val = Parse_Expr(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
-
- auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val));
- // TODO: Attributes on associated constants
- impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) /*, mv$(item_attrs)*/ );
- break ;
- }
- else if( tok.type() == TOK_RWORD_UNSAFE )
- {
- fn_is_unsafe = true;
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
- }
- fn_is_const = true;
- }
- if( tok.type() == TOK_RWORD_EXTERN )
- // FALL
- case TOK_RWORD_EXTERN:
- {
- abi = "C";
- if( GET_TOK(tok, lex) == TOK_STRING )
- abi = tok.str();
- else
- PUTBACK(tok, lex);
-
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_RWORD_FN);
- // FALL
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- // TODO: Hygine on function names? - Not in impl blocks?
- ::std::string name = mv$(tok.str());
- DEBUG("Function " << name);
- // - Self allowed, can't be prototype-form
- auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const);
- impl.add_function(is_public, is_specialisable, mv$(name), mv$(fcn));
- break; }
-
- default:
- throw ParseError::Unexpected(lex, tok);
- }
-
- impl.items().back().data->span = lex.end_span(ps);
- impl.items().back().data->attrs = mv$(item_attrs); // Empty for functions
-}
-
-AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::MetaItems& block_attrs)
-{
- TRACE_FUNCTION;
- Token tok;
-
- while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
- {
- block_attrs.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
- PUTBACK(tok, lex);
-
- AST::ExternBlock rv { abi };
-
- while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
- {
- AST::MetaItems meta_items;
- while( tok.type() == TOK_ATTR_OPEN )
- {
- meta_items.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- GET_TOK(tok, lex);
- }
- SET_ATTRS(lex, meta_items);
-
- auto ps = lex.start_span();
-
- bool is_public = false;
- if( tok.type() == TOK_RWORD_PUB ) {
- is_public = true;
- GET_TOK(tok, lex);
- }
- switch(tok.type())
- {
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- // parse function as prototype
- // - no self, is prototype, is unsafe and not const
- auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, true,false) );
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
-
- i.attrs = mv$(meta_items);
- i.span = lex.end_span(ps);
-
- rv.add_item( AST::Named<AST::Item> { mv$(name), mv$(i), is_public } );
- break; }
- case TOK_RWORD_STATIC: {
- bool is_mut = false;
- if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
- is_mut = true;
- else
- PUTBACK(tok, lex);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto type = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
-
- auto i = ::AST::Item(::AST::Static( (is_mut ? ::AST::Static::MUT : ::AST::Static::STATIC), mv$(type), ::AST::Expr() ));
- i.attrs = mv$(meta_items);
- i.span = lex.end_span(ps);
- rv.add_item( AST::Named<AST::Item> { mv$(name), mv$(i), is_public } );
- break; }
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_STATIC});
- }
- }
-
- return rv;
-}
-
-void Parse_Use_Wildcard(Span sp, AST::Path base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
-{
- fcn( AST::UseStmt(mv$(sp), mv$(base_path)), "" ); // HACK! Empty path indicates wilcard import
-}
-void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
-{
- TRACE_FUNCTION;
-
- Token tok;
- do {
- AST::Path path;
- ::std::string name;
- if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) {
- path = ::AST::Path(base_path);
- name = base_path[base_path.size()-1].name();
- }
- else if( tok.type() == TOK_BRACE_CLOSE ) {
- break ;
- }
- else {
- CHECK_TOK(tok, TOK_IDENT);
- path = base_path + AST::PathNode(tok.str(), {});
- name = mv$(tok.str());
- }
-
- if( GET_TOK(tok, lex) == TOK_RWORD_AS ) {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
- }
- fcn(AST::UseStmt(lex.end_span(ps), mv$(path)), mv$(name));
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- PUTBACK(tok, lex);
-}
-
-void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
-{
- TRACE_FUNCTION;
-
- Token tok;
- AST::Path path = AST::Path("", {});
- ::std::vector<AST::PathNode> nodes;
- ProtoSpan span_start = lex.start_span();
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_RWORD_SELF:
- path = AST::Path( AST::Path::TagSelf(), {} ); // relative path
- break;
- case TOK_RWORD_SUPER: {
- unsigned int count = 1;
- while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON && lex.lookahead(1) == TOK_RWORD_SUPER ) {
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- GET_CHECK_TOK(tok, lex, TOK_RWORD_SUPER);
- count += 1;
- }
- path = AST::Path( AST::Path::TagSuper(), count, {} );
- break; }
- case TOK_IDENT:
- path.append( AST::PathNode(mv$(tok.str()), {}) );
- break;
- // Leading :: is allowed and ignored for the $crate feature
- case TOK_DOUBLE_COLON:
- // Absolute path
- // HACK! mrustc emits $crate as `::"crate-name"`
- if( LOOK_AHEAD(lex) == TOK_STRING )
- {
- GET_CHECK_TOK(tok, lex, TOK_STRING);
- path = ::AST::Path(tok.str(), {});
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- }
- else {
- PUTBACK(tok, lex);
- }
- break;
- case TOK_BRACE_OPEN:
- Parse_Use_Set(lex, span_start, path, fcn);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- return;
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
- {
- if( GET_TOK(tok, lex) == TOK_IDENT )
- {
- path.append( AST::PathNode( mv$(tok.str()), {}) );
- }
- else
- {
- //path.set_span( lex.end_span(span_start) );
- switch( tok.type() )
- {
- case TOK_BRACE_OPEN:
- Parse_Use_Set(lex, span_start, mv$(path), fcn);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- break ;
- case TOK_STAR:
- Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn );
- break ;
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- // early return - This branch is either the end of the use statement, or a syntax error
- return ;
- }
- }
- //path.set_span( lex.end_span(span_start) );
-
- ::std::string name;
- // This should only be allowed if the last token was an ident
- // - Above checks ensure this
- if( tok.type() == TOK_RWORD_AS )
- {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = mv$(tok.str());
- }
- else
- {
- PUTBACK(tok, lex);
- assert(path.nodes().size() > 0);
- name = path.nodes().back().name();
- }
-
- fcn( AST::UseStmt(lex.end_span(span_start), mv$(path)), name);
-}
-
-
-::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, ::std::string name, TokenStream& lex)
-{
- Token tok;
- ::std::string ident;
- if( GET_TOK(tok, lex) == TOK_IDENT ) {
- ident = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
- }
- DEBUG("name=" << name << ", ident=" << ident);
- TokenTree tt = Parse_TT(lex, true);
- return ::AST::MacroInvocation( lex.end_span(span_start), mv$(name), mv$(ident), mv$(tt));
-}
-
-::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::MetaItems meta_items)
-{
- TRACE_FUNCTION_F("mod_path="<<mod_path<<", meta_items="<<meta_items);
- Token tok;
-
- while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN /* || LOOKAHEAD2(lex, TOK_HASH, TOK_SQUARE_OPEN) */ )
- {
- // Attributes!
- GET_CHECK_TOK(tok, lex, TOK_ATTR_OPEN);
- meta_items.push_back( Parse_MetaItem(lex) );
- GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
- }
-
- if( LOOK_AHEAD(lex) == TOK_INTERPOLATED_ITEM ) {
- GET_TOK(tok, lex);
- auto rv = tok.take_frag_item();
- // Transfer new attributes onto the item
- for(auto& mi : meta_items.m_items)
- rv.data.attrs.m_items.push_back( mv$(mi) );
- return rv;
- }
-
- auto ps = lex.start_span();
-
- ::std::string item_name;
- ::AST::Item item_data;
-
- if( LOOK_AHEAD(lex) == TOK_MACRO ) {
- GET_TOK(tok, lex);
-
- ::std::string name = mv$(tok.str());
- bool is_braced = (LOOK_AHEAD(lex) == TOK_BRACE_OPEN || LOOKAHEAD2(lex, TOK_IDENT, TOK_BRACE_OPEN));
- item_data = ::AST::Item( Parse_MacroInvocation( ps, mv$(name), lex ) );
-
- if( !is_braced ) {
- // - Consume the ';' after the macro
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- }
-
- item_data.attrs = mv$(meta_items);
- item_data.span = lex.end_span(ps);
-
- return ::AST::Named< ::AST::Item> { "", mv$(item_data), false };
- }
-
- bool is_public = false;
- if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) {
- is_public = true;
- }
- else {
- PUTBACK(tok, lex);
- }
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_RWORD_USE:
- // NOTE: The only problem here is with things like `use foo::{a, b, c}` - all others are a single statement.
- // - These are caught by the condition in the closure
- Parse_Use(lex, [&](AST::UseStmt p, std::string s) {
- DEBUG(mod_path << " - use " << p << " as '" << s << "'");
- if( !item_data.is_None() )
- TODO(lex.getPosition(), "Encode multi-item use statements as a single Item");
- item_data = ::AST::Item(mv$(p));
- item_name = mv$(s);
- });
- assert( !item_data.is_None() );
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break;
-
- case TOK_RWORD_EXTERN:
- switch( GET_TOK(tok, lex) )
- {
- // `extern "<ABI>" fn ...`
- // `extern "<ABI>" { ...`
- case TOK_STRING: {
- ::std::string abi = tok.str();
- switch(GET_TOK(tok, lex))
- {
- // `extern "<ABI>" fn ...`
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, false,false) );
- break; }
- // `extern "ABI" {`
- case TOK_BRACE_OPEN:
- item_name = "";
- item_data = ::AST::Item( Parse_ExternBlock(lex, mv$(abi), meta_items) );
- break;
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_BRACE_OPEN});
- }
- break; }
- // `extern fn ...`
- case TOK_RWORD_FN:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, "C", false, false,false) );
- break;
-
- // NOTE: `extern { ...` is handled in caller
- case TOK_BRACE_OPEN:
- item_name = "";
- item_data = ::AST::Item( Parse_ExternBlock(lex, "C", meta_items) );
- break;
-
- // `extern crate "crate-name" as crate_name;`
- // `extern crate crate_name;`
- // `extern crate crate_name as other_name;`
- case TOK_RWORD_CRATE:
- switch( GET_TOK(tok, lex) )
- {
- // `extern crate "crate-name" as crate_name;`
- // NOTE: rustc doesn't allow this, keep in mrustc for for reparse support
- case TOK_STRING:
- item_data = ::AST::Item::make_Crate({ tok.str() });
- GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- break;
- // `extern crate crate_name;`
- // `extern crate crate_name as other_name;`
- case TOK_IDENT:
- item_name = mv$(tok.str());
- if(GET_TOK(tok, lex) == TOK_RWORD_AS) {
- item_data = ::AST::Item::make_Crate({ mv$(item_name) });
-
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
- item_data = ::AST::Item::make_Crate({ item_name });
- }
- break;
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT});
- }
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- break;
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_RWORD_FN, TOK_BRACE_OPEN, TOK_RWORD_CRATE});
- }
- break;
-
- // `const NAME`
- // `const [unsafe] fn`
- case TOK_RWORD_CONST:
- switch( GET_TOK(tok, lex) )
- {
- case TOK_IDENT: {
- item_name = mv$(tok.str());
-
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- TypeRef type = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- AST::Expr val = Parse_Expr(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- item_data = ::AST::Item( ::AST::Static(AST::Static::CONST, mv$(type), mv$(val)) );
- break; }
- case TOK_RWORD_UNSAFE:
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,true/*unsafe,const*/) );
- break;
- case TOK_RWORD_FN:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- // - self not allowed, not prototype
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,true/*unsafe,const*/) );
- break;
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_RWORD_FN});
- }
- break;
- // `static NAME`
- // `static mut NAME`
- case TOK_RWORD_STATIC: {
- bool is_mut = false;
- if(GET_TOK(tok, lex) == TOK_RWORD_MUT) {
- is_mut = true;
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_IDENT);
- item_name = mv$(tok.str());
-
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- TypeRef type = Parse_Type(lex);
-
- GET_CHECK_TOK(tok, lex, TOK_EQUAL);
-
- AST::Expr val = Parse_Expr(lex);
-
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- item_data = ::AST::Item( ::AST::Static( (is_mut ? AST::Static::MUT : AST::Static::STATIC), mv$(type), mv$(val)) );
- break; }
-
- // `unsafe fn`
- // `unsafe trait`
- // `unsafe impl`
- case TOK_RWORD_UNSAFE:
- meta_items.push_back( AST::MetaItem("#UNSAFE") );
- switch(GET_TOK(tok, lex))
- {
- // `unsafe extern fn`
- case TOK_RWORD_EXTERN: {
- ::std::string abi = "C";
- if(GET_TOK(tok, lex) == TOK_STRING) {
- abi = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
- }
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, true,false/*unsafe,const*/) );
- break; }
- // `unsafe fn`
- case TOK_RWORD_FN:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- // - self not allowed, not prototype
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,false/*unsafe,const*/) );
- break;
- // `unsafe trait`
- case TOK_RWORD_TRAIT:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- // TODO: Mark as unsafe
- meta_items.push_back( AST::MetaItem("#UNSAFE") );
- item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
- break;
- // `unsafe impl`
- case TOK_RWORD_IMPL:
- return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items), true), false };
- default:
- throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL});
- }
- break;
- // `fn`
- case TOK_RWORD_FN:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- // - self not allowed, not prototype
- item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,false/*unsafe,const*/) );
- break;
- // `type`
- case TOK_RWORD_TYPE:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_TypeAlias(lex) );
- break;
- // `struct`
- case TOK_RWORD_STRUCT:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_Struct(lex, meta_items) );
- break;
- // `enum`
- case TOK_RWORD_ENUM:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_EnumDef(lex, meta_items) );
- break;
- // Contextual keywords
- case TOK_IDENT:
- if( tok.str() == "union" ) {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_Union(lex, meta_items) );
- }
- else {
- throw ParseError::Unexpected(lex, tok);
- }
- break;
- // `impl`
- case TOK_RWORD_IMPL:
- return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items)), false };
- // `trait`
- case TOK_RWORD_TRAIT:
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- item_name = mv$(tok.str());
- item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
- break;
-
- case TOK_RWORD_MOD: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- DEBUG("Sub module '" << name << "'");
- AST::Module submod( mod_path + name );
-
- // Rules for external files (/ path handling):
- // - IF using stdin (path='-') - Disallow and propagate '-' as path
- // - IF a #[path] attribute was passed, allow
- // - IF in crate root or mod.rs, allow (input flag)
- // - else, disallow and set flag
- ::std::string path_attr = (meta_items.has("path") ? meta_items.get("path")->string() : "");
-
- //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON);
-
- ::std::string sub_path;
- bool sub_file_controls_dir = true;
- if( mod_fileinfo.path == "-" ) {
- if( path_attr.size() ) {
- ERROR(lex.getPosition(), E0000, "Cannot load module from file when reading stdin");
- }
- sub_path = "-";
- }
- else if( path_attr.size() > 0 )
- {
- sub_path = dirname(mod_fileinfo.path) + path_attr;
- }
- else if( mod_fileinfo.controls_dir )
- {
- sub_path = dirname(mod_fileinfo.path) + name;
- }
- else
- {
- sub_path = mod_fileinfo.path;
- sub_file_controls_dir = false;
- }
- DEBUG("Mod '" << name << "', sub_path = " << sub_path);
-
- submod.m_file_info.path = sub_path;
- submod.m_file_info.controls_dir = sub_file_controls_dir;
-
- // Check #[cfg] and don't load if it fails
- struct H {
- static 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;
- }
- };
-
- switch( GET_TOK(tok, lex) )
- {
- case TOK_BRACE_OPEN:
- submod.m_file_info.path = sub_path + "/";
- Parse_ModRoot(lex, submod, meta_items);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- break;
- case TOK_SEMICOLON:
- if( sub_path == "-" ) {
- ERROR(lex.getPosition(), E0000, "Cannot load module from file when reading stdin");
- }
- else if( path_attr.size() == 0 && ! mod_fileinfo.controls_dir )
- {
- ERROR(lex.getPosition(), E0000, "Can't load from files outside of mod.rs or crate root");
- }
- else if( !H::check_item_cfg(meta_items) ) {
- // Ignore - emit Item::None
- item_name = mv$(name);
- item_data = ::AST::Item( );
- break ;
- }
- else
- {
- ::std::string newpath_dir = sub_path + "/";
- ::std::string newpath_file = path_attr.size() > 0 ? sub_path : sub_path + ".rs";
- DEBUG("newpath_dir = '" << newpath_dir << "', newpath_file = '" << newpath_file << "'");
- ::std::ifstream ifs_dir (newpath_dir + "mod.rs");
- ::std::ifstream ifs_file(newpath_file);
- if( ifs_dir.is_open() && ifs_file.is_open() )
- {
- // Collision
- ERROR(lex.getPosition(), E0000, "Both modname.rs and modname/mod.rs exist");
- }
- else if( ifs_dir.is_open() )
- {
- // Load from dir
- submod.m_file_info.path = newpath_dir + "mod.rs";
- }
- else if( ifs_file.is_open() )
- {
- submod.m_file_info.path = newpath_file;
- }
- else
- {
- // Can't find file
- ERROR(lex.getPosition(), E0000, "Can't find file for '" << name << "' in '" << mod_fileinfo.path << "'");
- }
- DEBUG("- path = " << submod.m_file_info.path);
- Lexer sub_lex(submod.m_file_info.path);
- Parse_ModRoot(sub_lex, submod, meta_items);
- GET_CHECK_TOK(tok, sub_lex, TOK_EOF);
- }
- break;
- default:
- throw ParseError::Generic("Expected { or ; after module name");
- }
- item_name = mv$(name);
- item_data = ::AST::Item( mv$(submod) );
- break; }
-
- default:
- throw ParseError::Unexpected(lex, tok);
- }
-
- item_data.attrs = mv$(meta_items);
- item_data.span = lex.end_span(ps);
-
- return ::AST::Named< ::AST::Item> { mv$(item_name), mv$(item_data), is_public };
-}
-
-void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items)
-{
- SET_MODULE(lex, mod);
- lex.parse_state().parent_attrs = &meta_items;
-
- //TRACE_FUNCTION;
- Token tok;
-
- // `use ...`
- if( LOOK_AHEAD(lex) == TOK_RWORD_USE || (lex.lookahead(0) == TOK_RWORD_PUB && lex.lookahead(1) == TOK_RWORD_USE) )
- {
- bool is_public = false;
- if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) {
- is_public = true;
- GET_TOK(tok, lex);
- }
-
- Parse_Use(lex, [&mod,is_public,&meta_items](AST::UseStmt p, std::string s) {
- DEBUG(mod.path() << " - use " << p << " as '" << s << "'");
- mod.add_alias(is_public, mv$(p), s, meta_items.clone());
- });
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- }
- else
- {
- mod.add_item( Parse_Mod_Item_S(lex, mod.m_file_info, mod.path(), mv$(meta_items)) );
- }
-}
-
-void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod)
-{
- Token tok;
-
- for(;;)
- {
- // Check 1 - End of module (either via a closing brace, or EOF)
- switch(GET_TOK(tok, lex))
- {
- case TOK_BRACE_CLOSE:
- case TOK_EOF:
- PUTBACK(tok, lex);
- return;
- default:
- PUTBACK(tok, lex);
- break;
- }
-
- // Attributes on the following item
- AST::MetaItems 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);
- }
- PUTBACK(tok, lex);
- DEBUG("meta_items = " << meta_items);
-
- Parse_Mod_Item(lex, mod, mv$(meta_items));
- }
-}
-
-void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs)
-{
- TRACE_FUNCTION;
-
- Token tok;
-
- // 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);
-
- mod_attrs.push_back( mv$(item) );
- }
- PUTBACK(tok, lex);
-
- Parse_ModRoot_Items(lex, mod);
-}
-
-AST::Crate Parse_Crate(::std::string mainfile)
-{
- Token tok;
-
- Lexer lex(mainfile);
-
- size_t p = mainfile.find_last_of('/');
- ::std::string mainpath = (p != ::std::string::npos ? ::std::string(mainfile.begin(), mainfile.begin()+p+1) : "./");
-
- AST::Crate crate;
-
- crate.root_module().m_file_info.path = mainpath;
- crate.root_module().m_file_info.controls_dir = true;
-
- Parse_ModRoot(lex, crate.root_module(), crate.m_attrs);
-
- return crate;
-}
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/root.cpp
+ * - Parsing at the module level (highest-level parsing)
+ *
+ * Entrypoint:
+ * - Parse_Crate : Handles crate attrbutes, and passes on to Parse_ModRoot
+ * - Parse_ModRoot
+ */
+#include <ast/ast.hpp>
+#include <ast/crate.hpp>
+#include "parseerror.hpp"
+#include "common.hpp"
+#include <cassert>
+#include <hir/hir.hpp> // ABI_RUST - TODO: Move elsewhere?
+#include <expand/cfg.hpp> // check_cfg - for `mod nonexistant;`
+#include <fstream> // Used by directory path
+#include "lex.hpp" // New file lexer
+
+template<typename T>
+Spanned<T> get_spanned(TokenStream& lex, ::std::function<T()> f) {
+ auto ps = lex.start_span();
+ auto v = f();
+ return Spanned<T> {
+ lex.end_span(ps),
+ mv$(v)
+ };
+}
+#define GET_SPANNED(type, lex, val) get_spanned< type >(lex, [&](){ return val; })
+
+// Check the next two tokens
+#define LOOKAHEAD2(lex, tok1, tok2) ((lex).lookahead(0) == (tok1) && (lex).lookahead(1) == (tok2))
+
+::std::string dirname(::std::string input) {
+ while( input.size() > 0 && input.back() != '/' ) {
+ input.pop_back();
+ }
+ return input;
+}
+
+AST::MetaItem Parse_MetaItem(TokenStream& lex);
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs);
+
+::std::vector< ::std::string> Parse_HRB(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ ::std::vector< ::std::string> lifetimes;
+ GET_CHECK_TOK(tok, lex, TOK_LT);
+ do {
+ GET_TOK(tok, lex);
+
+ ::AST::MetaItems attrs;
+ while(tok.type() == TOK_ATTR_OPEN)
+ {
+ attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ (void)attrs; // TODO: Attributes on generic params
+
+ switch(tok.type())
+ {
+ case TOK_LIFETIME:
+ lifetimes.push_back(tok.str());
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME));
+ }
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_GT);
+ return lifetimes;
+}
+/// Parse type parameters in a definition
+void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, ::std::vector< ::std::string> lifetimes = {})
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ do
+ {
+ ::std::vector< ::std::string> hrls;
+ if(GET_TOK(tok, lex) == TOK_LIFETIME) {
+ ret.add_bound(AST::GenericBound::make_TypeLifetime( {
+ checked_type.clone(), tok.str()
+ } ));
+ }
+ else if( tok.type() == TOK_QMARK ) {
+ ret.add_bound(AST::GenericBound::make_MaybeTrait( {
+ checked_type.clone(), Parse_Path(lex, PATH_GENERIC_TYPE)
+ } ));
+ }
+ else {
+ if( tok.type() == TOK_RWORD_FOR )
+ {
+ hrls = Parse_HRB(lex);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ (void)hrls; // TODO: HRLs
+
+ ret.add_bound( AST::GenericBound::make_IsTrait({
+ checked_type.clone(), mv$(lifetimes), Parse_Path(lex, PATH_GENERIC_TYPE)
+ }) );
+ }
+ } while( GET_TOK(tok, lex) == TOK_PLUS );
+ PUTBACK(tok, lex);
+}
+
+/// Parse type parameters within '<' and '>' (definition)
+AST::GenericParams Parse_GenericParams(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ AST::GenericParams ret;
+ Token tok;
+ do {
+ if( GET_TOK(tok, lex) == TOK_GT ) {
+ break ;
+ }
+
+ ::AST::MetaItems attrs;
+ while(tok.type() == TOK_ATTR_OPEN)
+ {
+ attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ (void)attrs; // TODO: Attributes on generic params
+
+ if( tok.type() == TOK_IDENT )
+ {
+ // TODO: Hygine
+ ::std::string param_name = mv$(tok.str());
+ ret.add_ty_param( AST::TypeParam( param_name ) );
+
+ auto param_ty = TypeRef(lex.getPosition(), param_name);
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ {
+ Parse_TypeBound(lex, ret, mv$(param_ty));
+ GET_TOK(tok, lex);
+ }
+
+ if( tok.type() == TOK_EQUAL )
+ {
+ ret.ty_params().back().setDefault( Parse_Type(lex) );
+ GET_TOK(tok, lex);
+ }
+ }
+ else if( tok.type() == TOK_LIFETIME )
+ {
+ // TODO: Should lifetimes have hygine?
+ ::std::string param_name = tok.str();
+ ret.add_lft_param( param_name );
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ {
+ do {
+ GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
+ ret.add_bound(AST::GenericBound::make_Lifetime( {param_name, tok.str()} ));
+ } while( GET_TOK(tok, lex) == TOK_PLUS );
+ }
+ }
+ else
+ {
+ throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_LIFETIME});
+ }
+ } while( tok.type() == TOK_COMMA );
+ PUTBACK(tok, lex);
+ return ret;
+}
+
+
+/// Parse the contents of a 'where' clause
+void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ do {
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_BRACE_OPEN ) {
+ break;
+ }
+
+ if( tok.type() == TOK_LIFETIME )
+ {
+ auto lhs = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ do {
+ GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
+ auto rhs = mv$(tok.str());
+ params.add_bound( AST::GenericBound::make_Lifetime({lhs, rhs}) );
+ } while( GET_TOK(tok, lex) == TOK_PLUS );
+ PUTBACK(tok, lex);
+ }
+ // Higher-ranked types/lifetimes
+ else if( tok.type() == TOK_RWORD_FOR )
+ {
+ ::std::vector< ::std::string> lifetimes = Parse_HRB(lex);
+
+ TypeRef type = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ Parse_TypeBound(lex,params, mv$(type), mv$(lifetimes));
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ TypeRef type = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ Parse_TypeBound(lex, params, mv$(type));
+ }
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ PUTBACK(tok, lex);
+}
+
+// Parse a single function argument
+::std::pair< AST::Pattern, TypeRef> Parse_Function_Arg(TokenStream& lex, bool expect_named)
+{
+ TRACE_FUNCTION_F("expect_named = " << expect_named);
+ Token tok;
+
+ AST::Pattern pat;
+
+ // If any of the following
+ // - Expecting a named parameter (i.e. defining a function in root or impl)
+ // - Next token is an underscore (only valid as a pattern here)
+ // - Next token is 'mut' (a mutable parameter slot)
+ // - Next two are <ident> ':' (a trivial named parameter)
+ // NOTE: When not expecting a named param, destructuring patterns are not allowed
+ if( expect_named
+ || LOOK_AHEAD(lex) == TOK_UNDERSCORE
+ || LOOK_AHEAD(lex) == TOK_RWORD_MUT
+ || (LOOK_AHEAD(lex) == TOK_IDENT && lex.lookahead(1) == TOK_COLON)
+ )
+ {
+ // Function args can't be refuted
+ pat = Parse_Pattern(lex, false);
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ }
+
+ TypeRef type = Parse_Type(lex);
+
+
+ return ::std::make_pair( ::std::move(pat), ::std::move(type) );
+}
+
+/// Parse a function definition (after the 'fn <name>')
+AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_self, bool can_be_prototype, bool is_unsafe, bool is_const)
+{
+ TRACE_FUNCTION;
+ ProtoSpan ps = lex.start_span();
+
+ Token tok;
+
+ // Parameters
+ AST::GenericParams params;
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ AST::Function::Arglist args;
+
+ GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN);
+ GET_TOK(tok, lex);
+
+ // Handle self
+ if( tok.type() == TOK_AMP )
+ {
+ // By-reference method?
+ // TODO: If a lifetime is seen (and not a prototype), it is definitely a self binding
+
+ unsigned int ofs = 0;
+ if( lex.lookahead(0) == TOK_LIFETIME )
+ ofs ++;
+
+ if( lex.lookahead(ofs) == TOK_RWORD_SELF || (lex.lookahead(ofs) == TOK_RWORD_MUT && lex.lookahead(ofs+1) == TOK_RWORD_SELF) )
+ {
+ auto ps = lex.start_span();
+ ::std::string lifetime;
+ if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
+ lifetime = tok.str();
+ GET_TOK(tok, lex);
+ }
+ auto ty_sp = lex.end_span(ps);
+
+ if( tok.type() == TOK_RWORD_MUT )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, true, TypeRef(ty_sp, "Self", 0xFFFF))) );
+ }
+ else
+ {
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, false, TypeRef(ty_sp, "Self", 0xFFFF))) );
+ }
+ DEBUG("TODO: UFCS / self lifetimes");
+ if( allow_self == false )
+ throw ParseError::Generic(lex, "Self binding not expected");
+ //args.push_back( ::std::make_pair(
+ // AST::Pattern(),
+ // TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), )
+ //) );
+
+ // Prime tok for next step
+ GET_TOK(tok, lex);
+ }
+ else
+ {
+ // Unbound method
+ }
+ }
+ else if( tok.type() == TOK_RWORD_MUT )
+ {
+ if( LOOK_AHEAD(lex) == TOK_RWORD_SELF )
+ {
+ GET_TOK(tok, lex);
+ if( allow_self == false )
+ throw ParseError::Generic(lex, "Self binding not expected");
+ TypeRef ty = TypeRef( lex.getPosition(), "Self", 0xFFFF );
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ // Typed mut self
+ ty = Parse_Type(lex);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
+ GET_TOK(tok, lex);
+ }
+ }
+ else if( tok.type() == TOK_RWORD_SELF )
+ {
+ // By-value method
+ if( allow_self == false )
+ throw ParseError::Generic(lex, "Self binding not expected");
+ TypeRef ty = TypeRef( lex.getPosition(), "Self", 0xFFFF );
+ if( GET_TOK(tok, lex) == TOK_COLON ) {
+ // Typed mut self
+ ty = Parse_Type(lex);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
+ GET_TOK(tok, lex);
+ }
+ else
+ {
+ // Unbound method
+ }
+
+ bool is_variadic = false;
+ if( tok.type() != TOK_PAREN_CLOSE )
+ {
+ // Comma after self
+ if( args.size() )
+ {
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ // Argument list
+ do {
+ if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE ) {
+ GET_TOK(tok, lex);
+ break;
+ }
+ if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) {
+ GET_TOK(tok, lex);
+ is_variadic = true;
+ GET_TOK(tok, lex);
+ break;
+ }
+ args.push_back( Parse_Function_Arg(lex, !can_be_prototype) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ }
+ else {
+ // Eat 'tok', negative comparison
+ }
+
+ TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos()));
+ if( GET_TOK(tok, lex) == TOK_THINARROW )
+ {
+ // Return type
+ ret_type = Parse_Type(lex);
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ }
+
+ if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
+ {
+ Parse_WhereClause(lex, params);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ return AST::Function(lex.end_span(ps), mv$(params), mv$(abi), is_unsafe, is_const, is_variadic, mv$(ret_type), mv$(args));
+}
+
+AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, bool allow_self, bool is_unsafe, bool is_const)
+{
+ Token tok;
+ auto ret = Parse_FunctionDef(lex, abi, allow_self, false, is_unsafe, is_const);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+ PUTBACK(tok, lex);
+ ret.set_code( Parse_ExprBlock(lex) );
+ return ret;
+}
+
+AST::TypeAlias Parse_TypeAlias(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ // Params
+ AST::GenericParams params;
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ GET_TOK(tok, lex);
+ }
+
+ if( tok.type() == TOK_RWORD_WHERE )
+ {
+ Parse_WhereClause(lex, params);
+ GET_TOK(tok, lex);
+ }
+ 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) );
+}
+
+AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ tok = lex.getToken();
+ AST::GenericParams params;
+ if( tok.type() == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
+ {
+ Parse_WhereClause(lex, params);
+ tok = lex.getToken();
+ }
+ }
+ if(tok.type() == TOK_PAREN_OPEN)
+ {
+ // Tuple structs
+ ::std::vector<AST::TupleItem> refs;
+ while(GET_TOK(tok, lex) != TOK_PAREN_CLOSE)
+ {
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ bool is_pub = false;
+ if(tok.type() == TOK_RWORD_PUB)
+ is_pub = true;
+ else
+ PUTBACK(tok, lex);
+
+ refs.push_back( AST::TupleItem( mv$(item_attrs), is_pub, Parse_Type(lex) ) );
+ if( GET_TOK(tok, lex) != TOK_COMMA )
+ break;
+ }
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+
+ if(LOOK_AHEAD(lex) == TOK_RWORD_WHERE)
+ {
+ GET_TOK(tok, lex);
+ Parse_WhereClause(lex, params);
+ }
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ //if( refs.size() == 0 )
+ // WARNING( , W000, "Use 'struct Name;' instead of 'struct Name();' ... ning-nong");
+ return AST::Struct(mv$(params), mv$(refs));
+ }
+ else if(tok.type() == TOK_SEMICOLON)
+ {
+ // Unit-like struct
+ return AST::Struct(mv$(params), ::std::vector<AST::TupleItem>());
+ }
+ else if(tok.type() == TOK_BRACE_OPEN)
+ {
+ ::std::vector<AST::StructItem> items;
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ bool is_pub = false;
+ if(tok.type() == TOK_RWORD_PUB) {
+ is_pub = true;
+ GET_TOK(tok, lex);
+ }
+
+ CHECK_TOK(tok, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ TypeRef type = Parse_Type(lex);
+
+ items.push_back( AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(type) ) );
+ if(GET_TOK(tok, lex) == TOK_BRACE_CLOSE)
+ break;
+ CHECK_TOK(tok, TOK_COMMA);
+ }
+ //if( items.size() == 0 )
+ // WARNING( , W000, "Use 'struct Name;' instead of 'struct Nam { };' ... ning-nong");
+ return AST::Struct(::std::move(params), ::std::move(items));
+ }
+ else
+ {
+ throw ParseError::Unexpected(lex, tok);
+ }
+}
+
+AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ AST::GenericParams params;
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ tok = lex.getToken();
+ }
+
+ // Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2"
+ ::std::vector<Spanned<AST::Path> > supertraits;
+ if(tok.type() == TOK_COLON)
+ {
+ do {
+ if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
+ // TODO: Need a better way of indiciating 'static than just an invalid path
+ supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::Path() ) );
+ }
+ else {
+ PUTBACK(tok, lex);
+ supertraits.push_back( GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE)) );
+ }
+ } while( GET_TOK(tok, lex) == TOK_PLUS );
+ }
+
+ // TODO: Support "for Sized?"
+ if(tok.type() == TOK_RWORD_WHERE)
+ {
+ //if( params.ty_params().size() == 0 )
+ // throw ParseError::Generic("Where clause with no generic params");
+ Parse_WhereClause(lex, params);
+ tok = lex.getToken();
+ }
+
+
+ AST::Trait trait( mv$(params), mv$(supertraits) );
+
+ CHECK_TOK(tok, TOK_BRACE_OPEN);
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ auto ps = lex.start_span();
+ if( tok.type() == TOK_MACRO ) {
+ auto inv = Parse_MacroInvocation( ps, mv$(tok.str()), lex );
+ // - Silently consume ';' after the macro
+ if( GET_TOK(tok, lex) != TOK_SEMICOLON )
+ PUTBACK(tok, lex);
+
+ trait.items().push_back( AST::Named<AST::Item>("", AST::Item(mv$(inv)), false) );
+ continue ;
+ }
+
+ bool is_specialisable = false;
+ if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
+ is_specialisable = true;
+ GET_TOK(tok, lex);
+ }
+ // TODO: Mark specialisation
+ (void)is_specialisable;
+
+ bool fn_is_const = false;
+ bool fn_is_unsafe = false;
+ ::std::string abi = ABI_RUST;
+ switch(tok.type())
+ {
+ case TOK_RWORD_STATIC: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ // TODO: Attributes on associated statics
+ trait.add_static( mv$(name), ::AST::Static(AST::Static::STATIC, mv$(ty), val)/*, mv$(item_attrs)*/ );
+ break; }
+ case TOK_RWORD_CONST: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ // TODO: Attributes on associated constants
+ trait.add_static( mv$(name), ::AST::Static(AST::Static::CONST, mv$(ty), val)/*, mv$(item_attrs)*/ );
+ break; }
+ // Associated type
+ case TOK_RWORD_TYPE: {
+ auto atype_params = ::AST::GenericParams { };
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ {
+ // Bounded associated type
+ Parse_TypeBound(lex, atype_params, TypeRef(lex.getPosition(), "Self", 0xFFFF));
+ GET_TOK(tok, lex);
+ }
+ if( tok.type() == TOK_RWORD_WHERE ) {
+ throw ParseError::Todo(lex, "Where clause on associated type");
+ }
+
+ TypeRef default_type = TypeRef( lex.getPosition() );
+ if( tok.type() == TOK_EQUAL ) {
+ default_type = Parse_Type(lex);
+ GET_TOK(tok, lex);
+ }
+
+ CHECK_TOK(tok, TOK_SEMICOLON);
+ trait.add_type( ::std::move(name), ::std::move(default_type) );
+ trait.items().back().data.as_Type().params() = mv$(atype_params);
+ break; }
+
+ // Functions (possibly unsafe)
+ // TODO: Const?
+ case TOK_RWORD_UNSAFE:
+ fn_is_unsafe = true;
+ if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ PUTBACK(tok, lex);
+
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_RWORD_FN);
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = mv$(tok.str());
+ // Self allowed, prototype-form allowed (optional names and no code)
+ auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const);
+ if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
+ {
+ PUTBACK(tok, lex);
+ fcn.set_code( Parse_ExprBlock(lex) );
+ }
+ else if( tok.type() == TOK_SEMICOLON )
+ {
+ // Accept it
+ }
+ else
+ {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ // TODO: Store `item_attrs`
+ trait.add_function( ::std::move(name), /*mv$(item_attrs),*/ ::std::move(fcn) );
+ break; }
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ }
+
+ return trait;
+}
+
+AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ tok = lex.getToken();
+ // Type params supporting "where"
+ AST::GenericParams params;
+ if( tok.type() == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
+ {
+ Parse_WhereClause(lex, params);
+ tok = lex.getToken();
+ }
+ }
+
+ // Body
+ CHECK_TOK(tok, TOK_BRACE_OPEN);
+ ::std::vector<AST::EnumVariant> variants;
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ auto sp = lex.start_span();
+
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ CHECK_TOK(tok, TOK_IDENT);
+ ::std::string name = mv$(tok.str());
+ if( GET_TOK(tok, lex) == TOK_PAREN_OPEN )
+ {
+ ::std::vector<TypeRef> types;
+ // Get type list
+ do
+ {
+ if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE)
+ {
+ GET_TOK(tok, lex);
+ break;
+ }
+
+ AST::MetaItems field_attrs;
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
+ {
+ GET_TOK(tok, lex);
+ field_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ 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::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) );
+ }
+ else if( tok.type() == TOK_BRACE_OPEN )
+ {
+ ::std::vector<::AST::StructItem> fields;
+ do
+ {
+ if(LOOK_AHEAD(lex) == TOK_BRACE_CLOSE)
+ {
+ GET_TOK(tok, lex);
+ break;
+ }
+
+ AST::MetaItems field_attrs;
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
+ {
+ GET_TOK(tok, lex);
+ field_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ fields.push_back( ::AST::StructItem(mv$(field_attrs), true, mv$(name), mv$(ty)) );
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ GET_TOK(tok, lex);
+
+ variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) );
+ }
+ else if( tok.type() == TOK_EQUAL )
+ {
+ auto node = Parse_Expr(lex);
+ variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) );
+ GET_TOK(tok, lex);
+ }
+ else
+ {
+ variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), ::AST::Expr()) );
+ }
+
+ if( tok.type() != TOK_COMMA )
+ break;
+ }
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+
+ return AST::Enum( mv$(params), mv$(variants) );
+}
+
+::AST::Union Parse_Union(TokenStream& lex, AST::MetaItems& meta_items)
+{
+ Token tok;
+
+ TRACE_FUNCTION;
+
+ AST::GenericParams params;
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ if(GET_TOK(tok, lex) == TOK_RWORD_WHERE)
+ {
+ Parse_WhereClause(lex, params);
+ tok = lex.getToken();
+ }
+ }
+
+ ::std::vector< ::AST::StructItem> variants;
+
+ CHECK_TOK(tok, TOK_BRACE_OPEN);
+ do {
+ if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) {
+ GET_TOK(tok, lex);
+ break ;
+ }
+
+ AST::MetaItems item_attrs;
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN )
+ {
+ GET_TOK(tok, lex);
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ bool is_pub = false;
+ if( LOOK_AHEAD(lex) == TOK_RWORD_PUB ) {
+ is_pub = true;
+ GET_TOK(tok, lex);
+ }
+
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+
+ auto ty = Parse_Type(lex);
+
+ variants.push_back( ::AST::StructItem( mv$(item_attrs), is_pub, mv$(name), mv$(ty) ) );
+
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+
+ return ::AST::Union( mv$(params), mv$(variants) );
+}
+
+/// Parse a meta-item declaration (either #![ or #[)
+AST::MetaItem Parse_MetaItem(TokenStream& lex)
+{
+ TRACE_FUNCTION;
+ Token tok;
+ GET_TOK(tok, lex);
+
+ if( tok.type() == TOK_INTERPOLATED_META ) {
+ return mv$(tok.frag_meta());
+ }
+
+ CHECK_TOK(tok, TOK_IDENT);
+ ::std::string name = mv$(tok.str());
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_EQUAL:
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ return AST::MetaItem(name, tok.str());
+ case TOK_PAREN_OPEN: {
+ ::std::vector<AST::MetaItem> items;
+ do {
+ if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE) {
+ GET_TOK(tok, lex);
+ break;
+ }
+ items.push_back(Parse_MetaItem(lex));
+ } while(GET_TOK(tok, lex) == TOK_COMMA);
+ CHECK_TOK(tok, TOK_PAREN_CLOSE);
+ return AST::MetaItem(name, mv$(items)); }
+ default:
+ PUTBACK(tok, lex);
+ return AST::MetaItem(name);
+ }
+}
+
+::AST::Item Parse_Impl(TokenStream& lex, AST::MetaItems attrs, bool is_unsafe=false)
+{
+ TRACE_FUNCTION;
+ Token tok;
+ auto ps = lex.start_span();
+
+ AST::GenericParams params;
+ // 1. (optional) type parameters
+ if( GET_TOK(tok, lex) == TOK_LT )
+ {
+ params = Parse_GenericParams(lex);
+ GET_CHECK_TOK(tok, lex, TOK_GT);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ // 2. Either a trait name (with type params), or the type to impl
+
+ Spanned<AST::Path> trait_path;
+
+ // - Handle negative impls specially, which must be a trait
+ // "impl !Trait for Type {}"
+ if( GET_TOK(tok, lex) == TOK_EXCLAM )
+ {
+ trait_path = GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE));
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FOR);
+ auto impl_type = Parse_Type(lex, true);
+
+ if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
+ {
+ Parse_WhereClause(lex, params);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_BRACE_OPEN);
+ // negative impls can't have any content
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+
+ return ::AST::Item::make_NegImpl( AST::ImplDef(lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
+ }
+
+ // - Don't care which at this stage
+ PUTBACK(tok, lex);
+
+ auto impl_type = Parse_Type(lex, true);
+
+ if( GET_TOK(tok, lex) == TOK_RWORD_FOR )
+ {
+ // Trickery! All traits parse as valid types, so this works.
+ if( !impl_type.is_path() )
+ throw ParseError::Generic(lex, "Trait was not a path");
+ trait_path = Spanned< AST::Path> {
+ impl_type.span(),
+ mv$(impl_type.path())
+ };
+ // Implementing a trait for another type, get the target type
+ if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT )
+ {
+ // Default impl
+ impl_type = TypeRef(TypeRef::TagInvalid(), lex.getPosition());
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ impl_type = Parse_Type(lex, true);
+ }
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ // Where clause
+ if( GET_TOK(tok, lex) == TOK_RWORD_WHERE )
+ {
+ Parse_WhereClause(lex, params);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+
+ while( LOOK_AHEAD(lex) == TOK_CATTR_OPEN )
+ {
+ GET_TOK(tok, lex);
+ attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ AST::Impl impl( AST::ImplDef( lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
+
+ // A sequence of method implementations
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ auto ps = lex.start_span();
+ if( tok.type() == TOK_MACRO )
+ {
+ impl.add_macro_invocation( Parse_MacroInvocation( ps, mv$(tok.str()), lex ) );
+ // - Silently consume ';' after the macro
+ if( GET_TOK(tok, lex) != TOK_SEMICOLON )
+ PUTBACK(tok, lex);
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ Parse_Impl_Item(lex, impl);
+ }
+ }
+
+ return ::AST::Item::make_Impl( mv$(impl) );
+}
+
+void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ GET_TOK(tok, lex);
+
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, item_attrs);
+
+ auto ps = lex.start_span();
+
+ bool is_public = false;
+ if(tok.type() == TOK_RWORD_PUB) {
+ is_public = true;
+ GET_TOK(tok, lex);
+ }
+
+ bool is_specialisable = false;
+ if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
+ is_specialisable = true;
+ GET_TOK(tok, lex);
+ }
+
+ ::std::string abi = ABI_RUST;
+ bool fn_is_unsafe = false;
+ bool fn_is_const = false;
+ switch(tok.type())
+ {
+ case TOK_RWORD_TYPE: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ impl.add_type(is_public, is_specialisable, name, Parse_Type(lex));
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ break; }
+ case TOK_RWORD_UNSAFE:
+ fn_is_unsafe = true;
+ GET_TOK(tok, lex);
+ if( tok.type() == TOK_RWORD_CONST )
+ case TOK_RWORD_CONST:
+ {
+ GET_TOK(tok, lex);
+ if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE && !fn_is_unsafe )
+ {
+ CHECK_TOK(tok, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ auto val = Parse_Expr(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val));
+ // TODO: Attributes on associated constants
+ impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) /*, mv$(item_attrs)*/ );
+ break ;
+ }
+ else if( tok.type() == TOK_RWORD_UNSAFE )
+ {
+ fn_is_unsafe = true;
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ }
+ fn_is_const = true;
+ }
+ if( tok.type() == TOK_RWORD_EXTERN )
+ // FALL
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ PUTBACK(tok, lex);
+
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_RWORD_FN);
+ // FALL
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ // TODO: Hygine on function names? - Not in impl blocks?
+ ::std::string name = mv$(tok.str());
+ DEBUG("Function " << name);
+ // - Self allowed, can't be prototype-form
+ auto fcn = Parse_FunctionDefWithCode(lex, abi, true, fn_is_unsafe, fn_is_const);
+ impl.add_function(is_public, is_specialisable, mv$(name), mv$(fcn));
+ break; }
+
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+
+ impl.items().back().data->span = lex.end_span(ps);
+ impl.items().back().data->attrs = mv$(item_attrs); // Empty for functions
+}
+
+AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::MetaItems& block_attrs)
+{
+ TRACE_FUNCTION;
+ Token tok;
+
+ while( GET_TOK(tok, lex) == TOK_CATTR_OPEN )
+ {
+ block_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+ PUTBACK(tok, lex);
+
+ AST::ExternBlock rv { abi };
+
+ while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
+ {
+ AST::MetaItems meta_items;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ meta_items.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+ SET_ATTRS(lex, meta_items);
+
+ auto ps = lex.start_span();
+
+ bool is_public = false;
+ if( tok.type() == TOK_RWORD_PUB ) {
+ is_public = true;
+ GET_TOK(tok, lex);
+ }
+ switch(tok.type())
+ {
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ // parse function as prototype
+ // - no self, is prototype, is unsafe and not const
+ auto i = ::AST::Item( Parse_FunctionDef(lex, abi, false, true, true,false) );
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ i.attrs = mv$(meta_items);
+ i.span = lex.end_span(ps);
+
+ rv.add_item( AST::Named<AST::Item> { mv$(name), mv$(i), is_public } );
+ break; }
+ case TOK_RWORD_STATIC: {
+ bool is_mut = false;
+ if( GET_TOK(tok, lex) == TOK_RWORD_MUT )
+ is_mut = true;
+ else
+ PUTBACK(tok, lex);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto type = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ auto i = ::AST::Item(::AST::Static( (is_mut ? ::AST::Static::MUT : ::AST::Static::STATIC), mv$(type), ::AST::Expr() ));
+ i.attrs = mv$(meta_items);
+ i.span = lex.end_span(ps);
+ rv.add_item( AST::Named<AST::Item> { mv$(name), mv$(i), is_public } );
+ break; }
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_STATIC});
+ }
+ }
+
+ return rv;
+}
+
+void Parse_Use_Wildcard(Span sp, AST::Path base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
+{
+ fcn( AST::UseStmt(mv$(sp), mv$(base_path)), "" ); // HACK! Empty path indicates wilcard import
+}
+void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ do {
+ AST::Path path;
+ ::std::string name;
+ if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) {
+ path = ::AST::Path(base_path);
+ name = base_path[base_path.size()-1].name();
+ }
+ else if( tok.type() == TOK_BRACE_CLOSE ) {
+ break ;
+ }
+ else {
+ CHECK_TOK(tok, TOK_IDENT);
+ path = base_path + AST::PathNode(tok.str(), {});
+ name = mv$(tok.str());
+ }
+
+ if( GET_TOK(tok, lex) == TOK_RWORD_AS ) {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ fcn(AST::UseStmt(lex.end_span(ps), mv$(path)), mv$(name));
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ PUTBACK(tok, lex);
+}
+
+void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+ AST::Path path = AST::Path("", {});
+ ::std::vector<AST::PathNode> nodes;
+ ProtoSpan span_start = lex.start_span();
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_SELF:
+ path = AST::Path( AST::Path::TagSelf(), {} ); // relative path
+ break;
+ case TOK_RWORD_SUPER: {
+ unsigned int count = 1;
+ while( LOOK_AHEAD(lex) == TOK_DOUBLE_COLON && lex.lookahead(1) == TOK_RWORD_SUPER ) {
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_SUPER);
+ count += 1;
+ }
+ path = AST::Path( AST::Path::TagSuper(), count, {} );
+ break; }
+ case TOK_IDENT:
+ path.append( AST::PathNode(mv$(tok.str()), {}) );
+ break;
+ // Leading :: is allowed and ignored for the $crate feature
+ case TOK_DOUBLE_COLON:
+ // Absolute path
+ // HACK! mrustc emits $crate as `::"crate-name"`
+ if( LOOK_AHEAD(lex) == TOK_STRING )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_STRING);
+ path = ::AST::Path(tok.str(), {});
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ break;
+ case TOK_BRACE_OPEN:
+ Parse_Use_Set(lex, span_start, path, fcn);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+ return;
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
+ {
+ if( GET_TOK(tok, lex) == TOK_IDENT )
+ {
+ path.append( AST::PathNode( mv$(tok.str()), {}) );
+ }
+ else
+ {
+ //path.set_span( lex.end_span(span_start) );
+ switch( tok.type() )
+ {
+ case TOK_BRACE_OPEN:
+ Parse_Use_Set(lex, span_start, mv$(path), fcn);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+ break ;
+ case TOK_STAR:
+ Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn );
+ break ;
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ // early return - This branch is either the end of the use statement, or a syntax error
+ return ;
+ }
+ }
+ //path.set_span( lex.end_span(span_start) );
+
+ ::std::string name;
+ // This should only be allowed if the last token was an ident
+ // - Above checks ensure this
+ if( tok.type() == TOK_RWORD_AS )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ assert(path.nodes().size() > 0);
+ name = path.nodes().back().name();
+ }
+
+ fcn( AST::UseStmt(lex.end_span(span_start), mv$(path)), name);
+}
+
+
+::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, ::std::string name, TokenStream& lex)
+{
+ Token tok;
+ ::std::string ident;
+ if( GET_TOK(tok, lex) == TOK_IDENT ) {
+ ident = mv$(tok.str());
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ DEBUG("name=" << name << ", ident=" << ident);
+ TokenTree tt = Parse_TT(lex, true);
+ return ::AST::MacroInvocation( lex.end_span(span_start), mv$(name), mv$(ident), mv$(tt));
+}
+
+::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::MetaItems meta_items)
+{
+ TRACE_FUNCTION_F("mod_path="<<mod_path<<", meta_items="<<meta_items);
+ Token tok;
+
+ while( LOOK_AHEAD(lex) == TOK_ATTR_OPEN /* || LOOKAHEAD2(lex, TOK_HASH, TOK_SQUARE_OPEN) */ )
+ {
+ // Attributes!
+ GET_CHECK_TOK(tok, lex, TOK_ATTR_OPEN);
+ meta_items.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ }
+
+ if( LOOK_AHEAD(lex) == TOK_INTERPOLATED_ITEM ) {
+ GET_TOK(tok, lex);
+ auto rv = tok.take_frag_item();
+ // Transfer new attributes onto the item
+ for(auto& mi : meta_items.m_items)
+ rv.data.attrs.m_items.push_back( mv$(mi) );
+ return rv;
+ }
+
+ auto ps = lex.start_span();
+
+ ::std::string item_name;
+ ::AST::Item item_data;
+
+ if( LOOK_AHEAD(lex) == TOK_MACRO ) {
+ GET_TOK(tok, lex);
+
+ ::std::string name = mv$(tok.str());
+ bool is_braced = (LOOK_AHEAD(lex) == TOK_BRACE_OPEN || LOOKAHEAD2(lex, TOK_IDENT, TOK_BRACE_OPEN));
+ item_data = ::AST::Item( Parse_MacroInvocation( ps, mv$(name), lex ) );
+
+ if( !is_braced ) {
+ // - Consume the ';' after the macro
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ }
+
+ item_data.attrs = mv$(meta_items);
+ item_data.span = lex.end_span(ps);
+
+ return ::AST::Named< ::AST::Item> { "", mv$(item_data), false };
+ }
+
+ bool is_public = false;
+ if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) {
+ is_public = true;
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_USE:
+ // NOTE: The only problem here is with things like `use foo::{a, b, c}` - all others are a single statement.
+ // - These are caught by the condition in the closure
+ Parse_Use(lex, [&](AST::UseStmt p, std::string s) {
+ DEBUG(mod_path << " - use " << p << " as '" << s << "'");
+ if( !item_data.is_None() )
+ TODO(lex.getPosition(), "Encode multi-item use statements as a single Item");
+ item_data = ::AST::Item(mv$(p));
+ item_name = mv$(s);
+ });
+ assert( !item_data.is_None() );
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ break;
+
+ case TOK_RWORD_EXTERN:
+ switch( GET_TOK(tok, lex) )
+ {
+ // `extern "<ABI>" fn ...`
+ // `extern "<ABI>" { ...`
+ case TOK_STRING: {
+ ::std::string abi = tok.str();
+ switch(GET_TOK(tok, lex))
+ {
+ // `extern "<ABI>" fn ...`
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, false,false) );
+ break; }
+ // `extern "ABI" {`
+ case TOK_BRACE_OPEN:
+ item_name = "";
+ item_data = ::AST::Item( Parse_ExternBlock(lex, mv$(abi), meta_items) );
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_BRACE_OPEN});
+ }
+ break; }
+ // `extern fn ...`
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, "C", false, false,false) );
+ break;
+
+ // NOTE: `extern { ...` is handled in caller
+ case TOK_BRACE_OPEN:
+ item_name = "";
+ item_data = ::AST::Item( Parse_ExternBlock(lex, "C", meta_items) );
+ break;
+
+ // `extern crate "crate-name" as crate_name;`
+ // `extern crate crate_name;`
+ // `extern crate crate_name as other_name;`
+ case TOK_RWORD_CRATE:
+ switch( GET_TOK(tok, lex) )
+ {
+ // `extern crate "crate-name" as crate_name;`
+ // NOTE: rustc doesn't allow this, keep in mrustc for for reparse support
+ case TOK_STRING:
+ item_data = ::AST::Item::make_Crate({ tok.str() });
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_AS);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ break;
+ // `extern crate crate_name;`
+ // `extern crate crate_name as other_name;`
+ case TOK_IDENT:
+ item_name = mv$(tok.str());
+ if(GET_TOK(tok, lex) == TOK_RWORD_AS) {
+ item_data = ::AST::Item::make_Crate({ mv$(item_name) });
+
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ }
+ else {
+ PUTBACK(tok, lex);
+ item_data = ::AST::Item::make_Crate({ item_name });
+ }
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_IDENT});
+ }
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_STRING, TOK_RWORD_FN, TOK_BRACE_OPEN, TOK_RWORD_CRATE});
+ }
+ break;
+
+ // `const NAME`
+ // `const [unsafe] fn`
+ case TOK_RWORD_CONST:
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_IDENT: {
+ item_name = mv$(tok.str());
+
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ TypeRef type = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+ AST::Expr val = Parse_Expr(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ item_data = ::AST::Item( ::AST::Static(AST::Static::CONST, mv$(type), mv$(val)) );
+ break; }
+ case TOK_RWORD_UNSAFE:
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,true/*unsafe,const*/) );
+ break;
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ // - self not allowed, not prototype
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,true/*unsafe,const*/) );
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_RWORD_FN});
+ }
+ break;
+ // `static NAME`
+ // `static mut NAME`
+ case TOK_RWORD_STATIC: {
+ bool is_mut = false;
+ if(GET_TOK(tok, lex) == TOK_RWORD_MUT) {
+ is_mut = true;
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_IDENT);
+ item_name = mv$(tok.str());
+
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ TypeRef type = Parse_Type(lex);
+
+ GET_CHECK_TOK(tok, lex, TOK_EQUAL);
+
+ AST::Expr val = Parse_Expr(lex);
+
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ item_data = ::AST::Item( ::AST::Static( (is_mut ? AST::Static::MUT : AST::Static::STATIC), mv$(type), mv$(val)) );
+ break; }
+
+ // `unsafe fn`
+ // `unsafe trait`
+ // `unsafe impl`
+ case TOK_RWORD_UNSAFE:
+ meta_items.push_back( AST::MetaItem("#UNSAFE") );
+ switch(GET_TOK(tok, lex))
+ {
+ // `unsafe extern fn`
+ case TOK_RWORD_EXTERN: {
+ ::std::string abi = "C";
+ if(GET_TOK(tok, lex) == TOK_STRING) {
+ abi = mv$(tok.str());
+ }
+ else {
+ PUTBACK(tok, lex);
+ }
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, abi, false, true,false/*unsafe,const*/) );
+ break; }
+ // `unsafe fn`
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ // - self not allowed, not prototype
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,false/*unsafe,const*/) );
+ break;
+ // `unsafe trait`
+ case TOK_RWORD_TRAIT:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ // TODO: Mark as unsafe
+ meta_items.push_back( AST::MetaItem("#UNSAFE") );
+ item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
+ break;
+ // `unsafe impl`
+ case TOK_RWORD_IMPL:
+ return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items), true), false };
+ default:
+ throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL});
+ }
+ break;
+ // `fn`
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ // - self not allowed, not prototype
+ item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, false,false/*unsafe,const*/) );
+ break;
+ // `type`
+ case TOK_RWORD_TYPE:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_TypeAlias(lex) );
+ break;
+ // `struct`
+ case TOK_RWORD_STRUCT:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_Struct(lex, meta_items) );
+ break;
+ // `enum`
+ case TOK_RWORD_ENUM:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_EnumDef(lex, meta_items) );
+ break;
+ // Contextual keywords
+ case TOK_IDENT:
+ if( tok.str() == "union" ) {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_Union(lex, meta_items) );
+ }
+ else {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ break;
+ // `impl`
+ case TOK_RWORD_IMPL:
+ return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items)), false };
+ // `trait`
+ case TOK_RWORD_TRAIT:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ item_name = mv$(tok.str());
+ item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
+ break;
+
+ case TOK_RWORD_MOD: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ auto name = mv$(tok.str());
+ DEBUG("Sub module '" << name << "'");
+ AST::Module submod( mod_path + name );
+
+ // Rules for external files (/ path handling):
+ // - IF using stdin (path='-') - Disallow and propagate '-' as path
+ // - IF a #[path] attribute was passed, allow
+ // - IF in crate root or mod.rs, allow (input flag)
+ // - else, disallow and set flag
+ ::std::string path_attr = (meta_items.has("path") ? meta_items.get("path")->string() : "");
+
+ //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON);
+
+ ::std::string sub_path;
+ bool sub_file_controls_dir = true;
+ if( mod_fileinfo.path == "-" ) {
+ if( path_attr.size() ) {
+ ERROR(lex.getPosition(), E0000, "Cannot load module from file when reading stdin");
+ }
+ sub_path = "-";
+ }
+ else if( path_attr.size() > 0 )
+ {
+ sub_path = dirname(mod_fileinfo.path) + path_attr;
+ }
+ else if( mod_fileinfo.controls_dir )
+ {
+ sub_path = dirname(mod_fileinfo.path) + name;
+ }
+ else
+ {
+ sub_path = mod_fileinfo.path;
+ sub_file_controls_dir = false;
+ }
+ DEBUG("Mod '" << name << "', sub_path = " << sub_path);
+
+ submod.m_file_info.path = sub_path;
+ submod.m_file_info.controls_dir = sub_file_controls_dir;
+
+ // Check #[cfg] and don't load if it fails
+ struct H {
+ static 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;
+ }
+ };
+
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_BRACE_OPEN:
+ submod.m_file_info.path = sub_path + "/";
+ Parse_ModRoot(lex, submod, meta_items);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+ break;
+ case TOK_SEMICOLON:
+ if( sub_path == "-" ) {
+ ERROR(lex.getPosition(), E0000, "Cannot load module from file when reading stdin");
+ }
+ else if( path_attr.size() == 0 && ! mod_fileinfo.controls_dir )
+ {
+ ERROR(lex.getPosition(), E0000, "Can't load from files outside of mod.rs or crate root");
+ }
+ else if( !H::check_item_cfg(meta_items) ) {
+ // Ignore - emit Item::None
+ item_name = mv$(name);
+ item_data = ::AST::Item( );
+ break ;
+ }
+ else
+ {
+ ::std::string newpath_dir = sub_path + "/";
+ ::std::string newpath_file = path_attr.size() > 0 ? sub_path : sub_path + ".rs";
+ DEBUG("newpath_dir = '" << newpath_dir << "', newpath_file = '" << newpath_file << "'");
+ ::std::ifstream ifs_dir (newpath_dir + "mod.rs");
+ ::std::ifstream ifs_file(newpath_file);
+ if( ifs_dir.is_open() && ifs_file.is_open() )
+ {
+ // Collision
+ ERROR(lex.getPosition(), E0000, "Both modname.rs and modname/mod.rs exist");
+ }
+ else if( ifs_dir.is_open() )
+ {
+ // Load from dir
+ submod.m_file_info.path = newpath_dir + "mod.rs";
+ }
+ else if( ifs_file.is_open() )
+ {
+ submod.m_file_info.path = newpath_file;
+ }
+ else
+ {
+ // Can't find file
+ ERROR(lex.getPosition(), E0000, "Can't find file for '" << name << "' in '" << mod_fileinfo.path << "'");
+ }
+ DEBUG("- path = " << submod.m_file_info.path);
+ Lexer sub_lex(submod.m_file_info.path);
+ Parse_ModRoot(sub_lex, submod, meta_items);
+ GET_CHECK_TOK(tok, sub_lex, TOK_EOF);
+ }
+ break;
+ default:
+ throw ParseError::Generic("Expected { or ; after module name");
+ }
+ item_name = mv$(name);
+ item_data = ::AST::Item( mv$(submod) );
+ break; }
+
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+
+ item_data.attrs = mv$(meta_items);
+ item_data.span = lex.end_span(ps);
+
+ return ::AST::Named< ::AST::Item> { mv$(item_name), mv$(item_data), is_public };
+}
+
+void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items)
+{
+ SET_MODULE(lex, mod);
+ lex.parse_state().parent_attrs = &meta_items;
+
+ //TRACE_FUNCTION;
+ Token tok;
+
+ // `use ...`
+ if( LOOK_AHEAD(lex) == TOK_RWORD_USE || (lex.lookahead(0) == TOK_RWORD_PUB && lex.lookahead(1) == TOK_RWORD_USE) )
+ {
+ bool is_public = false;
+ if( GET_TOK(tok, lex) == TOK_RWORD_PUB ) {
+ is_public = true;
+ GET_TOK(tok, lex);
+ }
+
+ Parse_Use(lex, [&mod,is_public,&meta_items](AST::UseStmt p, std::string s) {
+ DEBUG(mod.path() << " - use " << p << " as '" << s << "'");
+ mod.add_alias(is_public, mv$(p), s, meta_items.clone());
+ });
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ }
+ else
+ {
+ mod.add_item( Parse_Mod_Item_S(lex, mod.m_file_info, mod.path(), mv$(meta_items)) );
+ }
+}
+
+void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod)
+{
+ Token tok;
+
+ for(;;)
+ {
+ // Check 1 - End of module (either via a closing brace, or EOF)
+ switch(GET_TOK(tok, lex))
+ {
+ case TOK_BRACE_CLOSE:
+ case TOK_EOF:
+ PUTBACK(tok, lex);
+ return;
+ default:
+ PUTBACK(tok, lex);
+ break;
+ }
+
+ // Attributes on the following item
+ AST::MetaItems 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);
+ }
+ PUTBACK(tok, lex);
+ DEBUG("meta_items = " << meta_items);
+
+ Parse_Mod_Item(lex, mod, mv$(meta_items));
+ }
+}
+
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs)
+{
+ TRACE_FUNCTION;
+
+ Token tok;
+
+ // 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);
+
+ mod_attrs.push_back( mv$(item) );
+ }
+ PUTBACK(tok, lex);
+
+ Parse_ModRoot_Items(lex, mod);
+}
+
+AST::Crate Parse_Crate(::std::string mainfile)
+{
+ Token tok;
+
+ Lexer lex(mainfile);
+
+ size_t p = mainfile.find_last_of('/');
+ ::std::string mainpath = (p != ::std::string::npos ? ::std::string(mainfile.begin(), mainfile.begin()+p+1) : "./");
+
+ AST::Crate crate;
+
+ crate.root_module().m_file_info.path = mainpath;
+ crate.root_module().m_file_info.controls_dir = true;
+
+ Parse_ModRoot(lex, crate.root_module(), crate.m_attrs);
+
+ return crate;
+}
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index 95adf594..13af2043 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -38,7 +38,7 @@ Token::~Token()
default:
break;
}
-
+
}
Token::Token():
@@ -87,7 +87,7 @@ Token::Token(const InterpolatedFragment& frag)
m_type = TOK_INTERPOLATED_STMT; if(0)
case InterpolatedFragment::BLOCK:
m_type = TOK_INTERPOLATED_BLOCK;
-
+
m_data = reinterpret_cast<const AST::ExprNode*>(frag.m_ptr)->clone().release();
break;
case InterpolatedFragment::META:
@@ -125,7 +125,7 @@ Token::Token(TagTakeIP, InterpolatedFragment frag)
m_type = TOK_INTERPOLATED_STMT; if(0)
case InterpolatedFragment::BLOCK:
m_type = TOK_INTERPOLATED_BLOCK;
-
+
m_data = reinterpret_cast<AST::ExprNode*>(frag.m_ptr);
frag.m_ptr = nullptr;
break;
@@ -160,7 +160,7 @@ Token Token::clone() const
{
Token rv(m_type);
rv.m_pos = m_pos;
-
+
assert( m_data.tag() != Data::TAGDEAD );
TU_MATCH(Data, (m_data), (e),
(None,
@@ -254,7 +254,7 @@ enum eTokenType Token::typefromstr(const ::std::string& s)
struct EscapedString {
const ::std::string& s;
EscapedString(const ::std::string& s): s(s) {}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const EscapedString& x) {
for(auto b : x.s) {
switch(b)
@@ -284,7 +284,7 @@ struct EscapedString {
{
switch(m_type)
{
- case TOK_NULL: return "/*null*/";
+ case TOK_NULL: return "/*null*/";
case TOK_EOF: return "/*eof*/";
case TOK_NEWLINE: return "\n";
diff --git a/src/parse/token.hpp b/src/parse/token.hpp
index 3e7f7c24..0fcf0ed7 100644
--- a/src/parse/token.hpp
+++ b/src/parse/token.hpp
@@ -26,7 +26,7 @@ public:
RcString filename;
unsigned int line;
unsigned int ofs;
-
+
Position():
filename(""),
line(0),
@@ -71,11 +71,11 @@ class Token:
}),
(Fragment, void*)
);
-
+
enum eTokenType m_type;
Data m_data;
Position m_pos;
-
+
public:
virtual ~Token();
Token();
@@ -95,7 +95,7 @@ public:
}
Token(const Token& t);
Token clone() const;
-
+
Token(enum eTokenType type);
Token(enum eTokenType type, ::std::string str);
Token(uint64_t val, enum eCoreType datatype);
@@ -110,14 +110,14 @@ public:
enum eCoreType datatype() const { TU_MATCH_DEF(Data, (m_data), (e), (assert(!"Getting datatype of invalid token type");), (Integer, return e.m_datatype;), (Float, return e.m_datatype;)) }
uint64_t intval() const { return m_data.as_Integer().m_intval; }
double floatval() const { return m_data.as_Float().m_floatval; }
-
+
TypeRef& frag_type() { assert(m_type == TOK_INTERPOLATED_TYPE); return *reinterpret_cast<TypeRef*>( m_data.as_Fragment() ); }
AST::Path& frag_path() { assert(m_type == TOK_INTERPOLATED_PATH); return *reinterpret_cast<AST::Path*>( m_data.as_Fragment() ); }
AST::Pattern& frag_pattern() { assert(m_type == TOK_INTERPOLATED_PATTERN); return *reinterpret_cast<AST::Pattern*>( m_data.as_Fragment() ); }
AST::MetaItem& frag_meta() { assert(m_type == TOK_INTERPOLATED_META); return *reinterpret_cast<AST::MetaItem*>( m_data.as_Fragment() ); }
::std::unique_ptr<AST::ExprNode> take_frag_node();
::AST::Named<AST::Item> take_frag_item();
-
+
bool operator==(const Token& r) const {
if(type() != r.type())
return false;
@@ -133,13 +133,13 @@ public:
bool operator!=(const Token& r) const { return !(*this == r); }
::std::string to_str() const;
-
+
void set_pos(Position pos) { m_pos = pos; }
const Position& get_pos() const { return m_pos; }
-
+
static const char* typestr(enum eTokenType type);
static eTokenType typefromstr(const ::std::string& s);
-
+
SERIALISABLE_PROTOTYPES();
friend ::std::ostream& operator<<(::std::ostream& os, const Token& tok);
diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp
index 0182e548..9a961a04 100644
--- a/src/parse/tokenstream.cpp
+++ b/src/parse/tokenstream.cpp
@@ -73,17 +73,17 @@ void TokenStream::putback(Token tok)
eTokenType TokenStream::lookahead(unsigned int i)
{
const unsigned int MAX_LOOKAHEAD = 3;
-
+
if( m_cache_valid )
{
if( i == 0 )
return m_cache.type();
i --;
}
-
+
if( i >= MAX_LOOKAHEAD )
throw ParseError::BugCheck("Excessive lookahead");
-
+
while( i >= m_lookahead.size() )
{
DEBUG("lookahead - read #" << m_lookahead.size());
@@ -91,7 +91,7 @@ eTokenType TokenStream::lookahead(unsigned int i)
auto hygiene = this->realGetHygiene();
m_lookahead.push_back( ::std::make_pair(mv$(tok), mv$(hygiene)) );
}
-
+
DEBUG("lookahead(" << i << ") = " << m_lookahead[i]);
return m_lookahead[i].first.type();
}
diff --git a/src/parse/tokenstream.hpp b/src/parse/tokenstream.hpp
index ae737d0d..85fc62e2 100644
--- a/src/parse/tokenstream.hpp
+++ b/src/parse/tokenstream.hpp
@@ -26,15 +26,15 @@ struct ParseState
bool disallow_struct_literal = false;
// A debugging hook that disables expansion of macros
bool no_expand_macros = false;
-
+
::AST::Module* module = nullptr;
::AST::MetaItems* parent_attrs = nullptr;
-
+
::AST::Module& get_current_mod() {
assert(this->module);
return *this->module;
}
-
+
friend ::std::ostream& operator<<(::std::ostream& os, const ParseState& ps) {
os << "ParseState {";
if(ps.disallow_struct_literal) os << " disallow_struct_literal";
@@ -47,7 +47,7 @@ struct ParseState
class TokenStream
{
friend class TTLexer; // needs access to internals to know what was consumed
-
+
bool m_cache_valid;
Token m_cache;
Ident::Hygiene m_hygiene;
@@ -59,17 +59,17 @@ public:
Token getToken();
void putback(Token tok);
eTokenType lookahead(unsigned int count);
-
+
virtual Position getPosition() const = 0;
Ident::Hygiene getHygiene() const;
-
+
ParseState& parse_state() { return m_parse_state; }
-
+
ProtoSpan start_span() const;
Span end_span(ProtoSpan ps) const;
-
+
Ident get_ident(Token tok) const;
-
+
protected:
virtual Token realGetToken() = 0;
virtual Ident::Hygiene realGetHygiene() const = 0;
diff --git a/src/parse/tokentree.hpp b/src/parse/tokentree.hpp
index 8472ec7f..26e23876 100644
--- a/src/parse/tokentree.hpp
+++ b/src/parse/tokentree.hpp
@@ -1,61 +1,61 @@
-/*
- * MRustC - Rust Compiler
- * - By John Hodge (Mutabah/thePowersGang)
- *
- * parse/tokentree.hpp
- * - Token Trees (groups of tokens
- */
-#ifndef TOKENTREE_HPP_INCLUDED
-#define TOKENTREE_HPP_INCLUDED
-
-#include "token.hpp"
-#include <ident.hpp>
-#include <vector>
-
-class TokenTree
-{
- Ident::Hygiene m_hygiene;
- Token m_tok;
- ::std::vector<TokenTree> m_subtrees;
-public:
- virtual ~TokenTree() {}
- TokenTree() {}
- TokenTree(TokenTree&&) = default;
- TokenTree& operator=(TokenTree&&) = default;
- TokenTree(enum eTokenType ty):
- m_tok( Token(ty) )
- {
- }
- TokenTree(Token tok):
- m_tok( ::std::move(tok) )
- {
- }
- TokenTree(Ident::Hygiene hygiene, Token tok):
- m_hygiene( ::std::move(hygiene) ),
- m_tok( ::std::move(tok) )
- {
- }
- TokenTree(Ident::Hygiene hygiene, ::std::vector<TokenTree> subtrees):
- m_hygiene( ::std::move(hygiene) ),
- m_subtrees( ::std::move(subtrees) )
- {
- }
-
- TokenTree clone() const;
-
- bool is_token() const {
- return m_tok.type() != TOK_NULL;
- }
- unsigned int size() const {
- return m_subtrees.size();
- }
- const TokenTree& operator[](unsigned int idx) const { return m_subtrees[idx]; }
- TokenTree& operator[](unsigned int idx) { return m_subtrees[idx]; }
- const Token& tok() const { return m_tok; }
- Token& tok() { return m_tok; }
- const Ident::Hygiene& hygiene() const { return m_hygiene; }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const TokenTree& tt);
-};
-
-#endif // TOKENTREE_HPP_INCLUDED
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * parse/tokentree.hpp
+ * - Token Trees (groups of tokens
+ */
+#ifndef TOKENTREE_HPP_INCLUDED
+#define TOKENTREE_HPP_INCLUDED
+
+#include "token.hpp"
+#include <ident.hpp>
+#include <vector>
+
+class TokenTree
+{
+ Ident::Hygiene m_hygiene;
+ Token m_tok;
+ ::std::vector<TokenTree> m_subtrees;
+public:
+ virtual ~TokenTree() {}
+ TokenTree() {}
+ TokenTree(TokenTree&&) = default;
+ TokenTree& operator=(TokenTree&&) = default;
+ TokenTree(enum eTokenType ty):
+ m_tok( Token(ty) )
+ {
+ }
+ TokenTree(Token tok):
+ m_tok( ::std::move(tok) )
+ {
+ }
+ TokenTree(Ident::Hygiene hygiene, Token tok):
+ m_hygiene( ::std::move(hygiene) ),
+ m_tok( ::std::move(tok) )
+ {
+ }
+ TokenTree(Ident::Hygiene hygiene, ::std::vector<TokenTree> subtrees):
+ m_hygiene( ::std::move(hygiene) ),
+ m_subtrees( ::std::move(subtrees) )
+ {
+ }
+
+ TokenTree clone() const;
+
+ bool is_token() const {
+ return m_tok.type() != TOK_NULL;
+ }
+ unsigned int size() const {
+ return m_subtrees.size();
+ }
+ const TokenTree& operator[](unsigned int idx) const { return m_subtrees[idx]; }
+ TokenTree& operator[](unsigned int idx) { return m_subtrees[idx]; }
+ const Token& tok() const { return m_tok; }
+ Token& tok() { return m_tok; }
+ const Ident::Hygiene& hygiene() const { return m_hygiene; }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TokenTree& tt);
+};
+
+#endif // TOKENTREE_HPP_INCLUDED
diff --git a/src/parse/ttstream.hpp b/src/parse/ttstream.hpp
index 575178ac..946cca5f 100644
--- a/src/parse/ttstream.hpp
+++ b/src/parse/ttstream.hpp
@@ -21,7 +21,7 @@ public:
~TTStream();
TTStream& operator=(const TTStream& x) { m_stack = x.m_stack; return *this; }
-
+
Position getPosition() const override;
protected:
@@ -44,7 +44,7 @@ public:
TTStreamO& operator=(const TTStreamO& x) { m_stack = x.m_stack; return *this; }
TTStreamO& operator=(TTStreamO&& x) = default;
-
+
Position getPosition() const override;
protected:
diff --git a/src/parse/types.cpp b/src/parse/types.cpp
index 4cd9d755..cb664f79 100644
--- a/src/parse/types.cpp
+++ b/src/parse/types.cpp
@@ -32,7 +32,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list)
auto ps = lex.start_span();
Token tok;
-
+
switch( GET_TOK(tok, lex) )
{
case TOK_INTERPOLATED_TYPE:
@@ -45,7 +45,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list)
// '_' = Wildcard (type inferrence variable)
case TOK_UNDERSCORE:
return TypeRef(Span(tok.get_pos()));
-
+
// 'unsafe' - An unsafe function type
case TOK_RWORD_UNSAFE:
// 'extern' - A function type with an ABI
@@ -54,10 +54,10 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list)
case TOK_RWORD_FN:
PUTBACK(tok, lex);
return Parse_Type_Fn(lex);
-
+
case TOK_RWORD_IMPL:
return Parse_Type_ErasedType(lex, allow_trait_list);
-
+
// '<' - An associated type cast
case TOK_LT:
case TOK_DOUBLE_LT: {
@@ -65,7 +65,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list)
auto path = Parse_Path(lex, PATH_GENERIC_TYPE);
return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(path));
}
- //
+ //
case TOK_RWORD_FOR: {
auto hrls = Parse_HRB(lex);
switch(LOOK_AHEAD(lex))
@@ -156,14 +156,14 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list)
throw ParseError::Unexpected(lex, tok/*, "; or ]"*/);
}
}
-
+
// '(' - Tuple (or lifetime bounded trait)
case TOK_PAREN_OPEN: {
DEBUG("Tuple");
if( GET_TOK(tok, lex) == TOK_PAREN_CLOSE )
return TypeRef(TypeRef::TagTuple(), lex.end_span(ps), {});
PUTBACK(tok, lex);
-
+
TypeRef inner = Parse_Type(lex, true);
if( LOOK_AHEAD(lex) == TOK_PAREN_CLOSE )
{
@@ -198,12 +198,12 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls)
// TODO: HRLs
TRACE_FUNCTION;
Token tok;
-
+
::std::string abi = "";
bool is_unsafe = false;
-
+
GET_TOK(tok, lex);
-
+
if( tok.type() == TOK_RWORD_UNSAFE )
{
is_unsafe = true;
@@ -231,7 +231,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls)
if( LOOK_AHEAD(lex) == TOK_TRIPLE_DOT ) {
GET_TOK(tok, lex);
is_variadic = true;
- break;
+ break;
}
// Handle `ident: `
if( lex.lookahead(0) == TOK_IDENT && lex.lookahead(1) == TOK_COLON ) {
@@ -245,7 +245,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls)
}
}
GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE);
-
+
TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos()));
if( GET_TOK(tok, lex) == TOK_THINARROW )
{
@@ -254,7 +254,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls)
else {
PUTBACK(tok, lex);
}
-
+
return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type));
}
@@ -263,7 +263,7 @@ TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls, boo
Token tok;
auto ps = lex.start_span();
-
+
if( ! allow_trait_list )
{
return TypeRef(TypeRef::TagPath(), lex.end_span(ps), Parse_Path(lex, PATH_GENERIC_TYPE));
@@ -307,7 +307,7 @@ TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list)
traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) );
} while( GET_TOK(tok, lex) == TOK_PLUS );
PUTBACK(tok, lex);
-
+
if( lifetimes.size() )
DEBUG("TODO: Lifetime bounds on erased types");
return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ {}, mv$(traits) }));
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 0b9c2476..db85ed3f 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -20,7 +20,7 @@ struct GenericSlot
Method,
} level;
unsigned short index;
-
+
unsigned int to_binding() const {
if(level == Level::Method && index != 0xFFFF) {
return (unsigned int)index + 256;
@@ -63,7 +63,7 @@ struct Context
unsigned int m_var_count;
unsigned int m_block_level;
bool m_frozen_bind_set;
-
+
Context(const ::AST::Crate& crate, const ::AST::Module& mod):
m_crate(crate),
m_mod(mod),
@@ -71,11 +71,11 @@ struct Context
m_block_level(0),
m_frozen_bind_set( false )
{}
-
+
void push(const ::AST::GenericParams& params, GenericSlot::Level level, bool has_self=false) {
auto e = Ent::make_Generic({});
auto& data = e.as_Generic();
-
+
if( has_self ) {
//assert( level == GenericSlot::Level::Top );
data.types.push_back( Named<GenericSlot> { "Self", GenericSlot { level, 0xFFFF } } );
@@ -90,7 +90,7 @@ struct Context
if( params.lft_params().size() > 0 ) {
//TODO(Span(), "resolve/absolute.cpp - Context::push(GenericParams) - Lifetime params - " << params);
}
-
+
m_name_context.push_back(mv$(e));
}
void pop(const ::AST::GenericParams& , bool has_self=false) {
@@ -111,7 +111,7 @@ struct Context
BUG(Span(), "resolve/absolute.cpp - Context::pop(GenericParams) - Mismatched pop");
m_name_context.pop_back();
}
-
+
class RootBlockScope {
friend struct Context;
Context& ctxt;
@@ -133,7 +133,7 @@ struct Context
RootBlockScope clear_rootblock() {
return RootBlockScope(*this, ~0u);
}
-
+
void push_self(const TypeRef& tr) {
m_name_context.push_back( Ent::make_ConcreteSelf(&tr) );
}
@@ -224,7 +224,7 @@ struct Context
}
m_block_level -= 1;
}
-
+
/// Indicate that a multiple-pattern binding is started
void start_patbind() {
assert( m_block_level > 0 );
@@ -239,8 +239,8 @@ struct Context
void end_patbind() {
m_frozen_bind_set = false;
}
-
-
+
+
enum class LookupMode {
Namespace,
Type,
@@ -292,7 +292,7 @@ struct Context
}
}
break;
-
+
case LookupMode::Type:
//if( name == "IntoIterator" ) {
// DEBUG("lookup_in_mod(mod="<<mod.path()<<")");
@@ -406,14 +406,14 @@ struct Context
)
)
}
-
+
// Top-level module
DEBUG("- Top module (" << m_mod.path() << ")");
::AST::Path rv;
if( this->lookup_in_mod(m_mod, name, mode, rv) ) {
return rv;
}
-
+
DEBUG("- Primitives");
switch(mode)
{
@@ -429,7 +429,7 @@ struct Context
default:
break;
}
-
+
return AST::Path();
}
@@ -468,10 +468,10 @@ struct Context
)
)
}
-
+
ERROR(sp, E0000, "Unable to find local " << (mode == LookupMode::Variable ? "variable" : "type") << " '" << name << "'");
}
-
+
/// Clones the context, including only the module-level items (i.e. just the Module entries)
Context clone_mod() const {
auto rv = Context(this->m_crate, this->m_mod);
@@ -543,18 +543,18 @@ void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::L
nodes.erase( nodes.begin() );
path = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(span, mv$(inner_path)), ::AST::Path(), mv$(nodes) );
}
-
+
const auto& ufcs = path.m_class.as_UFCS();
if( ufcs.nodes.size() == 0 ) {
-
+
if( mode == Context::LookupMode::Type && ufcs.trait && *ufcs.trait == ::AST::Path() ) {
return ;
}
-
+
BUG(sp, "UFCS with no nodes encountered - " << path);
}
const auto& node = ufcs.nodes.at(0);
-
+
if( ufcs.trait && ufcs.trait->is_valid() )
{
// Trait is specified, definitely a trait item
@@ -567,7 +567,7 @@ void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::L
return ;
assert( pb.as_Trait().trait_ );
const auto& tr = *pb.as_Trait().trait_;
-
+
switch(mode)
{
case Context::LookupMode::Pattern:
@@ -637,18 +637,18 @@ namespace {
const auto& path_abs = path.m_class.as_Absolute();
auto type_path = ::AST::Path( path );
type_path.m_class.as_Absolute().nodes.resize( i+1 );
-
+
auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
-
+
return new_path;
}
AST::Path split_replace_into_ufcs_path(const Span& sp, AST::Path path, unsigned int i, const AST::Path& ty_path_tpl)
{
auto& path_abs = path.m_class.as_Absolute();
auto& n = path_abs.nodes[i];
-
+
auto type_path = ::AST::Path(ty_path_tpl);
if( ! n.args().is_empty() ) {
type_path.nodes().back().args() = mv$(n.args());
@@ -656,10 +656,10 @@ namespace {
auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
-
+
return new_path;
}
-
+
void Resolve_Absolute_Path_BindAbsolute__hir_from_import(Context& context, const Span& sp, bool is_value, AST::Path& path, const ::HIR::SimplePath& p)
{
TRACE_FUNCTION_FR("path="<<path<<", p="<<p, path);
@@ -671,7 +671,7 @@ namespace {
auto it = hmod->m_mod_items.find(name);
if( it == hmod->m_mod_items.end() )
ERROR(sp, E0000, "Couldn't find path component '" << name << "' of " << p);
-
+
TU_MATCH_DEF(::HIR::TypeItem, (it->second->ent), (e),
(
TODO(sp, "Unknown item type in path - " << i << " " << p << " - " << it->second->ent.tag_str());
@@ -685,7 +685,7 @@ namespace {
ASSERT_BUG(sp, it != e.m_variants.end(), "Extern crate import path points to non-present variant - " << p);
unsigned int var_idx = it - e.m_variants.begin();
auto pb = ::AST::PathBinding::make_EnumVar({nullptr, var_idx, &e});
-
+
// Construct output path (with same set of parameters)
AST::Path rv( p.m_crate_name, {} );
rv.nodes().reserve( p.m_components.size() );
@@ -694,7 +694,7 @@ namespace {
rv.nodes().back().args() = mv$( path.nodes().back().args() );
rv.bind( mv$(pb) );
path = mv$(rv);
-
+
return ;
),
(Module,
@@ -702,9 +702,9 @@ namespace {
)
)
}
-
+
::AST::PathBinding pb;
-
+
const auto& name = p.m_components.back();
if( is_value )
{
@@ -763,7 +763,7 @@ namespace {
)
)
}
-
+
// Construct output path (with same set of parameters)
AST::Path rv( p.m_crate_name, {} );
rv.nodes().reserve( p.m_components.size() );
@@ -773,12 +773,12 @@ namespace {
rv.bind( mv$(pb) );
path = mv$(rv);
}
-
+
void Resolve_Absolute_Path_BindAbsolute__hir_from(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path, const AST::ExternCrate& crate, unsigned int start)
{
TRACE_FUNCTION_FR(path << " start=" << start, path);
auto& path_abs = path.m_class.as_Absolute();
-
+
if( path_abs.nodes.empty() ) {
switch(mode)
{
@@ -789,7 +789,7 @@ namespace {
TODO(sp, "");
}
}
-
+
const ::HIR::Module* hmod = &crate.m_hir->m_root_module;
for(unsigned int i = start; i < path_abs.nodes.size() - 1; i ++ )
{
@@ -798,7 +798,7 @@ namespace {
auto it = hmod->m_mod_items.find(n.name());
if( it == hmod->m_mod_items.end() )
ERROR(sp, E0000, "Couldn't find path component '" << n.name() << "' of " << path);
-
+
TU_MATCH(::HIR::TypeItem, (it->second->ent), (e),
(Import,
// - Update path then restart
@@ -830,7 +830,7 @@ namespace {
}
}
trait_path.bind( ::AST::PathBinding::make_Trait({nullptr, &e}) );
-
+
::AST::Path new_path;
const auto& next_node = path_abs.nodes[i+1];
// If the named item can't be found in the trait, fall back to it being a type binding
@@ -847,7 +847,7 @@ namespace {
found = (e.m_values.find( next_node.name() ) != e.m_values.end());
break;
}
-
+
if( !found ) {
new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(trait_path)));
}
@@ -856,7 +856,7 @@ namespace {
}
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
-
+
path = mv$(new_path);
return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
),
@@ -881,7 +881,7 @@ namespace {
for( const auto& var : e.m_variants )
{
if( var.first == last_node.name() ) {
-
+
if( i != path_abs.nodes.size() - 2 ) {
ERROR(sp, E0000, "Unexpected enum in path " << path);
}
@@ -889,7 +889,7 @@ namespace {
if( ! n.args().is_empty() ) {
ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
}
-
+
path.bind( ::AST::PathBinding::make_EnumVar({nullptr, static_cast<unsigned int>(&var - &*e.m_variants.begin()), &e}) );
path = split_into_crate(sp, mv$(path), start, crate.m_name);
return;
@@ -901,7 +901,7 @@ namespace {
)
)
}
-
+
const auto& name = path_abs.nodes.back().name();
switch(mode)
{
@@ -942,7 +942,7 @@ namespace {
}
}
break;
-
+
case Context::LookupMode::Pattern:
{
auto v = hmod->m_mod_items.find(name);
@@ -1028,14 +1028,14 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
{
TRACE_FUNCTION_FR("path = " << path, path);
auto& path_abs = path.m_class.as_Absolute();
-
+
if( path_abs.crate != "" ) {
// TODO: Handle items from other crates (back-converting HIR paths)
Resolve_Absolute_Path_BindAbsolute__hir_from(context, sp, mode, path, context.m_crate.m_extern_crates.at(path_abs.crate), 0);
return ;
}
-
-
+
+
const ::AST::Module* mod = &context.m_crate.m_root_module;
for(unsigned int i = 0; i < path_abs.nodes.size() - 1; i ++ )
{
@@ -1045,11 +1045,11 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
if( ! n.args().is_empty() ) {
ERROR(sp, E0000, "Type parameters were not expected here");
}
-
+
if( n.name() == "#" ) {
TODO(sp, "magic module");
}
-
+
char c;
unsigned int idx;
::std::stringstream ss( n.name() );
@@ -1067,7 +1067,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
}
const auto& name_ref = it->second;
DEBUG("#" << i << " \"" << n.name() << "\" = " << name_ref.path << (name_ref.is_import ? " (import)" : "") );
-
+
TU_MATCH_DEF(::AST::PathBinding, (name_ref.path.binding()), (e),
(
ERROR(sp, E0000, "Encountered non-namespace item '" << n.name() << "' ("<<name_ref.path<<") in path " << path);
@@ -1143,7 +1143,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
}
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
-
+
path = mv$(new_path);
return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
),
@@ -1164,7 +1164,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
const auto& last_node = path_abs.nodes.back();
for( const auto& var : e.enum_->variants() ) {
if( var.m_name == last_node.name() ) {
-
+
if( i != path_abs.nodes.size() - 2 ) {
ERROR(sp, E0000, "Unexpected enum in path " << path);
}
@@ -1172,12 +1172,12 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
if( ! n.args().is_empty() ) {
ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
}
-
+
path.bind_enum_var(*e.enum_, var.m_name);
return;
}
}
-
+
path = split_replace_into_ufcs_path(sp, mv$(path), i, name_ref.path);
return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
}
@@ -1210,14 +1210,14 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
)
}
}
-
+
// Set binding to binding of node in last module
::AST::Path tmp;
if( ! Context::lookup_in_mod(*mod, path_abs.nodes.back().name(), mode, tmp) ) {
ERROR(sp, E0000, "Couldn't find " << Context::lookup_mode_msg(mode) << " '" << path_abs.nodes.back().name() << "' of " << path);
}
assert( ! tmp.binding().is_Unbound() );
-
+
// Replaces the path with the one returned by `lookup_in_mod`, ensuring that `use` aliases are eliminated
DEBUG("Replace " << path << " with " << tmp);
auto args = mv$(path.nodes().back().args());
@@ -1235,7 +1235,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::LookupMode mode, ::AST::Path& path)
{
TRACE_FUNCTION_FR("mode = " << mode << ", path = " << path, path);
-
+
TU_MATCH(::AST::Path::Class, (path.m_class), (e),
(Invalid,
BUG(sp, "Attempted resolution of invalid path");
@@ -1270,7 +1270,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
if( !pe.module_ ) {
assert( pe.hir );
const auto& mod = *pe.hir;
-
+
switch( e.nodes.size() == 2 ? mode : Context::LookupMode::Namespace )
{
case Context::LookupMode::Namespace:
@@ -1321,11 +1321,11 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
auto ct = coretype_fromstring(e.nodes[0].name());
p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(Span("-",0,0,0,0), ct), ::AST::Path(), ::std::vector< ::AST::PathNode>() );
}
-
+
DEBUG("Primitive module hack yeilded " << p);
)
}
-
+
if( e.nodes.size() > 1 )
{
// Only primitive types turn `Local` paths
@@ -1355,7 +1355,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
}
path = mv$(p);
}
-
+
if( !path.is_trivial() )
Resolve_Absolute_PathNodes(context, sp, path.nodes());
),
@@ -1372,7 +1372,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
unsigned int start_len = e.count > mp_nodes.size() ? 0 : mp_nodes.size() - e.count;
while( start_len > 0 && mp_nodes[start_len-1].name()[0] == '#' )
start_len --;
-
+
// - Create a new path
::AST::Path np("", {});
auto& np_nodes = np.nodes();
@@ -1381,10 +1381,10 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
np_nodes.push_back( mp_nodes[i] );
for(auto& en : e.nodes)
np_nodes.push_back( mv$(en) );
-
+
if( !path.is_trivial() )
Resolve_Absolute_PathNodes(context, sp, np_nodes);
-
+
path = mv$(np);
),
(Absolute,
@@ -1398,11 +1398,11 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
if( e.trait && *e.trait != ::AST::Path() ) {
Resolve_Absolute_Path(context, sp, Context::LookupMode::Type, *e.trait);
}
-
+
Resolve_Absolute_PathNodes(context, sp, e.nodes);
)
)
-
+
DEBUG("path = " << path);
// TODO: Should this be deferred until the HIR?
// - Doing it here so the HIR lowering has a bit more information
@@ -1424,7 +1424,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
)
)
-
+
// TODO: Expand default type parameters?
// - Helps with cases like PartialOrd<Self>, but hinders when the default is a hint (in expressions)
}
@@ -1495,7 +1495,7 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type)
}
assert( ufcs.nodes.size() == 1);
)
-
+
TU_IFLET(::AST::PathBinding, e.path.binding(), Trait, be,
auto ty = ::TypeRef( type.span(), {}, ::make_vec1(mv$(e.path)) );
type = mv$(ty);
@@ -1534,12 +1534,12 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
public AST::NodeVisitorDef
{
Context& context;
-
+
NV(Context& context):
context(context)
{
}
-
+
void visit(AST::ExprNode_Block& node) override {
DEBUG("ExprNode_Block");
if( node.m_local_mod ) {
@@ -1556,7 +1556,7 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
this->context.pop( *node.m_local_mod );
}
}
-
+
void visit(AST::ExprNode_Match& node) override {
DEBUG("ExprNode_Match");
node.m_val->visit( *this );
@@ -1579,12 +1579,12 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
else {
Resolve_Absolute_Pattern(this->context, true, arm.m_patterns[0]);
}
-
+
if(arm.m_cond)
arm.m_cond->visit( *this );
assert( arm.m_code );
arm.m_code->visit( *this );
-
+
this->context.pop_block();
}
}
@@ -1606,7 +1606,7 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
node.m_code->visit( *this );
this->context.pop_block();
}
-
+
void visit(AST::ExprNode_LetBinding& node) override {
DEBUG("ExprNode_LetBinding");
Resolve_Absolute_Type(this->context, node.m_type);
@@ -1616,14 +1616,14 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
void visit(AST::ExprNode_IfLet& node) override {
DEBUG("ExprNode_IfLet");
node.m_value->visit( *this );
-
+
this->context.push_block();
Resolve_Absolute_Pattern(this->context, true, node.m_pattern);
-
+
assert( node.m_true );
node.m_true->visit( *this );
this->context.pop_block();
-
+
if(node.m_false)
node.m_false->visit(*this);
}
@@ -1653,17 +1653,17 @@ void Resolve_Absolute_ExprNode(Context& context, ::AST::ExprNode& node)
}
void visit(AST::ExprNode_Closure& node) override {
DEBUG("ExprNode_Closure");
-
+
Resolve_Absolute_Type(this->context, node.m_return);
-
+
this->context.push_block();
for( auto& arg : node.m_args ) {
Resolve_Absolute_Type(this->context, arg.second);
Resolve_Absolute_Pattern(this->context, false, arg.first);
}
-
+
node.m_code->visit(*this);
-
+
this->context.pop_block();
}
} expr_iter(context);
@@ -1744,7 +1744,7 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa
}
else {
auto name = mv$( e.name );
-
+
pat = ::AST::Pattern(::AST::Pattern::TagBind(), mv$(name));
pat.binding().m_slot = context.push_var( pat.span(), pat.binding().m_name );
}
@@ -1828,32 +1828,32 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::AST::NamedList< ::AST:
assert( e.params().lft_params().size() == 0 );
item_context.push( e.params(), GenericSlot::Level::Method, true );
Resolve_Absolute_Generic(item_context, e.params());
-
+
Resolve_Absolute_Type( item_context, e.type() );
-
+
item_context.pop( e.params(), true );
),
(Function,
DEBUG("Function - " << i.name);
item_context.push( e.params(), GenericSlot::Level::Method );
Resolve_Absolute_Generic(item_context, e.params());
-
+
Resolve_Absolute_Type( item_context, e.rettype() );
for(auto& arg : e.args())
Resolve_Absolute_Type( item_context, arg.second );
-
+
{
auto _h = item_context.enter_rootblock();
item_context.push_block();
for(auto& arg : e.args()) {
Resolve_Absolute_Pattern( item_context, false, arg.first );
}
-
+
Resolve_Absolute_Expr( item_context, e.code() );
-
+
item_context.pop_block();
}
-
+
item_context.pop( e.params() );
),
(Static,
@@ -1891,9 +1891,9 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::std::vector< ::AST::Im
assert( e.params().lft_params().size() == 0 );
item_context.push( e.params(), GenericSlot::Level::Method, true );
Resolve_Absolute_Generic(item_context, e.params());
-
+
Resolve_Absolute_Type( item_context, e.type() );
-
+
item_context.pop( e.params(), true );
),
(Function,
@@ -1925,9 +1925,9 @@ void Resolve_Absolute_Function(Context& item_context, ::AST::Function& fcn)
for(auto& arg : fcn.args()) {
Resolve_Absolute_Pattern( item_context, false, arg.first );
}
-
+
Resolve_Absolute_Expr( item_context, fcn.code() );
-
+
item_context.pop_block();
}
@@ -1944,7 +1944,7 @@ void Resolve_Absolute_Struct(Context& item_context, ::AST::Struct& e)
{
item_context.push( e.params(), GenericSlot::Level::Top );
Resolve_Absolute_Generic(item_context, e.params());
-
+
TU_MATCH(::AST::StructData, (e.m_data), (s),
(Tuple,
for(auto& field : s.ents) {
@@ -1957,25 +1957,25 @@ void Resolve_Absolute_Struct(Context& item_context, ::AST::Struct& e)
}
)
)
-
+
item_context.pop( e.params() );
}
void Resolve_Absolute_Union(Context& item_context, ::AST::Union& e)
{
item_context.push( e.m_params, GenericSlot::Level::Top );
Resolve_Absolute_Generic(item_context, e.m_params);
-
+
for(auto& field : e.m_variants) {
Resolve_Absolute_Type(item_context, field.m_type);
}
-
+
item_context.pop( e.m_params );
}
void Resolve_Absolute_Trait(Context& item_context, ::AST::Trait& e)
{
item_context.push( e.params(), GenericSlot::Level::Top, true );
Resolve_Absolute_Generic(item_context, e.params());
-
+
for(auto& st : e.supertraits()) {
if( !st.ent.is_valid() ) {
DEBUG("- ST 'static");
@@ -1985,16 +1985,16 @@ void Resolve_Absolute_Trait(Context& item_context, ::AST::Trait& e)
Resolve_Absolute_Path(item_context, st.sp, Context::LookupMode::Type, st.ent);
}
}
-
+
Resolve_Absolute_ImplItems(item_context, e.items());
-
+
item_context.pop( e.params(), true );
}
void Resolve_Absolute_Enum(Context& item_context, ::AST::Enum& e)
{
item_context.push( e.params(), GenericSlot::Level::Top );
Resolve_Absolute_Generic(item_context, e.params());
-
+
for(auto& variant : e.variants())
{
TU_MATCH(::AST::EnumVariantData, (variant.m_data), (s),
@@ -2014,7 +2014,7 @@ void Resolve_Absolute_Enum(Context& item_context, ::AST::Enum& e)
)
)
}
-
+
item_context.pop( e.params() );
}
@@ -2024,7 +2024,7 @@ void Resolve_Absolute_Mod(const ::AST::Crate& crate, ::AST::Module& mod) {
void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
{
TRACE_FUNCTION_F("(mod="<<mod.path()<<")");
-
+
for( auto& i : mod.items() )
{
TU_MATCH(AST::Item, (i.data), (e),
@@ -2062,13 +2062,13 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
Resolve_Absolute_Generic(item_context, def.params());
assert( def.trait().ent.is_valid() );
Resolve_Absolute_Path(item_context, def.trait().sp, Context::LookupMode::Type, def.trait().ent);
-
+
if( e.items().size() != 0 ) {
ERROR(def.span(), E0000, "impl Trait for .. with methods");
}
-
+
item_context.pop(def.params());
-
+
const_cast< ::AST::Trait*>(def.trait().ent.binding().as_Trait().trait_)->set_is_marker();
}
else
@@ -2076,14 +2076,14 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
item_context.push_self( def.type() );
item_context.push(def.params(), GenericSlot::Level::Top);
Resolve_Absolute_Generic(item_context, def.params());
-
+
Resolve_Absolute_Type(item_context, def.type());
if( def.trait().ent.is_valid() ) {
Resolve_Absolute_Path(item_context, def.trait().sp, Context::LookupMode::Type, def.trait().ent);
}
-
+
Resolve_Absolute_ImplItems(item_context, e.items());
-
+
item_context.pop(def.params());
item_context.pop_self( def.type() );
}
@@ -2093,14 +2093,14 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
item_context.push_self( impl_def.type() );
item_context.push(impl_def.params(), GenericSlot::Level::Top);
Resolve_Absolute_Generic(item_context, impl_def.params());
-
+
Resolve_Absolute_Type(item_context, impl_def.type());
if( !impl_def.trait().ent.is_valid() )
BUG(impl_def.span(), "Encountered negative impl with no trait");
Resolve_Absolute_Path(item_context, impl_def.trait().sp, Context::LookupMode::Type, impl_def.trait().ent);
-
+
// No items
-
+
item_context.pop(impl_def.params());
item_context.pop_self( impl_def.type() );
),
@@ -2123,9 +2123,9 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
DEBUG("Type - " << i.name);
item_context.push( e.params(), GenericSlot::Level::Top, true );
Resolve_Absolute_Generic(item_context, e.params());
-
+
Resolve_Absolute_Type( item_context, e.type() );
-
+
item_context.pop( e.params(), true );
),
(Struct,
@@ -2146,7 +2146,7 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
)
)
}
-
+
// - Run through the indexed items and fix up those paths
static Span sp;
DEBUG("mod = " << mod.path());
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index c0276695..b65bea6f 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -53,11 +53,11 @@ namespace {
void _add_item(const Span& sp, AST::Module& mod, IndexName location, const ::std::string& name, bool is_pub, ::AST::Path ir, bool error_on_collision=true)
{
auto& list = get_mod_index(mod, location);
-
+
bool was_import = (ir != mod.path() + name);
if( list.count(name) > 0 )
{
- if( error_on_collision )
+ if( error_on_collision )
{
ERROR(sp, E0000, "Duplicate definition of name '" << name << "' in " << location << " scope (" << mod.path() << ")");
}
@@ -99,7 +99,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
{
::AST::Path p = mod.path() + i.name;
//DEBUG("- p = " << p << " : " << ::AST::Item::tag_to_str(i.data.tag()));
-
+
TU_MATCH(AST::Item, (i.data), (e),
(None,
),
@@ -112,7 +112,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
),
(NegImpl,
),
-
+
(Use,
// Skip for now
),
@@ -162,7 +162,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
)
)
}
-
+
bool has_pub_wildcard = false;
// Named imports
for( const auto& i : mod.items() )
@@ -173,7 +173,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
if( i.name != "" )
{
// TODO: Ensure that the path is canonical?
-
+
const auto& sp = i_data.sp;
struct H {
static void handle_pb(const Span& sp, AST::Module& mod, const AST::Named<AST::Item>& i, const AST::PathBinding& pb, bool allow_collide)
@@ -194,14 +194,14 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
(StructMethod,
BUG(sp, "Import was bound to struct method");
),
-
+
(Crate , _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i_data.path, !allow_collide); ),
(Module, _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i_data.path, !allow_collide); ),
(Enum, _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide); ),
(Union, _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide); ),
(Trait, _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide); ),
(TypeAlias,_add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide); ),
-
+
(Struct,
_add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
// - If the struct is a tuple-like struct, it presents in the value namespace
@@ -258,9 +258,9 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
}
}
}
-
+
mod.m_index_populated = (has_pub_wildcard ? 1 : 2);
-
+
// Handle child modules
for( auto& i : mod.items() )
{
@@ -326,7 +326,7 @@ void Resolve_Index_Module_Wildcard__glob_in_hir_mod(const Span& sp, const AST::C
if( ve.ent.is_Import() ) {
const auto& spath = ve.ent.as_Import().path;
p = hir_to_ast( spath );
-
+
ASSERT_BUG(sp, crate.m_extern_crates.count(spath.m_crate_name) == 1, "Crate " << spath.m_crate_name << " is not loaded");
const auto* hmod = &crate.m_extern_crates.at(spath.m_crate_name).m_hir->m_root_module;
for(unsigned int i = 0; i < spath.m_components.size()-1; i ++) {
@@ -390,7 +390,7 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod, bool han
if( ! i.data.is_Use() )
continue ;
const auto& i_data = i.data.as_Use();
-
+
if( i.name == "" && i.is_pub == handle_pub )
{
const auto& sp = i_data.sp;
@@ -414,7 +414,7 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod, bool han
(StructMethod,
BUG(sp, "Import was bound to struct method");
),
-
+
(Crate,
DEBUG("Glob crate " << i_data.path);
const auto& hmod = e.crate_->m_hir->m_root_module;
@@ -476,7 +476,7 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod, bool han
else {
_add_item_value( sp, mod, ev.m_name, i.is_pub, mv$(p), false );
}
-
+
idx += 1;
}
}
@@ -495,7 +495,7 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod, bool han
else {
_add_item_value( sp, mod, ev.first, i.is_pub, mv$(p), false );
}
-
+
idx += 1;
}
}
@@ -503,10 +503,10 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod, bool han
)
}
}
-
+
// handle_pub == true first, leading to full resoltion no matter what
mod.m_index_populated = 2;
-
+
// Handle child modules
for( auto& i : mod.items() )
{
@@ -538,7 +538,7 @@ void Resolve_Index_Module_Normalise_Path_ext(const ::AST::Crate& crate, const Sp
// path.nodes().erase( path.nodes().begin() + i );
//} while( --i > 0 );
-
+
for(unsigned int i = start; i < info.nodes.size() - 1; i ++)
{
auto it = hmod->m_mod_items.find( info.nodes[i].name() );
@@ -575,7 +575,7 @@ void Resolve_Index_Module_Normalise_Path_ext(const ::AST::Crate& crate, const Sp
)
}
const auto& lastnode = info.nodes.back();
-
+
switch(loc)
{
case IndexName::Type:
@@ -606,7 +606,7 @@ void Resolve_Index_Module_Normalise_Path_ext(const ::AST::Crate& crate, const Sp
}
} break;
}
-
+
ERROR(sp, E0000, "Couldn't find final node of path " << path);
}
@@ -619,17 +619,17 @@ bool Resolve_Index_Module_Normalise_Path(const ::AST::Crate& crate, const Span&
Resolve_Index_Module_Normalise_Path_ext(crate, sp, path, loc, crate.m_extern_crates.at(info.crate), 0);
return false;
}
-
+
const ::AST::Module* mod = &crate.m_root_module;
for( unsigned int i = 0; i < info.nodes.size() - 1; i ++ )
{
const auto& node = info.nodes[i];
-
+
auto it = mod->m_namespace_items.find( node.name() );
if( it == mod->m_namespace_items.end() )
ERROR(sp, E0000, "Couldn't find node " << i << " of path " << path);
const auto& ie = it->second;
-
+
if( ie.is_import ) {
// Need to replace all nodes up to and including the current with the import path
auto new_path = ie.path;
@@ -658,10 +658,10 @@ bool Resolve_Index_Module_Normalise_Path(const ::AST::Crate& crate, const Span&
)
}
}
-
+
const auto& node = info.nodes.back();
-
-
+
+
// TODO: Use get_mod_index instead.
const ::AST::Module::IndexEnt* ie_p = nullptr;
switch(loc)
@@ -685,7 +685,7 @@ bool Resolve_Index_Module_Normalise_Path(const ::AST::Crate& crate, const Span&
if( !ie_p )
ERROR(sp, E0000, "Couldn't find final node of path " << path);
const auto& ie = *ie_p;
-
+
if( ie.is_import ) {
// TODO: Prevent infinite recursion if the user does something dumb
path = ::AST::Path(ie.path);
@@ -706,7 +706,7 @@ void Resolve_Index_Module_Normalise(const ::AST::Crate& crate, const Span& mod_s
Resolve_Index_Module_Normalise(crate, item.data.span, e);
)
}
-
+
DEBUG("Index for " << mod.path());
for( auto& ent : mod.m_namespace_items ) {
Resolve_Index_Module_Normalise_Path(crate, mod_span, ent.second.path, IndexName::Namespace);
@@ -730,7 +730,7 @@ void Resolve_Index(AST::Crate& crate)
Resolve_Index_Module_Wildcard(crate, crate.m_root_module, true);
// - Add all private glob imported items
Resolve_Index_Module_Wildcard(crate, crate.m_root_module, false);
-
+
// - Normalise the index (ensuring all paths point directly to the item)
Resolve_Index_Module_Normalise(crate, Span(), crate.m_root_module);
}
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 0196108f..55c949b8 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -89,22 +89,22 @@ void Resolve_Use(::AST::Crate& crate)
void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path path, slice< const ::AST::Module* > parent_modules)
{
TRACE_FUNCTION_F("path = " << path);
-
+
for(auto& use_stmt : mod.items())
{
if( ! use_stmt.data.is_Use() )
continue ;
auto& use_stmt_data = use_stmt.data.as_Use();
-
+
const Span& span = use_stmt_data.sp;
use_stmt_data.path = Resolve_Use_AbsolutisePath(span, path, mv$(use_stmt_data.path));
if( !use_stmt_data.path.m_class.is_Absolute() )
BUG(span, "Use path is not absolute after absolutisation");
-
+
// TODO: Have Resolve_Use_GetBinding return the actual path
use_stmt_data.path.bind( Resolve_Use_GetBinding(span, crate, use_stmt_data.path, parent_modules) );
DEBUG("'" << use_stmt.name << "' = " << use_stmt_data.path);
-
+
// - If doing a glob, ensure the item type is valid
if( use_stmt.name == "" )
{
@@ -158,18 +158,18 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
{
const AST::Crate& crate;
::std::vector< const AST::Module* > parent_modules;
-
+
NV(const AST::Crate& crate, const AST::Module& cur_module):
crate(crate),
parent_modules()
{
parent_modules.push_back( &cur_module );
}
-
+
void visit(AST::ExprNode_Block& node) override {
if( node.m_local_mod ) {
Resolve_Use_Mod(this->crate, *node.m_local_mod, node.m_local_mod->path(), this->parent_modules);
-
+
parent_modules.push_back(&*node.m_local_mod);
}
AST::NodeVisitorDef::visit(node);
@@ -178,7 +178,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
}
}
} expr_iter(crate, mod);
-
+
// TODO: Check that all code blocks are covered by these
// - NOTE: Handle anon modules by iterating code (allowing correct item mappings)
for(auto& i : mod.items())
@@ -264,13 +264,13 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
assert( mod.anon_mods()[idx] );
return ::AST::PathBinding::make_Module({&*mod.anon_mods()[idx]});
}
-
+
// Seach for the name defined in the module.
for( const auto& item : mod.items() )
{
if( item.data.is_None() )
continue ;
-
+
if( item.name == des_item_name ) {
//if( allow != Lookup::Any )
// DEBUG(mod.path() << " " << des_item_name << " " << item.data.tag_str());
@@ -305,7 +305,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
if( allow != Lookup::Value )
return ::AST::PathBinding::make_Trait({&e});
),
-
+
(Function,
if( allow != Lookup::Type )
return ::AST::PathBinding::make_Function({&e});
@@ -335,7 +335,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
)
}
}
-
+
// Imports
for( const auto& imp : mod.items() )
{
@@ -406,7 +406,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
else {
//out_path = imp_data.path;
}
-
+
TU_MATCH_DEF(::AST::PathBinding, (*binding), (e),
(
BUG(sp2, "Wildcard import expanded to an invalid item class - " << binding->tag_str());
@@ -463,7 +463,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
namespace {
const ::HIR::Module* get_hir_mod_by_path(const Span& sp, const ::AST::Crate& crate, const ::HIR::SimplePath& path);
-
+
const void* get_hir_modenum_by_path(const Span& sp, const ::AST::Crate& crate, const ::HIR::SimplePath& path, bool& is_enum)
{
const auto* hmod = &crate.m_extern_crates.at( path.m_crate_name ).m_hir->m_root_module;
@@ -533,7 +533,7 @@ namespace {
ERROR(span, E0000, "Encountered enum at unexpected location in import");
}
const auto& name = nodes[i].name();
-
+
auto it2 = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == name; } );
if( it2 == enm.m_variants.end() ) {
ERROR(span, E0000, "Unable to find variant " << path);
@@ -553,7 +553,7 @@ namespace {
ERROR(span, E0000, "Encountered enum at unexpected location in import");
}
const auto& name = nodes[i].name();
-
+
auto it2 = ::std::find_if( e.m_variants.begin(), e.m_variants.end(), [&](const auto& x){ return x.first == name; } );
if( it2 == e.m_variants.end() ) {
ERROR(span, E0000, "Unable to find variant " << path);
@@ -648,7 +648,7 @@ namespace {
)
}
}
-
+
return ::AST::PathBinding::make_Unbound({});
}
::AST::PathBinding Resolve_Use_GetBinding__ext(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, const AST::ExternCrate& ec, unsigned int start, Lookup allow)
@@ -660,20 +660,20 @@ namespace {
{
TRACE_FUNCTION_F(path);
//::AST::Path rv;
-
+
// If the path is directly referring to an external crate - call __ext
if( path.m_class.is_Absolute() && path.m_class.as_Absolute().crate != "" ) {
const auto& path_abs = path.m_class.as_Absolute();
-
+
return Resolve_Use_GetBinding__ext(span, crate, path, crate.m_extern_crates.at( path_abs.crate ), 0, allow);
}
-
+
const AST::Module* mod = &crate.m_root_module;
const auto& nodes = path.nodes();
for( unsigned int i = 0; i < nodes.size()-1; i ++ )
{
// TODO: If this came from an import, return the real path?
-
+
//rv = Resolve_Use_CanoniseAndBind_Mod(span, crate, *mod, mv$(rv), nodes[i].name(), parent_modules, Lookup::Type);
//const auto& b = rv.binding();
auto b = Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes[i].name(), parent_modules, Lookup::Type);
@@ -691,7 +691,7 @@ namespace {
if( i != nodes.size() - 1 ) {
ERROR(span, E0000, "Encountered enum at unexpected location in import");
}
-
+
const auto& node2 = nodes[i];
int variant_index = -1;
for( unsigned int j = 0; j < enum_.variants().size(); j ++ )
@@ -704,12 +704,12 @@ namespace {
if( variant_index < 0 ) {
ERROR(span, E0000, "Unknown enum variant '" << node2.name() << "'");
}
-
+
return ::AST::PathBinding::make_EnumVar({&enum_, static_cast<unsigned int>(variant_index)});
),
(Module,
ASSERT_BUG(span, e.module_ || e.hir, "nullptr module pointer in node " << i << " of " << path);
- if( !e.module_ )
+ if( !e.module_ )
{
assert(e.hir);
// TODO: Mangle the original path (or return a new path somehow)
@@ -719,7 +719,7 @@ namespace {
)
)
}
-
+
assert(mod);
return Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes.back().name(), parent_modules, allow);
}
diff --git a/src/serialise.cpp b/src/serialise.cpp
index 5c57da9f..e79d4025 100644
--- a/src/serialise.cpp
+++ b/src/serialise.cpp
@@ -146,13 +146,13 @@ size_t Deserialiser_TextTree::start_array()
char c = getc();
if( c != '[' )
throw DeserialiseFailure("start_array", "no [");
-
+
eat_ws();
if( peekc() == ']' ) {
DEBUG("len = 0");
return 0;
}
-
+
size_t len;
m_is >> len;
if( !m_is.good() )
@@ -218,13 +218,13 @@ void Deserialiser_TextTree::item(double& v)
void Deserialiser_TextTree::item(::std::string& s)
{
eat_ws();
-
+
::std::string rv;
char c = getc();
DEBUG("c = '"<<c<<"'");
if( c != '"' )
throw DeserialiseFailure("item(::std::string)", "no open \"");
-
+
while(peekc() != '"')
{
char c = getc();
@@ -233,7 +233,7 @@ void Deserialiser_TextTree::item(::std::string& s)
rv.push_back(c);
}
getc(); // eat "
-
+
DEBUG("rv = '"<<rv<<"'");
s = rv;
}
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp
index 3f188dbf..28b8501c 100644
--- a/src/trans/codegen.cpp
+++ b/src/trans/codegen.cpp
@@ -18,7 +18,7 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
{
static Span sp;
auto codegen = Trans_Codegen_GetGeneratorC(crate, outfile);
-
+
// 1. Emit structure/type definitions.
// - Emit in the order they're needed.
for(const auto& ty : list.m_types)
@@ -40,7 +40,7 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
)
codegen->emit_type(ty);
}
-
+
// 2. Emit function prototypes
for(const auto& ent : list.m_functions)
{
@@ -59,7 +59,7 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
DEBUG("STATIC " << ent.first);
assert(ent.second->ptr);
const auto& stat = *ent.second->ptr;
-
+
if( stat.m_value_res.is_Invalid() )
{
codegen->emit_static_ext(ent.first, stat, ent.second->pp);
@@ -69,17 +69,17 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
codegen->emit_static_local(ent.first, stat, ent.second->pp);
}
}
-
+
for(const auto& ent : list.m_vtables)
{
const auto& trait = ent.first.m_data.as_UfcsKnown().trait;
const auto& type = *ent.first.m_data.as_UfcsKnown().type;
DEBUG("VTABLE " << trait << " for " << type);
-
+
codegen->emit_vtable(ent.first, crate.get_trait_by_path(Span(), trait.m_path));
}
-
-
+
+
// 4. Emit function code
for(const auto& ent : list.m_functions)
{
@@ -109,7 +109,7 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
}
}
}
-
+
codegen->finalise();
}
diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp
index b93f9d5d..e14a8e81 100644
--- a/src/trans/codegen.hpp
+++ b/src/trans/codegen.hpp
@@ -13,7 +13,7 @@ namespace HIR {
class TypeRef;
class Path;
class GenericPath;
-
+
class Function;
class Static;
}
@@ -27,22 +27,22 @@ class CodeGenerator
public:
virtual ~CodeGenerator() {}
virtual void finalise() {}
-
+
// Called on all types directly mentioned (e.g. variables, arguments, and fields)
// - Inner-most types are visited first.
virtual void emit_type(const ::HIR::TypeRef& ) {}
-
+
// Called when a TypeRef::Path is encountered (after visiting inner types)
virtual void emit_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) {}
virtual void emit_union(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Union& item) {}
virtual void emit_enum(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Enum& item) {}
-
+
virtual void emit_vtable(const ::HIR::Path& p, const ::HIR::Trait& trait) {}
-
+
virtual void emit_static_ext(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {}
virtual void emit_static_proto(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {}
virtual void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {}
-
+
virtual void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) {}
virtual void emit_function_proto(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) {}
virtual void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, const ::MIR::FunctionPointer& code) {}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 0552d118..37acb33b 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -23,7 +23,7 @@ namespace {
Slice,
TraitObject,
};
-
+
const ::HIR::Crate& m_crate;
::StaticTraitResolve m_resolve;
::std::ofstream m_of;
@@ -55,7 +55,7 @@ namespace {
<< "\n"
;
}
-
+
~CodeGenerator_C() {}
void finalise() override
@@ -67,7 +67,7 @@ namespace {
<< ");\n"
<< "}\n";
}
-
+
void emit_type(const ::HIR::TypeRef& ty) override
{
TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Tuple, te,
@@ -109,10 +109,10 @@ namespace {
)
else {
}
-
+
m_of << "tTYPEID __typeid_" << Trans_Mangle(ty) << ";\n";
}
-
+
void emit_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) override
{
::HIR::TypeRef tmp;
@@ -179,25 +179,25 @@ namespace {
m_of << "\treturn rv;\n";
m_of << "}\n";
)
-
+
auto struct_ty = ::HIR::TypeRef(p.clone(), &item);
auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue");
auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone());
::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, {}, *(::MIR::Function*)nullptr };
m_mir_res = &mir_res;
// - Drop Glue
-
+
if( item.m_markings.has_drop_impl ) {
m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(struct s_" << Trans_Mangle(p) << "*rv);\n";
}
-
+
m_of << "void " << Trans_Mangle(drop_glue_path) << "(struct s_" << Trans_Mangle(p) << "* rv) {\n";
-
+
// If this type has an impl of Drop, call that impl
if( item.m_markings.has_drop_impl ) {
m_of << "\t" << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(rv);\n";
}
-
+
auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) });
auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 });
TU_MATCHA( (item.m_data), (e),
@@ -208,7 +208,7 @@ namespace {
{
const auto& fld = e[i];
fld_lv.as_Field().field_index = i;
-
+
emit_destructor_call(fld_lv, monomorph(fld.ent), true);
}
),
@@ -217,7 +217,7 @@ namespace {
{
const auto& fld = e[i].second;
fld_lv.as_Field().field_index = i;
-
+
emit_destructor_call(fld_lv, monomorph(fld.ent), true);
}
)
@@ -277,9 +277,9 @@ namespace {
}
m_of << "\t} DATA;\n";
m_of << "};\n";
-
+
// TODO: Constructors for tuple variants
-
+
// ---
// - Drop Glue
// ---
@@ -288,24 +288,24 @@ namespace {
auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone());
::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, {}, *(::MIR::Function*)nullptr };
m_mir_res = &mir_res;
-
-
+
+
if( item.m_markings.has_drop_impl )
{
m_of << "void " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(struct e_" << Trans_Mangle(p) << "*rv);\n";
}
-
+
m_of << "void " << Trans_Mangle(drop_glue_path) << "(struct e_" << Trans_Mangle(p) << "* rv) {\n";
-
+
// If this type has an impl of Drop, call that impl
if( item.m_markings.has_drop_impl )
{
m_of << "\t" << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(rv);\n";
}
-
+
auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) });
auto fld_lv = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Downcast({ box$(self), 0 })), 0 });
-
+
m_of << "\tswitch(rv->TAG) {\n";
for(unsigned int var_idx = 0; var_idx < item.m_variants.size(); var_idx ++)
{
@@ -323,7 +323,7 @@ namespace {
{
fld_lv.as_Field().field_index = i;
const auto& fld = e[i];
-
+
emit_destructor_call(fld_lv, monomorph(fld.ent), false);
}
m_of << "\tbreak;\n";
@@ -343,7 +343,7 @@ namespace {
m_of << "\t}\n";
m_of << "}\n";
}
-
+
void emit_static_ext(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) override
{
TRACE_FUNCTION_F(p);
@@ -357,7 +357,7 @@ namespace {
void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) override
{
TRACE_FUNCTION_F(p);
-
+
auto type = params.monomorph(m_crate, item.m_type);
emit_ctype( type, FMT_CB(ss, ss << Trans_Mangle(p);) );
m_of << " = ";
@@ -481,13 +481,13 @@ namespace {
)
)
}
-
+
void emit_vtable(const ::HIR::Path& p, const ::HIR::Trait& trait) override
{
static Span sp;
const auto& trait_path = p.m_data.as_UfcsKnown().trait;
const auto& type = *p.m_data.as_UfcsKnown().type;
-
+
{
auto vtable_sp = trait_path.m_path;
vtable_sp.m_components.back() += "#vtable";
@@ -499,13 +499,13 @@ namespace {
}
const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_sp);
::HIR::TypeRef vtable_ty( ::HIR::GenericPath(mv$(vtable_sp), mv$(vtable_params)), &vtable_ref );
-
+
emit_ctype(vtable_ty);
m_of << " " << Trans_Mangle(p) << " = {\n";
}
auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr);
-
+
// TODO: Alignment and destructor
for(unsigned int i = 0; i < trait.m_value_indexes.size(); i ++ )
{
@@ -515,10 +515,10 @@ namespace {
{
if( m.second.first != i )
continue ;
-
+
//ASSERT_BUG(sp, tr.m_values.at(m.first).is_Function(), "TODO: Handle generating vtables with non-function items");
DEBUG("- " << m.second.first << " = " << m.second.second << " :: " << m.first);
-
+
auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false);
// NOTE: `void*` cast avoids mismatched pointer type errors due to the receiver being &mut()/&() in the vtable
m_of << "\t(void*)" << Trans_Mangle( ::HIR::Path(type.clone(), mv$(gpath), m.first) );
@@ -527,7 +527,7 @@ namespace {
m_of << "\n";
m_of << "\t};\n";
}
-
+
void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) override
{
m_of << "// extern \"" << item.m_abi << "\" " << p << "\n";
@@ -552,12 +552,12 @@ namespace {
{
static Span sp;
TRACE_FUNCTION_F(p);
-
+
::MIR::TypeResolve::args_t arg_types;
for(const auto& ent : item.m_args)
arg_types.push_back(::std::make_pair( ::HIR::Pattern{}, params.monomorph(m_crate, ent.second) ));
::HIR::TypeRef ret_type = params.monomorph(m_crate, item.m_return);
-
+
::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << p;), ret_type, arg_types, *code };
m_mir_res = &mir_res;
@@ -582,15 +582,15 @@ namespace {
for(unsigned int i = 0; i < code->blocks.size(); i ++)
{
TRACE_FUNCTION_F(p << " bb" << i);
-
+
if( code->blocks[i].statements.size() == 0 && code->blocks[i].terminator.is_Diverge() ) {
DEBUG("- Diverge only, omitting");
m_of << "bb" << i << ": _Unwind_Resume(); // Diverge\n";
continue ;
}
-
+
m_of << "bb" << i << ":\n";
-
+
for(const auto& stmt : code->blocks[i].statements)
{
mir_res.set_cur_stmt(i, (&stmt - &code->blocks[i].statements.front()));
@@ -601,7 +601,7 @@ namespace {
// TODO: Emit destructor calls
::HIR::TypeRef tmp;
const auto& ty = mir_res.get_lvalue_type(tmp, e.slot);
-
+
if( e.kind == ::MIR::eDropKind::SHALLOW ) {
// TODO: Shallow drops are only valid on owned_box
}
@@ -665,7 +665,7 @@ namespace {
m_of << "\\" << (unsigned int)v;
}
m_of << "\"" << ::std::dec;
-
+
m_of << ";\n\t";
emit_lvalue(e.dst);
m_of << ".META = " << c.size();
@@ -729,7 +729,7 @@ namespace {
m_of << "/* PhandomData cast */\n";
continue ;
}
-
+
emit_lvalue(e.dst);
m_of << " = ";
m_of << "("; emit_ctype(ve.type); m_of << ")";
@@ -771,7 +771,7 @@ namespace {
case ::MIR::eBinOp::MUL: m_of << " * "; break;
case ::MIR::eBinOp::DIV: m_of << " / "; break;
case ::MIR::eBinOp::MOD: m_of << " % "; break;
-
+
case ::MIR::eBinOp::BIT_OR: m_of << " | "; break;
case ::MIR::eBinOp::BIT_AND: m_of << " & "; break;
case ::MIR::eBinOp::BIT_XOR: m_of << " ^ "; break;
@@ -783,7 +783,7 @@ namespace {
case ::MIR::eBinOp::GE: m_of << " >= "; break;
case ::MIR::eBinOp::LT: m_of << " < " ; break;
case ::MIR::eBinOp::LE: m_of << " <= "; break;
-
+
case ::MIR::eBinOp::ADD_OV:
case ::MIR::eBinOp::SUB_OV:
case ::MIR::eBinOp::MUL_OV:
@@ -857,14 +857,14 @@ namespace {
if(ve.vals.size() > 0)
m_of << ";\n\t";
}
-
+
for(unsigned int j = 0; j < ve.vals.size(); j ++)
{
// HACK: Don't emit assignment of PhantomData
::HIR::TypeRef tmp;
if( m_resolve.is_type_phantom_data( mir_res.get_lvalue_type(tmp, ve.vals[j])) )
continue ;
-
+
if( j != 0 ) m_of << ";\n\t";
emit_lvalue(e.dst);
if(ve.variant_idx != ~0u)
@@ -879,7 +879,7 @@ namespace {
m_of << "\n";
}
}
-
+
mir_res.set_cur_stmt_term(i);
DEBUG("- " << code->blocks[i].terminator);
TU_MATCHA( (code->blocks[i].terminator), (e),
@@ -913,7 +913,7 @@ namespace {
{
const auto& name = e.fcn.as_Intrinsic().name;
const auto& params = e.fcn.as_Intrinsic().params;
-
+
struct H {
static const char* get_atomic_ordering(const ::MIR::TypeResolve& mir_res, const ::std::string& name, size_t prefix_len) {
if( name.size() < prefix_len )
@@ -1120,7 +1120,7 @@ namespace {
m_of << "\tgoto bb" << e.ret_block << ";\n";
break ;
}
-
+
TU_MATCHA( (e.fcn), (e2),
(Value,
{
@@ -1199,7 +1199,7 @@ namespace {
}
));
}
-
+
void emit_destructor_call(const ::MIR::LValue& slot, const ::HIR::TypeRef& ty, bool unsized_valid)
{
TU_MATCHA( (ty.m_data), (te),
@@ -1209,7 +1209,7 @@ namespace {
(ErasedType, ),
(Closure, ),
(Generic, ),
-
+
// Nothing
(Primitive,
),
@@ -1267,7 +1267,7 @@ namespace {
)
)
}
-
+
const ::HIR::Literal& get_literal_for_const(const ::HIR::Path& path)
{
TU_MATCHA( (path.m_data), (pe),
@@ -1288,7 +1288,7 @@ namespace {
)
throw "";
}
-
+
void assign_from_literal(::std::function<void()> emit_dst, const ::HIR::TypeRef& ty, const ::HIR::Literal& lit)
{
//TRACE_FUNCTION_F("ty=" << ty << ", lit=" << lit);
@@ -1440,7 +1440,7 @@ namespace {
)
)
}
-
+
void emit_lvalue(const ::MIR::LValue& val) {
TU_MATCHA( (val), (e),
(Variable,
@@ -1543,10 +1543,10 @@ namespace {
case ::HIR::CoreType::I32: m_of << "int32_t"; break;
case ::HIR::CoreType::U64: m_of << "uint64_t"; break;
case ::HIR::CoreType::I64: m_of << "int64_t"; break;
-
+
case ::HIR::CoreType::F32: m_of << "float"; break;
case ::HIR::CoreType::F64: m_of << "double"; break;
-
+
case ::HIR::CoreType::Bool: m_of << "bool"; break;
case ::HIR::CoreType::Char: m_of << "CHAR"; break;
case ::HIR::CoreType::Str:
@@ -1619,7 +1619,7 @@ namespace {
)
)
}
-
+
MetadataType metadata_type(const ::HIR::TypeRef& ty)
{
if( ty == ::HIR::CoreType::Str || ty.m_data.is_Slice() ) {
@@ -1658,7 +1658,7 @@ namespace {
return MetadataType::None;
}
}
-
+
void emit_ctype_ptr(const ::HIR::TypeRef& inner_ty, ::FmtLambda inner) {
if( inner_ty.m_data.is_Array() ) {
emit_ctype(inner_ty, FMT_CB(ss, ss << "(*" << inner << ")";));
@@ -1679,7 +1679,7 @@ namespace {
}
}
}
-
+
int is_dst(const ::HIR::TypeRef& ty) const
{
if( ty == ::HIR::CoreType::Str )
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index dc886f50..78270b7b 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -27,35 +27,35 @@ void Trans_Enumerate_FillFrom_Literal(TransList& out, const ::HIR::Crate& crate,
TransList Trans_Enumerate_Main(const ::HIR::Crate& crate)
{
static Span sp;
-
+
TransList rv;
-
+
// "start" language item
// - Takes main, and argc/argv as arguments
{
auto start_path = crate.get_lang_item_path(sp, "start");
const auto& fcn = crate.get_function_by_path(sp, start_path);
-
+
auto* ptr = rv.add_function(start_path);
assert(ptr);
Trans_Enumerate_FillFrom(rv, crate, fcn, *ptr);
}
-
+
// user entrypoint
{
auto main_path = ::HIR::SimplePath("", {"main"});
const auto& fcn = crate.get_function_by_path(sp, main_path);
-
+
auto* ptr = rv.add_function(main_path);
assert(ptr);
Trans_Enumerate_FillFrom(rv, crate, fcn, *ptr);
}
-
+
// TODO: Search the trans list for external functions that refer to a named symbol, search for that defined elsewhere.
// - Not needed yet, there's a slow hack elsewhere
Trans_Enumerate_Types(rv, crate);
-
+
return rv;
}
@@ -97,11 +97,11 @@ namespace {
TransList Trans_Enumerate_Public(const ::HIR::Crate& crate)
{
TransList rv;
-
+
Trans_Enumerate_Public_Mod(rv, crate, crate.m_root_module, ::HIR::SimplePath("",{}));
-
+
Trans_Enumerate_Types(rv, crate);
-
+
return rv;
}
@@ -111,22 +111,22 @@ namespace {
template<typename T>
bool operator()(const T* lhs, const T* rhs) const { return *lhs < *rhs; }
};
-
+
struct TypeVisitor
{
const ::HIR::Crate& m_crate;
::StaticTraitResolve m_resolve;
::std::vector< ::HIR::TypeRef>& out_list;
-
+
::std::set< ::HIR::TypeRef> visited;
::std::set< const ::HIR::TypeRef*, PtrComp> active_set;
-
+
TypeVisitor(const ::HIR::Crate& crate, ::std::vector< ::HIR::TypeRef>& out_list):
m_crate(crate),
m_resolve(crate),
out_list(out_list)
{}
-
+
void visit_struct(const ::HIR::GenericPath& path, const ::HIR::Struct& item) {
static Span sp;
::HIR::TypeRef tmp;
@@ -188,19 +188,19 @@ namespace {
)
}
}
-
+
void visit_type(const ::HIR::TypeRef& ty)
{
// Already done
if( visited.find(ty) != visited.end() )
return ;
-
+
if( active_set.find(&ty) != active_set.end() ) {
// TODO: Handle recursion
return ;
}
active_set.insert( &ty );
-
+
TU_MATCHA( (ty.m_data), (te),
// Impossible
(Infer,
@@ -236,7 +236,7 @@ namespace {
static Span sp;
// Ensure that the data trait's vtable is present
const auto& trait = *te.m_trait.m_trait_ptr;
-
+
auto vtable_ty_spath = te.m_trait.m_path.m_path;
vtable_ty_spath.m_components.back() += "#vtable";
const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_ty_spath);
@@ -249,8 +249,8 @@ namespace {
vtable_params.m_types.resize(idx+1);
vtable_params.m_types[idx] = ty_b.second.clone();
}
-
-
+
+
visit_type( ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref ) );
),
(Array,
@@ -276,7 +276,7 @@ namespace {
)
)
active_set.erase( active_set.find(&ty) );
-
+
visited.insert( ty.clone() );
out_list.push_back( ty.clone() );
DEBUG("Add type " << ty);
@@ -299,11 +299,11 @@ void Trans_Enumerate_Types(TransList& out, const ::HIR::Crate& crate)
assert(ent.second->ptr);
const auto& fcn = *ent.second->ptr;
const auto& pp = ent.second->pp;
-
+
tv.visit_type( pp.monomorph(crate, fcn.m_return) );
for(const auto& arg : fcn.m_args)
tv.visit_type( pp.monomorph(crate, arg.second) );
-
+
if( fcn.m_code.m_mir )
{
const auto& mir = *fcn.m_code.m_mir;
@@ -319,10 +319,10 @@ void Trans_Enumerate_Types(TransList& out, const ::HIR::Crate& crate)
assert(ent.second->ptr);
const auto& stat = *ent.second->ptr;
const auto& pp = ent.second->pp;
-
+
tv.visit_type( pp.monomorph(crate, stat.m_type) );
}
-
+
constructors_added = false;
for(unsigned int i = types_count; i < out.m_types.size(); i ++ )
{
@@ -345,12 +345,12 @@ void Trans_Enumerate_Types(TransList& out, const ::HIR::Crate& crate)
)
)
ASSERT_BUG(Span(), markings_ptr, "Path binding not set correctly - " << ty);
-
+
if( markings_ptr->has_drop_impl )
{
// Add the Drop impl to the codegen list
Trans_Enumerate_FillFrom_Path(out, crate, ::HIR::Path( ty.clone(), crate.get_lang_item_path(Span(), "drop"), "drop"), {});
-
+
constructors_added = true;
}
}
@@ -377,7 +377,7 @@ namespace {
else {
mod = &crate.m_root_module;
}
-
+
for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
{
const auto& pc = path.m_components[i];
@@ -399,12 +399,12 @@ namespace {
)
)
}
-
+
auto it = mod->m_value_items.find( path.m_components.back() );
if( it == mod->m_value_items.end() ) {
return EntPtr {};
}
-
+
TU_MATCH( ::HIR::ValueItem, (it->second->ent), (e),
(Import,
),
@@ -430,7 +430,7 @@ namespace {
{
TRACE_FUNCTION_F(path);
StaticTraitResolve resolve { crate };
-
+
TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
(Generic,
return get_ent_simplepath(sp, crate, e.m_path);
@@ -463,13 +463,13 @@ namespace {
),
(UfcsKnown,
EntPtr rv;
-
+
// Obtain trait pointer (for default impl and to know what the item type is)
const auto& trait_ref = crate.get_trait_by_path(sp, e.trait.m_path);
auto trait_vi_it = trait_ref.m_values.find(e.item);
ASSERT_BUG(sp, trait_vi_it != trait_ref.m_values.end(), "Couldn't find item " << e.item << " in trait " << e.trait.m_path);
const auto& trait_vi = trait_vi_it->second;
-
+
bool is_dynamic = false;
::std::vector<::HIR::TypeRef> best_impl_params;
const ::HIR::TraitImpl* best_impl = nullptr;
@@ -485,7 +485,7 @@ namespace {
const auto& impl_ref_e = impl_ref.m_data.as_TraitImpl();
const auto& impl = *impl_ref_e.impl;
ASSERT_BUG(sp, impl.m_trait_args.m_types.size() == e.trait.m_params.m_types.size(), "Trait parameter count mismatch " << impl.m_trait_args << " vs " << e.trait.m_params);
-
+
if( best_impl == nullptr || impl.more_specific_than(*best_impl) ) {
best_impl = &impl;
bool is_spec = false;
@@ -529,7 +529,7 @@ namespace {
const auto& impl = *best_impl;
impl_pp.m_types = mv$(best_impl_params);
-
+
TU_MATCHA( (trait_vi), (ve),
(Constant, TODO(sp, "Associated constant"); ),
(Static,
@@ -784,7 +784,7 @@ void Trans_Enumerate_FillFrom_VTable(TransList& out, const ::HIR::Crate& crate,
const auto& type = *vtable_path.m_data.as_UfcsKnown().type;
const auto& trait_path = vtable_path.m_data.as_UfcsKnown().trait;
const auto& tr = crate.get_trait_by_path(Span(), trait_path.m_path);
-
+
auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr);
for(const auto& m : tr.m_value_indexes)
{
@@ -832,7 +832,7 @@ namespace {
}
)
}
-
+
for(const auto& ti : mod.m_mod_items)
{
TU_IFLET( ::HIR::TypeItem, ti.second->ent, Module, i,
@@ -840,7 +840,7 @@ namespace {
return rv;
)
}
-
+
return nullptr;
}
::HIR::Function* find_function_by_link_name(const ::HIR::Crate& crate, const char* name, ::HIR::SimplePath& out_path)
diff --git a/src/trans/mangling.cpp b/src/trans/mangling.cpp
index ef41abed..c14b1b29 100644
--- a/src/trans/mangling.cpp
+++ b/src/trans/mangling.cpp
@@ -187,7 +187,7 @@ namespace {
BUG(Span(), "Closure during trans - " << ty);
)
)
-
+
throw "";
}
diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp
index d129eae9..03623855 100644
--- a/src/trans/monomorphise.cpp
+++ b/src/trans/monomorphise.cpp
@@ -60,9 +60,9 @@ namespace {
{
static Span sp;
TRACE_FUNCTION;
-
+
::MIR::Function output;
-
+
// 1. Monomorphise locals and temporaries
output.named_variables.reserve( tpl->named_variables.size() );
for(const auto& var : tpl->named_variables)
@@ -76,13 +76,13 @@ namespace {
DEBUG("- var" << output.temporaries.size());
output.temporaries.push_back( params.monomorph(crate, ty) );
}
-
+
// 2. Monomorphise all paths
output.blocks.reserve( tpl->blocks.size() );
for(const auto& block : tpl->blocks)
{
::std::vector< ::MIR::Statement> statements;
-
+
TRACE_FUNCTION_F("bb" << output.blocks.size());
statements.reserve( block.statements.size() );
for(const auto& stmt : block.statements)
@@ -101,7 +101,7 @@ namespace {
{
const auto& e = stmt.as_Assign();
DEBUG("- " << e.dst << " = " << e.src);
-
+
::MIR::RValue rval;
TU_MATCHA( (e.src), (se),
(Use,
@@ -213,16 +213,16 @@ namespace {
});
)
)
-
+
statements.push_back( ::MIR::Statement::make_Assign({
monomorph_LValue(crate, params, e.dst),
mv$(rval)
}) );
}
}
-
+
::MIR::Terminator terminator;
-
+
DEBUG("> " << block.terminator);
TU_MATCHA( (block.terminator), (e),
(Incomplete,
@@ -278,9 +278,9 @@ namespace {
});
)
)
-
+
output.blocks.push_back( ::MIR::BasicBlock { mv$(statements), mv$(terminator) } );
}
-
+
return ::MIR::FunctionPointer( box$(output).release() );
}
diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp
index 0ff2745c..e80a2b6e 100644
--- a/src/trans/trans_list.hpp
+++ b/src/trans/trans_list.hpp
@@ -23,18 +23,18 @@ struct Trans_Params
::HIR::PathParams pp_method;
::HIR::PathParams pp_impl;
::HIR::TypeRef self_type;
-
+
Trans_Params() {}
Trans_Params(const Span& sp):
sp(sp)
{}
-
+
t_cb_generic get_cb() const;
::HIR::TypeRef monomorph(const ::HIR::Crate& crate, const ::HIR::TypeRef& p) const;
::HIR::Path monomorph(const ::HIR::Crate& crate, const ::HIR::Path& p) const;
::HIR::GenericPath monomorph(const ::HIR::Crate& crate, const ::HIR::GenericPath& p) const;
::HIR::PathParams monomorph(const ::HIR::Crate& crate, const ::HIR::PathParams& p) const;
-
+
bool has_types() const {
return pp_method.m_types.size() > 0 || pp_impl.m_types.size() > 0;
}
@@ -57,7 +57,7 @@ public:
::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Function> > m_functions;
::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Static> > m_statics;
::std::map< ::HIR::Path, Trans_Params> m_vtables;
-
+
::std::vector< ::HIR::TypeRef> m_types;
TransList_Function* add_function(::HIR::Path p);