@@ -29,25 +29,40 @@ import java.lang.reflect.Method
29
29
* previously compiled and is present in the classpath of the current context.
30
30
*/
31
31
class Interpreter (implicit ctx : Context ) {
32
- import tpd ._
33
-
34
- type Env = Map [Symbol , Object ]
35
32
36
33
private [this ] val classLoader = {
37
34
val urls = ctx.settings.classpath.value.split(':' ).map(cp => java.nio.file.Paths .get(cp).toUri.toURL)
38
35
new URLClassLoader (urls, getClass.getClassLoader)
39
36
}
40
37
41
- /** Returns the interpreted result of interpreting the code represented by the tree .
38
+ /** Returns the interpreted result of interpreting the code a call to the symbol with default arguments .
42
39
* Return Some of the result or None if some error happen during the interpretation.
43
40
*/
44
- def interpretTree [T ](tree : Tree )(implicit ct : ClassTag [T ]): Option [T ] = {
41
+ def interpretCallToSymbol [T ](sym : Symbol )(implicit pos : Position , ct : ClassTag [T ]): Option [T ] = {
45
42
try {
46
- interpretTreeImpl(tree, Map .empty) match {
43
+ val clazz = loadClass(sym.owner.companionModule.fullName)(pos)
44
+ val paramClasses = paramsSig(sym)
45
+ val interpretedArgs = paramClasses.map { clazz =>
46
+ if (clazz == classOf [Boolean ]) false .asInstanceOf [Object ]
47
+ else if (clazz == classOf [Byte ]) 0 .toByte.asInstanceOf [Object ]
48
+ else if (clazz == classOf [Char ]) 0 .toChar.asInstanceOf [Object ]
49
+ else if (clazz == classOf [Short ]) 0 .asInstanceOf [Object ]
50
+ else if (clazz == classOf [Int ]) 0 .asInstanceOf [Object ]
51
+ else if (clazz == classOf [Long ]) 0L .asInstanceOf [Object ]
52
+ else if (clazz == classOf [Float ]) 0f .asInstanceOf [Object ]
53
+ else if (clazz == classOf [Double ]) 0d .asInstanceOf [Object ]
54
+ else null
55
+ }
56
+
57
+ val method = getMethod(clazz, sym.name, paramClasses)
58
+
59
+ val o = stopIfRuntimeException(method.invoke(null , interpretedArgs : _* ))(pos)
60
+
61
+ o match {
47
62
case obj : T => Some (obj)
48
63
case obj =>
49
64
// TODO upgrade to a full type tag check or something similar
50
- ctx.error(s " Interpreted tree returned a result of an unexpected type. Expected ${ct.runtimeClass} but was ${obj.getClass}" , tree. pos)
65
+ ctx.error(s " Interpreted tree returned a result of an unexpected type. Expected ${ct.runtimeClass} but was ${obj.getClass}" , pos)
51
66
None
52
67
}
53
68
} catch {
@@ -57,133 +72,6 @@ class Interpreter(implicit ctx: Context) {
57
72
}
58
73
}
59
74
60
- def interpretCallToSymbol [T ](sym : Symbol )(implicit pos : Position ): T = {
61
- val clazz = loadClass(sym.owner.companionModule.fullName)
62
- val paramClasses = paramsSig(sym)
63
- val interpretedArgs = paramClasses.map(_ => 1 .asInstanceOf [Object ])
64
- println(" ----------------" )
65
- println(clazz)
66
- println(paramClasses)
67
- println(interpretedArgs)
68
- println()
69
- println(sym.name)
70
- println()
71
- println()
72
- println()
73
-
74
- val method =
75
- clazz.getMethod(sym.name.toString, paramClasses : _* )
76
- stopIfRuntimeException(method.invoke(null , interpretedArgs : _* )).asInstanceOf [T ]
77
- }
78
-
79
- /** Returns the interpreted result of interpreting the code represented by the tree.
80
- * Returns the result of the interpreted tree.
81
- *
82
- * If some error is encountered while interpreting a ctx.error is emitted and a StopInterpretation is thrown.
83
- */
84
- private def interpretTreeImpl (tree : Tree , env : Env ): Object = {
85
- // println(s"Interpreting:\n${tree.show}\n$env\n")
86
-
87
- implicit val pos : Position = tree.pos
88
-
89
- tree match {
90
- case Quoted (quotedTree) =>
91
- if (quotedTree.isTerm) new scala.quoted.Exprs .TreeExpr (quotedTree)
92
- else new scala.quoted.Types .TreeType (quotedTree)
93
-
94
- case Literal (Constant (c)) => c.asInstanceOf [Object ]
95
-
96
- case Apply (fn, args) if fn.symbol.isConstructor =>
97
- val clazz = loadClass(fn.symbol.owner.symbol.fullName)
98
- val paramClasses = paramsSig(fn.symbol)
99
- val interpretedArgs = args.map(arg => interpretTreeImpl(arg, env))
100
- val constructor = getConstructor(clazz, paramClasses)
101
- stopIfRuntimeException(constructor.newInstance(interpretedArgs : _* ))
102
-
103
- case _ : RefTree if tree.symbol.isStatic =>
104
- val clazz = loadClass(tree.symbol.owner.companionModule.fullName)
105
- val method = getMethod(clazz, tree.symbol.name, Nil )
106
- stopIfRuntimeException(method.invoke(null ))
107
-
108
- case tree : Apply =>
109
- val evaluatedPrefix = if (tree.symbol.isStatic) null else interpretPrefix(tree, env)
110
- val clazz =
111
- if (tree.symbol.isStatic) loadClass(tree.symbol.owner.companionModule.fullName)
112
- else evaluatedPrefix.getClass
113
- val paramClasses = paramsSig(tree.symbol)
114
- val interpretedArgs = interpretArgs(tree, env)
115
- val method = getMethod(clazz, tree.symbol.name, paramClasses)
116
- stopIfRuntimeException(method.invoke(evaluatedPrefix, interpretedArgs : _* ))
117
-
118
- case tree : Ident if env.contains(tree.symbol) =>
119
- env(tree.symbol)
120
-
121
- case Block (stats, expr) =>
122
- val env2 = stats.foldLeft(env)((acc, x) => interpretStat(x, acc))
123
- interpretTreeImpl(expr, env2)
124
-
125
- case tree : NamedArg =>
126
- interpretTreeImpl(tree.arg, env)
127
-
128
- case Inlined (_, bindings, expansion) =>
129
- val env2 = bindings.foldLeft(env)((acc, x) => interpretStat(x, acc))
130
- interpretTreeImpl(expansion, env2)
131
-
132
- case TypeApply (fn, _) =>
133
- interpretTreeImpl(fn, env)
134
-
135
- case Typed (expr, _) =>
136
- interpretTreeImpl(expr, env)
137
-
138
- case Select (qualifier, name)
139
- if tree.symbol.owner.isValueClass && tree.symbol.is(ParamAccessor ) && env.contains(qualifier.symbol) =>
140
- val value = env(qualifier.symbol)
141
- val clazz = value.getClass
142
- if (clazz.getCanonicalName != tree.symbol.owner.showFullName) value // Already unboxed
143
- else {
144
- val method = getMethod(clazz, name, Nil )
145
- stopIfRuntimeException(method.invoke(value))
146
- }
147
-
148
- case SeqLiteral (elems, _) =>
149
- elems.map(elem => interpretTreeImpl(elem, env))
150
-
151
- case _ =>
152
- // TODO Add more precise descriptions of why it could not be interpreted.
153
- // This should be done after the full interpreter is implemented.
154
- throw new StopInterpretation (s " Could not interpret ${tree.show}. Consider extracting logic into a helper def. " , tree.pos)
155
- }
156
- }
157
-
158
- private def interpretArgs (tree : Tree , env : Env ): Seq [Object ] = {
159
- val b = Seq .newBuilder[Object ]
160
- def interpretArgs (tree : Tree ): Unit = tree match {
161
- case Apply (fn, args) =>
162
- interpretArgs(fn)
163
- args.foreach(arg => b += interpretTreeImpl(arg, env))
164
- case _ =>
165
- }
166
- interpretArgs(tree)
167
- b.result()
168
- }
169
-
170
- private def interpretPrefix (tree : Tree , env : Env ): Object = tree match {
171
- case Apply (qual, _) => interpretPrefix(qual, env)
172
- case TypeApply (qual, _) => interpretPrefix(qual, env)
173
- case Select (qual, _) => interpretTreeImpl(qual, env)
174
- }
175
-
176
- /** Interprets the statement and returns the updated environment */
177
- private def interpretStat (stat : Tree , env : Env ): Env = stat match {
178
- case tree : ValDef =>
179
- val obj = interpretTreeImpl(tree.rhs, env)
180
- env.updated(tree.symbol, obj)
181
-
182
- case _ =>
183
- interpretTreeImpl(stat, env)
184
- env
185
- }
186
-
187
75
private def loadClass (name : Name )(implicit pos : Position ): Class [_] = {
188
76
try classLoader.loadClass(name.toString)
189
77
catch {
@@ -202,15 +90,6 @@ class Interpreter(implicit ctx: Context) {
202
90
}
203
91
}
204
92
205
- private def getConstructor (clazz : Class [_], paramClasses : List [Class [_]])(implicit pos : Position ): Constructor [Object ] = {
206
- try clazz.getConstructor(paramClasses : _* ).asInstanceOf [Constructor [Object ]]
207
- catch {
208
- case _ : NoSuchMethodException =>
209
- val msg = s " Could not find interpreted constructor of ${clazz.getCanonicalName} with parameters $paramClasses"
210
- throw new StopInterpretation (msg, pos)
211
- }
212
- }
213
-
214
93
private def stopIfRuntimeException [T ](thunk : => T )(implicit pos : Position ): T = {
215
94
try thunk
216
95
catch {
0 commit comments