Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  list.rs

  Sprache: Rust
 

//! An [`OverloadSet`] represented as a vector of rules.
//!
//! [`OverloadSet`]: crate::proc::overloads::OverloadSet

use crate::common::{DiagnosticDebug, ForDebug, ForDebugWithTypes};
use crate::ir;
use crate::proc::overloads::one_bits_iter::OneBitsIter;
use crate::proc::overloads::Rule;
use crate::proc::{GlobalCtx, TypeResolution};

use alloc::rc::Rc;
use alloc::vec::Vec;
use core::fmt;

/// A simple list of overloads.
///
/// Note that this type is not quite as general as it looks, in that
/// the implementation of `most_preferred` doesn't work for arbitrary
/// lists of overloads. See the documentation for [`List::rules`] for
/// details.
#[derive(Clone)]
pub(in crate::proc::overloads) struct List {
    /// A bitmask of which elements of `rules` are included in the set.
    members: u64,

    /// A list of type rules that are members of the set.
    ///
    /// These must be listed in order such that every rule in the list
    /// is always more preferred than all subsequent rules in the
    /// list. If there is no such arrangement of rules, then you
    /// cannot use `List` to represent the overload set.
    rules: Rc<Vec<Rule>>,
}

impl List {
    pub(in crate::proc::overloads) fn from_rules(rules: Vec<Rule>) -> List {
        List {
            members: len_to_full_mask(rules.len()),
            rules: Rc::new(rules),
        }
    }

    fn members(&self) -> impl Iterator<Item = (u64, &Rule)> {
        OneBitsIter::new(self.members).map(|mask| {
            let index = mask.trailing_zeros() as usize;
            (mask, &self.rules[index])
        })
    }

    fn filter<F>(&selfmut pred: F) -> List
    where
        F: FnMut(&Rule) -> bool,
    {
        let mut filtered_members = 0;
        for (mask, rule) in self.members() {
            if pred(rule) {
                filtered_members |= mask;
            }
        }

        List {
            members: filtered_members,
            rules: self.rules.clone(),
        }
    }
}

impl crate::proc::overloads::OverloadSet for List {
    fn is_empty(&self) -> bool {
        self.members == 0
    }

    fn min_arguments(&self) -> usize {
        self.members()
            .fold(None, |best, (_, rule)| {
                // This is different from `max_arguments` because
                // `<Option as PartialOrd>` doesn't work the way we'd like.
                let len = rule.arguments.len();
                Some(match best {
                    Some(best) => core::cmp::max(best, len),
                    None => len,
                })
            })
            .unwrap()
    }

    fn max_arguments(&self) -> usize {
        self.members()
            .fold(None, |n, (_, rule)| {
                core::cmp::max(n, Some(rule.arguments.len()))
            })
            .unwrap()
    }

    fn arg(&self, i: usize, arg_ty: &ir::TypeInner, types: &crate::UniqueArena<ir::Type>) -> Self {
        log::debug!("arg {i} of type {:?}", arg_ty.for_debug(types));
        self.filter(|rule| {
            if log::log_enabled!(log::Level::Debug) {
                log::debug!("    considering rule {:?}", rule.for_debug(types));
                match rule.arguments.get(i) {
                    Some(rule_ty) => {
                        let rule_ty = rule_ty.inner_with(types);
                        if arg_ty.non_struct_equivalent(rule_ty, types) {
                            log::debug!("    types are equivalent");
                        } else {
                            match arg_ty.automatically_converts_to(rule_ty, types) {
                                Some((from, to)) => {
                                    log::debug!(
                                        "    converts automatically from {:?} to {:?}",
                                        from.for_debug(),
                                        to.for_debug()
                                    );
                                }
                                None => {
                                    log::debug!("    no conversion possible");
                                }
                            }
                        }
                    }
                    None => {
                        log::debug!("    argument index {i} out of bounds");
                    }
                }
            }
            rule.arguments.get(i).is_some_and(|rule_ty| {
                let rule_ty = rule_ty.inner_with(types);
                arg_ty.non_struct_equivalent(rule_ty, types)
                    || arg_ty.automatically_converts_to(rule_ty, types).is_some()
            })
        })
    }

    fn concrete_only(self, types: &crate::UniqueArena<ir::Type>) -> Self {
        self.filter(|rule| {
            rule.arguments
                .iter()
                .all(|arg_ty| !arg_ty.inner_with(types).is_abstract(types))
        })
    }

    fn most_preferred(&self) -> Rule {
        // As documented for `Self::rules`, whatever rule is first is
        // the most preferred. `OverloadSet` documents this method to
        // panic if the set is empty.
        let (_, rule) = self.members().next().unwrap();
        rule.clone()
    }

    fn overload_list(&self, _gctx: &GlobalCtx<'_>) -> Vec<Rule> {
        self.members().map(|(_, rule)| rule.clone()).collect()
    }

    fn allowed_args(&self, i: usize, _gctx: &GlobalCtx<'_>) -> Vec<TypeResolution> {
        self.members()
            .map(|(_, rule)| rule.arguments[i].clone())
            .collect()
    }

    fn for_debug(&self, types: &crate::UniqueArena<ir::Type>) -> impl fmt::Debug {
        DiagnosticDebug((self, types))
    }
}

const fn len_to_full_mask(n: usize) -> u64 {
    #[expect(
        clippy::allow_attributes,
        reason = "This is a const function, which _sometimes_ gets called, \
            so this lint is _sometimes_ triggered, depending on feature set."
    )]
    #[allow(clippy::panic)]
    if n >= 64 {
        panic!("List::rules can only hold up to 63 rules");
    }

    (1_u64 << n) - 1
}

impl ForDebugWithTypes for &List {}

impl fmt::Debug for DiagnosticDebug<(&List, &crate::UniqueArena<ir::Type>)> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let (list, types) = self.0;

        f.debug_list()
            .entries(list.members().map(|(_mask, rule)| rule.for_debug(types)))
            .finish()
    }
}

Messung V0.5 in Prozent
C=87 H=100 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002