@@ -55,8 +55,29 @@ class Semantic {
55
55
* V ⊑ R if V ∈ R
56
56
*
57
57
*/
58
- sealed abstract class Value {
58
+ sealed abstract class Value extends Cloneable {
59
59
def show : String = this .toString()
60
+
61
+ /** Source code where the value originates from
62
+ *
63
+ * It is used for displaying friendly messages
64
+ */
65
+ private var mySource : Tree = EmptyTree
66
+
67
+ def source : Tree = mySource
68
+
69
+ def attachSource (source : Tree ): this .type =
70
+ assert(mySource.isEmpty, " Update existing source of value " + this )
71
+ mySource = source
72
+ this
73
+
74
+ def withSource (source : Tree ): Value =
75
+ if mySource.isEmpty then attachSource(source)
76
+ else {
77
+ val value2 = this .clone.asInstanceOf [Value ]
78
+ value2.mySource = source
79
+ value2
80
+ }
60
81
}
61
82
62
83
/** A transitively initialized object */
@@ -238,6 +259,8 @@ class Semantic {
238
259
239
260
def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [Value ], source : Tree ): Contextual [Result ] =
240
261
value.instantiate(klass, ctor, args, source) ++ errors
262
+
263
+ def withSource (source : Tree ): Result = Result (value.withSource(source), errors)
241
264
}
242
265
243
266
/** The state that threads through the interpreter */
@@ -626,9 +649,9 @@ class Semantic {
626
649
val ress = args.map { arg =>
627
650
if arg.isByName then
628
651
val fun = Fun (arg.tree, Nil , thisV, klass, env)
629
- Result (fun, Nil )
652
+ Result (fun, Nil ).withSource(arg.tree)
630
653
else
631
- eval(arg.tree, thisV, klass)
654
+ eval(arg.tree, thisV, klass).withSource(arg.tree)
632
655
}
633
656
(ress.flatMap(_.errors), ress.map(_.value))
634
657
0 commit comments