umaudemc 0.12.1__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
umaudemc/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.12.1'
1
+ __version__ = '0.12.2'
umaudemc/__main__.py CHANGED
@@ -62,7 +62,8 @@ def add_backend_arg(parser):
62
62
 
63
63
  parser.add_argument(
64
64
  '--backend',
65
- help='comma-separated prioritized list of model-checking backends (among maude, ltsmin, pymc, nusmv, spot, spin, builtin)'
65
+ help='comma-separated prioritized list of model-checking backends '
66
+ '(among maude, ltsmin, pymc, nusmv, spot, spin, builtin)'
66
67
  )
67
68
 
68
69
 
@@ -205,6 +206,11 @@ def build_parser():
205
206
  help='probability assignment method for adding them to the graph',
206
207
  metavar='METHOD'
207
208
  )
209
+ parser_graph.add_argument(
210
+ '-k', '--kleene-iteration',
211
+ help='write annotations on the transitions starting and terminating an iteration',
212
+ action='store_true'
213
+ )
208
214
  parser_graph.set_defaults(mode='graph')
209
215
 
210
216
  #
umaudemc/api.py CHANGED
@@ -215,7 +215,7 @@ class MaudeModel:
215
215
  :type merge_states: str
216
216
  :param backends: Prioritized list of model checking backends to be used
217
217
  :type backends: str or list of str
218
- :param formula_str: Formula given a a string (in case formula is a list)
218
+ :param formula_str: Formula given a string (in case formula is a list)
219
219
  :type formula_str: str or None
220
220
  :param logic: Logic (in case formula is a list)
221
221
  :type logic: str
@@ -297,7 +297,7 @@ class MaudeModel:
297
297
  wgraph = _wrappers.BoundedGraph(self.graph, depth) if depth > 0 else self.graph
298
298
 
299
299
  # Create and store the wrapped graph
300
- wgraph = _wrappers.wrapGraph(wgraph, purge, merge)
300
+ wgraph = _wrappers.wrap_graph(wgraph, purge, merge)
301
301
  self.wgraphs[(purge, merge, depth > 0)] = wgraph
302
302
 
303
303
  # In case both purge and merge are used, we keep the purged
@@ -517,7 +517,7 @@ class MaudeModel:
517
517
 
518
518
  def print_counterexample(self, stats, printer=None, sformat=None, eformat=None):
