@@ -27,17 +27,13 @@ class RecorderMacro(using qctx0: Quotes) {
27
27
recording : Expr [A ],
28
28
message : Expr [String ],
29
29
listener : Expr [RecorderListener [A , R ]]): Expr [R ] = {
30
- val termArg : Term = recording.asTerm.underlyingArgument // TODO remove use of underlyingArgument
30
+ val termArg = recording.asTerm.underlyingArgument.asExprOf[ A ] // TODO remove use of underlyingArgument
31
31
32
32
' {
33
33
val recorderRuntime : RecorderRuntime [A , R ] = new RecorderRuntime ($listener)
34
34
recorderRuntime.recordMessage($message)
35
- $ {
36
- Block (
37
- recordExpressions(' { recorderRuntime }.asTerm, termArg),
38
- ' { recorderRuntime.completeRecording() }.asTerm
39
- ).asExprOf[R ]
40
- }
35
+ $ {recordExpressions(' recorderRuntime , termArg)}
36
+ recorderRuntime.completeRecording()
41
37
}
42
38
}
43
39
@@ -46,33 +42,22 @@ class RecorderMacro(using qctx0: Quotes) {
46
42
found : Expr [A ],
47
43
message : Expr [String ],
48
44
listener : Expr [RecorderListener [A , R ]]): Expr [R ] = {
49
- val expectedArg : Term = expected.asTerm
50
- val foundArg : Term = found.asTerm
51
-
52
45
' {
53
46
val recorderRuntime : RecorderRuntime [A , R ] = new RecorderRuntime ($listener)
54
47
recorderRuntime.recordMessage($message)
55
- $ {
56
- Block (
57
- recordExpressions(' { recorderRuntime }.asTerm, expectedArg) :::
58
- recordExpressions(' { recorderRuntime }.asTerm, foundArg),
59
- ' { recorderRuntime.completeRecording() }.asTerm
60
- ).asExprOf[R ]
61
- }
48
+ $ {recordExpressions(' recorderRuntime , expected)}
49
+ $ {recordExpressions(' recorderRuntime , found)}
50
+ recorderRuntime.completeRecording()
62
51
}
63
52
}
64
53
65
- private [this ] def recordExpressions (runtime : Term , recording : Term ): List [ Term ] = {
54
+ private [this ] def recordExpressions [ A : Type , R : Type ] (runtime : Expr [ RecorderRuntime [ A , R ]], recording : Expr [ A ] ): Expr [ Any ] = {
66
55
val source = getSourceCode(recording)
67
- val ast = recording.show(using Printer .TreeStructure )
56
+ val ast = recording.asTerm. show(using Printer .TreeStructure )
68
57
69
- val resetValuesSel : Term = {
70
- val m = runtimeSym.memberMethod(" resetValues" ).head
71
- runtime.select(m)
72
- }
73
58
try {
74
- List (
75
- Apply (resetValuesSel, List () ),
59
+ Expr .block (
60
+ List ( ' { $runtime.resetValues() } ),
76
61
recordExpression(runtime, source, ast, recording)
77
62
)
78
63
} catch {
@@ -82,21 +67,14 @@ class RecorderMacro(using qctx0: Quotes) {
82
67
}
83
68
84
69
// emit recorderRuntime.recordExpression(<source>, <tree>, instrumented)
85
- private [this ] def recordExpression (runtime : Term , source : String , ast : String , expr : Term ): Term = {
86
- val instrumented = recordAllValues(runtime, expr)
87
- val recordExpressionSel : Term = {
88
- val m = runtimeSym.memberMethod(" recordExpression" ).head
89
- runtime.select(m)
90
- }
91
- Apply (recordExpressionSel,
92
- List (
93
- Literal (StringConstant (source)),
94
- Literal (StringConstant (ast)),
95
- instrumented
96
- ))
70
+ private [this ] def recordExpression [R : Type , A : Type ](runtime : Expr [RecorderRuntime [A , R ]], source : String , ast : String , expr : Expr [A ]): Expr [Any ] = {
71
+ val instrumented = recordAllValues(runtime, expr.asTerm).asExprOf[A ]
72
+ val sourceExpr = Expr (source)
73
+ val astExpr = Expr (ast)
74
+ ' { $runtime.recordExpression($sourceExpr, $astExpr, $instrumented) }
97
75
}
98
76
99
- private [this ] def recordAllValues (runtime : Term , expr : Term ): Term =
77
+ private [this ] def recordAllValues [ R , A ] (runtime : Expr [ RecorderRuntime [ A , R ]] , expr : Term ): Term =
100
78
// TODO use an TreeMap or an ExprMap
101
79
expr match {
102
80
case New (_) => expr
@@ -109,7 +87,7 @@ class RecorderMacro(using qctx0: Quotes) {
109
87
case _ => recordValue(runtime, recordSubValues(runtime, expr), expr)
110
88
}
111
89
112
- private [this ] def recordSubValues (runtime : Term , expr : Term ): Term =
90
+ private [this ] def recordSubValues [ R , A ] (runtime : Expr [ RecorderRuntime [ A , R ]] , expr : Term ): Term =
113
91
expr match {
114
92
case Apply (x, ys) =>
115
93
try {
@@ -125,12 +103,12 @@ class RecorderMacro(using qctx0: Quotes) {
125
103
case _ => expr
126
104
}
127
105
128
- private [this ] def recordValue (runtime : Term , expr : Term , origExpr : Term ): Term = {
106
+ private [this ] def recordValue [ R , A ] (runtime : Expr [ RecorderRuntime [ A , R ]] , expr : Term , origExpr : Term ): Term = {
129
107
// debug
130
108
// println("recording " + expr.showExtractors + " at " + getAnchor(expr))
131
109
val recordValueSel : Term = {
132
110
val m = runtimeSym.memberMethod(" recordValue" ).head
133
- runtime.select(m)
111
+ runtime.asTerm. select(m)
134
112
}
135
113
def skipIdent (sym : Symbol ): Boolean =
136
114
sym match {
@@ -156,6 +134,9 @@ class RecorderMacro(using qctx0: Quotes) {
156
134
case TypeApply (_, _) => expr
157
135
case Ident (_) if skipIdent(expr.symbol) => expr
158
136
case _ =>
137
+ // TODO:
138
+ // expr.asExpr match { case '{ $e: t } => '{ $runtime.recordValue[t]($e, ${Expr(getAnchor(expr))}) } }
139
+ // Then remove `runtimeSym`
159
140
val tapply = recordValueSel.appliedToType(expr.tpe)
160
141
Apply .copy(expr)(
161
142
tapply,
@@ -167,8 +148,8 @@ class RecorderMacro(using qctx0: Quotes) {
167
148
}
168
149
}
169
150
170
- private [this ] def getSourceCode (expr : Tree ): String = {
171
- val pos = expr.pos
151
+ private [this ] def getSourceCode (expr : Expr [ Any ] ): String = {
152
+ val pos = expr.asTerm. pos
172
153
(" " * pos.startColumn) + pos.sourceCode.get
173
154
}
174
155
0 commit comments