@@ -30,6 +30,8 @@ import java.lang.reflect.Method
3030class Interpreter (implicit ctx : Context ) {
3131 import tpd ._
3232
33+ type Env = Map [Symbol , Object ]
34+
3335 private [this ] val classLoader = {
3436 val urls = ctx.settings.classpath.value.split(':' ).map(cp => java.nio.file.Paths .get(cp).toUri.toURL)
3537 new URLClassLoader (urls, getClass.getClassLoader)
@@ -40,7 +42,7 @@ class Interpreter(implicit ctx: Context) {
4042 */
4143 def interpretTree [T ](tree : Tree )(implicit ct : ClassTag [T ]): Option [T ] = {
4244 try {
43- interpretTreeImpl(tree) match {
45+ interpretTreeImpl(tree, Map .empty ) match {
4446 case obj : T => Some (obj)
4547 case obj =>
4648 // TODO upgrade to a full type tag check or something similar
@@ -57,52 +59,76 @@ class Interpreter(implicit ctx: Context) {
5759 /** Returns the interpreted result of interpreting the code represented by the tree.
5860 * Returns the result of the interpreted tree.
5961 *
60- * If some error is encountered while interpreting a ctx.error is emited and a StopInterpretation is thrown.
62+ * If some error is encountered while interpreting a ctx.error is emitted and a StopInterpretation is thrown.
6163 */
62- private def interpretTreeImpl (tree : Tree ): Object = { // TODO add environment
64+ private def interpretTreeImpl (tree : Tree , env : Env ): Object = {
65+ ctx.debuglog(
66+ s """ Interpreting:
67+ | ${tree.show}
68+ | $env
69+ """ .stripMargin)
70+
6371 implicit val pos : Position = tree.pos
72+
6473 tree match {
6574 case Quoted (quotedTree) => RawQuoted (quotedTree)
6675
67- case Literal (Constant (c)) => c.asInstanceOf [AnyRef ]
76+ case Literal (Constant (c)) => c.asInstanceOf [Object ]
6877
6978 case Apply (fn, args) if fn.symbol.isConstructor =>
7079 val clazz = loadClass(fn.symbol.owner.symbol.fullName)
7180 val paramClasses = paramsSig(fn.symbol)
72- val interpretedArgs = args.map(arg => interpretTreeImpl(arg))
81+ val interpretedArgs = args.map(arg => interpretTreeImpl(arg, env ))
7382 val constructor = getConstructor(clazz, paramClasses)
7483 interpreted(constructor.newInstance(interpretedArgs : _* ))
7584
7685 case _ : RefTree | _ : Apply if tree.symbol.isStatic =>
7786 val clazz = loadClass(tree.symbol.owner.companionModule.fullName)
7887 val paramClasses = paramsSig(tree.symbol)
79-
8088 val interpretedArgs = Array .newBuilder[Object ]
8189 def interpretArgs (tree : Tree ): Unit = tree match {
8290 case Apply (fn, args) =>
8391 interpretArgs(fn)
84- args.foreach(arg => interpretedArgs += interpretTreeImpl(arg))
92+ args.foreach(arg => interpretedArgs += interpretTreeImpl(arg, env ))
8593 case _ =>
8694 }
8795 interpretArgs(tree)
8896
8997 val method = getMethod(clazz, tree.symbol.name, paramClasses)
9098 interpreted(method.invoke(null , interpretedArgs.result(): _* ))
9199
92- // case tree: RefTree if tree.symbol.is(Module) => // TODO
93- // case Block(stats, expr) => // TODO evaluate bindings add environment
94- // case ValDef(_, _, rhs) => // TODO evaluate bindings add environment
100+ case tree : Ident if env.contains(tree.symbol) =>
101+ env(tree.symbol)
102+
103+ case Block (stats, expr) =>
104+ val env2 = stats.foldLeft(env)((acc, x) => interpretStat(x, acc))
105+ interpretTreeImpl(expr, env2)
106+
107+ case tree : NamedArg =>
108+ interpretTreeImpl(tree.arg, env)
95109
96110 case Inlined (_, bindings, expansion) =>
97- assert(bindings.isEmpty) // TODO evaluate bindings and add environment
98- interpretTreeImpl(expansion)
111+ val env2 = bindings.foldLeft(env)((acc, x) => interpretStat(x, acc))
112+ interpretTreeImpl(expansion, env2)
113+
99114 case _ =>
100115 // TODO Add more precise descriptions of why it could not be interpreted.
101116 // This should be done after the full interpreter is implemented.
102- throw new StopInterpretation (s " Could not interpret ${tree.show}" , tree.pos)
117+ throw new StopInterpretation (s " Could not interpret ${tree.show}\n ${tree} " , tree.pos)
103118 }
104119 }
105120
121+ /** Interprets the statement and returns the updated environment */
122+ private def interpretStat (stat : Tree , env : Env ): Env = stat match {
123+ case tree : ValDef =>
124+ val obj = interpretTreeImpl(tree.rhs, env)
125+ env.updated(tree.symbol, obj)
126+
127+ case _ =>
128+ interpretTreeImpl(stat, env)
129+ env
130+ }
131+
106132 private def loadClass (name : Name )(implicit pos : Position ): Class [_] = {
107133 try classLoader.loadClass(name.toString)
108134 catch {
@@ -135,7 +161,7 @@ class Interpreter(implicit ctx: Context) {
135161 catch {
136162 case ex : RuntimeException =>
137163 val sw = new StringWriter ()
138- sw.write(" A runtime exception occurred while interpreting" )
164+ sw.write(" A runtime exception occurred while interpreting\n " )
139165 sw.write(ex.getMessage)
140166 sw.write(" \n " )
141167 ex.printStackTrace(new PrintWriter (sw))
0 commit comments