Introduce incrementality-allowed levels: No, Unsafe, Yes

Instead of simple allowed/not option sometimes Unsafe
is useful. 'Unsafe' status may be present when there're
few "bad" rules.
With this level end code may resolve to go with
incrementality without strict guarantees.
This commit is contained in:
Grigorii Kirgizov 2020-07-23 12:13:29 +03:00
parent f6d7f5c4bd
commit 54335cb2fd
12 changed files with 120 additions and 82 deletions

View File

@ -18,7 +18,7 @@ package jetbrains.mps.logic.reactor.core.internal
import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.evaluation.EvaluationTrace
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.evaluation.SessionToken
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalContext
@ -43,7 +43,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
journal: MatchJournalImpl,
private val ruleIndex: RuleIndex,
val logicalState: LogicalState,
override val ispec: IncrementalProgramSpec = IncrementalProgramSpec.DefaultSpec,
override val ispec: IncrementalSpec = IncrementalSpec.DefaultSpec,
val trace: EvaluationTrace = EvaluationTrace.NULL,
val profiler: Profiler? = null)
: StoreAwareJournalImpl(journal, logicalState), IncrSpecHolder
@ -222,7 +222,9 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
logActivation(active)
active.revive(logicalState)
if (ispec.assertContracts()) active.addContractObservers(logicalState)
if (ispec.assertLevel().assertContracts()) {
active.addContractObservers(logicalState)
}
}
assert(active.alive)

View File

@ -23,7 +23,7 @@ import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalContext
import jetbrains.mps.logic.reactor.logical.MetaLogical
import jetbrains.mps.logic.reactor.program.Constraint
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.program.Predicate
import jetbrains.mps.logic.reactor.util.Profiler
import jetbrains.mps.logic.reactor.util.profile
@ -31,7 +31,7 @@ import jetbrains.mps.logic.reactor.util.profile
internal class ControllerImpl (
val supervisor: Supervisor,
val processing: ConstraintsProcessing,
override val ispec: IncrementalProgramSpec = IncrementalProgramSpec.DefaultSpec,
override val ispec: IncrementalSpec = IncrementalSpec.DefaultSpec,
val trace: EvaluationTrace = EvaluationTrace.NULL,
val profiler: Profiler? = null) : Controller, IncrSpecHolder
{
@ -369,11 +369,11 @@ fun createController(
MatchJournalImpl(),
ruleIndex,
logicalState,
IncrementalProgramSpec.DefaultSpec,
IncrementalSpec.DefaultSpec,
trace,
profiler
),
IncrementalProgramSpec.DefaultSpec,
IncrementalSpec.DefaultSpec,
trace,
profiler
)

View File

