bool apply(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.hash() != b.hash()) return false; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); if (m_cache.check(a, b)) return true; switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) == const_name(b) && compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; }); case expr_kind::Meta: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)); case expr_kind::Local: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)) && (!CompareBinderInfo || local_pp_name(a) == local_pp_name(b)) && (!CompareBinderInfo || local_info(a) == local_info(b)); case expr_kind::App: check_system(); return apply(app_fn(a), app_fn(b)) && apply(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: check_system(); return apply(binding_domain(a), binding_domain(b)) && apply(binding_body(a), binding_body(b)) && (!CompareBinderInfo || binding_name(a) == binding_name(b)) && (!CompareBinderInfo || binding_info(a) == binding_info(b)); case expr_kind::Let: check_system(); return apply(let_type(a), let_type(b)) && apply(let_value(a), let_value(b)) && apply(let_body(a), let_body(b)) && (!CompareBinderInfo || let_name(a) == let_name(b)); case expr_kind::Sort: return sort_level(a) == sort_level(b); case expr_kind::Macro: check_system(); if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!apply(macro_arg(a, i), macro_arg(b, i))) return false; } return true; } lean_unreachable(); // LCOV_EXCL_LINE }
expr update_mlocal(expr const & e, expr const & new_type) { if (is_eqp(mlocal_type(e), new_type)) return e; else if (is_metavar(e)) return mk_metavar(mlocal_name(e), new_type, e.get_tag()); else return mk_local(mlocal_name(e), local_pp_name(e), new_type, local_info(e), e.get_tag()); }
unsigned hash_bi(expr const & e) { unsigned h = e.hash(); for_each(e, [&](expr const & e, unsigned) { if (is_binding(e)) { h = hash(h, hash(binding_name(e).hash(), binding_info(e).hash())); } else if (is_local(e)) { h = hash(h, hash(mlocal_name(e).hash(), local_info(e).hash())); return false; // do not visit type } else if (is_metavar(e)) { return false; // do not visit type } return true; }); return h; }
/* Collect (and sort) dependencies of collected parameters */ void collect_and_normalize_dependencies(buffer<expr> & norm_params) { name_map<expr> new_types; for (unsigned i = 0; i < m_params.size(); i++) { expr x = m_params[i]; expr new_type = collect(m_ctx.instantiate_mvars(m_ctx.infer(x))); new_types.insert(mlocal_name(x), new_type); } local_context const & lctx = m_ctx.lctx(); std::sort(m_params.begin(), m_params.end(), [&](expr const & l1, expr const & l2) { return lctx.get_local_decl(l1)->get_idx() < lctx.get_local_decl(l2)->get_idx(); }); for (unsigned i = 0; i < m_params.size(); i++) { expr x = m_params[i]; expr type = *new_types.find(mlocal_name(x)); expr new_type = replace_locals(type, i, m_params.data(), norm_params.data()); expr new_param = m_ctx.push_local(local_pp_name(x), new_type, local_info(x)); norm_params.push_back(new_param); } }
//------------------------------------------------------------------------------ // bool gosFX::Effect::Execute(ExecuteInfo *info) { Check_Object(this); Check_Pointer(info); Verify(IsExecuted()); gos_PushCurrentHeap(Heap); // //----------------------------------------------------- // If a new seed is provided, override the current seed //----------------------------------------------------- // if (info->m_seed != -1.0f) { Verify(info->m_seed>=0.0f && info->m_seed<1.0f); m_seed = info->m_seed; } // //-------------------------------------------- // Figure out the new age and clear the bounds //-------------------------------------------- // Stuff::Scalar age = m_age + static_cast<Stuff::Scalar>(info->m_time - m_lastRan) * m_ageRate; Verify(age >= 0.0f && age >= m_age); *info->m_bounds = Stuff::OBB::Identity; // //-------------------------------- // Update the effectToWorld matrix //-------------------------------- // Check_Object(info->m_parentToWorld); m_localToWorld.Multiply(m_localToParent, *info->m_parentToWorld); // //-------------------------------------------------- // Check to see if the top event needs to be handled //-------------------------------------------------- // Check_Object(m_specification); Event *event; while ((event = m_event.GetCurrent()) != NULL) { Check_Object(event); if (event->m_time > m_age) break; // //------------------------------------------------------------- // This event needs to go, so spawn and bump the effect pointer //------------------------------------------------------------- // unsigned flags = ExecuteFlag; if ((event->m_flags&SimulationModeMask) == ParentSimulationMode) { Verify((m_flags&SimulationModeMask) != ParentSimulationMode); flags |= m_flags&SimulationModeMask; } else flags |= event->m_flags&SimulationModeMask; Effect* effect = EffectLibrary::Instance->MakeEffect( event->m_effectID, flags ); Register_Object(effect); m_children.Add(effect); m_event.Next(); // //--------------------------------------------- // Now set the info for starting the new effect //--------------------------------------------- // effect->m_localToParent = event->m_localToParent; Stuff::Scalar min_seed = m_specification->m_minimumChildSeed.ComputeValue(m_age, m_seed); Stuff::Scalar seed_range = m_specification->m_maximumChildSeed.ComputeValue(m_age, m_seed) - min_seed; Stuff::Scalar seed = Stuff::Random::GetFraction()*seed_range + min_seed; Clamp(seed, 0.0f, 1.0f); ExecuteInfo local_info( info->m_time, &m_localToWorld, NULL, seed ); effect->Start(&local_info); } // //------------------------------------------------------------ // Execute all the children. If any of them finish, kill them //------------------------------------------------------------ // Stuff::ChainIteratorOf<gosFX::Effect*> children(&m_children); gosFX::Effect *child; Stuff::OBB child_obb = Stuff::OBB::Identity; ExecuteInfo child_info( info->m_time, &m_localToWorld, &child_obb ); child_info.m_bounds = &child_obb; while ((child = children.ReadAndNext()) != NULL) { Check_Object(child); if (!child->Execute(&child_info)) { Unregister_Object(child); delete child; } // //-------------------------------------------------------------- // Merge the bounding sphere of the child into the bounds of the // parent //-------------------------------------------------------------- // Stuff::OBB parent_bounds; parent_bounds.Multiply(child_obb, m_localToParent); info->m_bounds->Union(*info->m_bounds, parent_bounds); } Check_Object(info->m_bounds); // //---------------------------------------------------------------------- // Set the new time, then if we have run the course of the effect, start // over if we loop, otherwise wait for our children to finish before // killing ourselves //---------------------------------------------------------------------- // m_lastRan = info->m_time; m_age = age; if (m_age >= 1.0f) { if (IsLooped()) Start(info); else if (HasFinished()) Kill(); } // //---------------------------------- // Tell our parent if we need to die //---------------------------------- // gos_PopCurrentHeap(); return IsExecuted(); }
expr update_local(expr const & e, expr const & new_type, binder_info const & bi) { if (is_eqp(mlocal_type(e), new_type) && local_info(e) == bi) return e; else return mk_local(mlocal_name(e), local_pp_name(e), new_type, bi, e.get_tag()); }