All Downloads are FREE. Search and download functionalities are using the official Maven repository.

singleton.ops.package.scala Maven / Gradle / Ivy

The newest version!
package singleton
import shapeless.Nat
import singleton.ops.impl._

package object ops {
  /////////////////////////////////////////////////
  //Short of shapeless's Witness
  /////////////////////////////////////////////////
  val W = shapeless.Witness
  /////////////////////////////////////////////////

  /////////////////////////////////////////////////
  //Short aliases of singleton types
  /////////////////////////////////////////////////
  type XChar                = Char with Singleton
  type XInt                 = Int with Singleton
  type XLong                = Long with Singleton
  type XFloat               = Float with Singleton
  type XDouble              = Double with Singleton
  type XString              = String with Singleton
  type XBoolean             = Boolean with Singleton
  type XSymbol              = Symbol with Singleton
  /////////////////////////////////////////////////

  /////////////////////////////////////////////////
  //Short aliases for casting operation type value
  /////////////////////////////////////////////////
  type SafeNat[P1]          = impl.OpNat[ToNat[Require[IsNat[P1]] ==> P1]]
  type SafeChar[P1]         = impl.OpChar[Require[IsChar[P1]] ==> P1]
  type SafeInt[P1]          = impl.OpInt[Require[IsInt[P1]] ==> P1]
  type SafeLong[P1]         = impl.OpLong[Require[IsLong[P1]] ==> P1]
  type SafeFloat[P1]        = impl.OpFloat[Require[IsFloat[P1]] ==> P1]
  type SafeDouble[P1]       = impl.OpDouble[Require[IsDouble[P1]] ==> P1]
  type SafeString[P1]       = impl.OpString[Require[IsString[P1]] ==> P1]
  type SafeBoolean[P1]      = impl.OpBoolean[Require[IsBoolean[P1]] ==> P1]
  type SafeSymbol[P1]       = impl.OpSymbol[ToSymbol[Require[IsSymbol[P1]] ==> P1]]
  /////////////////////////////////////////////////

  /////////////////////////////////////////////////
  //Short aliases of auxiliary operation types
  /////////////////////////////////////////////////
  type OpAuxGen[O <: Op,      Ret_Out]              = OpGen.Aux[O, Ret_Out]
  type OpAuxNat[O <: Op,      Ret_Out <: Nat]       = OpNat.Aux[O, Ret_Out]
  type OpAuxChar[O <: Op,     Ret_Out <: XChar]     = OpChar.Aux[O, Ret_Out]
  type OpAuxInt[O <: Op,      Ret_Out <: XInt]      = OpInt.Aux[O, Ret_Out]
  type OpAuxLong[O <: Op,     Ret_Out <: XLong]     = OpLong.Aux[O, Ret_Out]
  type OpAuxFloat[O <: Op,    Ret_Out <: XFloat]    = OpFloat.Aux[O, Ret_Out]
  type OpAuxDouble[O <: Op,   Ret_Out <: XDouble]   = OpDouble.Aux[O, Ret_Out]
  type OpAuxString[O <: Op,   Ret_Out <: XString]   = OpString.Aux[O, Ret_Out]
  type OpAuxBoolean[O <: Op,  Ret_Out <: XBoolean]  = OpBoolean.Aux[O, Ret_Out]
  type OpAuxSymbol[O <: Op,   Ret_Out <: Symbol]    = OpSymbol.Aux[O, Ret_Out]
  /////////////////////////////////////////////////

  private val NP = W(0)
  private type NP = NP.T
  private val DefaultRequireMsg = W("Cannot prove requirement Require[...]")
  private type DefaultRequireMsg = DefaultRequireMsg.T
  protected[singleton] val True = W(true)
  protected[singleton] type True = True.T
  protected[singleton] val False = W(false)
  protected[singleton] type False = False.T
  protected[singleton] val SomethingBadHappened = W("Something bad happened")
  protected[singleton] type SomethingBadHappened = SomethingBadHappened.T

  /////////////////////////////////////////////////
  //Special control aliases
  /////////////////////////////////////////////////
  type ITE[Cond,TBody,EBody]= OpMacro[OpId.ITE, Cond, TBody, EBody]
  type ==>[A,B]             = OpMacro[OpId.==>, A, B, NP]
  /////////////////////////////////////////////////

  protected[singleton] type Arg[Num, T, TWide] = OpMacro[OpId.Arg, Num, T, TWide] //Argument for real-time function creation
  protected[singleton] type GetType[Sym] = OpMacro[OpId.GetType, Sym, NP, NP] //Argument for real-time function creation
  type AcceptNonLiteral[P1] = OpMacro[OpId.AcceptNonLiteral, P1, NP, NP]
  type GetArg[ArgIdx]       = OpMacro[OpId.GetArg, ArgIdx, NP, NP] //Use to get argument type of class/definition
  type GetLHSArg[ArgIdx]    = OpMacro[OpId.GetLHSArg, ArgIdx, NP, NP] //Use to get argument type of the left-hand-side
  type ImplicitFound[Sym]   = OpMacro[OpId.ImplicitFound, GetType[Sym], NP, NP] //Implicit Found boolean indication
  type EnumCount[Sym]       = OpMacro[OpId.EnumCount, GetType[Sym], NP, NP] //Number of direct subclasses
  final val  GetArg         = impl.GetArg
  final val  GetLHSArg      = impl.GetLHSArg
  type GetArg0              = GetArg[W.`0`.T]
  type GetLHSArg0           = GetLHSArg[W.`0`.T]
  type Id[P1]               = OpMacro[OpId.Id, P1, NP, NP]
  type ![P1]                = OpMacro[OpId.!, P1, NP, NP]
  type Require[Cond]        = OpMacro[OpId.Require, Cond, DefaultRequireMsg, NoSym]
  type RequireMsg[Cond,Msg] = OpMacro[OpId.Require, Cond, Msg, NoSym]
  type RequireMsgSym[Cond,Msg,Sym] = OpMacro[OpId.Require, Cond, Msg, GetType[Sym]]
  type Warn                 = impl.Warn
  type ToNat[P1]            = OpMacro[OpId.ToNat, P1, NP, NP]
  type ToChar[P1]           = OpMacro[OpId.ToChar, P1, NP, NP]
  type ToInt[P1]            = OpMacro[OpId.ToInt, P1, NP, NP]
  type ToLong[P1]           = OpMacro[OpId.ToLong, P1, NP, NP]
  type ToFloat[P1]          = OpMacro[OpId.ToFloat, P1, NP, NP]
  type ToDouble[P1]         = OpMacro[OpId.ToDouble, P1, NP, NP]
  type ToString[P1]         = OpMacro[OpId.ToString, P1, NP, NP]
  type ToSymbol[P1]         = OpMacro[OpId.ToSymbol, P1, NP, NP]
  type IsNat[P1]            = OpMacro[OpId.IsNat, P1, NP, NP]
  type IsChar[P1]           = OpMacro[OpId.IsChar, P1, NP, NP]
  type IsInt[P1]            = OpMacro[OpId.IsInt, P1, NP, NP]
  type IsLong[P1]           = OpMacro[OpId.IsLong, P1, NP, NP]
  type IsFloat[P1]          = OpMacro[OpId.IsFloat, P1, NP, NP]
  type IsDouble[P1]         = OpMacro[OpId.IsDouble, P1, NP, NP]
  type IsString[P1]         = OpMacro[OpId.IsString, P1, NP, NP]
  type IsBoolean[P1]        = OpMacro[OpId.IsBoolean, P1, NP, NP]
  type IsSymbol[P1]         = OpMacro[OpId.IsSymbol, P1, NP, NP]
  type IsNonLiteral[P1]     = OpMacro[OpId.IsNonLiteral, P1, NP, NP]
  type Reverse[P1]          = OpMacro[OpId.Reverse, P1, NP, NP]
  type Negate[P1]           = OpMacro[OpId.Negate, P1, NP, NP]
  type NumberOfLeadingZeros[P1] = OpMacro[OpId.NumberOfLeadingZeros, P1, NP, NP]

  type +[P1, P2]            = OpMacro[OpId.+, P1, P2, NP]
  type -[P1, P2]            = OpMacro[OpId.-, P1, P2, NP]
  type *[P1, P2]            = OpMacro[OpId.*, P1, P2, NP]
  type /[P1, P2]            = OpMacro[OpId./, P1, P2, NP]
  type %[P1, P2]            = OpMacro[OpId.%, P1, P2, NP]
  type <[P1, P2]            = OpMacro[OpId.<, P1, P2, NP]
  type <=[P1, P2]           = OpMacro[OpId.<=, P1, P2, NP]
  type >=[P1, P2]           = OpMacro[OpId.>=, P1, P2, NP]
  type >[P1, P2]            = OpMacro[OpId.>, P1, P2, NP]
  type ==[P1, P2]           = OpMacro[OpId.==, P1, P2, NP]
  type !=[P1, P2]           = OpMacro[OpId.!=, P1, P2, NP]
  type &&[P1, P2]           = OpMacro[OpId.&&, P1, P2, NP]
  type ||[P1, P2]           = OpMacro[OpId.||, P1, P2, NP]
  type Substring[P1, P2]    = OpMacro[OpId.Substring, P1, P2, NP]
  type Length[P1]           = OpMacro[OpId.Length, P1, NP, NP]
  type CharAt[P1, P2]       = OpMacro[OpId.CharAt, P1, P2, NP]

  type CompileTime[C]       = Require[ITE[IsNonLiteral[C], W.`true`.T, C]]
  type RunTime[R]           = SafeBoolean[IsNonLiteral[R]]

  object math {
    type Pi                 = W.`3.141592653589793`.T
    type E                  = W.`2.718281828459045`.T
    type Abs[P1]            = OpMacro[OpId.Abs, P1, NP, NP]
    type Min[P1, P2]        = OpMacro[OpId.Min, P1, P2, NP]
    type Max[P1, P2]        = OpMacro[OpId.Max, P1, P2, NP]
    type Pow[P1, P2]        = OpMacro[OpId.Pow, P1, P2, NP]
    type Floor[P1]          = OpMacro[OpId.Floor, P1, NP, NP]
    type Ceil[P1]           = OpMacro[OpId.Ceil, P1, NP, NP]
    type Round[P1]          = OpMacro[OpId.Round, P1, NP, NP]
    type Sin[P1]            = OpMacro[OpId.Sin, P1, NP, NP]
    type Cos[P1]            = OpMacro[OpId.Cos, P1, NP, NP]
    type Tan[P1]            = OpMacro[OpId.Tan, P1, NP, NP]
    type Sqrt[P1]           = OpMacro[OpId.Sqrt, P1, NP, NP]
    type Log[P1]            = OpMacro[OpId.Log, P1, NP, NP]
    type Log10[P1]          = OpMacro[OpId.Log10, P1, NP, NP]
  }


  /////////////////////////////////////////////////
  //Implicit proof that
  //singleton type is equivalent to type operation
  //E.g. val four : 2 + 2 = 4
  /////////////////////////////////////////////////
  implicit def singletonToOp[
  X <: Singleton, N, S1, S2, S3, OP_OUT
  ](x: X)
   (implicit
    op : OpMacro[N, S1, S2, S3],
    opaux: OpAuxGen[OpMacro[N, S1, S2, S3], OP_OUT],
    check : Require[X == OP_OUT]
   ) : OpMacro[N, S1, S2, S3] = op
  /////////////////////////////////////////////////


  /////////////////////////////////////////////////
  //Implicit proof that
  //type operation is equivalent to singleton type
  //E.g. val four : 4 = implicitly[2 + 2]
  /////////////////////////////////////////////////
  implicit def opToSingleton[
  N, S1, S2, S3, OP_OUT
  ](op : OpMacro[N, S1, S2, S3])
   (implicit
    opaux: OpAuxGen[OpMacro[N, S1, S2, S3], OP_OUT],
    id : Id[OP_OUT]
   ) : OP_OUT = id.value.asInstanceOf[OP_OUT]
  /////////////////////////////////////////////////


  /////////////////////////////////////////////////
  //Implicit proof that
  //type operation is equivalent to a different type operation
  //E.g. val four : 1 + 3 = implicitly[2 + 2]
  /////////////////////////////////////////////////
  implicit def opToOp[
  NA, SA1, SA2, SA3,
  NB, SB1, SB2, SB3,
  OP_OUTA,
  OP_OUTB
  ](opA : OpMacro[NA, SA1, SA2, SA3])
   (implicit
    opauxA: OpAuxGen[OpMacro[NA, SA1, SA2, SA3], OP_OUTA],
    opauxB: OpAuxGen[OpMacro[NB, SB1, SB2, SB3], OP_OUTB],
    opB : OpMacro[NB, SB1, SB2, SB3],
    check : Require[OP_OUTA == OP_OUTB]
  ) : OpMacro[NB, SB1, SB2, SB3] = opB
  /////////////////////////////////////////////////


  /////////////////////////////////////////////////
  //Implicit proof for type class containers of
  //singleton type operations & literals
  /////////////////////////////////////////////////
  implicit def opContainer1[
  F,
  T,
  C[_]
  ](cf : C[F])
   (implicit
    ct : C[T],
    check : Require[
      F == T
      ])
  : C[T] = ct

  implicit def opContainer2[
  F1, F2,
  T1, T2,
  C[_,_]
  ](cf : C[F1, F2])
   (implicit
    ct : C[T1, T2],
    check : Require[
        (F1 == T1) &&
        (F2 == T2)
      ]
   ) : C[T1, T2] = ct

  implicit def opContainer3[
  F1, F2, F3,
  T1, T2, T3,
  C[_,_,_]
  ](cf : C[F1, F2, F3])
   (implicit
    ct : C[T1, T2, T3],
    check : Require[
        (F1 == T1) &&
        (F2 == T2) &&
        (F3 == T3)
      ]
   ) : C[T1, T2, T3] = ct
  /////////////////////////////////////////////////
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy