@@ -57,28 +57,6 @@ class Semantic {
57
57
*/
58
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 if this == Hot || this == Cold then this
77
- else {
78
- val value2 = this .clone.asInstanceOf [Value ]
79
- value2.mySource = source
80
- value2
81
- }
82
60
}
83
61
84
62
/** A transitively initialized object */
@@ -265,13 +243,11 @@ class Semantic {
265
243
def select (f : Symbol , source : Tree ): Contextual [Result ] =
266
244
value.select(f, source) ++ errors
267
245
268
- def call (meth : Symbol , args : List [Value ], superType : Type , source : Tree ): Contextual [Result ] =
246
+ def call (meth : Symbol , args : List [ArgInfo ], superType : Type , source : Tree ): Contextual [Result ] =
269
247
value.call(meth, args, superType, source) ++ errors
270
248
271
- def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [Value ], source : Tree ): Contextual [Result ] =
249
+ def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [ArgInfo ], source : Tree ): Contextual [Result ] =
272
250
value.instantiate(klass, ctor, args, source) ++ errors
273
-
274
- def withSource (source : Tree ): Result = Result (value.withSource(source), errors)
275
251
}
276
252
277
253
/** The state that threads through the interpreter */
@@ -379,8 +355,8 @@ class Semantic {
379
355
}
380
356
}
381
357
382
- def call (meth : Symbol , args : List [Value ], superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" call " + meth.show + " , args = " + args, printer, res => res.asInstanceOf [Result ].show) {
383
- def checkArgs = args.flatMap { arg => arg.promote( " May only use initialized value as arguments " , arg.source) }
358
+ def call (meth : Symbol , args : List [ArgInfo ], superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] = log(" call " + meth.show + " , args = " + args, printer, res => res.asInstanceOf [Result ].show) {
359
+ def checkArgs = args.flatMap(_.promote)
384
360
385
361
// fast track if the current object is already initialized
386
362
if promoted.isCurrentObjectPromoted then Result (Hot , Nil )
@@ -408,7 +384,7 @@ class Semantic {
408
384
given Trace = trace1
409
385
val cls = target.owner.enclosingClass.asClass
410
386
val ddef = target.defTree.asInstanceOf [DefDef ]
411
- val env2 = Env (ddef, args.widen)
387
+ val env2 = Env (ddef, args.map(_.value). widen)
412
388
if target.isPrimaryConstructor then
413
389
given Env = env2
414
390
val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
@@ -437,7 +413,7 @@ class Semantic {
437
413
// meth == NoSymbol for poly functions
438
414
if meth.name.toString == " tupled" then Result (value, Nil ) // a call like `fun.tupled`
439
415
else
440
- val env3 = Env (params.zip(args.widen).toMap).union(env2)
416
+ val env3 = Env (params.zip(args.map(_.value). widen).toMap).union(env2)
441
417
use(env3) {
442
418
eval(body, thisV, klass, cacheResult = true )
443
419
}
@@ -451,17 +427,17 @@ class Semantic {
451
427
}
452
428
453
429
/** Handle a new expression `new p.C` where `p` is abstracted by `value` */
454
- def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [Value ], source : Tree ): Contextual [Result ] = log(" instantiating " + klass.show + " , args = " + args, printer, res => res.asInstanceOf [Result ].show) {
430
+ def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [ArgInfo ], source : Tree ): Contextual [Result ] = log(" instantiating " + klass.show + " , args = " + args, printer, res => res.asInstanceOf [Result ].show) {
455
431
val trace1 = trace.add(source)
456
432
if promoted.isCurrentObjectPromoted then Result (Hot , Nil )
457
433
else value match {
458
434
case Hot =>
459
435
val buffer = new mutable.ArrayBuffer [Error ]
460
436
val args2 = args.map { arg =>
461
- val errors = arg.promote( " May only use initialized value as arguments " , arg.source)
437
+ val errors = arg.promote
462
438
buffer ++= errors
463
439
if errors.isEmpty then Hot
464
- else arg.widen
440
+ else arg.value. widen
465
441
}
466
442
467
443
if buffer.isEmpty then Result (Hot , Errors .empty)
@@ -485,7 +461,7 @@ class Semantic {
485
461
case Warm (_, _ : Warm , _, _) => Cold
486
462
case _ => addr
487
463
488
- val value = Warm (klass, outer, ctor, args.widen)
464
+ val value = Warm (klass, outer, ctor, args.map(_.value). widen)
489
465
if ! heap.contains(value) then
490
466
val obj = Objekt (klass, fields = mutable.Map .empty, outers = mutable.Map (klass -> outer))
491
467
heap.update(value, obj)
@@ -616,7 +592,7 @@ class Semantic {
616
592
val trace2 = trace.add(m.defTree)
617
593
locally {
618
594
given Trace = trace2
619
- val args = m.info.paramInfoss.flatten.map(_ => Hot )
595
+ val args = m.info.paramInfoss.flatten.map(_ => ArgInfo ( Hot , EmptyTree ) )
620
596
val res = warm.call(m, args, superType = NoType , source = source)
621
597
buffer ++= res.ensureHot(msg, source).errors
622
598
}
@@ -643,6 +619,11 @@ class Semantic {
643
619
644
620
// ----- Semantic definition --------------------------------
645
621
622
+ /** Utility definition used for better error-reporting of argument errors */
623
+ case class ArgInfo (value : Value , source : Tree ) {
624
+ def promote : Contextual [List [Error ]] = value.promote(" May only use initialized value as arguments" , source)
625
+ }
626
+
646
627
/** Evaluate an expression with the given value for `this` in a given class `klass`
647
628
*
648
629
* Note that `klass` might be a super class of the object referred by `thisV`.
@@ -678,15 +659,21 @@ class Semantic {
678
659
exprs.map { expr => eval(expr, thisV, klass) }
679
660
680
661
/** Evaluate arguments of methods */
681
- def evalArgs (args : List [Arg ], thisV : Addr , klass : ClassSymbol ): Contextual [(List [Error ], List [Value ])] =
682
- val ress = args.map { arg =>
683
- if arg.isByName then
684
- val fun = Fun (arg.tree, Nil , thisV, klass, env)
685
- Result (fun, Nil ).withSource(arg.tree)
686
- else
687
- eval(arg.tree, thisV, klass).withSource(arg.tree)
662
+ def evalArgs (args : List [Arg ], thisV : Addr , klass : ClassSymbol ): Contextual [(List [Error ], List [ArgInfo ])] =
663
+ val errors = new mutable.ArrayBuffer [Error ]
664
+ val argInfos = new mutable.ArrayBuffer [ArgInfo ]
665
+ args.foreach { arg =>
666
+ val res =
667
+ if arg.isByName then
668
+ val fun = Fun (arg.tree, Nil , thisV, klass, env)
669
+ Result (fun, Nil )
670
+ else
671
+ eval(arg.tree, thisV, klass)
672
+
673
+ errors ++= res.errors
674
+ argInfos += ArgInfo (res.value, arg.tree)
688
675
}
689
- (ress.flatMap(_. errors), ress.map(_.value) )
676
+ (errors.toList, argInfos.toList )
690
677
691
678
/** Handles the evaluation of different expressions
692
679
*
@@ -939,7 +926,7 @@ class Semantic {
939
926
printer.println(acc.show + " initialized with " + value)
940
927
}
941
928
942
- def superCall (tref : TypeRef , ctor : Symbol , args : List [Value ], source : Tree )(using Env ): Unit =
929
+ def superCall (tref : TypeRef , ctor : Symbol , args : List [ArgInfo ], source : Tree )(using Env ): Unit =
943
930
val cls = tref.classSymbol.asClass
944
931
// update outer for super class
945
932
val res = outerValue(tref, thisV, klass, source)
0 commit comments