@@ -233,15 +233,15 @@ class Semantic {
233
233
def select (f : Symbol , source : Tree ): Contextual [Result ] =
234
234
value.select(f, source) ++ errors
235
235
236
- def call (meth : Symbol , superType : Type , source : Tree ): Contextual [Result ] =
237
- value.call(meth, superType, source) ++ errors
236
+ def call (meth : Symbol , args : List [ Value ], superType : Type , source : Tree ): Contextual [Result ] =
237
+ value.call(meth, args, superType, source) ++ errors
238
238
239
- def instantiate (klass : ClassSymbol , ctor : Symbol , source : Tree ): Contextual [Result ] =
240
- value.instantiate(klass, ctor, source) ++ errors
239
+ def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [ Value ], source : Tree ): Contextual [Result ] =
240
+ value.instantiate(klass, ctor, args, source) ++ errors
241
241
}
242
242
243
243
/** The state that threads through the interpreter */
244
- type Contextual [T ] = (Context , Trace , Promoted ) ?=> T
244
+ type Contextual [T ] = (Env , Context , Trace , Promoted ) ?=> T
245
245
246
246
// ----- Error Handling -----------------------------------
247
247
@@ -282,9 +282,8 @@ class Semantic {
282
282
283
283
def widen : Value =
284
284
a match
285
+ case _ : Addr | _ : Fun => Cold
285
286
case RefSet (refs) => refs.map(_.widen).join
286
- case _ : Addr => Cold
287
- case Fun (e, params, thisV, klass, env) => Fun (e, params, thisV.widen, klass, env)
288
287
case _ => a
289
288
290
289
@@ -308,7 +307,7 @@ class Semantic {
308
307
case addr : Addr =>
309
308
val target = if needResolve then resolve(addr.klass, field) else field
310
309
if target.is(Flags .Lazy ) then
311
- value.call(target, superType = NoType , source, needResolve = false )
310
+ value.call(target, Nil , superType = NoType , source, needResolve = false )
312
311
else
313
312
val obj = heap(addr)
314
313
if obj.fields.contains(target) then
@@ -330,8 +329,9 @@ class Semantic {
330
329
val error = AccessNonInit (target, trace.add(source).toVector)
331
330
Result (Hot , error :: Nil )
332
331
333
- case _ : Fun =>
334
- ???
332
+ case fun : Fun =>
333
+ report.error(" unexpected tree in selecting a function, fun = " + fun.expr.show, source)
334
+ Result (Hot , Nil )
335
335
336
336
case RefSet (refs) =>
337
337
val resList = refs.map(_.select(field, source))
@@ -340,7 +340,7 @@ class Semantic {
340
340
Result (value2, errors)
341
341
}
342
342
343
- def call (meth : Symbol , superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] =
343
+ def call (meth : Symbol , args : List [ Value ], superType : Type , source : Tree , needResolve : Boolean = true ): Contextual [Result ] =
344
344
value match {
345
345
case Hot =>
346
346
Result (Hot , Errors .empty)
@@ -362,7 +362,7 @@ class Semantic {
362
362
val cls = target.owner.enclosingClass.asClass
363
363
if target.isPrimaryConstructor then
364
364
val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
365
- eval(tpl, addr, cls, cacheResult = true )(using ctx, trace.add(cls.defTree), promoted)
365
+ eval(tpl, addr, cls, cacheResult = true )(using env, ctx, trace.add(cls.defTree), promoted)
366
366
else
367
367
val rhs = target.defTree.asInstanceOf [ValOrDefDef ].rhs
368
368
eval(rhs, addr, cls, cacheResult = true )
@@ -378,20 +378,20 @@ class Semantic {
378
378
else
379
379
value.select(target, source, needResolve = false )
380
380
381
- case Fun (body, thisV, klass) =>
381
+ case Fun (body, params, thisV, klass, env ) =>
382
382
// meth == NoSymbol for poly functions
383
383
if meth.name.toString == " tupled" then Result (value, Nil ) // a call like `fun.tupled`
384
384
else eval(body, thisV, klass, cacheResult = true )
385
385
386
386
case RefSet (refs) =>
387
- val resList = refs.map(_.call(meth, superType, source))
387
+ val resList = refs.map(_.call(meth, args, superType, source))
388
388
val value2 = resList.map(_.value).join
389
389
val errors = resList.flatMap(_.errors)
390
390
Result (value2, errors)
391
391
}
392
392
393
393
/** Handle a new expression `new p.C` where `p` is abstracted by `value` */
394
- def instantiate (klass : ClassSymbol , ctor : Symbol , source : Tree ): Contextual [Result ] =
394
+ def instantiate (klass : ClassSymbol , ctor : Symbol , args : List [ Value ], source : Tree ): Contextual [Result ] =
395
395
value match {
396
396
case Hot =>
397
397
Result (Hot , Errors .empty)
@@ -403,21 +403,22 @@ class Semantic {
403
403
case addr : Addr =>
404
404
// widen the outer to finitize addresses
405
405
val outer = addr match
406
- case Warm (_, _ : Warm ) => Cold
406
+ case Warm (_, _ : Warm , _, _ ) => Cold
407
407
case _ => addr
408
408
409
- val value = Warm (klass, outer)
409
+ val value = Warm (klass, outer, ctor, args.widen )
410
410
if ! heap.contains(value) then
411
411
val obj = Objekt (klass, fields = mutable.Map .empty, outers = mutable.Map (klass -> outer))
412
412
heap.update(value, obj)
413
- val res = value.call(ctor, superType = NoType , source)
413
+ val res = value.call(ctor, args, superType = NoType , source)
414
414
Result (value, res.errors)
415
415
416
- case Fun (body, thisV, klass) =>
417
- ??? // impossible
416
+ case Fun (body, params, thisV, klass, env) =>
417
+ report.error(" unexpected tree in instantiating a function, fun = " + body.show, source)
418
+ Result (Hot , Nil )
418
419
419
420
case RefSet (refs) =>
420
- val resList = refs.map(_.instantiate(klass, ctor, source))
421
+ val resList = refs.map(_.instantiate(klass, ctor, args, source))
421
422
val value2 = resList.map(_.value).join
422
423
val errors = resList.flatMap(_.errors)
423
424
Result (value2, errors)
@@ -490,7 +491,7 @@ class Semantic {
490
491
errors
491
492
}
492
493
493
- case fun @ Fun (body, thisV, klass) =>
494
+ case fun @ Fun (body, params, thisV, klass, env ) =>
494
495
if promoted.contains(fun) then Nil
495
496
else
496
497
val res = eval(body, thisV, klass)
@@ -550,7 +551,8 @@ class Semantic {
550
551
val trace2 = trace.add(m.defTree)
551
552
locally {
552
553
given Trace = trace2
553
- val res = warm.call(m, superType = NoType , source = source)
554
+ val args = m.info.paramInfoss.flatten.map(_ => Hot )
555
+ val res = warm.call(m, args, superType = NoType , source = source)
554
556
buffer ++= res.ensureHot(msg, source).errors
555
557
}
556
558
buffer.nonEmpty
@@ -611,18 +613,15 @@ class Semantic {
611
613
exprs.map { expr => eval(expr, thisV, klass) }
612
614
613
615
/** Evaluate arguments of methods */
614
- def evalArgs (args : List [Arg ], thisV : Addr , klass : ClassSymbol ): Contextual [List [Error ]] =
616
+ def evalArgs (args : List [Arg ], thisV : Addr , klass : ClassSymbol ): Contextual [( List [Error ], List [ Value ]) ] =
615
617
val ress = args.map { arg =>
616
- val res =
617
- if arg.isByName then
618
- val fun = Fun (arg.tree, thisV, klass)
619
- Result (fun, Nil )
620
- else
621
- eval(arg.tree, thisV, klass)
622
-
623
- res.ensureHot(" May only use initialized value as arguments" , arg.tree)
618
+ if arg.isByName then
619
+ val fun = Fun (arg.tree, Nil , thisV, klass, env)
620
+ Result (fun, Nil )
621
+ else
622
+ eval(arg.tree, thisV, klass)
624
623
}
625
- ress.flatMap(_.errors)
624
+ ( ress.flatMap(_.errors), ress.map(_.value) )
626
625
627
626
/** Handles the evaluation of different expressions
628
627
*
@@ -640,31 +639,31 @@ class Semantic {
640
639
641
640
case NewExpr (tref, New (tpt), ctor, argss) =>
642
641
// check args
643
- val errors = evalArgs(argss.flatten, thisV, klass)
642
+ val ( errors, args) = evalArgs(argss.flatten, thisV, klass)
644
643
645
644
val cls = tref.classSymbol.asClass
646
645
val res = outerValue(tref, thisV, klass, tpt)
647
646
val trace2 = trace.add(expr)
648
647
locally {
649
648
given Trace = trace2
650
- (res ++ errors).instantiate(cls, ctor, expr)
649
+ (res ++ errors).instantiate(cls, ctor, args, expr)
651
650
}
652
651
653
652
case Call (ref, argss) =>
654
653
// check args
655
- val errors = evalArgs(argss.flatten, thisV, klass)
654
+ val ( errors, args) = evalArgs(argss.flatten, thisV, klass)
656
655
657
656
val trace2 : Trace = trace.add(expr)
658
657
659
658
ref match
660
659
case Select (supert : Super , _) =>
661
660
val SuperType (thisTp, superTp) = supert.tpe
662
661
val thisValue2 = resolveThis(thisTp.classSymbol.asClass, thisV, klass, ref)
663
- Result (thisValue2, errors).call(ref.symbol, superTp, expr)(using ctx, trace2)
662
+ Result (thisValue2, errors).call(ref.symbol, args, superTp, expr)(using env, ctx, trace2)
664
663
665
664
case Select (qual, _) =>
666
665
val res = eval(qual, thisV, klass) ++ errors
667
- res.call(ref.symbol, superType = NoType , source = expr)(using ctx, trace2)
666
+ res.call(ref.symbol, args, superType = NoType , source = expr)(using env, ctx, trace2)
668
667
669
668
case id : Ident =>
670
669
id.tpe match
@@ -673,10 +672,10 @@ class Semantic {
673
672
val enclosingClass = id.symbol.owner.enclosingClass.asClass
674
673
val thisValue2 = resolveThis(enclosingClass, thisV, klass, id)
675
674
// local methods are not a member, but we can reuse the method `call`
676
- thisValue2.call(id.symbol, superType = NoType , expr, needResolve = false )
675
+ thisValue2.call(id.symbol, args, superType = NoType , expr, needResolve = false )
677
676
case TermRef (prefix, _) =>
678
677
val res = cases(prefix, thisV, klass, id) ++ errors
679
- res.call(id.symbol, superType = NoType , source = expr)(using ctx, trace2)
678
+ res.call(id.symbol, args, superType = NoType , source = expr)(using env, ctx, trace2)
680
679
681
680
case Select (qualifier, name) =>
682
681
eval(qualifier, thisV, klass).select(expr.symbol, expr)
@@ -703,11 +702,12 @@ class Semantic {
703
702
eval(rhs, thisV, klass).ensureHot(" May only assign fully initialized value" , rhs)
704
703
705
704
case closureDef(ddef) =>
706
- val value = Fun (ddef.rhs, thisV, klass)
705
+ val params = ddef.termParamss.head.map(_.symbol)
706
+ val value = Fun (ddef.rhs, params, thisV, klass, env)
707
707
Result (value, Nil )
708
708
709
709
case PolyFun (body) =>
710
- val value = Fun (body, thisV, klass)
710
+ val value = Fun (body, Nil , thisV, klass, env )
711
711
Result (value, Nil )
712
712
713
713
case Block (stats, expr) =>
@@ -860,7 +860,7 @@ class Semantic {
860
860
}
861
861
}
862
862
863
- def superCall (tref : TypeRef , ctor : Symbol , source : Tree ): Unit =
863
+ def superCall (tref : TypeRef , ctor : Symbol , args : List [ Value ], source : Tree ): Unit =
864
864
val cls = tref.classSymbol.asClass
865
865
// update outer for super class
866
866
val res = outerValue(tref, thisV, klass, source)
@@ -870,23 +870,25 @@ class Semantic {
870
870
// follow constructor
871
871
if cls.hasSource then
872
872
printer.println(" init super class " + cls.show)
873
- val res2 = thisV.call(ctor, superType = NoType , source)(using ctx, trace.add(source))
873
+ val res2 = thisV.call(ctor, args, superType = NoType , source)(using env, ctx, trace.add(source))
874
874
errorBuffer ++= res2.errors
875
875
876
876
// parents
877
877
def initParent (parent : Tree ) = parent match {
878
878
case tree @ Block (stats, NewExpr (tref, New (tpt), ctor, argss)) => // can happen
879
879
eval(stats, thisV, klass).foreach { res => errorBuffer ++= res.errors }
880
- errorBuffer ++= evalArgs(argss.flatten, thisV, klass)
881
- superCall(tref, ctor, tree)
880
+ val (erros, args) = evalArgs(argss.flatten, thisV, klass)
881
+ errorBuffer ++= erros
882
+ superCall(tref, ctor, args, tree)
882
883
883
884
case tree @ NewExpr (tref, New (tpt), ctor, argss) => // extends A(args)
884
- errorBuffer ++= evalArgs(argss.flatten, thisV, klass)
885
- superCall(tref, ctor, tree)
885
+ val (erros, args) = evalArgs(argss.flatten, thisV, klass)
886
+ errorBuffer ++= erros
887
+ superCall(tref, ctor, args, tree)
886
888
887
889
case _ => // extends A or extends A[T]
888
890
val tref = typeRefOf(parent.tpe)
889
- superCall(tref, tref.classSymbol.primaryConstructor, parent)
891
+ superCall(tref, tref.classSymbol.primaryConstructor, Nil , parent)
890
892
}
891
893
892
894
// see spec 5.1 about "Template Evaluation".
@@ -913,7 +915,7 @@ class Semantic {
913
915
// term arguments to B. That can only be done in a concrete class.
914
916
val tref = typeRefOf(klass.typeRef.baseType(mixin).typeConstructor)
915
917
val ctor = tref.classSymbol.primaryConstructor
916
- if ctor.exists then superCall(tref, ctor, superParent)
918
+ if ctor.exists then superCall(tref, ctor, Nil , superParent)
917
919
}
918
920
919
921
0 commit comments