diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 4 | ||||
-rw-r--r-- | src/hir/hir.cpp | 6 | ||||
-rw-r--r-- | src/hir/hir.hpp | 6 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 4 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 154 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 24 |
6 files changed, 150 insertions, 48 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 4161cd09..fcfaeda1 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -910,6 +910,10 @@ namespace { { #define _(x, ...) case ::HIR::Literal::TAG_##x: return ::HIR::Literal::make_##x(__VA_ARGS__); _(List, deserialise_vec< ::HIR::Literal>() ) + _(Variant, { + static_cast<unsigned int>(read_count()), + deserialise_vec< ::HIR::Literal>() + }) _(Integer, read_u64() ) _(Float, read_double() ) _(BorrowOf, deserialise_path() ) diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index c2ad4d00..aa3344eb 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -15,6 +15,12 @@ namespace HIR { os << " " << val << ","; os << " ]"; ), + (Variant, + os << "#" << e.idx << ":["; + for(const auto& val : e.vals) + os << " " << val << ","; + os << " ]"; + ), (Integer, os << e; ), diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index b1f18fcf..5c7f5a30 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -49,6 +49,12 @@ TAGGED_UNION(Literal, Invalid, (Invalid, struct {}), // List = Array, Tuple, struct literal (List, ::std::vector<Literal>), // TODO: Have a variant for repetition lists + // Variant = Enum variant + (Variant, struct { + unsigned int idx; + ::std::vector<Literal> vals; + }), + // Literal values (Integer, uint64_t), (Float, double), (BorrowOf, ::HIR::Path), diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 6a74d348..0b581a27 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -466,6 +466,10 @@ namespace { (List, serialise_vec(e); ), + (Variant, + write_count(e.idx); + serialise_vec(e.vals); + ), (Integer, write_u64(e); ), diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 909c70da..47a0db6d 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -41,6 +41,13 @@ namespace { } return ::HIR::Literal( mv$(vals) ); ), + (Variant, + ::std::vector< ::HIR::Literal> vals; + for(const auto& val : e.vals) { + vals.push_back( clone_literal(val) ); + } + return ::HIR::Literal::make_Variant({ e.idx, mv$(vals) }); + ), (Integer, return ::HIR::Literal(e); ), @@ -194,16 +201,6 @@ namespace { TODO(sp, "Could not find function for " << path << " - " << rv.tag_str()); } } - const ::HIR::Struct& get_struct(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path) - { - auto rv = get_ent_fullpath(sp, crate, path, EntNS::Type); - TU_IFLET( EntPtr, rv, Struct, e, - return *e; - ) - else { - TODO(sp, "Could not find struct for " << path << " - " << rv.tag_str()); - } - } ::HIR::Literal evaluate_constant_hir(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprNode& expr, ::std::vector< ::HIR::Literal> args) { @@ -421,16 +418,37 @@ namespace { } void visit(::HIR::ExprNode_TupleVariant& node) override { - if( ! node.m_is_struct ) { - TODO(node.span(), "_TupleVariant - Enum"); - } + ::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) ); } - m_rv = ::HIR::Literal::make_List(mv$(vals)); + + 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)); + } + else + { + const auto& varname = node.m_path.m_path.m_components.back(); + auto tmp_path = node.m_path.m_path; + tmp_path.m_components.pop_back(); + 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(); + + m_rv = ::HIR::Literal::make_Variant({var_idx, mv$(vals)}); + } } void visit(::HIR::ExprNode_CallPath& node) override { TRACE_FUNCTION_FR("_CallPath - " << node.m_path, m_rv); @@ -495,7 +513,29 @@ namespace { ) } void visit(::HIR::ExprNode_UnitVariant& node) override { - TODO(node.span(), "Unit varant/struct constructors in constant context"); + 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(), "_UnitVariant with m_is_struct set pointing to " << ent.tag_str()); + //const auto& str = ent.as_Struct(); + + m_rv = ::HIR::Literal::make_List({}); + } + else + { + const auto& varname = node.m_path.m_path.m_components.back(); + auto tmp_path = node.m_path.m_path; + tmp_path.m_components.pop_back(); + 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(); + + m_rv = ::HIR::Literal::make_Variant({var_idx, {}}); + } } void visit(::HIR::ExprNode_PathValue& node) override { TRACE_FUNCTION_FR("_PathValue - " << node.m_path, m_rv); @@ -541,37 +581,49 @@ namespace { void visit(::HIR::ExprNode_StructLiteral& node) override { TRACE_FUNCTION_FR("_StructLiteral - " << node.m_path, m_rv); - const auto& str = get_struct(node.span(), m_crate, node.m_path.m_path); - const auto& fields = str.m_data.as_Named(); - ::std::vector< ::HIR::Literal> vals; - if( node.m_base_value ) { - node.m_base_value->visit(*this); - auto base_val = mv$(m_rv); - if( !base_val.is_List() || base_val.as_List().size() != fields.size() ) { - BUG(node.span(), "Struct literal base value had an incorrect field count"); + // TODO: Fix for enums - see _UnitVariant and _TupleVariant + const auto& ent = m_crate.get_typeitem_by_path(node.span(), node.m_path.m_path); + TU_IFLET( ::HIR::TypeItem, ent, Struct, str, + ASSERT_BUG(node.span(), node.m_is_struct, "_StructLiteral with m_is_struct clear pointing to a struct"); + const auto& fields = str.m_data.as_Named(); + + ::std::vector< ::HIR::Literal> vals; + if( node.m_base_value ) { + node.m_base_value->visit(*this); + auto base_val = mv$(m_rv); + if( !base_val.is_List() || base_val.as_List().size() != fields.size() ) { + BUG(node.span(), "Struct literal base value had an incorrect field count"); + } + vals = mv$(base_val.as_List()); } - vals = mv$(base_val.as_List()); - } - else { - vals.resize( fields.size() ); - } - for( const auto& val_set : node.m_values ) { - unsigned int idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& v) { return v.first == val_set.first; } ) - fields.begin(); - if( idx == fields.size() ) { - ERROR(node.span(), E0000, "Field name " << val_set.first << " isn't a member of " << node.m_path); + else { + vals.resize( fields.size() ); } - val_set.second->visit(*this); - vals[idx] = mv$(m_rv); - } - for( unsigned int i = 0; i < vals.size(); i ++ ) { - const auto& val = vals[i]; - if( val.is_Invalid() ) { - ERROR(node.span(), E0000, "Field " << fields[i].first << " wasn't set"); + for( const auto& val_set : node.m_values ) { + unsigned int idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& v) { return v.first == val_set.first; } ) - fields.begin(); + if( idx == fields.size() ) { + ERROR(node.span(), E0000, "Field name " << val_set.first << " isn't a member of " << node.m_path); + } + val_set.second->visit(*this); + vals[idx] = mv$(m_rv); + } + for( unsigned int i = 0; i < vals.size(); i ++ ) { + const auto& val = vals[i]; + if( val.is_Invalid() ) { + ERROR(node.span(), E0000, "Field " << fields[i].first << " wasn't set"); + } } - } - m_rv = ::HIR::Literal::make_List(mv$(vals)); + m_rv = ::HIR::Literal::make_List(mv$(vals)); + ) + else TU_IFLET( ::HIR::TypeItem, ent, Enum, enm, + ASSERT_BUG(node.span(), !node.m_is_struct, "_StructLiteral with m_is_struct set pointing to an enum"); + TODO(node.span(), "Handle Enum _UnitVariant - " << node.m_path); + ) + else { + BUG(node.span(), "Could not find struct/enum for " << node.m_path << " - " << ent.tag_str()); + } } void visit(::HIR::ExprNode_Tuple& node) override { ::std::vector< ::HIR::Literal> vals; @@ -762,6 +814,7 @@ namespace { uint64_t mask; switch(te) { + // Integers mask down case ::HIR::CoreType::I8: case ::HIR::CoreType::U8: mask = 0xFF; @@ -791,6 +844,15 @@ namespace { default: TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval); } + ), + // Allow casting any integer value to a pointer (TODO: Ensure that the pointer is sized?) + (Pointer, + TU_IFLET( ::HIR::Literal, inval, Integer, i, + val = ::HIR::Literal(i); + ) + else { + BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type); + } ) ) ), @@ -932,6 +994,7 @@ namespace { void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override { visit_type(item.m_type); + assert(item.m_value); item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }, item.m_value, {}); DEBUG("constant: " << item.m_type << " = " << item.m_value_res); visit_expr(item.m_value); @@ -939,9 +1002,12 @@ namespace { void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override { visit_type(item.m_type); - item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }, item.m_value, {}); - DEBUG("static: " << item.m_type << " = " << item.m_value_res); - visit_expr(item.m_value); + if( item.m_value ) + { + item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }, item.m_value, {}); + DEBUG("static: " << item.m_type << " = " << item.m_value_res); + visit_expr(item.m_value); + } } void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override { for(auto& var : item.m_variants) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 6af70d30..8b4cc3a1 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1999,8 +1999,17 @@ namespace { } void visit(::HIR::ExprNode_CallValue& node) override { const auto& sp = node.span(); - const auto& ty = this->context.get_type(node.m_value->m_res_type); - TRACE_FUNCTION_F("CallValue: ty=" << ty); + const auto& ty_o = this->context.get_type(node.m_value->m_res_type); + TRACE_FUNCTION_F("CallValue: ty=" << ty_o); + + unsigned int deref_count = 0; + const auto* ty_p = &ty_o; + while(ty_p->m_data.is_Borrow()) + { + deref_count ++; + ty_p = &this->context.get_type(*ty_p->m_data.as_Borrow().inner); + } + const auto& ty = *ty_p; TU_MATCH_DEF(decltype(ty.m_data), (ty.m_data), (e), ( @@ -2099,8 +2108,9 @@ namespace { node.m_trait_used = ::HIR::ExprNode_CallValue::TraitUsed::Fn; ), (Borrow, - // TODO: Locate trait impl via borrow - TODO(sp, "CallValue on an &-ptr"); + // - Check inner (recursively) + // > use upper + TODO(sp, "CallValue on an &-ptr - " << ty); return ; ), (Infer, @@ -2108,6 +2118,12 @@ namespace { return ; ) ) + + if( deref_count > 0 ) + { + TODO(sp, "Insert autoderef for CallValue (" << deref_count << " needed) - " << ty << " and " << ty_o); + } + assert( node.m_arg_types.size() == node.m_args.size() + 1 ); for(unsigned int i = 0; i < node.m_args.size(); i ++) { |