<commit_before>/// <summary>
///     Module defining view (and func) definers.
/// </summary>
module Starling.Core.Definer

open Chessie.ErrorHandling

open Starling.Collections
open Starling.Utils
open Starling.Core.Expr
open Starling.Core.Var
open Starling.Core.View
open Starling.Core.TypeSystem


/// <summary>
///     A definer function mapping views to their meanings.
/// </summary>
/// <typeparam name="defn">
///     Type of definitions of <c>View</c>s stored in the table.
///     May be <c>unit</c>.
/// </typeparam>
type ViewDefiner<'defn> =
    // TODO(CaptainHayashi): this should probably be a map,
    // but translating it to one seems non-trivial.
    // Would need to define equality on funcs very loosely.
    (DView * 'defn) list

/// <summary>
///     A definer function mapping funcs to their meanings.
/// </summary>
/// <typeparam name="defn">
///     Type of definitions of <c>Func</c>s stored in the table.
///     May be <c>unit</c>.
/// </typeparam>
type FuncDefiner<'defn> =
    // TODO(CaptainHayashi): this should probably be a map,
    // but translating it to one seems non-trivial.
    // Would need to define equality on funcs very loosely.
    (DFunc * 'defn) list

/// <summary>
///     Type of errors encountered when using definers.
/// </summary>
type Error =
    /// <summary>
    ///     The func looked up has a parameter <c>param</c>, which
    ///     has been assigned to an argument of the incorrect type
    ///     <c>atype</c>.
    /// </summary>
    | TypeMismatch of param: TypedVar * atype: Type
    /// <summary>
    ///     The func looked up has <c>fn</c> arguments, but its
    ///     definition has <c>dn</c> parameters.
    /// </summary>
    | CountMismatch of fn: int * dn: int


module FuncDefiner =
    /// <summary>
    ///     Converts a <c>FuncDefiner</c> to a sequence of pairs of
    ///     <c>Func</c> and definition.
    /// </summary>
    /// <param name="definer">
    ///     A <see cref="FuncDefiner"/> to convert to a sequence.
    /// </param>
    /// <typeparam name="defn">
    ///     The type of <c>Func</c> definitions.  May be <c>unit</c>.
    /// </typeparam>
    /// <returns>
    ///     The sequence of (<c>Func</c>, <c>'defn</c>) pairs.
    ///     A <c>FuncDefiner</c> allowing the <c>'defn</c>s of the given
    ///     <c>Func</c> to be looked up.
    /// </returns>
    let toSeq (definer : FuncDefiner<'defn>) : (DFunc * 'defn) seq =
        // This function exists to smooth over any changes in Definer
        // representation we make later (eg. to maps).
        List.toSeq definer

    /// <summary>
    ///     Builds a <c>FuncDefiner</c> from a sequence of pairs of
    ///     <c>Func</c> and definition.
    /// </summary>
    /// <param name="fseq">
    ///     The sequence of (<c>Func</c>, <c>'defn</c>) pairs.
    /// </param>
    /// <typeparam name="defn">
    ///     The type of <c>Func</c> definitions.  May be <c>unit</c>.
    /// </typeparam>
    /// <returns>
    ///     A <c>FuncDefiner</c> allowing the <c>'defn</c>s of the given
    ///     <c>Func</c> to be looked up.
    /// </returns>
    let ofSeq (fseq : #((DFunc * 'defn) seq)) : FuncDefiner<'defn> =
        // This function exists to smooth over any changes in Definer
        // representation we make later (eg. to maps).
        Seq.toList fseq

    /// <summary>
    ///     Checks whether <c>func</c> and <c>_arg1</c> agree on parameter
    ///     count.
    /// </summary>
    /// <param name="func">
    ///     The func being looked up, the process of which this check is part.
    /// </param>
    /// <param name="defn">
    ///     An <c>Option</c>al pair of <c>DFunc</c> and its defining
    ///     <c>BoolExpr</c>.
    ///     The value <c>None</c> suggests that <c>func</c> has no definition,
    ///     which can be ok (eg. if the <c>func</c> is a non-defining view).
    /// </param>
    /// <typeparam name="Par">The type of func-signature parameters.</typeparam>
    /// <typeparam name="Arg">The type of func arguments.</typeparam>
    /// <typeparam name="Defn">The type of func definitions.</typeparam>
    /// <returns>
    ///     A Chessie result, where the <c>ok</c> value is the optional pair of
    ///     prototype func and definition, and the failure value is a
    ///     <c>Starling.Core.Definer.Error</c>.
    /// </returns>
    let checkParamCount (func : Func<'Arg>) (defn : (Func<'Par> * 'Defn) option)
       : Result<(Func<'Par> * 'Defn) option, Error> =
        match defn with<commit_msg>Add way to combine FuncDefiners typesafely.<commit_after>/// <summary>
///     Module defining view (and func) definers.
/// </summary>
module Starling.Core.Definer

open Chessie.ErrorHandling

open Starling.Collections
open Starling.Utils
open Starling.Core.Expr
open Starling.Core.Var
open Starling.Core.View
open Starling.Core.TypeSystem


/// <summary>
///     A definer function mapping views to their meanings.
/// </summary>
/// <typeparam name="defn">
///     Type of definitions of <c>View</c>s stored in the table.
///     May be <c>unit</c>.
/// </typeparam>
type ViewDefiner<'defn> =
    // TODO(CaptainHayashi): this should probably be a map,
    // but translating it to one seems non-trivial.
    // Would need to define equality on funcs very loosely.
    (DView * 'defn) list

/// <summary>
///     A definer function mapping funcs to their meanings.
/// </summary>
/// <typeparam name="defn">
///     Type of definitions of <c>Func</c>s stored in the table.
///     May be <c>unit</c>.
/// </typeparam>
type FuncDefiner<'defn> =
    // TODO(CaptainHayashi): this should probably be a map,
    // but translating it to one seems non-trivial.
    // Would need to define equality on funcs very loosely.
    (DFunc * 'defn) list

/// <summary>
///     Type of errors encountered when using definers.
/// </summary>
type Error =
    /// <summary>
    ///     The func looked up has a parameter <c>param</c>, which
    ///     has been assigned to an argument of the incorrect type
    ///     <c>atype</c>.
    /// </summary>
    | TypeMismatch of param: TypedVar * atype: Type
    /// <summary>
    ///     The func looked up has <c>fn</c> arguments, but its
    ///     definition has <c>dn</c> parameters.
    /// </summary>
    | CountMismatch of fn: int * dn: int


module FuncDefiner =
    /// <summary>
    ///     Converts a <c>FuncDefiner</c> to a sequence of pairs of
    ///     <c>Func</c> and definition.
    /// </summary>
    /// <param name="definer">
    ///     A <see cref="FuncDefiner"/> to convert to a sequence.
    /// </param>
    /// <typeparam name="defn">
    ///     The type of <c>Func</c> definitions.  May be <c>unit</c>.
    /// </typeparam>
    /// <returns>
    ///     The sequence of (<c>Func</c>, <c>'defn</c>) pairs.
    ///     A <c>FuncDefiner</c> allowing the <c>'defn</c>s of the given
    ///     <c>Func</c> to be looked up.
    /// </returns>
    let toSeq (definer : FuncDefiner<'defn>) : (DFunc * 'defn) seq =
        // This function exists to smooth over any changes in Definer
        // representation we make later (eg. to maps).
        List.toSeq definer

    /// <summary>
    ///     Builds a <c>FuncDefiner</c> from a sequence of pairs of
    ///     <c>Func</c> and definition.
    /// </summary>
    /// <param name="fseq">
    ///     The sequence of (<c>Func</c>, <c>'defn</c>) pairs.
    /// </param>
    /// <typeparam name="defn">
    ///     The type of <c>Func</c> definitions.  May be <c>unit</c>.
    /// </typeparam>
    /// <returns>
    ///     A <c>FuncDefiner</c> allowing the <c>'defn</c>s of the given
    ///     <c>Func</c> to be looked up.
    /// </returns>
    let ofSeq (fseq : #((DFunc * 'defn) seq)) : FuncDefiner<'defn> =
        // This function exists to smooth over any changes in Definer
        // representation we make later (eg. to maps).
        Seq.toList fseq

    /// <summary>
    ///     Merges two definers.
    /// </summary>
    /// <param name="x">The first <see cref="FuncDefiner"/> to merge.</param>
    /// <param name="y">The second <see cref="FuncDefiner"/> to merge.</param>
    /// <typeparam name="Defn">
    ///     The type of <c>Func</c> definitions.  May be <c>unit</c>.
    /// </typeparam>
    /// <returns>
    ///     The <see cref="FuncDefiner"/> containing definitions from both
    ///     <paramref name="x"/> and <paramref name="y"/>.
    /// </returns>
    /// <remarks>
    ///    This does not yet check for duplicates.
    /// </remarks>
    let combine
      (x : FuncDefiner<'Defn>) (y : FuncDefiner<'Defn>) : FuncDefiner<'Defn> =
        // TODO(CaptainHayashi): duplicate checking.
        let xs = toSeq x
        let ys = toSeq y
        let xys = Seq.append x y
        ofSeq xys

    /// <summary>
    ///     Checks whether <c>func</c> and <c>_arg1</c> agree on parameter
    ///     count.
    /// </summary>
    /// <param name="func">
    ///     The func being looked up, the process of which this check is part.
    /// </param>
    /// <param name="defn">
    ///     An <c>Option</c>al pair of <c>DFunc</c> and its defining
    ///     <c>BoolExpr</c>.
    ///     The value <c>None</c> suggests that <c>func</c> has no definition,
    ///     which can be ok (eg. if the <c>func</c> is a non-defining view).
    /// </param>
    /// <typeparam name="Par">The type of func-signature parameters.</typeparam>
    /// <typeparam name="Arg">The type of func arguments.</typeparam>
    /// <typeparam name="Defn">The type of func definitions.</typeparam>
    /// <returns>
    ///     A Chessie result, where the <c>ok</c> value is the optional pair of
    ///     prototype func and definition, and the failure value is a
    ///     <c>Starling.Core.Definer.Error</c>.
    /// </returns>
    let checkParamCount (func : Func<'Arg>) (defn : (Func<'Par> * 'Defn) option)
       : Result<(Func<'Par> * 'Defn) option, Error> =
        match defn with
{'fraction_non_alphanumeric': 0.17082030067601656, 'fraction_numerical': 0.00020179598425991324, 'mean_word_length': 2.0630407911001236, 'pattern_counts': {'":': 0, '<': 281, '<?xml version=': 0, '>': 281, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6142301', 'n_tokens_mistral': 3208, 'n_tokens_neox': 3178, 'n_words': 1020}