@ -20,7 +20,7 @@ import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.core.internal.FeedbackStatus.FAILED
import jetbrains.mps.logic.reactor.evaluation.*
import jetbrains.mps.logic.reactor.program.Constraint
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.program.Program
import jetbrains.mps.logic.reactor.util.Profiler
import java.util.*
@ -41,7 +41,7 @@ internal class EvaluationSessionImpl private constructor (
private fun launch(
main: Constraint, profiler: Profiler?,
token: SessionToken?, rulesDiff: RulesDiff, ispec: IncrementalProgramSpec
token: SessionToken?, rulesDiff: RulesDiff, incrementality: IncrementalSpec
) : EvaluationResult {
val newToken: SessionToken
@ -50,15 +50,15 @@ internal class EvaluationSessionImpl private constructor (
val ruleIndex = RuleIndex(program.rulesLists())
if (ispec is IncrementalProgramSpec.NonIncrSpec || token == null) {
if (!incrementality.ability().allowed() || token == null) {
val logicalState = LogicalState()
val processing = ConstraintsProcessing(
Dispatcher(ruleIndex).front(),
MatchJournalImpl(ispec),
ruleIndex, logicalState, ispec, trace, profiler
MatchJournalImpl(incrementality),
ruleIndex, logicalState, incrementality, trace, profiler
)
val controller = ControllerImpl(supervisor, processing, ispec, trace, profiler)
val controller = ControllerImpl(supervisor, processing, incrementality, trace, profiler)
logicalState.init(controller)
status = controller.activate(main)
@ -71,10 +71,10 @@ internal class EvaluationSessionImpl private constructor (
val processing = ConstraintsProcessing(
Dispatcher(ruleIndex, tkn.getFrontState()).front(),
MatchJournalImpl(ispec, tkn.journalView as MatchJournal.View),
ruleIndex, logicalState, ispec, trace, profiler
MatchJournalImpl(incrementality, tkn.journalView as MatchJournal.View),
ruleIndex, logicalState, incrementality, trace, profiler
)
val controller = ControllerImpl(supervisor, processing, ispec, trace, profiler)
val controller = ControllerImpl(supervisor, processing, incrementality, trace, profiler)
logicalState.init(controller)
val status2tags = controller.incrLaunch(main, rulesDiff)
@ -97,7 +97,7 @@ internal class EvaluationSessionImpl private constructor (
var evaluationTrace: EvaluationTrace = EvaluationTrace.NULL
var ispec: IncrementalProgramSpec = IncrementalProgramSpec.DefaultSpec
var ispec: IncrementalSpec = IncrementalSpec.DefaultSpec
var token: SessionToken? = null
@ -115,7 +115,7 @@ internal class EvaluationSessionImpl private constructor (
return this
}
override fun withIncrSpec(ispec: IncrementalProgramSpec): EvaluationSession.Config {
override fun withIncrSpec(ispec: IncrementalSpec): EvaluationSession.Config {
this.ispec = ispec
return this
}

View File

@ -19,11 +19,11 @@ package jetbrains.mps.logic.reactor.core.internal
import jetbrains.mps.logic.reactor.core.Occurrence
import jetbrains.mps.logic.reactor.evaluation.RuleMatch
import jetbrains.mps.logic.reactor.program.IncrementalContractViolationException
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.program.Rule
interface IncrSpecHolder {
val ispec: IncrementalProgramSpec
val ispec: IncrementalSpec
val Occurrence.isPrincipal get() = ispec.isPrincipal(this.constraint())
@ -47,5 +47,5 @@ inline fun IncrSpecHolder.assertContract(lazyValue: () -> Boolean) {
assertContract(lazyValue) { "Contract assertion failed" }
}
inline fun IncrSpecHolder.assertContract(lazyValue: () -> Boolean, noinline lazyMsg: () -> String) {
if (ispec.assertContracts()) checkContract(lazyValue(), lazyMsg)
if (ispec.assertLevel().assertContracts()) checkContract(lazyValue(), lazyMsg)
}

View File

@ -30,7 +30,7 @@ import java.util.*
internal open class MatchJournalImpl(
override val ispec: IncrementalProgramSpec,
override val ispec: IncrementalSpec,
view: MatchJournal.View? = null
) : MatchJournal, IncrSpecHolder {
@ -87,7 +87,7 @@ internal open class MatchJournalImpl(
ancestorChunksStack = mutableListOf(initialChunk())
}
constructor(view: MatchJournal.View? = null) : this(IncrementalProgramSpec.DefaultSpec, view)
constructor(view: MatchJournal.View? = null) : this(IncrementalSpec.DefaultSpec, view)
// pointer to current position in history where logging (chunk additions) and log erasing (chunk removals) happens

View File

@ -17,7 +17,7 @@
package jetbrains.mps.logic.reactor.core.internal
import jetbrains.mps.logic.reactor.core.LogicalStateObservable
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import java.lang.IllegalArgumentException
@ -34,7 +34,7 @@ interface StoreAwareJournal : MatchJournal, LogicalStateObservable {
// for tests
companion object {
fun fromView(
ispec: IncrementalProgramSpec = IncrementalProgramSpec.DefaultSpec,
ispec: IncrementalSpec = IncrementalSpec.DefaultSpec,
view: MatchJournal.View? = null
): StoreAwareJournal = StoreAwareJournalImpl(MatchJournalImpl(ispec, view))
}

View File

@ -17,12 +17,9 @@
package jetbrains.mps.logic.reactor.evaluation;
import jetbrains.mps.logic.reactor.core.RulesDiff;
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec;
import jetbrains.mps.logic.reactor.program.IncrementalSpec;
import jetbrains.mps.logic.reactor.program.Program;
import java.util.Map;
/**
* The starting point to evaluate a program.
* <p>
@ -88,7 +85,7 @@ public abstract class EvaluationSession {
public Config withSessionToken(SessionToken token) { return this; }
public Config withIncrSpec(IncrementalProgramSpec ispec) { return this; }
public Config withIncrSpec(IncrementalSpec ispec) { return this; }
public abstract EvaluationResult start(Supervisor supervisor);

View File

@ -1,40 +0,0 @@
/*
* Copyright 2014-2019 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.logic.reactor.program;
public interface IncrementalProgramSpec {
boolean isPrincipal(Constraint ctr);
boolean isPrincipal(Rule rule);
boolean isWeakPrincipal(Rule rule);
boolean assertContracts();
class NonIncrSpec implements IncrementalProgramSpec {
@Override
public boolean isPrincipal(Constraint ctr) { return false; }
@Override
public boolean isPrincipal(Rule rule) { return false; }
@Override
public boolean isWeakPrincipal(Rule rule) { return false; }
@Override
public boolean assertContracts() { return false; }
}
NonIncrSpec DefaultSpec = new NonIncrSpec();
}

View File

@ -0,0 +1,78 @@
/*
* Copyright 2014-2019 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.logic.reactor.program;
import org.jetbrains.annotations.NotNull;
public interface IncrementalSpec {
boolean isPrincipal(Constraint ctr);
boolean isPrincipal(Rule rule);
boolean isWeakPrincipal(Rule rule);
@NotNull
Enabled ability();
@NotNull
AssertLevel assertLevel();
enum Enabled {
No, Unsafe, Yes;
public Enabled min(Enabled other) {
return this.compareTo(other) <= 0 ? this : other;
}
public boolean allowed() {
return this.compareTo(Enabled.No) > 0;
}
public boolean strict() {
return this.compareTo(Enabled.Yes) >= 0;
}
}
enum AssertLevel {
Normal, AssertContracts;
public AssertLevel max(AssertLevel other) {
return this.compareTo(other) >= 0 ? this : other;
}
public boolean assertContracts() {
return this.compareTo(AssertLevel.AssertContracts) >= 0;
}
}
class StubSpec implements IncrementalSpec {
@Override
public boolean isPrincipal(Constraint ctr) { return false; }
@Override
public boolean isPrincipal(Rule rule) { return false; }
@Override
public boolean isWeakPrincipal(Rule rule) { return false; }
@Override
@NotNull
public Enabled ability() { return Enabled.No; }
@NotNull
@Override
public AssertLevel assertLevel() { return AssertLevel.Normal; }
}
StubSpec DefaultSpec = new StubSpec();
}

View File

@ -14,27 +14,27 @@
* limitations under the License.
*/
import jetbrains.mps.logic.reactor.core.allHeads
import jetbrains.mps.logic.reactor.program.Constraint
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.program.Rule
class MockIncrProgSpec(
val principalRuleTags: Set<Any>,
val principalCtrSyms: Set<ConstraintSymbol>,
val weakPrincipalRuleTags: Set<Any>,
private var checkContracts: Boolean = false
) : IncrementalProgramSpec {
private var strictness: IncrementalSpec.AssertLevel = IncrementalSpec.AssertLevel.Normal
) : IncrementalSpec {
constructor(principalRuleTags: Set<Any>, principalCtrSyms: Set<ConstraintSymbol>) :
this(principalRuleTags, principalCtrSyms, emptySet())
fun withContractChecks() = this.also { checkContracts = true }
fun withContractChecks() = this.also { strictness = IncrementalSpec.AssertLevel.AssertContracts }
override fun isPrincipal(ctr: Constraint): Boolean = principalCtrSyms.contains(ctr.symbol())
override fun isPrincipal(rule: Rule): Boolean = principalRuleTags.contains(rule.uniqueTag())
override fun isWeakPrincipal(rule: Rule): Boolean = weakPrincipalRuleTags.contains(rule.uniqueTag())
override fun assertContracts(): Boolean = checkContracts
override fun ability(): IncrementalSpec.Enabled = IncrementalSpec.Enabled.Yes
override fun assertLevel(): IncrementalSpec.AssertLevel = strictness
}

View File

@ -1,4 +1,4 @@
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.core.Occurrence
import jetbrains.mps.logic.reactor.core.ReactorLifecycle
import jetbrains.mps.logic.reactor.core.RulesDiff
@ -51,7 +51,7 @@ class TestIncrementalProgram {
}
}
private fun Builder.launch(name: String, incrSpec: IncrementalProgramSpec, resultHandler: (EvaluationResult) -> Unit)
private fun Builder.launch(name: String, incrSpec: IncrementalSpec, resultHandler: (EvaluationResult) -> Unit)
: Pair<Builder, EvaluationResult>
{
val result = EvaluationSession.newSession(program(name))
@ -63,7 +63,7 @@ class TestIncrementalProgram {
return this to result
}
private fun Builder.relaunch(name: String, incrSpec: IncrementalProgramSpec, sessionToken: SessionToken, resultHandler: (EvaluationResult) -> Unit )
private fun Builder.relaunch(name: String, incrSpec: IncrementalSpec, sessionToken: SessionToken, resultHandler: (EvaluationResult) -> Unit )
: Pair<Builder, EvaluationResult>
{
val prog = program(name).withRulesDiff(

View File

@ -2,7 +2,7 @@ import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.core.internal.*
import jetbrains.mps.logic.reactor.program.Constraint
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
import jetbrains.mps.logic.reactor.program.IncrementalProgramSpec
import jetbrains.mps.logic.reactor.program.IncrementalSpec
import jetbrains.mps.logic.reactor.program.Rule
import org.junit.Test
import org.junit.Assert.*
@ -27,14 +27,15 @@ import org.junit.Ignore
class TestStoreAwareJournal {
private object LegacyMockIncrProgSpec : IncrementalProgramSpec.NonIncrSpec() {
private object LegacyMockIncrProgSpec : IncrementalSpec.StubSpec() {
override fun isPrincipal(ctr: Constraint): Boolean = ctr.isPrincipal
override fun isPrincipal(rule: Rule): Boolean = rule.all().any { it is Constraint && it.isPrincipal }
override fun ability(): IncrementalSpec.Enabled = IncrementalSpec.Enabled.Yes
}
private class JournalDispatcherHelper(
dispatcher: Dispatcher,
ispec: IncrementalProgramSpec = LegacyMockIncrProgSpec,
ispec: IncrementalSpec = LegacyMockIncrProgSpec,
val hist: StoreAwareJournal = StoreAwareJournal.fromView(ispec)
) {
var d: Dispatcher.DispatchingFront = dispatcher.front()