File tree Expand file tree Collapse file tree 5 files changed +96
-15
lines changed
Expand file tree Collapse file tree 5 files changed +96
-15
lines changed Original file line number Diff line number Diff line change @@ -389,21 +389,10 @@ object UclidMain {
389389 (acc, module) => {
390390 val declsP = {
391391 val nonInitAccDecls = acc.decls.filter(p => ! p.isInstanceOf [InitDecl ])
392- val initAccDecls = acc.decls.filter(p => p.isInstanceOf [InitDecl ]).headOption
392+ val initAccDecls = acc.decls.filter(p => p.isInstanceOf [InitDecl ])
393393 val nonInitModuleDecls = module.decls.filter(p => ! p.isInstanceOf [InitDecl ])
394- val initModuleDecls = module.decls.filter(p => p.isInstanceOf [InitDecl ]).headOption
395- val newInitDecl = initAccDecls match {
396- case Some (initAcc) => initModuleDecls match {
397- case Some (initMod) => List (InitDecl (BlockStmt (List [BlockVarsDecl ](),
398- List (initAcc.asInstanceOf [InitDecl ].body, initMod.asInstanceOf [InitDecl ].body))))
399- case None => List (initAcc)
400- }
401- case None => initModuleDecls match {
402- case Some (initMod) => List (initMod)
403- case None => List [Decl ]()
404- }
405- }
406- newInitDecl ++ nonInitAccDecls ++ nonInitModuleDecls
394+ val initModuleDecls = module.decls.filter(p => p.isInstanceOf [InitDecl ])
395+ initAccDecls ++ initModuleDecls ++ nonInitAccDecls ++ nonInitModuleDecls
407396 }
408397 val cmdsP = (acc.cmds ++ module.cmds)
409398 Utils .assert(module.notes.size == 1 && module.notes.head.asInstanceOf [InstanceVarMapAnnotation ].iMap.size == 0 , " Expected module to initially have empty annotations." )
Original file line number Diff line number Diff line change @@ -42,9 +42,28 @@ package lang
4242
4343class ModuleCanonicalizerPass extends RewritePass {
4444 override def rewriteModule (moduleIn : Module , ctx : Scope ) : Option [Module ] = {
45+ // Currently we only allow one init and one next block in a module.
46+ // we could alternatively, combine multiple init (or next) blocks into a single init (or next) block.
47+ var errors : List [(String , lang.ASTPosition )] = List .empty
48+ val initdecls = moduleIn.decls.filter(_.isInstanceOf [InitDecl ]).map(_.asInstanceOf [InitDecl ])
49+ if (initdecls.size > 1 ) {
50+ val msg = " Module has multiple init blocks. This is not allowed."
51+ val position = initdecls(1 ).position
52+ errors = errors :+ (msg, position)
53+ }
54+ val nextdecls = moduleIn.decls.filter(_.isInstanceOf [NextDecl ]).map(_.asInstanceOf [NextDecl ])
55+ if (nextdecls.size > 1 ) {
56+ val msg = " Module has multiple next blocks. This is not allowed."
57+ val position = nextdecls(1 ).position
58+ errors = errors :+ (msg, position)
59+ }
60+ if (errors.nonEmpty) {
61+ throw throw new Utils .ParserErrorList (errors)
62+ }
63+
4564 val initP = moduleIn.init match {
4665 case None => Some (InitDecl (SkipStmt ()))
47- case Some (_) => None
66+ case Some (_) => None
4867 }
4968 val nextP = moduleIn.next match {
5069 case None => Some (NextDecl (SkipStmt ()))
Original file line number Diff line number Diff line change @@ -258,6 +258,28 @@ class ParserSpec extends AnyFlatSpec {
258258 assert (p.errors.size == 5 )
259259 }
260260 }
261+ " test-multiple-init-blocks.ucl" should " not parse successfully." in {
262+ try {
263+ val fileModules = UclidMain .compile(ConfigCons .createConfig(" test/test-multiple-init-blocks.ucl" ), lang.Identifier (" main" ))
264+ // should never get here.
265+ assert (false );
266+ }
267+ catch {
268+ case p : Utils .ParserErrorList =>
269+ assert (p.errors.size == 1 )
270+ }
271+ }
272+ " test-multiple-next-blocks.ucl" should " not parse successfully." in {
273+ try {
274+ val fileModules = UclidMain .compile(ConfigCons .createConfig(" test/test-multiple-next-blocks.ucl" ), lang.Identifier (" main" ))
275+ // should never get here.
276+ assert (false );
277+ }
278+ catch {
279+ case p : Utils .ParserErrorList =>
280+ assert (p.errors.size == 1 )
281+ }
282+ }
261283 " test-typechecker-6.ucl" should " not parse successfully." in {
262284 try {
263285 val fileModules = UclidMain .compile(ConfigCons .createConfig(" test/test-typechecker-6.ucl" ), lang.Identifier (" main" ))
Original file line number Diff line number Diff line change 1+ // should throw an error because there are multiple init blocks in the module
2+ module main {
3+ var x : integer;
4+
5+ init {
6+ x = 0;
7+ }
8+
9+ init {
10+ x = 1;
11+ }
12+
13+ next{
14+
15+ }
16+
17+ invariant prop_eq: x == 0;
18+
19+ control {
20+ v = bmc(5);
21+ check;
22+ print_results;
23+ }
24+
25+ }
Original file line number Diff line number Diff line change 1+ // should throw an error because there are multiple next blocks in the module
2+ module main {
3+ var x : integer;
4+ var y : integer;
5+
6+ init {
7+ x = 0;
8+ y = 0;
9+ }
10+
11+ next {
12+ x' = x + 1;
13+ }
14+
15+ next {
16+ y' = y + 2;
17+ }
18+ invariant prop_eq: x != 0;
19+
20+ control {
21+ v = bmc(5);
22+ check;
23+ print_results;
24+ v.print_cex(x);
25+ }
26+ }
You can’t perform that action at this time.
0 commit comments