diff --git a/src/Val.cc b/src/Val.cc index aa71d5e739..c20b1e0376 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3653,6 +3653,50 @@ VectorValPtr VectorVal::Order(Func* cmp_func) return result_v; } +bool VectorVal::Concretize(const TypePtr& t) + { + if ( ! any_yield ) + // Could do a same_type() call here, but really this case + // shouldn't happen in any case. + return yield_type->Tag() == t->Tag(); + + if ( ! vector_val ) + // Trivially concretized. + return true; + + auto n = vector_val->size(); + for ( auto i = 0U; i < n; ++i ) + { + auto& v = (*vector_val)[i]; + if ( ! v ) + // Vector hole does not require concretization. + continue; + + auto& vt_i = yield_types ? (*yield_types)[i] : yield_type; + if ( vt_i->Tag() == TYPE_ANY ) + { // Do the concretization. + ValPtr any_v = {NewRef{}, v->AsAny()}; + auto& vt = any_v->GetType(); + if ( vt->Tag() != t->Tag() ) + return false; + + v = ZVal(any_v, t); + } + + else if ( vt_i->Tag() != t->Tag() ) + return false; + } + + // Require that this vector be treated consistently in the future. + yield_type = t; + managed_yield = ZVal::IsManagedType(yield_type); + delete yield_types; + yield_types = nullptr; + any_yield = false; + + return true; + } + unsigned int VectorVal::Resize(unsigned int new_num_elements) { unsigned int oldsize = vector_val->size(); diff --git a/src/Val.h b/src/Val.h index 00b7bf7a28..66810ce4c0 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1553,6 +1553,22 @@ public: */ VectorValPtr Order(Func* cmp_func = nullptr); + /** + * Ensures that the vector can be used as a "vector of t". In + * general, this is only relevant for objects that are typed as + * "vector of any", making sure that each element is in fact + * of type "t", and is internally represented as such so that + * this object can be used directly without any special-casing. + * + * Returns true if the object is compatible with "vector of t" + * (including if it's not a vector-of-any but instead already a + * vector-of-t), false if not compatible. + * @param t The yield type to concretize to. + * @return True if the object is compatible with vector-of-t, false + * if not. + */ + bool Concretize(const TypePtr& t); + ValPtr ValAt(unsigned int index) const { return At(index); } bool Has(unsigned int index) const