| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unliftable is a type class similar to existing Liftable that lets
users to extract custom data types out of trees with the help of
straightforward type ascription syntax:
val q“foo.bar(${baz: Baz})” = ...
This will use Unliftable[Baz] to extract custom data type Baz out of
a tree nested inside of the another tree. A simpler example would be
extracting of constant values:
val q”${x: Int} + ${y: Int}” = q”1 + 2”
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit performs a number of preliminary refactoring needed to
implement unliftable:
1. Replace previous inheritance-heavy implementation of Holes with
similar but much simpler one. Holes are now split into two different
categories: ApplyHole and UnapplyHole which correspondingly represent
information about holes in construction and deconstruction quasiquotes.
2. Make Placeholders extract holes rather than their field values. This
is required to be able to get additional mode-specific information
from holes (e.g. only ApplyHoles have types).
3. Bring ApplyReifier & UnapplyReifier even closer to the future where
there is just a single base Reifier with mode parameter.
Along the way a few bugs were fixed:
1. SI-7980 SI-7996 fail with nice error on bottom types splices
2. Use asSeenFrom instead of typeArguments in parseCardinality.
This fixes a crash if T <:< Iterable[Tree] but does not itself
have any type arguments.
3. Fix spurious error message on splicing of Lists through Liftable[List[T]]
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously we believed that having Liftable outside of the Universe will
bring some advantages but it turned out this wasn’t worth it. Due to
infectious nature of path dependent types inside of the universe one
had to cast a lot. A nice example of what I’m talking about is a change
in trait ArbitraryTreesAndNames.
Additionally a number of standard Liftables is added for types that are
available through Predef and/or default scala._ import: Array, Vector,
List, Map, Set, Option, Either, TupleN.
|
| |
|
|
|
|
|
|
|
|
|
| |
Previously trees that represent parameters, case clauses and
type variables had strictly defined ValDef, TypeDef and CaseDef
types which caused problems in compositionality.
Now this checks are moved to runtime so it's possible to pass
a tree that is CaseDef but has Tree type.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Previously it also matched other nodes but returned Nil as value of xs.
This behavior was added for sake of consistentcy with q”f[..$ts]”. On
the other hand q”f[..$Nil]” == q”f” but q”f(..$Nil)” == q”f()” not q”f”.
Due to this deconstruction/construction symmetry was broken.
On the other hand applications also have q"f(...$xss)" option which is
infact similar to q"f[..$ts]". Splicing Nil into it also results in q"f".
|
|\
| |
| | |
Refactor out fresh name prefix extraction logic
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
1. refactor out FreshNameExtractor out of Quasiquotes cake into
SymbolTable (can’t put it outside due to the fact that names are
path-dependent)
2. add optional parameter to the fresh name creator to cover additional
qq$ prefix needed for quasiquotes
3. add unit tests
|
|\ \
| | |
| | | |
Removing deprecated code.
|
| |/
| |
| |
| |
| | |
Code which has been deprecated since 2.10.0 and which allowed
for straightforward removal.
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Our scalacheck tests now compile against 1.10.1 and 1.11.0.
They pass on 1.10.1, but fail on 1.11.0.
Once (that)[https://github.com/rickynils/scalacheck/issues/79]'s fixed,
and 1.11.1 released, we should be able to upgrade to it by simply
changing scalacheck.version.number in versions.properties.
The changes are mostly removing dead code (e.g., consolereporter business).
Of interest: the type ascription for `oneOf`. I haven't quite investigated,
but something seems to have changed between 1.10.1 and 1.11.0 that caused
a different overload to be picked without the type ascription.
Probably not a scalac bug, just a scalacheck api change.
|
| |
|
|
|
|
|
|
| |
1. q"for (..$enums) $body", q"for (..$enums) yield $body"
2. fq"..." quote to construct/deconstruct enumerators
|
|
|
|
|
|
|
|
|
|
|
| |
This effectively reconstructs a sequence of enumerators and body
from the tree produced by mkFor. This lets to define bi-directional
SyntacticFor and SyntacticForYield constructors/extractors to work
with for loops.
Correctness of the transformation is tested by a scalacheck test
that generates a sequence of random enumerators, sugars them into
maps/flatMaps/foreach/withFilter calls and reconstructs them back.
|
|
|
|
|
|
| |
Otherwise it's annoying that trees that look the same are not equal
due to some fresh name hidden underneath. Due to this one test needs
to be changed to use plain equalsStructure.
|
| |
|
|
|
|
|
|
| |
Typecheck trees with toolbox and check that they are still matched
by corresponding quasiquote. Fix tuples and function types matchers
to account for different shape of trees after typing.
|
|
|
|
|
|
| |
Previously tuple tree generation code has been implemented in
three place: tree builder, tree gen, build utils. Now it's just
defined once in tree gen.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously quasiquote arguments were type checked against Any
which caused weird inference that made splicing of complex expressions
unusable:
val l1 = List(q"foo")
val l2 = List(q"bar")
q"f(..${l1 ++ l2})" // argument type checked as Any instead of List[Tree]
This is fixed by forcing compiler to type check against type
variable which itself isn't used in any other way.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
During parsing some names are generated artificially using freshTermName & freshTypeName (e.g. `x$1`). Such names should be reified in a different way because they are assumed to be always fresh and non-overlapping with the environment. So `x$1` should reify down to equivalent of `freshTermName("x$")` rather than `TermName("x$1")`.
But this is not enough. One name can be used more than once in a tree. E.g. `q"_ + 1"` desugars into `q"x$1 => x$1 + 1"`. So we need to ensure that every place where `x$1` is used gets the same fresh name. Hence the need for `withFreshTermName` that lets q"_ + 1" quasiquote desugare into equivalent of `withFreshTermName("x$") { freshx => q"$freshx => $freshx + 1" }`.
For pattern quasiquotes it's a bit different. Due to the fact that end-result must be a pattern we need to represent fresh names as patterns too. A natural way to express that something is fresh is to represent it as a free variable (e.g. any name will do in that place). But due to possible use of the same name in multiple places we need to make sure that all such places have the same values by adding a sequence of guards to the pattern.
Previously such names were reified naively and it could have caused name collision problems and inability to properly much on trees that contain such names.
|
|
|
|
|
|
|
| |
Previously due to limited support for expansion in apply position
quasiquotes had to use a compiler hook for deconstruction. Now with
recent changes in pattern matcher it's possible to remove that special
case.
|
| |
|
|
|
|
|
|
| |
In order to implement this a new parser entry point
`parseStatsOrPackages` that augments current parseStats with ability
to parse "package name { ... }" syntax.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
There are three kinds of assign-like trees:
1. Assign(lhs, rhs) // $lhs = $rhs
3. AssignOrNamedArg(lhs, rhs) // $lhs = $rhs
2. Apply(Select(f, nme.update), args :+ rhs) // $f(..$args) = $rhs
New syntactic combinator unifies all of them and lets users not to think
about these implementations details.
|
| |
|
|
|
|
|
|
| |
Syntax spec mislead me to believe that annotation can't have type
parameters or multiple argument lists... I guess the lesson here is
don't trust the spec.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
1. blocks now match single term-level expressions to account for
automatic block elimination. E.g.
val q"{ ..$stats }" = q"foo"
will match into stats = List(q"foo"). This is useful to uniformly
deal with blocks on term level.
2. blocks in quasiquotes collapse into single expressions
3. Applied and TypeApplied now have constructors too which helps
to unify matching and extraction in quasiquote reifier
4. TypeApplied now matches AppliedTypeTree too
5. Add Syntactic prefix to Applied and TypeApplied
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is achieved in a following way:
1. Similarly to toolbox quasiquotes can go away with wrapping for
parsing purpose after introduction of `parseStats` and `parseRule`
entry points.
2. In case of syntax error quasiquote computes equivalent corresponding
position in the source code with the help of `corrrespondingPosition`
mapper which relies on position data collected into `posMap` during
code generation.
|
|
|
|
|
| |
Now when there's no hope left for type macros, it's reasonable to provide
a more specific type for DefDef.name.
|
|
Introduces an extensive ScalaCheck-based test suite for recently
implemented quasiquotes. Provides tools for syntactic tree comparison
and verifying compilation error messages.
|