Skip to content

Commit

Permalink
Use Scala 3
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-adam committed Sep 14, 2023
1 parent 30c7c1f commit 6f021c7
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 115 deletions.
2 changes: 2 additions & 0 deletions .jvmopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-Xmx4G
-XX:+UseG1GC
6 changes: 4 additions & 2 deletions .scalafix.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ rules = [
// Semantic Rules
NoAutoTupling
OrganizeImports
RemoveUnused
// RemoveUnused

// Syntactic Rules
DisableSyntax
LeakingImplicitClassVal
NoValInForComprehension
ProcedureSyntax
// ProcedureSyntax
RedundantSyntax
]

OrganizeImports.removeUnused = false

DisableSyntax.noVars = true
DisableSyntax.noThrows = true
DisableSyntax.noNulls = true
Expand Down
4 changes: 4 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ maxColumn = 80
version = 3.7.14
runner.dialect = scala3
preset = IntelliJ

newlines.source = "unfold"
newlines.beforeMultiline = fold
newlines.alwaysBeforeElseAfterCurlyIf = false

rewrite.trailingCommas.style = always
31 changes: 20 additions & 11 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ ThisBuild / tlBaseVersion := "1.6"

ThisBuild / developers := List(tlGitHubDev("kamil-adam", "Kamil Adam"))

//ThisBuild / crossScalaVersions := Seq("2.13.11", "3.3.0")
ThisBuild / crossScalaVersions := Seq("2.13.11")
//ThisBuild / crossScalaVersions := Seq("3.3.0")
ThisBuild / crossScalaVersions := Seq("3.3.0")
ThisBuild / tlVersionIntroduced := Map("3" -> "1.1.5")

ThisBuild / licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT"))
Expand Down Expand Up @@ -95,14 +93,21 @@ val coreJvmSettings = Seq(
val coreJsSettings = Seq(
tlVersionIntroduced ~= {
_ ++ List("2.13").map(_ -> "1.0.2").toMap
}
},
scalaJSLinkerConfig ~= {
_
.withModuleKind(ModuleKind.ESModule)
// .withModuleSplitStyle(ModuleSplitStyle.SmallModulesFor(List("livechart")))
},

)

val coreNativeSettings = Seq(
tlVersionIntroduced := Map(
"2.13" -> "1.1.3",
"3" -> "1.5.0"
)
),
Test / javaOptions ++= coreJavaOptions,
)

val core =
Expand All @@ -123,11 +128,15 @@ val root =
.aggregate(core)
.settings(rootSettings)

addCommandAlias("scalafmtCat", "scalafmtSbt; scalafmtAll")
addCommandAlias("compileCat", "clean; compile; Test/compile")
addCommandAlias("coverageJS", "coverage; coreJS/test")
addCommandAlias("coverageCat", "coverage; coreJS/test; coreJVM/test")
addCommandAlias("scalafixWTF", "scalafixEnable; scalafixAll")
addCommandAlias("scalafmtWTF", "scalafmtSbt; scalafmtAll")
addCommandAlias("compileAll", "clean; compile; Test/compile")
addCommandAlias("testAll", "coreJS/test; coreNative/test")
addCommandAlias("coverageAll", "coverage; coreJVM/test")
addCommandAlias("all", "scalafixWTF; scalafmtAll; compileAll; testAll; coverageAll; coverageReport")
//addCommandAlias("all", "scalafmtAll; compileAll; testAll; coverageAll; coverageReport")
//addCommandAlias("all", "scalafmtAll; compileAll; testAll")
//coverageReport

// sbt scalafixAll && scalafmtCat && sbt compileCat && sbt coverageCat && sbt coverageReport
// sbt scalafixAll && scalafmtAll && sbt compileCat && sbt coverageCat && sbt coverageReport
// sbt scalafixAll && scalafmtWTF && sbt compileAll && sbt testAll && sbt coverageAll && sbt coverageReport
// sbt scalafixAll && scalafmtAll && sbt compileAll && sbt testAll && sbt coverageAll && sbt coverageReport
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import cats.data.NonEmptyList

