@@ -212,6 +212,7 @@ object Objects:
212
212
given Trace = Trace .empty.add(classSym.defTree)
213
213
given Env .Data = Env .emptyEnv(tpl.constr.symbol)
214
214
given Heap .MutableData = Heap .empty()
215
+ given returns : Returns .Data = Returns .empty()
215
216
given regions : Regions .Data = Regions .empty // explicit name to avoid naming conflict
216
217
217
218
val obj = ObjectRef (classSym)
@@ -487,7 +488,33 @@ object Objects:
487
488
488
489
inline def cache (using c : Cache .Data ): Cache .Data = c
489
490
490
- type Contextual [T ] = (Context , State .Data , Env .Data , Cache .Data , Heap .MutableData , Regions .Data , Trace ) ?=> T
491
+
492
+ /**
493
+ * Handle return statements in methods and non-local returns in functions.
494
+ */
495
+ object Returns :
496
+ private class ReturnData (val method : Symbol , val values : mutable.ArrayBuffer [Value ])
497
+ opaque type Data = mutable.ArrayBuffer [ReturnData ]
498
+
499
+ def empty (): Data = mutable.ArrayBuffer ()
500
+
501
+ def installHandler (meth : Symbol )(using data : Data ): Unit =
502
+ data.addOne(ReturnData (meth, mutable.ArrayBuffer ()))
503
+
504
+ def popHandler (meth : Symbol )(using data : Data ): Value =
505
+ val returnData = data.remove(data.size - 1 )
506
+ assert(returnData.method == meth, " Symbol mismatch in return handlers, expect = " + meth + " , found = " + returnData.method)
507
+ returnData.values.join
508
+
509
+ def handle (meth : Symbol , value : Value )(using data : Data , trace : Trace , ctx : Context ): Unit =
510
+ data.findLast(_.method == meth) match
511
+ case Some (returnData) =>
512
+ returnData.values.addOne(value)
513
+
514
+ case None =>
515
+ report.error(" [Internal error] Unhandled return for method " + meth + " in " + meth.owner.show + " . Trace:\n " + Trace .show, Trace .position)
516
+
517
+ type Contextual [T ] = (Context , State .Data , Env .Data , Cache .Data , Heap .MutableData , Regions .Data , Returns .Data , Trace ) ?=> T
491
518
492
519
// --------------------------- domain operations -----------------------------
493
520
@@ -595,7 +622,13 @@ object Objects:
595
622
val env2 = Env .of(ddef, args.map(_.value), outerEnv)
596
623
extendTrace(ddef) {
597
624
given Env .Data = env2
598
- eval(ddef.rhs, ref, cls, cacheResult = true )
625
+ // eval(ddef.rhs, ref, cls, cacheResult = true)
626
+ cache.cachedEval(ref, ddef.rhs, cacheResult = true ) { expr =>
627
+ Returns .installHandler(meth)
628
+ val res = cases(expr, thisV, cls)
629
+ val returns = Returns .popHandler(meth)
630
+ res.join(returns)
631
+ }
599
632
}
600
633
else
601
634
Bottom
@@ -1079,7 +1112,8 @@ object Objects:
1079
1112
evalExprs(cases.map(_.body), thisV, klass).join
1080
1113
1081
1114
case Return (expr, from) =>
1082
- eval(expr, thisV, klass)
1115
+ Returns .handle(from.symbol, eval(expr, thisV, klass))
1116
+ Bottom
1083
1117
1084
1118
case WhileDo (cond, body) =>
1085
1119
evalExprs(cond :: body :: Nil , thisV, klass)
0 commit comments