<commit_before>namespace FSharp.DependentTyping

open System.Reflection
open FSharp.Core.CompilerServices
open ProviderImplementation
open ProviderImplementation.ProvidedTypes
open FSharp.Quotations

[<TypeProvider>]
type Numbers (_cfg) as tp =
  inherit TypeProviderForNamespaces ()
  let ns         = "FSharp.DependentTypes.Numbers"
  let asm        = Assembly.GetExecutingAssembly()
  let boundedInt = new ProvidedTypeDefinition(asm, ns, "BoundedInt32", Some typeof<int>)
  let upperBound = new ProvidedStaticParameter("Upper", typeof<int>)
  let lowerBound = new ProvidedStaticParameter("Lower", typeof<int>, parameterDefaultValue = 0us)
  let (|Bounds|) (args : obj array) =
    match args with
    | [| (:? int as lower)
         (:? int as upper) |] when lower < upper -> lower, upper
    |                                          a -> failwithf "Expected array of int but got %A" a
  let createBounded (tyName : string) (Bounds (lower, upper)) =
    let param = new ProvidedParameter("value", typeof<int>)
    let constrain (exprs : Expr list) =
      let v = exprs |> List.head
      <@@
      let  i = (%%Expr.Coerce(v, typeof<int>) : int)
      if   i > upper then failwithf "%d is greater than %d"  i upper
      elif i < lower then failwithf "%d is less than %d"     i lower
      else i
      @@>
    let ctor          = new ProvidedConstructor([param], InvokeCode = constrain)
    let boundedInt    = new ProvidedTypeDefinition(asm, ns, tyName, Some typeof<int>)
    let boundedIntOpt = typedefof<_ option>.MakeGenericType(boundedInt)
    let factory       = new ProvidedMethod("TryCreate", [param], boundedIntOpt, IsStaticMethod = true)
    factory.InvokeCode <-
      fun exprs ->
      let v = exprs |> List.head
      <@@
      let  i = (%%Expr.Coerce(v, typeof<int>) : int)
      if   i > upper then None
      elif i < lower then None
      else Some i
      @@>
    boundedInt.AddMember(ctor)
    boundedInt.AddMember(factory)

    let upperBoundGetter = new ProvidedProperty("MaxValue", typeof<int>, IsStatic =  true, GetterCode = (fun _ -> <@@ upper @@>))
    let lowerBoundGetter = new ProvidedProperty("MinValue", typeof<int>, IsStatic =  true, GetterCode = (fun _ -> <@@ lower @@>))
    boundedInt.AddMember(upperBoundGetter)
    boundedInt.AddMember(lowerBoundGetter)
    boundedInt

  do
    boundedInt.DefineStaticParameters([lowerBound; upperBound], createBounded)
    tp.AddNamespace(ns, [ boundedInt])
<commit_msg>introduce type parameter for underlying num type<commit_after>namespace FSharp.DependentTyping

open System
open System.Reflection
open FSharp.Core.CompilerServices
open ProviderImplementation
open ProviderImplementation.ProvidedTypes
open FSharp.Quotations

[<AutoOpen>]
module Bounds =
  let inline createBounded< ^n when ^n : comparison> asm ns (tyName : string) (bounds : obj array) =
    let lower = (bounds.[0] : obj) :?> ^n
    let upper = (bounds.[1] : obj) :?> ^n
    if lower > upper then failwithf "Lower %A must be less than upper %A" lower upper
    else
    let numType = typeof< ^n>
    let param = new ProvidedParameter("value", numType)
    let constrain (exprs : Expr list) =
      let v = exprs |> List.head
      <@@
      let  i = %%Expr.Coerce(v, numType)
      if   i > upper then failwithf "%A is greater than %A"  i upper
      elif i < lower then failwithf "%A is less than %A"     i lower
      else i
      @@>
    let ctor          = new ProvidedConstructor([param], InvokeCode = constrain)
    let boundedInt    = new ProvidedTypeDefinition(asm, ns, tyName, Some numType)
    let boundedIntOpt = typedefof<_ option>.MakeGenericType(boundedInt)
    let factory       = new ProvidedMethod("TryCreate", [param], boundedIntOpt, IsStaticMethod = true)
    factory.InvokeCode <-
      fun exprs ->
      let v = exprs |> List.head
      <@@
      let  i = (%%Expr.Coerce(v, numType) : 'n)
      if   i > upper then None
      elif i < lower then None
      else Some i
      @@>
    boundedInt.AddMember(ctor)
    boundedInt.AddMember(factory)

    let upperBoundGetter = new ProvidedProperty("MaxValue", numType, IsStatic = true, GetterCode = (fun _ -> <@@ upper @@>))
    let lowerBoundGetter = new ProvidedProperty("MinValue", numType, IsStatic = true, GetterCode = (fun _ -> <@@ lower @@>))
    boundedInt.AddMember(upperBoundGetter)
    boundedInt.AddMember(lowerBoundGetter)
    boundedInt

[<TypeProvider>]
type Numbers (_cfg) as tp =
  inherit TypeProviderForNamespaces ()
  let ns         = "FSharp.DependentTypes.Numbers"
  let asm        = Assembly.GetExecutingAssembly()
  let boundedInt = new ProvidedTypeDefinition(asm, ns, "BoundedInt32", Some typeof<obj>)
  let upperBound = new ProvidedStaticParameter("Upper", typeof<int>)
  let lowerBound = new ProvidedStaticParameter("Lower", typeof<int>, parameterDefaultValue = 0us)
  do
    boundedInt.DefineStaticParameters([lowerBound; upperBound], (createBounded<int> asm ns))
    tp.AddNamespace(ns, [boundedInt])

{'fraction_non_alphanumeric': 0.10834849403678998, 'fraction_numerical': 0.0016171417020416413, 'mean_word_length': 3.344161545215101, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4501124', 'n_tokens_mistral': 1515, 'n_tokens_neox': 1472, 'n_words': 438}