mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
Restrict degree to which Speedy.Machine exposes its mutable state
* Restrict degree to which Speedy.Machine exposes its mutable state CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
cfa7a34022
commit
f9b166ab35
@ -368,7 +368,7 @@ class Engine(val config: EngineConfig = Engine.StableConfig) {
|
||||
time: Time.Timestamp,
|
||||
): Result[(SubmittedTransaction, Tx.Metadata)] = machine.withOnLedger("Daml Engine") { onLedger =>
|
||||
def detailMsg = Some(
|
||||
s"Last location: ${Pretty.prettyLoc(machine.lastLocation).render(80)}, partial transaction: ${onLedger.nodesToString}"
|
||||
s"Last location: ${Pretty.prettyLoc(machine.getLastLocation).render(80)}, partial transaction: ${onLedger.nodesToString}"
|
||||
)
|
||||
def versionDisclosedContract(d: speedy.DisclosedContract): Versioned[DisclosedContract] = {
|
||||
val version = machine.tmplId2TxVersion(d.templateId)
|
||||
|
@ -4,18 +4,19 @@
|
||||
package com.daml.lf
|
||||
package speedy
|
||||
|
||||
import com.daml.lf.speedy.Speedy.{Machine, Control}
|
||||
import scala.collection.mutable.Map
|
||||
import com.daml.lf.speedy.Speedy.{Control, Machine}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
private[speedy] object Classify { // classify the machine state w.r.t what step occurs next
|
||||
|
||||
final class Counts(
|
||||
var ctrlExpr: Int = 0,
|
||||
var ctrlValue: Int = 0,
|
||||
var exprs: Map[String, Int] = Map.empty,
|
||||
var konts: Map[String, Int] = Map.empty,
|
||||
var exprs: mutable.Map[String, Int] = mutable.Map.empty,
|
||||
var konts: mutable.Map[String, Int] = mutable.Map.empty,
|
||||
) {
|
||||
def steps = ctrlExpr + ctrlValue
|
||||
def steps: Int = ctrlExpr + ctrlValue
|
||||
def pp: String = {
|
||||
val lines =
|
||||
(("CtrlExpr:", ctrlExpr) :: exprs.toList.map { case (expr, n) => ("- " + expr, n) }) ++
|
||||
@ -25,16 +26,16 @@ private[speedy] object Classify { // classify the machine state w.r.t what step
|
||||
}
|
||||
|
||||
def classifyMachine(machine: Machine, counts: Counts): Unit = {
|
||||
machine.control match {
|
||||
machine.currentControl match {
|
||||
case Control.Value(_) =>
|
||||
// classify a value by the continution it is about to return to
|
||||
counts.ctrlValue += 1
|
||||
val kont = machine.kontStack.get(machine.kontStack.size - 1).getClass.getSimpleName
|
||||
val _ = counts.konts += kont -> (counts.konts.get(kont).getOrElse(0) + 1)
|
||||
val kont = machine.peekKontStackEnd().getClass.getSimpleName
|
||||
val _ = counts.konts += kont -> (counts.konts.getOrElse(kont, 0) + 1)
|
||||
case Control.Expression(exp) =>
|
||||
counts.ctrlExpr += 1
|
||||
val expr = exp.getClass.getSimpleName
|
||||
val _ = counts.exprs += expr -> (counts.exprs.get(expr).getOrElse(0) + 1)
|
||||
val _ = counts.exprs += expr -> (counts.exprs.getOrElse(expr, 0) + 1)
|
||||
case _ => ()
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
package com.daml.lf
|
||||
package speedy
|
||||
|
||||
import java.util
|
||||
import scala.jdk.CollectionConverters._
|
||||
|
||||
import com.daml.lf.speedy.Speedy._
|
||||
@ -14,7 +13,7 @@ import com.daml.lf.speedy.SValue._
|
||||
private[speedy] object PrettyLightweight { // lightweight pretty printer for CEK machine states
|
||||
|
||||
def ppMachine(m: Machine): String = {
|
||||
s"[${m.envBase}] ${ppEnv(m.env)} -- ${ppCtrl(m.control)} -- ${ppKontStack(m.kontStack)}"
|
||||
s"[${m.currentEnvBase}] ${ppEnv(m.currentEnv)} -- ${ppCtrl(m.currentControl)} -- ${ppKontStack(m)}"
|
||||
}
|
||||
|
||||
def ppCtrl(control: Control): String =
|
||||
@ -31,8 +30,8 @@ private[speedy] object PrettyLightweight { // lightweight pretty printer for CEK
|
||||
s"#${env.size()}={${commas(env.asScala.map(pp))}}"
|
||||
}
|
||||
|
||||
def ppKontStack(ks: util.ArrayList[Kont]): String = {
|
||||
s"[${ppKont(ks.get(ks.size - 1))}... #${ks.size()}]" // head kont & size
|
||||
def ppKontStack(m: Machine): String = {
|
||||
s"[${ppKont(m.peekKontStackEnd())}... #${m.kontDepth()}]" // head kont & size
|
||||
}
|
||||
|
||||
def ppKont(k: Kont): String = k.getClass.getSimpleName
|
||||
|
@ -963,7 +963,7 @@ private[lf] object SBuiltin {
|
||||
templateId = cached.templateId,
|
||||
arg = createArgValue,
|
||||
agreementText = agreement,
|
||||
optLocation = machine.lastLocation,
|
||||
optLocation = machine.getLastLocation,
|
||||
signatories = cached.signatories,
|
||||
stakeholders = cached.stakeholders,
|
||||
key = cached.key,
|
||||
@ -1029,7 +1029,7 @@ private[lf] object SBuiltin {
|
||||
templateId = templateId,
|
||||
interfaceId = interfaceId,
|
||||
choiceId = choiceId,
|
||||
optLocation = machine.lastLocation,
|
||||
optLocation = machine.getLastLocation,
|
||||
consuming = consuming,
|
||||
actingParties = ctrls,
|
||||
signatories = sigs,
|
||||
@ -1454,7 +1454,7 @@ private[lf] object SBuiltin {
|
||||
onLedger.ptx.insertFetch(
|
||||
coid = coid,
|
||||
templateId = templateId,
|
||||
optLocation = machine.lastLocation,
|
||||
optLocation = machine.getLastLocation,
|
||||
signatories = signatories,
|
||||
observers = observers,
|
||||
key = key,
|
||||
@ -1498,7 +1498,7 @@ private[lf] object SBuiltin {
|
||||
}
|
||||
onLedger.ptx.insertLookup(
|
||||
templateId = templateId,
|
||||
optLocation = machine.lastLocation,
|
||||
optLocation = machine.getLastLocation,
|
||||
key = Node.KeyWithMaintainers(
|
||||
key = keyWithMaintainers.key,
|
||||
maintainers = keyWithMaintainers.maintainers,
|
||||
@ -1769,7 +1769,7 @@ private[lf] object SBuiltin {
|
||||
machine: Machine,
|
||||
): Control = {
|
||||
val message = getSText(args, 0)
|
||||
machine.traceLog.add(message, machine.lastLocation)(machine.loggingContext)
|
||||
machine.traceLog.add(message, machine.getLastLocation)(machine.loggingContext)
|
||||
Control.Value(args.get(1))
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ object SExpr {
|
||||
/** A let-expression with a single RHS */
|
||||
final case class SELet1General(rhs: SExpr, body: SExpr) extends SExpr with SomeArrayEquals {
|
||||
def execute(machine: Machine): Control = {
|
||||
machine.pushKont(KPushTo(machine, machine.env, body))
|
||||
machine.pushKont(KPushTo(machine, machine.currentEnv, body))
|
||||
Control.Expression(rhs)
|
||||
}
|
||||
}
|
||||
|
@ -113,22 +113,22 @@ private[lf] object Speedy {
|
||||
throw SError.SErrorDamlException(IError.Limit(error(limit)))
|
||||
|
||||
private[lf] final case class OnLedger(
|
||||
val validating: Boolean,
|
||||
val contractKeyUniqueness: ContractKeyUniquenessMode,
|
||||
validating: Boolean,
|
||||
contractKeyUniqueness: ContractKeyUniquenessMode,
|
||||
/* The current partial transaction */
|
||||
private[speedy] var ptx: PartialTransaction,
|
||||
/* Committers of the action. */
|
||||
val committers: Set[Party],
|
||||
committers: Set[Party],
|
||||
/* Additional readers (besides committers) for visibility checks. */
|
||||
val readAs: Set[Party],
|
||||
readAs: Set[Party],
|
||||
/* Commit location, if a scenario commit is in progress. */
|
||||
val commitLocation: Option[Location],
|
||||
commitLocation: Option[Location],
|
||||
/* Flag to trace usage of get_time builtins */
|
||||
var dependsOnTime: Boolean,
|
||||
// global contract discriminators, that are discriminators from contract created in previous transactions
|
||||
var cachedContracts: Map[V.ContractId, CachedContract],
|
||||
var numInputContracts: Int,
|
||||
val limits: interpretation.Limits,
|
||||
limits: interpretation.Limits,
|
||||
) extends LedgerMode {
|
||||
private[lf] val visibleToStakeholders: Set[Party] => SVisibleToStakeholders =
|
||||
if (validating) { _ => SVisibleToStakeholders.Visible }
|
||||
@ -298,25 +298,7 @@ private[lf] object Speedy {
|
||||
|
||||
/** The speedy CEK machine. */
|
||||
final class Machine(
|
||||
/* The machine control is either an expression or a value. */
|
||||
var control: Control,
|
||||
/* Frame: to access values for a closure's free-vars. */
|
||||
var frame: Frame,
|
||||
/* Actuals: to access values for a function application's arguments. */
|
||||
var actuals: Actuals,
|
||||
/* [env] is a stack of temporary values for: let-bindings and pattern-matches. */
|
||||
var env: Env,
|
||||
/* [envBase] is the depth of the temporaries-stack when the current code-context was
|
||||
* begun. We revert to this depth when entering a closure, or returning to the top
|
||||
* continuation on the kontStack.
|
||||
*/
|
||||
var envBase: Int,
|
||||
/* Kont, or continuation specifies what should be done next
|
||||
* once the control has been evaluated.
|
||||
*/
|
||||
var kontStack: util.ArrayList[Kont],
|
||||
/* The last encountered location */
|
||||
var lastLocation: Option[Location],
|
||||
val sexpr: SExpr,
|
||||
/* The trace log. */
|
||||
val traceLog: TraceLog,
|
||||
/* Engine-generated warnings. */
|
||||
@ -325,22 +307,61 @@ private[lf] object Speedy {
|
||||
implicit val loggingContext: LoggingContext,
|
||||
/* Compiled packages (Daml-LF ast + compiled speedy expressions). */
|
||||
var compiledPackages: CompiledPackages,
|
||||
/* Used when enableLightweightStepTracing is true */
|
||||
var steps: Int,
|
||||
/* Used when enableInstrumentation is true */
|
||||
var track: Instrumentation,
|
||||
/* Profile of the run when the packages haven been compiled with profiling enabled. */
|
||||
var profile: Profile,
|
||||
val profile: Profile = new Profile(),
|
||||
val submissionTime: Time.Timestamp,
|
||||
/* True if we are running on ledger building transactions, false if we
|
||||
are running off-ledger code, e.g., Daml Script or
|
||||
Triggers. It is safe to use on ledger for off ledger code but
|
||||
not the other way around.
|
||||
*/
|
||||
val submissionTime: Time.Timestamp,
|
||||
val ledgerMode: LedgerMode,
|
||||
val disclosureTable: DisclosureTable,
|
||||
) {
|
||||
|
||||
/* The machine control is either an expression or a value. */
|
||||
private[this] var control: Control = Control.Expression(sexpr)
|
||||
/* Frame: to access values for a closure's free-vars. */
|
||||
private[this] var frame: Frame = null
|
||||
/* Actuals: to access values for a function application's arguments. */
|
||||
private[this] var actuals: Actuals = null
|
||||
/* [env] is a stack of temporary values for: let-bindings and pattern-matches. */
|
||||
private[speedy] var env: Env = emptyEnv
|
||||
/* [envBase] is the depth of the temporaries-stack when the current code-context was
|
||||
* begun. We revert to this depth when entering a closure, or returning to the top
|
||||
* continuation on the kontStack.
|
||||
*/
|
||||
private[this] var envBase: Int = 0
|
||||
/* Kont, or continuation specifies what should be done next
|
||||
* once the control has been evaluated.
|
||||
*/
|
||||
private[speedy] var kontStack: util.ArrayList[Kont] = initialKontStack()
|
||||
/* The last encountered location */
|
||||
private[this] var lastLocation: Option[Location] = None
|
||||
/* Used when enableLightweightStepTracing is true */
|
||||
private[this] var steps: Int = 0
|
||||
/* Used when enableInstrumentation is true */
|
||||
private[this] var track: Instrumentation = Instrumentation()
|
||||
|
||||
private[speedy] def currentControl: Control = control
|
||||
|
||||
private[speedy] def currentFrame: Frame = frame
|
||||
|
||||
private[speedy] def currentActuals: Actuals = actuals
|
||||
|
||||
private[speedy] def currentEnv: Env = env
|
||||
|
||||
private[speedy] def currentEnvBase: Int = envBase
|
||||
|
||||
private[speedy] def currentKontStack: util.ArrayList[Kont] = kontStack
|
||||
|
||||
private[lf] def getLastLocation: Option[Location] = lastLocation
|
||||
|
||||
private[speedy] def clearEnv(): Unit = {
|
||||
env.clear()
|
||||
envBase = 0
|
||||
}
|
||||
|
||||
def tmplId2TxVersion(tmplId: TypeConName): TransactionVersion =
|
||||
TransactionVersion.assignNodeVersion(
|
||||
compiledPackages.pkgInterface.packageLanguageVersion(tmplId.packageId)
|
||||
@ -351,6 +372,8 @@ private[lf] object Speedy {
|
||||
|
||||
/* kont manipulation... */
|
||||
|
||||
private[speedy] def clearKontStack(): Unit = kontStack.clear()
|
||||
|
||||
@inline
|
||||
private[speedy] def kontDepth(): Int = kontStack.size()
|
||||
|
||||
@ -374,6 +397,16 @@ private[lf] object Speedy {
|
||||
kontStack.remove(kontStack.size - 1)
|
||||
}
|
||||
|
||||
@inline
|
||||
private[speedy] def peekKontStackEnd(): Kont = {
|
||||
kontStack.get(kontStack.size - 1)
|
||||
}
|
||||
|
||||
@inline
|
||||
private[speedy] def peekKontStackTop(): Kont = {
|
||||
kontStack.get(0)
|
||||
}
|
||||
|
||||
/* env manipulation... */
|
||||
|
||||
// The environment is partitioned into three locations: Stack, Args, Free
|
||||
@ -928,13 +961,7 @@ private[lf] object Speedy {
|
||||
disclosedContracts: ImmArray[speedy.DisclosedContract],
|
||||
)(implicit loggingContext: LoggingContext): Machine = {
|
||||
new Machine(
|
||||
control = Control.Expression(expr),
|
||||
frame = null,
|
||||
actuals = null,
|
||||
env = emptyEnv,
|
||||
envBase = 0,
|
||||
kontStack = initialKontStack(),
|
||||
lastLocation = None,
|
||||
sexpr = expr,
|
||||
submissionTime = submissionTime,
|
||||
ledgerMode = OnLedger(
|
||||
validating = validating,
|
||||
@ -958,9 +985,6 @@ private[lf] object Speedy {
|
||||
warningLog = warningLog,
|
||||
loggingContext = loggingContext,
|
||||
compiledPackages = compiledPackages,
|
||||
steps = 0,
|
||||
track = Instrumentation(),
|
||||
profile = new Profile(),
|
||||
disclosureTable = buildDiscTable(disclosedContracts, compiledPackages.pkgInterface),
|
||||
)
|
||||
}
|
||||
@ -977,6 +1001,7 @@ private[lf] object Speedy {
|
||||
limits: interpretation.Limits = interpretation.Limits.Lenient,
|
||||
)(implicit loggingContext: LoggingContext): Machine = {
|
||||
val updateSE: SExpr = compiledPackages.compiler.unsafeCompile(updateE)
|
||||
|
||||
fromUpdateSExpr(
|
||||
compiledPackages,
|
||||
transactionSeed,
|
||||
@ -1050,22 +1075,13 @@ private[lf] object Speedy {
|
||||
warningLog: WarningLog = newWarningLog,
|
||||
)(implicit loggingContext: LoggingContext): Machine = {
|
||||
new Machine(
|
||||
control = Control.Expression(expr),
|
||||
frame = null,
|
||||
actuals = null,
|
||||
env = emptyEnv,
|
||||
envBase = 0,
|
||||
kontStack = initialKontStack(),
|
||||
lastLocation = None,
|
||||
sexpr = expr,
|
||||
submissionTime = Time.Timestamp.Epoch,
|
||||
ledgerMode = OffLedger,
|
||||
traceLog = traceLog,
|
||||
warningLog = warningLog,
|
||||
loggingContext = loggingContext,
|
||||
compiledPackages = compiledPackages,
|
||||
steps = 0,
|
||||
track = Instrumentation(),
|
||||
profile = new Profile(),
|
||||
disclosureTable = buildDiscTable(disclosedContracts, compiledPackages.pkgInterface),
|
||||
)
|
||||
}
|
||||
@ -1137,8 +1153,8 @@ private[lf] object Speedy {
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val savedBase = machine.markBase()
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(vfun: SValue): Control = {
|
||||
machine.restoreBase(savedBase);
|
||||
@ -1155,8 +1171,8 @@ private[lf] object Speedy {
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val savedBase = machine.markBase()
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(vfun: SValue): Control = {
|
||||
machine.restoreBase(savedBase);
|
||||
@ -1315,8 +1331,8 @@ private[lf] object Speedy {
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val savedBase = machine.markBase()
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(v: SValue): Control = {
|
||||
machine.restoreBase(savedBase);
|
||||
@ -1329,7 +1345,7 @@ private[lf] object Speedy {
|
||||
* This continuation is used to implement both function application and lets. In
|
||||
* the case of function application the arguments are pushed into the 'actuals' array of
|
||||
* the PAP that is being built, and in the case of lets the evaluated value is pushed
|
||||
* direy into the environment.
|
||||
* directly into the environment.
|
||||
*/
|
||||
private[speedy] final case class KPushTo(
|
||||
machine: Machine,
|
||||
@ -1339,8 +1355,8 @@ private[lf] object Speedy {
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val savedBase = machine.markBase()
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(v: SValue): Control = {
|
||||
machine.restoreBase(savedBase);
|
||||
@ -1357,8 +1373,8 @@ private[lf] object Speedy {
|
||||
) extends Kont
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(acc: SValue): Control = {
|
||||
list.pop match {
|
||||
@ -1383,8 +1399,8 @@ private[lf] object Speedy {
|
||||
) extends Kont
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(acc: SValue): Control = {
|
||||
if (lastIndex > 0) {
|
||||
@ -1411,8 +1427,8 @@ private[lf] object Speedy {
|
||||
) extends Kont
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(closure: SValue): Control = {
|
||||
revClosures = closure +: revClosures
|
||||
@ -1437,8 +1453,8 @@ private[lf] object Speedy {
|
||||
) extends Kont
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
def execute(acc: SValue): Control = {
|
||||
revClosures.pop match {
|
||||
@ -1488,7 +1504,6 @@ private[lf] object Speedy {
|
||||
Control.Value(cached.any)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private[speedy] final case class KCheckKeyVisibility(
|
||||
@ -1497,6 +1512,7 @@ private[lf] object Speedy {
|
||||
cid: V.ContractId,
|
||||
handleKeyFound: (Machine, V.ContractId) => Control,
|
||||
) extends Kont {
|
||||
|
||||
def execute(sv: SValue): Control = {
|
||||
machine.withOnLedger("KCheckKeyVisibitiy") { onLedger =>
|
||||
machine.checkKeyVisibility(onLedger, gKey, cid, handleKeyFound)
|
||||
@ -1530,8 +1546,8 @@ private[lf] object Speedy {
|
||||
with SomeArrayEquals {
|
||||
|
||||
private[this] val savedBase = machine.markBase()
|
||||
private[this] val frame = machine.frame
|
||||
private[this] val actuals = machine.actuals
|
||||
private[this] val frame = machine.currentFrame
|
||||
private[this] val actuals = machine.currentActuals
|
||||
|
||||
// we must restore when catching a throw, or for normal execution
|
||||
def restore(): Unit = {
|
||||
@ -1597,9 +1613,8 @@ private[lf] object Speedy {
|
||||
// We must abort, because the transaction has failed in a way that is
|
||||
// unrecoverable (it depends on the state of an input contract that
|
||||
// we may not have the authority to fetch).
|
||||
machine.kontStack.clear()
|
||||
machine.env.clear()
|
||||
machine.envBase = 0
|
||||
machine.clearKontStack()
|
||||
machine.clearEnv()
|
||||
k.abort()
|
||||
case KPreventException(_) =>
|
||||
throw SError.SErrorDamlException(
|
||||
@ -1620,9 +1635,8 @@ private[lf] object Speedy {
|
||||
machine.pushEnv(excep) // payload on stack where handler expects it
|
||||
Control.Expression(kh.handler)
|
||||
case None =>
|
||||
machine.kontStack.clear()
|
||||
machine.env.clear()
|
||||
machine.envBase = 0
|
||||
machine.clearKontStack()
|
||||
machine.clearEnv()
|
||||
Control.Error(
|
||||
IError.UnhandledException(excep.ty, excep.value.toUnnormalizedValue)
|
||||
)
|
||||
@ -1636,7 +1650,7 @@ private[lf] object Speedy {
|
||||
}
|
||||
}
|
||||
|
||||
/** Continuation produced by [[SELabelClsoure]] expressions. This is only
|
||||
/** Continuation produced by [[SELabelClosure]] expressions. This is only
|
||||
* used during profiling. Its purpose is to attach a label to closures such
|
||||
* that entering the closure can write an "open event" with that label.
|
||||
*/
|
||||
|
@ -118,13 +118,13 @@ class TailCallTest extends AnyWordSpec with Matchers with TableDrivenPropertyChe
|
||||
case None => ()
|
||||
case Some(bound) =>
|
||||
val onlyKont: Speedy.Kont =
|
||||
if (machine.kontStack.size != 1) {
|
||||
crash(s"setBoundedKontStack, unexpected size of kont-stack: ${machine.kontStack.size}")
|
||||
if (machine.kontDepth() != 1) {
|
||||
crash(s"setBoundedKontStack, unexpected size of kont-stack: ${machine.kontDepth()}")
|
||||
} else {
|
||||
machine.kontStack.get(0)
|
||||
machine.peekKontStackTop()
|
||||
}
|
||||
machine.kontStack = new BoundedArrayList[Speedy.Kont](bound)
|
||||
machine.kontStack.add(onlyKont)
|
||||
machine.pushKont(onlyKont)
|
||||
}
|
||||
// run the machine
|
||||
machine.run() match {
|
||||
|
@ -558,7 +558,7 @@ object Repl {
|
||||
case error: ScenarioRunner.ScenarioError =>
|
||||
println(
|
||||
"failed at " +
|
||||
prettyLoc(machine.lastLocation).render(128) +
|
||||
prettyLoc(machine.getLastLocation).render(128) +
|
||||
": " + PrettyScenario.prettyError(error.error).render(128)
|
||||
)
|
||||
failures += 1
|
||||
|
@ -61,7 +61,7 @@ class CollectAuthorityState {
|
||||
compiledPackages,
|
||||
expr,
|
||||
)
|
||||
the_sexpr = machine.control match {
|
||||
the_sexpr = machine.currentControl match {
|
||||
case Control.Expression(exp) => exp
|
||||
case x => crash(s"expected Control.Expression, got: $x")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user