Skip to content

Commit

Permalink
INTERP fixes #20
Browse files Browse the repository at this point in the history
  • Loading branch information
eed3si9n committed Sep 1, 2013
1 parent a3acf89 commit 865376d
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 129 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Expand Up @@ -3,7 +3,7 @@ import Dependencies._

val commonSettings = Seq(
organization := "com.eed3si9n",
version := "0.2.4-SNAPSHOT",
version := "0.3.0-SNAPSHOT",
scalaVersion := "2.10.2",
crossScalaVersions := Seq("2.10.2", "2.9.2", "2.9.1", "2.9.0-1"),
homepage := Some(url("http://eed3si9n.com/treehugger")),
Expand Down
128 changes: 8 additions & 120 deletions docs/02/e/14.markdown
@@ -1,134 +1,22 @@
---
out: typelevelexp.html
out: stringinterpolation.html
---

[1]: stdtypcon.html
String Interpolation
--------------------

Type-Level Expressions
----------------------

### Type references

Use `TYPE_REF(tree|sym|"C")` to explicitly convert symbols, names, and trees into types:

```scala
(VAL("pos", TYPE_REF(REF("board") DOT "Coord")): Tree)
```

This prints as:

```
val pos: board.Coord
```

### Applied types

Applied types are written by calling `TYPE_OF(typ|"C", ...)` on a type:

```scala
REF("x") withType(ListClass TYPE_OF IntClass)
```

This prints as:
String interpolations are written using `INTERP(sym|"x", arg, ...)`:

```scala
(x: List[Int])
```
INTERP(StringContext_s, LIT("Jello"), LIT(1), REF("x"))

### Type constructors

treehugger DSL provides built-in type constructors, which will be covered more [later][1]:

```scala
REF("x") withType(TYPE_LIST(IntClass))
REF("y") withType(TYPE_TUPLE(IntClass, IntClass))
REF("z") withType(IntClass TYPE_=> IntClass)
INTERP("s", LIT("Hello"), LIT(1), REF("x"))
```

These examples print as:

```scala
(x: List[Int])
(y: (Int, Int))
(z: Int => Int)
```

### Refined types

Refined types are written by calling `TYPE_WITH (typ|"C", ...)` on a type:

```scala
(VAL("x", TYPE_REF("A") TYPE_WITH "B"): Tree)
```

This prints as:

```scala
val x: A with B
```

### Singleton types

Singleton type are written using `TYPE_SINGLETON(tree)`:

```scala
(VAL("x", TYPE_SINGLETON(THIS)): Tree)
```

This prints as:

```scala
val x: this.type
```

### Structural types

Structural types are written using `TYPE_STRUCT(tree, ...)`:

```scala
REF("x") withType(TYPE_STRUCT(
DEF("close", UnitClass)
))
```

This prints as:

```scala
(x: ({ def close: Unit }))
```

### Type projections

Type projections are written by calling `TYPE_# (typ|"C")` on a type:

```scala
REF("x") withType(TYPE_STRUCT(
TYPEVAR("L") withTypeParams(TYPEVAR("A")) :=
REF("Const") APPLYTYPE ("M", "A")
) TYPE_#("L"))
```

This prints as:

```scala
(foo: ({ type L[A] = Const[M, A] })#L)
```

### Existential types

Existential types are written by calling `TYPE_FORSOME(tree, ...)` on a type:

```scala
(DEF("foo")
withParams(PARAM("arg", TYPE_LIST(
TYPE_REF(REF("x") DOT "T")) TYPE_FORSOME(
VAL("x", "Outer")
)))).tree
```

This prints as:
s"Jello\${1}\$x"

```scala
def foo(arg: List[x.T] forSome { val x: Outer })
s"Hello\${1}\$x"
```

134 changes: 134 additions & 0 deletions docs/02/e/15.markdown
@@ -0,0 +1,134 @@
---
out: typelevelexp.html
---

[1]: stdtypcon.html

Type-Level Expressions
----------------------

### Type references

Use `TYPE_REF(tree|sym|"C")` to explicitly convert symbols, names, and trees into types:

```scala
(VAL("pos", TYPE_REF(REF("board") DOT "Coord")): Tree)
```

This prints as:

```
val pos: board.Coord
```

### Applied types

Applied types are written by calling `TYPE_OF(typ|"C", ...)` on a type:

```scala
REF("x") withType(ListClass TYPE_OF IntClass)
```

This prints as:

```scala
(x: List[Int])
```

### Type constructors

treehugger DSL provides built-in type constructors, which will be covered more [later][1]:

```scala
REF("x") withType(TYPE_LIST(IntClass))
REF("y") withType(TYPE_TUPLE(IntClass, IntClass))
REF("z") withType(IntClass TYPE_=> IntClass)
```

These examples print as:

```scala
(x: List[Int])
(y: (Int, Int))
(z: Int => Int)
```

### Refined types

Refined types are written by calling `TYPE_WITH (typ|"C", ...)` on a type:

```scala
(VAL("x", TYPE_REF("A") TYPE_WITH "B"): Tree)
```

This prints as:

```scala
val x: A with B
```

### Singleton types

Singleton type are written using `TYPE_SINGLETON(tree)`:

```scala
(VAL("x", TYPE_SINGLETON(THIS)): Tree)
```

This prints as:

```scala
val x: this.type
```

### Structural types

Structural types are written using `TYPE_STRUCT(tree, ...)`:

```scala
REF("x") withType(TYPE_STRUCT(
DEF("close", UnitClass)
))
```

This prints as:

```scala
(x: ({ def close: Unit }))
```

### Type projections

Type projections are written by calling `TYPE_# (typ|"C")` on a type:

```scala
REF("x") withType(TYPE_STRUCT(
TYPEVAR("L") withTypeParams(TYPEVAR("A")) :=
REF("Const") APPLYTYPE ("M", "A")
) TYPE_#("L"))
```

This prints as:

```scala
(foo: ({ type L[A] = Const[M, A] })#L)
```

### Existential types

Existential types are written by calling `TYPE_FORSOME(tree, ...)` on a type:

```scala
(DEF("foo")
withParams(PARAM("arg", TYPE_LIST(
TYPE_REF(REF("x") DOT "T")) TYPE_FORSOME(
VAL("x", "Outer")
)))).tree
```

This prints as:

```scala
def foo(arg: List[x.T] forSome { val x: Outer })
```

2 changes: 1 addition & 1 deletion docs/template.properties
@@ -1,2 +1,2 @@
version=0.2.3
version=0.3.0
toc = collapse
4 changes: 4 additions & 0 deletions library/src/main/scala/treehugger/Definitions.scala
Expand Up @@ -228,6 +228,10 @@ trait Definitions extends api.StandardDefinitions { self: Forest =>
lazy val JavaCloneableClass = getClass("java.lang.Cloneable")
lazy val RemoteInterfaceClass = getClass("java.rmi.Remote")
lazy val RemoteExceptionClass = getClass("java.rmi.RemoteException")
lazy val StringContextClass = getClass("scala.StringContext")
lazy val StringContext_f = getMember(StringContextClass, "f")
lazy val StringContext_raw = getMember(StringContextClass, "raw")
lazy val StringContext_s = getMember(StringContextClass, "s")

lazy val RepeatedParamClass = newCovariantPolyClass(
ScalaPackageClass,
Expand Down
18 changes: 17 additions & 1 deletion library/src/main/scala/treehugger/TreePrinters.scala
Expand Up @@ -221,6 +221,20 @@ trait TreePrinters extends api.TreePrinters { self: Forest =>
}
}

def printInterpolatedString(tree: Interpolated): Unit = {
print(tree.interpolator)
print("\"")
tree.args foreach { _ match {
case Literal(x) if x.tag == StringTag =>
print((x.stringValue map x.escapedChar) mkString "")
case Ident(x) =>
print("$", x)
case arg =>
print("${", arg, "}")
}}
print("\"")
}

private var currentOwner: Symbol = NoSymbol
private var selectorType: Type = NoType

Expand Down Expand Up @@ -664,7 +678,9 @@ trait TreePrinters extends api.TreePrinters { self: Forest =>
case _ => print(args(0))
}
else printRow(args, "(", ", ", ")")

case x: Interpolated =>
printInterpolatedString(x)

// SelectFromArray is no longer visible in reflect.internal.
// eliminated until we figure out what we will do with both TreePrinters and
// SelectFromArray.
Expand Down
11 changes: 10 additions & 1 deletion library/src/main/scala/treehugger/api/Trees.scala
Expand Up @@ -708,7 +708,13 @@ trait Trees { self: Universe =>
case class ForTree(enums: List[Enumerator], body: Tree) extends Tree

case class ForYieldTree(enums: List[Enumerator], body: Tree) extends Tree


case class Interpolated(interpolator: Name, args: List[Tree])
extends Tree

def Interpolated(sym: Symbol, args: List[Tree]): Interpolated =
Interpolated(sym.name, args)

// ------ traversers, copiers, and transformers ---------------------------------------------

val treeCopy = newLazyTreeCopier
Expand Down Expand Up @@ -836,6 +842,9 @@ trait Trees { self: Universe =>
traverse(test)
case Infix(qual, fun, args) =>
traverse(qual); traverseTrees(args)
case Interpolated(interpolator, args) =>
traverseTrees(args)

case _ => xtraverse(this, tree)
}

Expand Down
3 changes: 3 additions & 0 deletions library/src/main/scala/treehugger/treehuggerdsls.scala
Expand Up @@ -757,6 +757,9 @@ trait TreehuggerDSLs { self: Forest =>
def FOR(xs: Iterable[Enumerator]): ForStart = new ForStart(xs.toList)
def WHILE(tree: Tree) = new WhileStart(tree)

def INTERP(sym: Symbol, args: Tree*): Interpolated = Interpolated(sym, args.toList)
def INTERP(name: Name, args: Tree*): Interpolated = Interpolated(name, args.toList)

def BLOCK(xs: Iterable[Tree]) = Block(xs.toList: _*)
def BLOCK(xs: Tree*) = Block(xs: _*)
def NOT(tree: Tree) = Select(tree, Boolean_not)
Expand Down
7 changes: 7 additions & 0 deletions library/src/test/scala/DSL_3ExpressionSpec2.scala
Expand Up @@ -14,6 +14,9 @@ class DSL_3ExpressionSpec2 extends DSLSpec { def is = s2
`tree INFIX(sym|"op", arg, ...)`, $infix2
`tree INFIX_CHAIN(sym|"op", tree, ...)`, $infix3

String interpolations are written as
`INTERP(sym|"x", arg, ...)`, $interpolation1

Assignments are written as
`tree := rhs`. $assignment1

Expand Down Expand Up @@ -96,6 +99,10 @@ class DSL_3ExpressionSpec2 extends DSLSpec { def is = s2
def infix3 =
(INFIX_CHAIN("+", LIT(1), LIT(2), LIT(3)) must print_as("1 + 2 + 3")) and
(INFIX_CHAIN(Any_==, LIT(1) :: LIT(2) :: LIT(3) :: Nil) must print_as("1 == 2 == 3"))

def interpolation1 =
(INTERP("s", LIT("Hello\n"), LIT(1), REF("x")) must print_as("s\"Hello\\n${1}$x\"")) and
(INTERP(StringContext_s, LIT("Jello"), LIT(1), REF("x")) must print_as("s\"Jello${1}$x\""))

def assignment1 = (REF("x") := LIT(0)) must print_as("x = 0")

Expand Down
5 changes: 0 additions & 5 deletions notes/0.2.4.markdown

This file was deleted.

0 comments on commit 865376d

Please sign in to comment.