object Extras {

def foldNonEmpty[A](l: NonEmptyList[A])(f: (A, A)=> A): A = l.tail.fold(l.head)(f)
def foldNonEmpty[A](l: NonEmptyList[A])(f: (A, A) => A): A = l
.tail
.fold(l.head)(f)

def fix[T, R](f: (T => R) => (T => R)): (T => R) = new Function1[T, R] {
def apply(t: T): R = f(this)(t)
}

// it is any way to have if-else in one line?
// format: off
def ifElse[E](c: => Boolean)(e1: => E)(e2: => E): E = if(c) e1 else e2
// format: on
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ object Combinator {

def generateC(c: Combinator): String = c.toString

final case object S extends Combinator
final case object K extends Combinator
final case object I extends Combinator
case object S extends Combinator
case object K extends Combinator
case object I extends Combinator
}

sealed trait Combinator
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ object Lambda {
val trueVariable: Lambda = Var("true")

// def wrapAppThrush(name: String, l1: Lambda, l2: Lambda): Lambda = App(thrushVariable, App(l1, Abs(name, l2)))
def wrapAppVireoApp(l1: Lambda, l2: Lambda): Lambda = App(App (vireoVariable, l1), l2)
def wrapAppVireoApp(l1: Lambda, l2: Lambda): Lambda =
App(App(vireoVariable, l1), l2)

def appSuccVariable(l: Lambda): Lambda = App(succVariable, l)

def generate(l: Lambda): String = l match {
Expand All @@ -33,18 +35,21 @@ object Lambda {

// def apps1(head: Lambda, tail: List[Lambda]): Lambda = Apps(NonEmptyList(head, tail))

//I know it is crazy, but I wanted to check it is possible
private val isOnlyCombinatorStep: (Lambda => Boolean) => Lambda => Boolean = rec => {
case Com(_) => true
case App(f, g) => rec(f) && rec(g)
case _ => false
}
// I know it is crazy, but I wanted to check it is possible
private val isOnlyCombinatorStep: (Lambda => Boolean) => Lambda => Boolean =
rec => {
case Com(_) => true
case App(f, g) => rec(f) && rec(g)
case _ => false
}

//I know it is crazy, but I wanted to check it is possible
// I know it is crazy, but I wanted to check it is possible
val isOnlyCombinator: Lambda => Boolean = fix(isOnlyCombinatorStep)

def multi1(head: Lambda, tail: List[Lambda]): Lambda = MultiApp(NonEmptyList(head, tail))
def local1(head: Lambda, tail: List[Lambda]): Lambda = LocalScope(NonEmptyList(head, tail))
def multi1(head: Lambda, tail: List[Lambda]): Lambda =
MultiApp(NonEmptyList(head, tail))
def local1(head: Lambda, tail: List[Lambda]): Lambda =
LocalScope(NonEmptyList(head, tail))

def natNumFromString(s: String): Lambda = NatNum(Natural(s))

Expand All @@ -55,7 +60,7 @@ object Lambda {
final case class Abs(param: String, body: Lambda) extends Lambda
final case class App(f: Lambda, x: Lambda) extends Lambda
final case class MultiApp(fs: NonEmptyList[Lambda]) extends Lambda
final case class LocalScope(xs: NonEmptyList[Lambda])extends Lambda
final case class LocalScope(xs: NonEmptyList[Lambda]) extends Lambda
final case class NilList(xs: List[Lambda]) extends Lambda
final case class CharStr(s: String) extends Lambda
final case class NatNum(n: Natural) extends Lambda
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package pl.writeonly.catculator.core.adt.calculus
object Sign {

def generate(s: Sign): String = s match {
case Plus => "+"
case Plus => "+"
case Minus => "-"
}

final case object Plus extends Sign
final case object Minus extends Sign
case object Plus extends Sign
case object Minus extends Sign
}

trait Sign
trait Sign
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ object BinaryTree {

case class Leaf[A](leaf: A) extends BinaryTree[A]

case class Node[A](first: BinaryTree[A], follow: BinaryTree[A]) extends BinaryTree[A]
case class Node[A](first: BinaryTree[A], follow: BinaryTree[A])
extends BinaryTree[A]
}

sealed trait BinaryTree[+A]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package pl.writeonly.catculator.core.adt.tree
import cats.data.NonEmptyList

object Tree {
def node[A](head: Tree[A], tail: Tree[A]*): Tree[A] = Node(NonEmptyList(head, tail.toList))
def node[A](head: Tree[A], tail: Tree[A]*): Tree[A] =
Node(NonEmptyList(head, tail.toList))

case class Leaf[A](leaf: A) extends Tree[A]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
package pl.writeonly.catculator.core.parsers

import cats.parse.Numbers.digits
import cats.parse.Parser0
import cats.parse.strings.Json.delimited.{parser => jsonString}
import cats.parse.{Parser0, Parser => P}
import cats.parse.{Parser => P}
import cats.syntax.all._
import pl.writeonly.catculator.core.adt.calculus
import pl.writeonly.catculator.core.adt.calculus.Lambda
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.adt.calculus.Sign
import pl.writeonly.catculator.core.adt.calculus.Sign._

object LambdaParser {
val identifierStart: P[Char] = P.charWhere(c => c.isLetter || "_:;,.".contains(c))
// val identifierStart: P[Char] = P.charWhere(_.isLetter)
val identifierContinue: P[Char] = P.charWhere(c => c.isLetterOrDigit || c == '_')
private val identifierStart: P[Char] = P.charWhere { c =>
c.isLetter || "_:;,.".contains(c)
}
private val identifierContinue: P[Char] = P.charWhere { c =>
c.isLetterOrDigit || c === '_'
}

val whitespace: P[Char] = P.charWhere(Character.isWhitespace)
val whitespaces: Parser0[String] = whitespace.rep0.string
private val whitespace: P[Char] = P.charWhere(Character.isWhitespace)
private val whitespaces: Parser0[String] = whitespace.rep0.string

def symbol[A](a: P[A]): P[A] = a <* whitespaces
def charSymbol(c: Char): P[Unit] = symbol(P.char(c))

// val identifier: P[String] = symbol((identifierChar ~ identifierChar.rep0).string)
val identifier: P[String] = symbol((identifierStart ~ identifierContinue.rep0).string)
val identifier: P[String] =
symbol((identifierStart ~ identifierContinue.rep0).string)

val lambda: P[calculus.Lambda] = P.defer(
// format: off
val lambda: P[Lambda] = P.defer(
variable
| abstraction
| application
Expand All @@ -33,35 +40,45 @@ object LambdaParser {
| natNum
| intNum
)
// format: on

val variable: P[calculus.Lambda] = identifier.map(Var)
val variable: P[Lambda] = identifier.map(Var.apply)

val abstraction: P[calculus.Lambda] = (charSymbol('\\') *> identifier ~ lambda).map(Abs.tupled)
val abstraction: P[Lambda] = (charSymbol('\\') *> identifier ~ lambda)
.map(Abs.apply)

val application: P[calculus.Lambda] = (charSymbol('`') *> lambda ~ lambda).map(App.tupled)
val application: P[Lambda] = (charSymbol('`') *> lambda ~ lambda)
.map(App.apply)

val mautiApplicationChildren: P[calculus.Lambda] = (lambda ~ lambda.rep0).map((multi1 _).tupled)
val mautiApplicationChildren: P[Lambda] = (lambda ~ lambda.rep0)
.map((multi1 _).tupled)

val multiApplication: P[calculus.Lambda] = charSymbol('(') *> mautiApplicationChildren <* charSymbol(')')
val multiApplication: P[Lambda] =
charSymbol('(') *> mautiApplicationChildren <* charSymbol(')')

val localScopeChildren: P[calculus.Lambda] = (lambda ~ lambda.rep0).map((local1 _).tupled)
val localScopeChildren: P[Lambda] = (lambda ~ lambda.rep0)
.map((local1 _).tupled)

val localScope: P[calculus.Lambda] = charSymbol('{') *> localScopeChildren <* charSymbol('}')
val localScope: P[Lambda] = charSymbol('{') *> localScopeChildren <*
charSymbol('}')

val nilList: P[calculus.Lambda] = charSymbol('[') *> lambda.rep0.map(NilList) <* charSymbol(']')
val nilList: P[Lambda] = charSymbol('[') *> lambda.rep0.map(NilList.apply) <*
charSymbol(']')

val charStr: P[calculus.Lambda] = jsonString.map(CharStr)
val charStr: P[Lambda] = jsonString.map(CharStr.apply)

val natNum: P[calculus.Lambda] = digits.map(natNumFromString)
val natNum: P[Lambda] = digits.map(natNumFromString)

val sign: P[Sign] = P.charIn("+-").map {
case '+' => Plus
case '-' => Minus
}
val sign: P[Sign] = P
.charIn("+-")
.map {
case '+' => Plus
case '-' => Minus
}

val intNum: P[calculus.Lambda] = (sign ~ digits).map((intNumFromString _).tupled)
val intNum: P[Lambda] = (sign ~ digits).map((intNumFromString _).tupled)

val lambdaEnd: P[calculus.Lambda] = lambda <* P.end
val lambdaEnd: P[Lambda] = lambda <* P.end

val parse: String => Either[P.Error, calculus.Lambda] = lambdaEnd.parseAll
}
val parse: String => Either[P.Error, Lambda] = lambdaEnd.parseAll
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package pl.writeonly.catculator.core.reducer

import pl.writeonly.catculator.core.Extras.ifElse
import pl.writeonly.catculator.core.adt.calculus.Combinator._
import pl.writeonly.catculator.core.adt.calculus.Lambda
import pl.writeonly.catculator.core.adt.calculus.Lambda._
Expand All @@ -17,20 +18,22 @@ object AbstractionReducer {
case l if isOnlyCombinator(l) => wrapAppK(l)
case Var(n1) => reduceVar(p0, n1)
case Abs(p1, b1) => reduceAbs(p0, p1, b1)
case App(f, g) => wrapAppAppS(reduceAbstraction1(p0, f), reduceAbstraction1(p0, g))
case lambda => lambda
case App(f, g) =>
wrapAppAppS(reduceAbstraction1(p0, f), reduceAbstraction1(p0, g))
case lambda => lambda
}

private def reduceVar(n0: String, n1: String): Lambda =
if (n0 === n1) Com(I) else wrapAppK(Var(n1))
ifElse(n0 === n1)(Com(I))(wrapAppK(Var(n1)))

private def reduceAbs(p0: String, p1: String, b1: Lambda): Lambda =
reduceAbs1(p0, p1, reduceAbstraction1(p1, b1))

private def reduceAbs1(p0: String, p1: String, c: Lambda): Lambda =
if (p0 === p1) wrapAppK(c) else reduceAbstraction1(p0, c)
ifElse(p0 === p1)(wrapAppK(c))(reduceAbstraction1(p0, c))

private def wrapAppK(c: Lambda): Lambda = App(Com(K), c)

private def wrapAppAppS(c1: Lambda, c2: Lambda): Lambda = App(App(Com(S), c1), c2)
private def wrapAppAppS(c1: Lambda, c2: Lambda): Lambda =
App(App(Com(S), c1), c2)
}
Loading

0 comments on commit 6f021c7

Please sign in to comment.