-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OpIntercept to allow custom types and operations #149
Open
soronpo
wants to merge
9
commits into
fthomas:master
Choose a base branch
from
soronpo:op_intercept
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2277a09
Add OpIntercept to allow custom types and operations
a56f62b
Assume caching to be unique to the running operation without specifyi…
14d3c9f
fix calculation missing unknown return
4daee9a
Added error cases coverage and fixed literals for pre-2.13 scala
b87d834
fix minor issue
6a278b7
changed method of procuring the Out for OpIntercept
aa14d5e
add value support
6e5868a
fixed test-case for scala pre-2.13
299e10f
wip
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package singleton.ops | ||
import scala.reflect.macros.whitebox | ||
import impl._ | ||
|
||
import scala.annotation.implicitNotFound | ||
|
||
trait OpIntercept[Op <: HasOut] | ||
object OpIntercept { | ||
@implicitNotFound("Failed to cache with result ${Out}") | ||
trait CacheResult[Out] | ||
object CacheResult { | ||
implicit def call[Out] : CacheResult[Out] = macro Macro.materializeCacheResult[Out] | ||
final class Macro(val c: whitebox.Context) extends GeneralMacros { | ||
def materializeCacheResult[ | ||
Out: c.WeakTypeTag | ||
]: c.Tree = cacheOpInterceptResult[Out] | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package singleton.ops | ||
|
||
import org.scalacheck.Properties | ||
import shapeless.test.illTyped | ||
import singleton.TestUtils._ | ||
|
||
class OpInterceptSpec extends Properties("OpInterceptSpec") { | ||
|
||
trait Vec[A0, A1] | ||
|
||
implicit def `Vec+`[VL0, VL1, VR0, VR1, VO0, VO1]( | ||
implicit | ||
opL : OpAuxGen[VL0 + VR0, VO0], | ||
opR : OpAuxGen[VL1 + VR1, VO1], | ||
result : OpIntercept.CacheResult[Vec[VO0, VO1]] | ||
) : OpIntercept[Vec[VL0, VL1] + Vec[VR0, VR1]] = ??? | ||
|
||
implicit def `Vec==`[VL0, VL1, VR0, VR1, EqOut]( | ||
implicit | ||
op : OpAuxGen[(VL0 == VR0) && (VL1 == VR1), EqOut], | ||
result : OpIntercept.CacheResult[EqOut] | ||
) : OpIntercept[Vec[VL0, VL1] == Vec[VR0, VR1]] = ??? | ||
|
||
|
||
property("Custom Vec Equality OK") = wellTyped { | ||
val eq1 = shapeless.the[Vec[W.`1`.T, W.`2`.T] == Vec[W.`1`.T, W.`2`.T]] | ||
val eq2 = shapeless.the[Vec[W.`1`.T, W.`2`.T] == Vec[W.`1`.T, W.`1`.T]] | ||
implicitly[eq1.Out =:= W.`true`.T] | ||
implicitly[eq2.Out =:= W.`false`.T] | ||
} | ||
|
||
property("Custom Vec Addition OK") = wellTyped { | ||
val add2 = shapeless.the[Vec[W.`1`.T, W.`2`.T] + Vec[W.`3`.T, W.`8`.T]] | ||
val add3 = shapeless.the[Vec[W.`1`.T, W.`2`.T] + Vec[W.`3`.T, W.`8`.T] + Vec[W.`20`.T, W.`20`.T]] | ||
implicitly[add2.Out =:= Vec[W.`4`.T, W.`10`.T]] | ||
implicitly[add3.Out =:= Vec[W.`24`.T, W.`30`.T]] | ||
val add23 = shapeless.the[add2.Out + add3.Out] | ||
implicitly[add23.Out =:= Vec[W.`28`.T, W.`40`.T]] | ||
} | ||
|
||
trait FibId | ||
type Fib[P] = impl.OpMacro[FibId, P, W.`0`.T, W.`0`.T] | ||
implicit def doFib[P, Out]( | ||
implicit | ||
op : OpAuxGen[ITE[P == W.`0`.T, W.`0`.T, ITE[P == W.`1`.T, W.`1`.T, Fib[P - W.`1`.T] + Fib[P - W.`2`.T]]], Out], | ||
result : OpIntercept.CacheResult[Out] | ||
) : OpIntercept[Fib[P]] = ??? | ||
|
||
|
||
property("Custom Fibonacci Op OK") = wellTyped { | ||
val fib4 = shapeless.the[Fib[W.`4`.T]] | ||
implicitly[fib4.Out =:= W.`3`.T] | ||
val fib10 = shapeless.the[Fib[W.`10`.T]] | ||
implicitly[fib10.Out =:= W.`55`.T] | ||
} | ||
|
||
|
||
trait FooOpId | ||
type FooOp[C, M] = impl.OpMacro[FooOpId, C, M, W.`0`.T] | ||
implicit def FooOp[C, M]( | ||
implicit | ||
r : RequireMsg[C, M], | ||
result : OpIntercept.CacheResult[W.`true`.T] | ||
) : OpIntercept[FooOp[C, M]] = ??? | ||
|
||
property("Error Message Propagation") = wellTyped { | ||
illTyped("""shapeless.the[FooOp[W.`false`.T, W.`"this is a test"`.T]]""", "this is a test") | ||
} | ||
|
||
trait BarOpId | ||
type BarOp[C, M] = impl.OpMacro[BarOpId, C, M, W.`0`.T] | ||
implicit def BarOp[C, M]( | ||
implicit | ||
op : C + M | ||
) : OpIntercept[BarOp[C, M]] = ??? | ||
|
||
property("Missing Caching Error") = wellTyped { | ||
illTyped("""shapeless.the[BarOp[W.`1`.T, W.`2`.T]]""", "Missing a result cache for OpIntercept. Make sure you set `OpIntercept.CacheResult`") | ||
} | ||
|
||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is totally nitpicking, but IIUC, the convention for
Either
is that theLeft
is the "error" condition, isn't it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I've rarely used it in this fashion, so forgot. I'll fix.