Commit 3c030656 authored by dgelessus's avatar dgelessus
Browse files

Make :exec/:init/:constants automatically move in trace as needed

parent bc7eafab
Pipeline #43247 passed with stage
in 3 minutes and 24 seconds
......@@ -4,6 +4,9 @@
* Updated ProB 2 to version 4.0.0-SNAPSHOT.
* Improved the performance of loading machines by reusing the existing instance of ProB instead of starting a new one for each machine.
* Changed the `:exec`, `:init` and `:constants` commands to automatically move forward or backward in the trace to allow the command to execute successfully.
* Executing `:init` in an already initialised state will return to the last uninitialised state to re-initialise the machine (possibly with different initial values). The same works for `:constants`. Previously this caused an error "Machine is already initialised" or "Machine constants are already set up".
* Executing an operation in an uninitialised state will automatically initialise the machine with an arbitrary valid initialisation transition. If the machine has constants, they are also set up automatically in a similar way. This is useful if the machine's constants/initial variables are unambiguous or the exact values are not important. Previously this caused an error "Machine is not initialised".
* Significantly refactored the logic for parsing commands and their arguments.
* This is an internal change and should not affect any user-visible behavior. That is, all inputs that were accepted by previous versions should still be accepted - if any previously valid inputs are no longer accepted, this is a bug.
* As a side effect, the inspection and code completion features now work better in a few edge cases.
......
......@@ -564,15 +564,15 @@
"outputs": [
{
"ename": "IllegalArgumentException",
"evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Machine is already initialised, cannot execute SETUP_CONSTANTS",
"evalue": "Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Machine is already initialised, cannot execute SETUP_CONSTANTS\u001b[0m"
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope\u001b[0m"
]
}
],
"source": [
":constants"
":exec nope"
]
},
{
......@@ -582,114 +582,294 @@
"outputs": [
{
"ename": "IllegalArgumentException",
"evalue": "Executing operation $initialise_machine with predicate 1=1 produced errors: Machine is already initialised, cannot execute INITIALISATION",
"evalue": "Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $initialise_machine with predicate 1=1 produced errors: Machine is already initialised, cannot execute INITIALISATION\u001b[0m"
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)\u001b[0m"
]
}
],
"source": [
":init"
":exec add 1=0"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Loaded machine: NoConstants"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"::load\n",
"MACHINE NoConstants\n",
"VARIABLES z\n",
"INVARIANT z : MININT..MAXINT\n",
"INITIALISATION z :: {0, 1}\n",
"OPERATIONS\n",
" nothing = skip\n",
"END"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"ename": "IllegalArgumentException",
"evalue": "Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope",
"evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation nope with predicate 1=1 produced errors: Unknown Operation nope\u001b[0m"
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root\u001b[0m"
]
}
],
"source": [
":exec nope"
":constants"
]
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 27,
"metadata": {},
"outputs": [
{
"ename": "IllegalArgumentException",
"evalue": "Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)",
"ename": "ProBError",
"evalue": "ProB reported Errors\nProB returned error messages:\nError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation add with predicate 1=0 produced errors: Could not execute operation add in state 6 with additional predicate (but a transition for operation exists)\u001b[0m"
"\u001b[1m\u001b[30mError from ProB: \u001b[0m\u001b[1m\u001b[31mProB reported Errors\u001b[0m",
"\u001b[1m\u001b[31mError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)\u001b[0m",
"\u001b[1m\u001b[30m// Source code not known\u001b[0m"
]
}
],
"source": [
":exec add 1=0"
":init z = -1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Executing an operation in an uninitialised machine automatically initialises the machine."
]
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Loaded machine: NoConstants"
"Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
"Executed operation: nothing()"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":exec nothing"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An already initialised machine can be reinitialised."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Machine was already initialised. Returned to uninitialised state to re-initialise the machine.\n",
"Executed operation: INITIALISATION()"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":init z = 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The same also works if the machine has constants."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Loaded machine: ItHasConstants"
]
},
"execution_count": 27,
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"::load\n",
"MACHINE NoConstants\n",
"MACHINE ItHasConstants\n",
"CONSTANTS c\n",
"PROPERTIES c : MININT..MAXINT\n",
"VARIABLES z\n",
"INVARIANT z : MININT..MAXINT\n",
"INITIALISATION z :: {0, 1}\n",
"OPERATIONS\n",
" nothing = skip\n",
"END"
]
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 31,
"metadata": {},
"outputs": [
{
"ename": "IllegalArgumentException",
"evalue": "Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root",
"evalue": "Executing operation $initialise_machine with predicate z = 0 produced errors: Could not execute operation INITIALISATION in state root with additional predicate",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $setup_constants with predicate 1=1 produced errors: Could not execute operation SETUP_CONSTANTS in state root\u001b[0m"
"\u001b[1m\u001b[31mjava.lang.IllegalArgumentException: Executing operation $initialise_machine with predicate z = 0 produced errors: Could not execute operation INITIALISATION in state root with additional predicate\u001b[0m"
]
}
],
"source": [
":constants"
":init z = 0"
]
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 32,
"metadata": {},
"outputs": [
{
"ename": "ProBError",
"evalue": "ProB reported Errors\nProB returned error messages:\nError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)",
"output_type": "error",
"traceback": [
"\u001b[1m\u001b[30mError from ProB: \u001b[0m\u001b[1m\u001b[31mProB reported Errors\u001b[0m",
"\u001b[1m\u001b[31mError: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:4:15 to 4:26)\u001b[0m",
"\u001b[1m\u001b[30m// Source code not known\u001b[0m"
]
"data": {
"text/plain": [
"Executed operation: SETUP_CONSTANTS()"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":init z = -1"
":constants c = 2"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
"Executed operation: nothing()"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":exec nothing"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Machine was already initialised. Returned to uninitialised state to re-initialise the machine.\n",
"Executed operation: INITIALISATION()"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":init z = 1"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Changed to state with index -1"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":goto -1"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Machine constants were not set up yet. Automatically set up constants using arbitrary transition: SETUP_CONSTANTS()\n",
"Machine was not initialised yet. Automatically initialised machine using arbitrary transition: INITIALISATION()\n",
"Executed operation: nothing()"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
":exec nothing"
]
},
{
......@@ -701,7 +881,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 37,
"metadata": {},
"outputs": [
{
......@@ -710,7 +890,7 @@
"Loaded machine: Foo"
]
},
"execution_count": 30,
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
......@@ -728,7 +908,7 @@
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": 38,
"metadata": {},
"outputs": [
{
......@@ -737,7 +917,7 @@
"Executed operation: SETUP_CONSTANTS()"
]
},
"execution_count": 31,
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
......@@ -748,7 +928,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 39,
"metadata": {},
"outputs": [
{
......@@ -757,7 +937,7 @@
"Executed operation: INITIALISATION()"
]
},
"execution_count": 32,
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
......@@ -768,7 +948,7 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": 40,
"metadata": {},
"outputs": [
{
......@@ -780,7 +960,7 @@
"1"
]
},
"execution_count": 33,
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
......@@ -791,7 +971,7 @@
},
{
"cell_type": "code",
"execution_count": 34,
"execution_count": 41,
"metadata": {},
"outputs": [
{
......@@ -803,7 +983,7 @@
"2"
]
},
"execution_count": 34,
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
......@@ -821,7 +1001,7 @@
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 42,
"metadata": {},
"outputs": [
{
......@@ -830,7 +1010,7 @@
"Loaded machine: Counter"
]
},
"execution_count": 35,
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
......@@ -854,7 +1034,7 @@
},
{
"cell_type": "code",
"execution_count": 36,
"execution_count": 43,
"metadata": {},
"outputs": [
{
......@@ -866,7 +1046,7 @@
"1"
]
},
"execution_count": 36,
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
......@@ -877,7 +1057,7 @@
},
{
"cell_type": "code",
"execution_count": 37,
"execution_count": 44,
"metadata": {},
"outputs": [
{
......@@ -889,7 +1069,7 @@
"2"
]
},
"execution_count": 37,
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
......@@ -900,7 +1080,7 @@
},
{
"cell_type": "code",
"execution_count": 38,
"execution_count": 45,
"metadata": {},
"outputs": [
{
......@@ -909,7 +1089,7 @@
"Executed operation: SETUP_CONSTANTS()"
]
},
"execution_count": 38,
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
......@@ -920,7 +1100,7 @@
},
{
"cell_type": "code",
"execution_count": 39,
"execution_count": 46,
"metadata": {},
"outputs": [
{
......@@ -932,7 +1112,7 @@
"{−1,0,1,2}"
]
},
"execution_count": 39,
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
......@@ -943,7 +1123,7 @@
},
{
"cell_type": "code",
"execution_count": 40,
"execution_count": 47,
"metadata": {},
"outputs": [
{
......@@ -952,7 +1132,7 @@
"Executed operation: INITIALISATION()"
]
},
"execution_count": 40,
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
......@@ -963,7 +1143,7 @@
},
{
"cell_type": "code",
"execution_count": 41,
"execution_count": 48,
"metadata": {},
"outputs": [
{
......@@ -975,7 +1155,7 @@
"1"
]
},
"execution_count": 41,
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
......@@ -986,7 +1166,7 @@
},
{
"cell_type": "code",
"execution_count": 42,
"execution_count": 49,
"metadata": {},
"outputs": [
{
......@@ -995,7 +1175,7 @@
"Executed operation: add(-1)"
]
},
"execution_count": 42,
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
......@@ -1006,7 +1186,7 @@
},
{
"cell_type": "code",
"execution_count": 43,
"execution_count": 50,
"metadata": {},
"outputs": [
{
......@@ -1018,7 +1198,7 @@
"0"
]
},
"execution_count": 43,
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
......
%% Cell type:code id: tags:
``` prob
:help :browse
```
%%%% Output: execute_result
```
:browse
```
Show information about the current state.
The output shows the names of all sets, constants, and variables defined by the current machine, as well as a list of enabled operations (and possible parameter values) in the current state.
:browse
Show information about the current state.
The output shows the names of all sets, constants, and variables defined by the current machine, as well as a list of enabled operations (and possible parameter values) in the current state.
%% Cell type:code id: tags:
``` prob
:help :exec
```
%%%% Output: execute_result
```
:exec OPERATION [PREDICATE]
```
Execute an operation.
The predicate is used to select the operation's parameter values. The parameters can be fully specified explicitly (e. g. `:exec op param1 = 123 & param2 = {1, 2}`), or they can be partially constrained (e. g. `:exec op param1 > 100 & card(param2) >= 2`) to let ProB find a valid combination of parameters. If there are multiple valid combinations of parameters that satisfy the predicate, it is undefined which one is selected by ProB.
If no predicate is specified, the parameters are not constrained, and ProB will select an arbitrary valid combination of parameters.
:exec OPERATION [PREDICATE]
Execute an operation.
The predicate is used to select the operation's parameter values. The parameters can be fully specified explicitly (e. g. `:exec op param1 = 123 & param2 = {1, 2}`), or they can be partially constrained (e. g. `:exec op param1 > 100 & card(param2) >= 2`) to let ProB find a valid combination of parameters. If there are multiple valid combinations of parameters that satisfy the predicate, it is undefined which one is selected by ProB.
If no predicate is specified, the parameters are not constrained, and ProB will select an arbitrary valid combination of parameters.
%% Cell type:code id: tags:
``` prob
:help :constants
```
%%%% Output: execute_result
```
:constants [PREDICATE]
```
Set up the current machine's constants.
This is a shorthand for `:exec SETUP_CONSTANTS [PREDICATE]`.
:constants [PREDICATE]
Set up the current machine's constants.
This is a shorthand for `:exec SETUP_CONSTANTS [PREDICATE]`.
%% Cell type:code id: tags:
``` prob
:help :init
```
%%%% Output: execute_result
```
:init [PREDICATE]
```
Initialise the current machine with the specified predicate
This is a shorthand for `:exec INITIALISATION [PREDICATE]`.
:init [PREDICATE]
Initialise the current machine with the specified predicate
This is a shorthand for `:exec INITIALISATION [PREDICATE]`.
%% Cell type:code id: tags:
``` prob
:browse
```
%%%% Output: execute_result
Machine: repl
Sets: (none)
Constants: (none)
Variables: (none)
Operations:
INITIALISATION()
%% Cell type:code id: tags:
``` prob
::load
MACHINE Counter
CONSTANTS min_value, max_value
PROPERTIES min_value : MININT..0 & max_value : 0..MAXINT & min_value <= max_value
VARIABLES value
INVARIANT value : min_value..max_value
INITIALISATION value :: min_value..max_value
OPERATIONS
add(diff) = SELECT
value+diff : min_value..max_value
THEN
value := value+diff
END
END
```
%%%% Output: execute_result
Loaded machine: Counter
%% Cell type:code id: tags:
``` prob
:browse
```
%%%% Output: execute_result
Machine: Counter
Sets: (none)
Constants: min_value, max_value
Variables: value
Operations:
SETUP_CONSTANTS()
SETUP_CONSTANTS()
SETUP_CONSTANTS()
SETUP_CONSTANTS()
More operations may be available (MAX_OPERATIONS/MAX_INITIALISATIONS reached)
%% Cell type:code id: tags:
``` prob
min_value..max_value
```
%%%% Output: error
:eval: NOT-INITIALISED
%% Cell type:code id: tags:
``` prob
value
```
%%%% Output: error
:eval: NOT-INITIALISED
%% Cell type:code id: tags:
``` prob
:constants min_value=5 & max_value=-5
```
%%%% Output: error
java.lang.IllegalArgumentException: Executing operation $setup_constants with predicate min_value=5 & max_value=-5 produced errors: Could not execute operation SETUP_CONSTANTS in state root with additional predicate
%% Cell type:code id: tags:
``` prob
:constants min_value=-1 & max_value=2
```
%%%% Output: execute_result
Executed operation: SETUP_CONSTANTS()
%% Cell type:code id: tags:
``` prob
:browse
```
%%%% Output: execute_result
Machine: Counter
Sets: (none)
Constants: min_value, max_value
Variables: value
Operations:
INITIALISATION()
INITIALISATION()
INITIALISATION()
INITIALISATION()
More operations may be available (MAX_OPERATIONS/MAX_INITIALISATIONS reached)
%% Cell type:code id: tags:
``` prob
min_value..max_value
```
%%%% Output: execute_result
$\{-1,0,1,2\}$
{−1,0,1,2}
%% Cell type:code id: tags:
``` prob
value
```
%%%% Output: error
:eval: NOT-INITIALISED
%% Cell type:code id: tags:
``` prob
:init value=-100
```
%%%% Output: error
Error from ProB: ProB reported Errors
Error: INITIALISATION FAILS (/Users/Shared/Uni/SHK/ProB2/prob2-jupyter-kernel/notebooks/tests/(machine from Jupyter cell).mch:6:15 to 6:44)
// Source code not known
%% Cell type:code id: tags:
``` prob
:init value=2
```
%%%% Output: execute_result
Executed operation: INITIALISATION()
%% Cell type:code id: tags:
``` prob
:browse
```
%%%% Output: execute_result
Machine: Counter
Sets: (none)
Constants: min_value, max_value
Variables: value
Operations:
add(-3)
add(-2)
add(-1)
add(0)
%% Cell type:code id: tags:
``` prob
value
```
%%%% Output: execute_result
$2$
2
%% Cell type:code id: tags:
``` prob
:exec add diff=-1
```
%%%% Output: execute_result
Executed operation: add(-1)
%% Cell type:code id: tags:
``` prob
:browse
```
%%%% Output: execute_result
Machine: Counter
Sets: (none)
Constants: min_value, max_value
Variables: value
Operations:
add(-2)
add(-1)
add(0)
add(1)
%% Cell type:code id: tags:
``` prob
value
```
%%%% Output: execute_result