Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active March 2, 2022 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/dca46ea655c0a1666891901af80b6790 to your computer and use it in GitHub Desktop.
Save xuwei-k/dca46ea655c0a1666891901af80b6790 to your computer and use it in GitHub Desktop.
scalaVersion := "3.1.2-RC1"
import scala.compiletime.ops.string.{+, Substring, Length}
import scala.compiletime.ops.int
sealed trait HList
sealed trait :+:[H, +T <: HList] extends HList
sealed trait HNil extends HList
sealed trait Token
sealed trait NumLiteral[A <: Int] extends Token
sealed trait Add extends Token
sealed trait Sub extends Token
sealed trait Space extends Token
sealed trait Expr
sealed trait Num extends Expr
sealed trait NumValue[A <: Int] extends Num
sealed trait NumAdd[A1 <: Num, A2 <: Num] extends Num
sealed trait NumSub[A1 <: Num, A2 <: Num] extends Num
@annotation.experimental
object MatchTypeParseEval {
type Reverse[A <: String] =
ReverseLoop["", A]
type ReverseLoop[Acc <: String, Src <: String] <: String =
Length[Src] match
case 0 =>
Acc
case _ =>
ReverseLoop[Substring[Src, 0, 1] + Acc, Substring[Src, 1, Length[Src]]]
type StringToHList[A <: String] =
StringToHList0[HNil, Reverse[A]]
type StringToHList0[+Acc <: HList, Src <: String] <: HList =
Length[Src] match
case 0 =>
Acc
case _ =>
StringToHList0[Substring[Src, 0, 1] :+: Acc, Substring[Src, 1, Length[Src]]]
type StrToToken[A <: String] =
A match {
case "0" => NumLiteral[0]
case "1" => NumLiteral[1]
case "2" => NumLiteral[2]
case "3" => NumLiteral[3]
case "4" => NumLiteral[4]
case "5" => NumLiteral[5]
case "6" => NumLiteral[6]
case "7" => NumLiteral[7]
case "8" => NumLiteral[8]
case "9" => NumLiteral[9]
case "+" => Add
case "-" => Sub
case " " => Space
}
type HListToTokens[A <: HList] <: HList =
A match {
case x :+: xs =>
StrToToken[x] :+: HListToTokens[xs]
case HNil =>
HNil
}
type TokensToExpr0[Tokens <: HList, E <: Expr] <: Expr =
Tokens match {
case Add :+: NumLiteral[a] :+: xs =>
TokensToExpr0[xs, NumAdd[E, NumValue[a]]]
case Sub :+: NumLiteral[a] :+: xs =>
TokensToExpr0[xs, NumSub[E, NumValue[a]]]
case HNil =>
E
}
type TokensToExpr[Tokens <: HList] <: Expr =
Tokens match {
case NumLiteral[x] :+: xs =>
TokensToExpr0[xs, NumValue[x]]
}
type RemoveSpace[A <: HList] <: HList =
A match {
case Space :+: xs =>
RemoveSpace[xs]
case x :+: xs =>
x :+: RemoveSpace[xs]
case HNil =>
HNil
}
type Eval[A <: Expr] <: Int =
A match {
case NumValue[a] => a
case NumAdd[a1, a2] => int.+[Eval[a1], Eval[a2]]
case NumSub[a1, a2] => int.-[Eval[a1], Eval[a2]]
}
type Run[A <: String] =
Eval[
TokensToExpr[
RemoveSpace[
HListToTokens[
StringToHList[A]
]
]
]
]
def a1: Reverse["abc"] =
"cba"
def a2: StringToHList["123"] =
( ??? : ("1" :+: "2" :+: "3" :+: HNil) )
def a3: TokensToExpr[NumLiteral[1] :+: Add :+: NumLiteral[2] :+: HNil] =
( ??? : NumAdd[NumValue[1], NumValue[2]] )
def a4: Run["1 + 2 - 5 + 9"] = 7
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment