pg-verify 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +1 -1
- data/data/project-template/README.md +81 -0
- data/doc/examples/vending_machine/checkpoint_1.rb +29 -0
- data/doc/examples/vending_machine/checkpoint_2.rb +47 -0
- data/doc/examples/vending_machine/checkpoint_3.rb +68 -0
- data/doc/examples/vending_machine/checkpoint_4.rb +202 -0
- data/integration_tests/ruby_dsl/001_states.rb +2 -1
- data/integration_tests/ruby_dsl/002_transitions.rb +2 -1
- data/integration_tests/ruby_dsl/017_ctl_specifications.rb +19 -0
- data/integration_tests/ruby_dsl/018_non_atomic_hazard.rb +17 -0
- data/integration_tests/ruby_dsl/019_multiple_actions.rb +21 -0
- data/integration_tests/ruby_dsl/020_vending_machine.rb +188 -0
- data/lib/pg-verify/cli/cli.rb +80 -24
- data/lib/pg-verify/cli/cli_utils.rb +61 -0
- data/lib/pg-verify/interpret/component_context.rb +1 -1
- data/lib/pg-verify/interpret/interpret.rb +1 -1
- data/lib/pg-verify/interpret/pg_script.rb +1 -0
- data/lib/pg-verify/model/parsed_expression.rb +10 -5
- data/lib/pg-verify/model/simulation/trace.rb +15 -4
- data/lib/pg-verify/model/validation/errors.rb +21 -2
- data/lib/pg-verify/nusmv/runner.rb +69 -17
- data/lib/pg-verify/puml/puml.rb +1 -0
- data/lib/pg-verify/puml/runner.rb +0 -0
- data/lib/pg-verify/transform/hash_transformation.rb +46 -14
- data/lib/pg-verify/transform/nusmv_transformation.rb +4 -3
- data/lib/pg-verify/transform/puml_transformation.rb +27 -8
- data/lib/pg-verify/version.rb +1 -1
- data/vscript.rb +64 -0
- metadata +13 -2
@@ -5,9 +5,17 @@ module PgVerify
|
|
5
5
|
class Runner
|
6
6
|
|
7
7
|
def run_specs(program_graph)
|
8
|
-
|
9
|
-
|
8
|
+
transformer = Transform::NuSmvTransformation.new
|
9
|
+
nusmv_s = transformer.transform_graph(program_graph, include_specs: false)
|
10
|
+
commands = [ "go" ]
|
10
11
|
specs = program_graph.specification.flatten()
|
12
|
+
transform_map = specs.each { |spec|
|
13
|
+
transformed_spec_expr = transformer.transform_expression(spec.expression, program_graph.all_variables)
|
14
|
+
cmd = { ltl: "check_ltlspec", ctl: "check_ctlspec" }[spec.expression.predict_type]
|
15
|
+
commands << "#{cmd} -p \"#{transformed_spec_expr}\""
|
16
|
+
}
|
17
|
+
output = eval_nusmv(nusmv_s, commands: commands)
|
18
|
+
|
11
19
|
return parse_spec_results(program_graph, specs, output)
|
12
20
|
end
|
13
21
|
|
@@ -20,8 +28,8 @@ module PgVerify
|
|
20
28
|
nusmv_output.split("\n").each { |line|
|
21
29
|
result = line[/-- specification .* is (true|false)/, 1]
|
22
30
|
if !result.nil?
|
23
|
-
blocks << current_block unless current_block.nil?
|
24
|
-
current_block = block.new(result == "true", [])
|
31
|
+
blocks << current_block unless current_block.nil? # Complete the last block
|
32
|
+
current_block = block.new(result == "true", []) # Start a new block
|
25
33
|
next
|
26
34
|
end
|
27
35
|
current_block.lines << line unless current_block.nil?
|
@@ -41,10 +49,7 @@ module PgVerify
|
|
41
49
|
# variable to the value of that variable in that state
|
42
50
|
def run_simulation(program_graph, steps, random: false)
|
43
51
|
commands = []
|
44
|
-
commands << "
|
45
|
-
commands << "flatten_hierarchy"
|
46
|
-
commands << "encode_variables"
|
47
|
-
commands << "build_model"
|
52
|
+
commands << "go"
|
48
53
|
commands << "pick_state #{random ? '-r' : ''}"
|
49
54
|
commands << "simulate -k #{steps.to_s.to_i} -v #{random ? '-r' : ''}"
|
50
55
|
commands << "quit"
|
@@ -53,12 +58,48 @@ module PgVerify
|
|
53
58
|
return parse_trace(program_graph, output)
|
54
59
|
end
|
55
60
|
|
61
|
+
def run_check!(program_graph)
|
62
|
+
deadlock_state = run_check(program_graph)
|
63
|
+
return if deadlock_state.nil?
|
64
|
+
raise Model::Validation::DeadlockInFSMError.new(program_graph, deadlock_state)
|
65
|
+
end
|
66
|
+
|
67
|
+
def run_check(program_graph)
|
68
|
+
commands = [ "go", "check_fsm", "quit" ]
|
69
|
+
nusmv_s = Transform::NuSmvTransformation.new.transform_graph(program_graph, include_specs: false)
|
70
|
+
output = eval_nusmv(nusmv_s, commands: commands)
|
71
|
+
|
72
|
+
# Return "ok" if the FSM has no deadlocks
|
73
|
+
return nil if output.include?("The transition relation is total: No deadlock state exists")
|
74
|
+
|
75
|
+
# Otherwise compute and return the deadlock state
|
76
|
+
lines = output.split("\n").drop_while { |str|
|
77
|
+
!(str.start_with?("A deadlock state is:") || str.start_with?("successors is:"))
|
78
|
+
}
|
79
|
+
lines = lines[1, lines.length - 1]
|
80
|
+
|
81
|
+
var_state = {}
|
82
|
+
lines.each { |line|
|
83
|
+
key, val = parse_var_assignment_in_trace(line)
|
84
|
+
next if key.nil? || val.nil?
|
85
|
+
var_state[key] = val
|
86
|
+
}
|
87
|
+
|
88
|
+
return var_state
|
89
|
+
end
|
90
|
+
|
56
91
|
def parse_trace(program_graph, nusmv_output)
|
57
92
|
var_states, current_var_state = [], nil
|
58
93
|
|
59
94
|
loop_index = -1
|
60
95
|
|
61
96
|
nusmv_output.split("\n").each { |line|
|
97
|
+
# Mark a loop for the following state
|
98
|
+
if line.include?("Loop starts here")
|
99
|
+
loop_index = var_states.length
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
62
103
|
# Wait for heading of new state
|
63
104
|
if line.match(/\s*-> State: .+ <-/)
|
64
105
|
# Complete and store the old state if any
|
@@ -76,17 +117,28 @@ module PgVerify
|
|
76
117
|
# Skip lines before the first state
|
77
118
|
next if current_var_state.nil?
|
78
119
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
key_val = line.split("=").map(&:strip)
|
85
|
-
key = key_val[0].gsub("v.V_", "").to_sym
|
86
|
-
val = key_val[1].gsub("L_", "")
|
120
|
+
# Parse the variable state
|
121
|
+
key, val = parse_var_assignment_in_trace(line)
|
122
|
+
next if key.nil? || val.nil?
|
87
123
|
current_var_state[key] = val
|
88
124
|
}
|
89
|
-
|
125
|
+
# Finish up
|
126
|
+
unless current_var_state.nil?
|
127
|
+
missing_keys = var_states.empty? ? [] : var_states[-1].keys - current_var_state.keys
|
128
|
+
missing_keys.each { |key|
|
129
|
+
current_var_state[key] = var_states[-1][key]
|
130
|
+
}
|
131
|
+
var_states << current_var_state
|
132
|
+
end
|
133
|
+
return Model::Trace.new(program_graph, var_states, loop_index: loop_index)
|
134
|
+
end
|
135
|
+
|
136
|
+
def parse_var_assignment_in_trace(line)
|
137
|
+
return nil, nil unless line.include?("=")
|
138
|
+
key_val = line.split("=").map(&:strip)
|
139
|
+
key = key_val[0].gsub("v.V_", "").to_sym
|
140
|
+
val = key_val[1].gsub("L_", "")
|
141
|
+
return key, val
|
90
142
|
end
|
91
143
|
|
92
144
|
def eval_nusmv(nusmv_string, commands: [])
|
data/lib/pg-verify/puml/puml.rb
CHANGED
@@ -15,6 +15,7 @@ module PgVerify
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.convert_file(in_path, out_path)
|
18
|
+
# CALL WITH java -Djava.awt.headless=true -jar addon/plantuml-1.2023.13.jar --help
|
18
19
|
# TODO: The PlantUML jar switches focus to the desktop is if it would
|
19
20
|
# attempt to open a window each time it is invoked.
|
20
21
|
end
|
File without changes
|
@@ -4,16 +4,24 @@ module PgVerify
|
|
4
4
|
class HashTransformation
|
5
5
|
|
6
6
|
def transform_graph(graph)
|
7
|
-
|
8
|
-
|
9
|
-
}
|
7
|
+
components = graph.components.map { |c| transform_component(graph, c) }
|
8
|
+
hazards = graph.hazards.map { |h| transform_hazard(h) }
|
9
|
+
sub_hash = {}
|
10
|
+
sub_hash["components"] = components
|
11
|
+
sub_hash["hazards"] = hazards unless hazards.empty?
|
12
|
+
sub_hash["specification"] = transform_specification(graph.specification)
|
13
|
+
return { graph.name.to_s => sub_hash }
|
10
14
|
end
|
11
15
|
|
12
16
|
def parse_graph(hash)
|
13
17
|
name = hash.keys.first.to_sym
|
14
18
|
graph = Model::Graph.new(name)
|
15
|
-
components = hash[hash.keys.first].map { |c| parse_component(graph, c) }
|
19
|
+
components = hash[hash.keys.first]["components"].map { |c| parse_component(graph, c) }
|
20
|
+
hazards = hash[hash.keys.first]["hazards"]&.map { |h| parse_hazard(h) } || []
|
21
|
+
specification = parse_specification(hash[hash.keys.first]["specification"])
|
16
22
|
graph.components = components
|
23
|
+
graph.hazards = hazards
|
24
|
+
graph.specification = specification
|
17
25
|
return graph
|
18
26
|
end
|
19
27
|
|
@@ -22,6 +30,7 @@ module PgVerify
|
|
22
30
|
return { component.name.to_s => {
|
23
31
|
"states" => component.states.map(&:to_s),
|
24
32
|
"variables" => variables.map { |v| transform_variable(v) },
|
33
|
+
"init" => transform_expression(component.init_expression),
|
25
34
|
"transitions" => component.transitions.map { |t| transform_transition(t) },
|
26
35
|
"represents_fault" => component.represents_fault
|
27
36
|
}}
|
@@ -31,13 +40,14 @@ module PgVerify
|
|
31
40
|
name = hash.keys.first
|
32
41
|
states = hash[name]["states"].map(&:to_sym)
|
33
42
|
variables = hash[name]["variables"].map { |v| parse_variable(name, v) }
|
43
|
+
init_expression = parse_expression(hash[name]["init"])
|
34
44
|
transitions = hash[name]["transitions"].map { |t| parse_transition(t) }
|
35
45
|
represents_fault = hash[name]["represents_fault"]
|
36
46
|
|
37
47
|
graph.variables += variables
|
38
48
|
|
39
49
|
return Model::Component.new(name: name.to_sym, states: states,
|
40
|
-
transitions: transitions, represents_fault: represents_fault)
|
50
|
+
transitions: transitions, represents_fault: represents_fault, init_expression: init_expression)
|
41
51
|
end
|
42
52
|
|
43
53
|
def transform_variable(variable)
|
@@ -49,7 +59,7 @@ module PgVerify
|
|
49
59
|
|
50
60
|
def parse_variable(owner_name, hash)
|
51
61
|
name = hash.keys.first
|
52
|
-
range = hash[name]["range"]
|
62
|
+
range = parse_variable_range(hash[name]["range"])
|
53
63
|
init_expression = parse_expression(hash[name]["init"])
|
54
64
|
return Model::Variable.new(name.to_sym, range, owner_name.to_sym, nil, init: init_expression)
|
55
65
|
end
|
@@ -60,9 +70,10 @@ module PgVerify
|
|
60
70
|
end
|
61
71
|
|
62
72
|
def parse_variable_range(range)
|
63
|
-
|
73
|
+
# Matches ranges like 1..12 or -1..23
|
74
|
+
if range.is_a?(String) && range.match(/\A\-?\d+\.\.\-?\d+\z/)
|
64
75
|
first, last = range.split("..")[0], range.split("..")[-1]
|
65
|
-
return Range.new(first, last)
|
76
|
+
return Range.new(first.to_i, last.to_i)
|
66
77
|
end
|
67
78
|
return range
|
68
79
|
end
|
@@ -85,20 +96,41 @@ module PgVerify
|
|
85
96
|
def transform_transition(transition)
|
86
97
|
name = "#{transition.src_state} -> #{transition.tgt_state}"
|
87
98
|
return { name => {
|
88
|
-
"precon" => transition.precon
|
89
|
-
"guard" => transition.guard
|
90
|
-
"action" => transition.action
|
99
|
+
"precon" => transform_expression(transition.precon),
|
100
|
+
"guard" => transform_expression(transition.guard),
|
101
|
+
"action" => transform_expression(transition.action),
|
91
102
|
}}
|
92
103
|
end
|
93
104
|
|
94
105
|
def parse_transition(hash)
|
95
106
|
src_state, tgt_state = hash.keys.first.split("->").map(&:strip).map(&:to_sym)
|
96
|
-
precon = hash.values.first["precon"]
|
97
|
-
guard = hash.values.first["guard"]
|
98
|
-
action = hash.values.first["action"]
|
107
|
+
precon = parse_expression(hash.values.first["precon"])
|
108
|
+
guard = parse_expression(hash.values.first["guard"] )
|
109
|
+
action = parse_expression(hash.values.first["action"])
|
99
110
|
return Model::Transition.new(src_state, tgt_state, precon: precon, guard: guard, action: action)
|
100
111
|
end
|
101
112
|
|
113
|
+
def transform_hazard(hazard)
|
114
|
+
return { "label" => hazard.text, "expression" => hazard.expression }
|
115
|
+
end
|
116
|
+
|
117
|
+
def parse_hazard(hash)
|
118
|
+
return Model::Hazard.new(hash["label"], hash["expression"])
|
119
|
+
end
|
120
|
+
|
121
|
+
def transform_specification(specification)
|
122
|
+
return specification.flatten().map { |spec|
|
123
|
+
{ "label" => spec.text.strip, "expression" => transform_expression(spec.expression) }
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def parse_specification(array)
|
128
|
+
specs = array.map { |hash|
|
129
|
+
Model::Spec.new(hash["label"], parse_expression(hash["expression"]), nil)
|
130
|
+
}
|
131
|
+
return Model::Specification.new([Model::SpecSet.wrap(specs)])
|
132
|
+
end
|
133
|
+
|
102
134
|
end
|
103
135
|
end
|
104
136
|
end
|
@@ -3,7 +3,7 @@ module PgVerify
|
|
3
3
|
|
4
4
|
class NuSmvTransformation
|
5
5
|
|
6
|
-
def transform_graph(program_graph)
|
6
|
+
def transform_graph(program_graph, include_specs: true)
|
7
7
|
variables = program_graph.all_variables
|
8
8
|
components = program_graph.components
|
9
9
|
|
@@ -11,7 +11,7 @@ module PgVerify
|
|
11
11
|
cmp_s = transform_components(components, variables)
|
12
12
|
main_s = transform_main_module(components)
|
13
13
|
|
14
|
-
specs = transform_specification(program_graph.specification, variables)
|
14
|
+
specs = transform_specification(program_graph.specification, variables) if include_specs
|
15
15
|
|
16
16
|
return "#{var_s}\n\n#{cmp_s}\n\n#{main_s}\n\n#{specs}\n"
|
17
17
|
end
|
@@ -251,7 +251,8 @@ module PgVerify
|
|
251
251
|
def transform_spec(spec, varset)
|
252
252
|
expression_s = "-- #{spec.text}\n"
|
253
253
|
expression_s += "-- Defined in: #{spec.source_location.to_s}\n"
|
254
|
-
|
254
|
+
keyword = { ltl: "LTLSPEC", ctl: "CTLSPEC" }[spec.expression.predict_type]
|
255
|
+
expression_s += keyword + " " + transform_expression(spec.expression, varset)
|
255
256
|
return expression_s
|
256
257
|
end
|
257
258
|
|
@@ -5,13 +5,25 @@ module PgVerify
|
|
5
5
|
|
6
6
|
class PumlTransformation
|
7
7
|
|
8
|
+
attr_accessor :render_labels
|
9
|
+
attr_accessor :render_precons
|
10
|
+
attr_accessor :render_guards
|
11
|
+
attr_accessor :render_actions
|
12
|
+
|
13
|
+
def initialize(render_options = {})
|
14
|
+
@render_labels = render_options[:render_labels].nil? ? true : render_options[:render_labels]
|
15
|
+
@render_precons = render_options[:render_precons].nil? ? true : render_options[:render_precons]
|
16
|
+
@render_guards = render_options[:render_guards].nil? ? true : render_options[:render_guards]
|
17
|
+
@render_actions = render_options[:render_actions].nil? ? true : render_options[:render_actions]
|
18
|
+
end
|
19
|
+
|
8
20
|
def transform_graph(graph, variable_state: nil, only: nil)
|
9
21
|
|
10
22
|
components = graph.components
|
11
23
|
components = components.select { |c| only.map(&:to_s).include?(c.name.to_s) } unless only.nil?
|
12
24
|
|
13
25
|
parts = []
|
14
|
-
parts << components.map { |c| transform_component(graph, c) }.join("\n\n")
|
26
|
+
parts << components.map { |c| transform_component(graph, c, variable_state) }.join("\n\n")
|
15
27
|
parts << transform_variable_state(graph, variable_state) unless variable_state.nil?
|
16
28
|
parts = parts.compact.join("\n\n")
|
17
29
|
return "@startuml Programmgraph\n#{parts}\n@enduml\n"
|
@@ -25,14 +37,14 @@ module PgVerify
|
|
25
37
|
}.join("\n")
|
26
38
|
end
|
27
39
|
|
28
|
-
def transform_component(graph, component)
|
40
|
+
def transform_component(graph, component, variable_state)
|
29
41
|
# Transform component states
|
30
42
|
states_s = component.states.map { |s| transform_state(component, s) }.join("\n")
|
31
43
|
# Transform component transitions
|
32
44
|
trans_s = component.transitions.map { |t| transform_transition(component, t) }.join("\n")
|
33
45
|
# Transform component variables
|
34
46
|
vars = graph.variables.select_by_owner(component.name)
|
35
|
-
vars_s = transform_variables(component, vars)
|
47
|
+
vars_s = transform_variables(component, vars, variable_state)
|
36
48
|
# Transform the initial state
|
37
49
|
initial_s = transform_initial(graph, component)
|
38
50
|
|
@@ -59,10 +71,14 @@ module PgVerify
|
|
59
71
|
end
|
60
72
|
|
61
73
|
def transform_transition(component, transition)
|
62
|
-
|
63
|
-
|
74
|
+
precon = @render_precons ? transition.precon : nil
|
75
|
+
guard = @render_guards ? transition.guard : nil
|
76
|
+
action = @render_actions ? transition.action : nil
|
64
77
|
|
78
|
+
label = [ precon, guard ].map(&:to_s).reject(&:empty?).join(" && ")
|
79
|
+
label += " / " + action.to_s unless action.nil?
|
65
80
|
label = ": #{label}" unless label.strip.empty?
|
81
|
+
label = "" unless @render_labels
|
66
82
|
return "#{component.name}_#{transition.src_state} --> #{component.name}_#{transition.tgt_state} #{label}"
|
67
83
|
end
|
68
84
|
|
@@ -70,9 +86,12 @@ module PgVerify
|
|
70
86
|
str.split("\n").map { |s| "\t#{s}" }.join("\n")
|
71
87
|
end
|
72
88
|
|
73
|
-
def transform_variables(component, variables)
|
74
|
-
return nil if variables.empty?
|
75
|
-
body = variables.map { |
|
89
|
+
def transform_variables(component, variables, variable_state)
|
90
|
+
return nil if variables.empty?
|
91
|
+
body = variables.map { |var|
|
92
|
+
value = variable_state.nil? ? transform_range(var.range) : variable_state[var.name]
|
93
|
+
"#{var.name} => #{value}"
|
94
|
+
}.join("\n")
|
76
95
|
return "map #{component.name}Variables {\n#{body}\n}"
|
77
96
|
end
|
78
97
|
|
data/lib/pg-verify/version.rb
CHANGED
data/vscript.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
task :gen_examples do
|
3
|
+
files = Dir["integration_tests/ruby_dsl/*.rb"].select(&:file?)
|
4
|
+
|
5
|
+
target_dir = "examples"
|
6
|
+
FileUtils.rm_rf(target_dir); FileUtils.mkdir(target_dir)
|
7
|
+
|
8
|
+
files.each { |file|
|
9
|
+
json = x "./devpg show json --script #{file}", verbose: false
|
10
|
+
yaml = x "./devpg show yaml --script #{file}", verbose: false
|
11
|
+
json_file = File.join(target_dir, File.basename(file, '.rb') + ".json")
|
12
|
+
yaml_file = File.join(target_dir, File.basename(file, '.rb') + ".yaml")
|
13
|
+
FileUtils.cp(file, File.join(target_dir, File.basename(file)))
|
14
|
+
File.write(json_file, json)
|
15
|
+
File.write(yaml_file, yaml)
|
16
|
+
|
17
|
+
x "tar -czf examples.tar.gz examples/"
|
18
|
+
}
|
19
|
+
FileUtils.rm_rf(target_dir)
|
20
|
+
|
21
|
+
done "Generated examples.tar.gz"
|
22
|
+
end
|
23
|
+
|
24
|
+
task :integration_test do
|
25
|
+
|
26
|
+
work_dir = ".pg-work"
|
27
|
+
FileUtils.rm_rf(work_dir); FileUtils.mkdir(work_dir)
|
28
|
+
|
29
|
+
test_files = Dir["integration_tests/ruby_dsl/*.rb"].sort.select(&:file?)
|
30
|
+
|
31
|
+
|
32
|
+
# Create json files for all tests
|
33
|
+
test_files.each { |source|
|
34
|
+
log "JSON #{File.basename(source)}"
|
35
|
+
target = File.join(work_dir, File.basename(source, '.rb') + ".json")
|
36
|
+
content = x "./devpg show json --script #{source}", verbose: false
|
37
|
+
File.write(target, content)
|
38
|
+
}
|
39
|
+
|
40
|
+
# Create json files for all tests
|
41
|
+
test_files.each { |source|
|
42
|
+
log "YAML #{File.basename(source)}"
|
43
|
+
target = File.join(work_dir, File.basename(source, '.rb') + ".yaml")
|
44
|
+
content = x "./devpg show yaml --script #{source}", verbose: false
|
45
|
+
File.write(target, content)
|
46
|
+
}
|
47
|
+
|
48
|
+
# Run tests for all files
|
49
|
+
test_files.each { |source|
|
50
|
+
args = {
|
51
|
+
"script" => source,
|
52
|
+
"json-file" => File.join(work_dir, File.basename(source, '.rb') + ".json"),
|
53
|
+
}
|
54
|
+
commands = [ "show puml", "test", "dcca", "show png", "simulate" ]
|
55
|
+
args.each { |argument, file|
|
56
|
+
commands.each { |command|
|
57
|
+
log "pgv #{command} #{argument} | #{File.basename(file)}"
|
58
|
+
x "./devpg #{command} --#{argument} #{file}", verbose: false
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
done "Great success!"
|
64
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg-verify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arian Weber
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -92,6 +92,10 @@ files:
|
|
92
92
|
- devpg
|
93
93
|
- doc/examples/railroad_crossing.rb
|
94
94
|
- doc/examples/train-tree.rb
|
95
|
+
- doc/examples/vending_machine/checkpoint_1.rb
|
96
|
+
- doc/examples/vending_machine/checkpoint_2.rb
|
97
|
+
- doc/examples/vending_machine/checkpoint_3.rb
|
98
|
+
- doc/examples/vending_machine/checkpoint_4.rb
|
95
99
|
- doc/examples/weidezaun.rb
|
96
100
|
- doc/examples/weidezaun.txt
|
97
101
|
- doc/expose/definition.png
|
@@ -115,8 +119,13 @@ files:
|
|
115
119
|
- integration_tests/ruby_dsl/014_tau_transitions.rb
|
116
120
|
- integration_tests/ruby_dsl/015_basic_dcca.rb
|
117
121
|
- integration_tests/ruby_dsl/016_pressure_tank.rb
|
122
|
+
- integration_tests/ruby_dsl/017_ctl_specifications.rb
|
123
|
+
- integration_tests/ruby_dsl/018_non_atomic_hazard.rb
|
124
|
+
- integration_tests/ruby_dsl/019_multiple_actions.rb
|
125
|
+
- integration_tests/ruby_dsl/020_vending_machine.rb
|
118
126
|
- lib/pg-verify.rb
|
119
127
|
- lib/pg-verify/cli/cli.rb
|
128
|
+
- lib/pg-verify/cli/cli_utils.rb
|
120
129
|
- lib/pg-verify/core/cmd_runner.rb
|
121
130
|
- lib/pg-verify/core/core.rb
|
122
131
|
- lib/pg-verify/core/extensions/array_extensions.rb
|
@@ -170,6 +179,7 @@ files:
|
|
170
179
|
- lib/pg-verify/nusmv/nusmv.rb
|
171
180
|
- lib/pg-verify/nusmv/runner.rb
|
172
181
|
- lib/pg-verify/puml/puml.rb
|
182
|
+
- lib/pg-verify/puml/runner.rb
|
173
183
|
- lib/pg-verify/shell/loading/line_animation.rb
|
174
184
|
- lib/pg-verify/shell/loading/loading_animation.rb
|
175
185
|
- lib/pg-verify/shell/loading/loading_prompt.rb
|
@@ -185,6 +195,7 @@ files:
|
|
185
195
|
- lib/pg-verify/version.rb
|
186
196
|
- pg-verify.gemspec
|
187
197
|
- sig/pg-verify.rbs
|
198
|
+
- vscript.rb
|
188
199
|
homepage: https://github.com/ArianWeber/pg-verify
|
189
200
|
licenses: []
|
190
201
|
metadata:
|