I am trying to write a DSL with Scala. I would initially like to be able to write things like
defType "foo"
when using it.
I had thought that the following should work:
src/main/scala/Test.scala
class Dsl {
def defType(name: String) = "dummy"
}
object Dsl {
def apply() = new Dsl()
}
class UseDsl {
def foo() = {
val dsl = Dsl()
import dsl._
dsl defType "foo"
defType("foo")
defType "foo"
}
}
This fails to compile:
[error] Test.scala:15:17: ';' expected but string literal found.
[error] defType "foo"
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
Explicitly giving dsl works with spaces to separate the method names and arguments.
Implicitly using dsl and parentheses to indicate arguments vs method names works.
Attempting to use both of them together fails.
Is there a way to get that to work?
Once this is working, I plan to extend the DSL to support things like
defType "foo"
-- "bar1" :: "quz"
-- "bar2" :: "quz"
which would be equivalent to
dsl.defType("foo").
--(ImplicitClass("bar1", dsl).::("quz")).
--(ImplicitClass("bar2", dsl).::("quz"))
Is this something that I will be able to get to work? I think the ImplicitClass would work with a declaration like
def implicit ImplicitClass(a: String, implicit dsl: Dsl) = ...
but clearly, my understanding of how you can get Scala to add things to your code is imperfect.
If it won't work, what are some minimal additions that would let it work?
build.sbt
ThisBuild / organization := "test"
ThisBuild / version := "0.0.1-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.8"
//
// Projects
//
lazy val root = (project in file("."))