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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +75 -0
  3. data/VERSION +1 -0
  4. data/bin/tla-resolver.rb +7 -0
  5. data/lib/cli/cli.rb +90 -0
  6. data/lib/parser/exception.rb +6 -0
  7. data/lib/parser/lvalue.rb +63 -0
  8. data/lib/parser/parser.rb +129 -0
  9. data/lib/parser/parser_nodes.rb +1063 -0
  10. data/lib/parser/parser_sexp.treetop +442 -0
  11. data/lib/semantics/context.rb +355 -0
  12. data/lib/semantics/exception.rb +13 -0
  13. data/lib/semantics/resolver.rb +327 -0
  14. data/lib/semantics/symbol_table.rb +139 -0
  15. data/lib/tla-parser-s.rb +15 -0
  16. data/lib/utils/logger.rb +80 -0
  17. data/lib/utils/syntax_node.rb +73 -0
  18. data/lib/utils/version.rb +13 -0
  19. data/spec/fixtures/callables1.tla +64 -0
  20. data/spec/fixtures/directives.tla +7 -0
  21. data/spec/fixtures/resolver1/comments.tla +1 -0
  22. data/spec/fixtures/resolver1/directives.cfg +6 -0
  23. data/spec/fixtures/resolver1/directives.tla +12 -0
  24. data/spec/fixtures/resolver1/empty.tla +0 -0
  25. data/spec/fixtures/resolver1/macro1.tla +3 -0
  26. data/spec/fixtures/resolver1/macro2.tla +3 -0
  27. data/spec/fixtures/resolver1/op1.tla +3 -0
  28. data/spec/fixtures/resolver1/op2.tla +3 -0
  29. data/spec/fixtures/resolver1/proc1.tla +4 -0
  30. data/spec/fixtures/resolver1/proc2.tla +7 -0
  31. data/spec/fixtures/resolver1/proc3.tla +4 -0
  32. data/spec/fixtures/resolver1/proc4.tla +4 -0
  33. data/spec/fixtures/resolver1/proc4_hide.tla +4 -0
  34. data/spec/fixtures/resolver1/proc5.tla +4 -0
  35. data/spec/fixtures/resolver1/proc6.tla +4 -0
  36. data/spec/fixtures/resolver1/proc7.tla +4 -0
  37. data/spec/fixtures/resolver1/stmt_assert.tla +8 -0
  38. data/spec/fixtures/resolver1/stmt_assign.tla +6 -0
  39. data/spec/fixtures/resolver1/stmt_assign2.tla +6 -0
  40. data/spec/fixtures/resolver1/stmt_cond.tla +13 -0
  41. data/spec/fixtures/resolver1/stmt_either.tla +12 -0
  42. data/spec/fixtures/resolver1/stmt_print.tla +5 -0
  43. data/spec/fixtures/resolver1/var4.tla +1 -0
  44. data/spec/fixtures/resolver1/var5.tla +1 -0
  45. data/spec/fixtures/resolver1/var_choose_except.tla +2 -0
  46. data/spec/fixtures/resolver1/var_quantify.tla +4 -0
  47. data/spec/fixtures/resolver1/var_rec_except.tla +4 -0
  48. data/spec/fixtures/resolver1/var_rec_expr.tla +3 -0
  49. data/spec/fixtures/resolver1/var_record.tla +2 -0
  50. data/spec/fixtures/resolver1/var_seq.tla +1 -0
  51. data/spec/fixtures/resolver1/var_set.tla +1 -0
  52. data/spec/fixtures/resolver1/var_set_expr_map.tla +1 -0
  53. data/spec/fixtures/resolver1/var_x.tla +1 -0
  54. data/spec/fixtures/resolver1/variables.tla +4 -0
  55. data/spec/parser/parser_fixtures_spec.rb +117 -0
  56. data/spec/parser/parser_spec.rb +1649 -0
  57. data/spec/semantics/context_spec.rb +392 -0
  58. data/spec/semantics/resolver_spec.rb +364 -0
  59. data/spec/semantics/symbol_table_spec.rb +144 -0
  60. data/spec/spec_helper.rb +5 -0
  61. data/tla-parser-s.gemspec +41 -0
  62. 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
+