Skip to content

Commit

Permalink
Merge pull request #21 from julianpeeters/dev
Browse files Browse the repository at this point in the history
Setup mdoc and github actions
  • Loading branch information
julianpeeters committed Oct 1, 2023
2 parents 6f65d0b + 0267aaa commit 9805956
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 44 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Scala CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
name: Build and Test
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
scala: [3.3.1]
java: ['11', '17']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3.13.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
- name: Run tests
run: sbt ++${{ matrix.scala }} test
23 changes: 23 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Release

on:
push:
tags: ["*"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-java@v3.13.0
with:
distribution: temurin
java-version: 8
cache: sbt
- run: sbt ci-release
env:
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
PGP_SECRET: ${{ secrets.PGP_SECRET }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
99 changes: 89 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,106 @@
# dc10
A ***D**efinitional* ***C**ompiler* for compiling models of programs into programs.
- `dc10-compile`: Evaluate metaprograms into code strings
- `dc10-io`: Evaluate metaprograms into source files
- `dc10-scala`: AST and dsl for constructing metaprograms
A ***D**efinitional* ***C**ompiler* for generating Scala code.
- [`dc10-core`](#dc10-core): Core models and abstractions for defining a language implementation
- [`dc10-io`](#dc10-io): Fs2 integration for evaluating metaprograms into source files
- [`dc10-scala`](#dc10-scala): AST and dsl for defining and rendering Scala programs

### Installation
### Getting Started
- Libraries for Scala 3 (JVM only)
- Generates code for Scala 3

#### Add the dependencies, e.g.:
```
"com.julianpeeters" %% "dc10-compile" % "0.1.0-SNAPSHOT"
```scala
"com.julianpeeters" %% "dc10-<module>" % "0.0.0"
```

### Usage

#### `dc10-scala`
### `dc10-core`
The `compile` package provides abstractions for defining and rendering code:

<details><summary>Compiler</summary>

```
package dc10.compile
trait Compiler[
F[_], // Error functor in ctx
G[_], // Output unit, e.g., List, Id, etc.
E, // Error type
A, // Code level, representing symbols introduced into ctx
B // File level, representing source files with path and ast
]:
type Ctx[_[_],_,_] // Monadic context, to build up ASTs and then compile them
extension [C, D] (ast: Ctx[F, List[D], C])
def compile: F[List[D]]
extension (res: F[G[A]])
def toString[V](using R: Renderer[V, E, G[A]]): String
extension (res: F[G[A]])
def toStringOrError[V](using R: Renderer[V, E, G[A]]): F[String]
extension (res: F[G[B]])
def toVirtualFile[V](using R: Renderer[V, E, G[A]]): F[List[VirtualFile]]
```
</details>

<details><summary>Renderer</summary>

```
package dc10.compile
trait Renderer[V, E, A]:
def render(input: A): String
def renderErrors(errors: List[E]): String
def version: V
```
</details>

Use the dsl to define some Scala code:
<details><summary>VirtualFile</summary>

```
package dc10.compile
import java.nio.file.Path
case class VirtualFile(path: Path, contents: String)
```
</details>

### `dc10-io`
The `io` package provides extension methods to write files using fs2:

```scala
_.toFile["scala-3.3.1"]
```

### `dc10-scala`

Use the dsl to define Scala code:

```scala
import cats.data.StateT
import dc10.scala.ast.Statement
import dc10.scala.dsl.{*, given}
import dc10.scala.error.ErrorF
import scala.language.implicitConversions // for literals, e.g. "hello, world"

val snippet: StateT[ErrorF, List[Statement], Unit] =
for
s <- VAL("str", STRING, "hello, world")
_ <- VAL("msg", STRING, s)
yield ()
```

Use the compiler impl to check and render code to `String` or `VirtualFile`:

```scala
import dc10.scala.compiler.{compile, toString}
import dc10.scala.version.`3.3.1`

val result: String = snippet.compile.toString["scala-3.3.1"]
// result: String = """val str: String = "hello, world"
// val msg: String = str"""
```
72 changes: 45 additions & 27 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
val CatsV = "2.9.0"
val Fs2V = "3.7.0"
val CatsV = "2.10.0"
val Fs2V = "3.9.2"
val MUnitV = "0.7.29"
val SourcePosV = "1.1.0"

ThisBuild / description := "Purely functional Scala code generation."
ThisBuild / organization := "com.julianpeeters"
ThisBuild / scalaVersion := "3.3.1"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / versionScheme := Some("semver-spec")

lazy val commonSettings = Seq(
inThisBuild(List(
crossScalaVersions := Seq(scalaVersion.value),
description := "Scala code generation tools.",
organization := "com.julianpeeters",
homepage := Some(url("https://github.com/julianpeeters/dc10")),
licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")),
developers := List(
Developer(
"julianpeeters",
"Julian Peeters",
"julianpeeters@gmail.com",
url("http://github.com/julianpeeters")
)
),
scalacOptions ++= Seq(
"-deprecation",
"-feature",
Expand All @@ -18,39 +25,50 @@ lazy val commonSettings = Seq(
"-Wunused:all",
"-Wvalue-discard"
),
libraryDependencies ++= Seq(
"org.scalameta" %% "munit" % MUnitV % Test
)
)
scalaVersion := "3.3.1",
versionScheme := Some("semver-spec"),
))

lazy val dc10 = (project in file("."))
.settings(name := "dc10")
.aggregate(`dc10-compile`, `dc10-io`, `dc10-scala`)
.aggregate(`dc10-core`, `dc10-io`, `dc10-scala`)

lazy val `dc10-compile` = (project in file("modules/compile"))
lazy val `dc10-core` = (project in file("modules/core"))
.settings(
commonSettings,
name := "dc10-compile",
libraryDependencies ++= Seq(
"org.tpolecat" %% "sourcepos" % SourcePosV,
"org.typelevel" %% "cats-core" % CatsV,
"org.typelevel" %% "cats-free" % CatsV,
)
name := "dc10-core",
)

lazy val `dc10-io` = (project in file("modules/io"))
.dependsOn(`dc10-compile`)
.dependsOn(`dc10-core`)
.settings(
commonSettings,
name := "dc10-io",
libraryDependencies ++= Seq(
"co.fs2" %% "fs2-io" % Fs2V
)
)

lazy val `dc10-scala` = (project in file("modules/scala"))
.dependsOn(`dc10-compile`)
.dependsOn(`dc10-core`)
.settings(
commonSettings,
name := "dc10-scala",
)
libraryDependencies ++= Seq(
// main
"org.tpolecat" %% "sourcepos" % SourcePosV,
"org.typelevel" %% "cats-core" % CatsV,
"org.typelevel" %% "cats-free" % CatsV,
// test
"org.scalameta" %% "munit" % MUnitV % Test
)
)

lazy val docs = project.in(file("docs/gitignored"))
.settings(
mdocOut := dc10.base,
mdocVariables := Map(
"SCALA" -> crossScalaVersions.value.map(e => e.takeWhile(_ != '.')).mkString(", "),
"VERSION" -> version.value.takeWhile(_ != '+'),
)
)
.dependsOn(`dc10-core`, `dc10-io`, `dc10-scala`)
.enablePlugins(MdocPlugin)
.enablePlugins(NoPublishPlugin)
104 changes: 104 additions & 0 deletions docs/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# dc10
A ***D**efinitional* ***C**ompiler* for generating Scala code.
- [`dc10-core`](#dc10-core): Core models and abstractions for defining a language implementation
- [`dc10-io`](#dc10-io): Fs2 integration for evaluating metaprograms into source files
- [`dc10-scala`](#dc10-scala): AST and dsl for defining and rendering Scala programs

### Getting Started
- Libraries for Scala @SCALA@ (JVM only)
- Generates code for Scala @SCALA@

```scala
"com.julianpeeters" %% "dc10-<module>" % "@VERSION@"
```

### Usage

### `dc10-core`
The `compile` package provides abstractions for defining and rendering code:

<details><summary>Compiler</summary>

```
package dc10.compile
trait Compiler[
F[_], // Error functor in ctx
G[_], // Output unit, e.g., List, Id, etc.
E, // Error type
A, // Code level, representing symbols introduced into ctx
B // File level, representing source files with path and ast
]:
type Ctx[_[_],_,_] // Monadic context, to build up ASTs and then compile them
extension [C, D] (ast: Ctx[F, List[D], C])
def compile: F[List[D]]
extension (res: F[G[A]])
def toString[V](using R: Renderer[V, E, G[A]]): String
extension (res: F[G[A]])
def toStringOrError[V](using R: Renderer[V, E, G[A]]): F[String]
extension (res: F[G[B]])
def toVirtualFile[V](using R: Renderer[V, E, G[A]]): F[List[VirtualFile]]
```
</details>

<details><summary>Renderer</summary>

```
package dc10.compile
trait Renderer[V, E, A]:
def render(input: A): String
def renderErrors(errors: List[E]): String
def version: V
```
</details>

<details><summary>VirtualFile</summary>

```
package dc10.compile
import java.nio.file.Path
case class VirtualFile(path: Path, contents: String)
```
</details>

### `dc10-io`
The `io` package provides extension methods to write files using fs2:

```scala
_.toFile["scala-3.3.1"]
```

### `dc10-scala`

Use the dsl to define Scala code:

```scala mdoc:silent
import cats.data.StateT
import dc10.scala.ast.Statement
import dc10.scala.dsl.{*, given}
import dc10.scala.error.ErrorF
import scala.language.implicitConversions // for literals, e.g. "hello, world"

val snippet: StateT[ErrorF, List[Statement], Unit] =
for
s <- VAL("str", STRING, "hello, world")
_ <- VAL("msg", STRING, s)
yield ()
```

Use the compiler impl to check and render code to `String` or `VirtualFile`:

```scala mdoc
import dc10.scala.compiler.{compile, toString}
import dc10.scala.version.`3.3.1`

val result: String = snippet.compile.toString["scala-3.3.1"]
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package dc10.compile

import cats.kernel.Monoid

trait Compiler[
F[_], // Error functor in ctx
G[_], // Output unit, e.g., List, Id, etc.
Expand All @@ -12,8 +10,8 @@ trait Compiler[

type Ctx[_[_],_,_] // Monadic context, to build up ASTs and then compile them

extension [L: Monoid, A] (ast: Ctx[F, L, A])
def compile: F[L]
extension [C, D] (ast: Ctx[F, List[D], C])
def compile: F[List[D]]

extension (res: F[G[A]])
def toString[V](using R: Renderer[V, E, G[A]]): String
Expand Down

0 comments on commit 9805956

Please sign in to comment.