tla-parser-s 0.1.0
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 +7 -0
- data/README.md +75 -0
- data/VERSION +1 -0
- data/bin/tla-resolver.rb +7 -0
- data/lib/cli/cli.rb +90 -0
- data/lib/parser/exception.rb +6 -0
- data/lib/parser/lvalue.rb +63 -0
- data/lib/parser/parser.rb +129 -0
- data/lib/parser/parser_nodes.rb +1063 -0
- data/lib/parser/parser_sexp.treetop +442 -0
- data/lib/semantics/context.rb +355 -0
- data/lib/semantics/exception.rb +13 -0
- data/lib/semantics/resolver.rb +327 -0
- data/lib/semantics/symbol_table.rb +139 -0
- data/lib/tla-parser-s.rb +15 -0
- data/lib/utils/logger.rb +80 -0
- data/lib/utils/syntax_node.rb +73 -0
- data/lib/utils/version.rb +13 -0
- data/spec/fixtures/callables1.tla +64 -0
- data/spec/fixtures/directives.tla +7 -0
- data/spec/fixtures/resolver1/comments.tla +1 -0
- data/spec/fixtures/resolver1/directives.cfg +6 -0
- data/spec/fixtures/resolver1/directives.tla +12 -0
- data/spec/fixtures/resolver1/empty.tla +0 -0
- data/spec/fixtures/resolver1/macro1.tla +3 -0
- data/spec/fixtures/resolver1/macro2.tla +3 -0
- data/spec/fixtures/resolver1/op1.tla +3 -0
- data/spec/fixtures/resolver1/op2.tla +3 -0
- data/spec/fixtures/resolver1/proc1.tla +4 -0
- data/spec/fixtures/resolver1/proc2.tla +7 -0
- data/spec/fixtures/resolver1/proc3.tla +4 -0
- data/spec/fixtures/resolver1/proc4.tla +4 -0
- data/spec/fixtures/resolver1/proc4_hide.tla +4 -0
- data/spec/fixtures/resolver1/proc5.tla +4 -0
- data/spec/fixtures/resolver1/proc6.tla +4 -0
- data/spec/fixtures/resolver1/proc7.tla +4 -0
- data/spec/fixtures/resolver1/stmt_assert.tla +8 -0
- data/spec/fixtures/resolver1/stmt_assign.tla +6 -0
- data/spec/fixtures/resolver1/stmt_assign2.tla +6 -0
- data/spec/fixtures/resolver1/stmt_cond.tla +13 -0
- data/spec/fixtures/resolver1/stmt_either.tla +12 -0
- data/spec/fixtures/resolver1/stmt_print.tla +5 -0
- data/spec/fixtures/resolver1/var4.tla +1 -0
- data/spec/fixtures/resolver1/var5.tla +1 -0
- data/spec/fixtures/resolver1/var_choose_except.tla +2 -0
- data/spec/fixtures/resolver1/var_quantify.tla +4 -0
- data/spec/fixtures/resolver1/var_rec_except.tla +4 -0
- data/spec/fixtures/resolver1/var_rec_expr.tla +3 -0
- data/spec/fixtures/resolver1/var_record.tla +2 -0
- data/spec/fixtures/resolver1/var_seq.tla +1 -0
- data/spec/fixtures/resolver1/var_set.tla +1 -0
- data/spec/fixtures/resolver1/var_set_expr_map.tla +1 -0
- data/spec/fixtures/resolver1/var_x.tla +1 -0
- data/spec/fixtures/resolver1/variables.tla +4 -0
- data/spec/parser/parser_fixtures_spec.rb +117 -0
- data/spec/parser/parser_spec.rb +1649 -0
- data/spec/semantics/context_spec.rb +392 -0
- data/spec/semantics/resolver_spec.rb +364 -0
- data/spec/semantics/symbol_table_spec.rb +144 -0
- data/spec/spec_helper.rb +5 -0
- data/tla-parser-s.gemspec +41 -0
- metadata +153 -0
@@ -0,0 +1,392 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
describe TlaParserS::Context do
|
4
|
+
|
5
|
+
let ( :parser ) { TlaParserS::Parser.new }
|
6
|
+
let ( :context ) { described_class.new }
|
7
|
+
|
8
|
+
|
9
|
+
root_definitions = <<-EOS
|
10
|
+
A == 1
|
11
|
+
procedure proc() {}
|
12
|
+
macro mac(){}
|
13
|
+
EOS
|
14
|
+
|
15
|
+
let ( :snippets ) { parser.parse( root_definitions )}
|
16
|
+
let ( :initialContext ) { context.pushContext( snippets ) }
|
17
|
+
|
18
|
+
|
19
|
+
# ------------------------------------------------------------------
|
20
|
+
# resolve
|
21
|
+
|
22
|
+
describe "interface" do
|
23
|
+
|
24
|
+
it "#initContext" do
|
25
|
+
expect( context ).to respond_to( :initContext )
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
it "#addContext" do
|
30
|
+
expect( context ).to respond_to( :addContext )
|
31
|
+
end
|
32
|
+
|
33
|
+
it "#pushContext" do
|
34
|
+
expect( context ).to respond_to( :pushContext )
|
35
|
+
end
|
36
|
+
|
37
|
+
it "#resolveExpression" do
|
38
|
+
expect( context ).to respond_to( :resolveExpression )
|
39
|
+
end
|
40
|
+
|
41
|
+
it "#resolveDefines" do
|
42
|
+
expect( context ).to respond_to( :resolveDefine )
|
43
|
+
end
|
44
|
+
|
45
|
+
it "#currentContext" do
|
46
|
+
expect( context ).to respond_to( :currentContext )
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# ------------------------------------------------------------------
|
53
|
+
# resolve
|
54
|
+
describe "initSymbolTable" do
|
55
|
+
|
56
|
+
it "#they are valid" do
|
57
|
+
expect( snippets ).not_to eql( nil )
|
58
|
+
end
|
59
|
+
|
60
|
+
it "#they are valid" do
|
61
|
+
expect( initialContext.currentContext.keys() ).to eql( ["A", "proc", "mac" ] )
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# ------------------------------------------------------------------
|
68
|
+
# resolve
|
69
|
+
|
70
|
+
describe "resolveExpression" do
|
71
|
+
|
72
|
+
|
73
|
+
it "#fulle resolve output" do
|
74
|
+
|
75
|
+
expression = parser.parse( "A", :expression )
|
76
|
+
resolved = initialContext.resolveExpression( expression )
|
77
|
+
expect( resolved.first ).
|
78
|
+
to match(
|
79
|
+
{:symbol=>"A",
|
80
|
+
:resolved=> a_hash_including(
|
81
|
+
{:symbol_type=>"OperatorDef",
|
82
|
+
:context_type=>"Snippets",
|
83
|
+
:context=>"Snippets",
|
84
|
+
:symbol_name=>"A"}
|
85
|
+
)
|
86
|
+
})
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
[
|
92
|
+
{
|
93
|
+
:initialContextSnippets => [ "A == 1" ],
|
94
|
+
:expression => "A",
|
95
|
+
:desc => "Define constant operator",
|
96
|
+
:debug => false,
|
97
|
+
:expect_synopsis =>"Expression resoves to constant expression",
|
98
|
+
:expect => [ {"A" => "OperatorDef" }],
|
99
|
+
},
|
100
|
+
|
101
|
+
{
|
102
|
+
:initialContextSnippets => [ "macro A() {}" ],
|
103
|
+
:expression => "A + B",
|
104
|
+
:desc => "Define constant operator, one not resolved",
|
105
|
+
:debug => false,
|
106
|
+
:expect_synopsis =>"A-resolved, B-not resolved",
|
107
|
+
:expect => [ {"A" => "Macro" }, { "B" => nil } ],
|
108
|
+
},
|
109
|
+
|
110
|
+
{
|
111
|
+
:initialContextSnippets => [
|
112
|
+
"procedure A() {}",
|
113
|
+
"B==TRUE",
|
114
|
+
],
|
115
|
+
:expression => "A + B",
|
116
|
+
:desc => "Two level context",
|
117
|
+
:debug => false,
|
118
|
+
:expect_synopsis =>"A-resolved, B-resolved",
|
119
|
+
:expect => [ {"A" => "Procedure" }, { "B" => "OperatorDef" } ],
|
120
|
+
},
|
121
|
+
|
122
|
+
{
|
123
|
+
:initialContextSnippets => [
|
124
|
+
],
|
125
|
+
:expression => "TRUE",
|
126
|
+
:desc => "Expression 'TRUE'",
|
127
|
+
:debug => false,
|
128
|
+
:expect_synopsis =>"in global definitions",
|
129
|
+
:expect => [ {"TRUE" => nil } ],
|
130
|
+
},
|
131
|
+
|
132
|
+
|
133
|
+
].each_with_index do |testCase,i|
|
134
|
+
|
135
|
+
describe "#Case #{i}: #{testCase[:desc]}'" do
|
136
|
+
|
137
|
+
it "##{testCase[:expect_synopsis]}" do
|
138
|
+
|
139
|
+
initialContext = described_class.new
|
140
|
+
|
141
|
+
# reset symbol table in context
|
142
|
+
initialContext.initContext
|
143
|
+
|
144
|
+
# build context
|
145
|
+
testCase[:initialContextSnippets].each do |initialContextSnippet|
|
146
|
+
|
147
|
+
parsedSnippets = parser.parse( initialContextSnippet )
|
148
|
+
expect( parsedSnippets ).not_to eql( nil )
|
149
|
+
|
150
|
+
if ( testCase[:debug] )
|
151
|
+
puts "Snippets"
|
152
|
+
puts parsedSnippets.inspect
|
153
|
+
end
|
154
|
+
|
155
|
+
initialContext.pushContext( parsedSnippets )
|
156
|
+
end
|
157
|
+
|
158
|
+
# parse expression
|
159
|
+
expression = parser.parse( testCase[:expression], :expression )
|
160
|
+
if ( testCase[:debug] )
|
161
|
+
puts "Expression:"
|
162
|
+
puts expression.inspect
|
163
|
+
end
|
164
|
+
expect( expression ).not_to eql( nil )
|
165
|
+
|
166
|
+
# resolve in context
|
167
|
+
resolved = initialContext.resolveExpression( expression )
|
168
|
+
expect( resolved.map{ |r| { r[:symbol] => r[:resolved] ? r[:resolved][:symbol_type] : nil } } ).to eql( testCase[:expect] )
|
169
|
+
|
170
|
+
end # it
|
171
|
+
|
172
|
+
end # describe
|
173
|
+
|
174
|
+
end # each
|
175
|
+
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
# ------------------------------------------------------------------
|
181
|
+
# resolveDefine
|
182
|
+
|
183
|
+
describe "resolveDefine" do
|
184
|
+
|
185
|
+
context "return value" do
|
186
|
+
|
187
|
+
it "#full resolve output" do
|
188
|
+
|
189
|
+
baseContext = <<-EOS
|
190
|
+
procedure Be() {}
|
191
|
+
EOS
|
192
|
+
|
193
|
+
|
194
|
+
myContext = described_class.new
|
195
|
+
myContext.initContext
|
196
|
+
baseSnippets = parser.parse( baseContext )
|
197
|
+
myContext.pushContext( baseSnippets, "module2" )
|
198
|
+
|
199
|
+
statement = parser.parse( "procedure procci(){ call Be(); }", :procedure )
|
200
|
+
resolved = myContext.resolveDefine( statement )
|
201
|
+
expect( resolved ).
|
202
|
+
to match(
|
203
|
+
[
|
204
|
+
{:symbol=>"Be",
|
205
|
+
:resolved=>a_hash_including(
|
206
|
+
{:symbol_type=>"Procedure",
|
207
|
+
:context_type=>"Snippets",
|
208
|
+
:context=>"Snippets",
|
209
|
+
:module=>"module2",
|
210
|
+
:symbol_name=>"Be"})
|
211
|
+
}]
|
212
|
+
)
|
213
|
+
end
|
214
|
+
end # return value
|
215
|
+
|
216
|
+
describe "test cases" do
|
217
|
+
|
218
|
+
[
|
219
|
+
{
|
220
|
+
:initialContext => [
|
221
|
+
<<-EOS,
|
222
|
+
procedure proc1() {}
|
223
|
+
macro macro1() {}
|
224
|
+
op1 == TRUE
|
225
|
+
EOS
|
226
|
+
],
|
227
|
+
|
228
|
+
:callable => "procedure procci(){ call proc1(); macro1(); }",
|
229
|
+
:start => :procedure,
|
230
|
+
:desc => "Call proc, call macro",
|
231
|
+
:debug => false,
|
232
|
+
:expect_synopsis =>"Resolved in base context definitions ",
|
233
|
+
:expect => [{"proc1" => "Procedure:Snippets" }, { "macro1" => "Macro:Snippets" } ],
|
234
|
+
},
|
235
|
+
|
236
|
+
|
237
|
+
{
|
238
|
+
:initialContext => [
|
239
|
+
<<-EOS,
|
240
|
+
procedure proc1() {}
|
241
|
+
macro macro1() {}
|
242
|
+
op1 == TRUE
|
243
|
+
a = {}
|
244
|
+
EOS
|
245
|
+
],
|
246
|
+
|
247
|
+
:callable => "procedure procci(){ call proc1( a ); macro1(op1); }",
|
248
|
+
:start => :procedure,
|
249
|
+
:desc => "Actual paramters resolved",
|
250
|
+
:debug => false,
|
251
|
+
:expect_synopsis =>"in base context",
|
252
|
+
:expect => [{"proc1" => "Procedure:Snippets" },
|
253
|
+
{ "a" => "VariableDef:Snippets"},
|
254
|
+
{ "macro1" => "Macro:Snippets" },
|
255
|
+
{ "op1" => "OperatorDef:Snippets" }],
|
256
|
+
},
|
257
|
+
|
258
|
+
{
|
259
|
+
:initialContext => [
|
260
|
+
<<-EOS,
|
261
|
+
procedure proc1( a ) {}
|
262
|
+
macro macro1() {}
|
263
|
+
op1 == TRUE
|
264
|
+
EOS
|
265
|
+
],
|
266
|
+
|
267
|
+
:callable => "procedure procci( a ){ call proc1( a ); macro1(a); }",
|
268
|
+
:start => :procedure,
|
269
|
+
:desc => "Actual paramters resolved",
|
270
|
+
:debug => false,
|
271
|
+
:expect_synopsis =>"in formal parameter",
|
272
|
+
:expect => [{"proc1" => "Procedure:Snippets" }, { "a" => "Identifier:procci" },
|
273
|
+
{ "macro1" => "Macro:Snippets" }, { "a" => "Identifier:procci" }],
|
274
|
+
},
|
275
|
+
|
276
|
+
{
|
277
|
+
:initialContext => [
|
278
|
+
<<-EOS,
|
279
|
+
procedure proc1( a ) { }
|
280
|
+
macro macro1() {}
|
281
|
+
vari = 1
|
282
|
+
EOS
|
283
|
+
],
|
284
|
+
:callable => "procedure procci( a ){ macro1(a, vari, { a \\in Setti: a = vari } ); }",
|
285
|
+
:start => :procedure,
|
286
|
+
:desc => "Resolved",
|
287
|
+
:debug => false,
|
288
|
+
:expect_synopsis =>"2nd a in set generator",
|
289
|
+
:expect => [
|
290
|
+
{"macro1" => "Macro:Snippets" }, { "a" => "Identifier:procci" },
|
291
|
+
{ "vari" => "VariableDef:Snippets" }, { "a" => "SetExpression:Set-Setti"}, { "vari" => "VariableDef:Snippets" } ],
|
292
|
+
},
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
{
|
297
|
+
:initialContext => [
|
298
|
+
<<-EOS,
|
299
|
+
procedure proc1( a ) { }
|
300
|
+
macro macro1() {}
|
301
|
+
vari = 1
|
302
|
+
operattori == FALSE
|
303
|
+
EOS
|
304
|
+
],
|
305
|
+
:callable => "procedure procci( a ){ macro1(a, vari, \\A a \\in Joukko: a + FALSE ); }",
|
306
|
+
:start => :procedure,
|
307
|
+
:desc => "Resolve in procedure context",
|
308
|
+
:debug => false,
|
309
|
+
:expect_synopsis =>"2nd 'a' resolved as quantification parameter",
|
310
|
+
:expect => [
|
311
|
+
{"macro1"=>"Macro:Snippets"}, {"a"=>"Identifier:procci"}, {"vari"=>"VariableDef:Snippets"},
|
312
|
+
{ "Joukko" => nil},
|
313
|
+
{"a"=>"QuantifyExpression:Quantification-??"}, {"FALSE" => nil }, ]
|
314
|
+
},
|
315
|
+
|
316
|
+
{
|
317
|
+
:initialContext => [
|
318
|
+
<<-EOS,
|
319
|
+
macro macro1( a ) {}
|
320
|
+
macro macro2( a ) {}
|
321
|
+
v1 = 1
|
322
|
+
v2 = 2
|
323
|
+
EOS
|
324
|
+
],
|
325
|
+
:callable => "procedure proxy( a ){ macro1( a, v1 ); macro2( a, v2, v3 ); }",
|
326
|
+
:start => :procedure,
|
327
|
+
:desc => "Two macro calls in compound statement, v3 not resolved",
|
328
|
+
:debug => false,
|
329
|
+
:expect_synopsis =>"macro1 & macro2 calls resolved",
|
330
|
+
:expect => [
|
331
|
+
{"macro1" => "Macro:Snippets" }, { "a" => "Identifier:proxy" }, { "v1" => "VariableDef:Snippets" },
|
332
|
+
{"macro2" => "Macro:Snippets" }, { "a" => "Identifier:proxy" }, { "v2" => "VariableDef:Snippets" }, { "v3" => nil },
|
333
|
+
]
|
334
|
+
},
|
335
|
+
|
336
|
+
|
337
|
+
].each_with_index do |testCase,i|
|
338
|
+
|
339
|
+
describe "#Case #{i+1}: #{testCase[:desc]}'" do
|
340
|
+
|
341
|
+
it "##{testCase[:expect_synopsis]}" do
|
342
|
+
|
343
|
+
myContext = described_class.new
|
344
|
+
|
345
|
+
# reset symbol table in context
|
346
|
+
myContext.initContext
|
347
|
+
myContext.pushContext
|
348
|
+
|
349
|
+
# build context
|
350
|
+
testCase[:initialContext].each_with_index do |myContextSnippet,i|
|
351
|
+
|
352
|
+
parsedSnippets = parser.parse( myContextSnippet )
|
353
|
+
expect( parsedSnippets ).not_to eql( nil )
|
354
|
+
|
355
|
+
if ( testCase[:debug] )
|
356
|
+
puts "Snippets"
|
357
|
+
puts parsedSnippets.inspect
|
358
|
+
end
|
359
|
+
|
360
|
+
moduleName = "module-#{i+1}"
|
361
|
+
myContext.addContext( parsedSnippets, moduleName )
|
362
|
+
end
|
363
|
+
|
364
|
+
if ( testCase[:debug] )
|
365
|
+
puts "Context"
|
366
|
+
myContext.dumpContext
|
367
|
+
end
|
368
|
+
|
369
|
+
# parse callable
|
370
|
+
callable = parser.parse( testCase[:callable], testCase[:start] )
|
371
|
+
if ( testCase[:debug] )
|
372
|
+
puts "Callable:"
|
373
|
+
puts callable.inspect
|
374
|
+
end
|
375
|
+
expect( callable ).not_to eql( nil )
|
376
|
+
|
377
|
+
# resolve in context
|
378
|
+
resolved = myContext.resolveDefine( callable )
|
379
|
+
expect( resolved.map{ |r| { r[:symbol] => r[:resolved] ? r[:resolved][:symbol_type] + ':' + r[:resolved][:context] : nil } } ).to eql( testCase[:expect] )
|
380
|
+
|
381
|
+
end # it
|
382
|
+
|
383
|
+
end # describe
|
384
|
+
|
385
|
+
end #eac
|
386
|
+
|
387
|
+
end # testCases
|
388
|
+
|
389
|
+
end # resolveDefine
|
390
|
+
|
391
|
+
end
|
392
|
+
|
@@ -0,0 +1,364 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
describe TlaParserS::Resolver do
|
4
|
+
|
5
|
+
fixture1DirPath = "#{FIXTURE_ROOT}/resolver1/*"
|
6
|
+
entries = Dir.glob(fixture1DirPath).map { |fileName| File.new(fileName )}
|
7
|
+
|
8
|
+
let ( :resolver ) { described_class.new }
|
9
|
+
|
10
|
+
|
11
|
+
# ------------------------------------------------------------------
|
12
|
+
# resolve
|
13
|
+
|
14
|
+
describe "interface" do
|
15
|
+
|
16
|
+
describe "getters" do
|
17
|
+
|
18
|
+
it "#context" do
|
19
|
+
expect( resolver ).to respond_to( :context )
|
20
|
+
end
|
21
|
+
|
22
|
+
it "#parser" do
|
23
|
+
expect( resolver ).to respond_to( :parser )
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
describe "phases" do
|
30
|
+
|
31
|
+
it "#initContext" do
|
32
|
+
expect( resolver ).to respond_to( :initContext )
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
it "#initSnippets" do
|
37
|
+
expect( resolver ).to respond_to( :initSnippets )
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#resolveModules" do
|
41
|
+
expect( resolver ).to respond_to( :resolveModules )
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end # interface
|
47
|
+
|
48
|
+
|
49
|
+
# ------------------------------------------------------------------
|
50
|
+
# Fixture 1
|
51
|
+
|
52
|
+
describe "Fixture 'resolver1'" do
|
53
|
+
|
54
|
+
|
55
|
+
before :all do
|
56
|
+
@resolver = described_class.new.initSnippets( entries )
|
57
|
+
end
|
58
|
+
|
59
|
+
it "#fixture include some files" do
|
60
|
+
expect( entries.map{ |e| File.basename(e) } ).to include( "proc1.tla", "proc2.tla" )
|
61
|
+
end
|
62
|
+
|
63
|
+
# ------------------------------------------------------------------
|
64
|
+
# resolveModules (after initSnippets)
|
65
|
+
|
66
|
+
context "resolveModules successfull" do
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
%w( proc1 proc2 proc3 proc4 proc5 var1 var2 var4 var5 op1 macro1 macro2 ).each do |entry|
|
71
|
+
it "#defines #{entry} -entry" do
|
72
|
+
expect( @resolver.context.entries ).to include( entry )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
[
|
77
|
+
{
|
78
|
+
:desc => "Proc1 calls macro1",
|
79
|
+
:entrypoints => ["proc1"],
|
80
|
+
:expect => [ "proc1.tla", "macro1.tla", "directives.tla", "directives.cfg" ]
|
81
|
+
},
|
82
|
+
|
83
|
+
{
|
84
|
+
:desc => "Proc2 calls macro1, macro2",
|
85
|
+
:entrypoints => ["proc2"],
|
86
|
+
:expect => [ "proc2.tla", "macro1.tla", "macro2.tla", "proc1.tla", "directives.tla", "directives.cfg" ]
|
87
|
+
},
|
88
|
+
|
89
|
+
{
|
90
|
+
:desc => "Proc3 calls macro1, v1, op1",
|
91
|
+
:entrypoints => ["proc3"],
|
92
|
+
:expect => [ "proc3.tla", "macro1.tla", "variables.tla", "op1.tla", "directives.tla", "directives.cfg" ]
|
93
|
+
},
|
94
|
+
|
95
|
+
{
|
96
|
+
:desc => "Proc4 uses var4",
|
97
|
+
:entrypoints => ["proc4"],
|
98
|
+
:expect => [ "proc4.tla", "var4.tla", "directives.tla", "directives.cfg" ]
|
99
|
+
},
|
100
|
+
|
101
|
+
{
|
102
|
+
:desc => "Proc4_hide uses var4 -as formal parametr",
|
103
|
+
:entrypoints => ["proc4_hide"],
|
104
|
+
:expect => [ "proc4_hide.tla", "directives.tla", "directives.cfg" ]
|
105
|
+
},
|
106
|
+
|
107
|
+
{
|
108
|
+
:desc => "Proc5 uses var5",
|
109
|
+
:entrypoints => ["proc5"],
|
110
|
+
:expect => [ "proc5.tla", "var5.tla", "directives.tla", "op1.tla", "directives.cfg"]
|
111
|
+
},
|
112
|
+
|
113
|
+
{
|
114
|
+
:desc => "Loop proc7->proc6",
|
115
|
+
:entrypoints => ["proc7"],
|
116
|
+
:expect => [ "proc7.tla", "proc6.tla", "directives.tla", "directives.cfg" ]
|
117
|
+
},
|
118
|
+
|
119
|
+
{
|
120
|
+
:desc => "Loop proc6->proc7",
|
121
|
+
:entrypoints => ["proc6"],
|
122
|
+
:expect => [ "proc6.tla", "proc7.tla", "directives.tla", "directives.cfg" ]
|
123
|
+
},
|
124
|
+
|
125
|
+
{
|
126
|
+
:desc => "Variable defintion w. set expression",
|
127
|
+
:entrypoints => ["var_set"],
|
128
|
+
:expect => [ "var_set.tla", "op1.tla", "directives.tla", "directives.cfg" ]
|
129
|
+
},
|
130
|
+
|
131
|
+
{
|
132
|
+
:desc => "Sequence defintion w. set expression",
|
133
|
+
:entrypoints => ["var_seq"],
|
134
|
+
:expect => [ "var_seq.tla", "op1.tla", "op2.tla", "directives.tla", "directives.cfg" ]
|
135
|
+
},
|
136
|
+
|
137
|
+
{
|
138
|
+
:desc => "Print statement",
|
139
|
+
:entrypoints => ["printit"],
|
140
|
+
:expect => [ "stmt_print.tla", "variables.tla", "op2.tla", "var4.tla", "directives.tla", "op1.tla", "directives.cfg" ]
|
141
|
+
},
|
142
|
+
|
143
|
+
{
|
144
|
+
:desc => "Assignment statement",
|
145
|
+
:entrypoints => ["assignit"],
|
146
|
+
:expect => [ "stmt_assign.tla", "variables.tla", "var4.tla", "directives.tla" , "op1.tla", "directives.cfg"]
|
147
|
+
},
|
148
|
+
|
149
|
+
{
|
150
|
+
:desc => "Assignment statement to record",
|
151
|
+
:entrypoints => ["assignit2"],
|
152
|
+
:expect => [ "stmt_assign2.tla", "var5.tla", "var_x.tla", "var4.tla", "directives.tla" , "op1.tla", "directives.cfg"]
|
153
|
+
},
|
154
|
+
|
155
|
+
{
|
156
|
+
:desc => "Record except",
|
157
|
+
:entrypoints => ["var_rec_except"],
|
158
|
+
:expect => [ "var_rec_except.tla", "var5.tla", "op1.tla", "directives.tla", "directives.cfg" ]
|
159
|
+
},
|
160
|
+
|
161
|
+
{
|
162
|
+
:desc => "Choose x in Set:",
|
163
|
+
:entrypoints => ["var_choose_except"],
|
164
|
+
:expect => [ "var_choose_except.tla", "op1.tla", "var4.tla", "directives.tla", "directives.cfg" ]
|
165
|
+
},
|
166
|
+
|
167
|
+
{
|
168
|
+
:desc => "Record exression",
|
169
|
+
:entrypoints => ["var_rec_expr"],
|
170
|
+
:expect => [ "var_rec_expr.tla", "var4.tla", "op1.tla", "directives.tla", "directives.cfg" ]
|
171
|
+
},
|
172
|
+
|
173
|
+
{
|
174
|
+
:desc => "Variable definition with set map expression",
|
175
|
+
:entrypoints => ["var_set_expr_map"],
|
176
|
+
:expect => [ "var_set_expr_map.tla", "var4.tla", "directives.tla", "directives.cfg" ]
|
177
|
+
},
|
178
|
+
|
179
|
+
{
|
180
|
+
:desc => "Variable definition set record expression",
|
181
|
+
:entrypoints => ["var_record"],
|
182
|
+
:expect => [ "var_record.tla", "var5.tla", "directives.tla", "op1.tla", "directives.cfg" ]
|
183
|
+
},
|
184
|
+
|
185
|
+
{
|
186
|
+
:desc => "Conditional statement ",
|
187
|
+
:entrypoints => ["stmt_cond"],
|
188
|
+
:expect => [ "stmt_cond.tla", "var4.tla", "var_x.tla", "var5.tla", "directives.tla", "op1.tla", "directives.cfg" ]
|
189
|
+
},
|
190
|
+
|
191
|
+
|
192
|
+
{
|
193
|
+
:desc => "Assert statemtn ",
|
194
|
+
:entrypoints => ["stmt_assert"],
|
195
|
+
:expect => [ "stmt_assert.tla", "var_x.tla", "directives.tla", "directives.cfg" ]
|
196
|
+
},
|
197
|
+
|
198
|
+
{
|
199
|
+
:desc => "Either statement ",
|
200
|
+
:entrypoints => ["stmt_either"],
|
201
|
+
:expect => [ "stmt_either.tla", "var4.tla", "var5.tla", "directives.tla", "op1.tla", "directives.cfg" ]
|
202
|
+
},
|
203
|
+
|
204
|
+
|
205
|
+
{
|
206
|
+
:desc => "Quantify expression",
|
207
|
+
:entrypoints => ["var_quantify"],
|
208
|
+
:expect => [ "var_quantify.tla", "op1.tla", "var4.tla", "directives.tla", "directives.cfg" ]
|
209
|
+
},
|
210
|
+
|
211
|
+
].each_with_index do |testCase,i|
|
212
|
+
it "Case #{i+1}: #{testCase[:desc]}" do
|
213
|
+
resolvedModules = @resolver.resolveModules( testCase[:entrypoints] ).map { |path| File.basename( path )}
|
214
|
+
expect( resolvedModules ).to eql( testCase[:expect] )
|
215
|
+
# testCase[:expect].each do |moduleName|
|
216
|
+
# expect( resolvedModules ).to include( moduleName )
|
217
|
+
# end # each testCase
|
218
|
+
end # it
|
219
|
+
end # each
|
220
|
+
|
221
|
+
end # resoveModule success
|
222
|
+
|
223
|
+
end # fixture - success
|
224
|
+
|
225
|
+
|
226
|
+
# ------------------------------------------------------------------
|
227
|
+
# Error cases
|
228
|
+
|
229
|
+
describe "resoveModule errors" do
|
230
|
+
|
231
|
+
[
|
232
|
+
{
|
233
|
+
:desc => "Succesfull case",
|
234
|
+
:snippets => [
|
235
|
+
"procedure proc1() {skip;}"
|
236
|
+
],
|
237
|
+
:entries => ["proc1"],
|
238
|
+
:entrypoints => ["proc1"],
|
239
|
+
:exception => nil,
|
240
|
+
:expect => [ "entries[0]"]
|
241
|
+
},
|
242
|
+
|
243
|
+
{
|
244
|
+
:desc => "Parse error",
|
245
|
+
:snippets => [
|
246
|
+
"procedure xxx proc1() {skip;}"
|
247
|
+
],
|
248
|
+
:entries => ["proc1"],
|
249
|
+
:entrypoints => ["proc1"],
|
250
|
+
:exception => /Parse error/,
|
251
|
+
:expect => nil,
|
252
|
+
},
|
253
|
+
|
254
|
+
{
|
255
|
+
:desc => "Parse error includes module name",
|
256
|
+
:snippets => [
|
257
|
+
"procedure proc0() {skip;}",
|
258
|
+
"procedure xxx proc1() {skip;}",
|
259
|
+
],
|
260
|
+
:entries => ["proc1"],
|
261
|
+
:entrypoints => ["proc1"],
|
262
|
+
:exception => /Parsing 'entries\[1\]'/,
|
263
|
+
:expect => nil,
|
264
|
+
},
|
265
|
+
|
266
|
+
{
|
267
|
+
:desc => "Unknown entrypoint",
|
268
|
+
:snippets => [
|
269
|
+
"procedure proccci3() {skip;}"
|
270
|
+
],
|
271
|
+
:entries => ["proccci3"],
|
272
|
+
:entrypoints => ["proc1"],
|
273
|
+
:exception => /Unknown entrypoint 'proc1'/,
|
274
|
+
:expect => [],
|
275
|
+
},
|
276
|
+
|
277
|
+
{
|
278
|
+
:desc => "Unknown resource used, default no errors",
|
279
|
+
:snippets => [
|
280
|
+
"procedure p1() {skip;}",
|
281
|
+
"procedure p2() {skip;}",
|
282
|
+
"procedure p3() {skip;}",
|
283
|
+
"procedure p4() { macro1(var1);}",
|
284
|
+
],
|
285
|
+
:entries => ["p4"],
|
286
|
+
:entrypoints => ["p4"],
|
287
|
+
:exception => nil,
|
288
|
+
:expect => [ "entries[3]"],
|
289
|
+
},
|
290
|
+
|
291
|
+
|
292
|
+
].each_with_index do |testCase,i|
|
293
|
+
|
294
|
+
it "Case #{i+1}: #{testCase[:desc]}" do
|
295
|
+
resolver = described_class.new
|
296
|
+
|
297
|
+
if ( testCase[:exception] )
|
298
|
+
|
299
|
+
expect{
|
300
|
+
resolver.initSnippets( testCase[:snippets] )
|
301
|
+
resolver.resolveModules( testCase[:entrypoints] )
|
302
|
+
}.to raise_exception( testCase[:exception] )
|
303
|
+
else
|
304
|
+
|
305
|
+
resolver.initSnippets( testCase[:snippets] )
|
306
|
+
|
307
|
+
if testCase[:entries]
|
308
|
+
expect( resolver.context.entries ).to include( *testCase[:entries] )
|
309
|
+
end
|
310
|
+
|
311
|
+
expect( resolver.resolveModules( testCase[:entrypoints] ).map { |path| File.basename( path )} ).to eql( testCase[:expect] )
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
end # each
|
317
|
+
end # error case 1
|
318
|
+
|
319
|
+
# ------------------------------------------------------------------
|
320
|
+
# Error cases 2
|
321
|
+
|
322
|
+
describe "Error cases 2" do
|
323
|
+
|
324
|
+
describe "initSnippets" do
|
325
|
+
|
326
|
+
it "#nil input" do
|
327
|
+
expect( resolver.initSnippets( nil ) ).to eql( resolver )
|
328
|
+
end
|
329
|
+
|
330
|
+
it "[] input" do
|
331
|
+
expect( resolver.initSnippets( [] ) ).to eql( resolver )
|
332
|
+
end
|
333
|
+
|
334
|
+
it "#unknown file exception" do
|
335
|
+
expect{ resolver.initSnippets( File.new( "no-sushc-file")) }.to raise_exception /No such file or directory/
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
|
342
|
+
# ------------------------------------------------------------------
|
343
|
+
# Option to report unresolved identifiers
|
344
|
+
|
345
|
+
describe "Reports un-resolved" do
|
346
|
+
|
347
|
+
let ( :uentries ) {
|
348
|
+
[
|
349
|
+
"procedure proc6( a ) { call proc6(unknown); }"
|
350
|
+
]
|
351
|
+
}
|
352
|
+
let( :entryPoints ) { ["proc6"] }
|
353
|
+
|
354
|
+
it "outputs to stderr unresolved" do
|
355
|
+
uresolver = described_class.new( {:report_unresolved => true }).initSnippets( uentries )
|
356
|
+
expect( uresolver.resolveModules( entryPoints )).to eql( [ "entries[0]"] )
|
357
|
+
expect { uresolver.resolveModules( entryPoints ) }.to output( /Symbol 'unknown' in entry 'proc6'/ ).to_stderr
|
358
|
+
end
|
359
|
+
|
360
|
+
end # reports unresolver
|
361
|
+
|
362
|
+
|
363
|
+
end
|
364
|
+
|