<commit_before>﻿module Renamer

open System.Collections.Generic
open Ast
open Options.Globals

type RenameMode = Unambiguous | Frequency | Context

let mutable private renameMode = Unambiguous

let doNotOverloadList = options.noRenamingList

      (* Contextual renaming *)

let contextTable = new HashMultiMap<(char*char), int>(HashIdentity.Structural)

// This function is called when all 1-char ident are already used
let makeLetterIdent =
    let chars = [| 'a' .. 'z' |]
    let mutable first = 0
    let mutable second = 0
    fun () ->
        second <- second + 1
        if second >= chars.Length then second <- 0; first <- first + 1
        string(chars.[first]) + string(chars.[second])

let computeContextTable code =
    Printer.quickPrint code |> Seq.pairwise |> Seq.iter (fun (prev, next) ->
        match contextTable.TryFind (prev, next) with
        | Some n -> contextTable.[(prev, next)] <- n + 1
        | None -> contextTable.[(prev, next)] <- 1
    )
    //let chars, n = Seq.maxBy snd [for pair in contextTable -> pair.Key, pair.Value]
    //printfn "max occ: %A -> %d" chars n

let chooseIdent ident candidates =
    let allChars = [char 0 .. char 255]
    let prevs = allChars |> Seq.choose (fun c ->
        match contextTable.TryFind (c, ident) with
        | Some occ -> Some (c, occ)
        | None -> None
    )
    let nexts = allChars |> Seq.choose (fun c ->
        match contextTable.TryFind (ident, c) with
        | Some occ -> Some (c, occ)
        | None -> None
    )

    let mutable best = -1000, "a"
    for word in candidates do
        let letter = (word : string).[0] // FIXME: use both first and last letter to compute stats
        let mutable score = 0
        for c, _ in prevs do
            match contextTable.TryFind (c, letter) with
            | None -> ()
            | Some occ2 -> score <- score + occ2 // * occ

        for c, _ in nexts do
            match contextTable.TryFind (letter, c) with
            | None -> ()
            | Some occ2 -> score <- score + occ2 // * occ
<commit_msg>Make Shader Minifier twice as fast (#48)<commit_after>﻿module Renamer

open System.Collections.Generic
open Ast
open Options.Globals

type RenameMode = Unambiguous | Frequency | Context

let mutable private renameMode = Unambiguous

let doNotOverloadList = options.noRenamingList

      (* Contextual renaming *)

let contextTable = new HashMultiMap<(char*char), int>(HashIdentity.Structural)

// This function is called when all 1-char ident are already used
let makeLetterIdent =
    let chars = [| 'a' .. 'z' |]
    let mutable first = 0
    let mutable second = 0
    fun () ->
        second <- second + 1
        if second >= chars.Length then second <- 0; first <- first + 1
        string(chars.[first]) + string(chars.[second])

let computeContextTable code =
    Printer.quickPrint code |> Seq.pairwise |> Seq.iter (fun (prev, next) ->
        match contextTable.TryFind (prev, next) with
        | Some n -> contextTable.[(prev, next)] <- n + 1
        | None -> contextTable.[(prev, next)] <- 1
    )
    //let chars, n = Seq.maxBy snd [for pair in contextTable -> pair.Key, pair.Value]
    //printfn "max occ: %A -> %d" chars n

// /!\ This function is a performance bottleneck.
let chooseIdent ident candidates =
    let allChars = [char 32 .. char 127] // printable chars
    let prevs = allChars |> Seq.choose (fun c ->
        match contextTable.TryFind (c, ident) with
        | Some occ -> Some (c, occ)
        | None -> None
    )
    let nexts = allChars |> Seq.choose (fun c ->
        match contextTable.TryFind (ident, c) with
        | Some occ -> Some (c, occ)
        | None -> None
    )

    let mutable best = -1000, "a"
    for word in candidates do
        let letter = (word : string).[0] // FIXME: use both first and last letter to compute stats
        let mutable score = 0
        for c, _ in prevs do
            match contextTable.TryFind (c, letter) with
            | None -> ()
            | Some occ2 -> score <- score + occ2 // * occ

        for c, _ in nexts do
            match contextTable.TryFind (letter, c) with
            | None -> ()
            | Some occ2 -> score <- score + occ2 // * occ

{'fraction_non_alphanumeric': 0.11502738747320791, 'fraction_numerical': 0.011193141224100976, 'mean_word_length': 2.193916349809886, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 47, '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': '5646652', 'n_tokens_mistral': 1326, 'n_tokens_neox': 1241, 'n_words': 452}