519
519
  """
520
- Pretty print an counterexample for a previous check (nothing is printed
520
+ Pretty print a counterexample for a previous check (nothing is printed
521
521
  if no counterexample has been found)
522
522
 
523
523
  :param stats: Statistics produced by the check method
umaudemc/backend/_spot.py CHANGED
@@ -8,7 +8,6 @@ import buddy
8
8
  import spot
9
9
 
10
10
  from ..formulae import collect_aprops
11
- from ..opsem import OpSemKleeneInstance, OpSemGraph
12
11
  from ..wrappers import create_graph
13
12
 
14
13
 
@@ -136,9 +135,10 @@ class KleeneModelBuilder(SpotModelBuilder):
136
135
  """Generator of ω-automata for strategy-controlled models with an iteration like the Kleene star"""
137
136
 
138
137
  def __init__(self, module, initial, strategy, aprops, bdd_dict, metamodule=None, opaques=()):
139
- self.instance = OpSemKleeneInstance.make_instance(module, metamodule)
138
+ from ..kleene import get_kleene_graph_mts
140
139
 
141
- super().__init__(self.instance.make_graph(initial, strategy, opaques), aprops, bdd_dict)
140
+ # opaque strategies are ignored with the new implementation
141
+ super().__init__(get_kleene_graph_mts(module, initial, strategy), aprops, bdd_dict)
142
142
 
143
143
  # Table of distinct iterations (from their context to the index of
144
144
  # its accepting condition)
@@ -166,7 +166,7 @@ class KleeneModelBuilder(SpotModelBuilder):
166
166
  state = pending.pop()
167
167
  state_spot = self.state_map[state]
168
168
 
169
- for next_state in self.graph.getNextStates(state):
169
+ for next_state, edge in self.graph.getTransitions(state):
170
170
  next_state_spot = self.state_map.get(next_state)
171
171
 
172
172
  if next_state_spot is None:
@@ -175,10 +175,10 @@ class KleeneModelBuilder(SpotModelBuilder):
175
175
  pending.append(next_state)
176
176
 
177
177
  # Check the iteration tags and set the accepting labels of the edges
178
- next_state_term = self.instance.get_cterm(self.graph.getStateTerm(next_state))
178
+ next_state_term = self.graph.getStateTerm(next_state)
179
179
  acc_set = []
180
180
 
181
- for tag, enter in self.instance.extract_tags(self.graph.getStateTerm(next_state)):
181
+ for tag, enter in edge.iterations:
182
182
  acc_index = self.iter_map.get(tag)
183
183
 
184
184
  if acc_index is None:
@@ -299,7 +299,6 @@ class SpotBackend:
299
299
  stats['counterexample'] = model_builder.extract_counterexample(run, model_automaton)
300
300
 
301
301
  if get_graph:
302
- stats['graph'] = model_builder.graph if not kleene_iteration \
303
- else OpSemGraph(model_builder.graph, model_builder.instance)
302
+ stats['graph'] = model_builder.graph
304
303
 
305
304
  return holds, stats
@@ -85,21 +85,21 @@ class ParityGame:
85
85
 
86
86
  # The recursive Zielonka's algorithm implemented in solve_rec does not
87
87
  # take finite plays into account, which are handled here. The recursive
88
- # algorithm receives a a game without deadlock states.
88
+ # algorithm receives a game without deadlock states.
89
89
  # (this decomposition is sound, because if player i can force the game
90
90
  # to reach a deadlock state for 1-i, player 1-i cannot force reaching a
91
91
  # deadlock state for i nor an infinite play)
92
92
  w0, w1 = self.solve_rec(whole_game - finite_win0 - finite_win1)
93
93
 
94
- # The winning states for each player are the union of those in which
95
- # they have an infinite and those in which they a finite winning strategy
94
+ # The winning states for each player are the union of those in which they
95
+ # have an infinite and those in which they have a finite winning strategy
96
96
  return w0.union(finite_win0), w1.union(finite_win1)
97
97
 
98
98
  def attractor(self, player, subgame, subset):
99
99
  """Compute the attractor of a subset on a subgraph for a player"""
100
100
 
101
- # Iteratively extend subset with the states where it is sure that
102
- # the given player can reach the previous subset.
101
+ # Iteratively extend subset with the states where it is certain
102
+ # that the given player can reach the previous subset.
103
103
 
104
104
  while True:
105
105
  # reach is what will be added to the attractor at each step
@@ -180,7 +180,7 @@ class ParityGame:
180
180
 
181
181
  # Solve subgame once subgame - B has been solved
182
182
  # (notice that the subgame variable is not really the
183
- # subgame, which is not longer needed, but B)
183
+ # subgame, which is no longer needed, but B)
184
184
  elif phase == 2:
185
185
  B = subgame
186
186
  result[1-player].update(B)
@@ -382,7 +382,7 @@ class MuMaudeGame(ParityGame):
382
382
  node = self.add_state(player, 0)
383
383
 
384
384
  elif head == '~_':
385
- # Formulae is assumed to be in negative normal form
385
+ # Formulae are assumed to be in negative normal form
386
386
  player = 0 if self.check_aprop(state, self.formula_nodes[fnode.children[0]].extra) else 1
387
387
  node = self.add_state(player, 0)
388
388
 
@@ -440,7 +440,7 @@ class MuMaudeGame(ParityGame):
440
440
  self.add_edge(parent, node)
441
441
 
442
442
  def solve_mucalc(self):
443
- """Generate a solve the μ-calculus game"""
443
+ """Solve the μ-calculus game"""
444
444
 
445
445
  self.build()
446
446
  w0, w1 = self.solve()
@@ -330,7 +330,7 @@ class LTSmin:
330
330
  aprops = set()
331
331
  collect_aprops(formula, aprops)
332
332
 
333
- # Create a instance of LTSmin and run it
333
+ # Create an instance of LTSmin and run it
334
334
  runner = self.new_runner()
335
335
  runner.set_module(module_str, metamodule_str, labels, opaque)
336
336
  runner.add_formula(formula, logic, aprops)
umaudemc/backend/nusmv.py CHANGED
@@ -315,7 +315,7 @@ class NuSMVGrapher:
315
315
  print(' esac;', file=self.outfile)
316
316
 
317
317
  def explore(self, graph, stateNr, bound=-1):
318
- """Explore the graph up to a optional given depth, adding the nodes to the visited set"""
318
+ """Explore the graph up to an optional given depth, adding the nodes to the visited set"""
319
319
  # Depth-first search with a stack
320
320
  pending = [(stateNr, bound)]
321
321
  self.visited.add(stateNr)
umaudemc/backend/prism.py CHANGED
@@ -136,7 +136,7 @@ def make_prism_query(form, aprops, deterministic, raw_form=None, cost=False, rew
136
136
  else:
137
137
  full_formula = f'{query}=? [ {prism_formula} ]'
138
138
 
139
- # Otherwise, if the model is a MDP, we calculate the minimum
139
+ # Otherwise, if the model is an MDP, we calculate the minimum
140
140
  # and maximum probabilities for the formula
141
141
  else:
142
142
  # Multiple formulae are admitted separated by semicolon
@@ -148,7 +148,7 @@ def make_prism_query(form, aprops, deterministic, raw_form=None, cost=False, rew
148
148
  def collect_raw_aprops(form, aprops):
149
149
  """Collect atomic propositions from raw formula"""
150
150
 
151
- # The start of the last string, whether a escape character
151
+ # The start of the last string, whether an escape character
152
152
  # has been just seen, the algorithm state (out, string or braces),
153
153
  # and the position where the current proposition starts
154
154
  last, escaped, state, pos = 0, False, 'o', 0
@@ -208,7 +208,7 @@ class PRISMBasedBackend:
208
208
  # Output the DTMC or MDP for the model
209
209
  # Expand the graph and calculate the output degrees
210
210
  grapher.graph(graph)
211
- # Output the map of an user-specified reward
211
+ # Output the map of a user-specified reward
212
212
  if reward is not None:
213
213
  grapher.make_reward(graph, 'user', reward)
214
214
 
umaudemc/backend/spin.py CHANGED
@@ -295,7 +295,7 @@ class SpinGrapher:
295
295
  print(' od\n}', file=self.outfile)
296
296
 
297
297
  def explore(self, graph, stateNr, bound=-1):
298
- """Explore the graph up to a optional given depth, adding the nodes to the visited set"""
298
+ """Explore the graph up to an optional given depth, adding the nodes to the visited set"""
299
299
  # Depth-first search with a stack
300
300
  pending = [(stateNr, bound)]
301
301
  self.visited.add(stateNr)
@@ -0,0 +1,21 @@
1
+ #
2
+ # Admissibility checking subcommand
3
+ #
4
+
5
+ import os
6
+
7
+ from ..common import parse_initial_data, usermsgs
8
+ # Meter las herramientas en backends y usar la misma estrategia que en otros contextos
9
+
10
+ def acheck(args):
11
+ """Admissibility check subcommand"""
12
+
13
+ # Parse the module data
14
+ data = parse_initial_data(args, only_module=True)
15
+
16
+ if data is None:
17
+ return 1
18
+
19
+ print(data.module)
20
+
21
+ return 0
umaudemc/command/graph.py CHANGED
@@ -11,7 +11,7 @@ from shutil import which
11
11
  from ..common import maude, usermsgs, default_model_settings, parse_initial_data, split_comma
12
12
  from ..formatter import get_formatters
13
13
  from ..grapher import DOTGrapher, PDOTGrapher, TikZGrapher
14
- from ..wrappers import wrapGraph
14
+ from ..wrappers import wrap_graph
15
15
 
16
16
 
17
17
  class ProcessStream:
@@ -96,6 +96,18 @@ def graph(args):
96
96
  args.merge_states,
97
97
  args.strategy)
98
98
 
99
+ # Check the Kleene iteration flag
100
+ kleene_graph = False
101
+
102
+ if args.kleene_iteration:
103
+ if not with_strategy:
104
+ usermsgs.print_warning('The --kleene-iteration flag should only be used with a strategy. Ignoring.')
105
+ elif args.passign:
106
+ usermsgs.print_warning('The --kleene-iteration flag cannot be used with probabilities. Ignoring.')
107
+ else:
108
+ kleene_graph = True
109
+
110
+
99
111
  # Select the appropriate rewriting graph
100
112
  # (probabilistic, strategy-controlled, or standard)
101
113
  if args.passign or oformat in ('prism', 'jani'):
@@ -106,20 +118,25 @@ def graph(args):
106
118
  purge_fails=args.purge_fails,
107
119
  merge_states=args.merge_states)
108
120
 
121
+ elif kleene_graph:
122
+ from ..kleene import get_kleene_graph
123
+ rwgraph = get_kleene_graph(initial_data)
124
+ rwgraph = wrap_graph(rwgraph, purge_fails, merge_states)
125
+
109
126
  elif not with_strategy:
110
127
  rwgraph = maude.RewriteGraph(initial_data.term)
111
128
 
112
129
  else:
113
130
  rwgraph = maude.StrategyRewriteGraph(initial_data.term, initial_data.strategy,
114
131
  initial_data.opaque, initial_data.full_matchrew)
115
- rwgraph = wrapGraph(rwgraph, purge_fails, merge_states)
132
+ rwgraph = wrap_graph(rwgraph, purge_fails, merge_states)
116
133
 
117
134
  # If something has failed when creating the graph
118
135
  if rwgraph is None:
119
136
  return 1
120
137
 
121
138
  # It is possible to generate models of the NuSMV and PRISM model checkers instead of
122
- # DOT graphs. They are can be annotated with atomic propositions that are checked in the states.
139
+ # DOT graphs. They can be annotated with atomic propositions that are checked in the states.
123
140
  if args.aprops is not None:
124
141
  aprops = [initial_data.module.parseTerm(prop) for prop in split_comma(args.aprops)]
125
142
 
@@ -129,8 +146,19 @@ def graph(args):
129
146
  else:
130
147
  aprops = []
131
148
 
149
+ # State and edge labels
132
150
  slabel, elabel = get_formatters(args.slabel, args.elabel, with_strategy, only_labels=True)
133
151
 
152
+ if kleene_graph:
153
+ # Extend the label with the iteration flags
154
+ original_elabel = elabel
155
+
156
+ def kleene_elabel(stmt):
157
+ iterations_txt = ''.join(f'{" +" if enter else " -"}{iid}' for iid, enter in stmt.iterations)
158
+ return f'{original_elabel(stmt)}{iterations_txt}'
159
+
160
+ elabel = kleene_elabel
161
+
134
162
  # Whether the graph should be seen as a CTMC and probabilities should not be normalized
135
163
  is_ctmc = args.passign and args.passign.startswith('ctmc-')
136
164
 
@@ -61,7 +61,7 @@ def plot_results(program, qdata):
61
61
  rs.append(query.h)
62
62
 
63
63
  else:
64
- # Parametric queries with less that two points are
64
+ # Parametric queries with less than two points are
65
65
  # ignored (line plots do not make sense for them)
66
66
  if len(xs) > 1:
67
67
  results.append((index, xs, ys, rs))
umaudemc/command/test.py CHANGED
@@ -64,9 +64,9 @@ def load_cases(filename):
64
64
 
65
65
  extension = os.path.splitext(filename)[1]
66
66
 
67
- # The YAML package is only loaded if YAML will be used because
68
- # it is an optional dependency
69
- if extension in {'.yaml', '.yml'}:
67
+ # The YAML package is only loaded when needed
68
+ # (pyaml is an optional dependency)
69
+ if extension in ('.yaml', '.yml'):
70
70
  try:
71
71
  import yaml
72
72
  from yaml.loader import SafeLoader
@@ -79,7 +79,7 @@ def load_cases(filename):
79
79
 
80
80
  # The YAML loader is replaced so that entities have its line number
81
81
  # associated to print more useful messages. This is not possible with
82
- # the standard JSON library as easily.
82
+ # the standard JSON library.
83
83
 
84
84
  class SafeLineLoader(SafeLoader):
85
85
  def construct_mapping(self, node, deep=False):
@@ -89,16 +89,34 @@ def load_cases(filename):
89
89
  return mapping
90
90
 
91
91
  try:
92
- with open(filename, 'r') as caspec:
92
+ with open(filename) as caspec:
93
93
  return yaml.load(caspec, Loader=SafeLineLoader)
94
94
 
95
95
  except yaml.error.YAMLError as ype:
96
96
  usermsgs.print_error(f'Error while parsing test file: {ype}.')
97
97
 
98
+ # TOML format
99
+ if extension == '.toml':
100
+ try:
101
+ import tomllib
102
+
103
+ except ImportError:
104
+ usermsgs.print_error(
105
+ 'Cannot load cases from TOML file, '
106
+ 'which is only available since Python 3.10.')
107
+ return None
108
+
109
+ try:
110
+ with open(filename) as caspec:
111
+ return tomllib.load(caspec)
112
+
113
+ except tomllib.TOMLDecodeError as tde:
114
+ usermsgs.print_error(f'Error while parsing test file: {tde}.')
115
+
98
116
  # JSON format
99
117
  else:
100
118
  try:
101
- with open(filename, 'r') as caspec:
119
+ with open(filename) as caspec:
102
120
  return json.load(caspec)
103
121
 
104
122
  except json.JSONDecodeError as jde:
@@ -321,7 +339,7 @@ class ParameterSet:
321
339
  # Fields admitted by the test specification format
322
340
  # (some others keys are admitted but treated apart)
323
341
  #
324
- # They consists of a name, a type, the function that need to be called for
342
+ # They consist of a name, a type, the function that need to be called for
325
343
  # parsing them, and the arguments that must be reparsed because of it.
326
344
 
327
345
  TEST_FIELDS = {
@@ -524,7 +542,7 @@ def read_cases(filename, source, parser, skip=0):
524
542
  if test.initial is None or test.formula is None:
525
543
  usermsgs.print_error((f'Missing initial state or formula for a test case in file {test.rel_filename}'
526
544
  f'(line {test.line_number}).') if len(test_stack) > 0 else
527
- f'Expected cases for file {test.rel_filename}.')
545
+ f'Expected cases for file {test.rel_filename}.')
528
546
  return None, None
529
547
 
530
548
  # Whether the model has changed
@@ -573,7 +591,7 @@ def _run_backend(name, backend, case, timeout, args):
573
591
  timeout=timeout)
574
592
 
575
593
 
576
- def run_tests(suite, backends, args, only_file=None, only_logic=None, resume=None, **kwargs):
594
+ def run_tests(suite, backends, args, only_file=None, only_logic=None, resume=None, **_):
577
595
  """Run the tests in the suite with the first backend available"""
578
596
 
579
597
  for source, cases in suite:
@@ -964,7 +982,7 @@ def _memory_case(memusage, psutil, case, name, backend, args, log, maudebin=None
964
982
  total,
965
983
  peak,
966
984
  stack
967
- ))
985
+ ))
968
986
 
969
987
 
970
988
  def memory_tests(suite, backends, args, only_file=None, only_logic=None,
umaudemc/common.py CHANGED
@@ -14,30 +14,6 @@ from . import usermsgs
14
14
  # Warn about old versions of the maude package installed
15
15
  #
16
16
 
17
- if hasattr(maude, 'StateTransitionGraph'):
18
- usermsgs.print_warning('Version 0.3 of the maude package contains bugs related to model checking.\n'
19
- 'Please update.')
20
-
21
- # Anyhow, allow using it at their own risk, for which some adaptations are needed
22
- maude.RewriteGraph = maude.StateTransitionGraph
23
- maude.StrategyRewriteGraph = maude.StrategyTransitionGraph
24
-
25
- maude.Symbol.__call__ = lambda self, *args: self.makeTerm(args)
26
-
27
- if not hasattr(maude, 'Hook'):
28
- usermsgs.print_warning('Version 0.5 of the maude package adds some useful features for this program.\n'
29
- 'Please update.')
30
-
31
- maude.RewriteGraph.getNrRewrites = lambda: 0
32
- maude.StrategyRewriteGraph.getNrRewrites = lambda: 0
33
- maude.ModelCheckResult.nrBuchiStates = 0
34
- maude.downModule = lambda term: term.symbol().getModule().downModule(term)
35
- maude.Sort.__le__ = lambda self, other: self.leq(other)
36
- maude.Term.__eq__ = lambda self, other: self.equal(other)
37
-
38
- if not hasattr(maude.StrategyRewriteGraph, 'getNrRealStates'):
39
- maude.StrategyRewriteGraph.getNrRealStates = maude.StrategyRewriteGraph.getNrStates
40
-
41
17
  if not hasattr(maude.Term, 'getVarName'):
42
18
  usermsgs.print_warning('Version 1.0 of the maude package adds some useful features for this program.\n'
43
19
  'Please update.')
umaudemc/counterprint.py CHANGED
@@ -78,17 +78,21 @@ def print_counterexample(graph, counter, printer_triple):
78
78
  next_index = lead_in[i+1] if i+1 < len(lead_in) else cycle[0]
79
79
 
80
80
  if graph.strategyControlled:
81
+ trans = graph.getTransition(index, next_index)
82
+
81
83
  printer.next_step_strat(
82
84
  sformat(graph, index),
83
85
  graph.getStateStrategy(index),
84
- eformat(graph, index, next_index),
86
+ eformat(trans),
85
87
  sformat(graph, next_index),
86
88
  first_index=index,
87
89
  second_index=next_index)
88
90
  else:
91
+ rule = graph.getRule(index, next_index)
92
+
89
93
  printer.next_step(
90
94
  sformat(graph, index),
91
- eformat(graph, index, next_index),
95
+ eformat(rule),
92
96
  sformat(graph, next_index),
93
97
  first_index=index,
94
98
  second_index=next_index)
@@ -103,17 +107,21 @@ def print_counterexample(graph, counter, printer_triple):
103
107
  next_index = cycle[i+1] if i+1 < len(cycle) else cycle[0]
104
108
 
105
109
  if graph.strategyControlled:
110
+ trans = graph.getTransition(index, next_index)
111
+
106
112
  printer.next_step_strat(
107
113
  sformat(graph, index),
108
114
  graph.getStateStrategy(index),
109
- eformat(graph, index, next_index),
115
+ eformat(trans),
110
116
  sformat(graph, next_index),
111
117
  first_index=index,
112
118
  second_index=next_index)
113
119
  else:
120
+ rule = graph.getRule(index, next_index)
121
+
114
122
  printer.next_step(
115
123
  sformat(graph, index),
116
- eformat(graph, index, next_index),
124
+ eformat(rule),
117
125
  sformat(graph, next_index),
118
126
  first_index=index,
119
127
  second_index=next_index)
umaudemc/data/smcgraph.js CHANGED
@@ -63,6 +63,9 @@ function showPopup(state, nr)
63
63
 
64
64
  function transitionText(transition)
65
65
  {
66
+ if (!transition)
67
+ return '';
68
+
66
69
  switch (transition.type)
67
70
  {
68
71
  case 0 : return 'idle' ; break
umaudemc/data/smcview.js CHANGED
@@ -38,13 +38,11 @@ function browseDir(dir)
38
38
  }
39
39
  }
40
40
 
41
- var question = new FormData()
42
-
43
- question.append('question', 'ls')
44
- question.append('url', dir)
41
+ var question = {question: 'ls', url: dir}
45
42
 
46
43
  request.open('post', 'ask')
47
- request.send(question)
44
+ request.setRequestHeader('Content-Type', 'application/json')
45
+ request.send(JSON.stringify(question))
48
46
  }
49
47
 
50
48
  function openFile(file)
@@ -57,6 +55,23 @@ function openFile(file)
57
55
  loadSourceModules(file)
58
56
  }
59
57
 
58
+ function loadSourceNative()
59
+ {
60
+ const request = new XMLHttpRequest()
61
+
62
+ request.onreadystatechange = function()
63
+ {
64
+ if (this.readyState == XMLHttpRequest.DONE && this.status == 200)
65
+ {
66
+ console.log(this.responseText)
67
+ openFile(this.responseText)
68
+ }
69
+ }
70
+
71
+ request.open('get', 'umaudemc://open/')
72
+ request.send()
73
+ }
74
+
60
75
  function incompletePassign()
61
76
  {
62
77
  switch (document.getElementById('pmethod').value) {
@@ -193,11 +208,10 @@ function loadSourceModules(file)
193
208
  // Discard modules from previous files
194
209
  smodule.options.length = 0
195
210
 
196
- var question = new FormData()
197
- question.append('question', 'sourceinfo')
198
- question.append('url', file)
211
+ var question = {question: 'sourceinfo', url: file}
199
212
  request.open('post', 'ask')
200
- request.send(question)
213
+ request.setRequestHeader('Content-Type', 'application/json')
214
+ request.send(JSON.stringify(question))
201
215
  }
202
216
 
203
217
  function addPropToFormula(prop)
@@ -318,11 +332,11 @@ function loadModule()
318
332
 
319
333
  description.innerText = 'Please select a Maude file and a Maude module defining the system and properties specification.'
320
334
 
321
- var question = new FormData()
322
- question.append('question', 'modinfo')
323
- question.append('mod', currentModule)
335
+ var question = {question: 'modinfo', mod: currentModule}
336
+
324
337
  request.open('post', 'ask')
325
- request.send(question)
338
+ request.setRequestHeader('Content-Type', 'application/json')
339
+ request.send(JSON.stringify(question))
326
340
  }
327
341
 
328
342
  function modelcheck()
@@ -356,14 +370,14 @@ function modelcheck()
356
370
  }
357
371
  }
358
372
 
359
- var question = new FormData()
360
-
361
- question.append('question', 'modelcheck')
362
- question.append('mod', document.getElementById('module').value)
363
- question.append('initial', document.getElementById('initial').value)
364
- question.append('formula', document.getElementById('formula').value)
365
- question.append('strategy', document.getElementById('strategy').value)
366
- question.append('opaques', document.getElementById('opaques').value)
373
+ const question = {
374
+ question: 'modelcheck',
375
+ mod: document.getElementById('module').value,
376
+ initial: document.getElementById('initial').value,
377
+ formula: document.getElementById('formula').value,
378
+ strategy: document.getElementById('strategy').value,
379
+ opaques: document.getElementById('opaques').value
380
+ }
367
381
 
368
382
  // Quantitative model checking stuff
369
383
  if (document.getElementById('command').value == 'qt')
@@ -375,7 +389,8 @@ function modelcheck()
375
389
  }
376
390
 
377
391
  request.open('post', 'ask')
378
- request.send(question)
392
+ request.setRequestHeader('Content-Type', 'application/json')
393
+ request.send(JSON.stringify(question))
379
394
  }
380
395
 
381
396
  function escapeHTMLChars(text) {
@@ -460,17 +475,15 @@ function waitModelChecker(mcref) {
460
475
  // Disable input until model checking has finished
461
476
  disableInput(true)
462
477
 
463
- var question = new FormData()
478
+ const question = {question: 'wait', mcref: mcref}
464
479
 
465
- question.append('question', 'wait')
466
- question.append('mcref', mcref)
467
480
  request.open('post', 'ask')
468
- request.send(question)
481
+ request.setRequestHeader('Content-Type', 'application/json')
482
+ request.send(JSON.stringify(question))
469
483
  }
470
484
 
471
485
  function cancelChecking() {
472
486
  const request = new XMLHttpRequest()
473
- const question = new FormData()
474
487
 
475
488
  request.onreadystatechange = function()
476
489
  {
@@ -486,9 +499,9 @@ function cancelChecking() {
486
499
  }
487
500
  }
488
501
 
489
- question.append('question', 'cancel')
490
502
  request.open('post', 'ask')
491
- request.send(question)
503
+ request.setRequestHeader('Content-Type', 'application/json')
504
+ request.send('{"question": "cancel"}')
492
505
  }
493
506
 
494
507
  function closeResultDialog()